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