From mkamm@sbox.tu-graz.ac.at  Wed Feb 28 13:42:51 2001
Return-Path: <mkamm@sbox.tu-graz.ac.at>
Received: from ns1.tu-graz.ac.at (ns1.tu-graz.ac.at [129.27.2.3])
	by hub.freebsd.org (Postfix) with ESMTP id 145E537B719
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 28 Feb 2001 13:42:50 -0800 (PST)
	(envelope-from mkamm@sbox.tu-graz.ac.at)
Received: from homebox.kammerhofer.org (isdn099.tu-graz.ac.at [129.27.240.99])
	by ns1.tu-graz.ac.at (8.9.3/8.9.3) with ESMTP id WAA24557
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 28 Feb 2001 22:42:44 +0100 (MET)
Received: (from mkamm@localhost)
	by homebox.kammerhofer.org (8.11.2/8.11.2) id f1SLY6f26052;
	Wed, 28 Feb 2001 22:34:06 +0100 (CET)
	(envelope-from mkamm)
Message-Id: <200102282134.f1SLY6f26052@homebox.kammerhofer.org>
Date: Wed, 28 Feb 2001 22:34:06 +0100 (CET)
From: mkamm@gmx.net
Reply-To: mkamm@gmx.net
To: FreeBSD-gnats-submit@freebsd.org
Subject: daemon(3) fails if called by a session leader
X-Send-Pr-Version: 3.2

>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:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 28 13:50:01 PST 2001
>Closed-Date:    Mon Nov 10 16:12:27 CST 2003
>Last-Modified:  Wed Jul 21 07:50:00 GMT 2004
>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:
State-Changed-From-To: open->closed 
State-Changed-By: ghelmer 
State-Changed-When: Mon Nov 10 16:11:53 CST 2003 
State-Changed-Why:  
Committed a fix, thanks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=25462 

From: dada@sbox.tugraz.at
To: ghelmer@freebsd.org
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/25462: daemon(3) fails if called by a session leader:
	Please MFC!
Date: Wed, 21 Jul 2004 09:41:08 +0200

 Please MFC this PR!
 
>Unformatted:
