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