diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-06-13 06:48:41 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-06-13 06:48:41 +0000 |
commit | 07ad6ff1c450d29d89afb16eadc39ecbf842365e (patch) | |
tree | 7216a440404f1eafa0ed541f72d8e30b975759d5 /usr.sbin/lpr | |
parent | a965e01bad29a9ba78e1b2d29a39b46bd2d8a3b4 (diff) |
Fixed some lpd bugs while on the plane from Calgary:
o mark fatal() as __dead
o add SIGINT to the signal mask when installing abort() as a handler.
We can end up in abortpr() due to several different signals and since
abortpr() kill()s itself with SIGINT we need to explicately protect
against the current process receiving SIGINT while in abortpr()
o Don't leak the lock fd to children spawned by lpd
o Close the lock file (and thus unlocke immediately in abortpr().
Otherwise, if there is an output filter the lock file only gets
closed after we finish waiting for the output filter to die.
This causes a race condition in lprm such that the per-printer
daemon does not get restarted when lprm kills the active job
(noticed during c2k2 with the mp3 printer spool ;-)
o Open the printcap file with privs raised just in case it is not
world-readable.
Diffstat (limited to 'usr.sbin/lpr')
-rw-r--r-- | usr.sbin/lpr/common_source/common.c | 6 | ||||
-rw-r--r-- | usr.sbin/lpr/common_source/lp.h | 4 | ||||
-rw-r--r-- | usr.sbin/lpr/lpd/printjob.c | 46 |
3 files changed, 37 insertions, 19 deletions
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c index 5f6576627d6..a0723a429bf 100644 --- a/usr.sbin/lpr/common_source/common.c +++ b/usr.sbin/lpr/common_source/common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: common.c,v 1.22 2002/06/09 03:56:28 millert Exp $ */ +/* $OpenBSD: common.c,v 1.23 2002/06/13 06:48:40 millert Exp $ */ /* $NetBSD: common.c,v 1.21 2000/08/09 14:28:50 itojun Exp $ */ /* @@ -43,7 +43,7 @@ #if 0 static const char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95"; #else -static const char rcsid[] = "$OpenBSD: common.c,v 1.22 2002/06/09 03:56:28 millert Exp $"; +static const char rcsid[] = "$OpenBSD: common.c,v 1.23 2002/06/13 06:48:40 millert Exp $"; #endif #endif /* not lint */ @@ -434,7 +434,7 @@ delay(int n) (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay); } -void +__dead void fatal(const char *msg, ...) { extern char *__progname; diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h index 98ffc67cca8..3c117b3566a 100644 --- a/usr.sbin/lpr/common_source/lp.h +++ b/usr.sbin/lpr/common_source/lp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lp.h,v 1.12 2002/06/09 03:56:28 millert Exp $ */ +/* $OpenBSD: lp.h,v 1.13 2002/06/13 06:48:40 millert Exp $ */ /* $NetBSD: lp.h,v 1.14 2000/04/16 14:43:58 mrg Exp $ */ /* @@ -132,7 +132,7 @@ char *checkremote(void); int chk(char *); void displayq(int); void dump(char *, char *, int); -void fatal(const char *, ...) +__dead void fatal(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); int getline(FILE *); int getport(char *, int); diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c index 6efe8e00006..306eba7dd37 100644 --- a/usr.sbin/lpr/lpd/printjob.c +++ b/usr.sbin/lpr/lpd/printjob.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printjob.c,v 1.34 2002/06/08 23:23:24 millert Exp $ */ +/* $OpenBSD: printjob.c,v 1.35 2002/06/13 06:48:40 millert Exp $ */ /* $NetBSD: printjob.c,v 1.31 2002/01/21 14:42:30 wiz Exp $ */ /* @@ -145,6 +145,7 @@ printjob(void) struct stat stb; struct queue *q, **qp; struct queue **queue; + struct sigaction sa; int i, fd, nitems; off_t pidoff; int errcnt, count = 0; @@ -164,14 +165,21 @@ printjob(void) syslog(LOG_ERR, "dup2: %m"); exit(1); } - close(fd); + (void)close(fd); } pid = getpid(); /* for use with lprm */ setpgrp(0, pid); - signal(SIGHUP, abortpr); - signal(SIGINT, abortpr); - signal(SIGQUIT, abortpr); - signal(SIGTERM, abortpr); + + /* we add SIGINT to the mask so abortpr() doesn't kill itself */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = abortpr; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGINT); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); /* so we can use short form file names */ if (chdir(SD) < 0) { @@ -348,7 +356,7 @@ printit(char *file) if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) { syslog(LOG_INFO, "%s: %s: %m", printer, file); if (fd >= 0) - close(fd); + (void)close(fd); return(OK); } /* @@ -755,7 +763,7 @@ start: if (fd >= 0) { while ((nread = read(fd, buf, sizeof(buf))) > 0) (void)write(STDERR_FILENO, buf, nread); - close(fd); + (void)close(fd); } if (!WIFEXITED(status)) { @@ -1182,6 +1190,7 @@ dofork(int action) * Child should run as daemon instead of root */ if (pid == 0) { + (void)close(lfd); PRIV_START; pw = getpwuid(DU); if (pw == 0) { @@ -1216,8 +1225,9 @@ dofork(int action) static void abortpr(int signo) { + (void)close(lfd); (void)unlink(tempfile); - kill(0, SIGINT); + (void)kill(0, SIGINT); if (ofilter > 0) kill(ofilter, SIGCONT); while (wait(NULL) > 0) @@ -1231,14 +1241,22 @@ init(void) int status; char *s; - if ((status = cgetent(&bp, printcapdb, printer)) == -2) { - syslog(LOG_ERR, "can't open printer description file"); - exit(1); - } else if (status == -1) { + PRIV_START; + status = cgetent(&bp, printcapdb, printer); + PRIV_END; + + switch (status) { + case -1: syslog(LOG_ERR, "unknown printer: %s", printer); exit(1); - } else if (status == -3) + case -2: + syslog(LOG_ERR, "can't open printer description file"); + exit(1); + case -3: fatal("potential reference loop detected in printcap file"); + default: + break; + } if (cgetstr(bp, DEFLP, &LP) == -1) LP = _PATH_DEFDEVLP; |