From 45bf0bd0627d9f5ab9d2dda56f4946bc507b26b3 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sun, 15 Dec 2013 13:07:19 +0100 Subject: [PATCH] lldpd: use vfork+exec instead of fork+exec This will help compatibility with systems not having a working `fork()` implementation. For those who do, we will still use `fork()`. --- configure.ac | 1 + src/daemon/lldpd.c | 41 ++++++++++++++++++++--------------------- src/daemon/lldpd.h | 7 +++++++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index 553a17c3..dcaaaa60 100644 --- a/configure.ac +++ b/configure.ac @@ -101,6 +101,7 @@ lldp_CHECK_ALIGNOF AC_CONFIG_LIBOBJ_DIR([src/compat]) AC_FUNC_MALLOC AC_FUNC_REALLOC +AC_FUNC_FORK AC_SEARCH_LIBS([setproctitle], [util bsd]) AC_REPLACE_FUNCS([setproctitle]) AC_CHECK_FUNCS([setproctitle_init]) diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index eff4455c..f3cc7fe1 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -645,11 +645,11 @@ lldpd_get_lsb_release() { return NULL; } - if ((pid = fork()) < 0) { + pid = vfork(); + switch (pid) { + case -1: log_warn("localchassis", "unable to fork"); return NULL; - } - switch (pid) { case 0: /* Child, exec lsb_release */ close(pipefd[0]); @@ -661,7 +661,7 @@ lldpd_get_lsb_release() { if (pipefd[1] > 2) close(pipefd[1]); execvp("lsb_release", command); } - exit(127); + _exit(127); break; default: /* Father, read the output from the children */ @@ -1108,9 +1108,15 @@ lldpd_exit(struct lldpd *cfg) static pid_t lldpd_configure(int debug, const char *path, const char *ctlname) { - pid_t lldpcli = fork(); + pid_t lldpcli = vfork(); int devnull; + char sdebug[debug + 3]; + memset(sdebug, 'd', debug + 3); + sdebug[debug + 2] = '\0'; + sdebug[0] = '-'; sdebug[1] = 's'; + log_debug("main", "invoke %s %s", path, sdebug); + switch (lldpcli) { case -1: log_warn("main", "unable to fork"); @@ -1118,27 +1124,20 @@ lldpd_configure(int debug, const char *path, const char *ctlname) case 0: /* Child, exec lldpcli */ if ((devnull = open("/dev/null", O_RDWR, 0)) != -1) { - char sdebug[debug + 3]; - memset(sdebug, 'd', debug + 3); - sdebug[debug + 2] = '\0'; - sdebug[0] = '-'; sdebug[1] = 's'; - dup2(devnull, STDIN_FILENO); dup2(devnull, STDOUT_FILENO); if (devnull > 2) close(devnull); - log_debug("main", "invoke %s %s", path, sdebug); - if (execl(path, "lldpcli", sdebug, - "-u", ctlname, - "-c", SYSCONFDIR "/lldpd.conf", - "-c", SYSCONFDIR "/lldpd.d", - "resume", - NULL) == -1) { - log_warn("main", "unable to execute %s", path); - log_warnx("main", "configuration is incomplete, lldpd needs to be unpaused"); - } + execl(path, "lldpcli", sdebug, + "-u", ctlname, + "-c", SYSCONFDIR "/lldpd.conf", + "-c", SYSCONFDIR "/lldpd.d", + "resume", + NULL); + log_warn("main", "unable to execute %s", path); + log_warnx("main", "configuration is incomplete, lldpd needs to be unpaused"); } - exit(127); + _exit(127); break; default: /* Father, don't do anything stupid */ diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 56835763..38bb0fbf 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -38,6 +38,13 @@ #include #include +#if HAVE_VFORK_H +# include +#endif +#if HAVE_WORKING_FORK +# define vfork fork +#endif + #include "lldp-tlv.h" #if defined (ENABLE_CDP) || defined (ENABLE_FDP) # include "cdp.h" -- 2.39.5