Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Aug 2012 13:06:44 +0400
From:      Andrey Zonov <zont@FreeBSD.org>
To:        freebsd-arch@freebsd.org
Subject:   Re: [patch] unprivileged mlock(2)
Message-ID:  <503F2D24.8050103@FreeBSD.org>
In-Reply-To: <20120829092318.GW33100@deviant.kiev.zoral.com.ua>
References:  <503DD433.2030108@FreeBSD.org> <201208290906.q7T96C9j032802@gw.catspoiler.org> <20120829092318.GW33100@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
--------------enig5C2551C41E5B3832AFE69806
Content-Type: multipart/mixed; boundary="------------020105090900020700090502"

This is a multi-part message in MIME format.
--------------020105090900020700090502
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Hi,

So, I've got the first version of the patch (attached) which fixes
memory locked limit checking and accounting.

I also want to change 'pmap_wired_count(vm_map_pmap(map))' with
'vmspace_wired_count(vmspace)', and apply the patch below separately:

Index: sys/vm/vm_mmap.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/vm/vm_mmap.c	(revision 239611)
+++ sys/vm/vm_mmap.c	(working copy)
@@ -1483,11 +1483,13 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_=
t
 			PROC_UNLOCK(td->td_proc);
 			return (ENOMEM);
 		}
+#ifdef RACCT
 		if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
 			PROC_UNLOCK(td->td_proc);
 			return (ENOMEM);
 		}
 		PROC_UNLOCK(td->td_proc);
+#endif
 	}

 	/*

It looks like this was missed in r220373.

--=20
Andrey Zonov

--------------020105090900020700090502
Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0";
	name="mlock.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
 filename="mlock.patch"

Index: sys/vm/vm_map.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/vm/vm_map.c	(revision 239772)
+++ sys/vm/vm_map.c	(working copy)
@@ -3247,7 +3247,7 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm
 	vm_offset_t bot, top;
 	vm_size_t init_ssize;
 	int orient, rv;
-	rlim_t vmemlim;
+	rlim_t lmemlim, vmemlim;
=20
 	/*
 	 * The stack orientation is piggybacked with the cow argument.
@@ -3267,6 +3267,7 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm
 	init_ssize =3D (max_ssize < sgrowsiz) ? max_ssize : sgrowsiz;
=20
 	PROC_LOCK(curthread->td_proc);
+	lmemlim =3D lim_cur(curthread->td_proc, RLIMIT_MEMLOCK);
 	vmemlim =3D lim_cur(curthread->td_proc, RLIMIT_VMEM);
 	PROC_UNLOCK(curthread->td_proc);
=20
@@ -3278,6 +3279,14 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm=

 		return (KERN_NO_SPACE);
 	}
=20
+	if (map->flags & MAP_WIREFUTURE) {
+		if (ptoa(vmspace_wired_count(curthread->td_proc->p_vmspace)) +
+		    init_ssize > lmemlim) {
+			vm_map_unlock(map);
+			return (KERN_NO_SPACE);
+		}
+	}
+
 	/* If we would blow our VMEM resource limit, no go */
 	if (map->size + init_ssize > vmemlim) {
 		vm_map_unlock(map);
@@ -3358,7 +3367,7 @@ vm_map_growstack(struct proc *p, vm_offset_t addr)
 	vm_map_t map =3D &vm->vm_map;
 	vm_offset_t end;
 	size_t grow_amount, max_grow;
-	rlim_t stacklim, vmemlim;
+	rlim_t lmemlim, stacklim, vmemlim;
 	int is_procstack, rv;
 	struct ucred *cred;
 #ifdef notyet
@@ -3370,6 +3379,7 @@ vm_map_growstack(struct proc *p, vm_offset_t addr)
=20
 Retry:
 	PROC_LOCK(p);
+	lmemlim =3D lim_cur(p, RLIMIT_MEMLOCK);
 	stacklim =3D lim_cur(p, RLIMIT_STACK);
 	vmemlim =3D lim_cur(p, RLIMIT_VMEM);
 	PROC_UNLOCK(p);
@@ -3491,7 +3501,25 @@ Retry:
 	if (is_procstack && (ctob(vm->vm_ssize) + grow_amount > limit))
 		grow_amount =3D limit - ctob(vm->vm_ssize);
 #endif
-
+	if (map->flags & MAP_WIREFUTURE) {
+		if (ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount >
+		    lmemlim) {
+			vm_map_unlock_read(map);
+			rv =3D KERN_NO_SPACE;
+			goto out;
+		}
+#ifdef RACCT
+		PROC_LOCK(p);
+		if (racct_set(p, RACCT_MEMLOCK,
+		    ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount)) {
+			PROC_UNLOCK(p);
+			vm_map_unlock_read(map);
+			rv =3D KERN_NO_SPACE;
+			goto out;
+		}
+		PROC_UNLOCK(p);
+#endif
+	}
 	/* If we would blow our VMEM resource limit, no go */
 	if (map->size + grow_amount > vmemlim) {
 		vm_map_unlock_read(map);
Index: sys/vm/vm_mmap.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/vm/vm_mmap.c	(revision 239772)
+++ sys/vm/vm_mmap.c	(working copy)
@@ -1035,9 +1035,6 @@ sys_mlock(td, uap)
 	unsigned long nsize;
 	int error;
=20
-	error =3D priv_check(td, PRIV_VM_MLOCK);
-	if (error)
-		return (error);
 	addr =3D (vm_offset_t)uap->addr;
 	size =3D uap->len;
 	last =3D addr + size;
@@ -1102,22 +1099,18 @@ sys_mlockall(td, uap)
 	if ((uap->how =3D=3D 0) || ((uap->how & ~(MCL_CURRENT|MCL_FUTURE)) !=3D=
 0))
 		return (EINVAL);
=20
-#if 0
 	/*
 	 * If wiring all pages in the process would cause it to exceed
 	 * a hard resource limit, return ENOMEM.
 	 */
-	PROC_LOCK(td->td_proc);
-	if (map->size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
+	if (uap->how & MCL_CURRENT) {
+		PROC_LOCK(td->td_proc);
+		if (map->size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
+			PROC_UNLOCK(td->td_proc);
+			return (ENOMEM);
+		}
 		PROC_UNLOCK(td->td_proc);
-		return (ENOMEM);
 	}
-	PROC_UNLOCK(td->td_proc);
-#else
-	error =3D priv_check(td, PRIV_VM_MLOCK);
-	if (error)
-		return (error);
-#endif
 #ifdef RACCT
 	PROC_LOCK(td->td_proc);
 	error =3D racct_set(td->td_proc, RACCT_MEMLOCK, map->size);
@@ -1174,9 +1167,6 @@ sys_munlockall(td, uap)
 	int error;
=20
 	map =3D &td->td_proc->p_vmspace->vm_map;
-	error =3D priv_check(td, PRIV_VM_MUNLOCK);
-	if (error)
-		return (error);
=20
 	/* Clear the MAP_WIREFUTURE flag from this vm_map. */
 	vm_map_lock(map);
@@ -1215,9 +1205,6 @@ sys_munlock(td, uap)
 	vm_size_t size;
 	int error;
=20
-	error =3D priv_check(td, PRIV_VM_MUNLOCK);
-	if (error)
-		return (error);
 	addr =3D (vm_offset_t)uap->addr;
 	size =3D uap->len;
 	last =3D addr + size;
@@ -1479,14 +1466,32 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_=
t
=20
 	if (map =3D=3D &td->td_proc->p_vmspace->vm_map) {
 		PROC_LOCK(td->td_proc);
+		if (map->flags & MAP_WIREFUTURE) {
+			if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
+			    size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
+				PROC_UNLOCK(td->td_proc);
+				return (ENOMEM);
+			}
+#ifdef RACCT
+			error =3D racct_set(td->td_proc, RACCT_MEMLOCK,
+			    ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
+			    size);
+			if (error !=3D 0) {
+				PROC_UNLOCK(td->td_proc);
+				return (error);
+			}
+#endif
+		}
 		if (map->size + size > lim_cur(td->td_proc, RLIMIT_VMEM)) {
 			PROC_UNLOCK(td->td_proc);
 			return (ENOMEM);
 		}
+#ifdef RACCT /* was missed in r220373 */
 		if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
 			PROC_UNLOCK(td->td_proc);
 			return (ENOMEM);
 		}
+#endif
 		PROC_UNLOCK(td->td_proc);
 	}
=20
Index: sys/vm/vm_unix.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/vm/vm_unix.c	(revision 239772)
+++ sys/vm/vm_unix.c	(working copy)
@@ -77,13 +77,14 @@ sys_obreak(td, uap)
 {
 	struct vmspace *vm =3D td->td_proc->p_vmspace;
 	vm_offset_t new, old, base;
-	rlim_t datalim, vmemlim;
+	rlim_t datalim, lmemlim, vmemlim;
 	int prot, rv;
 	int error =3D 0;
 	boolean_t do_map_wirefuture;
=20
 	PROC_LOCK(td->td_proc);
 	datalim =3D lim_cur(td->td_proc, RLIMIT_DATA);
+	lmemlim =3D lim_cur(td->td_proc, RLIMIT_MEMLOCK);
 	vmemlim =3D lim_cur(td->td_proc, RLIMIT_VMEM);
 	PROC_UNLOCK(td->td_proc);
=20
@@ -116,6 +117,13 @@ sys_obreak(td, uap)
 		goto done;
 	}
 	if (new > old) {
+		if (vm->vm_map.flags & MAP_WIREFUTURE) {
+			if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
+			    (new - old) > lmemlim) {
+				error =3D ENOMEM;
+				goto done;
+			}
+		}
 		if (vm->vm_map.size + (new - old) > vmemlim) {
 			error =3D ENOMEM;
 			goto done;
Index: lib/libc/sys/mlockall.2
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- lib/libc/sys/mlockall.2	(revision 239772)
+++ lib/libc/sys/mlockall.2	(working copy)
@@ -72,8 +72,6 @@ limit and the per-process
 .Dv RLIMIT_MEMLOCK
 resource limit.
 .Pp
-These calls are only available to the super-user.
-.Pp
 The
 .Fn munlockall
 call unlocks any locked memory regions in the process address space.
Index: lib/libc/sys/mlock.2
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- lib/libc/sys/mlock.2	(revision 239772)
+++ lib/libc/sys/mlock.2	(working copy)
@@ -98,8 +98,6 @@ a system-wide ``wired pages'' limit and
 the per-process
 .Li RLIMIT_MEMLOCK
 resource limit.
-.Pp
-These calls are only available to the super-user.
 .Sh RETURN VALUES
 .Rv -std
 .Pp
@@ -111,8 +109,6 @@ The
 system call
 will fail if:
 .Bl -tag -width Er
-.It Bq Er EPERM
-The caller is not the super-user.
 .It Bq Er EINVAL
 The address given is not page aligned or the length is negative.
 .It Bq Er EAGAIN
@@ -128,8 +124,6 @@ The
 system call
 will fail if:
 .Bl -tag -width Er
-.It Bq Er EPERM
-The caller is not the super-user.
 .It Bq Er EINVAL
 The address given is not page aligned or the length is negative.
 .It Bq Er ENOMEM

--------------020105090900020700090502--

--------------enig5C2551C41E5B3832AFE69806
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.18 (Darwin)
Comment: GPGTools - http://gpgtools.org

iQEcBAEBAgAGBQJQPy0nAAoJEBWLemxX/CvTF0QIAK0JH1n++jqx9etPFKNP8TRP
lcSoyPBdzMwnpqiOPNBxJqXfrh0kW+73gyCDaPhOp65KTVIK+VPaGcZX/3qwTyA1
IdwTji8nRdwGp+L8mbjNRq/2CbHcaS/us31qql/I8krL+kJ0gfaDHOSlxuNvQj10
T3pMXQ5PmPvuioVutSrA6u1HENGCBLQemk5npvfNzDbYdwXe5re0+GhU3v7n4zoy
IdX/9sDdj8skboOeVHO+n0Z9Dzr1vuTiYitfTiuy9wXhqCx2CtDOlbefWc0TEoR4
t4bNv8cnVVyXj/h7b2OdBgOOhzFtJt8jN9hjGvOMbfK6+2t17skdKcDB8R++l14=
=voP9
-----END PGP SIGNATURE-----

--------------enig5C2551C41E5B3832AFE69806--



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