>From f1d199310e2c93509e50e8b0b70bfde344328c02 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Mon, 26 Oct 2009 13:00:46 +0000 Subject: [PATCH 2/2] daemon: Change chdir to use openat/fdopendir. --- daemon/realpath.c | 35 ++++++++++++++++++++++++++--------- 1 files changed, 26 insertions(+), 9 deletions(-) diff --git a/daemon/realpath.c b/daemon/realpath.c index bfe8e67..b4f2dcc 100644 --- a/daemon/realpath.c +++ b/daemon/realpath.c @@ -18,16 +18,19 @@ #include +#ifndef _ATFILE_SOURCE +#define _ATFILE_SOURCE +#endif + #include #include #include #include +#include #include #include #include -#include "ignore-value.h" - #include "daemon.h" #include "actions.h" @@ -52,9 +55,13 @@ do_case_sensitive_path (const char *path) { char ret[PATH_MAX+1] = "/"; size_t next = 1; + int fd; - /* MUST chdir ("/") before leaving this function. */ - if (chdir (sysroot) == -1) { + /* 'fd' here is a surrogate for the current working directory, so + * that we don't have to actually call chdir(2). + */ + fd = open (sysroot, O_RDONLY | O_DIRECTORY); + if (fd == -1) { reply_with_perror ("%s", sysroot); return NULL; } @@ -93,7 +100,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); /* 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 +148,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, d->d_name, O_RDONLY | O_DIRECTORY); + int err = errno; + close (fd); + fd = fd2; + errno = err; + if (fd == -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 +167,7 @@ do_case_sensitive_path (const char *path) } } - ignore_value (chdir ("/")); + close (fd); ret[next] = '\0'; char *retp = strdup (ret); @@ -161,6 +178,6 @@ do_case_sensitive_path (const char *path) return retp; /* caller frees */ error: - ignore_value (chdir ("/")); + close (fd); return NULL; } -- 1.6.5.rc2