NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/40319: fts_close() spuriously closes fd 0
>Number: 40319
>Category: lib
>Synopsis: fts_close() spuriously closes fd 0
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jan 03 00:50:00 +0000 2009
>Originator: Ben Harris
>Release: 4.0.1
>Organization:
>Environment:
NetBSD aquila.bjh21.me.uk 5.0_BETA NetBSD 5.0_BETA (GENERIC.MP) #0: Wed Dec 31
03:56:29 UTC 2008
builds%b6.netbsd.org@localhost:/home/builds/ab/netbsd-5/sparc64/200812300000Z-obj/home/builds/ab/netbsd-5/src/sys/arch/sparc64/compile/GENERIC.MP
sparc64
>Description:
NB: problem system is running a 4.0.1 userland on a 5.0_BETA kernel. I
don't think this matters, though.
The problem is a simple one: if fts_open() is called with an "options"
argument that includes FTS_LOGICAL, then an immediate call of fts_close()
will close file descriptor 0 (standard input).
>How-To-Repeat:
Compile and run this program:
#include <sys/stat.h>
#include <err.h>
#include <fts.h>
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char **argv)
{
FTS *ftsp;
char *path_argv[2];
struct stat st;
path_argv[0] = "/";
path_argv[1] = NULL;
if ((ftsp = fts_open(path_argv, FTS_LOGICAL, NULL)) == NULL)
err(1, "fts_open");
if (fts_close(ftsp) != 0) err(1, "fts_close");
if (fstat(STDIN_FILENO, &st) != 0) err(1, "stdin");
return 0;
}
On my system, this happens:
aquila:~$ cc -o fts_close_bug{,.c}
aquila:~$ ./fts_close_bug
fts_close_bug: stdin: Bad file descriptor
>Fix:
I think the problem lies in the use of ISSET(FTS_SYMFOLLOW) in fts.c.
ISSET tests the fts_options field, but the FTS_SYMFOLLOW flag is in
fts_flags. The value of FTS_SYMFOLLOW is the same as that of FTS_LOGICAL,
so if the latter is set, fts_close treats fts_cur->fts_symfd as being valid and
closes it, hence causing the problem. The obvious fix is as follows,
but I don't know the fts code at all well and I've not tested this since
I don't yet have a running -current system to test it on.
--- fts.c 02 Jan 2009 16:24:24 +0000 1.34
+++ fts.c 03 Jan 2009 00:43:27 +0000
@@ -256,7 +256,7 @@
* list which has a valid parent pointer.
*/
if (sp->fts_cur) {
- if (ISSET(FTS_SYMFOLLOW))
+ if (sp->fts_cur->fts_flags & FTS_SYMFOLLOW)
(void)close(sp->fts_cur->fts_symfd);
for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
freep = p;
Home |
Main Index |
Thread Index |
Old Index