Perhaps something like this? Only compile-tested.
- todd
Index: usr.sbin/lpr/lpd/printjob.c
===================================================================
RCS file: /home/cvs/openbsd/src/usr.sbin/lpr/lpd/printjob.c,v
retrieving revision 1.49
diff -u -r1.49 printjob.c
--- usr.sbin/lpr/lpd/printjob.c 10 Dec 2013 16:38:04 -0000 1.49
+++ usr.sbin/lpr/lpd/printjob.c 18 Jan 2014 16:41:28 -0000
@@ -352,6 +352,8 @@
(void)snprintf(&width[2], sizeof(width) - 2, "%ld", PW);
indent[2] = '0';
indent[3] = '\0';
+ fdev = (dev_t)-1;
+ fino = (ino_t)-1;
/*
* read the control file for work to do
@@ -538,20 +540,30 @@
int fd, status, serrno;
int n, fi, fo, p[2], stopped = 0, nofile;
- PRIV_START;
- if (lstat(file, &stb) < 0 || (fi = safe_open(file, O_RDONLY, 0)) < 0) {
+ if (fdev != (dev_t)-1 && fino != (ino_t)-1) {
+ /* symbolic link */
+ PRIV_START;
+ fi = safe_open(file, O_RDONLY, 0);
+ PRIV_END;
+ if (fi != -1) {
+ /*
+ * The symbolic link should still point to the same file
+ * or someone is trying to print something he shouldn't.
+ */
+ if (fstat(fi, &stb) == -1 ||
+ stb.st_dev != fdev || stb.st_ino != fino) {
+ close(fi);
+ return(ACCESS);
+ }
+ }
+ } else {
+ /* regular file */
+ PRIV_START;
+ fi = safe_open(file, O_RDONLY|O_NOFOLLOW, 0);
PRIV_END;
- return(ERROR);
}
- PRIV_END;
- /*
- * Check to see if data file is a symbolic link. If so, it should
- * still point to the same file or someone is trying to print
- * something he shouldn't.
- */
- if (S_ISLNK(stb.st_mode) && fstat(fi, &stb) == 0 &&
- (stb.st_dev != fdev || stb.st_ino != fino))
- return(ACCESS);
+ if (fi == -1)
+ return(ERROR);
if (!SF && !tof) { /* start on a fresh page */
(void)write(ofd, FF, strlen(FF));
tof = 1;