aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debianutils/start_stop_daemon.c85
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/vfork_daemon_rexec.c4
3 files changed, 52 insertions, 39 deletions
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 1933e1cfc..d8a0d7d46 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -8,6 +8,9 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
+/* NB: we have a problem here with /proc/NN/exe usage, similar to
+ * one fixed in killall/pidof */
+
#include <getopt.h>
#include <sys/resource.h>
@@ -28,33 +31,22 @@ struct pid_list {
static struct pid_list *found;
-static inline void push(pid_t pid)
-{
- struct pid_list *p;
-
- p = xmalloc(sizeof(*p));
- p->next = found;
- p->pid = pid;
- found = p;
-}
-
static int pid_is_exec(pid_t pid, const char *name)
{
char buf[sizeof("/proc//exe") + sizeof(int)*3];
char *execbuf;
- int sz;
- int equal;
+ int n;
- sprintf(buf, "/proc/%d/exe", pid);
- sz = strlen(name) + 1;
- execbuf = xzalloc(sz);
- readlink(buf, execbuf, sz);
+ sprintf(buf, "/proc/%u/exe", pid);
+ n = strlen(name) + 1;
+ execbuf = xzalloc(n + 1);
+ readlink(buf, execbuf, n);
/* if readlink fails, execbuf still contains "" */
- equal = !strcmp(execbuf, name);
+ n = strcmp(execbuf, name);
if (ENABLE_FEATURE_CLEAN_UP)
free(execbuf);
- return equal;
+ return ~n; /* nonzero (true) if execbuf == name */
}
static int pid_is_user(int pid, int uid)
@@ -90,9 +82,10 @@ static int pid_is_cmd(pid_t pid, const char *name)
return r;
}
-
static void check(int pid)
{
+ struct pid_list *p;
+
if (execname && !pid_is_exec(pid, execname)) {
return;
}
@@ -102,14 +95,16 @@ static void check(int pid)
if (cmdname && !pid_is_cmd(pid, cmdname)) {
return;
}
- push(pid);
+ p = xmalloc(sizeof(*p));
+ p->next = found;
+ p->pid = pid;
+ found = p;
}
-
static void do_pidfile(void)
{
FILE *f;
- pid_t pid;
+ unsigned pid;
f = fopen(pidfile, "r");
if (f) {
@@ -143,10 +138,9 @@ static void do_procinit(void)
}
closedir(procdir);
if (!foundany)
- bb_error_msg_and_die ("nothing in /proc - not mounted?");
+ bb_error_msg_and_die("nothing in /proc - not mounted?");
}
-
static int do_stop(void)
{
char *what;
@@ -155,11 +149,13 @@ static int do_stop(void)
do_procinit();
- if (cmdname)
- what = xstrdup(cmdname);
- else if (execname)
- what = xstrdup(execname);
- else if (pidfile)
+ if (cmdname) {
+ if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(cmdname);
+ if (!ENABLE_FEATURE_CLEAN_UP) what = cmdname;
+ } else if (execname) {
+ if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(execname);
+ if (!ENABLE_FEATURE_CLEAN_UP) what = execname;
+ } else if (pidfile)
what = xasprintf("process in pidfile '%s'", pidfile);
else if (userspec)
what = xasprintf("process(es) owned by '%s'", userspec);
@@ -169,25 +165,25 @@ static int do_stop(void)
if (!found) {
if (!quiet)
printf("no %s found; none killed\n", what);
- if (ENABLE_FEATURE_CLEAN_UP)
- free(what);
- return -1;
+ killed = -1;
+ goto ret;
}
for (p = found; p; p = p->next) {
if (kill(p->pid, signal_nr) == 0) {
- p->pid = -p->pid;
+ p->pid = - p->pid;
killed++;
} else {
- bb_perror_msg("warning: failed to kill %d", p->pid);
+ bb_perror_msg("warning: killing process %u", p->pid);
}
}
if (!quiet && killed) {
printf("stopped %s (pid", what);
for (p = found; p; p = p->next)
if (p->pid < 0)
- printf(" %d", -p->pid);
+ printf(" %u", - p->pid);
puts(")");
}
+ ret:
if (ENABLE_FEATURE_CLEAN_UP)
free(what);
return killed;
@@ -287,7 +283,7 @@ int start_stop_daemon_main(int argc, char **argv)
if (opt & CTX_STOP) {
int i = do_stop();
- return (opt & OPT_OKNODO) ? 0 : (i<=0);
+ return (opt & OPT_OKNODO) ? 0 : (i <= 0);
}
do_procinit();
@@ -299,7 +295,24 @@ int start_stop_daemon_main(int argc, char **argv)
}
*--argv = startas;
if (opt & OPT_BACKGROUND) {
+#if BB_MMU
bb_daemonize(0);
+#else
+ pid_t pid = vfork();
+ if (pid < 0) /* error */
+ bb_perror_msg_and_die("vfork");
+ if (pid == 0) /* parent */
+ return 0;
+ }
+ /* child */
+ /* Redirect stdio to /dev/null, close extra FDs.
+ * We do not actually daemonize because of DAEMON_ONLY_SANITIZE */
+ bb_daemonize_or_rexec(
+ DAEMON_DEVNULL_STDIO
+ + DAEMON_CLOSE_EXTRA_FDS
+ + DAEMON_ONLY_SANITIZE,
+ NULL /* argv, unused */ );
+#endif
}
if (opt & OPT_MAKEPID) {
/* user wants _us_ to make the pidfile */
diff --git a/include/libbb.h b/include/libbb.h
index ddbde1833..547b8f798 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -573,7 +573,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet
*/
enum {
DAEMON_CHDIR_ROOT = 1,
- DAEMON_DEVNULL_STDIO = /* 2 */ 0, /* no users so far */
+ DAEMON_DEVNULL_STDIO = 2,
DAEMON_CLOSE_EXTRA_FDS = 4,
DAEMON_ONLY_SANITIZE = 8, /* internal use */
};
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index ea7b475eb..f7c620996 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -244,8 +244,6 @@ void bb_daemonize_or_rexec(int flags, char **argv)
{
int fd;
- fd = xopen(bb_dev_null, O_RDWR);
-
if (flags & DAEMON_CHDIR_ROOT)
xchdir("/");
@@ -255,6 +253,8 @@ void bb_daemonize_or_rexec(int flags, char **argv)
close(2);
}
+ fd = xopen(bb_dev_null, O_RDWR);
+
while ((unsigned)fd < 2)
fd = dup(fd); /* have 0,1,2 open at least to /dev/null */