selinux: alternate root support (#42768)

This PR changes some SELinux bits related to working with alternate
roots (specifically when using `--root` or `--image` on a bunch of
executables).

It addresses bug #42643 and it's hopefully the more whole approach than
the naive approach I PR'ed in #42644.

Before this PR the 'wrong' labels get applied because the path lookups
in the SELinux label database are prefixed with whatever the location of
the alternate root is (explained in more detail below).

Initially I had taken a very naive approach that did fix the issue by
stripping the alternate root from the path; however this still looks up
that path in the hosts' label database, which might differ from the one
contained in the alternate root.

So this expanded approach actually reads the label database from the
alternate root, strips the prefix *if* an alternate root is used
directly in `selinux-util.c` and then uses that to assign labels
instead.

See under the line for the behavior pre/post.

I've tried builds of this PR on both enforcing/non-enforcing/non-enabled
hosts *and* on enabled/non-enabled disk images and things seem to work
or at least fall back to ignoring MAC when required bits aren't present.

One thing is *if* an `/etc/selinux/config` is present that defines a
`SELINUXTYPE=` we *do* require the policy given to be present in the
image. This is the only new actual error in this code path that doesn't
get ignored.

We *could* verify that the path exists and also ignore it but I
personally don't think that's the right approach since the actual system
itself would likely also be broken anyhow. Let me know thoughts on that.

There's a tight coupling here still with the *hosts* SELinux policy in
that to set (potentially) unknown labels to the policy loaded in the
host kernel these executables would need to execute in a domain that
allows transitioning to `mac_admin`. I'd say that `install_t` is the
most likely candidate for that. See the first comment on this PR for
more explanation on it/request for input.

---

When mounting `a.raw` before running any tooling against it and showing
the `/etc/shadow` file labels we have:

```
€ sudo systemd-dissect --mount test/a.raw test/mnt/a
€ ls -Zlart test/mnt/a/etc/shadow
----------. 1 root root system_u:object_r:shadow_t:s0 520 Jun 27 07:55 test/mnt/a/etc/shadow
€ sudo systemd-dissect ---umount test/mnt/a
```

After running `systemd-firstboot` against the image, then remounting,
note the labels that have been changed to incorrect values:

```
€ sudo systemd-firstboot --image test/a.raw --root-password test    
/home/user/src/github.com/teamsbc/artifacts/test/a.raw: /etc/passwd written.
/home/user/src/github.com/teamsbc/artifacts/test/a.raw: /etc/shadow written.
€ sudo systemd-dissect --mount test/a.raw test/mnt/a           
€ ls -Zlart test/mnt/a/etc/shadow
----------. 1 root root system_u:object_r:init_var_run_t:s0 579 Jun 27 08:01 test/mnt/a/etc/shadow
```

The behavior before this PR looks up the labels in the label database of
the host, but the path that gets looked up is the path where the image
is temporarily mounted, or in the case of `--root` where the root is on
the host. Since that path doesn't define any labels we get the labels of
the location where the file was created on the host. In this case since
`--image` was used, which mounted things in a temporary location we end
up with `var_run_t`.

If this image is booted things that want to read `/etc/shadow` might not
be allowed to read files labeled this way; thus services fail to start,
and root can't login when SELinux is in enforcing mode.

After this PR is applied there are two main differences in how things
are handled. The first being that instead of reading the label database
from the host (which might have none, or have a different one from the
one contained inside an image or root) we read the label database from
inside the alternate root. This tries to make sure we get the correct
labels for given paths.

Second, and most importantly, if we did init SELinux with an alternate
root then any paths passed to the relevant label lookup functions strip
that alternate root from the path. While previously we'd look up a path
like `/run/dissect-XXXX/etc/shadow` we now look up a path like
`/etc/shadow` *and* this path gets looked up in the label database in
the alternate root.

Together these things give in my opinion better handling of SELinux in
alternate roots. To confirm things work here's the same operations on
the second copy of our image:

```
€ sudo systemd-dissect --mount test/b.raw test/mnt/b
artifacts € ls -Zlart test/mnt/b/etc/shadow
----------. 1 root root system_u:object_r:shadow_t:s0 520 Jun 27 07:55 test/mnt/b/etc/shadow
€ sudo ~/src/github.com/systemd/systemd/build/systemd-firstboot --image test/b.raw --root-password test
/home/user/src/github.com/teamsbc/artifacts/test/b.raw: /etc/passwd written.
/home/user/src/github.com/teamsbc/artifacts/test/b.raw: /etc/shadow written.
€ sudo systemd-dissect --mount test/b.raw test/mnt/b                                                  
€ ls -Zlart test/mnt/b/etc/shadow
----------. 1 root root system_u:object_r:shadow_t:s0 579 Jun 27 08:44 test/mnt/b/etc/shadow
```

Showing that we now have the correct labels applied.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-08-02 02:06:12 +02:00
committed by GitHub
34 changed files with 595 additions and 214 deletions
+4 -4
View File
@@ -665,7 +665,7 @@ static void write_env_var(FILE *f, const char *v) {
fputc_unlocked('\n', f);
}
int write_env_file(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags) {
int write_env_file_label(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags, LabelContext *label_context) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
@@ -675,7 +675,7 @@ int write_env_file(int dir_fd, const char *fname, char **headers, char **l, Writ
bool call_label_ops_post = false;
if (FLAGS_SET(flags, WRITE_ENV_FILE_LABEL)) {
r = label_ops_pre(dir_fd, fname, S_IFREG);
r = label_ops_pre(dir_fd, fname, S_IFREG, label_context);
if (r < 0)
return r;
@@ -683,7 +683,7 @@ int write_env_file(int dir_fd, const char *fname, char **headers, char **l, Writ
}
r = fopen_tmpfile_linkable_at(dir_fd, fname, O_WRONLY|O_CLOEXEC, &p, &f);
int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fname, /* created= */ !!f) : 0;
int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fname, /* created= */ !!f, label_context) : 0;
if (r < 0)
return r;
CLEANUP_TMPFILE_AT(dir_fd, p);
@@ -717,5 +717,5 @@ int write_vconsole_conf(int dir_fd, const char *fname, char **l) {
"# Written by systemd-localed(8) or systemd-firstboot(1), read by systemd-localed",
"# and systemd-vconsole-setup(8). Use localectl(1) to update this file.");
return write_env_file(dir_fd, fname, headers, l, WRITE_ENV_FILE_LABEL);
return write_env_file_label(dir_fd, fname, headers, l, WRITE_ENV_FILE_LABEL, /* label_context= */ NULL);
}
+4 -1
View File
@@ -24,7 +24,10 @@ typedef enum WriteEnvFileFlags {
WRITE_ENV_FILE_LABEL = 1 << 0,
} WriteEnvFileFlags;
int write_env_file(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags);
int write_env_file_label(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags, LabelContext *label_context);
static inline int write_env_file(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags) {
return write_env_file_label(dir_fd, fname, headers, l, flags, /* label_context= */ NULL);
}
int write_vconsole_conf(int dir_fd, const char *fname, char **l);
+10 -8
View File
@@ -219,7 +219,8 @@ static int write_string_file_atomic_at(
const char *fn,
const char *line,
WriteStringFileFlags flags,
const struct timespec *ts) {
const struct timespec *ts,
LabelContext *label_context) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
@@ -235,7 +236,7 @@ static int write_string_file_atomic_at(
bool call_label_ops_post = false;
if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL)) {
r = label_ops_pre(dir_fd, fn, mode);
r = label_ops_pre(dir_fd, fn, mode, label_context);
if (r < 0)
return r;
@@ -243,7 +244,7 @@ static int write_string_file_atomic_at(
}
r = fopen_temporary_at(dir_fd, fn, &f, &p);
int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fn, /* created= */ !!f) : 0;
int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fn, /* created= */ !!f, label_context) : 0;
/* If fopen_temporary_at() failed in the above, propagate the error code, and ignore failures in
* label_ops_post(). */
if (r < 0)
@@ -276,13 +277,14 @@ static int write_string_file_atomic_at(
return 0;
}
int write_string_file_full(
int write_string_file_full_label(
int dir_fd,
const char *fn,
const char *line,
WriteStringFileFlags flags,
const struct timespec *ts,
const char *label_fn) {
const char *label_fn,
LabelContext *label_context) {
bool made_file = false;
_cleanup_fclose_ FILE *f = NULL;
@@ -307,7 +309,7 @@ int write_string_file_full(
assert(fn);
assert(flags & WRITE_STRING_FILE_CREATE);
r = write_string_file_atomic_at(dir_fd, fn, line, flags, ts);
r = write_string_file_atomic_at(dir_fd, fn, line, flags, ts, label_context);
if (r < 0)
goto fail;
@@ -326,7 +328,7 @@ int write_string_file_full(
bool call_label_ops_post = false;
if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) {
r = label_ops_pre(dir_fd, label_fn ?: fn, mode);
r = label_ops_pre(dir_fd, label_fn ?: fn, mode, label_context);
if (r < 0)
goto fail;
@@ -345,7 +347,7 @@ int write_string_file_full(
if (call_label_ops_post)
/* If openat_report_new() failed in the above, propagate the error code, and ignore
* failures in label_ops_post(). */
RET_GATHER(r, label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : fn, made_file));
RET_GATHER(r, label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : fn, made_file, label_context));
}
if (r < 0)
goto fail;
+4 -1
View File
@@ -45,7 +45,10 @@ static inline int write_string_stream(FILE *f, const char *line, WriteStringFile
return write_string_stream_full(f, line, flags, NULL);
}
int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn);
int write_string_file_full_label(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn, LabelContext *label_context);
static inline int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn) {
return write_string_file_full_label(dir_fd, fn, line, flags, ts, label_fn, /* label_context= */ NULL);
}
static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_full(dir_fd, fn, line, flags, NULL, NULL);
}
+1
View File
@@ -128,6 +128,7 @@ typedef struct dual_timestamp dual_timestamp;
typedef struct triple_timestamp triple_timestamp;
typedef struct Compressor Compressor;
typedef struct ConfFile ConfFile;
typedef struct LabelContext LabelContext;
typedef struct LockFile LockFile;
typedef struct PidRef PidRef;
typedef struct Prioq Prioq;
+13 -12
View File
@@ -461,7 +461,7 @@ int symlinkat_idempotent(const char *target, int atfd, const char *linkpath, boo
return 0;
}
int symlinkat_atomic_full(const char *target, int atfd, const char *linkpath, SymlinkFlags flags) {
int symlinkat_atomic_full_label(const char *target, int atfd, const char *linkpath, SymlinkFlags flags, LabelContext *label_context) {
int r;
assert(target);
@@ -483,7 +483,7 @@ int symlinkat_atomic_full(const char *target, int atfd, const char *linkpath, Sy
bool call_label_ops_post = false;
if (FLAGS_SET(flags, SYMLINK_LABEL)) {
r = label_ops_pre(atfd, linkpath, S_IFLNK);
r = label_ops_pre(atfd, linkpath, S_IFLNK, label_context);
if (r < 0)
return r;
@@ -492,7 +492,7 @@ int symlinkat_atomic_full(const char *target, int atfd, const char *linkpath, Sy
r = RET_NERRNO(symlinkat(target, atfd, t));
if (call_label_ops_post)
RET_GATHER(r, label_ops_post(atfd, t, /* created= */ r >= 0));
RET_GATHER(r, label_ops_post(atfd, t, /* created= */ r >= 0, label_context));
if (r < 0)
return r;
@@ -1035,7 +1035,7 @@ int parse_cifs_service(
return 0;
}
int open_mkdir_at_full(int dirfd, const char *path, int flags, XOpenFlags xopen_flags, mode_t mode) {
int open_mkdir_at_full_label(int dirfd, const char *path, int flags, XOpenFlags xopen_flags, mode_t mode, LabelContext *label_context) {
_cleanup_close_ int fd = -EBADF, parent_fd = -EBADF;
_cleanup_free_ char *fname = NULL, *parent = NULL;
int r;
@@ -1071,7 +1071,7 @@ int open_mkdir_at_full(int dirfd, const char *path, int flags, XOpenFlags xopen_
path = fname;
}
fd = xopenat_full(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, xopen_flags, mode);
fd = xopenat_full_label(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, xopen_flags, mode, label_context);
if (IN_SET(fd, -ELOOP, -ENOTDIR))
return -EEXIST;
if (fd < 0)
@@ -1171,7 +1171,7 @@ static int openat_with_automount(int dir_fd, const char *path, int open_flags, m
return RET_NERRNO(openat(dir_fd, path, open_flags, mode));
}
int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) {
int xopenat_full_label(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LabelContext *label_context) {
_cleanup_close_ int fd = -EBADF;
bool made_dir = false, made_file = false;
int r;
@@ -1276,7 +1276,7 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_
bool call_label_ops_post = false;
if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) {
r = label_ops_pre(dir_fd, path, FLAGS_SET(open_flags, O_DIRECTORY) ? S_IFDIR : S_IFREG);
r = label_ops_pre(dir_fd, path, FLAGS_SET(open_flags, O_DIRECTORY) ? S_IFDIR : S_IFREG, label_context);
if (r < 0)
return r;
@@ -1433,7 +1433,7 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_
if (call_label_ops_post) {
call_label_ops_post = false;
r = label_ops_post(fd, /* path= */ NULL, made_file || made_dir);
r = label_ops_post(fd, /* path= */ NULL, made_file || made_dir, label_context);
if (r < 0)
goto error;
}
@@ -1448,7 +1448,7 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_
error:
if (call_label_ops_post)
(void) label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : path, made_dir || made_file);
(void) label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : path, made_dir || made_file, label_context);
if (made_dir || made_file)
(void) unlinkat(dir_fd, path, made_dir ? AT_REMOVEDIR : 0);
@@ -1456,14 +1456,15 @@ error:
return r;
}
int xopenat_lock_full(
int xopenat_lock_full_label(
int dir_fd,
const char *path,
int open_flags,
XOpenFlags xopen_flags,
mode_t mode,
LockType locktype,
int operation) {
int operation,
LabelContext *label_context) {
_cleanup_close_ int fd = -EBADF;
int r;
@@ -1479,7 +1480,7 @@ int xopenat_lock_full(
for (;;) {
struct stat st;
fd = xopenat_full(dir_fd, path, open_flags, xopen_flags, mode);
fd = xopenat_full_label(dir_fd, path, open_flags, xopen_flags, mode, label_context);
if (fd < 0)
return fd;
+16 -4
View File
@@ -58,7 +58,10 @@ typedef enum SymlinkFlags {
SYMLINK_LABEL = 1 << 1,
} SymlinkFlags;
int symlinkat_atomic_full(const char *target, int atfd, const char *linkpath, SymlinkFlags flags);
int symlinkat_atomic_full_label(const char *target, int atfd, const char *linkpath, SymlinkFlags flags, LabelContext *label_context);
static inline int symlinkat_atomic_full(const char *target, int atfd, const char *linkpath, SymlinkFlags flags) {
return symlinkat_atomic_full_label(target, atfd, linkpath, flags, /* label_context= */ NULL);
}
static inline int symlink_atomic(const char *target, const char *linkpath) {
return symlinkat_atomic_full(target, AT_FDCWD, linkpath, 0);
}
@@ -119,7 +122,10 @@ typedef enum XOpenFlags {
XO_AUTO_RW_RO = 1 << 7, /* Open in O_RDWR mode if possible, O_RDONLY if not */
} XOpenFlags;
int open_mkdir_at_full(int dirfd, const char *path, int flags, XOpenFlags xopen_flags, mode_t mode);
int open_mkdir_at_full_label(int dirfd, const char *path, int flags, XOpenFlags xopen_flags, mode_t mode, LabelContext *label_context);
static inline int open_mkdir_at_full(int dirfd, const char *path, int flags, XOpenFlags xopen_flags, mode_t mode) {
return open_mkdir_at_full_label(dirfd, path, flags, xopen_flags, mode, /* label_context= */ NULL);
}
static inline int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) {
return open_mkdir_at_full(dirfd, path, flags, 0, mode);
}
@@ -129,12 +135,18 @@ static inline int open_mkdir(const char *path, int flags, mode_t mode) {
int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, bool *ret_newly_created);
int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode);
int xopenat_full_label(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LabelContext *label_context);
static inline int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) {
return xopenat_full_label(dir_fd, path, open_flags, xopen_flags, mode, /* label_context= */ NULL);
}
static inline int xopenat(int dir_fd, const char *path, int open_flags) {
return xopenat_full(dir_fd, path, open_flags, 0, MODE_INVALID);
}
int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation);
int xopenat_lock_full_label(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation, LabelContext *label_context);
static inline int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation) {
return xopenat_lock_full_label(dir_fd, path, open_flags, xopen_flags, mode, locktype, operation, /* label_context= */ NULL);
}
static inline int xopenat_lock(int dir_fd, const char *path, int open_flags, LockType locktype, int operation) {
return xopenat_lock_full(dir_fd, path, open_flags, 0, 0, locktype, operation);
}
+4 -4
View File
@@ -18,16 +18,16 @@ void label_ops_reset(void) {
label_ops = NULL;
}
int label_ops_pre(int dir_fd, const char *path, mode_t mode) {
int label_ops_pre(int dir_fd, const char *path, mode_t mode, LabelContext *label_context) {
if (!label_ops || !label_ops->pre)
return 0;
return label_ops->pre(dir_fd, path, mode);
return label_ops->pre(dir_fd, path, mode, label_context);
}
int label_ops_post(int dir_fd, const char *path, bool created) {
int label_ops_post(int dir_fd, const char *path, bool created, LabelContext *label_context) {
if (!label_ops || !label_ops->post)
return 0;
return label_ops->post(dir_fd, path, created);
return label_ops->post(dir_fd, path, created, label_context);
}
+4 -4
View File
@@ -4,12 +4,12 @@
#include "forward.h"
typedef struct LabelOps {
int (*pre)(int dir_fd, const char *path, mode_t mode);
int (*post)(int dir_fd, const char *path, bool created);
int (*pre)(int dir_fd, const char *path, mode_t mode, LabelContext *label_context);
int (*post)(int dir_fd, const char *path, bool created, LabelContext *label_context);
} LabelOps;
int label_ops_set(const LabelOps *label_ops);
void label_ops_reset(void);
int label_ops_pre(int dir_fd, const char *path, mode_t mode);
int label_ops_post(int dir_fd, const char *path, bool created);
int label_ops_pre(int dir_fd, const char *path, mode_t mode, LabelContext *label_context);
int label_ops_post(int dir_fd, const char *path, bool created, LabelContext *label_context);
+22 -21
View File
@@ -25,16 +25,17 @@ int mkdirat_safe_internal(
uid_t uid,
gid_t gid,
MkdirFlags flags,
mkdirat_func_t _mkdirat) {
mkdirat_func_t _mkdirat,
LabelContext *label_context) {
struct stat st;
int r;
assert(path);
assert(mode != MODE_INVALID);
assert(_mkdirat && _mkdirat != mkdirat);
assert(_mkdirat);
r = _mkdirat(dir_fd, path, mode);
r = _mkdirat(dir_fd, path, mode, label_context);
if (r >= 0)
return chmod_and_chown_at(dir_fd, path, mode, uid, gid);
if (r != -EEXIST)
@@ -52,7 +53,7 @@ int mkdirat_safe_internal(
if (r == 0)
return mkdirat_safe_internal(dir_fd, p, mode, uid, gid,
flags & ~MKDIR_FOLLOW_SYMLINK,
_mkdirat);
_mkdirat, label_context);
if (fstatat(dir_fd, p, &st, AT_SYMLINK_NOFOLLOW) < 0)
return -errno;
@@ -80,20 +81,20 @@ int mkdirat_safe_internal(
return 0;
}
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode) {
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode, LabelContext *label_context) {
return RET_NERRNO(mkdirat(dirfd, pathname, mode));
}
int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_errno_wrapper, /* label_context= */ NULL);
}
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context) {
const char *e = NULL;
int r;
assert(path);
assert(_mkdirat != mkdirat);
assert(_mkdirat);
if (isempty(path))
return 0;
@@ -134,7 +135,7 @@ int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t ui
s[n] = '\0';
r = mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat);
r = mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat, label_context);
if (r < 0 && r != -EEXIST)
return r;
@@ -142,12 +143,12 @@ int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t ui
}
}
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context) {
_cleanup_close_ int fd = AT_FDCWD;
const char *p;
assert(path);
assert(_mkdirat != mkdirat);
assert(_mkdirat);
if (prefix) {
p = path_startswith_full(path, prefix, PATH_STARTSWITH_REFUSE_DOT_DOT);
@@ -160,34 +161,34 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui
} else
p = path;
return mkdirat_parents_internal(fd, p, mode, uid, gid, flags, _mkdirat);
return mkdirat_parents_internal(fd, p, mode, uid, gid, flags, _mkdirat, label_context);
}
int mkdirat_parents(int dir_fd, const char *path, mode_t mode) {
return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper, /* label_context= */ NULL);
}
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
return mkdir_parents_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
return mkdir_parents_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper, /* label_context= */ NULL);
}
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context) {
int r;
/* Like mkdir -p */
assert(_mkdirat != mkdirat);
assert(_mkdirat);
r = mkdir_parents_internal(prefix, path, mode, uid, gid, flags | MKDIR_FOLLOW_SYMLINK, _mkdirat);
r = mkdir_parents_internal(prefix, path, mode, uid, gid, flags | MKDIR_FOLLOW_SYMLINK, _mkdirat, label_context);
if (r < 0)
return r;
if (!uid_is_valid(uid) && !gid_is_valid(gid) && flags == 0) {
r = _mkdirat(AT_FDCWD, path, mode);
r = _mkdirat(AT_FDCWD, path, mode, label_context);
if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0))
return r;
} else {
r = mkdir_safe_internal(path, mode, uid, gid, flags, _mkdirat);
r = mkdir_safe_internal(path, mode, uid, gid, flags, _mkdirat, label_context);
if (r < 0 && r != -EEXIST)
return r;
}
@@ -196,11 +197,11 @@ int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t ui
}
int mkdir_p(const char *path, mode_t mode) {
return mkdir_p_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
return mkdir_p_internal(/* prefix= */ NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper, /* label_context= */ NULL);
}
int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper, /* label_context= */ NULL);
}
int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m, usec_t ts, Hashmap *subvolumes) {
+8 -8
View File
@@ -9,7 +9,7 @@ typedef enum MkdirFlags {
MKDIR_WARN_MODE = 1 << 2, /* Log at LOG_WARNING when mode doesn't match */
} MkdirFlags;
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode);
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode, LabelContext *label_context);
int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
static inline int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
@@ -28,11 +28,11 @@ static inline int mkdir_p_root(const char *root, const char *p, uid_t uid, gid_t
}
/* The following are used to implement the mkdir_xyz_label() calls, don't use otherwise. */
typedef int (*mkdirat_func_t)(int dir_fd, const char *pathname, mode_t mode);
int mkdirat_safe_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
static inline int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir) {
return mkdirat_safe_internal(AT_FDCWD, path, mode, uid, gid, flags, _mkdir);
typedef int (*mkdirat_func_t)(int dir_fd, const char *pathname, mode_t mode, LabelContext *label_context);
int mkdirat_safe_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir, LabelContext *label_context);
static inline int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir, LabelContext *label_context) {
return mkdirat_safe_internal(AT_FDCWD, path, mode, uid, gid, flags, _mkdir, label_context);
}
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir);
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir, LabelContext *label_context);
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdir, LabelContext *label_context);