--- Begin Message ---
- To: submit@bugs.debian.org
- Subject: freebsd-utils: add jls, jexec support
- From: Hideki Yamane <henrich@debian.or.jp>
- Date: Sun, 29 Nov 2015 07:25:08 +0900
- Message-id: <20151129072508.24c6b51bcdfd4eea52d62a31@debian.or.jp>
Package: freebsd-utils
Tags: patch
Hi,
At Tokyo Debian meeting, SUGIMOTO Norimitsu <dictoss@live.jp> demonstrates
kFreeBSD and it's interesting. And I heard about it lacks full jail support
since jls and jexec doesn't be included. So, I made a patch for it :)
It works, confirmed by Norimitsu as below
$ sudo dpkg -i freebsd-utils_10.1~svn273304+jail1-1_kfreebsd-amd64.deb
[norimitu@test-kf2]$ sudo jail -J /var/run/jail/1.jid -c jid=1 \
name=jail1 \
path=/srv/jail/jail_kf64_1 \
host.hostname=jail_kf64_1 \
ip4.addr=192.168.22.61 \
command=/bin/sh -- -c "/etc/init.d/rc S && /etc/init.d/rc 2"
## exec jls
[norimitu@test-kf2]$ sudo jls
JID IP Address Hostname Path
1 192.168.22.61 jail_kf64_1 /srv/jail/jail_kf64_1
## exec jexec
[norimitu@test-kf2]$ sudo jexec 1 touch /root/foobar.txt
## check file that was created with jexec
[norimitu@test-kf2]$ sudo ls -l /srv/jail/jail_kf64_1/root
合計 0
-rw-r--r-- 1 root root 0 11月 23 15:52 foobar.txt
## seems ok :)
--
Regards,
Hideki Yamane henrich @ debian.or.jp/org
http://wiki.debian.org/HidekiYamane
diff -urN freebsd-utils-10.1~svn273304.orig/debian/changelog freebsd-utils-10.1~svn273304/debian/changelog
--- freebsd-utils-10.1~svn273304.orig/debian/changelog 2014-10-21 19:11:16.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/changelog 2015-11-29 07:14:13.811304759 +0900
@@ -1,3 +1,9 @@
+freebsd-utils (10.1~svn273304+jail1-1) UNRELEASED; urgency=medium
+
+ * add jls/jexec support
+
+ -- Hideki Yamane <henrich@debian.org> Sun, 22 Nov 2015 01:54:31 +0900
+
freebsd-utils (10.1~svn273304-1) unstable; urgency=medium
[ Petr Salinger ]
diff -urN freebsd-utils-10.1~svn273304.orig/debian/freebsd-utils.install freebsd-utils-10.1~svn273304/debian/freebsd-utils.install
--- freebsd-utils-10.1~svn273304.orig/debian/freebsd-utils.install 2014-08-29 07:44:16.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/freebsd-utils.install 2015-11-22 02:09:34.000000000 +0900
@@ -27,3 +27,5 @@
usr/sbin/acpiconf /usr/sbin
usr/sbin/jail /usr/sbin
+usr/sbin/jls /usr/sbin
+usr/sbin/jexec /usr/sbin
diff -urN freebsd-utils-10.1~svn273304.orig/debian/patches/makefiles.diff freebsd-utils-10.1~svn273304/debian/patches/makefiles.diff
--- freebsd-utils-10.1~svn273304.orig/debian/patches/makefiles.diff 2014-10-06 04:59:11.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/patches/makefiles.diff 2015-11-22 02:31:57.000000000 +0900
+Index: freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jexec/Makefile
+===================================================================
+--- freebsd-utils-10.1~svn273304+jail1.orig/src/usr.sbin/jexec/Makefile
++++ freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jexec/Makefile
+@@ -3,6 +3,8 @@
+ PROG= jexec
+ MAN= jexec.8
+ DPADD= ${LIBJAIL} ${LIBUTIL}
+-LDADD= -ljail -lutil
++LDADD= -ljail -lutil-freebsd
++
++LDADD+= -lfreebsd-glue
+
+ .include <bsd.prog.mk>
+Index: freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jls/Makefile
+===================================================================
+--- freebsd-utils-10.1~svn273304+jail1.orig/src/usr.sbin/jls/Makefile
++++ freebsd-utils-10.1~svn273304+jail1/src/usr.sbin/jls/Makefile
+@@ -7,6 +7,8 @@ MAN= jls.8
+ DPADD= ${LIBJAIL}
+ LDADD= -ljail
+
++LDADD+= -lfreebsd-glue
++
+ .if ${MK_INET6_SUPPORT} != "no"
+ CFLAGS+= -DINET6
+ .endif
diff -urN freebsd-utils-10.1~svn273304.orig/debian/rules freebsd-utils-10.1~svn273304/debian/rules
--- freebsd-utils-10.1~svn273304.orig/debian/rules 2014-10-20 20:14:18.000000000 +0900
+++ freebsd-utils-10.1~svn273304/debian/rules 2015-11-22 02:02:32.000000000 +0900
@@ -113,6 +113,7 @@
sys/i386/linux/syscalls.master \
\
usr.sbin/jail bin/chflags \
+ usr.sbin/jls usr.sbin/jexec \
sbin/devd etc/devd.conf etc/devd sys/dev/usb/usbdevs \
usr.sbin/acpi/acpiconf \
usr.sbin/acpi/Makefile \
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/Makefile freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/Makefile
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/Makefile 1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/Makefile 2015-11-24 07:00:09.000000000 +0900
@@ -0,0 +1,10 @@
+# $FreeBSD: release/10.1.0/usr.sbin/jexec/Makefile 201390 2010-01-02 11:07:44Z ed $
+
+PROG= jexec
+MAN= jexec.8
+DPADD= ${LIBJAIL} ${LIBUTIL}
+LDADD= -ljail -lutil-freebsd
+
+LDADD+= -lfreebsd-glue
+
+.include <bsd.prog.mk>
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.8 freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.8
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.8 1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.8 2015-11-22 01:46:49.000000000 +0900
@@ -0,0 +1,76 @@
+.\"
+.\" Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: release/10.1.0/usr.sbin/jexec/jexec.8 192896 2009-05-27 14:30:26Z jamie $
+.\"
+.Dd May 27, 2009
+.Dt JEXEC 8
+.Os
+.Sh NAME
+.Nm jexec
+.Nd "execute a command inside an existing jail"
+.Sh SYNOPSIS
+.Nm
+.Op Fl u Ar username | Fl U Ar username
+.Ar jail command ...
+.Sh DESCRIPTION
+The
+.Nm
+utility executes
+.Ar command
+inside the
+.Ar jail
+identified by its jid or name.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl u Ar username
+The user name from host environment as whom the
+.Ar command
+should run.
+.It Fl U Ar username
+The user name from jailed environment as whom the
+.Ar command
+should run.
+.El
+.Sh SEE ALSO
+.Xr jail_attach 2 ,
+.Xr jail 8 ,
+.Xr jls 8
+.Sh HISTORY
+The
+.Nm
+utility was added in
+.Fx 5.1 .
+.Sh BUGS
+If the jail is not identified by
+.Ar jid
+there is a possible race in between the lookup of the jail
+and executing the command inside the jail.
+Giving a
+.Ar jid
+has a similar race as another process can stop the jail and
+start another one after the user looked up the
+.Ar jid .
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.c freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.c
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jexec/jexec.c 1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jexec/jexec.c 2015-11-22 01:46:49.000000000 +0900
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: release/10.1.0/usr.sbin/jexec/jexec.c 194869 2009-06-24 18:18:35Z jamie $
+ */
+
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <jail.h>
+#include <limits.h>
+#include <login_cap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <unistd.h>
+
+static void usage(void);
+
+#define GET_USER_INFO do { \
+ pwd = getpwnam(username); \
+ if (pwd == NULL) { \
+ if (errno) \
+ err(1, "getpwnam: %s", username); \
+ else \
+ errx(1, "%s: no such user", username); \
+ } \
+ lcap = login_getpwclass(pwd); \
+ if (lcap == NULL) \
+ err(1, "getpwclass: %s", username); \
+ ngroups = ngroups_max; \
+ if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \
+ err(1, "getgrouplist: %s", username); \
+} while (0)
+
+int
+main(int argc, char *argv[])
+{
+ int jid;
+ login_cap_t *lcap = NULL;
+ struct passwd *pwd = NULL;
+ gid_t *groups = NULL;
+ int ch, ngroups, uflag, Uflag;
+ long ngroups_max;
+ char *username;
+
+ ch = uflag = Uflag = 0;
+ username = NULL;
+ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
+ if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
+ err(1, "malloc");
+
+ while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
+ switch (ch) {
+ case 'n':
+ /* Specified name, now unused */
+ break;
+ case 'u':
+ username = optarg;
+ uflag = 1;
+ break;
+ case 'U':
+ username = optarg;
+ Uflag = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc < 2)
+ usage();
+ if (uflag && Uflag)
+ usage();
+ if (uflag)
+ GET_USER_INFO;
+ jid = jail_getid(argv[0]);
+ if (jid < 0)
+ errx(1, "%s", jail_errmsg);
+ if (jail_attach(jid) == -1)
+ err(1, "jail_attach(%d)", jid);
+ if (chdir("/") == -1)
+ err(1, "chdir(): /");
+ if (username != NULL) {
+ if (Uflag)
+ GET_USER_INFO;
+ if (setgroups(ngroups, groups) != 0)
+ err(1, "setgroups");
+ if (setgid(pwd->pw_gid) != 0)
+ err(1, "setgid");
+ if (setusercontext(lcap, pwd, pwd->pw_uid,
+ LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
+ err(1, "setusercontext");
+ login_close(lcap);
+ }
+ if (execvp(argv[1], argv + 1) == -1)
+ err(1, "execvp(): %s", argv[1]);
+ exit(0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "%s\n",
+ "usage: jexec [-u username | -U username] jail command ...");
+ exit(1);
+}
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/Makefile freebsd-utils-10.1~svn273304/src/usr.sbin/jls/Makefile
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/Makefile 1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jls/Makefile 2015-11-24 07:00:09.000000000 +0900
@@ -0,0 +1,19 @@
+# $FreeBSD: release/10.1.0/usr.sbin/jls/Makefile 222465 2011-05-29 21:03:40Z bz $
+
+.include <bsd.own.mk>
+
+PROG= jls
+MAN= jls.8
+DPADD= ${LIBJAIL}
+LDADD= -ljail
+
+LDADD+= -lfreebsd-glue
+
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
+
+.include <bsd.prog.mk>
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.8 freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.8
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.8 1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.8 2015-11-22 01:46:45.000000000 +0900
@@ -0,0 +1,115 @@
+.\"
+.\" Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: release/10.1.0/usr.sbin/jls/jls.8 250736 2013-05-17 08:48:16Z des $
+.\"
+.Dd July 20, 2012
+.Dt JLS 8
+.Os
+.Sh NAME
+.Nm jls
+.Nd "list jails"
+.Sh SYNOPSIS
+.Nm
+.Op Fl dhNnqsv
+.Op Fl j Ar jail
+.Op Ar parameter ...
+.Sh DESCRIPTION
+The
+.Nm
+utility lists all active jails, or the specified jail.
+Each jail is represented by one row which contains space-separated values of
+the listed
+.Ar parameters ,
+including the pseudo-parameter
+.Va all
+which will show all available jail parameters.
+A list of available parameters can be retrieved via
+.Dq Nm sysctl Fl d Va security.jail.param .
+See
+.Xr jail 8
+for a description of some core parameters.
+.Pp
+If no
+.Ar parameters
+or any of the options
+.Fl hns
+are given, the following four columns will be printed:
+jail identifier (jid), IP address (ip4.addr), hostname (host.hostname),
+and path (path).
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl d
+List
+.Va dying
+as well as active jails.
+.It Fl h
+Print a header line containing the parameters listed.
+If no parameters are given on the command line,
+.Va all
+is assumed.
+.It Fl N
+In the standard display mode, print each jail's name instead of its
+numeric ID.
+If the jail does not have a name, the numeric ID is printed instead.
+.It Fl n
+Print parameters in
+.Dq name=value
+format, where each parameter is preceded by its name.
+If no parameters are given on the command line,
+.Va all
+is assumed.
+.It Fl q
+Put quotes around parameters if they contain spaces or quotes, or are
+the empty string.
+.It Fl s
+Print parameters suitable for passing to
+.Xr jail 8 ,
+skipping read-only and unused parameters.
+Implies
+.Fl nq .
+.It Fl v
+Print a multiple-line summary per jail, with the following parameters:
+jail identifier (jid), hostname (host.hostname), path (path),
+jail name (name), jail state (dying), cpuset ID (cpuset),
+IP address(es) (ip4.addr and ip6.addr).
+.It Fl j Ar jail
+The jid or name of the
+.Ar jail
+to list.
+Without this option, all active jails will be listed.
+.El
+.Sh SEE ALSO
+.Xr jail_get 2 ,
+.Xr jail 8 ,
+.Xr jexec 8
+.Sh HISTORY
+The
+.Nm
+utility was added in
+.Fx 5.1 .
+Extensible jail parameters were introduced in
+.Fx 8.0 .
diff -urN freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.c freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.c
--- freebsd-utils-10.1~svn273304.orig/src/usr.sbin/jls/jls.c 1970-01-01 09:00:00.000000000 +0900
+++ freebsd-utils-10.1~svn273304/src/usr.sbin/jls/jls.c 2015-11-22 01:46:45.000000000 +0900
@@ -0,0 +1,516 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
+ * Copyright (c) 2009 James Gritton <jamie@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: release/10.1.0/usr.sbin/jls/jls.c 250736 2013-05-17 08:48:16Z des $");
+
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <jail.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define JP_USER 0x01000000
+#define JP_OPT 0x02000000
+
+#define PRINT_DEFAULT 0x01
+#define PRINT_HEADER 0x02
+#define PRINT_NAMEVAL 0x04
+#define PRINT_QUOTED 0x08
+#define PRINT_SKIP 0x10
+#define PRINT_VERBOSE 0x20
+#define PRINT_JAIL_NAME 0x40
+
+static struct jailparam *params;
+static int *param_parent;
+static int nparams;
+#ifdef INET6
+static int ip6_ok;
+#endif
+#ifdef INET
+static int ip4_ok;
+#endif
+
+static int add_param(const char *name, void *value, size_t valuelen,
+ struct jailparam *source, unsigned flags);
+static int sort_param(const void *a, const void *b);
+static char *noname(const char *name);
+static char *nononame(const char *name);
+static int print_jail(int pflags, int jflags);
+static void quoted_print(char *str);
+
+int
+main(int argc, char **argv)
+{
+ char *dot, *ep, *jname;
+ int c, i, jflags, jid, lastjid, pflags, spc;
+
+ jname = NULL;
+ pflags = jflags = jid = 0;
+ while ((c = getopt(argc, argv, "adj:hNnqsv")) >= 0)
+ switch (c) {
+ case 'a':
+ case 'd':
+ jflags |= JAIL_DYING;
+ break;
+ case 'j':
+ jid = strtoul(optarg, &ep, 10);
+ if (!jid || *ep) {
+ jid = 0;
+ jname = optarg;
+ }
+ break;
+ case 'h':
+ pflags = (pflags & ~(PRINT_SKIP | PRINT_VERBOSE)) |
+ PRINT_HEADER;
+ break;
+ case 'N':
+ pflags |= PRINT_JAIL_NAME;
+ break;
+ case 'n':
+ pflags = (pflags & ~PRINT_VERBOSE) | PRINT_NAMEVAL;
+ break;
+ case 'q':
+ pflags |= PRINT_QUOTED;
+ break;
+ case 's':
+ pflags = (pflags & ~(PRINT_HEADER | PRINT_VERBOSE)) |
+ PRINT_NAMEVAL | PRINT_QUOTED | PRINT_SKIP;
+ break;
+ case 'v':
+ pflags = (pflags &
+ ~(PRINT_HEADER | PRINT_NAMEVAL | PRINT_SKIP)) |
+ PRINT_VERBOSE;
+ break;
+ default:
+ errx(1, "usage: jls [-dhNnqv] [-j jail] [param ...]");
+ }
+
+#ifdef INET6
+ ip6_ok = feature_present("inet6");
+#endif
+#ifdef INET
+ ip4_ok = feature_present("inet");
+#endif
+
+ /* Add the parameters to print. */
+ if (optind == argc) {
+ if (pflags & (PRINT_HEADER | PRINT_NAMEVAL))
+ add_param("all", NULL, (size_t)0, NULL, JP_USER);
+ else if (pflags & PRINT_VERBOSE) {
+ add_param("jid", NULL, (size_t)0, NULL, JP_USER);
+ add_param("host.hostname", NULL, (size_t)0, NULL,
+ JP_USER);
+ add_param("path", NULL, (size_t)0, NULL, JP_USER);
+ add_param("name", NULL, (size_t)0, NULL, JP_USER);
+ add_param("dying", NULL, (size_t)0, NULL, JP_USER);
+ add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER);
+#ifdef INET
+ if (ip4_ok)
+ add_param("ip4.addr", NULL, (size_t)0, NULL,
+ JP_USER);
+#endif
+#ifdef INET6
+ if (ip6_ok)
+ add_param("ip6.addr", NULL, (size_t)0, NULL,
+ JP_USER | JP_OPT);
+#endif
+ } else {
+ pflags |= PRINT_DEFAULT;
+ if (pflags & PRINT_JAIL_NAME)
+ add_param("name", NULL, (size_t)0, NULL, JP_USER);
+ else
+ add_param("jid", NULL, (size_t)0, NULL, JP_USER);
+#ifdef INET
+ if (ip4_ok)
+ add_param("ip4.addr", NULL, (size_t)0, NULL,
+ JP_USER);
+#endif
+ add_param("host.hostname", NULL, (size_t)0, NULL,
+ JP_USER);
+ add_param("path", NULL, (size_t)0, NULL, JP_USER);
+ }
+ } else
+ while (optind < argc)
+ add_param(argv[optind++], NULL, (size_t)0, NULL,
+ JP_USER);
+
+ if (pflags & PRINT_SKIP) {
+ /* Check for parameters with jailsys parents. */
+ for (i = 0; i < nparams; i++) {
+ if ((params[i].jp_flags & JP_USER) &&
+ (dot = strchr(params[i].jp_name, '.'))) {
+ *dot = 0;
+ param_parent[i] = add_param(params[i].jp_name,
+ NULL, (size_t)0, NULL, JP_OPT);
+ *dot = '.';
+ }
+ }
+ }
+
+ /* Add the index key parameters. */
+ if (jid != 0)
+ add_param("jid", &jid, sizeof(jid), NULL, 0);
+ else if (jname != NULL)
+ add_param("name", jname, strlen(jname), NULL, 0);
+ else
+ add_param("lastjid", &lastjid, sizeof(lastjid), NULL, 0);
+
+ /* Print a header line if requested. */
+ if (pflags & PRINT_VERBOSE)
+ printf(" JID Hostname Path\n"
+ " Name State\n"
+ " CPUSetID\n"
+ " IP Address(es)\n");
+ else if (pflags & PRINT_DEFAULT)
+ if (pflags & PRINT_JAIL_NAME)
+ printf(" JID IP Address "
+ "Hostname Path\n");
+ else
+ printf(" JID IP Address "
+ "Hostname Path\n");
+ else if (pflags & PRINT_HEADER) {
+ for (i = spc = 0; i < nparams; i++)
+ if (params[i].jp_flags & JP_USER) {
+ if (spc)
+ putchar(' ');
+ else
+ spc = 1;
+ fputs(params[i].jp_name, stdout);
+ }
+ putchar('\n');
+ }
+
+ /* Fetch the jail(s) and print the paramters. */
+ if (jid != 0 || jname != NULL) {
+ if (print_jail(pflags, jflags) < 0)
+ errx(1, "%s", jail_errmsg);
+ } else {
+ for (lastjid = 0;
+ (lastjid = print_jail(pflags, jflags)) >= 0; )
+ ;
+ if (errno != 0 && errno != ENOENT)
+ errx(1, "%s", jail_errmsg);
+ }
+
+ return (0);
+}
+
+static int
+add_param(const char *name, void *value, size_t valuelen,
+ struct jailparam *source, unsigned flags)
+{
+ struct jailparam *param, *tparams;
+ int i, tnparams;
+
+ static int paramlistsize;
+
+ /* The pseudo-parameter "all" scans the list of available parameters. */
+ if (!strcmp(name, "all")) {
+ tnparams = jailparam_all(&tparams);
+ if (tnparams < 0)
+ errx(1, "%s", jail_errmsg);
+ qsort(tparams, (size_t)tnparams, sizeof(struct jailparam),
+ sort_param);
+ for (i = 0; i < tnparams; i++)
+ add_param(tparams[i].jp_name, NULL, (size_t)0,
+ tparams + i, flags);
+ free(tparams);
+ return -1;
+ }
+
+ /* Check for repeat parameters. */
+ for (i = 0; i < nparams; i++)
+ if (!strcmp(name, params[i].jp_name)) {
+ if (value != NULL && jailparam_import_raw(params + i,
+ value, valuelen) < 0)
+ errx(1, "%s", jail_errmsg);
+ params[i].jp_flags |= flags;
+ if (source != NULL)
+ jailparam_free(source, 1);
+ return i;
+ }
+
+ /* Make sure there is room for the new param record. */
+ if (!nparams) {
+ paramlistsize = 32;
+ params = malloc(paramlistsize * sizeof(*params));
+ param_parent = malloc(paramlistsize * sizeof(*param_parent));
+ if (params == NULL || param_parent == NULL)
+ err(1, "malloc");
+ } else if (nparams >= paramlistsize) {
+ paramlistsize *= 2;
+ params = realloc(params, paramlistsize * sizeof(*params));
+ param_parent = realloc(param_parent,
+ paramlistsize * sizeof(*param_parent));
+ if (params == NULL || param_parent == NULL)
+ err(1, "realloc");
+ }
+
+ /* Look up the parameter. */
+ param_parent[nparams] = -1;
+ param = params + nparams++;
+ if (source != NULL) {
+ *param = *source;
+ param->jp_flags |= flags;
+ return param - params;
+ }
+ if (jailparam_init(param, name) < 0)
+ errx(1, "%s", jail_errmsg);
+ param->jp_flags = flags;
+ if ((value != NULL ? jailparam_import_raw(param, value, valuelen)
+ : jailparam_import(param, value)) < 0) {
+ if (flags & JP_OPT) {
+ nparams--;
+ return (-1);
+ }
+ errx(1, "%s", jail_errmsg);
+ }
+ return param - params;
+}
+
+static int
+sort_param(const void *a, const void *b)
+{
+ const struct jailparam *parama, *paramb;
+ char *ap, *bp;
+
+ /* Put top-level parameters first. */
+ parama = a;
+ paramb = b;
+ ap = strchr(parama->jp_name, '.');
+ bp = strchr(paramb->jp_name, '.');
+ if (ap && !bp)
+ return (1);
+ if (bp && !ap)
+ return (-1);
+ return (strcmp(parama->jp_name, paramb->jp_name));
+}
+
+static char *
+noname(const char *name)
+{
+ char *nname, *p;
+
+ nname = malloc(strlen(name) + 3);
+ if (nname == NULL)
+ err(1, "malloc");
+ p = strrchr(name, '.');
+ if (p != NULL)
+ sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1);
+ else
+ sprintf(nname, "no%s", name);
+ return nname;
+}
+
+static char *
+nononame(const char *name)
+{
+ char *nname, *p;
+
+ p = strrchr(name, '.');
+ if (strncmp(p ? p + 1 : name, "no", 2))
+ return NULL;
+ nname = malloc(strlen(name) - 1);
+ if (nname == NULL)
+ err(1, "malloc");
+ if (p != NULL)
+ sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3);
+ else
+ strcpy(nname, name + 2);
+ return nname;
+}
+
+static int
+print_jail(int pflags, int jflags)
+{
+ char *nname;
+ char **param_values;
+ int i, ai, jid, count, n, spc;
+ char ipbuf[INET6_ADDRSTRLEN];
+
+ jid = jailparam_get(params, nparams, jflags);
+ if (jid < 0)
+ return jid;
+ if (pflags & PRINT_VERBOSE) {
+ printf("%6d %-29.29s %.74s\n"
+ "%6s %-29.29s %.74s\n"
+ "%6s %-6d\n",
+ *(int *)params[0].jp_value,
+ (char *)params[1].jp_value,
+ (char *)params[2].jp_value,
+ "",
+ (char *)params[3].jp_value,
+ *(int *)params[4].jp_value ? "DYING" : "ACTIVE",
+ "",
+ *(int *)params[5].jp_value);
+ n = 6;
+#ifdef INET
+ if (ip4_ok && !strcmp(params[n].jp_name, "ip4.addr")) {
+ count = params[n].jp_valuelen / sizeof(struct in_addr);
+ for (ai = 0; ai < count; ai++)
+ if (inet_ntop(AF_INET,
+ &((struct in_addr *)params[n].jp_value)[ai],
+ ipbuf, sizeof(ipbuf)) == NULL)
+ err(1, "inet_ntop");
+ else
+ printf("%6s %-15.15s\n", "", ipbuf);
+ n++;
+ }
+#endif
+#ifdef INET6
+ if (ip6_ok && !strcmp(params[n].jp_name, "ip6.addr")) {
+ count = params[n].jp_valuelen / sizeof(struct in6_addr);
+ for (ai = 0; ai < count; ai++)
+ if (inet_ntop(AF_INET6,
+ &((struct in6_addr *)
+ params[n].jp_value)[ai],
+ ipbuf, sizeof(ipbuf)) == NULL)
+ err(1, "inet_ntop");
+ else
+ printf("%6s %s\n", "", ipbuf);
+ n++;
+ }
+#endif
+ } else if (pflags & PRINT_DEFAULT) {
+ if (pflags & PRINT_JAIL_NAME)
+ printf(" %-15s ", (char *)params[0].jp_value);
+ else
+ printf("%6d ", *(int *)params[0].jp_value);
+ printf("%-15.15s %-29.29s %.74s\n",
+#ifdef INET
+ (!ip4_ok || params[1].jp_valuelen == 0) ? "-"
+ : inet_ntoa(*(struct in_addr *)params[1].jp_value),
+ (char *)params[2-!ip4_ok].jp_value,
+ (char *)params[3-!ip4_ok].jp_value);
+#else
+ "-",
+ (char *)params[1].jp_value,
+ (char *)params[2].jp_value);
+#endif
+ } else {
+ param_values = alloca(nparams * sizeof(*param_values));
+ for (i = 0; i < nparams; i++) {
+ if (!(params[i].jp_flags & JP_USER))
+ continue;
+ param_values[i] = jailparam_export(params + i);
+ if (param_values[i] == NULL)
+ errx(1, "%s", jail_errmsg);
+ }
+ for (i = spc = 0; i < nparams; i++) {
+ if (!(params[i].jp_flags & JP_USER))
+ continue;
+ if ((pflags & PRINT_SKIP) &&
+ ((!(params[i].jp_ctltype &
+ (CTLFLAG_WR | CTLFLAG_TUN))) ||
+ (param_parent[i] >= 0 &&
+ *(int *)params[param_parent[i]].jp_value !=
+ JAIL_SYS_NEW)))
+ continue;
+ if (spc)
+ putchar(' ');
+ else
+ spc = 1;
+ if (pflags & PRINT_NAMEVAL) {
+ /*
+ * Generally "name=value", but for booleans
+ * either "name" or "noname".
+ */
+ if (params[i].jp_flags &
+ (JP_BOOL | JP_NOBOOL)) {
+ if (*(int *)params[i].jp_value)
+ printf("%s", params[i].jp_name);
+ else {
+ nname = (params[i].jp_flags &
+ JP_NOBOOL) ?
+ nononame(params[i].jp_name)
+ : noname(params[i].jp_name);
+ printf("%s", nname);
+ free(nname);
+ }
+ continue;
+ }
+ printf("%s=", params[i].jp_name);
+ }
+ if (params[i].jp_valuelen == 0) {
+ if (pflags & PRINT_QUOTED)
+ printf("\"\"");
+ else if (!(pflags & PRINT_NAMEVAL))
+ putchar('-');
+ } else
+ quoted_print(param_values[i]);
+ }
+ putchar('\n');
+ for (i = 0; i < nparams; i++)
+ if (params[i].jp_flags & JP_USER)
+ free(param_values[i]);
+ }
+ return (jid);
+}
+
+static void
+quoted_print(char *str)
+{
+ int c, qc;
+ char *p = str;
+
+ /* An empty string needs quoting. */
+ if (!*p) {
+ fputs("\"\"", stdout);
+ return;
+ }
+
+ /*
+ * The value will be surrounded by quotes if it contains spaces
+ * or quotes.
+ */
+ qc = strchr(p, '\'') ? '"'
+ : strchr(p, '"') ? '\''
+ : strchr(p, ' ') || strchr(p, '\t') ? '"'
+ : 0;
+ if (qc)
+ putchar(qc);
+ while ((c = *p++)) {
+ if (c == '\\' || c == qc)
+ putchar('\\');
+ putchar(c);
+ }
+ if (qc)
+ putchar(qc);
+}
--- End Message ---