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 Signed-off-by: Askar Safin <safinaskar@xxxxxxxxxxxx> --- 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 +functions described in this page (until glibc 2.27) +or raw +.BR getcwd () +system call should consider checking whether the returned pathname starts with '/' or '(' to avoid misinterpreting an unreachable path as a relative pathname. -- 2.39.5