diff options
author | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2016-09-15 16:16:04 +0000 |
---|---|---|
committer | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2016-09-15 16:16:04 +0000 |
commit | 59d8babc9d895cabb7c63196d27624ab1eec2987 (patch) | |
tree | f060a14d1edb14e41ef61f29b0bd8f5591042129 | |
parent | ebe5ab80415dd7b9e17988cbf90476799118d89a (diff) |
Go in the background later, using rdaemon().
rdaemon() works like daemon(3) but requires its caller to pre-open
/dev/null. This makes it possible to go in the background after
a chroot(2), allowing for more error checking. The pattern is basically
- open /dev/null
- chroot
- privdrop
- rdaemon
"design" initialy discussed with semarie@ a while ago, ok dlg@
-rw-r--r-- | usr.sbin/dhcrelay/dhcrelay.c | 46 | ||||
-rw-r--r-- | usr.sbin/ftp-proxy/ftp-proxy.c | 47 | ||||
-rw-r--r-- | usr.sbin/rtadvd/rtadvd.c | 51 |
3 files changed, 123 insertions, 21 deletions
diff --git a/usr.sbin/dhcrelay/dhcrelay.c b/usr.sbin/dhcrelay/dhcrelay.c index 88b1afda29d..54ee05a6fc3 100644 --- a/usr.sbin/dhcrelay/dhcrelay.c +++ b/usr.sbin/dhcrelay/dhcrelay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcrelay.c,v 1.41 2016/09/04 10:43:52 jca Exp $ */ +/* $OpenBSD: dhcrelay.c,v 1.42 2016/09/15 16:16:03 jca Exp $ */ /* * Copyright (c) 2004 Henning Brauer <henning@cvs.openbsd.org> @@ -48,6 +48,7 @@ #include <net/if.h> #include <errno.h> +#include <fcntl.h> #include <netdb.h> #include <paths.h> #include <pwd.h> @@ -62,6 +63,7 @@ #include "dhcpd.h" void usage(void); +int rdaemon(int); void relay(struct interface_info *, struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *); char *print_hw_addr(int, int, unsigned char *); @@ -91,7 +93,7 @@ struct server_list { int main(int argc, char *argv[]) { - int ch, daemonize, opt, rdomain; + int ch, devnull = -1, daemonize, opt, rdomain; extern char *__progname; struct server_list *sp = NULL; struct passwd *pw; @@ -158,8 +160,11 @@ main(int argc, char *argv[]) argv++; } - if (daemonize) - log_perror = 0; + if (daemonize) { + devnull = open(_PATH_DEVNULL, O_RDWR, 0); + if (devnull == -1) + error("open(%s): %m", _PATH_DEVNULL); + } if (interfaces == NULL) error("no interface given"); @@ -230,8 +235,6 @@ main(int argc, char *argv[]) time(&cur_time); bootp_packet_handler = relay; - if (daemonize) - daemon(0, 0); if ((pw = getpwnam("_dhcp")) == NULL) error("user \"_dhcp\" not found"); @@ -244,6 +247,12 @@ main(int argc, char *argv[]) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) error("can't drop privileges: %m"); + if (daemonize) { + if (rdaemon(devnull) == -1) + error("rdaemon: %m"); + log_perror = 0; + } + dispatch(); /* not reached */ @@ -356,6 +365,31 @@ usage(void) exit(1); } +int +rdaemon(int devnull) +{ + + switch (fork()) { + case -1: + return (-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return (-1); + + (void)dup2(devnull, STDIN_FILENO); + (void)dup2(devnull, STDOUT_FILENO); + (void)dup2(devnull, STDERR_FILENO); + if (devnull > 2) + (void)close(devnull); + + return (0); +} + char * print_hw_addr(int htype, int hlen, unsigned char *data) { diff --git a/usr.sbin/ftp-proxy/ftp-proxy.c b/usr.sbin/ftp-proxy/ftp-proxy.c index 366a6fabcac..74216d0791f 100644 --- a/usr.sbin/ftp-proxy/ftp-proxy.c +++ b/usr.sbin/ftp-proxy/ftp-proxy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ftp-proxy.c,v 1.34 2016/02/12 08:12:48 ajacoutot Exp $ */ +/* $OpenBSD: ftp-proxy.c,v 1.35 2016/09/15 16:16:03 jca Exp $ */ /* * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> @@ -32,6 +32,7 @@ #include <event.h> #include <fcntl.h> #include <netdb.h> +#include <paths.h> #include <pwd.h> #include <signal.h> #include <stdarg.h> @@ -101,6 +102,7 @@ void logmsg(int, const char *, ...); u_int16_t parse_port(int); u_int16_t pick_proxy_port(void); void proxy_reply(int, struct sockaddr *, u_int16_t); +int rdaemon(int); void server_error(struct bufferevent *, short, void *); int server_parse(struct session *s); int allow_data_connection(struct session *s); @@ -610,7 +612,7 @@ main(int argc, char *argv[]) struct rlimit rlp; struct addrinfo hints, *res; struct event ev_sighup, ev_sigint, ev_sigterm; - int ch, error, listenfd, on; + int ch, devnull, error, listenfd, on; const char *errstr; /* Defaults. */ @@ -770,18 +772,22 @@ main(int argc, char *argv[]) init_filter(qname, tagname, verbose); if (daemonize) { - if (daemon(0, 0) == -1) + devnull = open(_PATH_DEVNULL, O_RDWR, 0); + if (devnull == -1) + err(1, "open(%s)", _PATH_DEVNULL); + } + + if (!drop_privs()) + err(1, "cannot drop privileges"); + + if (daemonize) { + if (rdaemon(devnull) == -1) err(1, "cannot daemonize"); openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); } /* Use logmsg for output from here on. */ - if (!drop_privs()) { - logmsg(LOG_ERR, "cannot drop privileges: %s", strerror(errno)); - exit(1); - } - event_init(); /* Setup signal handler. */ @@ -1132,3 +1138,28 @@ usage(void) " [-t timeout]\n", __progname); exit(1); } + +int +rdaemon(int devnull) +{ + + switch (fork()) { + case -1: + return (-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return (-1); + + (void)dup2(devnull, STDIN_FILENO); + (void)dup2(devnull, STDOUT_FILENO); + (void)dup2(devnull, STDERR_FILENO); + if (devnull > 2) + (void)close(devnull); + + return (0); +} diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c index 8b8436cc6f0..b21ceeed070 100644 --- a/usr.sbin/rtadvd/rtadvd.c +++ b/usr.sbin/rtadvd/rtadvd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtadvd.c,v 1.78 2016/09/03 16:57:29 jca Exp $ */ +/* $OpenBSD: rtadvd.c,v 1.79 2016/09/15 16:16:03 jca Exp $ */ /* $KAME: rtadvd.c,v 1.66 2002/05/29 14:18:36 itojun Exp $ */ /* @@ -55,6 +55,8 @@ #include <string.h> #include <pwd.h> #include <signal.h> +#include <fcntl.h> +#include <paths.h> #include "rtadvd.h" #include "advcap.h" @@ -139,6 +141,7 @@ static int nd6_options(struct nd_opt_hdr *, int, static void free_ndopts(union nd_opts *); static void ra_output(struct rainfo *); static struct rainfo *if_indextorainfo(int); +static int rdaemon(int); static void dump_cb(int, short, void *); static void die_cb(int, short, void *); @@ -151,6 +154,7 @@ main(int argc, char *argv[]) { struct passwd *pw; int ch; + int devnull = -1; struct event ev_sock; struct event ev_rtsock; struct event ev_sigterm; @@ -182,6 +186,12 @@ main(int argc, char *argv[]) if (argc == 0) usage(); + if (!dflag) { + devnull = open(_PATH_DEVNULL, O_RDWR, 0); + if (devnull == -1) + fatal("open(\"" _PATH_DEVNULL "\")"); + } + SLIST_INIT(&ralist); /* get iflist block from kernel */ @@ -196,12 +206,6 @@ main(int argc, char *argv[]) if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1) fatal("inet_pton failed"); - if (conffile != NULL) - log_init(dflag); - - if (!dflag) - daemon(1, 0); - sock_open(); if (sflag == 0) @@ -218,6 +222,14 @@ main(int argc, char *argv[]) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("cannot drop privileges"); + if (!dflag) { + if (rdaemon(devnull) == -1) + fatal("rdaemon"); + } + + if (conffile != NULL) + log_init(dflag); + if (pledge("stdio inet route", NULL) == -1) err(1, "pledge"); @@ -1297,3 +1309,28 @@ ra_timer_update(struct rainfo *rai) log_debug("RA timer on %s set to %lld.%lds", rai->ifname, (long long)tm->tv_sec, tm->tv_usec); } + +int +rdaemon(int devnull) +{ + + switch (fork()) { + case -1: + return (-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return (-1); + + (void)dup2(devnull, STDIN_FILENO); + (void)dup2(devnull, STDOUT_FILENO); + (void)dup2(devnull, STDERR_FILENO); + if (devnull > 2) + (void)close(devnull); + + return (0); +} |