Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Apr 2003 04:37:18 +0300
From:      Enache Adrian <enache@rdslink.ro>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/51535: uthreads bug: new opened files may get stale fcntl flags
Message-ID:  <20030429013718.GA14503@ratsnest.hole>
Resent-Message-ID: <200304290140.h3T1eDVo099987@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         51535
>Category:       bin
>Synopsis:       uthreads bug: new opened files may get stale fcntl flags
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 28 18:40:13 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Enache Adrian
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
none
>Environment:
System: FreeBSD ratsnest.hole 5.0-CURRENT FreeBSD 5.0-CURRENT #2: Tue Apr 15 15:15:34 EEST 2003 root@ratsnest.hole:/opt/tmp/CUBATAO i386

>Description:
	
In programs linked against libc_r:
- dup2'ing another file to one of the standard file descriptors
- doing his job with it and then closing it
- opening another file ( which will re-use the same fd )

will cause the latter to "inherit" the closed file's fcntl flags.

That defeats anyone trying to play with redirecting stdout to a
(write-only opened) file - the only "solution" is to leave it
open, if not you he not be able to read from any file after that.

Perl for instance does a lot of things like that: this bug seems to
be the cause why recent threaded builds on FreeBSD fail miserably.

It's probably caused by the code in _thread_fd_table_init()
(uthread/uthread_fd.c:127)

                        if ((fd < 3) && (_pthread_stdio_flags[fd] != -1))
                                /*
                                 * Use the stdio flags read by
                                 * _pthread_init() to avoid
                                 * mistaking the non-blocking
                                 * flag that, when set on one
                                 * stdio fd, is set on all stdio
                                 * fds.
                                 */
                                entry->flags = _pthread_stdio_flags[fd];

I'm using a very recent -CURRENT.
There are rumors that this bug is present also in FreeBSD 4.8, NetBSD 1.6
and recent OpenBSD, but I have no possibility to verify it.

>How-To-Repeat:
	
compile the following test program with -lc_r or -pthread and run it:

----------------------------------------------------------------------
#include <unistd.h>
#include <fcntl.h>

int main(int argc,char **argv)
{
	int fd,cnt;
	char buf[12] = "hallo baby!";
	if (!argv[1])
		errx(1,"usage: %s file",argv[0]);

	if ((fd = open(argv[1],O_WRONLY)) == -1)
		err(1,"open");

	if ((cnt = dup2(fd,1)) == -1)
		err(1,"dup2");

	if ((cnt = write(1,buf,12)) == -1)
		err(1,"write");

	if (close(1) == -1)
		err(1,"close");

	if ((fd = open(argv[1],O_RDONLY)) == -1)
		err(1,"open");

	if ((cnt = read(fd,buf,12)) == -1)
		err(1,"read");
	else
		warnx("read: %s", buf);
	return 0;
}
----------------------------------------------------------------------

$ cc -lc_r test.c -o test
$ ./test a
test: read: Bad file descriptor

>Fix:

Applying this patch definitely fixes it on my box:

----------------------------------------------------------------------
diff -rup /arc/freebsd/src/lib/libc_r/uthread/uthread_close.c ./uthread/uthread_close.c
--- /arc/freebsd/src/lib/libc_r/uthread/uthread_close.c	Sat Oct 26 08:22:30 2002
+++ ./uthread/uthread_close.c	Tue Apr 29 01:26:54 2003
@@ -96,6 +96,10 @@ _close(int fd)
 		_thread_fd_table[fd] = NULL;
 		free(entry);
 
+		/* drop stale pthread stdio flags */
+		if (fd < 3)
+			_pthread_stdio_flags[fd] = -1;
+
 		/* Close the file descriptor: */
 		ret = __sys_close(fd);
 	}
----------------------------------------------------------------------
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030429013718.GA14503>