summaryrefslogtreecommitdiffstats
path: root/src/basic
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2024-10-21 22:43:18 +0200
committerLennart Poettering <lennart@poettering.net>2024-10-22 17:51:26 +0200
commit64053bed083d24f2151d05951935d0804173e657 (patch)
tree29b01d0b1a60537abad5c047e5be5658c49b7bc8 /src/basic
parentfs-util: don't second guess openat_report_new() return values (diff)
downloadsystemd-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.c20
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);