Date: Mon, 8 May 2006 19:51:05 -0400 (EDT) From: John Hood <jh@sirocco.sandstorm.net> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/97002: crond fails quietly if /usr/sbin/sendmail is missing Message-ID: <200605082351.k48Np5fX012137@sirocco.sandstorm.net> Resent-Message-ID: <200605082350.k48NoAw6059954@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 97002 >Category: bin >Synopsis: crond fails quietly if /usr/sbin/sendmail is missing >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon May 08 23:50:10 GMT 2006 >Closed-Date: >Last-Modified: >Originator: John Hood >Release: FreeBSD 6.0-RELEASE i386 >Organization: Sandstorm Enterprises, Inc. >Environment: System: FreeBSD faster.sandstorm.net 6.0-RELEASE FreeBSD 6.0-RELEASE #0: Thu Nov 3 09:36:13 UTC 2005 root@x64.samsco.home:/usr/obj/usr/src/sys/GENERIC i386 >Description: If cron's job-running child fails to exec /usr/sbin/sendmail and the cron job writes to stdout, hijinks ensue (thanks for the phrase, regis!) The cron job writes on a pipe to a crond process, which copies it to another pipe to what should be a sendmail. If this exits early and the pipe is closed, the cron child process gets killed with a SIGPIPE. Since cron delays running sendmail and doing any of this until it's received something from the cron job, the cron job executes before any of this happens. If the cron job writes again on *its* pipe, it gets a SIGPIPE too, and may fail mysteriously. There's code in cron to log mail failures, but the SIGPIPE prevents that code from running. >How-To-Repeat: rm /usr/sbin/sendmail echo '* * * * * tee /tmp/termcap < /etc/termcap' | crontab - tail -f /var/log/cron ls -l /etc/termcap /tmp/termcap >Fix: Patch to fix this problem by ignoring SIGPIPE, add logging of failure to exec /usr/sbin/sendmail, and minor cleanup of logging functions to get *that* to work. diff -r -u /usr/src/usr.sbin/cron/Makefile.inc ./Makefile.inc Only in ./cron: cron Only in ./cron: cron.8.gz Only in ./cron: cron.o Only in ./cron: database.o diff -r -u /usr/src/usr.sbin/cron/cron/do_command.c ./cron/do_command.c --- /usr/src/usr.sbin/cron/cron/do_command.c Sun May 16 15:29:33 2004 +++ ./cron/do_command.c Mon May 8 17:12:02 2006 @@ -26,9 +26,6 @@ #if defined(sequent) # include <sys/universe.h> #endif -#if defined(SYSLOG) -# include <syslog.h> -#endif #if defined(LOGIN_CAP) # include <login_cap.h> #endif @@ -187,9 +184,7 @@ /* that's the last thing we'll log. close the log files. */ -#ifdef SYSLOG - closelog(); -#endif + log_close(); /* get new pgrp, void tty, etc. */ @@ -388,6 +383,8 @@ register FILE *mail; register int bytes = 1; int status = 0; + + signal(SIGPIPE, SIG_IGN); Debug(DPROC|DEXT, ("[%d] got data (%x:%c) from grandchild\n", Only in ./cron: do_command.o Only in ./cron: job.o diff -r -u /usr/src/usr.sbin/cron/cron/popen.c ./cron/popen.c --- /usr/src/usr.sbin/cron/cron/popen.c Tue Feb 5 21:00:07 2002 +++ ./cron/popen.c Mon May 8 16:01:24 2006 @@ -35,9 +35,6 @@ #include <sys/signal.h> #include <fcntl.h> #include <paths.h> -#if defined(SYSLOG) -# include <syslog.h> -#endif #if defined(LOGIN_CAP) # include <login_cap.h> #endif @@ -65,6 +62,7 @@ PID_T pid; char *usernm; char *argv[MAX_ARGS + 1]; + int status; # if defined(LOGIN_CAP) struct passwd *pwd; login_cap_t *lc; @@ -112,7 +110,7 @@ #endif iop = NULL; - switch(pid = vfork()) { + switch(pid = fork()) { case -1: /* error */ (void)close(pdes[0]); (void)close(pdes[1]); @@ -120,10 +118,7 @@ /* NOTREACHED */ case 0: /* child */ if (e != NULL) { -#ifdef SYSLOG - closelog(); -#endif - + log_close(); /* get new pgrp, void tty, etc. */ (void) setsid(); @@ -173,7 +168,7 @@ (void) endpwent(); # endif /* set our directory, uid and gid. Set gid first, - * since once we set uid, we've lost root privledges. + * since once we set uid, we've lost root privileges. */ setgid(e->gid); # if defined(BSD) @@ -193,6 +188,7 @@ #else execvp(argv[0], argv); #endif + log_it("CRON", getpid(), "CAN'T EXEC", argv[0]); _exit(1); } /* parent; assume fdopen can't fail... */ Only in ./cron: popen.o Only in ./cron: user.o Only in ./crontab: crontab Only in ./crontab: crontab.1.gz Only in ./crontab: crontab.5.gz Only in ./crontab: crontab.o Only in ./lib: entry.o Only in ./lib: env.o Only in ./lib: libcron.a diff -r -u /usr/src/usr.sbin/cron/lib/misc.c ./lib/misc.c --- /usr/src/usr.sbin/cron/lib/misc.c Wed Feb 9 08:02:43 2005 +++ ./lib/misc.c Mon May 8 14:37:33 2006 @@ -49,6 +49,11 @@ static int LogFD = ERR; +#if defined(SYSLOG) +static int syslog_open = 0; +#endif + + int strcmp_until(left, right, until) @@ -459,10 +464,6 @@ register struct tm *t = localtime(&now); #endif /*LOG_FILE*/ -#if defined(SYSLOG) - static int syslog_open = 0; -#endif - #if defined(LOG_FILE) /* we assume that MAX_TEMPSTR will hold the date, time, &punctuation. */ @@ -535,10 +536,18 @@ void log_close() { +#if defined(LOG_FILE) if (LogFD != ERR) { close(LogFD); LogFD = ERR; } +#endif +#ifdef SYSLOG + if (syslog_open) { + closelog(); + syslog_open = 0; + } +#endif } Only in ./lib: misc.o >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200605082351.k48Np5fX012137>