[radvd/f16] Store PID before daemonizing

Petr Pisar ppisar at fedoraproject.org
Thu Apr 12 16:05:56 UTC 2012


commit 6608753dbad55119e811634b22188ff4cff36031
Author: Petr Písař <ppisar at redhat.com>
Date:   Thu Apr 12 15:58:28 2012 +0200

    Store PID before daemonizing

 radvd-1.8.2-Use-libdaemon-for-daemonization.patch |  239 +++++++++++++++++++++
 radvd.spec                                        |   14 ++-
 2 files changed, 252 insertions(+), 1 deletions(-)
---
diff --git a/radvd-1.8.2-Use-libdaemon-for-daemonization.patch b/radvd-1.8.2-Use-libdaemon-for-daemonization.patch
new file mode 100644
index 0000000..adf6479
--- /dev/null
+++ b/radvd-1.8.2-Use-libdaemon-for-daemonization.patch
@@ -0,0 +1,239 @@
+From 4c617f33c6e0b672c4e215af649b967873f799e9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar at redhat.com>
+Date: Thu, 5 Apr 2012 15:24:22 +0200
+Subject: [PATCH] Use libdaemon for daemonization
+
+The libc daemon(3) function suffers from race bewtween exiting parent
+and saving PID into a file.
+
+Using libdaemon library one can avoid this race and can simplify PID
+file manipulation.
+
+The only difference against older implementation is, the PID file will
+be inspected, created, and removed only if daemonization is requested.
+---
+ Makefile.am  |    6 +++-
+ README       |    2 +
+ configure.in |    2 +
+ radvd.c      |   95 ++++++++++++++++++++++++++++++----------------------------
+ 4 files changed, 58 insertions(+), 47 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index cc84f9f..c0f6d82 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -61,8 +61,12 @@ EXTRA_radvd_SOURCES = \
+ 	privsep-bsd44.c \
+ 	privsep-linux.c
+ 
++radvd_CPPFLAGS = \
++	@DAEMON_CFLAGS@
++
+ radvd_LDADD = \
+-	@CONDITIONAL_SOURCES@
++	@CONDITIONAL_SOURCES@ \
++	@DAEMON_LIBS@
+ 
+ radvd_DEPENDENCIES = \
+ 	@CONDITIONAL_SOURCES@
+diff --git a/README b/README
+index 0867576..21a49a6 100644
+--- a/README
++++ b/README
+@@ -3,6 +3,8 @@ $Id: README,v 1.9 2005/12/31 16:10:05 psavola Exp $
+ Installation:
+ =============
+ 
++Install 'pkg-config' and 'libdaemon'.
++
+ Run configure, e.g.
+ 
+ ./configure --prefix=/usr/local --sysconfdir=/etc --mandir=/usr/share/man
+diff --git a/configure.in b/configure.in
+index 1ed2280..cd00a09 100644
+--- a/configure.in
++++ b/configure.in
+@@ -139,6 +139,8 @@ AC_CHECK_LIB(c, inet_ntop,,
+ # prevent caching
+ unset ac_cv_lib_inet6_inet_ntop
+ 
++PKG_CHECK_MODULES([DAEMON], libdaemon)
++
+ dnl Checks for header files.
+ AC_HEADER_STDC
+ AC_CHECK_HEADERS( \
+diff --git a/radvd.c b/radvd.c
+index 73746d7..7135125 100644
+--- a/radvd.c
++++ b/radvd.c
+@@ -24,6 +24,8 @@
+ #endif
+ 
+ #include <poll.h>
++#include <libdaemon/dfork.h>
++#include <libdaemon/dpid.h>
+ 
+ struct Interface *IfaceList = NULL;
+ 
+@@ -72,6 +74,7 @@ char usage_str[] =
+ extern FILE *yyin;
+ 
+ char *conf_file = NULL;
++char *pidfile = NULL;
+ char *pname;
+ int sock = -1;
+ 
+@@ -93,16 +96,15 @@ void usage(void);
+ int drop_root_privileges(const char *);
+ int readin_config(char *);
+ int check_conffile_perm(const char *, const char *);
++const char *get_pidfile(void);
+ void main_loop(void);
+ 
+ int
+ main(int argc, char *argv[])
+ {
+-	char pidstr[16];
+-	ssize_t ret;
+ 	int c, log_method;
+-	char *logfile, *pidfile;
+-	int facility, fd;
++	char *logfile;
++	int facility;
+ 	char *username = NULL;
+ 	char *chrootdir = NULL;
+ 	int configtest = 0;
+@@ -110,6 +112,7 @@ main(int argc, char *argv[])
+ #ifdef HAVE_GETOPT_LONG
+ 	int opt_idx;
+ #endif
++	pid_t pid;
+ 
+ 	pname = ((pname=strrchr(argv[0],'/')) != NULL)?pname+1:argv[0];
+ 
+@@ -282,32 +285,6 @@ main(int argc, char *argv[])
+ 		}
+ 	}
+ 
+-	if ((fd = open(pidfile, O_RDONLY, 0)) > 0)
+-	{
+-		ret = read(fd, pidstr, sizeof(pidstr) - 1);
+-		if (ret < 0)
+-		{
+-			flog(LOG_ERR, "cannot read radvd pid file, terminating: %s", strerror(errno));
+-			exit(1);
+-		}
+-		pidstr[ret] = '\0';
+-		if (!kill((pid_t)atol(pidstr), 0))
+-		{
+-			flog(LOG_ERR, "radvd already running, terminating.");
+-			exit(1);
+-		}
+-		close(fd);
+-		fd = open(pidfile, O_CREAT|O_TRUNC|O_WRONLY, 0644);
+-	}
+-	else	/* FIXME: not atomic if pidfile is on an NFS mounted volume */
+-		fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644);
+-
+-	if (fd < 0)
+-	{
+-		flog(LOG_ERR, "cannot create radvd pid file, terminating: %s", strerror(errno));
+-		exit(1);
+-	}
+-
+ 	/*
+ 	 * okay, config file is read in, socket and stuff is setup, so
+ 	 * lets fork now...
+@@ -315,9 +292,37 @@ main(int argc, char *argv[])
+ 
+ 	if (get_debuglevel() == 0) {
+ 
+-		/* Detach from controlling terminal */
+-		if (daemon(0, 0) < 0)
+-			perror("daemon");
++		if (daemon_retval_init()) {
++			flog(LOG_ERR, "Could not initialize daemon IPC.");
++			exit(1);
++		}
++
++		pid = daemon_fork();
++		if (-1 == pid) {
++			flog(LOG_ERR, "Could not fork: %s", strerror(errno));
++			daemon_retval_done();
++			exit(1);
++ 		}
++		if (0 < pid) {
++			if (daemon_retval_wait(0)) {
++				flog(LOG_ERR, "Could not daemonize.");
++				exit(1);
++			}
++			exit(0);
++		}
++
++		daemon_pid_file_proc = get_pidfile;
++		if (daemon_pid_file_is_running() >= 0) {
++			flog(LOG_ERR, "radvd already running, terminating.");
++			daemon_retval_send(1);
++			exit(1);
++		}
++		if (daemon_pid_file_create()) {
++			flog(LOG_ERR, "Cannot create radvd PID file, terminating: %s",
++					strerror(errno));
++			daemon_retval_send(2);
++			exit(1);
++		}
+ 
+ 		/* close old logfiles, including stderr */
+ 		log_close();
+@@ -326,10 +331,12 @@ main(int argc, char *argv[])
+ 		if (log_method == L_STDERR_SYSLOG)
+ 			log_method = L_SYSLOG;
+ 		if (log_open(log_method, pname, logfile, facility) < 0) {
+-			perror("log_open");
++			flog(LOG_ERR, "log_open() failed: %s", strerror(errno));
++			daemon_retval_send(3);
+ 			exit(1);
+ 		}
+ 
++		daemon_retval_send(0);
+ 	}
+ 
+ 	/*
+@@ -340,26 +347,22 @@ main(int argc, char *argv[])
+ 	signal(SIGINT, sigint_handler);
+ 	signal(SIGUSR1, sigusr1_handler);
+ 
+-	snprintf(pidstr, sizeof(pidstr), "%ld\n", (long)getpid());
+-
+-	ret = write(fd, pidstr, strlen(pidstr));
+-	if (ret != strlen(pidstr))
+-	{
+-		flog(LOG_ERR, "cannot write radvd pid file, terminating: %s", strerror(errno));
+-		exit(1);
+-	}
+-
+-	close(fd);
+-
+ 	config_interface();
+ 	kickoff_adverts();
+ 	main_loop();
+ 	stop_adverts();
+-	unlink(pidfile);
++	if (get_debuglevel() == 0) {
++		flog(LOG_INFO, "removing %s", pidfile);
++		unlink(pidfile);
++	}
+ 
+ 	return 0;
+ }
+ 
++const char *get_pidfile(void) {
++	return pidfile;
++}
++
+ void main_loop(void)
+ {
+ 	struct pollfd fds[2];
+-- 
+1.7.7.6
+
diff --git a/radvd.spec b/radvd.spec
index 9b33798..f8be95c 100644
--- a/radvd.spec
+++ b/radvd.spec
@@ -4,7 +4,7 @@
 Summary:    A Router Advertisement daemon
 Name:       radvd
 Version:    1.8.2
-Release:    2%{?dist}
+Release:    3%{?dist}
 # The code includes the advertising clause, so it's GPL-incompatible
 License:    BSD with advertising
 Group:      System Environment/Daemons
@@ -17,10 +17,17 @@ Requires(postun):   chkconfig, /usr/sbin/userdel, initscripts
 Requires(preun):    chkconfig, initscripts
 Requires(post):     chkconfig
 Requires(pre):      /usr/sbin/useradd
+# autoconf needed for Use-libdaemon-for-daemonization patch
+BuildRequires:      autoconf
+BuildRequires:      automake
 BuildRequires:      flex, flex-static, byacc
+BuildRequires:      libdaemon-devel
+BuildRequires:      pkgconfig
 BuildRoot:          %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 Patch1: radvd-1.8.2-iface.patch
+# Bug #811997, fixed in upstream after 1.8.5
+Patch2: radvd-1.8.2-Use-libdaemon-for-daemonization.patch
 
 %description
 radvd is the router advertisement daemon for IPv6.  It listens to router
@@ -37,6 +44,8 @@ services.
 %setup -q
 
 %patch1 -p1 -b .iface
+%patch2 -p1 -b .libdaemon
+autoreconf -is
 
 %build
 export CFLAGS="$RPM_OPT_FLAGS -D_GNU_SOURCE -fPIE" 
@@ -113,6 +122,9 @@ exit 0
 %{_sbindir}/radvdump
 
 %changelog
+* Thu Apr 12 2012 Petr Pisar <ppisar at redhat.com> - 1.8.2-3
+- Store PID before daemonizing (bug #811997)
+
 * Mon Oct 10 2011 Jiri Skala <jskala at redhat.com> - 1.8.2-2
 - fixes CVE-2011-3602
 


More information about the scm-commits mailing list