>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"

Reply via email to