From owner-freebsd-audit Wed Feb 6 17:49:26 2002 Delivered-To: freebsd-audit@freebsd.org Received: from peitho.fxp.org (peitho.fxp.org [209.26.95.40]) by hub.freebsd.org (Postfix) with ESMTP id 02F6637B417 for ; Wed, 6 Feb 2002 17:49:15 -0800 (PST) Received: by peitho.fxp.org (Postfix, from userid 1501) id 7EF4B13667; Wed, 6 Feb 2002 20:49:08 -0500 (EST) Date: Wed, 6 Feb 2002 20:49:08 -0500 From: Chris Faulhaber To: biometrix Cc: audit@freebsd.org Subject: Re: tmpfile() libc call causes buffer overflow? Message-ID: <20020207014908.GA88916@peitho.fxp.org> References: <20020207010159.EFLX12982.out008.verizon.net@there> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="/9DWx/yDrRhgMJTb" Content-Disposition: inline In-Reply-To: <20020207010159.EFLX12982.out008.verizon.net@there> User-Agent: Mutt/1.3.24i Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --/9DWx/yDrRhgMJTb Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, Feb 05, 2002 at 07:05:30PM +0000, biometrix wrote: > I found if I altered TMPDIR exported variable to an a long string (X50 "G= ")=20 > /usr/bin/pr would exit with a segmentation fault. >=20 > export TMPDIR=3D`perl -e 'print "G" x 50'` > bash-2.05# pr > Cannot defer diagnostic messages > Segmentation fault (core dumped) >=20 > The code executed just before the segmentation fault is : >=20 > if ((err =3D tmpfile()) =3D=3D NULL) { > (void)fputs("Cannot defer diagnosticm=20 > essages\n",stderr); > return(1); > } >=20 actually: =2E.. This GDB was configured as "i386-unknown-freebsd"... Core was generated by `pr'. Program terminated with signal 11, Segmentation fault. Reading symbols from /usr/lib/libc.so.4...done. Reading symbols from /usr/libexec/ld-elf.so.1...done. #0 0x280dac49 in __sfvwrite () from /usr/lib/libc.so.4 (gdb) bt #0 0x280dac49 in __sfvwrite () from /usr/lib/libc.so.4 #1 0x280c69ce in fputs () from /usr/lib/libc.so.4 #2 0x804a87d in usage () at pr.c:1562 #3 0x8048b69 in main (argc=3D1, argv=3D0xbfbffa84) at pr.c:133 (gdb)=20 __sfvwrite() dies when fed a NULL stream. This is triggered by pr(1) attempting to use fputs() with an invalid stream caused by tmpfile() failing. It does not appear to be specific to a long TMPDIR but to any TMPDIR (i.e. any invalid directory) that will cause tmpfile() to fail. The fix to pr(1) is to explicitely set err =3D stderr before eventually calling usage(): Index: pr.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/usr.bin/pr/pr.c,v retrieving revision 1.9.2.1 diff -u -r1.9.2.1 pr.c --- usr.bin/pr/pr.c 4 Mar 2001 08:54:51 -0000 1.9.2.1 +++ usr.bin/pr/pr.c 7 Feb 2002 01:34:58 -0000 @@ -1588,6 +1588,7 @@ * defer diagnostics until processing is done */ if ((err =3D tmpfile()) =3D=3D NULL) { + err =3D stderr; (void)fputs("Cannot defer diagnostic messages\n",stderr); return(1); } The fix to __sfvwrite() is to ensure that fp !=3D NULL: Index: lib/libc/stdio/fvwrite.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/lib/libc/stdio/fvwrite.c,v retrieving revision 1.10 diff -u -r1.10 fvwrite.c --- lib/libc/stdio/fvwrite.c 28 Aug 1999 00:01:06 -0000 1.10 +++ lib/libc/stdio/fvwrite.c 7 Feb 2002 01:44:47 -0000 @@ -42,6 +42,7 @@ "$FreeBSD: src/lib/libc/stdio/fvwrite.c,v 1.10 1999/08/28 00:01:06 peter= Exp $"; #endif /* LIBC_SCCS and not lint */ =20 +#include #include #include #include @@ -68,6 +69,10 @@ =20 if ((len =3D uio->uio_resid) =3D=3D 0) return (0); + if (fp =3D=3D NULL) { + errno =3D EBADF; + return (EOF); + } /* make sure we can write */ if (cantwrite(fp)) return (EOF); >=20 > In : /usr/src/lib/libc/stdio/tmpfile.c there is a call for > "tmpdir =3D getenv("TMPDIR");" >=20 > so it returns a filename based on the enviroment variable "TMPDIR" so the= =20 > result of tmpfile() can be poisoned by altering TMPDIR ? >=20 Have you read tmpfile(3)? --=20 Chris D. Faulhaber - jedgar@fxp.org - jedgar@FreeBSD.org -------------------------------------------------------- FreeBSD: The Power To Serve - http://www.FreeBSD.org --/9DWx/yDrRhgMJTb Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (FreeBSD) Comment: FreeBSD: The Power To Serve iEYEARECAAYFAjxh3RMACgkQObaG4P6BelALpACffIyeBSudpkf73TIQ9CQUivko ybAAn0EVqlX/WV5nXl2+V1q9rZyS6xJR =nf14 -----END PGP SIGNATURE----- --/9DWx/yDrRhgMJTb-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message