On Mon, Oct 19, 2020 at 3:13 PM Tom Rollet <[email protected]> wrote:
> Hi,
>
> I'm starting to help in the development of the dt device.
>
> I'm stuck on permission handling of memory. I'm trying to allocate a
> page in kernel with read/write protections, fill the allocated page
> with data then change the permissions to read/exec.
>
> Snippet of my code:
>
> addr = uvm_km_alloc(kernel_map, PAGE_SIZE);
>
> [...] (memcpy data in allocated page)
>
> uvm_map_protect(kernel_map, addr, addr + PAGE_SIZE, PROT_READ
> | PROT_EXEC, FALSE)))
>
This is same usage as seen in the 'sti' driver...which is on hppa only, so
while it's presumably the correct usage of uvm_km_alloc() and
uvm_map_protect(), I don't think uvm_map_protect() has been used on
kernel-space on amd64 (or possibly all non-hppa archs) before in OpenBSD.
Whee?
It triggers the following error at boot time when executing
> the uvm_map_protect function.
>
> uvm_fault(0xffffffff81fb2c90, 0x7ffec0008000, 0, 2) -> e kernel: page fault
> trap, code=0 Stopped at pmap_write_protect+0x1f5: lock andq
> $-0x3,0(%rdi)
>
> Trace:
>
> pmap_write_protect(ffffffff82187b28,ffff80002255b000,ffff80002255c000,
> 5,50e8b70481f4f622,fffffd81b6567e70) at pmap_write_protect+0x212
> uvm_map_protect(ffffffff82129ae0,ffff80002255b000,ffff80002255c000
> ,5,0,ffffffff82129ae0) at uvm_map_protect+0x501
> dt_alloc_kprobe(ffffffff815560e0,ffff800000173900,e7ef01a2855152cc,
> ffffffff82395c98,0,ffffffff815560e0) at dt_alloc_kprobe+0x1ff
> dt_prov_kprobe_init(2333e28db00d3edd,0,ffffffff82121150,0,0,
> ffffffff824d9008) at dt_prov_kprobe_init+0x1d9
> dtattach(1,ffffffff821fb384,f,1,c2ee1c3f472154e,2dda28) at dtattach+0x5d
> main(0,0,0,0,0,1) at main+0x419
>
> The problem comes from the loop in pmap_write_protect
> (sys/arch/amd64/amd64/pmap.c:2108) that is executed
> infinity in my case.
>
> Entry of function pmap_write_protect:
> sva: FFFF80002250A000
> eva: FFFF80002250B000
>
> After &= PG_FRAME (line 2098-2099)
> sva= F80002250A000
> eva= F80002250B000
>
> loop: (ligne 2108)
>
> first iteration:
> va = F80002250A000
> eva = F80002250B000
> blockend = 0800122400000
>
...
> Does anyone have an idea how to fix this issue?
So, blockend is clearly wrong for va and eva. I suspect the use of
L2_FRAME here:
blockend = (va & L2_FRAME) + NBPD_L2;
is wrong here and it should be
blockend = (va & VA_SIGN_NEG(L2_FRAME)) + NBPD_L2;
or some equivalent expression to keep all the bits above the frame.
Philip Guenther