This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/18203] New: realpath() does not handle unreachable paths correctly
- From: "jannhorn at googlemail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Sun, 05 Apr 2015 16:05:32 +0000
- Subject: [Bug libc/18203] New: realpath() does not handle unreachable paths correctly
- Auto-submitted: auto-generated
https://sourceware.org/bugzilla/show_bug.cgi?id=18203
Bug ID: 18203
Summary: realpath() does not handle unreachable paths correctly
Product: glibc
Version: 2.19
Status: NEW
Severity: normal
Priority: P2
Component: libc
Assignee: unassigned at sourceware dot org
Reporter: jannhorn at googlemail dot com
CC: drepper.fsp at gmail dot com
On Linux, getcwd(2) can succeed without returning an absolute path. I just
documented that in a man-pages patch I sent to the man-pages ML and maintainer,
a copy is at
<http://var.thejh.net/0001-getcwd.3-behavior-for-unreachable-cwd.patch>. This
behavior causes realpath to behave inconsistently when dealing with unreachable
paths:
$ cat getcwd.c
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main(void) {
unshare(CLONE_NEWUSER | CLONE_NEWNS);
chdir("/usr");
chroot("bin");
printf("current directory: \"%s\"\n", get_current_dir_name());
char *real = realpath(".", NULL);
printf("realpath of .: \"%s\"\n", real ? real : "{none}");
real = realpath("../home/jann/.ssh", NULL);
printf("realpath of path: \"%s\"\n", real ? real : "{none}");
return 0;
}
$ gcc -o getcwd getcwd.c
$ ./getcwd
current directory: "(unreachable)/usr"
realpath of .: "(unreachable)/usr"
realpath of path: "{none}"
$ strace ./getcwd
[...]
unshare(CLONE_NEWNS|CLONE_NEWUSER) = 0
chdir("/usr") = 0
chroot("bin") = 0
stat(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/media/wdgreen/home/jann/tmp", 0x7fff685a5af0) = -1 ENOENT (No such file
or directory)
brk(0) = 0x7c6000
brk(0x7e8000) = 0x7e8000
getcwd("(unreachable)/usr", 4096) = 18
brk(0x7e7000) = 0x7e7000
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7f58a5941000
write(1, "current directory: \"(unreachable"..., 39current directory:
"(unreachable)/usr"
) = 39
getcwd("(unreachable)/usr", 4096) = 18
write(1, "realpath of .: \"(unreachable)/us"..., 35realpath of .:
"(unreachable)/usr"
) = 35
getcwd("(unreachable)/usr", 4096) = 18
lstat("(unreachable)/home", 0x7fff685a5ac0) = -1 ENOENT (No such file or
directory)
write(1, "realpath of path: \"{none}\"\n", 27realpath of path: "{none}"
) = 27
exit_group(0) = ?
+++ exited with 0 +++
As you can see, realpath attempts to lstat() the unreachable path returned by
getcwd() in the last invocation. I think the sanest option to deal with this
would be to let realpath() error out if getcwd() returns a path that does not
start with a slash, but I'm not sure about which errno value to use. Maybe
ENOENT, with the reasoning "if it's not under the root, it doesn't really exist
to us"?
--
You are receiving this mail because:
You are on the CC list for the bug.