diff options
author | Lennart Poettering <lennart@poettering.net> | 2024-10-21 22:43:18 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2024-10-22 17:51:26 +0200 |
commit | 64053bed083d24f2151d05951935d0804173e657 (patch) | |
tree | 29b01d0b1a60537abad5c047e5be5658c49b7bc8 /src/basic | |
parent | fs-util: don't second guess openat_report_new() return values (diff) | |
download | systemd-64053bed083d24f2151d05951935d0804173e657.tar.xz systemd-64053bed083d24f2151d05951935d0804173e657.zip |
fs-util: always call label post ops in xopenat_full(), in both success and error path
For SELinux it is essential that we reset the file creation label both
in the success and in the error path, hence do so.
Moreover, when calling the label post ops do it if possible with the
opened fd of the inode itself, rather than always going via its path,
simply to reduce the attack surface.
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/fs-util.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 53206c3b37..1d0533e4f0 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1164,10 +1164,14 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_ return fd_reopen(dir_fd, open_flags & ~O_NOFOLLOW); } + 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); if (r < 0) return r; + + call_label_ops_post = true; } if (FLAGS_SET(open_flags, O_DIRECTORY|O_CREAT)) { @@ -1183,14 +1187,7 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_ else made_dir = true; - if (FLAGS_SET(xopen_flags, XO_LABEL)) { - r = label_ops_post(dir_fd, path, made_dir); - if (r < 0) - goto error; - } - open_flags &= ~(O_EXCL|O_CREAT); - xopen_flags &= ~XO_LABEL; } fd = openat_report_new(dir_fd, path, open_flags, mode, &made_file); @@ -1199,8 +1196,10 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_ goto error; } - if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) { - r = label_ops_post(dir_fd, path, made_file || made_dir); + if (call_label_ops_post) { + call_label_ops_post = false; + + r = label_ops_post(fd, /* path= */ NULL, made_file || made_dir); if (r < 0) goto error; } @@ -1214,6 +1213,9 @@ int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_ return TAKE_FD(fd); error: + if (call_label_ops_post) + (void) label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : path, made_dir || made_file); + if (made_dir || made_file) (void) unlinkat(dir_fd, path, made_dir ? AT_REMOVEDIR : 0); |