From 71ec74d19332378dca8a6a7eb30411e08978f9a6 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 6 Jun 2019 14:05:27 +0200 Subject: [PATCH] fs-util: no need for fchmod_and_chown() to access /proc/self/fd directly fstat(2) is fine with O_PATH fds. For changing owership of a file opened with O_PATH, there's fchownat(2). Only changing permissions is problematic but we introduced fchmod_opath() for that purpose. --- src/basic/fs-util.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 7dfc1b309d..14d3725709 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -226,7 +226,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { } int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { - char fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; bool do_chown, do_chmod; struct stat st; @@ -236,11 +235,9 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { * unaffected if the uid/gid is changed, i.e. it undoes implicit suid/sgid dropping the kernel does * on chown(). * - * This call is happy with O_PATH fds, since we always go via /proc/self/fd/ to change - * ownership/access mode. */ + * This call is happy with O_PATH fds. */ - xsprintf(fd_path, "/proc/self/fd/%i", fd); - if (stat(fd_path, &st) < 0) + if (fstat(fd, &st) < 0) return -errno; do_chown = @@ -262,16 +259,16 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ if (((minimal ^ st.st_mode) & 07777) != 0) - if (chmod(fd_path, minimal & 07777) < 0) + if (fchmod_opath(fd, minimal & 07777) < 0) return -errno; } if (do_chown) - if (chown(fd_path, uid, gid) < 0) + if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0) return -errno; if (do_chmod) - if (chmod(fd_path, mode & 07777) < 0) + if (fchmod_opath(fd, mode & 07777) < 0) return -errno; return do_chown || do_chmod;