NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/51119: /bin/sh consumes fds when refusing to source an ELF binary (+FIX)



>Number:         51119
>Category:       bin
>Synopsis:       /bin/sh consumes fds when refusing to source an ELF binary (+FIX)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 06 21:45:00 +0000 2016
>Originator:     Robert Elz
>Release:        NetBSD 7.99.26 (all of NetBSD 5 6 7 & current to date)
>Organization:
>Environment:
System: NetBSD andromeda.noi.kre.to 7.99.26 NetBSD 7.99.26 (VBOX64-1.1-20160128) #43: Thu Jan 28 16:09:08 ICT 2016 kre%onyx.coe.psu.ac.th@localhost:/usr/obj/current/kernels/amd64/VBOX64 amd64
Architecture: x86_64
Machine: amd64
>Description:
	Before reading a file, sh reads the first few bytes, to
	determine if it is a binary (ELF, not just a binary file)
	and if so, refuses to treat it as commands.

	That's fine, but when it happens, the fd used is never closed.
	Do it often enough, and your shell will have no fd's left.

	It has been like this since this check was added in Feb 2007
	(which means in all currently supported shells, plus NetBSD 5.)

>How-To-Repeat:
	andromeda$ /bin/sh	# this is a NetBSD 7.0_BETA /bin/sh
	$ . /bin/sh
	.: Cannot execute ELF binary /bin/sh
	$ fstat -p $$
	USER     CMD          PID   FD MOUNT       INUM MODE         SZ|DV R/W
	kre      sh         25400   wd /home    4192948 drwxrwxr-x    2560 r 
	kre      sh         25400    0 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    1 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    2 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    3 /          10338 -r-xr-xr-x  175372 r 
	kre      sh         25400 1023 /          10428 crw-rw-rw-     tty rw
	$ . /bin/sh
	.: Cannot execute ELF binary /bin/sh
	$ fstat -p $$
	USER     CMD          PID   FD MOUNT       INUM MODE         SZ|DV R/W
	kre      sh         25400   wd /home    4192948 drwxrwxr-x    2560 r 
	kre      sh         25400    0 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    1 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    2 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    3 /          10338 -r-xr-xr-x  175372 r 
	kre      sh         25400    4 /          10338 -r-xr-xr-x  175372 r 
	kre      sh         25400 1023 /          10428 crw-rw-rw-     tty rw
	$ . /bin/sh
	.: Cannot execute ELF binary /bin/sh
	$ fstat -p $$
	USER     CMD          PID   FD MOUNT       INUM MODE         SZ|DV R/W
	kre      sh         25400   wd /home    4192948 drwxrwxr-x    2560 r 
	kre      sh         25400    0 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    1 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    2 /dev/pts      31 crwx-w----  pts/14 rw
	kre      sh         25400    3 /          10338 -r-xr-xr-x  175372 r 
	kre      sh         25400    4 /          10338 -r-xr-xr-x  175372 r 
	kre      sh         25400    5 /          10338 -r-xr-xr-x  175372 r 
	kre      sh         25400 1023 /          10428 crw-rw-rw-     tty rw

	Notice fd's 3, then 4, then 5, just sitting there, all the same file:

	$ ls -li /bin/sh
	10338 -r-xr-xr-x  1 root  wheel  175372 Dec 11  2014 /bin/sh

	Note (from reading the source) that the same thing would happen
	if (for some reason) it proved impossible to rewind the file.
	(I do not currently know how to provoke that one though.)

>Fix:
	As a workaround, if this has happened, it is possible to just
	use fstat (as above) then
		exec 3>&-
		exec 4>&-
	(etc) for any fd's the shell should not have open. (Don't close
	the tty shown here on fd 1023 - especially in current sh's the
	fds used for the controlling tty, and for reading files are likely
	to be close together, and biggish numbers, so it would be easy to
	mistakenly close the tty - that would do bad things to job control.)

	Better, apply this patch, which will appear in current soon...
	(in this form, or something very similar).

Index: input.c
===================================================================
RCS file: /cvsroot/src/bin/sh/input.c,v
retrieving revision 1.49
diff -u -r1.49 input.c
--- input.c	2 May 2016 01:46:31 -0000	1.49
+++ input.c	6 May 2016 21:38:01 -0000
@@ -404,11 +404,15 @@
 	 */
 	if (lseek(fd, 0, SEEK_SET) == 0) {
 		if (read(fd, magic, 4) == 4) {
-			if (memcmp(magic, "\177ELF", 4) == 0)
+			if (memcmp(magic, "\177ELF", 4) == 0) {
+				(void)close(fd);
 				error("Cannot execute ELF binary %s", fname);
+			}
 		}
-		if (lseek(fd, 0, SEEK_SET) != 0)
+		if (lseek(fd, 0, SEEK_SET) != 0) {
+			(void)close(fd);
 			error("Cannot rewind the file %s", fname);
+		}
 	}
 
 	fd2 = to_upper_fd(fd);	/* closes fd, returns higher equiv */



Home | Main Index | Thread Index | Old Index