Subject: Re: BoS: Linux & BSD's lpr exploit (fwd)
To: Curt Sampson <curt@portal.ca>
From: Michael Graff <explorer@flame.org>
List: current-users
Date: 10/25/1996 17:09:43
Curt Sampson <curt@portal.ca> writes:

> This is also a good candidate to put into the 1.2 patches. :-)

I requested that the 1.11 version of lpr.c be put in the official patch
list.  This fixes this hole, and one bug, but in a different way.  The
patch below is still "helpful" in that case.

(1)  1.11 makes it possible to print files which live on NFS servers
     which don't export the system to root.

(2)  It still gives you the shell in the hole found, but it's not a root
     shell.  I went through the code and limited the setuid portions to
     bare minimum.

Here's the version I'd use...  Until a 1.2 official patch comes out, try
this:

Index: lpr.c
===================================================================
RCS file: /a/cvsroot/src/usr.sbin/lpr/lpr/lpr.c,v
retrieving revision 1.10
diff -u -r1.10 lpr.c
--- lpr.c	1996/03/21 18:12:25	1.10
+++ lpr.c	1996/10/25 21:10:16
@@ -1,4 +1,4 @@
-/*	$NetBSD: lpr.c,v 1.10 1996/03/21 18:12:25 jtc Exp $	*/
+/*	$NetBSD: lpr.c,v 1.11 1996/08/10 20:09:19 explorer Exp $	*/
 /*
  * Copyright (c) 1983, 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -129,6 +129,7 @@
 	euid = geteuid();
 	uid = getuid();
 	seteuid(uid);
+
 	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 		signal(SIGHUP, cleanup);
 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
@@ -354,7 +355,7 @@
 		}
 		if (sflag)
 			printf("%s: %s: not linked, copying instead\n", name, arg);
-		seteuid(euid);
+		seteuid(uid);
 		if ((i = open(arg, O_RDONLY)) < 0) {
 			seteuid(uid);
 			printf("%s: cannot open %s\n", name, arg);
@@ -457,9 +458,7 @@
 	register int ret;
 
 	if (*file != '/') {
-		seteuid(euid);
 		if (getcwd(buf, BUFSIZ) == NULL) {
-			seteuid(uid);
 			return(NULL);
 		}
 		while (file[0] == '.') {
@@ -499,6 +498,10 @@
 	register char *p1 = buf;
 	register int len = 2;
 
+	if (strlen(p2) > BUFSIZ - 2)
+	  errx(1, "String longer than %d", BUFSIZ);
+
+
 	*p1++ = c;
 	while ((c = *p2++) != '\0') {
 		*p1++ = (c == '\n') ? ' ' : c;
@@ -587,7 +590,7 @@
 	register int fd;
 	register char *cp;
 
-	seteuid(euid);
+	seteuid(uid);
 	if (access(file, 4) < 0) {
 		printf("%s: cannot access %s\n", name, file);
 		goto bad;