From 93e0327a90dc02fd0242bd342897292a8f275f4f Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 29 Jun 2010 03:52:12 +0000 Subject: 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 --- sbin/devd/devd.cc | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- sbin/devd/devd.hh | 1 + 2 files changed, 95 insertions(+), 2 deletions(-) (limited to 'sbin') 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 #include #include +#include #include #include @@ -49,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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(); -- cgit v1.1