CHASE_STEP | \
CHASE_PROHIBIT_SYMLINKS | \
CHASE_PARENT | \
- CHASE_MKDIR_0755)
+ CHASE_MKDIR_0755 | \
+ CHASE_MUST_BE_DIRECTORY | \
+ CHASE_MUST_BE_REGULAR | \
+ CHASE_MUST_BE_SOCKET)
bool unsafe_transition(const struct stat *a, const struct stat *b) {
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
int r;
assert(!FLAGS_SET(flags, CHASE_PREFIX_ROOT));
- assert(!FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_REGULAR));
assert(!FLAGS_SET(flags, CHASE_STEP|CHASE_EXTRACT_FILENAME));
assert(!FLAGS_SET(flags, CHASE_NO_AUTOFS|CHASE_TRIGGER_AUTOFS));
assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
if (FLAGS_SET(flags, CHASE_PARENT))
flags |= CHASE_MUST_BE_DIRECTORY;
+ /* If multiple flags are set now, fail immediately */
+ if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY) + FLAGS_SET(flags, CHASE_MUST_BE_REGULAR) + FLAGS_SET(flags, CHASE_MUST_BE_SOCKET) > 1)
+ return -EBADSLT;
+
for (todo = buffer;;) {
_cleanup_free_ char *first = NULL;
_cleanup_close_ int child = -EBADF;
if (r < 0)
return r;
}
+
+ if (FLAGS_SET(flags, CHASE_MUST_BE_SOCKET)) {
+ r = stat_verify_socket(&st);
+ if (r < 0)
+ return r;
+ }
}
if (ret_path) {
DIR *d;
int r;
- assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR)));
+ assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR|CHASE_MUST_BE_SOCKET)));
assert(ret_dir);
if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) {
int mode_flags, r;
assert(path);
- assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT|CHASE_MUST_BE_DIRECTORY)));
+ assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT|CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_SOCKET)));
assert(open_flags);
assert(ret_file);
_cleanup_free_ char *p = NULL, *fname = NULL;
int r;
- assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
+ assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_SOCKET)));
XOpenFlags xopen_flags = 0;
if (FLAGS_SET(chase_flags, CHASE_MUST_BE_DIRECTORY))
DIR *d;
int r;
- assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR)));
+ assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR|CHASE_MUST_BE_SOCKET)));
assert(ret_dir);
if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) {
CHASE_EXTRACT_FILENAME = 1 << 13, /* Only return the last component of the resolved path */
CHASE_MUST_BE_DIRECTORY = 1 << 14, /* Fail if returned inode fd is not a dir */
CHASE_MUST_BE_REGULAR = 1 << 15, /* Fail if returned inode fd is not a regular file */
+ CHASE_MUST_BE_SOCKET = 1 << 16, /* Fail if returned inode fd is not a socket */
} ChaseFlags;
bool unsafe_transition(const struct stat *a, const struct stat *b);