Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Jun 2025 20:55:34 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f1ad4340e4ad - main - vm/vm_mmap.c: provide extended errors for most places
Message-ID:  <202506122055.55CKtYOl086521@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=f1ad4340e4adfbe9e64b4e2e9e9b19d87fa84eef

commit f1ad4340e4adfbe9e64b4e2e9e9b19d87fa84eef
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-06-11 08:36:20 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-06-12 20:32:26 +0000

    vm/vm_mmap.c: provide extended errors for most places
    
    Reviewed by:    brooks
    Sponsored by:   The FreeBSD Foundation
    Differential revision:  https://reviews.freebsd.org/D50792
---
 sys/vm/vm_mmap.c | 103 +++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 81 insertions(+), 22 deletions(-)

diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 492233215d4b..8444a8cbf021 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -231,35 +231,53 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp)
 	 */
 	if (!SV_CURPROC_FLAG(SV_AOUT)) {
 		if ((len == 0 && p->p_osrel >= P_OSREL_MAP_ANON) ||
-		    ((flags & MAP_ANON) != 0 && (fd != -1 || pos != 0)))
+		    ((flags & MAP_ANON) != 0 && (fd != -1 || pos != 0))) {
+			SET_ERROR2(EINVAL,
+			    "offset not zero/fd not -1 for MAP_ANON",
+			    fd, pos);
 			return (EINVAL);
+		}
 	} else {
 		if ((flags & MAP_ANON) != 0)
 			pos = 0;
 	}
 
 	if (flags & MAP_STACK) {
-		if ((fd != -1) ||
-		    ((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)))
+		if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
+		    (PROT_READ | PROT_WRITE))) {
+			SET_ERROR1(EINVAL, "MAP_STACK with prot < rw", prot);
 			return (EINVAL);
+		}
 		flags |= MAP_ANON;
 		pos = 0;
 	}
 	if ((flags & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | MAP_HASSEMAPHORE |
 	    MAP_STACK | MAP_NOSYNC | MAP_ANON | MAP_EXCL | MAP_NOCORE |
-	    MAP_PREFAULT_READ | MAP_GUARD | MAP_32BIT | MAP_ALIGNMENT_MASK)) != 0)
+	    MAP_PREFAULT_READ | MAP_GUARD | MAP_32BIT |
+	    MAP_ALIGNMENT_MASK)) != 0) {
+		SET_ERROR0(EINVAL, "reserved flag set");
 		return (EINVAL);
-	if ((flags & (MAP_EXCL | MAP_FIXED)) == MAP_EXCL)
+	}
+	if ((flags & (MAP_EXCL | MAP_FIXED)) == MAP_EXCL) {
+		SET_ERROR0(EINVAL, "EXCL without FIXED");
 		return (EINVAL);
-	if ((flags & (MAP_SHARED | MAP_PRIVATE)) == (MAP_SHARED | MAP_PRIVATE))
+	}
+	if ((flags & (MAP_SHARED | MAP_PRIVATE)) == (MAP_SHARED |
+	    MAP_PRIVATE)) {
+		SET_ERROR0(EINVAL, "both SHARED and PRIVATE set");
 		return (EINVAL);
+	}
 	if (prot != PROT_NONE &&
-	    (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) != 0)
+	    (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) != 0) {
+		SET_ERROR1(EINVAL, "invalid prot", prot);
 		return (EINVAL);
+	}
 	if ((flags & MAP_GUARD) != 0 && (prot != PROT_NONE || fd != -1 ||
 	    pos != 0 || (flags & ~(MAP_FIXED | MAP_GUARD | MAP_EXCL |
-	    MAP_32BIT | MAP_ALIGNMENT_MASK)) != 0))
+	    MAP_32BIT | MAP_ALIGNMENT_MASK)) != 0)) {
+		SET_ERROR0(EINVAL, "GUARD with wrong parameters");
 		return (EINVAL);
+	}
 
 	/*
 	 * Align the file position to a page boundary,
@@ -279,8 +297,10 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp)
 	align = flags & MAP_ALIGNMENT_MASK;
 	if (align != 0 && align != MAP_ALIGNED_SUPER &&
 	    (align >> MAP_ALIGNMENT_SHIFT >= sizeof(void *) * NBBY ||
-	    align >> MAP_ALIGNMENT_SHIFT < PAGE_SHIFT))
+	    align >> MAP_ALIGNMENT_SHIFT < PAGE_SHIFT)) {
+		SET_ERROR1(EINVAL, "bad alignment", align);
 		return (EINVAL);
+	}
 
 	/*
 	 * Check for illegal addresses.  Watch out for address wrap... Note
@@ -293,14 +313,21 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp)
 		 * should be aligned after adjustment by pageoff.
 		 */
 		addr -= pageoff;
-		if (addr & PAGE_MASK)
+		if ((addr & PAGE_MASK) != 0) {
+			SET_ERROR1(EINVAL, "fixed mapping not aligned", addr);
 			return (EINVAL);
+		}
 
 		/* Address range must be all in user VM space. */
-		if (!vm_map_range_valid(&vms->vm_map, addr, addr + size))
+		if (!vm_map_range_valid(&vms->vm_map, addr, addr + size)) {
+			SET_ERROR0(EINVAL, "mapping outside vm_map");
 			return (EINVAL);
-		if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR)
+		}
+		if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR) {
+			SET_ERROR0(EINVAL,
+			    "fixed 32bit mapping does not fit into 4G");
 			return (EINVAL);
+		}
 	} else if (flags & MAP_32BIT) {
 		/*
 		 * For MAP_32BIT, override the hint if it is too high and
@@ -367,6 +394,7 @@ kern_mmap(struct thread *td, const struct mmap_req *mrp)
 			goto done;
 		if ((flags & (MAP_SHARED | MAP_PRIVATE)) == 0 &&
 		    p->p_osrel >= P_OSREL_MAP_FSTRICT) {
+			SET_ERROR0(EINVAL, "neither SHARED nor PRIVATE req");
 			error = EINVAL;
 			goto done;
 		}
@@ -1296,6 +1324,7 @@ vm_mmap_vnode(struct thread *td, vm_size_t objsize,
 			vm_pager_update_writecount(obj, 0, objsize);
 		}
 	} else {
+		SET_ERROR0(EINVAL, "non-reg file");
 		error = EINVAL;
 		goto done;
 	}
@@ -1379,14 +1408,18 @@ vm_mmap_cdev(struct thread *td, vm_size_t objsize, vm_prot_t prot,
 		*flagsp |= MAP_ANON;
 		return (0);
 	}
+
 	/*
 	 * cdevs do not provide private mappings of any kind.
 	 */
 	if ((*maxprotp & VM_PROT_WRITE) == 0 &&
 	    (prot & VM_PROT_WRITE) != 0)
 		return (EACCES);
-	if (flags & (MAP_PRIVATE|MAP_COPY))
+	if ((flags & (MAP_PRIVATE | MAP_COPY)) != 0) {
+		SET_ERROR0(EINVAL, "cdev mapping must be shared");
 		return (EINVAL);
+	}
+
 	/*
 	 * Force device mappings to be shared.
 	 */
@@ -1410,8 +1443,10 @@ vm_mmap_cdev(struct thread *td, vm_size_t objsize, vm_prot_t prot,
 		return (error);
 	obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff,
 	    td->td_ucred);
-	if (obj == NULL)
+	if (obj == NULL) {
+		SET_ERROR0(EINVAL, "cdev driver does not support mmap");
 		return (EINVAL);
+	}
 	*objp = obj;
 	*flagsp = flags;
 	return (0);
@@ -1428,8 +1463,10 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
 	int error;
 	boolean_t writecounted;
 
-	if (size == 0)
+	if (size == 0) {
+		SET_ERROR0(EINVAL, "zero-sized req");
 		return (EINVAL);
+	}
 
 	size = round_page(size);
 	object = NULL;
@@ -1455,6 +1492,7 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
 		    handle, &foff, &object, &writecounted);
 		break;
 	default:
+		SET_ERROR1(EINVAL, "unsupported backing obj type", handle_type);
 		error = EINVAL;
 		break;
 	}
@@ -1536,21 +1574,32 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
 	 * callbacks) and other internal mapping requests (such as in
 	 * exec).
 	 */
-	if (foff & PAGE_MASK)
+	if ((foff & PAGE_MASK) != 0) {
+		SET_ERROR1(EINVAL, "offset not page-aligned", foff);
 		return (EINVAL);
+	}
 
 	if ((flags & MAP_FIXED) == 0) {
 		fitit = true;
 		*addr = round_page(*addr);
 	} else {
-		if (*addr != trunc_page(*addr))
+		if (*addr != trunc_page(*addr)) {
+			SET_ERROR1(EINVAL,
+			    "non-fixed mapping address not aligned", *addr);
 			return (EINVAL);
+		}
 		fitit = false;
 	}
 
 	if (flags & MAP_ANON) {
-		if (object != NULL || foff != 0)
+		if (object != NULL) {
+			SET_ERROR0(EINVAL, "anon mapping backed by an object");
+			return (EINVAL);
+		}
+		if (foff != 0) {
+			SET_ERROR0(EINVAL, "anon mapping with non-zero offset");
 			return (EINVAL);
+		}
 		docow = 0;
 	} else if (flags & MAP_PREFAULT_READ)
 		docow = MAP_PREFAULT;
@@ -1569,8 +1618,10 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
 	if (writecounted)
 		docow |= MAP_WRITECOUNT;
 	if (flags & MAP_STACK) {
-		if (object != NULL)
+		if (object != NULL) {
+			SET_ERROR0(EINVAL, "stack mapping backed by an object");
 			return (EINVAL);
+		}
 		docow |= MAP_STACK_AREA;
 	}
 	if ((flags & MAP_EXCL) != 0)
@@ -1632,16 +1683,24 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
 int
 vm_mmap_to_errno(int rv)
 {
+	int error;
 
 	switch (rv) {
 	case KERN_SUCCESS:
 		return (0);
 	case KERN_INVALID_ADDRESS:
 	case KERN_NO_SPACE:
-		return (ENOMEM);
+		error = ENOMEM;
+		break;
 	case KERN_PROTECTION_FAILURE:
-		return (EACCES);
+		error = EACCES;
+		break;
 	default:
-		return (EINVAL);
+		error = EINVAL;
+		break;
 	}
+	if ((curthread->td_pflags2 & (TDP2_UEXTERR | TDP2_EXTERR)) ==
+	    TDP2_UEXTERR)
+		SET_ERROR1(error, "mach error", rv);
+	return (error);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506122055.55CKtYOl086521>