]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
privsep: put /etc/localtime in chroot
authorVincent Bernat <bernat@luffy.cx>
Wed, 23 Oct 2013 08:01:12 +0000 (10:01 +0200)
committerVincent Bernat <bernat@luffy.cx>
Wed, 23 Oct 2013 08:02:22 +0000 (10:02 +0200)
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.

NEWS
debian/lldpd.init.d
debian/lldpd.upstart
redhat/lldpd.init
redhat/lldpd.init.suse
src/daemon/lldpd.c
src/daemon/lldpd.service.in
src/daemon/priv.c

diff --git a/NEWS b/NEWS
index 92e214b80775ce29ed2af98f6d7e25ca1fd52271..fc13d4e309eedfe3ad6392c7a9732500d850e4af 100644 (file)
--- 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)
index a1025dd5a855bb1cb15598e7f35a3590b9bb5c98..c91a32c052a5f36aac26b14d49b1f726f8f106b0 100644 (file)
@@ -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 -- \
index 19c852882c6e6dc73ac7c462b46adaef0cc922d5..c41afbad4d6d0e54deca6639cd0fc9839f242c0f 100644 (file)
@@ -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
index e62267671c122a19ba9e29cb92daab21199be851..f75cb213bb61363a54fb5ee52ff77c78dc8e3936 100644 (file)
@@ -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
index 18be155dc8848e7bee15e48531ac07bde6c5a7fe..d944786b25a520722d965790883152d03c8f1d13 100644 (file)
@@ -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
        ;;
index b4860be33bf4789413733bfe7fa6b94088eebb9c..fb91fd38f1fbf51c1073705d0b726c648ed45503 100644 (file)
@@ -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);
index 630aa48725368d4fb5a1a48263f6518c3cf5dbdd..9492d88da38968334fd4e11803028889e06811bc 100644 (file)
@@ -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]
index a4ff6cd80a5ad143a4dda4e98b82a6cfc48f3bf9..c8bce8236862d156f25f08551009d2ce199c7595 100644 (file)
@@ -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)