Skip to content
Advertisement

Virtual address to physical address and reverse in android linux kernel

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.

  1. malloc() in android user space native binary not app
  2. Transform va from malloc() to pa using the guide Is there any API for determining the physical address from virtual address in Linux?
  3. Pass pa to a system call function I made.
  4. Re-map received pa to va in linux kernel space using ioremap()
  5. Read value using readl() or ioread32()

But it’s not working now.

  1. The va to pa 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);
    }
  1. 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 calculate pa from va.
  • I set va to “ttttt”.
  • Pass pa to linux kernel space using syscall.
  • Remap this pa to va 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.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement