Subject: bug#10305: coreutils-8.14, "rm -r" fails with EBADF

From: "Joachim Schmitz" <[email-masked]>
Date: Fri, 16 Dec 2011 11:28:43 +0100

> From: Paul Eggert [mailto:[email-masked]]
> Sent: Thursday, December 15, 2011 7:07 PM
> To: Joachim Schmitz
> Cc: Jim Meyering; [email-masked]; [email-masked]
> Subject: Re: coreutils-8.14, "rm -r" fails with EBADF
> 
> On 12/15/11 08:28, Jim Meyering wrote:
> > If you can debug it further to narrow down what/how it is failing,
> > eventually we'll find the cause.
> 
> One way to do that might be to put a breakpoint on all the following
functions,
> and to let us know what their arguments are when called, and what they
> return.  You also might try to compile coreutils with debugging turned
off, so
> that functions aren't inlined.

I guess you meant turn of optimization rather than debugging?

> diropen
> fts_build
> fts_safe_changedir
> restore_initial_cwd
> fchdir
> cwd_advance_fd

OK here we go:
jojo@\hpitug:/home/jojo/Floss/coreutils-8.14/src $ run -debug -inspect=on
./rm -r /tmp/foo

TNS/E Native Inspect gdb Debugger [T1237 - 30-Jun-2010 17:53]
Copyright 1998 Free Software Foundation, Inc.
Copyright 2003-2008 Hewlett-Packard Development Company, L.P.

Native Inspect (based on GDB) is covered by the GNU General Public License.
Type "show copying" for conditions for changing and/or distributing copies.
Type "show warranty" for warranty/support information.

Working directory \HPITUG.$DATA01.JOJO.
Symbols read in for program loadfile /usr/local/Floss/coreutils-8.14/src/rm.
Added process (1,808).
Breakpoint 1 at 0x7000fcb0:1: file /usr/local/Floss/coreutils-8.14/src/rm.c,
line 206.
main (argc=3, argv=0x80ca000) at
/usr/local/Floss/coreutils-8.14/src/rm.c:206
*  206        bool preserve_root = true;
(eInspect 1,808):break
Breakpoint 2 at 0x7000fcb0:1: file /usr/local/Floss/coreutils-8.14/src/rm.c,
line 206.
(eInspect 1,808):clear
invalid command name "clear"
(eInspect 1,808):break 2
warning:  Line 2 in file "/usr/local/Floss/coreutils-8.14/src/rm.c" does not
have
instructions.
Placing breakpoint on the next available source line.
Breakpoint 3 at 0x7000e9c0:0: file /usr/local/Floss/coreutils-8.14/src/rm.c,
line 105.
(eInspect 1,808):exit
There are held processes that will be resumed.  Exit anyway? (y or n) y

There are existing Breakpoints.  Exit anyway? (y or n) y
eInspect is exiting...
./rm: traversal failed: `/tmp/foo': Bad file descriptor
jojo@\hpitug:/home/jojo/Floss/coreutils-8.14/src $ run -debug -inspect=on
./rm -r /tmp/foo

TNS/E Native Inspect gdb Debugger [T1237 - 30-Jun-2010 17:53]
Copyright 1998 Free Software Foundation, Inc.
Copyright 2003-2008 Hewlett-Packard Development Company, L.P.

Native Inspect (based on GDB) is covered by the GNU General Public License.
Type "show copying" for conditions for changing and/or distributing copies.
Type "show warranty" for warranty/support information.

Working directory \HPITUG.$DATA01.JOJO.
Symbols read in for program loadfile /usr/local/Floss/coreutils-8.14/src/rm.
Added process (1,317).
Breakpoint 1 at 0x7000fcb0:1: file /usr/local/Floss/coreutils-8.14/src/rm.c,
line 206.
main (argc=3, argv=0x80ca000) at
/usr/local/Floss/coreutils-8.14/src/rm.c:206
*  206        bool preserve_root = true;
(eInspect 1,317):break diropen
Breakpoint 2 at 0x7002f1a0:1: file
/usr/local/Floss/coreutils-8.14/lib/fts.c, line 360.
(eInspect 1,317):break fts_build
Breakpoint 3 at 0x70038af0:1: file
/usr/local/Floss/coreutils-8.14/lib/fts.c, line 1276.
(eInspect 1,317):break fts_safe_changedir
Breakpoint 4 at 0x7003ee80:1: file
/usr/local/Floss/coreutils-8.14/lib/fts.c, line 2009.
(eInspect 1,317):break restore_initial_cwd
Code location does not exist.

(eInspect 1,317):break fchdir
Breakpoint 5 at 0x7002cd30:2: file
/usr/local/Floss/coreutils-8.14/lib/fchdir.c, line 206.
(eInspect 1,317):break cwd_advance_fd
Breakpoint 6 at 0x70030f70:1: file
/usr/local/Floss/coreutils-8.14/lib/fts.c, line 331.
(eInspect 1,317):cont
Continuing.

Breakpoint 6, cwd_advance_fd (sp=0x80cee40, fd=-3041965,
chdir_down_one=true)
    at /usr/local/Floss/coreutils-8.14/lib/fts.c:331
*  331        int old = sp->fts_cwd_fd;
(eInspect 1,317):cont
Continuing.

Breakpoint 3, fts_build (sp=0x80cee40, type=3) at
    /usr/local/Floss/coreutils-8.14/lib/fts.c:1276
* 1276              FTSENT *cur = sp->fts_cur;
(eInspect 1,317):cont
Continuing.
./rm: traversal failed: `/tmp/foo': Bad file descriptor
Process (1,317) exited with code 01.
Removed process (1,317).
eInspect is exiting...
jojo@\hpitug:/home/jojo/Floss/coreutils-8.14/src $

so a) there is no restore_initial_cwd and b) it enters only cwd_advance_fd
and fts_build and both only once.

Stepping into fts_build shows that the dup(dir_fd) in line 1385 fails, with
errno being set to EBADF

* 1375              if (continue_readdir)
(eInspect 1,840):
* 1381              else if (nlinks || type == BREAD) {
(eInspect 1,840):
* 1382                      if (ISSET(FTS_CWDFD))
(eInspect 1,840):
* 1384                          dir_fd = dup (dir_fd);
(eInspect 1,840):p dir_fd
$3 = 3
(eInspect 1,840):next
* 1385                          if (0 <= dir_fd)
(eInspect 1,840):p dir_fd
$4 = -1
(eInspect 1,840):next
* 1388                      if (dir_fd < 0 || fts_safe_changedir(sp, cur,
dir_fd, NULL)) {
(eInspect 1,840):
* 1389                              if (nlinks && type == BREAD)
(eInspect 1,840):
* 1390                                      cur->fts_errno = errno;
(eInspect 1,840):
* 1391                              cur->fts_flags |= FTS_DONTCHDIR;
(eInspect 1,840):p cur->fts_errno
$5 = 4009
(eInspect 1,840):

So... it seems we can't dup() an fd for a directory here!

Bye, Jojo