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);
}
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);
}
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
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);
}