]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: make write_one_file() safe
authorFranck Bui <fbui@suse.com>
Fri, 13 Apr 2018 15:54:09 +0000 (17:54 +0200)
committerFranck Bui <fbui@suse.com>
Mon, 30 Jul 2018 13:54:02 +0000 (15:54 +0200)
src/tmpfiles/tmpfiles.c

index 28e6550243690d8df7d5101b948d7db661c741e1..36784a3ad9b2759e4bcf794ef3d0213a5c0db591 100644 (file)
@@ -1271,7 +1271,8 @@ static int path_set_attribute(Item *item, const char *path) {
 }
 
 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 @@ static int write_one_file(Item *i, const char *path) {
         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 @@ static int write_one_file(Item *i, const char *path) {
         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) {