android linux 内核中虚拟地址到物理地址的反向
Virtual address to physical address and reverse in android linux kernel
我正在尝试将虚拟地址转换为物理地址,并使用 android linux 内核环境将此物理地址映射到虚拟地址。
我可以修改内核代码。所以我尝试了下一个流程。
malloc()
在 android 用户中 space 本机二进制文件不是应用程序
- 使用指南将
va
从 malloc()
转换为 pa
Is there any API for determining the physical address from virtual address in Linux?
- 将
pa
传递给我创建的系统调用函数。
- 使用
ioremap()
将 pa
重新映射到 linux 内核 space 中的 va
- 使用
readl()
或ioread32()
读取值
但是现在不行了。
va
到pa
的逻辑在上面link;在我的本机二进制文件中,下面是伪代码。
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);
}
- 系统调用函数
void sys_readpa(unsigned long pa){
void __iomem* mapped_add = ioremap(pa);
printk("%c", readl(mapped_add));
printk("%c", ioread32(mapped_add));
}
我的代码有类似的逻辑:
- 我在用户 space 中定义
va
并从 va
计算 pa
。
- 我把
va
设为"ttttt"。
- 使用系统调用将
pa
传递给 linux 内核 space。
- 在内核 space 中将此
pa
重新映射到 va
。
- 在内核 space 中读取
va
并期望值为 "ttttt"
我不知道 va
到 pa
的逻辑是否正确。但它 returns 一个地址而不是失败。
但是当调用系统调用时,会发生内核崩溃 - 例如"dereference for 0000000 address",以及其他类型的错误。我检查了系统调用中的 pa
与用户 space.
中的相同
我这次尝试的目的是学习。我只是想知道如果我也可以修改内核代码,这个实现是可能的,但我遇到了障碍。
请告诉我有什么问题或不可能吗?如果需要,我会更新更多详细代码或具体错误消息。
我添加了详细错误和我的调试日志。
我的用户space登录
: vitrual address : 0xf079c000
: 0xf079c000 -> 0xa4a8a000
我将 0xa4a8a000 传递给系统调用。
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
我找到了修复。
ioremap 有一个地址验证的检查逻辑。
此函数用于保留地址,但它试图映射已经映射到进程的地址。
所以,我修改了ioreamp中的校验逻辑,效果很好。
我正在尝试将虚拟地址转换为物理地址,并使用 android linux 内核环境将此物理地址映射到虚拟地址。
我可以修改内核代码。所以我尝试了下一个流程。
malloc()
在 android 用户中 space 本机二进制文件不是应用程序- 使用指南将
va
从malloc()
转换为pa
Is there any API for determining the physical address from virtual address in Linux? - 将
pa
传递给我创建的系统调用函数。 - 使用
ioremap()
将 - 使用
readl()
或ioread32()
读取值
pa
重新映射到 linux 内核 space 中的 va
但是现在不行了。
va
到pa
的逻辑在上面link;在我的本机二进制文件中,下面是伪代码。
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);
}
- 系统调用函数
void sys_readpa(unsigned long pa){
void __iomem* mapped_add = ioremap(pa);
printk("%c", readl(mapped_add));
printk("%c", ioread32(mapped_add));
}
我的代码有类似的逻辑:
- 我在用户 space 中定义
va
并从va
计算pa
。 - 我把
va
设为"ttttt"。 - 使用系统调用将
pa
传递给 linux 内核 space。 - 在内核 space 中将此
pa
重新映射到va
。 - 在内核 space 中读取
va
并期望值为 "ttttt"
我不知道 va
到 pa
的逻辑是否正确。但它 returns 一个地址而不是失败。
但是当调用系统调用时,会发生内核崩溃 - 例如"dereference for 0000000 address",以及其他类型的错误。我检查了系统调用中的 pa
与用户 space.
我这次尝试的目的是学习。我只是想知道如果我也可以修改内核代码,这个实现是可能的,但我遇到了障碍。
请告诉我有什么问题或不可能吗?如果需要,我会更新更多详细代码或具体错误消息。
我添加了详细错误和我的调试日志。
我的用户space登录
: vitrual address : 0xf079c000
: 0xf079c000 -> 0xa4a8a000
我将 0xa4a8a000 传递给系统调用。
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
我找到了修复。 ioremap 有一个地址验证的检查逻辑。 此函数用于保留地址,但它试图映射已经映射到进程的地址。 所以,我修改了ioreamp中的校验逻辑,效果很好。