Debian Bug report logs - #355810
coreutils: pwd fails on bind mount

version graph

Package: coreutils; Maintainer for coreutils is Michael Stone <mstone@debian.org>; Source for coreutils is src:coreutils.

Reported by: Kenshi Muto <kmuto@debian.org>

Date: Wed, 8 Mar 2006 01:48:04 UTC

Severity: important

Tags: upstream

Merged with 361398

Found in version coreutils/5.94-1

Fixed in version 5.96-1

Done: Michael Stone <mstone@debian.org>

Bug is archived. No further changes may be made.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Kenshi Muto <kmuto@debian.org>, Michael Stone <mstone@debian.org>:
Bug#355810; Package coreutils. Full text and rfc822 format available.

Acknowledgement sent to Kenshi Muto <kmuto@debian.org>:
New Bug report received and forwarded. Copy sent to Kenshi Muto <kmuto@debian.org>, Michael Stone <mstone@debian.org>. Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: Kenshi Muto <kmuto@debian.org>
To: Debian Bug Tracking System <submit@bugs.debian.org>
Subject: coreutils: pwd fails on bind mount
Date: Wed, 8 Mar 2006 10:29:15 +0900 (JST)
Package: coreutils
Version: 5.94-1
Severity: important

Hi,
I noticed pwd command always failed (at least on ARM) when current
directory was mounted as bind.

For example,
------------------
$ df
/home                 37610056  11959772  23739756  34% /chroot/d-i/home
$ grep d-i /etc/fstab
/home   /chroot/d-i/home none bind  0       0
proc    /chroot/d-i/proc proc defaults 0 0

$ dchroot -c d-i

chroot$ pwd
/home/kmuto
chroot$ /bin/pwd
/bin/pwd: couldn't find directory entry in `../..' with matching i-node

chroot$ cd /usr
chroot$ /bin/pwd
/usr

chroot$ cd /home/kmuto/d-i
chroot$ /bin/pwd
/bin/pwd: couldn't find directory entry in `../../..' with matching i-node
------------------

5.93-5 works.
This problem hits Makefile using $(shell pwd).

Thanks,
-- 
Kenshi Muto
kmuto@debian.org



Information forwarded to debian-bugs-dist@lists.debian.org, Michael Stone <mstone@debian.org>:
Bug#355810; Package coreutils. Full text and rfc822 format available.

Acknowledgement sent to Jim Meyering <jim@meyering.net>:
Extra info received and forwarded to list. Copy sent to Michael Stone <mstone@debian.org>. Full text and rfc822 format available.

Message #10 received at 355810@bugs.debian.org (full text, mbox):

From: Jim Meyering <jim@meyering.net>
To: Kenshi Muto <kmuto@debian.org>
Cc: 355810@bugs.debian.org
Subject: Re: Bug#355810: coreutils: pwd fails on bind mount
Date: Wed, 08 Mar 2006 08:59:55 +0100
Kenshi Muto <kmuto@debian.org> wrote:
> Package: coreutils
> Version: 5.94-1
> Severity: important
>
> Hi,
> I noticed pwd command always failed (at least on ARM) when current
> directory was mounted as bind.
>
> For example,
> ------------------
> $ df
> /home                 37610056  11959772  23739756  34% /chroot/d-i/home
> $ grep d-i /etc/fstab
> /home   /chroot/d-i/home none bind  0       0
> proc    /chroot/d-i/proc proc defaults 0 0
>
> $ dchroot -c d-i
>
> chroot$ pwd
> /home/kmuto
> chroot$ /bin/pwd
> /bin/pwd: couldn't find directory entry in `../..' with matching i-node
>
> chroot$ cd /usr
> chroot$ /bin/pwd
> /usr
>
> chroot$ cd /home/kmuto/d-i
> chroot$ /bin/pwd
> /bin/pwd: couldn't find directory entry in `../../..' with matching i-node
> ------------------

Thank you for reporting that.
So far, I am unable to reproduce the failure on ia32.

Would you please send the output of this command?

  ls -lid / /home /home/kmuto /home/kmuto/d-i

also, please run the failing command under strace, e.g.

  cd /home/kmuto/d-i
  strace -o /tmp/log /bin/pwd

and send the /tmp/log file.



Information forwarded to debian-bugs-dist@lists.debian.org, Michael Stone <mstone@debian.org>:
Bug#355810; Package coreutils. Full text and rfc822 format available.

Acknowledgement sent to Kenshi Muto <kmuto@debian.org>:
Extra info received and forwarded to list. Copy sent to Michael Stone <mstone@debian.org>. Full text and rfc822 format available.

Message #15 received at 355810@bugs.debian.org (full text, mbox):

From: Kenshi Muto <kmuto@debian.org>
To: 355810@bugs.debian.org
Subject: Re: Bug#355810: coreutils: pwd fails on bind mount
Date: Wed, 08 Mar 2006 17:10:01 +0900
[Message part 1 (text/plain, inline)]
At Wed, 08 Mar 2006 08:59:55 +0100,
Jim Meyering wrote:
> Kenshi Muto <kmuto@debian.org> wrote:
> So far, I am unable to reproduce the failure on ia32.
> 
> Would you please send the output of this command?

Sure!

>   ls -lid / /home /home/kmuto /home/kmuto/d-i

853397 drwxr-xr-x 20 root  root  4096 Mar 27  2005 /
688129 drwxrwsr-x  9 root  staff 4096 Mar 27  2005 /home
278530 drwxr-xr-x  8 kmuto kmuto 4096 Mar  8 01:05 /home/kmuto
409635 drwxr-xr-x  7 kmuto kmuto 4096 Oct 26 07:59 /home/kmuto/d-i

> also, please run the failing command under strace, e.g.
> 
>   cd /home/kmuto/d-i
>   strace -o /tmp/log /bin/pwd

$ strace -o /tmp/log /bin/pwd outputs following to stderr:
umovestr: Input/output error
umovestr: Input/output error
umovestr: Input/output error
umovestr: Input/output error
umovestr: Input/output error
umovestr: Input/output error
umovestr: Input/output error
umovestr: Input/output error
/bin/pwd: couldn't find directory entry in `../../..' with matching i-node

And I attached /tmp/log.

Thanks,
-- 
Kenshi Muto
kmuto@debian.org
[log.gz (application/octet-stream, attachment)]

Tags added: upstream Request was from Thomas Hood <jdthood@yahoo.co.uk> to control@bugs.debian.org. Full text and rfc822 format available.

Information forwarded to debian-bugs-dist@lists.debian.org, Michael Stone <mstone@debian.org>:
Bug#355810; Package coreutils. Full text and rfc822 format available.

Acknowledgement sent to Jim Meyering <jim@meyering.net>:
Extra info received and forwarded to list. Copy sent to Michael Stone <mstone@debian.org>. Full text and rfc822 format available.

Message #22 received at 355810@bugs.debian.org (full text, mbox):

From: Jim Meyering <jim@meyering.net>
To: Kenshi Muto <kmuto@debian.org>
Cc: 355810@bugs.debian.org, bug-coreutils@gnu.org, bug-gnulib@gnu.org
Subject: Re: Bug#355810: coreutils: pwd fails on bind mount
Date: Sun, 19 Mar 2006 20:38:58 +0100
Kenshi Muto <kmuto@debian.org> wrote:
> At Wed, 08 Mar 2006 08:59:55 +0100,
> Jim Meyering wrote:
>> Kenshi Muto <kmuto@debian.org> wrote:
>> So far, I am unable to reproduce the failure on ia32.
...
>> also, please run the failing command under strace, e.g.
>>
>>   cd /home/kmuto/d-i
>>   strace -o /tmp/log /bin/pwd
>
> $ strace -o /tmp/log /bin/pwd outputs following to stderr:
> umovestr: Input/output error
...
> /bin/pwd: couldn't find directory entry in `../../..' with matching i-node

Thanks.

Your strace log showed that /bin/pwd was not calling getcwd.
Yet when I build coreutils-5.94 myself on leisner.debian.org
and try the same experiment, that binary does call getcwd, and
works just fine,

  leisner$ dchroot unstable /home/meyering/coreutils-5.94/src/pwd
  Executing pwd in chroot: /org/leisner.debian.org/chroot/sid
  /home/meyering
  leisner$ dchroot unstable /bin/pwd
  Executing pwd in chroot: /org/leisner.debian.org/chroot/sid
  pwd: couldn't find directory entry in `../..' with matching i-node
  [Exit 1]

I suspect that the arm binary was built against an older version of
libc -- one that made coreutils use its getcwd.c replacement.
I confirmed the theory by forcing coreutils to use the replacement getcwd:

  gl_cv_func_getcwd_null=no gl_cv_func_getcwd_path_max=no ./configure

Then the resulting binary fails (in leisner's chroot), just as
in the example above.

Debugging that failure, I found the source of the problem: a subtle flaw
in lib/getcwd.c (which is based on glibc's sysdeps/posix/getcwd.c).
See the comments in the patch for details.
(fyi, it looks big, but most of it is due to an indentation change)

Technically, this is grounds for changing m4/getcwd.m4 to detect
the deficiency in glibc's getcwd, but performing the actual test
would be tricky, to say the least, and the replacement would be
of only marginal value, since it'd come into play only in a chroot
when the working directory name is too long for the getcwd syscall
to work.  So I won't bother right now.

I've applied the following only in coreutils, for starters:

2006-03-19  Jim Meyering  <jim@meyering.net>

	Work even in a chroot where d_ino values for entries in "/"
	don't match the stat.st_ino values for the same names.
	* getcwd.c (__getcwd): When no d_ino value matches the target inode
	number, iterate through all entries again, using lstat instead.
	Reported by Kenshi Muto in http://bugs.debian.org/355810.

Index: lib/getcwd.c
===================================================================
RCS file: /fetish/cu/lib/getcwd.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -p -u -r1.19 -r1.20
--- lib/getcwd.c	19 Mar 2006 17:18:32 -0000	1.19
+++ lib/getcwd.c	19 Mar 2006 18:27:51 -0000	1.20
@@ -211,6 +211,7 @@ __getcwd (char *buf, size_t size)
       int parent_status;
       size_t dirroom;
       size_t namlen;
+      bool use_d_ino = true;
 
       /* Look at the parent directory.  */
 #ifdef AT_FDCWD
@@ -257,6 +258,21 @@ __getcwd (char *buf, size_t size)
 	     NULL.  */
 	  __set_errno (0);
 	  d = __readdir (dirstream);
+
+	  /* When we've iterated through all directory entries without finding
+	     one with a matching d_ino, rewind the stream and consider each
+	     name again, but this time, using lstat.  This is necessary in a
+	     chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
+	     .., ../.., ../../.., etc. all had the same device number, yet the
+	     d_ino values for entries in / did not match those obtained
+	     via lstat.  */
+	  if (d == NULL && errno == 0 && use_d_ino)
+	    {
+	      use_d_ino = false;
+	      rewinddir (dirstream);
+	      d = __readdir (dirstream);
+	    }
+
 	  if (d == NULL)
 	    {
 	      if (errno == 0)
@@ -269,58 +285,65 @@ __getcwd (char *buf, size_t size)
 	      (d->d_name[1] == '\0' ||
 	       (d->d_name[1] == '.' && d->d_name[2] == '\0')))
 	    continue;
-	  if (MATCHING_INO (d, thisino) || mount_point)
+
+	  if (use_d_ino)
 	    {
-	      int entry_status;
+	      bool match = (MATCHING_INO (d, thisino) || mount_point);
+	      if (! match)
+		continue;
+	    }
+
+	  {
+	    int entry_status;
 #ifdef AT_FDCWD
-	      entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
+	    entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
 #else
-	      /* Compute size needed for this file name, or for the file
-		 name ".." in the same directory, whichever is larger.
-	         Room for ".." might be needed the next time through
-		 the outer loop.  */
-	      size_t name_alloc = _D_ALLOC_NAMLEN (d);
-	      size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
-
-	      if (filesize < dotlen)
-		goto memory_exhausted;
-
-	      if (dotsize < filesize)
-		{
-		  /* My, what a deep directory tree you have, Grandma.  */
-		  size_t newsize = MAX (filesize, dotsize * 2);
-		  size_t i;
-		  if (newsize < dotsize)
-		    goto memory_exhausted;
-		  if (dotlist != dots)
-		    free (dotlist);
-		  dotlist = malloc (newsize);
-		  if (dotlist == NULL)
-		    goto lose;
-		  dotsize = newsize;
-
-		  i = 0;
-		  do
-		    {
-		      dotlist[i++] = '.';
-		      dotlist[i++] = '.';
-		      dotlist[i++] = '/';
-		    }
-		  while (i < dotlen);
-		}
-
-	      memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
-	      entry_status = __lstat (dotlist, &st);
-#endif
-	      /* We don't fail here if we cannot stat() a directory entry.
-		 This can happen when (network) file systems fail.  If this
-		 entry is in fact the one we are looking for we will find
-		 out soon as we reach the end of the directory without
-		 having found anything.  */
-	      if (entry_status == 0 && S_ISDIR (st.st_mode)
-		  && st.st_dev == thisdev && st.st_ino == thisino)
-		break;
-	    }
+	    /* Compute size needed for this file name, or for the file
+	       name ".." in the same directory, whichever is larger.
+	       Room for ".." might be needed the next time through
+	       the outer loop.  */
+	    size_t name_alloc = _D_ALLOC_NAMLEN (d);
+	    size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
+
+	    if (filesize < dotlen)
+	      goto memory_exhausted;
+
+	    if (dotsize < filesize)
+	      {
+		/* My, what a deep directory tree you have, Grandma.  */
+		size_t newsize = MAX (filesize, dotsize * 2);
+		size_t i;
+		if (newsize < dotsize)
+		  goto memory_exhausted;
+		if (dotlist != dots)
+		  free (dotlist);
+		dotlist = malloc (newsize);
+		if (dotlist == NULL)
+		  goto lose;
+		dotsize = newsize;
+
+		i = 0;
+		do
+		  {
+		    dotlist[i++] = '.';
+		    dotlist[i++] = '.';
+		    dotlist[i++] = '/';
+		  }
+		while (i < dotlen);
+	      }
+
+	    memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
+	    entry_status = __lstat (dotlist, &st);
+#endif
+	    /* We don't fail here if we cannot stat() a directory entry.
+	       This can happen when (network) file systems fail.  If this
+	       entry is in fact the one we are looking for we will find
+	       out soon as we reach the end of the directory without
+	       having found anything.  */
+	    if (entry_status == 0 && S_ISDIR (st.st_mode)
+		&& st.st_dev == thisdev && st.st_ino == thisino)
+	      break;
+	  }
 	}
 
       dirroom = dirp - dir;



Merged 355810 361398. Request was from Filippo Giunchedi <filippo@esaurito.net> to control@bugs.debian.org. Full text and rfc822 format available.

Reply sent to Michael Stone <mstone@debian.org>:
You have taken responsibility. Full text and rfc822 format available.

Notification sent to Kenshi Muto <kmuto@debian.org>:
Bug acknowledged by developer. Full text and rfc822 format available.

Message #29 received at 355810-close@bugs.debian.org (full text, mbox):

From: Michael Stone <mstone@debian.org>
To: 355810-close@bugs.debian.org
Subject: Re: pwd fails on bind mount
Date: Sat, 27 May 2006 09:35:51 -0400
Version: 5.96-1

Should be fixed in current version.



Reply sent to Michael Stone <mstone@debian.org>:
You have taken responsibility. Full text and rfc822 format available.

Notification sent to Filippo Giunchedi <filippo@debian.org>:
Bug acknowledged by developer. Full text and rfc822 format available.

Bug archived. Request was from Debbugs Internal Request <owner@bugs.debian.org> to internal_control@bugs.debian.org. (Sun, 24 Jun 2007 14:01:59 GMT) Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Mon Apr 21 13:28:28 2014; Machine Name: beach.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.