Bug 145992 - crond does not explicitly open file descriptor 0 if it is not available while startup
Summary: crond does not explicitly open file descriptor 0 if it is not available while...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: vixie-cron
Version: 3.0
Hardware: i386
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jason Vas Dias
QA Contact: Brock Organ
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2005-01-24 16:18 UTC by Mustafa Mahudhawala
Modified: 2007-11-30 22:07 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2005-05-20 00:05:24 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
Patch to open fd 0 if not already open (317 bytes, patch)
2005-01-24 16:21 UTC, Mustafa Mahudhawala
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2005:291 0 normal SHIPPED_LIVE vixie-cron bug fix update 2005-05-19 04:00:00 UTC

Internal Links: 163141

Description Mustafa Mahudhawala 2005-01-24 16:18:09 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5)
Gecko/20041107 Firefox/1.0

Description of problem:
The result of crond not explicitly opening file descriptor 0, is that
the cronjobs inherit a closed fd 0 (stdin), which tends to be an issue
in some cases. eg. if apache is periodically restarted from cron
(quite common in web hosting environments) and cron does not open
stdin i.e. fd 0 for it, then apache spams the apache error_log with
following error:

[error] (88)Socket operation on non-socket: apr_accept: (client socket)

Note: this issue manifests itself only if auditd is disabled and
/dev/audit removed (see Bug #131860)

If crond is invoked in same scenario (i.e. with closed fd 0) using
strace, 

# cat test.sh
#!/bin/sh
exec 0<&-
/usr/bin/strace -xv -tt -ff -o /tmp/crond.strace /usr/sbin/crond

following are some of the observations related to this issue:

/tmp/crond.strace.13897:09:21:01.000350 pipe([0, 4]) = 0
/tmp/crond.strace.13897:09:21:01.000453 pipe([5, 6]) = 0

Though pipe using 0 as one of the file descriptors is not an issue in
itself, but later fd 0 is specifically closed, and then a dup2 called,
which fails as follows ..

/tmp/crond.strace.13899:09:21:01.004200 dup2(0, 0)              = -1
EBADF (Bad file descriptor)
and later the cronjob is executed without a valid fd 0.

Analyzing the source of vixie-cron-3.0.1-75.1, this is how it probably
happens ..

acquire_daemonlock(0) in main() of cron.c uses fd 0 for the pid file
(since fd 0 was not available when cron started) this is then
converted to a file pointer using fdopen() and preserved via static
file pointer *fp (check misc.c)

later in do_command() of do_command.c (this is where the actual
execution of cronjob is handled) acquire_daemonlock(1) is called which
closes the static file pointer *fp, this inturn releases fd 0

later from child_process() pipe(stdin_pipe) and pipe(stdout_pipe)
calls are made to communicate with the future child (the cronjob).
here the file descriptor for reading of pipe(stdin_pipe) is 0 since fd
0 has been made available as the lowest file descriptor due to call of
acquire_daemonlock(1). This corresponds to the pipe calls seen in
strace above.

Then after fork(), intentionally, the not required (in child) ends of
the inherited pipes are closed via calls close(stdin_pipe[WRITE_PIPE])
and close(stdout_pipe[READ_PIPE])

But just before this, via the setsid() call, un-intentionally, the
file descriptor for reading of stdin_pipe  i.e. stdin_pipe[READ_PIPE]
gets closed since it was using fd 0 (check compat.c for details on setsid)

Due to this dup2(stdin_pipe[READ_PIPE], STDIN) which ties (duplicates)
the stdin_pipe[READ_PIPE] to the STDIN of the child (i.e. the cronjob)
fails with EBADF (Bad file descriptor) as seen in strace above.

And hence the cronjob is executed without a valid i.e. closed STDIN

If laus is enabled and /dev/audit exist, then possibly, when
/dev/audit is opened via LAUS_OPEN macro just before
acquire_daemonlock(0) in main() in cron.c, it uses up fd 0, this
causes acquire_daemonlock(0) to preserve a non 0 fd via static file
pointer *fp for the pid file, and due to which the the scenario
described above does not occur.

Version-Release number of selected component (if applicable):
vixie-cron-3.0.1-75.1

How reproducible:
Always

Steps to Reproduce:
1. Ensure auditd is disabled and /dev/audit is removed as per Bug #131860
1. Restart crond from a shell script after closing file descriptor zero

# cat test1.sh
#!/bin/sh
exec 0<&-
service crond restart

2. Schedule a cronjob which just attempts to open a file, and check
the file descriptor allocated

*/1 * * * * root /root/test2 >> /tmp/test2

test2 is created from test2.c

# cat test2.c
#include <errno.h>
#include <fcntl.h>
extern int errno;
int main(int argc, char *argv[]) {
        int fd;
        if((fd = open("/etc/hosts",O_RDONLY)) == -1)
                printf("Error No %d\n",errno);
        else
                printf("FD - %d\n", fd);
        close(fd);
        return 0;
}

Compiled using:
# gcc -o test2 test2.c

Check (tail -f) /tmp/test2

Actual Results:  FD - 0

Expected Results:  FD - 3

Additional info:

Comment 1 Mustafa Mahudhawala 2005-01-24 16:21:43 UTC
Created attachment 110129 [details]
Patch to open fd 0 if not already open

This patch needs to be applied after all the other vixie-cron-3.0.1 patches
have been applied

Comment 2 Jason Vas Dias 2005-01-24 16:32:03 UTC
This problem is now fixed in vixie-cron-4.1-2_EL3, which is the latest
version for RHEL-3, currently undergoing QA testing, and which should
be in RHEL-3-U5. Meanwhile, you can download it from:
   http://people.redhat.com/~jvdias/vixie-cron/RHEL-3 


Comment 5 Mustafa Mahudhawala 2005-01-24 17:06:39 UTC
Thank You Jason,
vixie-cron-4.1-2_EL3 works fine.

Btw, just to correct my explaination,

stdin_pipe[READ_PIPE] is un-intentionally closed not by setsid, but by
close(STDIN) called just before dup2(stdin_pipe[READ_PIPE], STDIN)
since it was using fd 0.

Comment 7 Tim Powers 2005-05-20 00:05:24 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHBA-2005-291.html



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