On Mon, Oct 19, 2020 at 3:13 PM Tom Rollet <tom.rol...@epita.fr> 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