]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: don't follow unsafe transitions in path_set_*()
authorFranck Bui <fbui@suse.com>
Tue, 20 Mar 2018 07:58:48 +0000 (08:58 +0100)
committerFranck Bui <fbui@suse.com>
Mon, 30 Jul 2018 14:04:20 +0000 (16:04 +0200)
Since all path_set_*() helpers don't follow symlinks, it's possible to use
chase_symlinks(CHASE_NOFOLLOW) flag to both open the files specified by the
passed paths and check their validity (unlike their counterpart fd_set_*()
helpers).

src/tmpfiles/tmpfiles.c

index 71f8dec49b51fe64a8cc78a0371dd36feb393316..cfd9044c5b9170ded0e0b9a782687a307fbd5a6f 100644 (file)
@@ -864,15 +864,38 @@ static int path_open_parent_safe(const char *path) {
         return fd;
 }
 
+static int path_open_safe(const char *path) {
+        int fd;
+
+        /* path_open_safe() returns a file descriptor opened with O_PATH after
+         * verifying that the path doesn't contain unsafe transitions, except
+         * for its final component as the function does not follow symlink. */
+
+        assert(path);
+
+        if (!path_is_normalized(path)) {
+                log_error("Failed to open invalid path '%s'.", path);
+                return -EINVAL;
+        }
+
+        fd = chase_symlinks(path, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_NOFOLLOW, NULL);
+        if (fd == -EPERM)
+                return log_error_errno(fd, "Unsafe symlinks encountered in %s, refusing.", path);
+        if (fd < 0)
+                return log_error_errno(fd, "Failed to validate path %s: %m", path);
+
+        return fd;
+}
+
 static int path_set_perms(Item *i, const char *path) {
         _cleanup_close_ int fd = -1;
 
         assert(i);
         assert(path);
 
-        fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+        fd = path_open_safe(path);
         if (fd < 0)
-                return log_error_errno(errno, "Failed to open \"%s\" to adjust permissions: %m", path);
+                return fd;
 
         return fd_set_perms(i, fd, NULL);
 }
@@ -945,9 +968,9 @@ static int path_set_xattrs(Item *i, const char *path) {
         assert(i);
         assert(path);
 
-        fd = open(path, O_CLOEXEC|O_NOFOLLOW|O_PATH);
+        fd = path_open_safe(path);
         if (fd < 0)
-                return log_error_errno(errno, "Cannot open '%s': %m", path);
+                return fd;
 
         return fd_set_xattrs(i, fd, NULL);
 }
@@ -1076,9 +1099,9 @@ static int path_set_acls(Item *item, const char *path) {
         assert(item);
         assert(path);
 
-        fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
+        fd = path_open_safe(path);
         if (fd < 0)
-                return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
+                return fd;
 
         r = fd_set_acls(item, fd, NULL);
 #endif
@@ -1238,9 +1261,9 @@ static int path_set_attribute(Item *item, const char *path) {
         if (!item->attribute_set || item->attribute_mask == 0)
                 return 0;
 
-        fd = open(path, O_CLOEXEC|O_NOFOLLOW|O_PATH);
+        fd = path_open_safe(path);
         if (fd < 0)
-                return log_error_errno(errno, "Cannot open '%s': %m", path);
+                return fd;
 
         return fd_set_attribute(item, fd, NULL);
 }