ARM64 - Linux 内存写保护不会禁用
ARM64 - Linux Memory Write protection won't disable
我正在尝试从 LKM 中禁用 ARM64 系统上的内存写保护。 (在 Xen 管理程序的 DOM0 中开始)
我使用 Linux 内核函数找到了对应虚拟地址的 PTE。
pgd_t *pgd;
pte_t *ptep, pte;
pud_t *pud;
pmd_t *pmd;
pgd = pgd_offset(init_mm, (addr));
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto out;
printk(KERN_NOTICE "Valid pgd 0x%lx\n",pgd);
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || pud_bad(*pud))
goto out;
printk(KERN_NOTICE "Valid pud 0x%lx\n",pud);
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto out;
printk(KERN_NOTICE "Valid pmd 0x%lx\n",pmd);
ptep = pte_offset_map(pmd, addr);
if (!ptep)
goto out;
pte = *ptep;
在此之后,我将清除 PTE 的第 7 位,根据 ARM-ARM(第 2066 页 - 第 1 阶段 VMSAv8-64 块和页面描述符中的属性字段),它应该禁用允许的写保护从 EL1 写入 (AP[2:1]==00)
另外我使用 Linux 内核函数 wo "make the pte writable" 尽管这个位(位 51)用于第 2 阶段翻译(我的工作是第 1 阶段)
printk(KERN_INFO "PTE before 0x%lx\n", pte);
printk(KERN_INFO "Setting PTE write\n");
pte = pte_mkwrite(pte);
pte = clear_pte_bit(pte, __pgprot((_AT(pteval_t, 1) << 7)));
printk(KERN_INFO "PTE after 0x%lx\n", pte);
flush_tlb_all();
printk(KERN_INFO "PTE nach flush 0x%lx\n", pte);
因为在使用memcpy 写入内存时仍然出现Kernel Panic,所以我调用了两次禁用写保护的函数以检查我的设置。这些是两个函数调用的输出:
[ 1804.078382] Valid pgd 0xffff000008e7d000
[ 1804.082397] Valid pud 0xffff800017ffe000
[ 1804.086374] Valid pmd 0xffff800017ffd200
[ 1804.090367] PTE before 0xc0000040081793
[ 1804.094529] Setting PTE write
[ 1804.097562] PTE after 0xc8000040081713
[ 1804.101637] PTE after flush 0xc8000040081713
[...More outputs...]
[ 1804.117395] ROUND 2########################
[ 1804.149190] Valid pgd 0xffff000008e7d000
[ 1804.153207] Valid pud 0xffff800017ffe000
[ 1804.157178] Valid pmd 0xffff800017ffd200
[ 1804.161172] PTE before 0xc0000040081793
[ 1804.165329] Setting PTE write
[ 1804.168366] PTE after 0xc8000040081713
[ 1804.172443] PTE after flush 0xc8000040081713
(不同之处在于从左数第二个位置是 8 而不是 0,从右数第二个位置是 1 而不是 9)
如你所见,第二次调用该函数后,我们预计第一轮的最后一个 PTE 值与第二轮的第一个相同(输出 NR:1804.101637 != 1804.161172 ),这里不是这种情况。
我正在用这个命令写入内存:
static unsigned char replace_blr[4] = {0xD6,0x3F, 0x03,0xA0}; (global defined)
memcpy(el1_sync,replace_blr,4);
其中 el1_sync 包含我用于查找 pte 的虚拟地址。
有没有人看到,为什么我的 PTE 配置没有 updated/is 重置?
如果有人有替代方案让我直接写入内核内存,我也会感谢任何其他输入。我的目标只是允许写入给定虚拟地址的页面。 (就像许多 x86 rootkit,但在 ARM64 上)
KERNEL OOPS when writing: (Virtual Address: 0xffff000008081a00)
[ 49.776343] Unable to handle kernel paging request at virtual address ffff000008081a00
[ 49.784313] pgd = ffff800013d91000
[ 49.787777] [ffff000008081a00] *pgd=0000000000000000[ 49.792542]
[ 49.794094] Internal error: Oops: 9600004f [#1] PREEMPT SMP
[ 49.799721] Modules linked in: mod_init(O+) adv7511 kirin_drm drm_kms_helper dw_drm_dsi drm asix
usbnet ipv6
[ 49.809610] CPU: 1 PID: 2328 Comm: insmod Tainted: G O 4.9.0-hikey-139764-g3e36302a0
621-dirty #1
[ 49.819580] Hardware name: HiKey Development Board (DT)
[ 49.824876] task: ffff80001580b200 task.stack: ffff800015af8000
[ 49.830864] PC is at init_module+0xf8/0x1f0 [mod_init]
[ 49.836061] LR is at init_module+0xe8/0x1f0 [mod_init]
[ 49.841259] pc : [<ffff000000b71568>] lr : [<ffff000000b71558>] pstate: 00000145
[ 49.848716] sp : ffff800015afbc40
[ 49.852099] x29: ffff800015afbc40 x28: 00000000024000c0
[ 49.857474] x27: 0000000000000124 x26: ffff000008129f68
[ 49.862851] x25: 0000000000000001 x24: ffff800014f5abc8
[ 49.868227] x23: ffff000000b730d0 x22: ffff800014f5ad80
[ 49.873604] x21: 0000000000000000 x20: ffff000000b72370
[ 49.878981] x19: ffff000000b73380 x18: 0000000000000010
[ 49.884357] x17: 0000aaaadb4f02b0 x16: 0000000000000012
[ 49.889734] x15: 0000000000000006 x14: ffff000088e40a27
[ 49.895110] x13: ffff000008e40a35 x12: 0000000000000007
[ 49.900487] x11: 000000000000016d x10: 0000000005f5e0ff
[ 49.905863] x9 : 000000000000016e x8 : 70752064656b6361
[ 49.911240] x7 : 62207972746e6520 x6 : ffff000008e40a53
[ 49.916616] x5 : 0000000000000000 x4 : 0000000000000000
[ 49.921993] x3 : 0000000000000000 x2 : 00000000a0033fd6
[ 49.927370] x1 : ffff000008081a00 x0 : 0000000000000000
[ 49.932745]
[ 49.934309] Process insmod (pid: 2328, stack limit = 0xffff800015af8020)
[ 49.941073] Stack: (0xffff800015afbc40 to 0xffff800015afc000)
[ 49.946885] bc40: ffff800015afbc60 ffff0000080830b8 ffff000000b71470 ffff800015af8000
[ 49.954776] bc60: ffff800015afbcd0 ffff00000816521c ffff000000b73080 ffff000008d80000
[ 49.962667] bc80: ffff000000b73080 ffff800014f5ad80 ffff000000b73080 ffff800014f5ab80
[ 49.970558] bca0: ffff000000b730d0 ffff800014f5abc8 0000000000000001 ffff000008129f68
[ 49.978450] bcc0: 0000000000000124 00000000024000c0 ffff800015afbd00 ffff00000812d454
[ 49.986341] bce0: ffff800015afbe58 0000000000000001 ffff000000b73080 ffff800014f5ab80
[ 49.994232] bd00: ffff800015afbe10 ffff00000812dd78 0000000000000000 0000000000000003
[ 50.002124] bd20: 0000aaaadb4dd8d0 0000ffffaf31fcf4 0000000080000000 0000000000000015
[ 50.010015] bd40: 0000000000000123 0000000000000111 ffff0000088c2000 ffff800015af8000
[ 50.017906] bd60: 000000000003c788 ffff000008b3c088 ffff000000000072 ffff000000000064
[ 50.025798] bd80: ffff80000000006e ffff000000b76000 ffff80001511a118 ffff000000b73250
[ 50.033689] bda0: ffff0000088d24c0 ffff0000088d24b0 000000007fffffff 0000000000000003
[ 50.041581] bdc0: 0000000000000123 ffff0000081dfa18 ffff800015afbe10 0000000000000000
[ 50.049472] bde0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 50.057364] be00: 0000000000000000 0000000000000000 0000000000000000 ffff000008082ef0
[ 50.065255] be20: 0000000000000000 0000000000000000 ffffffffffffffff 0000000000000000
[ 50.073147] be40: ffff800015afbeb0 000000000003c788 ffff00000cb6d000 ffff00000cb6d000
[ 50.081038] be60: 000000000003c788 ffff00000cba9088 ffff00000cba8f70 ffff00000cb8d838
[ 50.088929] be80: 0000000000003000 0000000000003798 0000000000000000 0000000000000000
[ 50.096820] bea0: 0000000000000bd0 0000001a00000019 0000000000000008 0000000000000005
[ 50.104712] bec0: 0000000000000003 0000aaaadb4dd8d0 0000000000000000 0000000000000003
[ 50.112603] bee0: 0000000000000000 000000000001fd31 0000000000000001 0000000000000001
[ 50.120497] bf00: 0000000000000111 fefefefefefefeff 00000000ffffffff 0000000000000030
[ 50.128386] bf20: 0000000000000004 0000000000000008 0000ffffaf259a94 0000ffffaf3a1588
[ 50.136278] bf40: 0000ffffaf31fcd0 0000aaaadb4f02b0 0000ffffcb3fe1b0 0000aaaaf319f190
[ 50.144169] bf60: 0000000000000000 0000aaaadb4dd8d0 0000000000000000 0000000000000002
[ 50.152061] bf80: 0000aaaaf319e0d0 0000ffffcb3fe518 0000000000000000 0000000000000000
[ 50.159952] bfa0: 0000000000000000 0000ffffcb3fe450 0000aaaadb4d3bd0 0000ffffcb3fe450
[ 50.167843] bfc0: 0000ffffaf31fcf4 0000000080000000 0000000000000003 0000000000000111
[ 50.175735] bfe0: 0000000000000000 0000000000000000 0000000000000000 0002000000000035
[ 50.183624] Call trace:
[ 50.186141] Exception stack(0xffff800015afba70 to 0xffff800015afbba0)
[ 50.192644] ba60: ffff000000b73380 0001000000000000
[ 50.200536] ba80: ffff800015afbc40 ffff000000b71568 0000000000000006 0000000000000006
[ 50.208428] baa0: ffff000008e42e4a 000000000000001c ffff000008e40000 ffff000008b39520
[ 50.216323] bac0: ffff800015afbb60 ffff0000080ff5a0 ffff000000b73380 ffff000000b72370
[ 50.224210] bae0: 0000000000000000 ffff800014f5ad80 ffff000000b730d0 ffff800014f5abc8
[ 50.232102] bb00: 0000000000000001 ffff000008129f68 0000000000000000 ffff000008081a00
[ 50.239993] bb20: 00000000a0033fd6 0000000000000000 0000000000000000 0000000000000000
[ 50.247889] bb40: ffff000008e40a53 62207972746e6520 70752064656b6361 000000000000016e
[ 50.255776] bb60: 0000000005f5e0ff 000000000000016d 0000000000000007 ffff000008e40a35
[ 50.263668] bb80: ffff000088e40a27 0000000000000006 0000000000000012 0000aaaadb4f02b0
[ 50.271564] [<ffff000000b71568>] init_module+0xf8/0x1f0 [mod_init]
[ 50.277808] [<ffff0000080830b8>] do_one_initcall+0x38/0x128
[ 50.283441] [<ffff00000816521c>] do_init_module+0x5c/0x1b8
[ 50.288992] [<ffff00000812d454>] load_module+0x1a44/0x20b8
[ 50.294540] [<ffff00000812dd78>] SyS_finit_module+0xd8/0xe8
[ 50.300176] [<ffff000008082ef0>] el0_svc_naked+0x24/0x28
[ 50.305554] Code: 58000802 52800000 f9400661 b9400042 (b9000022)
--[ end trace 13
发现我的错误。我在 "local variable" 而不是重点上工作。这修复了它:
*ptep = clear_pte_bit(*ptep, __pgprot((_AT(pteval_t, 1) << 7)));
其余代码正确
我正在尝试从 LKM 中禁用 ARM64 系统上的内存写保护。 (在 Xen 管理程序的 DOM0 中开始)
我使用 Linux 内核函数找到了对应虚拟地址的 PTE。
pgd_t *pgd;
pte_t *ptep, pte;
pud_t *pud;
pmd_t *pmd;
pgd = pgd_offset(init_mm, (addr));
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto out;
printk(KERN_NOTICE "Valid pgd 0x%lx\n",pgd);
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || pud_bad(*pud))
goto out;
printk(KERN_NOTICE "Valid pud 0x%lx\n",pud);
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto out;
printk(KERN_NOTICE "Valid pmd 0x%lx\n",pmd);
ptep = pte_offset_map(pmd, addr);
if (!ptep)
goto out;
pte = *ptep;
在此之后,我将清除 PTE 的第 7 位,根据 ARM-ARM(第 2066 页 - 第 1 阶段 VMSAv8-64 块和页面描述符中的属性字段),它应该禁用允许的写保护从 EL1 写入 (AP[2:1]==00) 另外我使用 Linux 内核函数 wo "make the pte writable" 尽管这个位(位 51)用于第 2 阶段翻译(我的工作是第 1 阶段)
printk(KERN_INFO "PTE before 0x%lx\n", pte);
printk(KERN_INFO "Setting PTE write\n");
pte = pte_mkwrite(pte);
pte = clear_pte_bit(pte, __pgprot((_AT(pteval_t, 1) << 7)));
printk(KERN_INFO "PTE after 0x%lx\n", pte);
flush_tlb_all();
printk(KERN_INFO "PTE nach flush 0x%lx\n", pte);
因为在使用memcpy 写入内存时仍然出现Kernel Panic,所以我调用了两次禁用写保护的函数以检查我的设置。这些是两个函数调用的输出:
[ 1804.078382] Valid pgd 0xffff000008e7d000
[ 1804.082397] Valid pud 0xffff800017ffe000
[ 1804.086374] Valid pmd 0xffff800017ffd200
[ 1804.090367] PTE before 0xc0000040081793
[ 1804.094529] Setting PTE write
[ 1804.097562] PTE after 0xc8000040081713
[ 1804.101637] PTE after flush 0xc8000040081713
[...More outputs...]
[ 1804.117395] ROUND 2########################
[ 1804.149190] Valid pgd 0xffff000008e7d000
[ 1804.153207] Valid pud 0xffff800017ffe000
[ 1804.157178] Valid pmd 0xffff800017ffd200
[ 1804.161172] PTE before 0xc0000040081793
[ 1804.165329] Setting PTE write
[ 1804.168366] PTE after 0xc8000040081713
[ 1804.172443] PTE after flush 0xc8000040081713
(不同之处在于从左数第二个位置是 8 而不是 0,从右数第二个位置是 1 而不是 9)
如你所见,第二次调用该函数后,我们预计第一轮的最后一个 PTE 值与第二轮的第一个相同(输出 NR:1804.101637 != 1804.161172 ),这里不是这种情况。
我正在用这个命令写入内存:
static unsigned char replace_blr[4] = {0xD6,0x3F, 0x03,0xA0}; (global defined)
memcpy(el1_sync,replace_blr,4);
其中 el1_sync 包含我用于查找 pte 的虚拟地址。
有没有人看到,为什么我的 PTE 配置没有 updated/is 重置? 如果有人有替代方案让我直接写入内核内存,我也会感谢任何其他输入。我的目标只是允许写入给定虚拟地址的页面。 (就像许多 x86 rootkit,但在 ARM64 上)
KERNEL OOPS when writing: (Virtual Address: 0xffff000008081a00)
[ 49.776343] Unable to handle kernel paging request at virtual address ffff000008081a00
[ 49.784313] pgd = ffff800013d91000
[ 49.787777] [ffff000008081a00] *pgd=0000000000000000[ 49.792542]
[ 49.794094] Internal error: Oops: 9600004f [#1] PREEMPT SMP
[ 49.799721] Modules linked in: mod_init(O+) adv7511 kirin_drm drm_kms_helper dw_drm_dsi drm asix
usbnet ipv6
[ 49.809610] CPU: 1 PID: 2328 Comm: insmod Tainted: G O 4.9.0-hikey-139764-g3e36302a0
621-dirty #1
[ 49.819580] Hardware name: HiKey Development Board (DT)
[ 49.824876] task: ffff80001580b200 task.stack: ffff800015af8000
[ 49.830864] PC is at init_module+0xf8/0x1f0 [mod_init]
[ 49.836061] LR is at init_module+0xe8/0x1f0 [mod_init]
[ 49.841259] pc : [<ffff000000b71568>] lr : [<ffff000000b71558>] pstate: 00000145
[ 49.848716] sp : ffff800015afbc40
[ 49.852099] x29: ffff800015afbc40 x28: 00000000024000c0
[ 49.857474] x27: 0000000000000124 x26: ffff000008129f68
[ 49.862851] x25: 0000000000000001 x24: ffff800014f5abc8
[ 49.868227] x23: ffff000000b730d0 x22: ffff800014f5ad80
[ 49.873604] x21: 0000000000000000 x20: ffff000000b72370
[ 49.878981] x19: ffff000000b73380 x18: 0000000000000010
[ 49.884357] x17: 0000aaaadb4f02b0 x16: 0000000000000012
[ 49.889734] x15: 0000000000000006 x14: ffff000088e40a27
[ 49.895110] x13: ffff000008e40a35 x12: 0000000000000007
[ 49.900487] x11: 000000000000016d x10: 0000000005f5e0ff
[ 49.905863] x9 : 000000000000016e x8 : 70752064656b6361
[ 49.911240] x7 : 62207972746e6520 x6 : ffff000008e40a53
[ 49.916616] x5 : 0000000000000000 x4 : 0000000000000000
[ 49.921993] x3 : 0000000000000000 x2 : 00000000a0033fd6
[ 49.927370] x1 : ffff000008081a00 x0 : 0000000000000000
[ 49.932745]
[ 49.934309] Process insmod (pid: 2328, stack limit = 0xffff800015af8020)
[ 49.941073] Stack: (0xffff800015afbc40 to 0xffff800015afc000)
[ 49.946885] bc40: ffff800015afbc60 ffff0000080830b8 ffff000000b71470 ffff800015af8000
[ 49.954776] bc60: ffff800015afbcd0 ffff00000816521c ffff000000b73080 ffff000008d80000
[ 49.962667] bc80: ffff000000b73080 ffff800014f5ad80 ffff000000b73080 ffff800014f5ab80
[ 49.970558] bca0: ffff000000b730d0 ffff800014f5abc8 0000000000000001 ffff000008129f68
[ 49.978450] bcc0: 0000000000000124 00000000024000c0 ffff800015afbd00 ffff00000812d454
[ 49.986341] bce0: ffff800015afbe58 0000000000000001 ffff000000b73080 ffff800014f5ab80
[ 49.994232] bd00: ffff800015afbe10 ffff00000812dd78 0000000000000000 0000000000000003
[ 50.002124] bd20: 0000aaaadb4dd8d0 0000ffffaf31fcf4 0000000080000000 0000000000000015
[ 50.010015] bd40: 0000000000000123 0000000000000111 ffff0000088c2000 ffff800015af8000
[ 50.017906] bd60: 000000000003c788 ffff000008b3c088 ffff000000000072 ffff000000000064
[ 50.025798] bd80: ffff80000000006e ffff000000b76000 ffff80001511a118 ffff000000b73250
[ 50.033689] bda0: ffff0000088d24c0 ffff0000088d24b0 000000007fffffff 0000000000000003
[ 50.041581] bdc0: 0000000000000123 ffff0000081dfa18 ffff800015afbe10 0000000000000000
[ 50.049472] bde0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 50.057364] be00: 0000000000000000 0000000000000000 0000000000000000 ffff000008082ef0
[ 50.065255] be20: 0000000000000000 0000000000000000 ffffffffffffffff 0000000000000000
[ 50.073147] be40: ffff800015afbeb0 000000000003c788 ffff00000cb6d000 ffff00000cb6d000
[ 50.081038] be60: 000000000003c788 ffff00000cba9088 ffff00000cba8f70 ffff00000cb8d838
[ 50.088929] be80: 0000000000003000 0000000000003798 0000000000000000 0000000000000000
[ 50.096820] bea0: 0000000000000bd0 0000001a00000019 0000000000000008 0000000000000005
[ 50.104712] bec0: 0000000000000003 0000aaaadb4dd8d0 0000000000000000 0000000000000003
[ 50.112603] bee0: 0000000000000000 000000000001fd31 0000000000000001 0000000000000001
[ 50.120497] bf00: 0000000000000111 fefefefefefefeff 00000000ffffffff 0000000000000030
[ 50.128386] bf20: 0000000000000004 0000000000000008 0000ffffaf259a94 0000ffffaf3a1588
[ 50.136278] bf40: 0000ffffaf31fcd0 0000aaaadb4f02b0 0000ffffcb3fe1b0 0000aaaaf319f190
[ 50.144169] bf60: 0000000000000000 0000aaaadb4dd8d0 0000000000000000 0000000000000002
[ 50.152061] bf80: 0000aaaaf319e0d0 0000ffffcb3fe518 0000000000000000 0000000000000000
[ 50.159952] bfa0: 0000000000000000 0000ffffcb3fe450 0000aaaadb4d3bd0 0000ffffcb3fe450
[ 50.167843] bfc0: 0000ffffaf31fcf4 0000000080000000 0000000000000003 0000000000000111
[ 50.175735] bfe0: 0000000000000000 0000000000000000 0000000000000000 0002000000000035
[ 50.183624] Call trace:
[ 50.186141] Exception stack(0xffff800015afba70 to 0xffff800015afbba0)
[ 50.192644] ba60: ffff000000b73380 0001000000000000
[ 50.200536] ba80: ffff800015afbc40 ffff000000b71568 0000000000000006 0000000000000006
[ 50.208428] baa0: ffff000008e42e4a 000000000000001c ffff000008e40000 ffff000008b39520
[ 50.216323] bac0: ffff800015afbb60 ffff0000080ff5a0 ffff000000b73380 ffff000000b72370
[ 50.224210] bae0: 0000000000000000 ffff800014f5ad80 ffff000000b730d0 ffff800014f5abc8
[ 50.232102] bb00: 0000000000000001 ffff000008129f68 0000000000000000 ffff000008081a00
[ 50.239993] bb20: 00000000a0033fd6 0000000000000000 0000000000000000 0000000000000000
[ 50.247889] bb40: ffff000008e40a53 62207972746e6520 70752064656b6361 000000000000016e
[ 50.255776] bb60: 0000000005f5e0ff 000000000000016d 0000000000000007 ffff000008e40a35
[ 50.263668] bb80: ffff000088e40a27 0000000000000006 0000000000000012 0000aaaadb4f02b0
[ 50.271564] [<ffff000000b71568>] init_module+0xf8/0x1f0 [mod_init]
[ 50.277808] [<ffff0000080830b8>] do_one_initcall+0x38/0x128
[ 50.283441] [<ffff00000816521c>] do_init_module+0x5c/0x1b8
[ 50.288992] [<ffff00000812d454>] load_module+0x1a44/0x20b8
[ 50.294540] [<ffff00000812dd78>] SyS_finit_module+0xd8/0xe8
[ 50.300176] [<ffff000008082ef0>] el0_svc_naked+0x24/0x28
[ 50.305554] Code: 58000802 52800000 f9400661 b9400042 (b9000022)
--[ end trace 13
发现我的错误。我在 "local variable" 而不是重点上工作。这修复了它:
*ptep = clear_pte_bit(*ptep, __pgprot((_AT(pteval_t, 1) << 7)));
其余代码正确