diff --git a/misc.c b/misc.c index 07d4179e479..65c9222aa8b 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.106 2016/10/23 22:04:05 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.107 2016/11/30 00:28:31 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -1251,3 +1251,21 @@ bind_permitted(int port, uid_t uid) return 0; return 1; } + +/* returns 1 if process is already daemonized, 0 otherwise */ +int +daemonized(void) +{ + int fd; + + if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { + close(fd); + return 0; /* have controlling terminal */ + } + if (getppid() != 1) + return 0; /* parent is not init */ + if (getsid(0) != getpid()) + return 0; /* not session leader */ + debug3("already daemonized"); + return 1; +} diff --git a/misc.h b/misc.h index 3578e8ef539..c242f9011f5 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.60 2016/10/23 22:04:05 dtucker Exp $ */ +/* $OpenBSD: misc.h,v 1.61 2016/11/30 00:28:31 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -31,6 +31,7 @@ struct Forward { int forward_equals(const struct Forward *, const struct Forward *); int bind_permitted(int, uid_t); +int daemonized(void); /* Common server and client forwarding options. */ struct ForwardOptions { diff --git a/sshd.c b/sshd.c index ce4a493ef88..fafcd3400b8 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.477 2016/11/29 03:54:50 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.478 2016/11/30 00:28:31 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1343,7 +1343,7 @@ main(int ac, char **av) struct ssh *ssh = NULL; extern char *optarg; extern int optind; - int r, opt, i, j, on = 1; + int r, opt, i, j, on = 1, already_daemon; int sock_in = -1, sock_out = -1, newsock = -1; const char *remote_ip; int remote_port; @@ -1802,11 +1802,12 @@ main(int ac, char **av) log_init(__progname, options.log_level, options.log_facility, log_stderr); /* - * If not in debugging mode, and not started from inetd, disconnect - * from the controlling terminal, and fork. The original process - * exits. + * If not in debugging mode, not started from inetd and not already + * daemonized (eg re-exec via SIGHUP), disconnect from the controlling + * terminal, and fork. The original process exits. */ - if (!(debug_flag || inetd_flag || no_daemon_flag)) { + already_daemon = daemonized(); + if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) { if (daemon(0, 0) < 0) fatal("daemon() failed: %.200s", strerror(errno)); @@ -1840,7 +1841,7 @@ main(int ac, char **av) * Write out the pid file after the sigterm handler * is setup and the listen sockets are bound */ - if (options.pid_file != NULL && !debug_flag) { + if (options.pid_file != NULL && !debug_flag && !already_daemon) { FILE *f = fopen(options.pid_file, "w"); if (f == NULL) {