bin/119305: [patch] jexec -n prisonname: selection by jail name

Frank Behrens frank+pr20070103 at harz.behrens.de
Thu Jan 3 08:30:03 PST 2008


>Number:         119305
>Category:       bin
>Synopsis:       [patch] jexec -n prisonname: selection by jail name
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 03 16:30:02 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Frank Behrens
>Release:        FreeBSD 7.0-BETA4-200712071613 i386
>Organization:
>Environment:
>Description:
jexec(8) needs the numeric id of jail. This id is not constant and changes on jail restarts.
Therefore it is desirable to select a jail by it's name. The attached patch is a
sample implementation.

>How-To-Repeat:
>Fix:

--- jexec_prisonbyname.patch begins here ---
--- jexec.8.orig	2007-03-16 12:09:03.000000000 +0100
+++ jexec.8	2008-01-03 16:56:53.000000000 +0100
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD: src/usr.sbin/jexec/jexec.8,v 1.4 2006/09/29 17:57:02 ru Exp $
 .\"
-.Dd April 19, 2006
+.Dd January 3, 2008
 .Dt JEXEC 8
 .Os
 .Sh NAME
@@ -35,6 +35,10 @@
 .Nm
 .Op Fl u Ar username | Fl U Ar username
 .Ar jid command ...
+.Nm
+.Op Fl u Ar username | Fl U Ar username 
+.Fl n Ar prisonname
+.Ar command ...
 .Sh DESCRIPTION
 The
 .Nm
@@ -45,6 +49,8 @@
 .Pp
 The following options are available:
 .Bl -tag -width indent
+.It Fl n Ar prisonname
+Use jail identified by name.
 .It Fl u Ar username
 The user name from host environment as whom the
 .Ar command
--- jexec.c.orig	2007-03-16 12:09:03.000000000 +0100
+++ jexec.c	2008-01-03 16:44:37.000000000 +0100
@@ -28,16 +28,19 @@
 
 #include <sys/param.h>
 #include <sys/jail.h>
+#include <sys/sysctl.h>
 
 #include <err.h>
 #include <errno.h>
 #include <login_cap.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <pwd.h>
 #include <unistd.h>
 
 static void	usage(void);
+static int	prison_id_byname(const char* prisonname);
 
 #define GET_USER_INFO do {						\
 	pwd = getpwnam(username);					\
@@ -64,11 +67,15 @@
 	gid_t groups[NGROUPS];
 	int ch, ngroups, uflag, Uflag;
 	char *username;
+	char *prisonname = NULL;
 	ch = uflag = Uflag = 0;
 	username = NULL;
 
-	while ((ch = getopt(argc, argv, "u:U:")) != -1) {
+	while ((ch = getopt(argc, argv, "n:u:U:")) != -1) {
 		switch (ch) {
+		case 'n':
+			prisonname = optarg;
+			break;
 		case 'u':
 			username = optarg;
 			uflag = 1;
@@ -83,13 +90,21 @@
 	}
 	argc -= optind;
 	argv += optind;
-	if (argc < 2)
+	if (argc < 1 || (!prisonname && argc < 2))
 		usage();
 	if (uflag && Uflag)
 		usage();
 	if (uflag)
 		GET_USER_INFO;
+	if (prisonname) {
+		jid = prison_id_byname(prisonname);
+		if (jid == -1)
+			errx(1, "prison name not found: %s", prisonname);
+	} else {
 	jid = (int)strtol(argv[0], NULL, 10);
+		argc--;
+		argv++;
+	}
 	if (jail_attach(jid) == -1)
 		err(1, "jail_attach(): %d", jid);
 	if (chdir("/") == -1)
@@ -106,8 +121,8 @@
 			err(1, "setusercontext");
 		login_close(lcap);
 	}
-	if (execvp(argv[1], argv + 1) == -1)
-		err(1, "execvp(): %s", argv[1]);
+	if (execvp(argv[0], argv) == -1)
+		err(1, "execvp(): %s", argv[0]);
 	exit(0);
 }
 
@@ -117,6 +132,54 @@
 
 	fprintf(stderr, "%s%s\n",
 		"usage: jexec [-u username | -U username]",
-		" jid command ...");
+		" -n pname | jid command ...");
 	exit(1); 
 }
+
+/*
+ * Returns prison id for prison name.
+ * return -1 if no prison with this name found.
+ */
+static int
+prison_id_byname(const char* prisonname)
+{ 
+	struct xprison *sxp, *xp;
+	size_t i, len;
+	int id = -1;
+
+	if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
+		err(1, "sysctlbyname(): security.jail.list");
+
+	for (i = 0; i < 4; i++) {
+		if (len <= 0)
+			exit(0);	
+		sxp = xp = malloc(len);
+		if (sxp == NULL)
+			err(1, "malloc()");
+
+		if (sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1) {
+			if (errno == ENOMEM) {
+				free(sxp);
+				sxp = NULL;
+				continue;
+			}
+			err(1, "sysctlbyname(): security.jail.list");
+		}
+		break;
+	}
+	if (sxp == NULL)
+		err(1, "sysctlbyname(): security.jail.list");
+	if (len < sizeof(*xp) || len % sizeof(*xp) ||
+	    xp->pr_version != XPRISON_VERSION)
+		errx(1, "Kernel and userland out of sync");
+
+	for (i = 0; i < len / sizeof(*xp); i++) {
+		if (strcmp(xp->pr_host, prisonname) == 0) {
+			id = xp->pr_id;
+			break;
+		}
+		xp++;
+	}
+	free(sxp);
+	return id;
+}
--- jexec_prisonbyname.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list