tmpfiles: make write_one_file() safe
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 28e6550..36784a3 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1271,7 +1271,8 @@
}
static int write_one_file(Item *i, const char *path) {
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -1, dir_fd = -1;
+ char *bn;
int r;
assert(i);
@@ -1279,8 +1280,16 @@
assert(i->argument);
assert(i->type == WRITE_FILE);
+ /* Validate the path and keep the fd on the directory for opening the
+ * file so we're sure that it can't be changed behind our back. */
+ dir_fd = path_open_parent_safe(path);
+ if (dir_fd < 0)
+ return dir_fd;
+
+ bn = basename(path);
+
/* Follows symlinks */
- fd = open(path, O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
+ fd = openat(dir_fd, bn, O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
if (fd < 0) {
if (errno == ENOENT) {
log_debug_errno(errno, "Not writing missing file \"%s\": %m", path);
@@ -1296,7 +1305,7 @@
if (r < 0)
return log_error_errno(r, "Failed to write file \"%s\": %m", path);
- return path_set_perms(i, path);
+ return fd_set_perms(i, fd, NULL);
}
static int create_file(Item *i, const char *path) {