tmpfiles: don't follow unsafe transitions in path_set_*()
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).
This commit is contained in:
parent
1f56e4ce77
commit
addc3e302d
|
@ -864,15 +864,38 @@ static int path_open_parent_safe(const char *path) {
|
||||||
return fd;
|
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) {
|
static int path_set_perms(Item *i, const char *path) {
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
assert(i);
|
assert(i);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
|
fd = path_open_safe(path);
|
||||||
if (fd < 0)
|
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);
|
return fd_set_perms(i, fd, NULL);
|
||||||
}
|
}
|
||||||
|
@ -945,9 +968,9 @@ static int path_set_xattrs(Item *i, const char *path) {
|
||||||
assert(i);
|
assert(i);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
fd = open(path, O_CLOEXEC|O_NOFOLLOW|O_PATH);
|
fd = path_open_safe(path);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Cannot open '%s': %m", path);
|
return fd;
|
||||||
|
|
||||||
return fd_set_xattrs(i, fd, NULL);
|
return fd_set_xattrs(i, fd, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1076,9 +1099,9 @@ static int path_set_acls(Item *item, const char *path) {
|
||||||
assert(item);
|
assert(item);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
|
fd = path_open_safe(path);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
|
return fd;
|
||||||
|
|
||||||
r = fd_set_acls(item, fd, NULL);
|
r = fd_set_acls(item, fd, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1238,9 +1261,9 @@ static int path_set_attribute(Item *item, const char *path) {
|
||||||
if (!item->attribute_set || item->attribute_mask == 0)
|
if (!item->attribute_set || item->attribute_mask == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fd = open(path, O_CLOEXEC|O_NOFOLLOW|O_PATH);
|
fd = path_open_safe(path);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Cannot open '%s': %m", path);
|
return fd;
|
||||||
|
|
||||||
return fd_set_attribute(item, fd, NULL);
|
return fd_set_attribute(item, fd, NULL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue