Thread (24 messages) 24 messages, 3 authors, 2025-02-20

Re: [PATCH v2] man/man3/getcwd.3: say more clear that syscall can return "(unreachable)", but modern glibc wrapper cannot

From: Alejandro Colomar <alx@kernel.org>
Date: 2025-02-16 10:00:13

Hi Askar, Carlos,

On Sun, Feb 16, 2025 at 06:18:28AM +0000, Askar Safin wrote:
I verified using expirement that modern glibc wrapper getcwd actually never returns "(unreachable)".
Also I have read modern glibc sources for all 3 functions documented here.
All they don't return "(unreachable)".
Also I changed "pathname" to "pathnames".

Now let me describe my expirement. I compiled this C source:

===
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>

int
main (void)
{
  char buf[1000];
  if(syscall(SYS_getcwd, buf, sizeof(buf)) == -1)
    {
      perror ("SYS_getcwd");
    }
  else
    {
      printf ("SYS_getcwd: %s\n", buf);
    }
  if(getcwd(buf, sizeof(buf)) == NULL)
    {
      perror ("getcwd");
    }
  else
    {
      printf ("getcwd: %s\n", buf);
    }
  return 0;
}
===

to a binary /tmp/a and run the following command:

$ sudo unshare --mount bash -c 'set -e; mkdir /tmp/dir; mount -t tmpfs tmpfs /tmp/dir; cd /tmp/dir; umount -l .; /tmp/a'

The output was:

SYS_getcwd: (unreachable)/
getcwd: No such file or directory
Thanks!  I prefer if we show a continuous shell session, which is easier
to follow than code mixed with explanations.  So I would add the
following (and indented, to show it's code; that also makes it easier to
keep the #include lines in git(1)):

	alx@devuan:~/tmp$ cat getcwd.c;
	#include <unistd.h>
	#include <stdio.h>
	#include <sys/syscall.h>

	int
	main(void)
	{
		char  buf[1000];

		if (syscall(SYS_getcwd, buf, sizeof(buf)) == -1)
			perror("SYS_getcwd");
		else
			printf("SYS_getcwd: %s\n", buf);

		if (getcwd(buf, sizeof(buf)) == NULL)
			perror("getcwd");
		else
			printf("getcwd: %s\n", buf);

		return 0;
	}
	alx@devuan:~/tmp$ gcc -Wall -Wextra -o /tmp/getcwd getcwd.c;
	alx@devuan:~/tmp$ sudo unshare --mount bash;
	root@devuan:/home/alx/tmp# set -e;
	root@devuan:/home/alx/tmp# mkdir /tmp/dir;
	root@devuan:/home/alx/tmp# mount -t tmpfs tmpfd /tmp/dir/;
	root@devuan:/home/alx/tmp# cd /tmp/dir/;
	root@devuan:/tmp/dir# umount -l .;
	root@devuan:/tmp/dir# /tmp/getcwd;
	SYS_getcwd: (unreachable)/
	getcwd: No such file or directory
	root@devuan:/tmp/dir# exit;
	exit

I have also adapted the example program to the C coding style of the
project:
<https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/CONTRIBUTING.d/style/c>
Signed-off-by: Askar Safin <redacted>
Please add a line for Carlos:

	Cc: Carlos O'Donell [off-list ref]
quoted hunk ↗ jump to hunk
---

Changes since v1:
- I added that old glibc versions are buggy, too
- Added sources for my expirement to commit message (and did small tweaks to commit message)

 man/man3/getcwd.3 | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/man/man3/getcwd.3 b/man/man3/getcwd.3
index 685585a60..97e3c766f 100644
--- a/man/man3/getcwd.3
+++ b/man/man3/getcwd.3
@@ -245,8 +245,11 @@ process (e.g., because the process set a new filesystem root using
 without changing its current directory into the new root).
 Such behavior can also be caused by an unprivileged user by changing
 the current directory into another mount namespace.
-When dealing with pathname from untrusted sources, callers of the
-functions described in this page
+When dealing with pathnames from untrusted sources, callers of the
As Carlos said, I prefer if this patch doesn't include the change
s/pathname/&s/.  That would reduce the diff.

Thanks for the help with this, Carlos!
+functions described in this page (until glibc 2.27)
+or raw
I think it would be more appropriate to say 's/or raw/or the raw/'.
+.BR getcwd ()
+system call
Other than those minor comments, I think this LGTM.  Please address
those, and I'll take the patch.

Carlos do you have any further comments?


Have a lovely day!
Alex
 should consider checking whether the returned pathname starts
 with '/' or '(' to avoid misinterpreting an unreachable path
 as a relative pathname.
-- 
2.39.5
-- 
<https://www.alejandro-colomar.es/>

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help