Merge pull request #34850 from poettering/openat-report-new-tweaks

openat_report_new() tweaks
This commit is contained in:
Lennart Poettering
2024-10-23 10:25:18 +02:00
committed by GitHub
25 changed files with 180 additions and 200 deletions

View File

@@ -18,6 +18,7 @@
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "label.h"
#include "log.h"
#include "macro.h"
#include "mkdir.h"
@@ -230,22 +231,40 @@ static int write_string_file_atomic_at(
/* Note that we'd really like to use O_TMPFILE here, but can't really, since we want replacement
* semantics here, and O_TMPFILE can't offer that. i.e. rename() replaces but linkat() doesn't. */
mode_t mode = write_string_file_flags_to_mode(flags);
bool call_label_ops_post = false;
if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL)) {
r = label_ops_pre(dir_fd, fn, mode);
if (r < 0)
return r;
call_label_ops_post = true;
}
r = fopen_temporary_at(dir_fd, fn, &f, &p);
if (r < 0)
return r;
goto fail;
if (call_label_ops_post) {
call_label_ops_post = false;
r = label_ops_post(fileno(f), /* path= */ NULL, /* created= */ true);
if (r < 0)
goto fail;
}
r = write_string_stream_full(f, line, flags, ts);
if (r < 0)
goto fail;
r = fchmod_umask(fileno(f), write_string_file_flags_to_mode(flags));
r = fchmod_umask(fileno(f), mode);
if (r < 0)
goto fail;
if (renameat(dir_fd, p, dir_fd, fn) < 0) {
r = -errno;
r = RET_NERRNO(renameat(dir_fd, p, dir_fd, fn));
if (r < 0)
goto fail;
}
if (FLAGS_SET(flags, WRITE_STRING_FILE_SYNC)) {
/* Sync the rename, too */
@@ -257,7 +276,11 @@ static int write_string_file_atomic_at(
return 0;
fail:
(void) unlinkat(dir_fd, p, 0);
if (call_label_ops_post)
(void) label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fn, /* created= */ !!f);
if (f)
(void) unlinkat(dir_fd, p, 0);
return r;
}
@@ -268,9 +291,10 @@ int write_string_file_full(
WriteStringFileFlags flags,
const struct timespec *ts) {
bool call_label_ops_post = false, made_file = false;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_close_ int fd = -EBADF;
int q, r;
int r;
assert(fn);
assert(line);
@@ -292,21 +316,40 @@ int write_string_file_full(
goto fail;
return r;
} else
assert(!ts);
}
mode_t mode = write_string_file_flags_to_mode(flags);
if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) {
r = label_ops_pre(dir_fd, fn, mode);
if (r < 0)
goto fail;
call_label_ops_post = true;
}
/* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */
fd = openat(dir_fd, fn, O_CLOEXEC|O_NOCTTY |
(FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY),
write_string_file_flags_to_mode(flags));
fd = openat_report_new(
dir_fd, fn, O_CLOEXEC | O_NOCTTY |
(FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |
(FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY),
mode,
&made_file);
if (fd < 0) {
r = -errno;
r = fd;
goto fail;
}
if (call_label_ops_post) {
call_label_ops_post = false;
r = label_ops_post(fd, /* path= */ NULL, made_file);
if (r < 0)
goto fail;
}
r = take_fdopen_unlocked(&fd, "w", &f);
if (r < 0)
goto fail;
@@ -321,19 +364,24 @@ int write_string_file_full(
return 0;
fail:
if (call_label_ops_post)
(void) label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : fn, made_file);
if (made_file)
(void) unlinkat(dir_fd, fn, 0);
if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
return r;
f = safe_fclose(f);
fd = safe_close(fd);
/* OK, the operation failed, but let's see if the right
* contents in place already. If so, eat up the error. */
/* OK, the operation failed, but let's see if the right contents in place already. If so, eat up the
* error. */
if (verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) || (flags & WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE)) > 0)
return 0;
q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) || (flags & WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE));
if (q <= 0)
return r;
return 0;
return r;
}
int write_string_filef(

View File

@@ -28,11 +28,7 @@ typedef enum {
WRITE_STRING_FILE_MODE_0600 = 1 << 10,
WRITE_STRING_FILE_MODE_0444 = 1 << 11,
WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL = 1 << 12,
/* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one
more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()
and friends. */
WRITE_STRING_FILE_LABEL = 1 << 13,
} WriteStringFileFlags;
typedef enum {

View File

@@ -1077,65 +1077,50 @@ int open_mkdir_at_full(int dirfd, const char *path, int flags, XOpenFlags xopen_
}
int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, bool *ret_newly_created) {
unsigned attempts = 7;
int fd;
/* Just like openat(), but adds one thing: optionally returns whether we created the file anew or if
* it already existed before. This is only relevant if O_CREAT is set without O_EXCL, and thus will
* shortcut to openat() otherwise */
if (!ret_newly_created)
return RET_NERRNO(openat(dirfd, pathname, flags, mode));
* shortcut to openat() otherwise.
*
* Note that this routine is a bit more strict with symlinks than regular openat() is. If O_NOFOLLOW
* is not specified, then we'll follow the symlink when opening an existing file but we will *not*
* follow it when creating a new one (because that's a terrible UNIX misfeature and generally a
* security hole). */
if (!FLAGS_SET(flags, O_CREAT) || FLAGS_SET(flags, O_EXCL)) {
fd = openat(dirfd, pathname, flags, mode);
if (fd < 0)
return -errno;
*ret_newly_created = FLAGS_SET(flags, O_CREAT);
if (ret_newly_created)
*ret_newly_created = FLAGS_SET(flags, O_CREAT);
return fd;
}
for (;;) {
for (unsigned attempts = 7;;) {
/* First, attempt to open without O_CREAT/O_EXCL, i.e. open existing file */
fd = openat(dirfd, pathname, flags & ~(O_CREAT | O_EXCL), mode);
if (fd >= 0) {
*ret_newly_created = false;
if (ret_newly_created)
*ret_newly_created = false;
return fd;
}
if (errno != ENOENT)
return -errno;
/* So the file didn't exist yet, hence create it with O_CREAT/O_EXCL. */
fd = openat(dirfd, pathname, flags | O_CREAT | O_EXCL, mode);
/* So the file didn't exist yet, hence create it with O_CREAT/O_EXCL/O_NOFOLLOW. */
fd = openat(dirfd, pathname, flags | O_CREAT | O_EXCL | O_NOFOLLOW, mode);
if (fd >= 0) {
*ret_newly_created = true;
if (ret_newly_created)
*ret_newly_created = true;
return fd;
}
if (errno != EEXIST)
return -errno;
/* Hmm, so now we got EEXIST? This can indicate two things. First, if the path points to a
* dangling symlink, the first openat() will fail with ENOENT because the symlink is resolved
* and the second openat() will fail with EEXIST because symlinks are not followed when
* O_CREAT|O_EXCL is specified. Let's check for this explicitly and fall back to opening with
* just O_CREAT and assume we're the ones that created the file. */
struct stat st;
if (fstatat(dirfd, pathname, &st, AT_SYMLINK_NOFOLLOW) < 0)
return -errno;
if (S_ISLNK(st.st_mode)) {
fd = openat(dirfd, pathname, flags | O_CREAT, mode);
if (fd < 0)
return -errno;
*ret_newly_created = true;
return fd;
}
/* If we're not operating on a symlink, someone might have created the file between the first
* and second call to openat(). Let's try again but with a limit so we don't spin forever. */
/* Hmm, so now we got EEXIST? Then someone might have created the file between the first and
* second call to openat(). Let's try again but with a limit so we don't spin forever. */
if (--attempts == 0) /* Give up eventually, somebody is playing with us */
return -EEXIST;
@@ -1164,10 +1149,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,37 +1172,19 @@ 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);
if (r < 0)
return r;
}
open_flags &= ~(O_EXCL|O_CREAT);
xopen_flags &= ~XO_LABEL;
}
fd = RET_NERRNO(openat_report_new(dir_fd, path, open_flags, mode, &made_file));
fd = openat_report_new(dir_fd, path, open_flags, mode, &made_file);
if (fd < 0) {
if (IN_SET(fd,
/* We got ENOENT? then someone else immediately removed it after we
* created it. In that case let's return immediately without unlinking
* anything, because there simply isn't anything to unlink anymore. */
-ENOENT,
/* is a symlink? exists already → created by someone else, don't unlink */
-ELOOP,
/* not a directory? exists already → created by someone else, don't unlink */
-ENOTDIR))
return fd;
if (made_dir)
(void) unlinkat(dir_fd, path, AT_REMOVEDIR);
return fd;
r = fd;
goto error;
}
if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) {
r = label_ops_post(dir_fd, path);
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;
}
@@ -1227,6 +1198,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);

View File

@@ -4,10 +4,13 @@
#include <stddef.h>
#include "label.h"
#include "macro.h"
static const LabelOps *label_ops = NULL;
int label_ops_set(const LabelOps *ops) {
assert(ops);
if (label_ops)
return -EBUSY;
@@ -15,6 +18,10 @@ int label_ops_set(const LabelOps *ops) {
return 0;
}
void label_ops_reset(void) {
label_ops = NULL;
}
int label_ops_pre(int dir_fd, const char *path, mode_t mode) {
if (!label_ops || !label_ops->pre)
return 0;
@@ -22,13 +29,9 @@ int label_ops_pre(int dir_fd, const char *path, mode_t mode) {
return label_ops->pre(dir_fd, path, mode);
}
int label_ops_post(int dir_fd, const char *path) {
int label_ops_post(int dir_fd, const char *path, bool created) {
if (!label_ops || !label_ops->post)
return 0;
return label_ops->post(dir_fd, path);
}
void label_ops_reset(void) {
label_ops = NULL;
return label_ops->post(dir_fd, path, created);
}

View File

@@ -1,15 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
#include <sys/types.h>
typedef struct LabelOps {
int (*pre)(int dir_fd, const char *path, mode_t mode);
int (*post)(int dir_fd, const char *path);
int (*post)(int dir_fd, const char *path, bool created);
} 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);
void label_ops_reset(void);
int label_ops_post(int dir_fd, const char *path, bool created);

View File

@@ -4,7 +4,6 @@
#include "bpf-socket-bind.h"
#include "bus-util.h"
#include "dbus.h"
#include "fileio-label.h"
#include "fileio.h"
#include "format-util.h"
#include "parse-util.h"

View File

@@ -29,7 +29,6 @@
#include "exec-credential.h"
#include "execute.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "format-util.h"
#include "id128-util.h"
@@ -4620,7 +4619,7 @@ int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const ch
return r;
}
r = write_string_file_atomic_label(q, wrapped);
r = write_string_file(q, wrapped, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL);
if (r < 0)
return r;

View File

@@ -7,7 +7,7 @@
#include "dropin.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "generator.h"
#include "initrd-util.h"
#include "parse-util.h"
@@ -206,7 +206,7 @@ static int process_unit_credentials(const char *credentials_dir) {
if (!p)
return log_oom();
r = write_string_file_at_label(AT_FDCWD, p, d, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755);
r = write_string_file(p, d, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL);
if (r < 0) {
log_warning_errno(r, "Failed to write unit file '%s' from credential '%s', ignoring: %m",
unit, de->d_name);

View File

@@ -19,7 +19,6 @@
#include "env-file-label.h"
#include "env-file.h"
#include "env-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "hostname-setup.h"
#include "hostname-util.h"
@@ -619,7 +618,7 @@ static int context_write_data_static_hostname(Context *c) {
return 0;
}
r = write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
r = write_string_file("/etc/hostname", c->data[PROP_STATIC_HOSTNAME], WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL);
if (r < 0)
return r;

View File

@@ -11,7 +11,6 @@
#include "env-file.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "fs-util.h"
#include "kbd-util.h"

View File

@@ -29,7 +29,6 @@
#include "escape.h"
#include "event-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "format-util.h"
#include "fs-util.h"
@@ -1593,7 +1592,7 @@ static int trigger_device(Manager *m, sd_device *parent) {
static int attach_device(Manager *m, const char *seat, const char *sysfs, sd_bus_error *error) {
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
_cleanup_free_ char *rule = NULL, *file = NULL;
_cleanup_free_ char *file = NULL;
const char *id_for_seat;
int r;
@@ -1614,11 +1613,10 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs, sd_bus
if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
return -ENOMEM;
if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
return -ENOMEM;
(void) mkdir_p_label("/etc/udev/rules.d", 0755);
r = write_string_file_atomic_label(file, rule);
r = write_string_filef(
file,
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL,
"TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat);
if (r < 0)
return r;
@@ -3286,11 +3284,9 @@ static int method_set_reboot_to_boot_loader_menu(
if (unlink("/run/systemd/reboot-to-boot-loader-menu") < 0 && errno != ENOENT)
return -errno;
} else {
char buf[DECIMAL_STR_MAX(uint64_t) + 1];
xsprintf(buf, "%" PRIu64, x); /* μs granularity */
r = write_string_file_atomic_label("/run/systemd/reboot-to-boot-loader-menu", buf);
r = write_string_filef("/run/systemd/reboot-to-boot-loader-menu",
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL,
"%" PRIu64, x); /* μs granularity */
if (r < 0)
return r;
}
@@ -3479,7 +3475,7 @@ static int method_set_reboot_to_boot_loader_entry(
if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT)
return -errno;
} else {
r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v);
r = write_string_file("/run/systemd/reboot-boot-to-loader-entry", v, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL);
if (r < 0)
return r;
}

View File

@@ -12,7 +12,7 @@
#include "dropin.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "hashmap.h"
#include "log.h"
#include "macro.h"
@@ -87,7 +87,7 @@ int write_drop_in(
if (r < 0)
return r;
return write_string_file_at_label(AT_FDCWD, p, data, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755);
return write_string_file(p, data, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL);
}
int write_drop_in_format(

View File

@@ -1,43 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/stat.h>
#include "fileio-label.h"
#include "fileio.h"
#include "selinux-util.h"
int write_string_file_full_label(int atfd, const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) {
int r;
r = mac_selinux_create_file_prepare_at(atfd, fn, S_IFREG);
if (r < 0)
return r;
r = write_string_file_full(atfd, fn, line, flags, ts);
mac_selinux_create_file_clear();
return r;
}
int create_shutdown_run_nologin_or_warn(void) {
int r;
/* This is used twice: once in systemd-user-sessions.service, in order to block logins when we
* actually go down, and once in systemd-logind.service when shutdowns are scheduled, and logins are
* to be turned off a bit in advance. We use the same wording of the message in both cases.
*
* Traditionally, there was only /etc/nologin, and we managed that. Then, in PAM 1.1
* support for /run/nologin was added as alternative
* (https://github.com/linux-pam/linux-pam/commit/e9e593f6ddeaf975b7fe8446d184e6bc387d450b).
* 13 years later we stopped managing /etc/nologin, leaving it for the administrator to manage.
*/
r = write_string_file_atomic_label("/run/nologin",
"System is going down. Unprivileged users are not permitted to log in anymore. "
"For technical details, see pam_nologin(8).");
if (r < 0)
return log_error_errno(r, "Failed to create /run/nologin: %m");
return 0;
}

View File

@@ -1,20 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdio.h>
/* These functions are split out of fileio.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 */
#include "fileio.h"
int write_string_file_full_label(int atfd, const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts);
static inline int write_string_file_at_label(int atfd, const char *fn, const char *line, WriteStringFileFlags flags) {
return write_string_file_full_label(atfd, fn, line, flags, /* ts= */ NULL);
}
static inline int write_string_file_atomic_label(const char *fn, const char *line) {
return write_string_file_at_label(AT_FDCWD, fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
}
int create_shutdown_run_nologin_or_warn(void);

View File

@@ -72,7 +72,6 @@ shared_sources = files(
'extension-util.c',
'fdset.c',
'fido2-util.c',
'fileio-label.c',
'find-esp.c',
'firewall-util-nft.c',
'firewall-util.c',

View File

@@ -204,3 +204,26 @@ bool kexec_loaded(void) {
return s[0] == '1';
}
int create_shutdown_run_nologin_or_warn(void) {
int r;
/* This is used twice: once in systemd-user-sessions.service, in order to block logins when we
* actually go down, and once in systemd-logind.service when shutdowns are scheduled, and logins are
* to be turned off a bit in advance. We use the same wording of the message in both cases.
*
* Traditionally, there was only /etc/nologin, and we managed that. Then, in PAM 1.1
* support for /run/nologin was added as alternative
* (https://github.com/linux-pam/linux-pam/commit/e9e593f6ddeaf975b7fe8446d184e6bc387d450b).
* 13 years later we stopped managing /etc/nologin, leaving it for the administrator to manage.
*/
r = write_string_file("/run/nologin",
"System is going down. Unprivileged users are not permitted to log in anymore. "
"For technical details, see pam_nologin(8).",
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL);
if (r < 0)
return log_error_errno(r, "Failed to create /run/nologin: %m");
return 0;
}

View File

@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
bool reboot_parameter_is_valid(const char *parameter);
int update_reboot_parameter_and_warn(const char *parameter, bool keep);
@@ -16,3 +18,5 @@ int reboot_with_parameter(RebootFlags flags);
bool shall_restore_state(void);
bool kexec_loaded(void);
int create_shutdown_run_nologin_or_warn(void);

View File

@@ -64,7 +64,7 @@ static int mac_selinux_label_pre(int dir_fd, const char *path, mode_t mode) {
return mac_selinux_create_file_prepare_at(dir_fd, path, mode);
}
static int mac_selinux_label_post(int dir_fd, const char *path) {
static int mac_selinux_label_post(int dir_fd, const char *path, bool created) {
mac_selinux_create_file_clear();
return 0;
}

View File

@@ -294,7 +294,10 @@ static int mac_smack_label_pre(int dir_fd, const char *path, mode_t mode) {
return 0;
}
static int mac_smack_label_post(int dir_fd, const char *path) {
static int mac_smack_label_post(int dir_fd, const char *path, bool created) {
if (!created)
return 0;
return mac_smack_fix_full(dir_fd, path, NULL, 0);
}

View File

@@ -670,6 +670,9 @@ TEST(openat_report_new) {
ASSERT_OK_ERRNO(symlinkat("target", tfd, "link"));
fd = openat_report_new(tfd, "link", O_RDWR|O_CREAT, 0666, &b);
ASSERT_ERROR(fd, EEXIST);
fd = openat_report_new(tfd, "target", O_RDWR|O_CREAT, 0666, &b);
ASSERT_OK(fd);
fd = safe_close(fd);
ASSERT_TRUE(b);

View File

@@ -286,9 +286,8 @@ TEST(id128_at) {
ASSERT_OK_ERRNO(unlinkat(tfd, "etc/machine-id", 0));
ASSERT_OK(id128_write_at(tfd, "etc2/machine-id", ID128_FORMAT_PLAIN, id));
ASSERT_OK_ERRNO(unlinkat(tfd, "etc/machine-id", 0));
ASSERT_OK(id128_write_at(tfd, "etc/hoge-id", ID128_FORMAT_PLAIN, id));
ASSERT_OK_ERRNO(unlinkat(tfd, "etc/machine-id", 0));
ASSERT_OK(id128_write_at(tfd, "etc2/hoge-id", ID128_FORMAT_PLAIN, id));
ASSERT_ERROR(id128_write_at(tfd, "etc/hoge-id", ID128_FORMAT_PLAIN, id), EEXIST);
ASSERT_OK(id128_write_at(tfd, "etc2/machine-id", ID128_FORMAT_PLAIN, id));
/* id128_read_at() */
i = SD_ID128_NULL; /* Not necessary in real code, but for testing that the id is really assigned. */

View File

@@ -43,7 +43,7 @@ static int pre_labelling_func(int dir_fd, const char *path, mode_t mode) {
return 0;
}
static int post_labelling_func(int dir_fd, const char *path) {
static int post_labelling_func(int dir_fd, const char *path, bool created) {
int r;
/* assume label policies that restrict certain labels */
@@ -140,17 +140,17 @@ TEST(label_ops_post) {
text1 = "Add initial texts to file for testing label operations to file1\n";
assert(labelling_op(fd, text1, "file1.txt", 0644) == 0);
assert_se(label_ops_post(fd, "file1.txt") == 0);
assert_se(label_ops_post(fd, "file1.txt", true) == 0);
assert_se(strlen(text1) == (size_t)buf.st_size);
text2 = "Add text2 data to file2\n";
assert(labelling_op(fd, text2, "file2.txt", 0644) == 0);
assert_se(label_ops_post(fd, "file2.txt") == 0);
assert_se(label_ops_post(fd, "file2.txt", true) == 0);
assert_se(strlen(text2) == (size_t)buf.st_size);
assert_se(label_ops_post(fd, "file3.txt") == -ENOENT);
assert_se(label_ops_post(fd, "/abcd") == -ENOENT);
assert_se(label_ops_post(fd, "/restricted_directory") == -EACCES);
assert_se(label_ops_post(fd, "") == -EINVAL);
assert_se(label_ops_post(fd, "file3.txt", true) == -ENOENT);
assert_se(label_ops_post(fd, "/abcd", true) == -ENOENT);
assert_se(label_ops_post(fd, "/restricted_directory", true) == -EACCES);
assert_se(label_ops_post(fd, "", true) == -EINVAL);
}
DEFINE_TEST_MAIN(LOG_INFO)

View File

@@ -24,7 +24,6 @@
#include "constants.h"
#include "daemon-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "fs-util.h"
#include "hashmap.h"
@@ -395,7 +394,7 @@ static int context_write_data_local_rtc(Context *c) {
if (r < 0)
return r;
return write_string_file_atomic_label("/etc/adjtime", w);
return write_string_file("/etc/adjtime", w, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL);
}
static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m) {

View File

@@ -5,7 +5,7 @@
#include <unistd.h>
#include "alloc-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "selinux-util.h"
#include "time-util.h"
@@ -29,7 +29,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
timespec_load_nsec(ts)) < 0)
return log_oom();
r = write_string_file_full_label(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC, ts);
r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts);
if (r == -EROFS)
log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
else if (r < 0)

View File

@@ -6,11 +6,10 @@
#include <sys/types.h>
#include <unistd.h>
#include "fileio.h"
#include "fileio-label.h"
#include "fs-util.h"
#include "main-func.h"
#include "log.h"
#include "main-func.h"
#include "reboot-util.h"
#include "selinux-util.h"
#include "string-util.h"