Module Name:    src
Committed By:   riastradh
Date:           Wed Jul  6 00:40:16 UTC 2022

Modified Files:
        src/sys/uvm: uvm_mmap.c

Log Message:
mmap(2): Avoid overflow in rounding and checking size.


To generate a diff of this commit:
cvs rdiff -u -r1.180 -r1.181 src/sys/uvm/uvm_mmap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/uvm/uvm_mmap.c
diff -u src/sys/uvm/uvm_mmap.c:1.180 src/sys/uvm/uvm_mmap.c:1.181
--- src/sys/uvm/uvm_mmap.c:1.180	Sat Jun  4 20:54:03 2022
+++ src/sys/uvm/uvm_mmap.c	Wed Jul  6 00:40:16 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_mmap.c,v 1.180 2022/06/04 20:54:03 riastradh Exp $	*/
+/*	$NetBSD: uvm_mmap.c,v 1.181 2022/07/06 00:40:16 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -46,7 +46,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_mmap.c,v 1.180 2022/06/04 20:54:03 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_mmap.c,v 1.181 2022/07/06 00:40:16 riastradh Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_pax.h"
@@ -274,7 +274,7 @@ sys_mmap(struct lwp *l, const struct sys
 	struct proc *p = l->l_proc;
 	vaddr_t addr;
 	off_t pos;
-	vsize_t size, pageoff, newsize;
+	vsize_t size, pageoff;
 	vm_prot_t prot, maxprot, extraprot;
 	int flags, fd, advice;
 	vaddr_t defaddr = 0;	/* XXXGCC */
@@ -309,17 +309,21 @@ sys_mmap(struct lwp *l, const struct sys
 		return EINVAL;
 
 	/*
-	 * align file position and save offset.  adjust size.
+	 * Align file position and save offset into page.  Adjust size
+	 * so that it is an integral multiple of the page size.
 	 */
-
-	pageoff = (pos & PAGE_MASK);
-	pos    -= pageoff;
-	newsize = size + pageoff;		/* add offset */
-	newsize = (vsize_t)round_page(newsize);	/* round up */
-
-	if (newsize < size)
+	pageoff = pos & PAGE_MASK;
+	pos -= pageoff;
+	CTASSERT(PAGE_MASK <= __type_max(vsize_t));
+	CTASSERT((__type_max(vsize_t) - PAGE_SIZE + 1) % PAGE_SIZE == 0);
+	if (size > __type_max(vsize_t) - PAGE_SIZE + 1 - pageoff)
 		return ENOMEM;
-	size = newsize;
+	/*
+	 * size + pageoff <= VSIZE_MAX + 1 - PAGE_SIZE, and the
+	 * right-hand side is an integral multiple of the page size, so
+	 * round_page(size + pageoff) <= VSIZE_MAX + 1 - PAGE_SIZE.
+	 */
+	size = round_page(size + pageoff);
 
 	/*
 	 * now check (MAP_FIXED) or get (!MAP_FIXED) the "addr"

Reply via email to