Date: Sat, 31 Jul 2010 15:06:16 GMT From: pluknet <pluknet@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/149152: [patch] BSD grep loops with EISDIR trying to read a directory Message-ID: <201007311506.o6VF6G0J000769@www.freebsd.org> Resent-Message-ID: <201007311510.o6VFA4fV098555@freefall.freebsd.org>
index | next in thread | raw e-mail
>Number: 149152
>Category: bin
>Synopsis: [patch] BSD grep loops with EISDIR trying to read a directory
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Jul 31 15:10:04 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator: pluknet
>Release: HEAD r210642
>Organization:
>Environment:
FreeBSD foo 9.0-CURRENT FreeBSD 9.0-CURRENT #36: Fri Jul 23 10:30:36 UTC 2010 root@foo:/usr/obj/usr/src/sys/GENERIC amd64
>Description:
BSD grep used in -CURRENT loops when it gets a directory
as a file argument for grepping.
grep open()'s a dir, stat()'s that dir, and do a read() on that dir
in an endless loop. It seems that grep has no enough error handling.
>How-To-Repeat:
Loop easily reproducible. Try this (on -CURRENT sources):
grep IP_FW_GET /sys/netinet/ipfw*; or
grep IP_FW_GET /sys/netinet/ip*; or
grep IP_FW_GET /sys/netinet/*
That will produce something like this:
[...]
41740 grep CALL stat(0x7fffffffe6d4,0x7fffffffda50)
41740 grep NAMI "/sys/netinet/ipfw"
41740 grep STRU struct stat {dev=67174149, ino=47296976,
mode=drwxr-xr-x , nlink=4, uid=0, gid=0, rdev=94607662,
atime=1276302257, stime=1279007706, ctime=1279007706, birthtime=-1,
size=1024, blksize=4096, blocks=4, flags=0x0 }
41740 grep RET stat 0
41740 grep CALL open(0x7fffffffe6d4,O_RDONLY,<unused>0x1b6)
41740 grep NAMI "/sys/netinet/ipfw"
41740 grep RET open 3
41740 grep CALL stat(0x507300,0x7fffffffd860)
41740 grep NAMI "/sys/netinet/ipfw"
41740 grep STRU struct stat {dev=67174149, ino=47296976,
mode=drwxr-xr-x , nlink=4, uid=0, gid=0, rdev=94607662,
atime=1276302257, stime=1279007706, ctime=1279007706, birthtime=-1,
size=1024, blksize=4096, blocks=4, flags=0x0 }
41740 grep RET stat 0
41740 grep CALL fstat(0x3,0x7fffffffd730)
41740 grep STRU struct stat {dev=67174149, ino=47296976,
mode=drwxr-xr-x , nlink=4, uid=0, gid=0, rdev=94607662,
atime=1276302257, stime=1279007706, ctime=1279007706, birthtime=-1,
size=1024, blksize=4096, blocks=4, flags=0x0 }
41740 grep RET fstat 0
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
41740 grep RET read -1 errno 21 Is a directory
41740 grep CALL read(0x3,0x800c38000,0x1000)
[...]
>Fix:
This is a sort of concept to demonstrate a possible way
to handle around the issue.
Patch attached with submission follows:
Index: file.c
===================================================================
--- file.c (revision 210642)
+++ file.c (working copy)
@@ -164,9 +164,12 @@
lnbuflen *= 2;
lnbuf = grep_realloc(lnbuf, ++lnbuflen);
}
- if ((ch == '\n') || (ch == EOF)) {
+ if ((ch == '\n') || (ch == EOF && errno != EISDIR)) {
lnbuf[i] = '\0';
break;
+ } else if (ch == EOF && errno == EISDIR) {
+ lnbuf[i] = '\0';
+ return (NULL); /* XXX unclear why '\0' doesn't work */
} else
lnbuf[i] = ch;
}
>Release-Note:
>Audit-Trail:
>Unformatted:
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007311506.o6VF6G0J000769>
