问题
i'm trying to disable the Memory Write protection on an ARM64 system from within an LKM. (Startet in the DOM0 of the Xen hypervisor)
I found the corresponding PTE to an virtual address by using the Linux Kernel Functions.
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;
After this I'm clearing the 7th Bit of the PTE which should, according to the ARM-ARM (Page 2066 - Attribute fields in stage 1 VMSAv8-64 Block and Page descriptors) disable the write protection as it allows write from EL1 (AP[2:1]==00) Additioanlly im using the Linux Kernel function wo "make the pte writable" eventhough this Bit (Bit 51) is used for stage 2 translation (my work is with Stage 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);
Because i still get a Kernel Panic when writting to the memory with memcpy, i call the function to disable write protection twice in order to check my settings. These are the outputs for two function calls:
[ 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
(difference is the 8 instead of an 0 on the second spot from left, and the 1 instead of a 9 on the second one from right)
As you can see, after call the function the second time, we would expect that the last PTE Value of the first round, is the same as the first one of the second round (Output NR: 1804.101637 != 1804.161172), which is not the case here.
I'm writing into the memory with this command:
static unsigned char replace_blr[4] = {0xD6,0x3F, 0x03,0xA0}; (global defined)
memcpy(el1_sync,replace_blr,4);
where el1_sync containts the virtuall address that I'm using for the pte finding.
Does anybody see, why my PTE configuration is not updated/is reset? If somebody got an alternative to let me write directly into the kernel memory, i would also appreciate any other input. My goal is just to enable writing into the Page of the given virtual address. (Just like many of the x86 rootkits, but on ARM64)
KERNEL OOPS when writing: (Virtuall 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
回答1:
Found my error. I worked on the "local variable" instead of the point. This fixed it:
*ptep = clear_pte_bit(*ptep, __pgprot((_AT(pteval_t, 1) << 7)));
Rest of the code was correct
来源:https://stackoverflow.com/questions/45216054/arm64-linux-memory-write-protection-wont-disable