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)));

其余代码正确