Date: Wed, 28 Feb 2001 22:34:06 +0100 (CET) From: mkamm@gmx.net To: FreeBSD-gnats-submit@freebsd.org Subject: bin/25462: daemon(3) fails if called by a session leader Message-ID: <200102282134.f1SLY6f26052@homebox.kammerhofer.org>
next in thread | raw e-mail | index | archive | help
>Number: 25462 >Category: bin >Synopsis: daemon(3) fails if called by a session leader >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Feb 28 13:50:01 PST 2001 >Closed-Date: >Last-Modified: >Originator: Martin Kammerhofer >Release: FreeBSD 4.2-STABLE i386 >Organization: TU Graz >Environment: Any FreeBSD system. >Description: The C library routine daemon(3) has a subtle bug: If the calling process is a session leader (i.e. pid == pgid) then a hangup signal will be delivered immediately to the created child process (daemon). The reason can be read in the _exit(2) manpage. I guess this bug is rarely triggered during normal operation but I can think of several scenarios were it will show up: - starting a daemon from /etc/passwd (as a login shell) - exec'ing a daemon from any login shell - exec'ing a daemon from a daemon - controlling a daemon with expect(1) from ports/lang/expect - giving a daemon as argument to script(1) >How-To-Repeat: ~/tmp$ cat daemontest.c #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> int main (void) { unlink("SUCCESS"); printf("I want to become a daemon\n"); if (daemon(1, 1)) perror("daemon"); open("SUCCESS", O_CREAT | O_TRUNC | O_WRONLY, 0666); printf("I'm a daemon now\n"); return (0); } ~/tmp$ make daemontest cc -Wall daemontest.c -o daemontest ~/tmp$ ./daemontest I want to become a daemon ~/tmp$ I'm a daemon now ~/tmp$ script -q logfile ./daemontest I want to become a daemon ~/tmp$ ls SUCCESS ls: SUCCESS: No such file or directory ~/tmp$ cat logfile I want to become a daemon ~/tmp$ >Fix: There are several options here. I guess the most simple approach is ignoring SIGHUP until setsid(2) has been called. Of course, this doesn't fix daemons using fork && _exit instead of daemon(3). Index: daemon.c =================================================================== RCS file: /home/ncvs/src/lib/libc/gen/daemon.c,v retrieving revision 1.4 diff -u -r1.4 daemon.c --- daemon.c 2001/01/24 12:59:21 1.4 +++ daemon.c 2001/02/28 19:32:40 @@ -41,6 +41,7 @@ #include <fcntl.h> #include <paths.h> #include <unistd.h> +#include <signal.h> #include "un-namespace.h" int @@ -48,7 +49,13 @@ int nochdir, noclose; { int fd; + struct sigaction sa_ign, sa_save; + pid_t newgrp; + sa_ign.sa_handler = SIG_IGN; + sa_ign.sa_flags = 0; + (void) sigaction(SIGHUP, &sa_ign, &sa_save); + switch (fork()) { case -1: return (-1); @@ -58,7 +65,9 @@ _exit(0); } - if (setsid() == -1) + newgrp = setsid(); + (void) sigaction(SIGHUP, &sa_save, (struct sigaction *) 0); + if (newgrp == -1) return (-1); if (!nochdir) >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102282134.f1SLY6f26052>