From: Richard Jones Date: Mon, 26 Oct 2009 13:00:46 +0000 (+0000) Subject: daemon: Change chdir to use openat/fdopendir. X-Git-Tag: 1.0.75~6 X-Git-Url: http://git.annexia.org/?a=commitdiff_plain;h=74bde73d5c60c13b894fa60fff680a447499c884;p=libguestfs.git daemon: Change chdir to use openat/fdopendir. Uses Gnulib implementation of openat which should be portable. --- diff --git a/daemon/.gitignore b/daemon/.gitignore index 11d8699..6a67b90 100644 --- a/daemon/.gitignore +++ b/daemon/.gitignore @@ -2,10 +2,31 @@ build-aux lib link-warning.h m4/00gnulib.m4 +m4/alloca.m4 +m4/canonicalize-lgpl.m4 +m4/chdir-long.m4 +m4/chown.m4 +m4/close.m4 +m4/d-ino.m4 +m4/dirent_h.m4 +m4/dirfd.m4 +m4/dirname.m4 +m4/dos.m4 +m4/double-slash-root.m4 +m4/dup2.m4 +m4/eealloc.m4 m4/errno_h.m4 m4/error.m4 m4/exitfail.m4 m4/extensions.m4 +m4/fchdir.m4 +m4/fclose.m4 +m4/fcntl-safer.m4 +m4/fcntl_h.m4 +m4/getcwd-abort-bug.m4 +m4/getcwd-path-max.m4 +m4/getcwd.m4 +m4/getpagesize.m4 m4/gnulib-common.m4 m4/gnulib-comp.m4 m4/gnulib-tool.m4 @@ -13,20 +34,41 @@ m4/hash.m4 m4/include_next.m4 m4/inline.m4 m4/inttostr.m4 +m4/lchown.m4 m4/longlong.m4 +m4/lstat.m4 +m4/malloc.m4 +m4/malloca.m4 m4/manywarnings.m4 +m4/memchr.m4 +m4/mempcpy.m4 +m4/memrchr.m4 +m4/mmap-anon.m4 +m4/mode_t.m4 m4/multiarch.m4 m4/onceonly.m4 +m4/open.m4 +m4/openat.m4 +m4/pathmax.m4 +m4/readlink.m4 +m4/save-cwd.m4 m4/stdbool.m4 m4/stddef_h.m4 m4/stdint.m4 +m4/stdio_h.m4 m4/stdlib_h.m4 m4/strerror.m4 m4/string_h.m4 +m4/strndup.m4 +m4/strnlen.m4 +m4/sys_stat_h.m4 +m4/unistd-safer.m4 m4/unistd_h.m4 m4/warnings.m4 m4/wchar.m4 m4/wchar_t.m4 m4/wint_t.m4 m4/xalloc.m4 +m4/xgetcwd.m4 +m4/xstrndup.m4 tests diff --git a/daemon/m4/gnulib-cache.m4 b/daemon/m4/gnulib-cache.m4 index df69113..2157ceb 100644 --- a/daemon/m4/gnulib-cache.m4 +++ b/daemon/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=gl c-ctype hash ignore-value manywarnings warnings +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=gl c-ctype hash ignore-value manywarnings openat warnings # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -24,6 +24,7 @@ gl_MODULES([ hash ignore-value manywarnings + openat warnings ]) gl_AVOID([]) diff --git a/daemon/realpath.c b/daemon/realpath.c index bfe8e67..0dc5fa5 100644 --- a/daemon/realpath.c +++ b/daemon/realpath.c @@ -22,11 +22,12 @@ #include #include #include +#include #include #include #include -#include "ignore-value.h" +#include "openat.h" #include "daemon.h" #include "actions.h" @@ -52,9 +53,13 @@ do_case_sensitive_path (const char *path) { char ret[PATH_MAX+1] = "/"; size_t next = 1; + int fd_cwd; - /* MUST chdir ("/") before leaving this function. */ - if (chdir (sysroot) == -1) { + /* 'fd_cwd' here is a surrogate for the current working directory, so + * that we don't have to actually call chdir(2). + */ + fd_cwd = open (sysroot, O_RDONLY | O_DIRECTORY); + if (fd_cwd == -1) { reply_with_perror ("%s", sysroot); return NULL; } @@ -93,7 +98,12 @@ do_case_sensitive_path (const char *path) /* Read the current directory looking (case insensitively) for * this element of the path. */ - DIR *dir = opendir ("."); + int fd2 = dup (fd_cwd); /* because closedir will close it */ + if (fd2 == -1) { + reply_with_perror ("dup"); + goto error; + } + DIR *dir = fdopendir (fd2); if (dir == NULL) { reply_with_perror ("opendir"); goto error; @@ -136,10 +146,15 @@ do_case_sensitive_path (const char *path) next += i; /* Is it a directory? Try going into it. */ - if (chdir (d->d_name) == -1) { + fd2 = openat (fd_cwd, d->d_name, O_RDONLY | O_DIRECTORY); + int err = errno; + close (fd_cwd); + fd_cwd = fd2; + errno = err; + if (fd_cwd == -1) { /* ENOTDIR is OK provided we've reached the end of the path. */ if (errno != ENOTDIR) { - reply_with_perror ("chdir: %s", d->d_name); + reply_with_perror ("openat: %s", d->d_name); goto error; } @@ -150,7 +165,7 @@ do_case_sensitive_path (const char *path) } } - ignore_value (chdir ("/")); + close (fd_cwd); ret[next] = '\0'; char *retp = strdup (ret); @@ -161,6 +176,6 @@ do_case_sensitive_path (const char *path) return retp; /* caller frees */ error: - ignore_value (chdir ("/")); + close (fd_cwd); return NULL; } diff --git a/m4/.gitignore b/m4/.gitignore index f158aa3..d5082d7 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -90,3 +90,36 @@ xsize.m4 /netinet_in_h.m4 /sockpfaf.m4 /sys_socket_h.m4 +/canonicalize-lgpl.m4 +/chdir-long.m4 +/chown.m4 +/close.m4 +/d-ino.m4 +/dirent_h.m4 +/dirfd.m4 +/dirname.m4 +/dos.m4 +/double-slash-root.m4 +/dup2.m4 +/fchdir.m4 +/fclose.m4 +/fcntl-safer.m4 +/fcntl_h.m4 +/getcwd-abort-bug.m4 +/getcwd-path-max.m4 +/getcwd.m4 +/lchown.m4 +/lstat.m4 +/malloc.m4 +/mempcpy.m4 +/memrchr.m4 +/mode_t.m4 +/open.m4 +/openat.m4 +/pathmax.m4 +/readlink.m4 +/save-cwd.m4 +/sys_stat_h.m4 +/unistd-safer.m4 +/xgetcwd.m4 +/xstrndup.m4