summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2010-06-29 03:52:12 +0000
committerimp <imp@FreeBSD.org>2010-06-29 03:52:12 +0000
commit93e0327a90dc02fd0242bd342897292a8f275f4f (patch)
tree1ae9808d688d1218eacfccedbe478811b98dcb84 /sbin
parentebed8715b65d342ce6fcff454c3ed50e4d4cd44d (diff)
downloadFreeBSD-src-93e0327a90dc02fd0242bd342897292a8f275f4f.zip
FreeBSD-src-93e0327a90dc02fd0242bd342897292a8f275f4f.tar.gz
Expand system into my_system, and add the necessary tidyness that we
need. Close the pidfile. Then close all descriptors >= 3 to avoid information leakage to children. This solves the problem of not being able to restart devd when you have, for example, a dhclient forked to configure your network... MFC after: 3 days
Diffstat (limited to 'sbin')
-rw-r--r--sbin/devd/devd.cc96
-rw-r--r--sbin/devd/devd.hh1
2 files changed, 95 insertions, 2 deletions
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index c3f3ea9..c7fa437 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2002-2003 M. Warner Losh.
+ * Copyright (c) 2002-2010 M. Warner Losh.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,6 +22,35 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * my_system is a variation on lib/libc/stdlib/system.c:
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
/*
@@ -41,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/un.h>
#include <ctype.h>
@@ -49,6 +79,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <fcntl.h>
#include <libutil.h>
+#include <paths.h>
#include <regex.h>
#include <signal.h>
#include <stdlib.h>
@@ -152,13 +183,67 @@ action::~action()
// nothing
}
+static int
+my_system(const char *command)
+{
+ pid_t pid, savedpid;
+ int pstat;
+ struct sigaction ign, intact, quitact;
+ sigset_t newsigblock, oldsigblock;
+
+ if (!command) /* just checking... */
+ return(1);
+
+ /*
+ * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save
+ * existing signal dispositions.
+ */
+ ign.sa_handler = SIG_IGN;
+ ::sigemptyset(&ign.sa_mask);
+ ign.sa_flags = 0;
+ ::sigaction(SIGINT, &ign, &intact);
+ ::sigaction(SIGQUIT, &ign, &quitact);
+ ::sigemptyset(&newsigblock);
+ ::sigaddset(&newsigblock, SIGCHLD);
+ ::sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
+ switch (pid = ::fork()) {
+ case -1: /* error */
+ break;
+ case 0: /* child */
+ /*
+ * Restore original signal dispositions and exec the command.
+ */
+ ::sigaction(SIGINT, &intact, NULL);
+ ::sigaction(SIGQUIT, &quitact, NULL);
+ ::sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ /*
+ * Close the PID file, and all other open descriptors.
+ * Inherit std{in,out,err} only.
+ */
+ cfg.close_pidfile();
+ ::closefrom(3);
+ ::execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
+ ::_exit(127);
+ default: /* parent */
+ savedpid = pid;
+ do {
+ pid = ::wait4(savedpid, &pstat, 0, (struct rusage *)0);
+ } while (pid == -1 && errno == EINTR);
+ break;
+ }
+ ::sigaction(SIGINT, &intact, NULL);
+ ::sigaction(SIGQUIT, &quitact, NULL);
+ ::sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ return (pid == -1 ? -1 : pstat);
+}
+
bool
action::do_action(config &c)
{
string s = c.expand_string(_cmd);
if (Dflag)
fprintf(stderr, "Executing '%s'\n", s.c_str());
- ::system(s.c_str());
+ my_system(s.c_str());
return (true);
}
@@ -391,6 +476,13 @@ config::write_pidfile()
}
void
+config::close_pidfile()
+{
+
+ pidfile_close(pfh);
+}
+
+void
config::remove_pidfile()
{
diff --git a/sbin/devd/devd.hh b/sbin/devd/devd.hh
index 32d98a2..b3c98f3 100644
--- a/sbin/devd/devd.hh
+++ b/sbin/devd/devd.hh
@@ -153,6 +153,7 @@ public:
void set_pidfile(const char *);
void reset();
void parse();
+ void close_pidfile();
void open_pidfile();
void write_pidfile();
void remove_pidfile();
OpenPOWER on IntegriCloud