#include "strv.h"
#include "user-util.h"
+#define CHASE_NO_SHORTCUT_MASK \
+ (CHASE_NONEXISTENT | \
+ CHASE_NO_AUTOFS | \
+ CHASE_SAFE | \
+ CHASE_STEP | \
+ CHASE_PROHIBIT_SYMLINKS | \
+ CHASE_PARENT | \
+ CHASE_MKDIR_0755)
+
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
* privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files
flags &= ~CHASE_AT_RESOLVE_IN_ROOT;
}
- if (!(flags &
- (CHASE_AT_RESOLVE_IN_ROOT|CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP|
- CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755|CHASE_PARENT)) &&
- !ret_path && ret_fd) {
-
+ if (!ret_path && ret_fd && (flags & (CHASE_AT_RESOLVE_IN_ROOT|CHASE_NO_SHORTCUT_MASK)) == 0) {
/* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root
* set and doesn't care about any of the other special features we provide either. */
r = openat(dir_fd, path, O_PATH|O_CLOEXEC|(FLAGS_SET(flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
- if (empty_or_root(root) && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+ if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return xopenat_full(AT_FDCWD, path,
open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
assert(ret_dir);
- if (empty_or_root(root) && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) {
+ if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) {
/* Shortcut this call if none of the special features of this call are requested */
d = opendir(path);
if (!d)
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
assert(ret_stat);
- if (empty_or_root(root) && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+ if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return RET_NERRNO(fstatat(AT_FDCWD, path, ret_stat,
FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0));
assert(path);
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
- if (empty_or_root(root) && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+ if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return RET_NERRNO(faccessat(AT_FDCWD, path, access_mode,
FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0));
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
- if (dir_fd == AT_FDCWD && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+ if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return xopenat_full(dir_fd, path,
open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
assert(ret_dir);
- if (dir_fd == AT_FDCWD && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0) {
+ if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) {
/* Shortcut this call if none of the special features of this call are requested */
d = opendir(path);
if (!d)
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
assert(ret_stat);
- if (dir_fd == AT_FDCWD && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+ if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return RET_NERRNO(fstatat(AT_FDCWD, path, ret_stat,
FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0));
assert(path);
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
- if (dir_fd == AT_FDCWD && !ret_path &&
- (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
+ if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return RET_NERRNO(faccessat(AT_FDCWD, path, access_mode,
FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0));