aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2018-08-06 16:22:01 +0000
committerMark Johnston <markj@FreeBSD.org>2018-08-06 16:22:01 +0000
commit976e100378844d5668810067ed07748f151c5ea2 (patch)
tree66c644fc86089cc600fbe06d58a7fae9efdb2f53
parent7db2360401dc8e8ff7f44efc8218bb82015f6f89 (diff)
downloadsrc-976e100378844d5668810067ed07748f151c5ea2.tar.gz
src-976e100378844d5668810067ed07748f151c5ea2.zip
dhclient: Don't chroot if we are in capability mode.
The main dhclient process is Capsicumized but also chroots to restrict filesystem access. With r322369, pidfile(3) maintains a directory descriptor for the pidfile, which can cause the chroot to fail in certain cases. To minimize the problem, only chroot if we fail to enter capability mode, and store dhclient pidfiles in a subdirectory of /var/run, thus restricting access via pidfile(3)'s directory descriptor. PR: 223327 Reviewed by: cem, oshogbo Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D16584
Notes
Notes: svn path=/head/; revision=337382
-rw-r--r--etc/mtree/BSD.var.dist2
-rw-r--r--sbin/dhclient/dhclient.817
-rw-r--r--sbin/dhclient/dhclient.c28
-rwxr-xr-xsbin/init/rc.d/dhclient2
4 files changed, 34 insertions, 15 deletions
diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist
index fc6021aad9ac..1fb95df460d6 100644
--- a/etc/mtree/BSD.var.dist
+++ b/etc/mtree/BSD.var.dist
@@ -74,6 +74,8 @@
preserve
..
run
+ dhclient
+ ..
ppp gname=network mode=0770
..
wpa_supplicant
diff --git a/sbin/dhclient/dhclient.8 b/sbin/dhclient/dhclient.8
index c6940da89632..3ea35e8eb472 100644
--- a/sbin/dhclient/dhclient.8
+++ b/sbin/dhclient/dhclient.8
@@ -38,7 +38,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 13, 2011
+.Dd August 4, 2018
.Dt DHCLIENT 8
.Os
.Sh NAME
@@ -87,7 +87,7 @@ for the leases file.
.It Fl p Ar file
Specify an alternate location for the PID file.
The default is
-.Pa /var/run/dhclient. Ns Ar interface Ns Pa .pid .
+.Pa /var/run/dhclient/dhclient. Ns Ar interface Ns Pa .pid .
.It Fl q
Forces
.Nm
@@ -194,3 +194,16 @@ and
.Pp
The current implementation was reworked by
.An Henning Brauer Aq Mt henning@openbsd.org .
+.Sh BUGS
+The
+.Nm
+utility uses
+.Xr capsicum 4
+to sandbox the main process.
+If the requisite kernel support is not available, the main process will
+attempt to run in a
+.Xr chroot 2
+sandbox instead.
+This will fail if the process is jailed or the
+.Va kern.chroot_allow_open_directories
+sysctl is set to 0.
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index f28558d164f0..34c748735f55 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -371,6 +371,7 @@ init_casper(void)
int
main(int argc, char *argv[])
{
+ u_int capmode;
int ch, fd, quiet = 0, i = 0;
int pipe_fd[2];
int immediate_daemon = 0;
@@ -419,7 +420,7 @@ main(int argc, char *argv[])
if (path_dhclient_pidfile == NULL) {
asprintf(&path_dhclient_pidfile,
- "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
+ "%s/dhclient/dhclient.%s.pid", _PATH_VARRUN, *argv);
if (path_dhclient_pidfile == NULL)
error("asprintf");
}
@@ -528,11 +529,6 @@ main(int argc, char *argv[])
if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
error("can't limit route socket: %m");
- if (chroot(_PATH_VAREMPTY) == -1)
- error("chroot");
- if (chdir("/") == -1)
- error("chdir(\"/\")");
-
if (setgroups(1, &pw->pw_gid) ||
setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
seteuid(pw->pw_uid) || setuid(pw->pw_uid))
@@ -545,6 +541,19 @@ main(int argc, char *argv[])
if (caph_enter_casper() < 0)
error("can't enter capability mode: %m");
+ /*
+ * If we are not in capability mode (i.e., because Capsicum or
+ * libcasper is disabled), try to restrict filesystem access. This
+ * will fail if kern.chroot_allow_open_directories is 0 or the process
+ * is jailed.
+ */
+ if (cap_getmode(&capmode) < 0 || capmode == 0) {
+ if (chroot(_PATH_VAREMPTY) == -1)
+ error("chroot");
+ if (chdir("/") == -1)
+ error("chdir(\"/\")");
+ }
+
if (immediate_daemon)
go_daemon();
@@ -2449,13 +2458,8 @@ go_daemon(void)
cap_rights_init(&rights);
- if (pidfile != NULL) {
+ if (pidfile != NULL)
pidfile_write(pidfile);
- if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
- errno != ENOSYS) {
- error("can't limit pidfile descriptor: %m");
- }
- }
if (nullfd != -1) {
close(nullfd);
diff --git a/sbin/init/rc.d/dhclient b/sbin/init/rc.d/dhclient
index eb9860ea4cc0..520a0850ccbc 100755
--- a/sbin/init/rc.d/dhclient
+++ b/sbin/init/rc.d/dhclient
@@ -14,7 +14,7 @@ ifn="$2"
name="dhclient"
desc="Dynamic Host Configuration Protocol (DHCP) client"
rcvar=
-pidfile="/var/run/${name}.${ifn}.pid"
+pidfile="/var/run/dhclient/${name}.${ifn}.pid"
start_precmd="dhclient_prestart"
stop_precmd="dhclient_pre_check"