X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Ftmpfiles%2Ftmpfiles.c;h=8b6342b2e446968eeb90d0c252beeada9063d8c7;hb=b206ac8e54a3656b681b2f6031c7cd0feb7f5e26;hp=183e98b3c16e9fb747178b6064241f53a572811c;hpb=cb8770ed2137c509f2b73af33619fa0168d727e3;p=thirdparty%2Fsystemd.git diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 183e98b3c16..8b6342b2e44 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1,10 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2010 Lennart Poettering, Kay Sievers - Copyright 2015 Zbigniew Jędrzejewski-Szmek -***/ #include #include @@ -778,6 +772,7 @@ static bool hardlink_vulnerable(const struct stat *st) { static int fd_set_perms(Item *i, int fd, const struct stat *st) { _cleanup_free_ char *path = NULL; + struct stat stbuf; int r; assert(i); @@ -790,6 +785,12 @@ static int fd_set_perms(Item *i, int fd, const struct stat *st) { if (!i->mode_set && !i->uid_set && !i->gid_set) goto shortcut; + if (!st) { + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "fstat(%s) failed: %m", path); + st = &stbuf; + } + if (hardlink_vulnerable(st)) { log_error("Refusing to set permissions on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.", path); return -EPERM; @@ -843,7 +844,7 @@ shortcut: static int path_set_perms(Item *i, const char *path) { _cleanup_close_ int fd = -1; - struct stat st; + struct stat stbuf, *st = NULL; assert(i); assert(path); @@ -863,13 +864,20 @@ static int path_set_perms(Item *i, const char *path) { return r; } - if (fstat(fd, &st) < 0) - return log_error_errno(errno, "Failed to fstat() file %s: %m", path); + if (i->type == EMPTY_DIRECTORY) { + /* FIXME: introduce fd_is_dir() helper ? */ + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "Failed to fstat() file %s: %m", path); - if (i->type == EMPTY_DIRECTORY && !S_ISDIR(st.st_mode)) - return log_error_errno(EEXIST, "'%s' already exists and is not a directory. ", path); + if (!S_ISDIR(stbuf.st_mode)) { + log_error("'%s' already exists and is not a directory. ", path); + return -EEXIST; + } + + st = &stbuf; + } - return fd_set_perms(i, fd, &st); + return fd_set_perms(i, fd, st); } static int parse_xattrs_from_arg(Item *i) { @@ -1017,15 +1025,21 @@ static int fd_set_acls(Item *item, int fd, const struct stat *st) { #if HAVE_ACL char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *path = NULL; + struct stat stbuf; assert(item); assert(fd); - assert(st); r = fd_get_path(fd, &path); if (r < 0) return r; + if (!st) { + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "fstat(%s) failed: %m", path); + st = &stbuf; + } + if (hardlink_vulnerable(st)) { log_error("Refusing to set ACLs on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.", path); return -EPERM; @@ -1041,7 +1055,8 @@ static int fd_set_acls(Item *item, int fd, const struct stat *st) { if (item->acl_access) r = path_set_acl(procfs_path, path, ACL_TYPE_ACCESS, item->acl_access, item->force); - if (r == 0 && item->acl_default) + /* set only default acls to folders */ + if (r == 0 && item->acl_default && S_ISDIR(st->st_mode)) r = path_set_acl(procfs_path, path, ACL_TYPE_DEFAULT, item->acl_default, item->force); if (r > 0) @@ -1058,9 +1073,8 @@ static int fd_set_acls(Item *item, int fd, const struct stat *st) { static int path_set_acls(Item *item, const char *path) { int r = 0; -#ifdef HAVE_ACL +#if HAVE_ACL _cleanup_close_ int fd = -1; - struct stat st; assert(item); assert(path); @@ -1069,13 +1083,10 @@ static int path_set_acls(Item *item, const char *path) { if (fd < 0) return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path); - if (fstat(fd, &st) < 0) - return log_error_errno(errno, "Failed to fstat() file %s: %m", path); - - r = fd_set_acls(item, fd, &st); - #endif - return r; - } + r = fd_set_acls(item, fd, NULL); +#endif + return r; +} #define ATTRIBUTES_ALL \ (FS_NOATIME_FL | \ @@ -1179,6 +1190,7 @@ static int parse_attribute_from_arg(Item *item) { static int fd_set_attribute(Item *item, int fd, const struct stat *st) { _cleanup_close_ int procfs_fd = -1; _cleanup_free_ char *path = NULL; + struct stat stbuf; unsigned f; int r; @@ -1189,6 +1201,12 @@ static int fd_set_attribute(Item *item, int fd, const struct stat *st) { if (r < 0) return r; + if (!st) { + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "fstat(%s) failed: %m", path); + st = &stbuf; + } + /* Issuing the file attribute ioctls on device nodes is not * safe, as that will be delivered to the drivers, not the * file system containing the device node. */ @@ -1219,7 +1237,6 @@ static int fd_set_attribute(Item *item, int fd, const struct stat *st) { static int path_set_attribute(Item *item, const char *path) { _cleanup_close_ int fd = -1; - struct stat st; if (!item->attribute_set || item->attribute_mask == 0) return 0; @@ -1228,10 +1245,7 @@ static int path_set_attribute(Item *item, const char *path) { if (fd < 0) return log_error_errno(errno, "Cannot open '%s': %m", path); - if (fstat(fd, &st) < 0) - return log_error_errno(errno, "Cannot stat '%s': %m", path); - - return fd_set_attribute(item, fd, &st); + return fd_set_attribute(item, fd, NULL); } static int write_one_file(Item *i, const char *path) { @@ -1300,18 +1314,23 @@ static int write_one_file(Item *i, const char *path) { typedef int (*action_t)(Item *, const char *); typedef int (*fdaction_t)(Item *, int fd, const struct stat *st); -static int item_do(Item *i, int fd, const struct stat *st, fdaction_t action) { +static int item_do(Item *i, int fd, fdaction_t action) { + struct stat st; int r = 0, q; assert(i); assert(fd >= 0); - assert(st); + + if (fstat(fd, &st) < 0) { + r = -errno; + goto finish; + } /* This returns the first error we run into, but nevertheless * tries to go on */ - r = action(i, fd, st); + r = action(i, fd, &st); - if (S_ISDIR(st->st_mode)) { + if (S_ISDIR(st.st_mode)) { char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -1327,16 +1346,15 @@ static int item_do(Item *i, int fd, const struct stat *st, fdaction_t action) { } FOREACH_DIRENT_ALL(de, d, q = -errno; goto finish) { - struct stat de_st; int de_fd; if (dot_or_dot_dot(de->d_name)) continue; de_fd = openat(fd, de->d_name, O_NOFOLLOW|O_CLOEXEC|O_PATH); - if (de_fd >= 0 && fstat(de_fd, &de_st) >= 0) + if (de_fd >= 0) /* pass ownership of dirent fd over */ - q = item_do(i, de_fd, &de_st, action); + q = item_do(i, de_fd, action); else q = -errno; @@ -1382,7 +1400,6 @@ static int glob_item_recursively(Item *i, fdaction_t action) { STRV_FOREACH(fn, g.gl_pathv) { _cleanup_close_ int fd = -1; - struct stat st; /* Make sure we won't trigger/follow file object (such as * device nodes, automounts, ...) pointed out by 'fn' with @@ -1395,12 +1412,7 @@ static int glob_item_recursively(Item *i, fdaction_t action) { continue; } - if (fstat(fd, &st) < 0) { - r = r ?: -errno; - continue; - } - - k = item_do(i, fd, &st, action); + k = item_do(i, fd, action); if (k < 0 && r == 0) r = k;