Disable write protection for memory pages in ARM
Asked Answered
R

1

7

I've researched on the topic for disabling of write protection on kernel text on linux, and I can only find solutions for x86 linux, which is temporarily clearing bit 16 of the cr0 register, write to the memory, and then setting bit 16 of the cr0 register again. However, this does not work for ARMv6 and above. An example of this is within this page: Linux Kernel: System call hooking example.

cr0 register is not present within the ARM architecture, and a few of the functions stated within the answers from the link, like lookup_address, change_page_attr etc. aren't present within ARM as well. I tried the solutions present within ARM, like set_memory_rw (which didn't change anything, writing to kernel text still causes oops), mem_text_write_kernel_word (writing to kernel text still causes oops), etc.

Example of oops log (formatted for presentation):

<3>[  239.987689] RKP -> Inst bf3e0098 out of cpu_v7_set_pte_ext range\
 from c01159c4 to c0115a1c
<1>[  239.988079] Unable to handle kernel paging request at virtual\
 address c01c1d50
<1>[  239.988123] pgd = ea8e4000
<1>[  239.988280] [c01c1d50] *pgd=0da00011
<0>[  239.988377] Internal error: Oops: 80f [#1] PREEMPT SMP ARM
<4>[  239.988416] Modules linked in: my_mod(O+) wlan(PO) mhi(O)
<4>[  239.988469] CPU: 0 PID: 5443 Comm: insmod \
 Tainted: P        W  O 3.10.0-2413392 #1
<4>[  239.988521] task: e4af4ec0 ti: da95a000 task.ti: da95a000
<4>[  239.988565] PC is at my_mod_init+0x98/0x1000 [my_mod]
<4>[  239.988605] LR is at my_mod_init+0x8c/0x1000 [my_mod]

[snip]

<4>[  239.994032] [<bf3e0098>] (my_mod_init+0x98/0x1000 [my_mod]) from\
     [<c010065c>] (do_one_initcall+0xcc/0x180)
<4>[  239.994107] [<c010065c>] (do_one_initcall+0xcc/0x180) from\
     [<c01c524c>] (load_module+0x1c98/0x1fc0)
<4>[  239.994174] [<c01c524c>] (load_module+0x1c98/0x1fc0) from\
     [<c01c5670>] (SyS_init_module+0xfc/0x11c)
<4>[  239.994240] [<c01c5670>] (SyS_init_module+0xfc/0x11c) from\
     [<c0106328>] (__sys_trace_return+0x0/0x18)
<0>[  239.994303] Code: ebffebdc e59f202c e1a00004 e59f3028 (e5832d50) 
<4>[  239.994580] ---[ end trace dec6997083161644 ]---
<0>[  239.994618] Kernel panic - not syncing: Fatal exception

Even trying to register a kprobe causes kernel oops:

<3>[  184.769314] RKP -> Inst c0abe2a0 out of cpu_v7_set_pte_ext\
    range from c01159c4 to c0115a1c
<1>[  184.769369] Unable to handle kernel paging request at\
     virtual address c0170ce4
<1>[  184.769416] pgd = dc828000
<1>[  184.769439] [c0170ce4] *pgd=0da00011
<0>[  184.769535] Internal error: Oops: 80f [#1] PREEMPT SMP ARM
<4>[  184.769572] Modules linked in: kp_mod(O+) wlan(PO) mhi(O)
<4>[  184.769620] CPU: 0 PID: 5835 Comm: insmod \
    Tainted: P        W  O 3.10.0-2413392 #1
<4>[  184.769665] task: ea0cf8c0 ti: de9a0000 task.ti: de9a0000
<4>[  184.769706] PC is at __patch_text+0x24/0x3c
<4>[  184.769734] LR is at __patch_text+0x1c/0x3c

[snip]

<4>[  184.776127] [<c0abe2a0>] (__patch_text+0x24/0x3c) from\
    [<c0abf000>] (arm_kprobe+0x24/0x34)
<4>[  184.776188] [<c0abf000>] (arm_kprobe+0x24/0x34) from\
    [<c0ac03d8>] (register_kprobe+0x4f0/0x58c)
<4>[  184.776256] [<c0ac03d8>] (register_kprobe+0x4f0/0x58c) from\
    [<bf3e0010>] (kprobe_init+0x10/0x1000 [kp_mod])
<4>[  184.776325] [<bf3e0010>] (kprobe_init+0x10/0x1000 [kp_mod]) from\
    [<c010065c>] (do_one_initcall+0xcc/0x180)
<4>[  184.776391] [<c010065c>] (do_one_initcall+0xcc/0x180) from\
    [<c01c524c>] (load_module+0x1c98/0x1fc0)
<4>[  184.776450] [<c01c524c>] (load_module+0x1c98/0x1fc0) from\
    [<c01c5670>] (SyS_init_module+0xfc/0x11c)
<4>[  184.776508] [<c01c5670>] (SyS_init_module+0xfc/0x11c) from\
    [<c0106328>] (__sys_trace_return+0x0/0x18)
<0>[  184.776563] Code: e1a00004 ebd9561f e1a01004 e1a00004 (e4815004) 
<4>[  184.776608] ---[ end trace dec6997083161644 ]---
<0>[  184.776642] Kernel panic - not syncing: Fatal exception

Can someone experienced in this area shed some light on this issue?

Rarebit answered 27/7, 2015 at 8:19 Comment(3)
Corey Henderson noted that set_memory_rw fails under certain conditions, and the only solution was to lookup the page table entry and set the permission bit manually. If the lookup_address function is not provided, virt_to_page might apply, however this answer triggered Oopses for someone too.Arnie
@Rarebit Have you disabled CONFIG_DEBUG_RODATA in your kernel?...Agribusiness
mem_text_write_kernel_word() might not be exactly what you want, but can be a good starting point.Dumpy
A
0

call set_kernel_text_rw() before hook sys_call_table

the path of set_kernel_text_rw() function in the linux kernel arch\arm\mm\init.c

Acrilan answered 6/4, 2021 at 7:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.