From 361bcb2097cd9c163f780863c9bd254b4c9c91c8 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 22 Dec 2022 14:26:29 +0100 Subject: [PATCH 1/4] env-file: Add write_env_file_at() --- src/basic/env-file.c | 9 +++++---- src/basic/env-file.h | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/basic/env-file.c b/src/basic/env-file.c index 45b0d901c5..16de727c09 100644 --- a/src/basic/env-file.c +++ b/src/basic/env-file.c @@ -578,14 +578,15 @@ static void write_env_var(FILE *f, const char *v) { fputc_unlocked('\n', f); } -int write_env_file(const char *fname, char **l) { +int write_env_file_at(int dir_fd, const char *fname, char **l) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(fname); - r = fopen_temporary(fname, &f, &p); + r = fopen_temporary_at(dir_fd, fname, &f, &p); if (r < 0) return r; @@ -596,12 +597,12 @@ int write_env_file(const char *fname, char **l) { r = fflush_and_check(f); if (r >= 0) { - if (rename(p, fname) >= 0) + if (renameat(dir_fd, p, dir_fd, fname) >= 0) return 0; r = -errno; } - (void) unlink(p); + (void) unlinkat(dir_fd, p, 0); return r; } diff --git a/src/basic/env-file.h b/src/basic/env-file.h index 2448d943cd..dc38b7a5c9 100644 --- a/src/basic/env-file.h +++ b/src/basic/env-file.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include #include #include @@ -16,4 +17,7 @@ int load_env_file_pairs(FILE *f, const char *fname, char ***ret); int merge_env_file(char ***env, FILE *f, const char *fname); -int write_env_file(const char *fname, char **l); +int write_env_file_at(int dir_fd, const char *fname, char **l); +static inline int write_env_file(const char *fname, char **l) { + return write_env_file_at(AT_FDCWD, fname, l); +} From d9daf0d14443a995077744fb9b407094f0ca9302 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 22 Dec 2022 14:27:26 +0100 Subject: [PATCH 2/4] copy: Add copy_file_at() --- src/shared/copy.c | 16 ++++++++++------ src/shared/copy.h | 10 ++++++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/shared/copy.c b/src/shared/copy.c index d15875739a..a1df3048ba 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -1329,8 +1329,10 @@ int copy_file_fd_full( return 0; } -int copy_file_full( +int copy_file_at_full( + int dir_fdf, const char *from, + int dir_fdt, const char *to, int flags, mode_t mode, @@ -1344,10 +1346,12 @@ int copy_file_full( struct stat st; int r; + assert(dir_fdf >= 0 || dir_fdf == AT_FDCWD); + assert(dir_fdt >= 0 || dir_fdt == AT_FDCWD); assert(from); assert(to); - fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY); + fdf = openat(dir_fdf, from, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fdf < 0) return -errno; @@ -1360,11 +1364,11 @@ int copy_file_full( WITH_UMASK(0000) { if (copy_flags & COPY_MAC_CREATE) { - r = mac_selinux_create_file_prepare(to, S_IFREG); + r = mac_selinux_create_file_prepare_at(dir_fdt, to, S_IFREG); if (r < 0) return r; } - fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, + fdt = openat(dir_fdt, to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode != MODE_INVALID ? mode : st.st_mode); if (copy_flags & COPY_MAC_CREATE) mac_selinux_create_file_clear(); @@ -1403,7 +1407,7 @@ int copy_file_full( goto fail; if (copy_flags & COPY_FSYNC_FULL) { - r = fsync_parent_at(AT_FDCWD, to); + r = fsync_parent_at(dir_fdt, to); if (r < 0) goto fail; } @@ -1413,7 +1417,7 @@ int copy_file_full( fail: /* Only unlink if we definitely are the ones who created the file */ if (FLAGS_SET(flags, O_EXCL)) - (void) unlink(to); + (void) unlinkat(dir_fdt, to, 0); return r; } diff --git a/src/shared/copy.h b/src/shared/copy.h index 22151ff83b..cb40a10f09 100644 --- a/src/shared/copy.h +++ b/src/shared/copy.h @@ -38,9 +38,15 @@ static inline int copy_file_fd(const char *from, int to, CopyFlags copy_flags) { return copy_file_fd_full(from, to, copy_flags, NULL, NULL); } -int copy_file_full(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +int copy_file_at_full(int dir_fdf, const char *from, int dir_fdt, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +static inline int copy_file_at(int dir_fdf, const char *from, int dir_fdt, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags) { + return copy_file_at_full(dir_fdf, from, dir_fdt, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL); +} +static inline int copy_file_full(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata) { + return copy_file_at_full(AT_FDCWD, from, AT_FDCWD, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, progress, userdata); +} static inline int copy_file(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags) { - return copy_file_full(from, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL); + return copy_file_at(AT_FDCWD, from, AT_FDCWD, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags); } int copy_file_atomic_full(const char *from, const char *to, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); From e8729892e88e7dacf52b39a8f859eb70d946b37e Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 22 Dec 2022 14:27:57 +0100 Subject: [PATCH 3/4] tmpfile-util-label: Add fopen_temporary_at_label() --- src/shared/tmpfile-util-label.c | 8 +++++--- src/shared/tmpfile-util-label.h | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/shared/tmpfile-util-label.c b/src/shared/tmpfile-util-label.c index 17c5038b51..a5f364cba0 100644 --- a/src/shared/tmpfile-util-label.c +++ b/src/shared/tmpfile-util-label.c @@ -6,7 +6,8 @@ #include "tmpfile-util-label.h" #include "tmpfile-util.h" -int fopen_temporary_label( +int fopen_temporary_at_label( + int dir_fd, const char *target, const char *path, FILE **f, @@ -14,13 +15,14 @@ int fopen_temporary_label( int r; + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(path); - r = mac_selinux_create_file_prepare(target, S_IFREG); + r = mac_selinux_create_file_prepare_at(dir_fd, target, S_IFREG); if (r < 0) return r; - r = fopen_temporary(path, f, temp_path); + r = fopen_temporary_at(dir_fd, path, f, temp_path); mac_selinux_create_file_clear(); diff --git a/src/shared/tmpfile-util-label.h b/src/shared/tmpfile-util-label.h index 4987057f13..68ab0755a9 100644 --- a/src/shared/tmpfile-util-label.h +++ b/src/shared/tmpfile-util-label.h @@ -1,10 +1,14 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include #include /* These functions are split out of tmpfile-util.h (and not for example just flags to the functions they * wrap) in order to optimize linking: this way, -lselinux is needed only for the callers of these functions * that need selinux, but not for all. */ -int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path); +int fopen_temporary_at_label(int dir_fd, const char *target, const char *path, FILE **f, char **temp_path); +static inline int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path) { + return fopen_temporary_at_label(AT_FDCWD, target, path, f, temp_path); +} From 9dcb8923ccfc1cfaac3a0ca6f2b632e1fca560ce Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 22 Dec 2022 14:28:27 +0100 Subject: [PATCH 4/4] smack-util: Add renameat_and_apply_smack_floor_label() Also add mac_smack_apply_at() as its a requirement for renameat_and_apply_smack_floor_label(). --- src/shared/smack-util.c | 22 +++++++++++----------- src/shared/smack-util.h | 10 ++++++++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/shared/smack-util.c b/src/shared/smack-util.c index b3b5c905ad..60fd24c0ba 100644 --- a/src/shared/smack-util.c +++ b/src/shared/smack-util.c @@ -67,8 +67,8 @@ int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { return fgetxattr_malloc(fd, smack_attr_to_string(attr), label); } -int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { - int r; +int mac_smack_apply_at(int dir_fd, const char *path, SmackAttr attr, const char *label) { + _cleanup_close_ int fd = -EBADF; assert(path); assert(attr >= 0 && attr < _SMACK_ATTR_MAX); @@ -76,14 +76,11 @@ int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { if (!mac_smack_use()) return 0; - if (label) - r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0); - else - r = lremovexattr(path, smack_attr_to_string(attr)); - if (r < 0) + fd = openat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (fd < 0) return -errno; - return 0; + return mac_smack_apply_fd(fd, attr, label); } int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { @@ -277,13 +274,16 @@ int mac_smack_copy(const char *dest, const char *src) { } #endif -int rename_and_apply_smack_floor_label(const char *from, const char *to) { +int renameat_and_apply_smack_floor_label(int fdf, const char *from, int fdt, const char *to) { - if (rename(from, to) < 0) + assert(fdf >= 0 || fdf == AT_FDCWD); + assert(fdt >= 0 || fdt == AT_FDCWD); + + if (renameat(fdf, from, fdt, to) < 0) return -errno; #if HAVE_SMACK_RUN_LABEL - return mac_smack_apply(to, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); + return mac_smack_apply_at(fdt, to, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); #else return 0; #endif diff --git a/src/shared/smack-util.h b/src/shared/smack-util.h index da8be5e6f0..17b31c6c25 100644 --- a/src/shared/smack-util.h +++ b/src/shared/smack-util.h @@ -38,9 +38,15 @@ const char* smack_attr_to_string(SmackAttr i) _const_; SmackAttr smack_attr_from_string(const char *s) _pure_; int mac_smack_read(const char *path, SmackAttr attr, char **label); int mac_smack_read_fd(int fd, SmackAttr attr, char **label); -int mac_smack_apply(const char *path, SmackAttr attr, const char *label); +int mac_smack_apply_at(int dir_fd, const char *path, SmackAttr attr, const char *label); +static inline int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { + return mac_smack_apply_at(AT_FDCWD, path, attr, label); +} int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label); int mac_smack_apply_pid(pid_t pid, const char *label); int mac_smack_copy(const char *dest, const char *src); -int rename_and_apply_smack_floor_label(const char *temp_path, const char *dest_path); +int renameat_and_apply_smack_floor_label(int fdf, const char *from, int fdt, const char *to); +static inline int rename_and_apply_smack_floor_label(const char *from, const char *to) { + return renameat_and_apply_smack_floor_label(AT_FDCWD, from, AT_FDCWD, to); +}