[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freebsd-bugs
Subject:    bin/51535: uthreads bug: new opened files may get stale fcntl flags
From:       Enache Adrian <enache () rdslink ! ro>
Date:       2003-04-29 1:37:18
[Download RAW message or body]


> 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:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscribe@freebsd.org"


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic