summaryrefslogtreecommitdiffstats
path: root/src/basic/tmpfile-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2024-03-13 12:43:43 +0100
committerLennart Poettering <lennart@poettering.net>2024-03-14 09:22:09 +0100
commitccec206498fd66ba1b6b05548ac827b661be566f (patch)
tree67fdcac34ef1bf6f77776f27c9b4d91b882bf48a /src/basic/tmpfile-util.c
parentfs-util: add new helper linkat_replace() (diff)
downloadsystemd-ccec206498fd66ba1b6b05548ac827b661be566f.tar.xz
systemd-ccec206498fd66ba1b6b05548ac827b661be566f.zip
tmpfile-util: port link_tmpfile_at() over to linkat_replace()
Diffstat (limited to '')
-rw-r--r--src/basic/tmpfile-util.c32
1 files changed, 6 insertions, 26 deletions
diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c
index 4cae5cbd0b..3a3f7dcc0f 100644
--- a/src/basic/tmpfile-util.c
+++ b/src/basic/tmpfile-util.c
@@ -331,7 +331,6 @@ int fopen_tmpfile_linkable(const char *target, int flags, char **ret_path, FILE
}
int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, LinkTmpfileFlags flags) {
- _cleanup_free_ char *tmp = NULL;
int r;
assert(fd >= 0);
@@ -350,33 +349,14 @@ int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, Li
r = RET_NERRNO(renameat(dir_fd, path, dir_fd, target));
else
r = rename_noreplace(dir_fd, path, dir_fd, target);
- if (r < 0)
- return r;
} else {
-
- r = link_fd(fd, dir_fd, target);
- if (r != -EEXIST || !FLAGS_SET(flags, LINK_TMPFILE_REPLACE))
- return r;
-
- /* So the target already exists and we were asked to replace it. That sucks a bit, since the kernel's
- * linkat() logic does not allow that. We work-around this by linking the file to a random name
- * first, and then renaming that to the final name. This reintroduces the race O_TMPFILE kinda is
- * trying to fix, but at least the vulnerability window (i.e. where the file is linked into the file
- * system under a temporary name) is very short. */
-
- r = tempfn_random(target, NULL, &tmp);
- if (r < 0)
- return r;
-
- if (link_fd(fd, dir_fd, tmp) < 0)
- return -EEXIST; /* propagate original error */
-
- r = RET_NERRNO(renameat(dir_fd, tmp, dir_fd, target));
- if (r < 0) {
- (void) unlinkat(dir_fd, tmp, 0);
- return r;
- }
+ if (FLAGS_SET(flags, LINK_TMPFILE_REPLACE))
+ r = linkat_replace(fd, /* oldpath= */ NULL, dir_fd, target);
+ else
+ r = link_fd(fd, dir_fd, target);
}
+ if (r < 0)
+ return r;
if (FLAGS_SET(flags, LINK_TMPFILE_SYNC)) {
r = fsync_full(fd);