From 2e91d1a1a0f90d17b14b8ee22fe9d4d596684635 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Fri, 11 May 2012 07:53:39 +0200 Subject: [PATCH] lldpd: listen on Unix socket before forking This way, lldpd Unix socket is ready to operate when lldpd detaches itself from the terminal. This mean that lldpctl can be used right away. This change also removes the need to create this socket using privilege separation operations. --- src/lldpd.c | 39 +++++++++++++++++++++++++++++++----- src/lldpd.h | 3 +-- src/priv.c | 57 +++-------------------------------------------------- 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/src/lldpd.c b/src/lldpd.c index 52e04574..8595b453 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include static void usage(void); @@ -1037,6 +1039,13 @@ lldpd_main(int argc, char *argv[]) char *lsb_release = NULL; int smart = 15; int receiveonly = 0; + int ctl; + + /* Non privileged user */ + struct passwd *user; + struct group *group; + uid_t uid; + gid_t gid; saved_argv = argv; @@ -1141,6 +1150,29 @@ lldpd_main(int argc, char *argv[]) log_init(debug, __progname); tzset(); /* Get timezone info before chroot */ + /* Grab uid and gid to use for priv sep */ + if ((user = getpwnam(PRIVSEP_USER)) == NULL) + fatal("no " PRIVSEP_USER " user for privilege separation"); + uid = user->pw_uid; + if ((group = getgrnam(PRIVSEP_GROUP)) == NULL) + fatal("no " PRIVSEP_GROUP " group for privilege separation"); + gid = group->gr_gid; + + /* Create and setup socket */ + if ((ctl = ctl_create(LLDPD_CTL_SOCKET)) == -1) { + LLOG_WARN ("unable to create control socket"); + LLOG_WARNX("If another instance is running, please stop it."); + LLOG_WARNX("Otherwise, remove " LLDPD_CTL_SOCKET); + fatalx("Giving up"); + } + if (chown(LLDPD_CTL_SOCKET, uid, gid) == -1) + LLOG_WARN("unable to chown control socket"); + if (chmod(LLDPD_CTL_SOCKET, + S_IRUSR | S_IWUSR | S_IXUSR | + S_IRGRP | S_IWGRP | S_IXGRP) == -1) + LLOG_WARN("unable to chmod control socket"); + + /* Detach if needed */ if (!debug) { int pid; char *spid; @@ -1164,13 +1196,14 @@ lldpd_main(int argc, char *argv[]) lsb_release = lldpd_get_lsb_release(); } - priv_init(PRIVSEP_CHROOT); + priv_init(PRIVSEP_CHROOT, ctl, uid, gid); /* Initialization of global configuration */ if ((cfg = (struct lldpd *) calloc(1, sizeof(struct lldpd))) == NULL) fatal(NULL); + cfg->g_ctl = ctl; cfg->g_mgmt_pattern = mgmtp; cfg->g_cid_pattern = cidp; cfg->g_interfaces = interfaces; @@ -1234,10 +1267,6 @@ lldpd_main(int argc, char *argv[]) TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries); lchassis->c_refcount++; /* We should always keep a reference to local chassis */ - /* Create socket */ - if ((cfg->g_ctl = priv_ctl_create()) == -1) - fatalx("unable to create control socket " LLDPD_CTL_SOCKET); - /* Main loop */ levent_loop(cfg); lldpd_exit(cfg); diff --git a/src/lldpd.h b/src/lldpd.h index cec7b85a..431001b8 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -608,8 +608,7 @@ int client_handle_client(struct lldpd *, int, enum hmsg_type, void *, int); /* priv.c */ -void priv_init(char*); -int priv_ctl_create(void); +void priv_init(char*, int, uid_t, gid_t); void priv_ctl_cleanup(void); char *priv_gethostbyname(void); int priv_open(char*); diff --git a/src/priv.c b/src/priv.c index 9e57532f..6466f0b6 100644 --- a/src/priv.c +++ b/src/priv.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -55,7 +54,6 @@ enum { PRIV_PING, - PRIV_CREATE_CTL_SOCKET, PRIV_DELETE_CTL_SOCKET, PRIV_GET_HOSTNAME, PRIV_OPEN, @@ -73,10 +71,6 @@ static int remote; /* Other side */ static int monitored = -1; /* Child */ static int sock = -1; -/* UID/GID of unprivileged user */ -static gid_t gid = 0; -static uid_t uid = 0; - /* Proxies */ static void @@ -89,20 +83,6 @@ priv_ping() LLOG_DEBUG("monitor ready"); } -/* Proxy for ctl_create, no argument since this is the monitor that decides the - * location of the socket */ -int -priv_ctl_create() -{ - int cmd, rc; - cmd = PRIV_CREATE_CTL_SOCKET; - must_write(remote, &cmd, sizeof(int)); - must_read(remote, &rc, sizeof(int)); - if (rc == -1) - return -1; - return receive_fd(remote); -} - /* Proxy for ctl_cleanup */ void priv_ctl_cleanup() @@ -206,28 +186,6 @@ asroot_ping() must_write(remote, &rc, sizeof(int)); } -static void -asroot_ctl_create() -{ - int rc; - if ((rc = ctl_create(LLDPD_CTL_SOCKET)) == -1) { - LLOG_WARN("[priv]: unable to create control socket"); - LLOG_WARNX("[priv]: If another instance is running, please stop it."); - LLOG_WARNX("[priv]: Otherwise, remove " LLDPD_CTL_SOCKET); - must_write(remote, &rc, sizeof(int)); - return; - } - if (chown(LLDPD_CTL_SOCKET, uid, gid) == -1) - LLOG_WARN("[priv]: unable to chown control socket"); - if (chmod(LLDPD_CTL_SOCKET, - S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IWGRP | S_IXGRP) == -1) - LLOG_WARN("[priv]: unable to chmod control socket"); - must_write(remote, &rc, sizeof(int)); - send_fd(remote, rc); - close(rc); -} - static void asroot_ctl_cleanup() { @@ -440,7 +398,6 @@ struct dispatch_actions { static struct dispatch_actions actions[] = { {PRIV_PING, asroot_ping}, - {PRIV_CREATE_CTL_SOCKET, asroot_ctl_create}, {PRIV_DELETE_CTL_SOCKET, asroot_ctl_cleanup}, {PRIV_GET_HOSTNAME, asroot_gethostbyname}, {PRIV_OPEN, asroot_open}, @@ -505,11 +462,10 @@ sig_chld(int sig) /* Initialization */ void -priv_init(char *chrootdir) +priv_init(char *chrootdir, int ctl, uid_t uid, gid_t gid) { + int pair[2]; - struct passwd *user; - struct group *group; gid_t gidset[1]; int status; @@ -517,14 +473,6 @@ priv_init(char *chrootdir) if (socketpair(AF_LOCAL, SOCK_DGRAM, PF_UNSPEC, pair) < 0) fatal("[priv]: unable to create socket pair for privilege separation"); - /* Get users */ - if ((user = getpwnam(PRIVSEP_USER)) == NULL) - fatal("[priv]: no " PRIVSEP_USER " user for privilege separation"); - uid = user->pw_uid; - if ((group = getgrnam(PRIVSEP_GROUP)) == NULL) - fatal("[priv]: no " PRIVSEP_GROUP " group for privilege separation"); - gid = group->gr_gid; - /* Spawn off monitor */ if ((monitored = fork()) < 0) fatal("[priv]: unable to fork monitor"); @@ -552,6 +500,7 @@ priv_init(char *chrootdir) break; default: /* We are in the monitor */ + if (ctl != -1) close(ctl); remote = pair[1]; close(pair[0]); if (atexit(priv_exit) != 0) -- 2.39.5