From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id E72B01382C5 for ; Tue, 23 Jan 2018 23:08:39 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 5AAB9E0995; Tue, 23 Jan 2018 23:08:39 +0000 (UTC) Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 2A9D0E0995 for ; Tue, 23 Jan 2018 23:08:39 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id F1550335C2E for ; Tue, 23 Jan 2018 23:08:37 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 868781C9 for ; Tue, 23 Jan 2018 23:08:36 +0000 (UTC) From: "William Hubbs" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "William Hubbs" Message-ID: <1516748166.1771bc2a83fe65bfe6ec3e93ea7632609e697a38.williamh@OpenRC> Subject: [gentoo-commits] proj/openrc:master commit in: src/rc/ X-VCS-Repository: proj/openrc X-VCS-Files: src/rc/checkpath.c X-VCS-Directories: src/rc/ X-VCS-Committer: williamh X-VCS-Committer-Name: William Hubbs X-VCS-Revision: 1771bc2a83fe65bfe6ec3e93ea7632609e697a38 X-VCS-Branch: master Date: Tue, 23 Jan 2018 23:08:36 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: b1f3bcb1-f10d-41ec-9851-6a9c6de06729 X-Archives-Hash: 14cdf2cfd2dbea6f3e727b09a0a049b9 commit: 1771bc2a83fe65bfe6ec3e93ea7632609e697a38 Author: William Hubbs gmail com> AuthorDate: Tue Jan 23 22:56:06 2018 +0000 Commit: William Hubbs gentoo org> CommitDate: Tue Jan 23 22:56:06 2018 +0000 URL: https://gitweb.gentoo.org/proj/openrc.git/commit/?id=1771bc2a checkpath: use fchown and fchmod to handle ownership and mode changes This is related to #195. This is an attempt to shorten the window for the first two issues discussed by using a file descriptor which does not follow symbolic links and using the fchmod and fchown calls instead of chown and chmod. with. src/rc/checkpath.c | 124 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 45 deletions(-) diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c index 39e7ce4d..2e2b4ee3 100644 --- a/src/rc/checkpath.c +++ b/src/rc/checkpath.c @@ -73,25 +73,32 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, inode_t type, bool trunc, bool chowner, bool selinux_on) { struct stat st; - int fd, flags; + int fd; + int flags; int r; + int readfd; + int readflags; int u; memset(&st, 0, sizeof(st)); - if (lstat(path, &st) || trunc) { - if (type == inode_file) { - einfo("%s: creating file", path); - if (!mode) /* 664 */ - mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; - flags = O_CREAT|O_NDELAY|O_WRONLY|O_NOCTTY; + flags = O_CREAT|O_NDELAY|O_WRONLY|O_NOCTTY; + readflags = O_NDELAY|O_NOCTTY|O_RDONLY; #ifdef O_CLOEXEC - flags |= O_CLOEXEC; + flags |= O_CLOEXEC; + readflags |= O_CLOEXEC; #endif #ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; + flags |= O_NOFOLLOW; + readflags |= O_NOFOLLOW; #endif - if (trunc) - flags |= O_TRUNC; + if (trunc) + flags |= O_TRUNC; + readfd = open(path, readflags); + if (readfd == -1 || (type == inode_file && trunc)) { + if (type == inode_file) { + einfo("%s: creating file", path); + if (!mode) /* 664 */ + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; u = umask(0); fd = open(path, flags, mode); umask(u); @@ -99,7 +106,9 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, eerror("%s: open: %s", applet, strerror(errno)); return -1; } - close (fd); + if (readfd != -1 && trunc) + close(readfd); + readfd = fd; } else if (type == inode_dir) { einfo("%s: creating directory", path); if (!mode) /* 775 */ @@ -113,7 +122,12 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, strerror (errno)); return -1; } - mode = 0; + readfd = open(path, readflags); + if (readfd == -1) { + eerror("%s: unable to open directory: %s", applet, + strerror(errno)); + return -1; + } } else if (type == inode_fifo) { einfo("%s: creating fifo", path); if (!mode) /* 600 */ @@ -126,56 +140,76 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, strerror (errno)); return -1; } + readfd = open(path, readflags); + if (readfd == -1) { + eerror("%s: unable to open fifo: %s", applet, + strerror(errno)); + return -1; + } } - } else { + } + if (fstat(readfd, &st) != -1) { if (type != inode_dir && S_ISDIR(st.st_mode)) { eerror("%s: is a directory", path); + close(readfd); return 1; } if (type != inode_file && S_ISREG(st.st_mode)) { eerror("%s: is a file", path); + close(readfd); return 1; } if (type != inode_fifo && S_ISFIFO(st.st_mode)) { eerror("%s: is a fifo", path); + close(readfd); return -1; } - } - if (mode && (st.st_mode & 0777) != mode) { - if ((type != inode_dir) && (st.st_nlink > 1)) { - eerror("%s: chmod: %s %s", applet, "Too many hard links to", path); - return -1; - } - if (S_ISLNK(st.st_mode)) { - eerror("%s: chmod: %s %s", applet, path, " is a symbolic link"); - return -1; - } - einfo("%s: correcting mode", path); - if (chmod(path, mode)) { - eerror("%s: chmod: %s", applet, strerror(errno)); - return -1; + if (mode && (st.st_mode & 0777) != mode) { + if ((type != inode_dir) && (st.st_nlink > 1)) { + eerror("%s: chmod: %s %s", applet, "Too many hard links to", path); + close(readfd); + return -1; + } + if (S_ISLNK(st.st_mode)) { + eerror("%s: chmod: %s %s", applet, path, " is a symbolic link"); + close(readfd); + return -1; + } + einfo("%s: correcting mode", path); + if (fchmod(readfd, mode)) { + eerror("%s: chmod: %s", applet, strerror(errno)); + close(readfd); + return -1; + } } - } - if (chowner && (st.st_uid != uid || st.st_gid != gid)) { - if ((type != inode_dir) && (st.st_nlink > 1)) { - eerror("%s: chown: %s %s", applet, "Too many hard links to", path); - return -1; - } - if (S_ISLNK(st.st_mode)) { - eerror("%s: chown: %s %s", applet, path, " is a symbolic link"); - return -1; - } - einfo("%s: correcting owner", path); - if (lchown(path, uid, gid)) { - eerror("%s: lchown: %s", applet, strerror(errno)); - return -1; + if (chowner && (st.st_uid != uid || st.st_gid != gid)) { + if ((type != inode_dir) && (st.st_nlink > 1)) { + eerror("%s: chown: %s %s", applet, "Too many hard links to", path); + close(readfd); + return -1; + } + if (S_ISLNK(st.st_mode)) { + eerror("%s: chown: %s %s", applet, path, " is a symbolic link"); + close(readfd); + return -1; + } + einfo("%s: correcting owner", path); + if (fchown(readfd, uid, gid)) { + eerror("%s: chown: %s", applet, strerror(errno)); + close(readfd); + return -1; + } } + if (selinux_on) + selinux_util_label(path); + } else { + eerror(fstat: %s: %s", path, strerror(errno)); + close(readfd); + return -1; } - - if (selinux_on) - selinux_util_label(path); + close(readfd); return 0; }