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>
index | next in thread | raw e-mail
>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:
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030429013718.GA14503>
