[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