From: Lennart Poettering Date: Fri, 6 Feb 2026 14:03:23 +0000 (+0100) Subject: chase: add new flag CHASE_MUST_BE_SOCKET X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e4fca7489c20e5cd8bc8896c1fd9d7c24727a89;p=thirdparty%2Fsystemd.git chase: add new flag CHASE_MUST_BE_SOCKET Just like CHASE_MUST_BE_DIRECTORY and CHASE_MUST_BE_REGULAR, but test if the inode is a socket. --- diff --git a/src/basic/chase.c b/src/basic/chase.c index f360cc26a3c..abe85a2a089 100644 --- a/src/basic/chase.c +++ b/src/basic/chase.c @@ -26,7 +26,10 @@ 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 @@ -133,7 +136,6 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int 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)); @@ -328,6 +330,10 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int 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; @@ -566,6 +572,12 @@ success: 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) { @@ -872,7 +884,7 @@ int chase_and_opendir(const char *path, const char *root, ChaseFlags chase_flags 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) { @@ -970,7 +982,7 @@ int chase_and_fopen_unlocked( 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); @@ -1040,7 +1052,7 @@ int chase_and_openat( _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)) @@ -1086,7 +1098,7 @@ int chase_and_opendirat(int dir_fd, const char *path, ChaseFlags chase_flags, ch 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) { diff --git a/src/basic/chase.h b/src/basic/chase.h index 948b83aad07..d0674aae73c 100644 --- a/src/basic/chase.h +++ b/src/basic/chase.h @@ -29,6 +29,7 @@ typedef enum ChaseFlags { 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);