From c9fa205213f14271b10deaee2c38c5cb3bf30508 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh@NetBSD.org>
Date: Mon, 18 Apr 2022 18:51:32 +0000
Subject: [PATCH] mmap(2): If we fail with a hint, try again without it.

`Hint' here means nonzero addr, but no MAP_FIXED or MAP_TRYFIXED.

Candidate fix for PR kern/55533.
---
 sys/uvm/uvm_mmap.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c
index f7dfbf32a914..c34ea0b9b2ff 100644
--- a/sys/uvm/uvm_mmap.c
+++ b/sys/uvm/uvm_mmap.c
@@ -333,6 +333,8 @@ sys_mmap(struct lwp *l, const struct sys_mmap_args *uap, register_t *retval)
 		if (error) {
 			return error;
 		}
+
+		defaddr = addr;
 	} else if (addr == 0 || !(flags & MAP_TRYFIXED)) {
 		/*
 		 * not fixed: make sure we skip over the largest
@@ -349,6 +351,8 @@ sys_mmap(struct lwp *l, const struct sys_mmap_args *uap, register_t *retval)
 			addr = MAX(addr, defaddr);
 		else
 			addr = MIN(addr, defaddr);
+	} else {
+		defaddr = addr;
 	}
 
 	/*
@@ -401,10 +405,22 @@ sys_mmap(struct lwp *l, const struct sys_mmap_args *uap, register_t *retval)
 	/*
 	 * now let kernel internal function uvm_mmap do the work.
 	 */
-
 	error = uvm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
 	    flags, advice, uobj, pos, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
 
+	/*
+	 * If the user provided a hint other than the default, and we
+	 * couldn't satisfy that hint, try again with the default
+	 * address.
+	 */
+	if (error && addr != defaddr) {
+		addr = defaddr;
+		pax_aslr_mmap(l, &addr, orig_addr, flags);
+		error = uvm_mmap(&p->p_vmspace->vm_map, &addr, size, prot,
+		    maxprot, flags, advice, uobj, pos,
+		    p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
+	}
+
 	/* remember to add offset */
 	*retval = (register_t)(addr + pageoff);