summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2022-01-05 17:53:45 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2022-01-05 17:53:45 +0000
commitedd8a89d22c994aa82e421a5e097e7940df10c82 (patch)
treea5badb3a2e26d3a7c8205e4d7e63742e08ef5918 /sys
parente86c08bc6bc0af9a70f47e797f619045e2e291f7 (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.c26
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) {