kern/122270: [Patch] Jail numbers keep incrementing

Ed Schouten ed at 80386.nl
Sun Mar 30 13:40:04 PDT 2008


>Number:         122270
>Category:       kern
>Synopsis:       [Patch] Jail numbers keep incrementing
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Mar 30 20:40:03 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Ed Schouten
>Release:        FreeBSD 8.0-CURRENT amd64
>Organization:
>Environment:
Today's CURRENT.
>Description:
The FreeBSD Jail code has some statements to make sure we never hand out
jails that share the same prison ID's. For some reason, it doesn't use
the unrhdr routines that exist inside the kernel.

If we just use unrhdr here, the jail numbers don't keep incrementing
forever, making jls/ps output a lot easier. No more 4-5 digit numbers
in your test setup, where you only have 10-20 jails.

It also removes some duplicate code from the kernel. We shouldn't roll
our own unit number allocators.
>How-To-Repeat:
Restart jails many times - jls will report very high digit jail numbers,
while you only have a small amount of jails.
>Fix:
--- sys/kern/kern_jail.c
+++ sys/kern/kern_jail.c
@@ -23,6 +23,7 @@
 #include <sys/proc.h>
 #include <sys/taskqueue.h>
 #include <sys/jail.h>
+#include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/sx.h>
@@ -78,11 +79,13 @@
     &jail_mount_allowed, 0,
     "Processes in jail can mount/unmount jail-friendly file systems");
 
-/* allprison, lastprid, and prisoncount are protected by allprison_lock. */
-struct	prisonlist allprison;
+/* allprison and prisoncount are protected by allprison_lock. */
 struct	sx allprison_lock;
-int	lastprid = 0;
+SX_SYSINIT(allprison_lock, &allprison_lock, "allprison");
+struct	prisonlist allprison = LIST_HEAD_INITIALIZER(allprison);
 int	prisoncount = 0;
+/* Prison number allocation */
+static struct unrhdr *prison_numpool;
 
 /*
  * List of jail services. Protected by allprison_lock.
@@ -108,8 +111,7 @@
 init_prison(void *data __unused)
 {
 
-	sx_init(&allprison_lock, "allprison");
-	LIST_INIT(&allprison);
+	prison_numpool = new_unrhdr(1, INT_MAX, NULL);
 }
 
 SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL);
@@ -123,11 +125,11 @@
 jail(struct thread *td, struct jail_args *uap)
 {
 	struct nameidata nd;
-	struct prison *pr, *tpr;
+	struct prison *pr;
 	struct prison_service *psrv;
 	struct jail j;
 	struct jail_attach_args jaa;
-	int vfslocked, error, tryprid;
+	int vfslocked, error, prid;
 
 	error = copyin(uap->jail, &j, sizeof(j));
 	if (error)
@@ -135,9 +137,15 @@
 	if (j.version != 0)
 		return (EINVAL);
 
+	/* Allocate prison number */
+	prid = alloc_unr(prison_numpool);
+	if (prid == -1)
+		return (EAGAIN);
+
 	MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
 	mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF);
 	pr->pr_ref = 1;
+	pr->pr_id = jaa.jid = prid;
 	error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);
 	if (error)
 		goto e_killmtx;
@@ -164,24 +172,8 @@
 		    M_PRISON, M_ZERO | M_WAITOK);
 	}
 
-	/* Determine next pr_id and add prison to allprison list. */
+	/* Add prison to allprison list. */
 	sx_xlock(&allprison_lock);
-	tryprid = lastprid + 1;
-	if (tryprid == JAIL_MAX)
-		tryprid = 1;
-next:
-	LIST_FOREACH(tpr, &allprison, pr_list) {
-		if (tpr->pr_id == tryprid) {
-			tryprid++;
-			if (tryprid == JAIL_MAX) {
-				sx_xunlock(&allprison_lock);
-				error = EAGAIN;
-				goto e_dropvnref;
-			}
-			goto next;
-		}
-	}
-	pr->pr_id = jaa.jid = lastprid = tryprid;
 	LIST_INSERT_HEAD(&allprison, pr, pr_list);
 	prisoncount++;
 	sx_downgrade(&allprison_lock);
@@ -213,6 +205,7 @@
 	VFS_UNLOCK_GIANT(vfslocked);
 e_killmtx:
 	mtx_destroy(&pr->pr_mtx);
+	free_unr(prison_numpool, pr->pr_id);
 	FREE(pr, M_PRISON);
 	return (error);
 }
@@ -346,6 +339,7 @@
 	mtx_destroy(&pr->pr_mtx);
 	if (pr->pr_linux != NULL)
 		FREE(pr->pr_linux, M_PRISON);
+	free_unr(prison_numpool, pr->pr_id);
 	FREE(pr, M_PRISON);
 }
 
--- sys/sys/jail.h
+++ sys/sys/jail.h
@@ -41,8 +41,6 @@
 #include <sys/_mutex.h>
 #include <sys/_task.h>
 
-#define JAIL_MAX	999999
-
 #ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_PRISON);
 #endif
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list