Bug 4833 - initlog makes daemons depend on stdin of starting session
Summary: initlog makes daemons depend on stdin of starting session
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: initscripts
Version: 6.0
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Bill Nottingham
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 1999-09-01 17:49 UTC by rjb
Modified: 2014-03-17 02:09 UTC (History)
3 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2000-01-21 06:12:54 UTC
Embargoed:


Attachments (Terms of Use)

Description rjb 1999-09-01 17:49:36 UTC
initlog does a dup of fd 0 (usually getting 10) before
fork(). the parent closes it, but the child does not. Most
daemon programs close 0,1,2 but do not know to close 10.
E.g. consider this extract of strace output....

870   execve("/sbin/initlog", ["initlog", "-c",
"/usr/sbin/snmpd"], [/* 10 vars */]) = 0
870   brk(0)                            = 0x804e2ac
870   open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No
such file or directory)
870   open("/etc/ld.so.cache", O_RDONLY) = 4
870   fstat(4, {st_mode=0, st_size=0, ...}) = 0
870   mmap(0, 21944, PROT_READ, MAP_PRIVATE, 4, 0) =
0x40014000
870   close(4)                          = 0
870   open("/lib/libc.so.6", O_RDONLY)  = 4
870   fstat(4, {st_mode=0, st_size=0, ...}) = 0
870   read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096)
= 4096
870   mmap(0, 974392, PROT_READ|PROT_EXEC, MAP_PRIVATE, 4,
0) = 0x4001a000
870   mprotect(0x40100000, 32312, PROT_NONE) = 0
870   mmap(0x40100000, 20480, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, 4, 0xe5000) = 0x40100000
870   mmap(0x40105000, 11832, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40105000
870   close(4)                          = 0
870   munmap(0x40014000, 21944)         = 0
870   personality(PER_LINUX)            = 0
870   getpid()                          = 870
870   brk(0)                            = 0x804e2ac
870   brk(0x804e2e4)                    = 0x804e2e4
870   brk(0x804f000)                    = 0x804f000
870   pipe([4, 5])                      = 0
870   pipe([6, 7])                      = 0
870   pipe([8, 9])                      = 0
870   dup(0)                            = 10
870   fork()                            = 871
870   close(10)                         = 0
870   close(5)                          = 0
870   close(7)                          = 0
870   close(9)                          = 0
870   pipe([5, 7])                      = 0
870   SYS_168(0x804ed20, 0x2, 0x1f4, 0x1f4, 0x804ed20
<unfinished ...>
871   dup2(5, 1)                        = 1
871   dup2(7, 2)                        = 2
871   dup2(9, 21)                       = 21
871   close(5)                          = 0
871   close(7)                          = 0
871   close(9)                          = 0
871   close(4)                          = 0
871   close(6)                          = 0
871   execve("/usr/sbin/snmpd", ["/usr/sbin/snmpd"], [/* 10
vars */]) = 0

This leads to many daemons having a reference to the
stdin of the starting session. (you can see this with lsof)

If the stdin was a real terminal then there is no problem
because the /dev/tty.. entry continues to exist after
the user logs out.

But, if the stdin is a socket (due to use of rsh) then
the rsh does not terminate (the init.d/xxx appears to never
terminate). If the user drops the connection then the
daemon gets killed!

initlog should not do this dup().

This problem can be worked around by editing
init.d/functions andputting a </dev/null on line 78 before
the &&.

Comment 1 Bill Nottingham 1999-09-20 20:49:59 UTC
fixed in initscripts-4.44-1.

Comment 2 rjb 1999-11-25 01:02:59 UTC
This behavior is different but not fixed in 4.48-1.
The daemon still ends up with a reference to the socket, and the
rsh is still blocked. E.g.:

bash# rsh revs lsof -p20451
COMMAND   PID USER   FD   TYPE DEVICE   SIZE   NODE NAME
nfsd    20451 root  cwd    DIR    3,3   4096      2 /
nfsd    20451 root  rtd    DIR    3,3   4096      2 /
nfsd    20451 root    0u  sock    0,0        166838 can't identify protocol
nfsd    20451 root    1w  FIFO    0,0        166867 pipe
nfsd    20451 root    2w  FIFO    0,0        166868 pipe
nfsd    20451 root    3w   REG    3,3 255731  59079 /tmp/wibble
nfsd    20451 root    4r   REG    3,3    557  15175 /etc/initlog.conf
nfsd    20451 root    9r  FIFO    0,0        166869 pipe
nfsd    20451 root   21w  FIFO    0,0        166869 pipe

[1]+  Stopped (tty input)     rsh revs strace -f -o /tmp/wibble
/etc/rc.d/init.d/nfs start
bash#

Indeed, the strace shows that initlog now does a close(1073817264)  getting
EBADF arounf about the point where it would be expected to close(0)

Please can this be reopened and fixed.

Comment 3 weejock-rhbug 2000-01-20 22:10:59 UTC
A slightly related bug is that the child daemon inherits a descriptor to
/etc/initlog.conf.

This diff fixes that:

--- initscripts-4.48/src/initlog.c.close        Thu Jan 20 16:58:01 2000
+++ initscripts-4.48/src/initlog.c      Thu Jan 20 16:59:43 2000
@@ -42,9 +42,9 @@
     int lfac=-1,lpri=-1;

     if ((fd=open(fname,O_RDONLY))==-1) return;
-    if (fstat(fd,&sbuf)) return;
+    if (fstat(fd,&sbuf)) goto clout;
     data=malloc(sbuf.st_size+1);
-    if (read(fd,data,sbuf.st_size)!=sbuf.st_size) return;
+    if (read(fd,data,sbuf.st_size)!=sbuf.st_size) goto clout;
     data[sbuf.st_size] = '\0';
     while ((line=getLine(&data))) {
        if (line[0]=='#') continue;
@@ -88,6 +88,9 @@
     }
     if (lfac!=-1) logfacility=lfac;
     if (lpri!=-1) logpriority=lpri;
+
+clout:
+    close(fd);
 }

 char *getLine(char **data) {

Comment 4 Bill Nottingham 2000-01-20 22:20:59 UTC
Second one is fixed since 4.65 or so.
First one is being worked on.

Comment 5 Bill Nottingham 2000-01-21 06:12:59 UTC
The first bug also seems to be fixed as of initscripts-4.5x or so,
and I can't reproduce it in initscripts-latest.


Note You need to log in before you can comment on or make changes to this bug.