[prev in list] [next in list] [prev in thread] [next in thread]
List: freebsd-bugs
Subject: bin/25462: daemon(3) fails if called by a session leader
From: mkamm () gmx ! net
Date: 2001-02-28 21:34:06
[Download RAW message or body]
>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
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic