diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2022-01-05 17:53:45 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2022-01-05 17:53:45 +0000 |
commit | edd8a89d22c994aa82e421a5e097e7940df10c82 (patch) | |
tree | a5badb3a2e26d3a7c8205e4d7e63742e08ef5918 /sys | |
parent | e86c08bc6bc0af9a70f47e797f619045e2e291f7 (diff) |
Remove kbind(2)'s restriction that a target buffer not cross page
boundaries: hppa has 8-byte PLT entries that sometimes do that.
ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/uvm/uvm_mmap.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c index 0a31c622210..d721562cd5f 100644 --- a/sys/uvm/uvm_mmap.c +++ b/sys/uvm/uvm_mmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_mmap.c,v 1.167 2021/12/23 18:50:32 guenther Exp $ */ +/* $OpenBSD: uvm_mmap.c,v 1.168 2022/01/05 17:53:44 guenther Exp $ */ /* $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $ */ /* @@ -1124,7 +1124,7 @@ sys_kbind(struct proc *p, void *v, register_t *retval) vaddr_t baseva, last_baseva, endva, pageoffset, kva; size_t psize, s; u_long pc; - int count, i; + int count, i, extra; int error; /* @@ -1175,7 +1175,6 @@ sys_kbind(struct proc *p, void *v, register_t *retval) paramp[count].kb_size > KBIND_DATA_MAX || baseva >= VM_MAXUSER_ADDRESS || endva >= VM_MAXUSER_ADDRESS || - trunc_page(baseva) != trunc_page(endva) || s < paramp[count].kb_size) return EINVAL; @@ -1191,9 +1190,17 @@ sys_kbind(struct proc *p, void *v, register_t *retval) TAILQ_INIT(&dead_entries); for (i = 0; i < count; i++) { baseva = (vaddr_t)paramp[i].kb_addr; + s = paramp[i].kb_size; pageoffset = baseva & PAGE_MASK; baseva = trunc_page(baseva); + /* hppa at least runs PLT entries over page edge */ + extra = (pageoffset + s) & PAGE_MASK; + if (extra > pageoffset) + extra = 0; + else + s -= extra; +redo: /* make sure sure the desired page is mapped into kernel_map */ if (baseva != last_baseva) { if (kva != 0) { @@ -1210,10 +1217,17 @@ sys_kbind(struct proc *p, void *v, register_t *retval) } /* do the update */ - if ((error = kcopy(data, (char *)kva + pageoffset, - paramp[i].kb_size))) + if ((error = kcopy(data, (char *)kva + pageoffset, s))) break; - data += paramp[i].kb_size; + data += s; + + if (extra > 0) { + baseva += PAGE_SIZE; + s = extra; + pageoffset = 0; + extra = 0; + goto redo; + } } if (kva != 0) { |