From: Vincent Bernat Date: Wed, 23 Oct 2013 08:01:12 +0000 (+0200) Subject: privsep: put /etc/localtime in chroot X-Git-Tag: 0.7.7~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b6312220edf577198716775a82ff96280b07b545;p=thirdparty%2Flldpd.git privsep: put /etc/localtime in chroot The chroot directory was created by lldpd if missing. We also copy `/etc/localtime` in it if not already present. This allows us to remove duplicate code in many init scripts. Since this file is not essential, we don't make a fuzz for some edge cases. --- diff --git a/NEWS b/NEWS index 92e214b8..fc13d4e3 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ lldpd (0.7.7) + Add support for "team" driver (alternative to bond devices). + Preliminary support for DTrace/systemtap. + Preliminary support for seccomp (for monitor process). + + Setup chroot inside lldpd instead of relying on init script. * Fixes: + Various bugs related to fixed point number handling (for coordinates in LLDP-MED) diff --git a/debian/lldpd.init.d b/debian/lldpd.init.d index a1025dd5..c91a32c0 100644 --- a/debian/lldpd.init.d +++ b/debian/lldpd.init.d @@ -32,19 +32,8 @@ CHROOT=/var/run/$NAME # LSB log_* functions . /lib/lsb/init-functions -do_chroot() -{ - oldumask=$(umask) - umask 022 - [ -d $CHROOT/etc ] || mkdir -p $CHROOT/etc - [ -f $CHROOT/etc/localtime ] || [ ! -f /etc/localtime ] || \ - cp /etc/localtime $CHROOT/etc/localtime - umask $oldumask -} - do_start() { - do_chroot start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ diff --git a/debian/lldpd.upstart b/debian/lldpd.upstart index 19c85288..c41afbad 100644 --- a/debian/lldpd.upstart +++ b/debian/lldpd.upstart @@ -1,3 +1,4 @@ + # lldpd - LLDP daemon # # lldpd is a 802.1AB implementation, a L2 network discovery @@ -11,13 +12,6 @@ stop on runlevel [06] expect stop respawn -pre-start script - CHROOT=/var/run/lldpd - [ -d $CHROOT/etc ] || mkdir -p $CHROOT/etc - [ -f $CHROOT/etc/localtime ] || [ ! -f /etc/localtime ] || \ - cp /etc/localtime $CHROOT/etc/localtime -end script - script . /etc/default/lldpd exec lldpd $DAEMON_ARGS diff --git a/redhat/lldpd.init b/redhat/lldpd.init index e6226767..f75cb213 100644 --- a/redhat/lldpd.init +++ b/redhat/lldpd.init @@ -39,17 +39,6 @@ if status | grep -q -- '-p' 2>/dev/null; then pidopts="-p $pidfile" fi -build_chroot() -{ - oldumask=$(umask) - umask 022 - [ -d $chroot/etc ] || mkdir -p $chroot/etc - [ -f $chroot/etc/localtime ] || [ ! -f /etc/localtime ] || \ - cp /etc/localtime $chroot/etc/localtime - export TZ=/etc/localtime - umask $oldumask -} - start() { [ -x $binary ] || exit 5 echo -n $"Starting $prog: " @@ -57,7 +46,6 @@ start() { RETVAL=1 failure else - build_chroot daemon $daemonopts $binary $LLDPD_OPTIONS RETVAL=$? [ $RETVAL -eq 0 ] && touch $lockfile diff --git a/redhat/lldpd.init.suse b/redhat/lldpd.init.suse index 18be155d..d944786b 100644 --- a/redhat/lldpd.init.suse +++ b/redhat/lldpd.init.suse @@ -34,22 +34,9 @@ test -r $LLDPD_CONFIG || { echo "$LLDPD_CONFIG not existing"; # Reset status of this service rc_reset -chroot=/var/run/lldpd -build_chroot() -{ - oldumask=$(umask) - umask 022 - [ -d $chroot/etc ] || mkdir -p $chroot/etc - [ -f $chroot/etc/localtime ] || [ ! -f /etc/localtime ] || \ - cp /etc/localtime $chroot/etc/localtime - export TZ=/etc/localtime - umask $oldumask -} - case "$1" in start) echo -n "Starting lldpd " - build_chroot /sbin/startproc $LLDPD_BIN rc_status -v ;; diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index b4860be3..fb91fd38 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -1462,7 +1462,7 @@ lldpd_main(int argc, char *argv[], char *envp[]) if (daemon(0, 0) != 0) fatal("main", "failed to detach daemon"); if ((pid = open(LLDPD_PID_FILE, - O_TRUNC | O_CREAT | O_WRONLY, 0644)) == -1) + O_TRUNC | O_CREAT | O_WRONLY, 0666)) == -1) fatal("main", "unable to open pid file " LLDPD_PID_FILE); if (asprintf(&spid, "%d\n", getpid()) == -1) fatal("main", "unable to create pid file " LLDPD_PID_FILE); diff --git a/src/daemon/lldpd.service.in b/src/daemon/lldpd.service.in index 630aa487..9492d88d 100644 --- a/src/daemon/lldpd.service.in +++ b/src/daemon/lldpd.service.in @@ -10,8 +10,6 @@ NotifyAccess=main EnvironmentFile=-/etc/default/lldpd EnvironmentFile=-/etc/sysconfig/lldpd ExecStart=@prefix@/sbin/lldpd $DAEMON_ARGS $LLDPD_OPTIONS -ExecStartPre=/bin/mkdir -p @PRIVSEP_CHROOT@/etc -ExecStartPre=/bin/cp /etc/localtime @PRIVSEP_CHROOT@/etc/localtime Restart=on-failure [Install] diff --git a/src/daemon/priv.c b/src/daemon/priv.c index a4ff6cd8..c8bce823 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -435,6 +435,84 @@ sig_chld(int sig) } /* Initialization */ +#define LOCALTIME "/etc/localtime" +static void +priv_setup_chroot(const char *chrootdir) +{ + /* Create chroot if it does not exist */ + struct stat schroot; + if (stat(chrootdir, &schroot) == -1) { + if (errno != ENOENT) + fatal("privsep", "chroot directory does not exist"); + if (mkdir(chrootdir, 0755) == -1) + fatal("privsep", "unable to create chroot directory"); + log_info("privsep", "created chroot directory %s", + chrootdir); + } + + /* Check if /etc/localtime exists in chroot or outside chroot */ + char path[1024]; + if (snprintf(path, sizeof(path), + "%s" LOCALTIME, chrootdir) >= sizeof(path)) + return; + if (stat(path, &schroot) != -1 || + stat(LOCALTIME, &schroot) == -1) return; + + /* Prepare copy of /etc/localtime */ + path[strlen(chrootdir) + 4] = '\0'; + if (stat(path, &schroot) == -1) { + if (errno != ENOENT) return; + if (mkdir(path, 0755) == -1) { + log_warn("privsep", "unable to create %s directory", + path); + return; + } + } + path[strlen(chrootdir) + 4] = '/'; + + /* Do copy */ + int source = -1, destination = -1; + char buffer[1024]; + ssize_t n; + if ((source = open(LOCALTIME, O_RDONLY)) == -1) { + log_warn("privsep", "cannot read " LOCALTIME); + return; + } + mode_t old = umask(S_IWGRP | S_IWOTH); + if ((destination = open(path, + O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { + log_warn("privsep", "cannot create %s", path); + close(source); + umask(old); + return; + } + umask(old); + while ((n = read(source, buffer, sizeof(buffer))) > 0) { + ssize_t nw, left = n; + char *p = buffer; + while (left > 0) { + if ((nw = write(destination, p, left)) == -1) { + if (errno == EINTR) continue; + log_warn("privsep", "cannot write to %s", path); + close(source); + close(destination); + unlink(path); + return; + } + left -= nw; + p += nw; + } + } + if (n == -1) { + log_warn("privsep", "cannot read " LOCALTIME); + unlink(path); + } else { + log_info("privsep", LOCALTIME " copied to chroot"); + } + close(source); + close(destination); +} + void priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid) { @@ -456,15 +534,7 @@ priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid) if (RUNNING_ON_VALGRIND) log_warnx("privsep", "running on valgrind, keep privileges"); else { - struct stat schroot; - if (stat(chrootdir, &schroot) == -1) { - if (errno != ENOENT) - fatal("privsep", "chroot directory does not exist"); - if (mkdir(chrootdir, 0755) == -1) - fatal("privsep", "unable to create chroot directory"); - log_info("privsep", "created chroot directory %s", - chrootdir); - } + priv_setup_chroot(chrootdir); if (chroot(chrootdir) == -1) fatal("privsep", "unable to chroot"); if (chdir("/") != 0)