I’m trying to transform virtual address to physical address and map this physical address to virtual address with android linux kernel environment.
I can modify kernel code. So I tried next flow.
malloc()
in android user space native binary not app- Transform
va
frommalloc()
topa
using the guide Is there any API for determining the physical address from virtual address in Linux? - Pass
pa
to a system call function I made. - Re-map received
pa
tova
in linux kernel space usingioremap()
- Read value using
readl()
orioread32()
But it’s not working now.
- The
va
topa
logic is in above link; in my native binary, below is the pseudo-code.
int main(){ char *va=malloc(100); memset(va, "ttttt", ...) uintptr_t paddr; vir_to_phys_user(&paddr, getpid(), va); syscall(sys_readpa, (unsigned long)paddr); }
- system call function
void sys_readpa(unsigned long pa){ void __iomem* mapped_add = ioremap(pa); printk("%c", readl(mapped_add)); printk("%c", ioread32(mapped_add)); }
My code has similar logic:
- I define
va
in user space and calculatepa
fromva
. - I set
va
to “ttttt”. - Pass
pa
to linux kernel space using syscall. - Remap this
pa
tova
in kernel space. - Read
va
in kernel space and expect the value to be “ttttt”
I don’t know the va
to pa
logic is correct. But it returns an address not failure.
But when syscall is called, kernel panic occur – e.g. “dereference for 0000000 address”, and other kinds of errors. I checked pa
in syscall is same with the one in user space.
My purpose of this try is study. I just wonder this implementation is possible if I can modify kernel code too but I met with an obstacle.
Please let me know what is problem or it’s impossible? If needed, I’ll update more detail code or specific error message.
I add detail errors and my debug log.
My user space log
: vitrual address : 0xf079c000 : 0xf079c000 -> 0xa4a8a000
I pass 0xa4a8a000 to syscall.
dmesg
[ 96.794448] accepted pa : 00000000a4a8a000 [ 96.794473] ------------[ cut here ]------------ [ 96.794500] WARNING: CPU: 6 PID: 11644 at arch/arm64/mm/ioremap.c:58 __ioremap_caller+0xc0/0xcc [ 96.794519] Modules linked in: [ 96.794552] CPU: 6 PID: 11644 Comm: mt Not tainted 4.14.113 #1 [ 96.794590] Call trace: [ 96.794611] [<0000000000000000>] dump_backtrace+0x0/0x2b8 [ 96.794632] [<0000000000000000>] show_stack+0x18/0x24 [ 96.794655] [<0000000000000000>] dump_stack+0xa0/0xdc [ 96.794676] [<0000000000000000>] __warn+0xbc/0x164 [ 96.794695] [<0000000000000000>] report_bug+0xac/0xdc [ 96.794713] [<0000000000000000>] bug_handler+0x30/0x8c [ 96.794732] [<0000000000000000>] brk_handler+0x94/0x150 [ 96.794751] [<0000000000000000>] do_debug_exception+0xd4/0x170 [ 96.794769] Exception stack(0xffffff8010fdbc10 to 0xffffff8010fdbd50) [ 96.794787] bc00: 0000000000000000 0000000000000004 [ 96.794805] bc20: 00e8000000000f07 ffffff8008358714 000000000000000c 0000000000002d7c [ 96.794822] bc40: ffffffc0119630e7 5b20205d38343434 0000000000000000 0000000000000001 [ 96.794839] bc60: 0000000000000001 00000000bab00000 0000000000000000 0000000080000000 [ 96.794856] bc80: ffffff800b18d000 0000000000000082 00000000000564c8 0000000000000074 [ 96.794873] bca0: 0000000000000074 00e8000000000f07 00000000a4a8a000 0000000000001000 [ 96.794890] bcc0: ffffff8008358714 0000000000000000 0000000000000011 000000000000018f [ 96.794908] bce0: 000000000000018e ffffff8009316000 ffffffc8767edf80 ffffff8010fdbe80 [ 96.794926] bd00: ffffff80081fe124 ffffff8010fdbe50 ffffff80081fe188 0000000020400145 [ 96.794943] bd20: 0000000000000034 7cebe7b2cf849500 0000007fffffffff ffffff8009316000 [ 96.794961] bd40: ffffff8010fdbe80 ffffff80081fe188 [ 96.794978] [<0000000000000000>] el1_dbg+0x18/0x74 [ 96.794995] [<0000000000000000>] __ioremap_caller+0xc0/0xcc [ 96.795014] [<0000000000000000>] __ioremap+0x10/0x1c [ 96.795035] [<0000000000000000>] sys_readpa+0x78/0xfc [ 96.795055] Exception stack(0xffffff8010fdbec0 to 0xffffff8010fdc000) [ 96.795072] bec0: 00000000a4a8a000 0000000028bf4d08 0000000000000003 00000000f079c000 [ 96.795090] bee0: 0000000000000000 00000000a4a8a000 0000000000000000 000000000000018e [ 96.795107] bf00: 00000000f09afd94 00000000f09d2b99 00000000ae6c9e84 00000000ae6a261e [ 96.795124] bf20: 00000000ff921bf0 00000000ff921be0 00000000ae5f7b27 0000000000000000 [ 96.795142] bf40: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 96.795159] bf60: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 96.795176] bf80: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 96.795195] bfa0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 96.795212] bfc0: 00000000f091ce20 0000000060000010 00000000a4a8a000 000000000000018e [ 96.795229] bfe0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 96.795247] [<0000000000000000>] __sys_trace_return+0x0/0x4 [ 96.795265] ---[ end trace 91e76f3be7c0b9bd ]--- [ 96.795418] ioremap return null
Advertisement
Answer
I found fix. ioremap have a check logic for validation of address. This function is for reserved address but it tring to map address that’s already mapped to a process. So, I modify the check logic in ioreamp and it works well.