1
0
mirror of https://github.com/systemd/systemd synced 2025-12-29 12:24:45 +01:00

Compare commits

..

No commits in common. "960b585ba116cc09055d3f5540a0c73e088d37e4" and "c7828862b39883cf1f55235a937d29588d5a806b" have entirely different histories.

28 changed files with 470 additions and 440 deletions

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+
-- fc2e22bc6ee647b6b90729ab34a250b1
Subject: Speicherabbild für Prozess @COREDUMP_PID@ (@COREDUMP_COMM@) generiert
Subject: Speicherabbild für Prozess @COREDUMP_PID@ (@COREDUMP_COMM) generiert
Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: man:core(5)

View File

@ -80,9 +80,6 @@ All tools:
honoured on systems built with libxcrypt and is ignored on systems using
glibc's original, internal crypt() implementation.)
* `$SYSTEMD_RDRAND=0` — if set, the RDRAND instruction will never be used,
even if the CPU supports it.
systemctl:
* `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID1's private D-Bus

View File

@ -518,11 +518,6 @@ sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION:pnE*:*
sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION:pnMEDION*:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# Medion Akoya E2221T MD60691
sensor:modalias:acpi:KIOX020A*:dmi:*:pnE2221TMD60691*:*
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, 1, 0; 0, 0, 1
ACCEL_LOCATION=base
#########################################
# MPMAN
#########################################

View File

@ -5,22 +5,20 @@
# Frank Hill <hxf.prc@gmail.com>, 2014.
# Boyuan Yang <073plan@gmail.com>, 2015.
# Jeff Bai <jeffbai@aosc.xyz>, 2016.
# Charles Lee <lchopn@gmail.com>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-19 18:02+0200\n"
"PO-Revision-Date: 2020-09-24 04:29+0000\n"
"Last-Translator: Charles Lee <lchopn@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://translate.fedoraproject.org/"
"projects/systemd/master/zh_CN/>\n"
"PO-Revision-Date: 2016-03-01 20:38-0700\n"
"Last-Translator: Jeff Bai <jeffbai@aosc.xyz>\n"
"Language-Team: Chinese <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.7.1\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.2.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
@ -296,6 +294,8 @@ msgid ""
msgstr "允许应用程序阻止系统响应笔记本上盖开关事件需要认证。"
#: src/login/org.freedesktop.login1.policy:117
#, fuzzy
#| msgid "Allow non-logged-in users to run programs"
msgid "Allow non-logged-in user to run programs"
msgstr "允许未登录用户运行程序"
@ -395,28 +395,42 @@ msgid "Halt the system"
msgstr "休眠系统"
#: src/login/org.freedesktop.login1.policy:225
#, fuzzy
#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to halt the system."
msgstr "停止系统需要认证。"
msgstr "休眠系统需要认证。"
#: src/login/org.freedesktop.login1.policy:235
#, fuzzy
#| msgid "Hibernate the system while other users are logged in"
msgid "Halt the system while other users are logged in"
msgstr "当存在其他已登录用户时仍然停止系统"
msgstr "存在其他已登录用户时仍然休眠"
#: src/login/org.freedesktop.login1.policy:236
#, fuzzy
#| msgid ""
#| "Authentication is required to hibernate the system while other users are "
#| "logged in."
msgid ""
"Authentication is required to halt the system while other users are logged "
"in."
msgstr "当存在其他已登录用户时停止系统需要认证。"
msgstr "存在其他已登录用户时进行休眠系统需要认证。"
#: src/login/org.freedesktop.login1.policy:246
#, fuzzy
#| msgid "Hibernate the system while an application is inhibiting this"
msgid "Halt the system while an application is inhibiting this"
msgstr "当存在应用程序阻止时仍然停止系统"
msgstr "有其它应用程序阻止时仍然休眠"
#: src/login/org.freedesktop.login1.policy:247
#, fuzzy
#| msgid ""
#| "Authentication is required to hibernate the system while an application "
#| "is inhibiting this."
msgid ""
"Authentication is required to halt the system while an application is "
"inhibiting this."
msgstr "当应用程序阻止时停止系统需要认证。"
msgstr "在其它应用程序阻止休眠时进行休眠需要认证。"
#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
@ -501,8 +515,10 @@ msgid "Authentication is required to set the reboot \"reason\" in the kernel."
msgstr "设置系统时区需要认证。"
#: src/login/org.freedesktop.login1.policy:352
#, fuzzy
#| msgid "Allow indication to the firmware to boot to setup interface"
msgid "Indicate to the firmware to boot to setup interface"
msgstr "指示固件以启动至设置界面"
msgstr "允许向固件发出指示以启动至设置界面"
#: src/login/org.freedesktop.login1.policy:353
msgid ""
@ -637,7 +653,7 @@ msgstr "设置系统时间需要认证。"
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
msgid "Set DNS servers"
msgstr "设置 DNS 服务器"
msgstr ""
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45

View File

@ -385,9 +385,11 @@ int fd_get_path(int fd, char **ret) {
/* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make
* things debuggable and distinguish the two. */
if (proc_mounted() == 0)
return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */
if (access("/proc/self/fd/", F_OK) < 0)
/* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */
return errno == ENOENT ? -EOPNOTSUPP : -errno;
return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
}
@ -729,7 +731,8 @@ int fd_duplicate_data_fd(int fd) {
if (f != 0)
return -errno;
CLOSE_AND_REPLACE(copy_fd, tmp_fd);
safe_close(copy_fd);
copy_fd = TAKE_FD(tmp_fd);
remains = mfree(remains);
remains_size = 0;
@ -862,7 +865,8 @@ int rearrange_stdio(int original_input_fd, int original_output_fd, int original_
goto finish;
}
CLOSE_AND_REPLACE(null_fd, copy);
safe_close(null_fd);
null_fd = copy;
}
}

View File

@ -93,16 +93,6 @@ static inline int make_null_stdio(void) {
_fd_; \
})
/* Like free_and_replace(), but for file descriptors */
#define CLOSE_AND_REPLACE(a, b) \
({ \
int *_fdp_ = &(a); \
safe_close(*_fdp_); \
*_fdp_ = TAKE_FD(b); \
0; \
})
int fd_reopen(int fd, int flags);
int read_nr_open(void);

View File

@ -280,6 +280,52 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
return do_chown || do_chmod;
}
int chmod_and_chown_unsafe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
bool do_chown, do_chmod;
struct stat st;
assert(path);
/* Change ownership and access mode of the specified path, see description of fchmod_and_chown().
* Should only be used on trusted paths. */
if (lstat(path, &st) < 0)
return -errno;
do_chown =
(uid != UID_INVALID && st.st_uid != uid) ||
(gid != GID_INVALID && st.st_gid != gid);
do_chmod =
!S_ISLNK(st.st_mode) && /* chmod is not defined on symlinks */
((mode != MODE_INVALID && ((st.st_mode ^ mode) & 07777) != 0) ||
do_chown); /* If we change ownership, make sure we reset the mode afterwards, since chown()
* modifies the access mode too */
if (mode == MODE_INVALID)
mode = st.st_mode; /* If we only shall do a chown(), save original mode, since chown() might break it. */
else if ((mode & S_IFMT) != 0 && ((mode ^ st.st_mode) & S_IFMT) != 0)
return -EINVAL; /* insist on the right file type if it was specified */
if (do_chown && do_chmod) {
mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */
if (((minimal ^ st.st_mode) & 07777) != 0)
if (chmod(path, minimal & 07777) < 0)
return -errno;
}
if (do_chown)
if (lchown(path, uid, gid) < 0)
return -errno;
if (do_chmod)
if (chmod(path, mode & 07777) < 0)
return -errno;
return do_chown || do_chmod;
}
int fchmod_umask(int fd, mode_t m) {
mode_t u;
int r;
@ -719,7 +765,7 @@ static int log_unsafe_transition(int a, int b, const char *path, unsigned flags)
return log_warning_errno(SYNTHETIC_ERRNO(ENOLINK),
"Detected unsafe path transition %s %s %s during canonicalization of %s.",
strna(n1), special_glyph(SPECIAL_GLYPH_ARROW), strna(n2), path);
n1, special_glyph(SPECIAL_GLYPH_ARROW), n2, path);
}
static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
@ -732,7 +778,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
return log_warning_errno(SYNTHETIC_ERRNO(EREMOTE),
"Detected autofs mount point %s during canonicalization of %s.",
strna(n1), path);
n1, path);
}
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) {
@ -1252,25 +1298,16 @@ int chase_symlinks_and_stat(
int access_fd(int fd, int mode) {
char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
int r;
/* Like access() but operates on an already open fd */
xsprintf(p, "/proc/self/fd/%i", fd);
if (access(p, mode) < 0) {
if (errno != ENOENT)
return -errno;
r = access(p, mode);
if (r < 0)
return -errno;
/* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's
* make things debuggable and distinguish the two. */
if (proc_mounted() == 0)
return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */
return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
}
return 0;
return r;
}
void unlink_tempfilep(char (*p)[]) {
@ -1404,9 +1441,9 @@ int fsync_directory_of_file(int fd) {
if (r < 0) {
log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m",
fd,
r == -ENOSYS ? ", ignoring" : "");
r == -EOPNOTSUPP ? ", ignoring" : "");
if (r == -ENOSYS)
if (r == -EOPNOTSUPP)
/* If /proc is not available, we're most likely running in some
* chroot environment, and syncing the directory is not very
* important in that case. Let's just silently do nothing. */

View File

@ -34,6 +34,7 @@ int readlink_and_make_absolute(const char *p, char **r);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid);
int chmod_and_chown_unsafe(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_umask(int fd, mode_t mode);
int fchmod_opath(int fd, mode_t m);

View File

@ -28,6 +28,14 @@
#include "time-util.h"
#include "utf8.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
}
bool is_path(const char *p) {
return !!strchr(p, '/');
}
int path_split_and_make_absolute(const char *p, char ***ret) {
char **l;
int r;
@ -585,9 +593,9 @@ char* path_join_internal(const char *first, ...) {
return joined;
}
int find_executable_full(const char *name, bool use_path_envvar, char **ret) {
int find_binary(const char *name, char **ret) {
int last_error, r;
const char *p = NULL;
const char *p;
assert(name);
@ -604,10 +612,11 @@ int find_executable_full(const char *name, bool use_path_envvar, char **ret) {
return 0;
}
if (use_path_envvar)
/* Plain getenv, not secure_getenv, because we want to actually allow the user to pick the
* binary. */
p = getenv("PATH");
/**
* Plain getenv, not secure_getenv, because we want
* to actually allow the user to pick the binary.
*/
p = getenv("PATH");
if (!p)
p = DEFAULT_PATH;
@ -640,7 +649,9 @@ int find_executable_full(const char *name, bool use_path_envvar, char **ret) {
if (access(with_dash, X_OK) >= 0)
continue;
/* We can't just `continue` inverting this case, since we need to update last_error. */
/**
* We can't just `continue` inverting this case, since we need to update last_error.
*/
if (errno == ENOTDIR) {
/* Found it! */
if (ret)
@ -693,17 +704,18 @@ bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool upd
return changed;
}
static int executable_is_good(const char *executable) {
static int binary_is_good(const char *binary) {
_cleanup_free_ char *p = NULL, *d = NULL;
int r;
r = find_executable(executable, &p);
r = find_binary(binary, &p);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
/* An fsck that is linked to /bin/true is a non-existent fsck */
/* An fsck that is linked to /bin/true is a non-existent
* fsck */
r = readlink_malloc(p, &d);
if (r == -EINVAL) /* not a symlink */
@ -726,7 +738,7 @@ int fsck_exists(const char *fstype) {
return -EINVAL;
checker = strjoina("fsck.", fstype);
return executable_is_good(checker);
return binary_is_good(checker);
}
int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) {

View File

@ -42,17 +42,9 @@
# define DEFAULT_USER_PATH DEFAULT_PATH
#endif
static inline bool is_path(const char *p) {
assert(p);
return strchr(p, '/');
}
static inline bool path_is_absolute(const char *p) {
assert(p);
return p[0] == '/';
}
bool is_path(const char *p) _pure_;
int path_split_and_make_absolute(const char *p, char ***ret);
bool path_is_absolute(const char *p) _pure_;
char* path_make_absolute(const char *p, const char *prefix);
int safe_getcwd(char **ret);
int path_make_absolute_cwd(const char *p, char **ret);
@ -88,10 +80,7 @@ int path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *root);
char** path_strv_resolve_uniq(char **l, const char *root);
int find_executable_full(const char *name, bool use_path_envvar, char **ret);
static inline int find_executable(const char *name, char **ret) {
return find_executable_full(name, true, ret);
}
int find_binary(const char *name, char **filename);
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);

View File

@ -21,7 +21,6 @@
#endif
#include "alloc-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
@ -117,15 +116,6 @@ int rdrand(unsigned long *ret) {
#endif
have_rdrand = !!(ecx & bit_RDRND);
if (have_rdrand > 0) {
/* Allow disabling use of RDRAND with SYSTEMD_RDRAND=0
If it is unset getenv_bool_secure will return a negative value. */
if (getenv_bool_secure("SYSTEMD_RDRAND") == 0) {
have_rdrand = false;
return -EOPNOTSUPP;
}
}
}
if (have_rdrand == 0)

View File

@ -1354,10 +1354,8 @@ int bus_set_transient_exec_command(
if (r < 0)
return r;
if (!path_is_absolute(path) && !filename_is_valid(path))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"\"%s\" is neither a valid executable name nor an absolute path",
path);
if (!path_is_absolute(path))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
r = sd_bus_message_read_strv(message, &argv);
if (r < 0)

View File

@ -2881,11 +2881,12 @@ static int setup_credentials(
#if ENABLE_SMACK
static int setup_smack(
const ExecContext *context,
const char *executable) {
const ExecCommand *command) {
int r;
assert(context);
assert(executable);
assert(command);
if (context->smack_process_label) {
r = mac_smack_apply_pid(0, context->smack_process_label);
@ -2896,7 +2897,7 @@ static int setup_smack(
else {
_cleanup_free_ char *exec_label = NULL;
r = mac_smack_read(executable, SMACK_ATTR_EXEC, &exec_label);
r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
if (r < 0 && !IN_SET(r, -ENODATA, -EOPNOTSUPP))
return r;
@ -3091,7 +3092,7 @@ static bool insist_on_sandboxing(
static int apply_mount_namespace(
const Unit *u,
ExecCommandFlags command_flags,
const ExecCommand *command,
const ExecContext *context,
const ExecParameters *params,
const ExecRuntime *runtime,
@ -3120,7 +3121,7 @@ static int apply_mount_namespace(
if (r < 0)
return r;
needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command_flags & EXEC_COMMAND_FULLY_PRIVILEGED);
needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED);
if (needs_sandboxing) {
/* The runtime struct only contains the parent of the private /tmp,
* which is non-accessible to world users. Inside of it there's a /tmp
@ -3699,11 +3700,11 @@ static int exec_child(
return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m");
}
if (!context->same_pgrp &&
setsid() < 0) {
*exit_status = EXIT_SETSID;
return log_unit_error_errno(unit, errno, "Failed to create new process session: %m");
}
if (!context->same_pgrp)
if (setsid() < 0) {
*exit_status = EXIT_SETSID;
return log_unit_error_errno(unit, errno, "Failed to create new process session: %m");
}
exec_context_tty_reset(context, params);
@ -3724,8 +3725,8 @@ static int exec_child(
return 0;
}
*exit_status = EXIT_CONFIRM;
return log_unit_error_errno(unit, SYNTHETIC_ERRNO(ECANCELED),
"Execution cancelled by the user");
log_unit_error(unit, "Execution cancelled by the user");
return -ECANCELED;
}
}
@ -4084,33 +4085,47 @@ static int exec_child(
}
}
if (needs_setuid && context->pam_name && username) {
if (needs_setuid) {
/* Let's call into PAM after we set up our own idea of resource limits to that pam_limits
* wins here. (See above.) */
r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
if (r < 0) {
*exit_status = EXIT_PAM;
return log_unit_error_errno(unit, r, "Failed to set up PAM session: %m");
}
if (context->pam_name && username) {
r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
if (r < 0) {
*exit_status = EXIT_PAM;
return log_unit_error_errno(unit, r, "Failed to set up PAM session: %m");
}
ngids_after_pam = getgroups_alloc(&gids_after_pam);
if (ngids_after_pam < 0) {
*exit_status = EXIT_MEMORY;
return log_unit_error_errno(unit, ngids_after_pam, "Failed to obtain groups after setting up PAM: %m");
ngids_after_pam = getgroups_alloc(&gids_after_pam);
if (ngids_after_pam < 0) {
*exit_status = EXIT_MEMORY;
return log_unit_error_errno(unit, ngids_after_pam, "Failed to obtain groups after setting up PAM: %m");
}
}
}
if (needs_sandboxing && context->private_users && !have_effective_cap(CAP_SYS_ADMIN)) {
if (needs_sandboxing) {
#if HAVE_SELINUX
if (use_selinux && params->selinux_context_net && socket_fd >= 0) {
r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
if (r < 0) {
*exit_status = EXIT_SELINUX_CONTEXT;
return log_unit_error_errno(unit, r, "Failed to determine SELinux context: %m");
}
}
#endif
/* If we're unprivileged, set up the user namespace first to enable use of the other namespaces.
* Users with CAP_SYS_ADMIN can set up user namespaces last because they will be able to
* set up the all of the other namespaces (i.e. network, mount, UTS) without a user namespace. */
userns_set_up = true;
r = setup_private_users(saved_uid, saved_gid, uid, gid);
if (r < 0) {
*exit_status = EXIT_USER;
return log_unit_error_errno(unit, r, "Failed to set up user namespacing for unprivileged user: %m");
if (context->private_users && !have_effective_cap(CAP_SYS_ADMIN)) {
userns_set_up = true;
r = setup_private_users(saved_uid, saved_gid, uid, gid);
if (r < 0) {
*exit_status = EXIT_USER;
return log_unit_error_errno(unit, r, "Failed to set up user namespacing for unprivileged user: %m");
}
}
}
@ -4137,7 +4152,7 @@ static int exec_child(
if (needs_mount_namespace) {
_cleanup_free_ char *error_path = NULL;
r = apply_mount_namespace(unit, command->flags, context, params, runtime, &error_path);
r = apply_mount_namespace(unit, command, context, params, runtime, &error_path);
if (r < 0) {
*exit_status = EXIT_NAMESPACE;
return log_unit_error_errno(unit, r, "Failed to set up mount namespacing%s%s: %m",
@ -4191,43 +4206,6 @@ static int exec_child(
}
}
/* Now that the mount namespace has been set up and privileges adjusted, let's look for the thing we
* shall execute. */
_cleanup_free_ char *executable = NULL;
r = find_executable_full(command->path, false, &executable);
if (r < 0) {
if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
log_struct_errno(LOG_INFO, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit),
LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
command->path),
"EXECUTABLE=%s", command->path);
return 0;
}
*exit_status = EXIT_EXEC;
return log_struct_errno(LOG_INFO, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit),
LOG_UNIT_MESSAGE(unit, "Failed to locate executable %s: %m",
command->path),
"EXECUTABLE=%s", command->path);
}
#if HAVE_SELINUX
if (needs_sandboxing && use_selinux && params->selinux_context_net && socket_fd >= 0) {
r = mac_selinux_get_child_mls_label(socket_fd, executable, context->selinux_context, &mac_selinux_context_net);
if (r < 0) {
*exit_status = EXIT_SELINUX_CONTEXT;
return log_unit_error_errno(unit, r, "Failed to determine SELinux context: %m");
}
}
#endif
/* We repeat the fd closing here, to make sure that nothing is leaked from the PAM modules. Note that we are
* more aggressive this time since socket_fd and the netns fds we don't need anymore. We do keep the exec_fd
* however if we have it as we want to keep it open until the final execve(). */
@ -4247,7 +4225,8 @@ static int exec_child(
return log_unit_error_errno(unit, errno, "Couldn't move exec fd up: %m");
}
CLOSE_AND_REPLACE(exec_fd, moved_fd);
safe_close(exec_fd);
exec_fd = moved_fd;
} else {
/* This fd should be FD_CLOEXEC already, but let's make sure. */
r = fd_cloexec(exec_fd, true);
@ -4300,7 +4279,7 @@ static int exec_child(
/* LSM Smack needs the capability CAP_MAC_ADMIN to change the current execution security context of the
* process. This is the latest place before dropping capabilities. Other MAC context are set later. */
if (use_smack) {
r = setup_smack(context, executable);
r = setup_smack(context, command);
if (r < 0) {
*exit_status = EXIT_SMACK_PROCESS_LABEL;
return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m");
@ -4552,7 +4531,7 @@ static int exec_child(
line = exec_command_line(final_argv);
if (line)
log_struct(LOG_DEBUG,
"EXECUTABLE=%s", executable,
"EXECUTABLE=%s", command->path,
LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit));
@ -4570,7 +4549,7 @@ static int exec_child(
}
}
execve(executable, final_argv, accum_env);
execve(command->path, final_argv, accum_env);
r = -errno;
if (exec_fd >= 0) {
@ -4585,8 +4564,19 @@ static int exec_child(
}
}
if (r == -ENOENT && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
log_struct_errno(LOG_INFO, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit),
LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
command->path),
"EXECUTABLE=%s", command->path);
return 0;
}
*exit_status = EXIT_EXEC;
return log_unit_error_errno(unit, r, "Failed to execute %s: %m", executable);
return log_unit_error_errno(unit, r, "Failed to execute command: %m");
}
static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l);
@ -4648,16 +4638,13 @@ int exec_spawn(Unit *unit,
if (!line)
return log_oom();
/* Fork with up-to-date SELinux label database, so the child inherits the up-to-date db
and, until the next SELinux policy changes, we save further reloads in future children. */
/* fork with up-to-date SELinux label database, so the child inherits the up-to-date db
and, until the next SELinux policy changes, we safe further reloads in future children */
mac_selinux_maybe_reload();
log_struct(LOG_DEBUG,
LOG_UNIT_MESSAGE(unit, "About to execute %s", line),
"EXECUTABLE=%s", command->path, /* We won't know the real executable path until we create
the mount namespace in the child, but we want to log
from the parent, so we need to use the (possibly
inaccurate) path here. */
LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
"EXECUTABLE=%s", command->path,
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit));

View File

@ -721,12 +721,6 @@ int config_parse_exec(
if (r <= 0)
return 0;
/* A lone ";" is a separator. Let's make sure we don't treat it as an executable name. */
if (streq(firstword, ";")) {
semicolon = true;
continue;
}
f = firstword;
for (;;) {
/* We accept an absolute path as first argument. If it's prefixed with - and the path doesn't
@ -789,11 +783,38 @@ int config_parse_exec(
return ignore ? 0 : -ENOEXEC;
}
if (!path_is_absolute(path) && !filename_is_valid(path)) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
"Neither a valid executable name nor an absolute path%s: %s",
ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
if (!path_is_absolute(path)) {
const char *prefix;
bool found = false;
if (!filename_is_valid(path)) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
"Neither a valid executable name nor an absolute path%s: %s",
ignore ? ", ignoring" : "", path);
return ignore ? 0 : -ENOEXEC;
}
/* Resolve a single-component name to a full path */
NULSTR_FOREACH(prefix, DEFAULT_PATH_NULSTR) {
_cleanup_free_ char *fullpath = NULL;
fullpath = path_join(prefix, path);
if (!fullpath)
return log_oom();
if (access(fullpath, F_OK) >= 0) {
free_and_replace(path, fullpath);
found = true;
break;
}
}
if (!found) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
"Executable \"%s\" not found in path \"%s\"%s",
path, DEFAULT_PATH, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
}
if (!separate_argv0) {

View File

@ -1973,9 +1973,10 @@ int manager_load_unit_prepare(
assert(m);
assert(_ret);
/* This will prepare the unit for loading, but not actually load anything from disk. */
/* This will prepare the unit for loading, but not actually
* load anything from disk. */
if (path && !path_is_absolute(path))
if (path && !is_path(path))
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
if (!name) {

View File

@ -185,7 +185,9 @@ static int raw_import_maybe_convert_qcow2(RawImport *i) {
(void) unlink(i->temp_path);
free_and_replace(i->temp_path, t);
CLOSE_AND_REPLACE(i->output_fd, converted_fd);
safe_close(i->output_fd);
i->output_fd = TAKE_FD(converted_fd);
return 1;
}

View File

@ -253,7 +253,9 @@ static int raw_pull_maybe_convert_qcow2(RawPull *i) {
(void) unlink(i->temp_path);
free_and_replace(i->temp_path, t);
CLOSE_AND_REPLACE(i->raw_job->disk_fd, converted_fd);
safe_close(i->raw_job->disk_fd);
i->raw_job->disk_fd = TAKE_FD(converted_fd);
return 1;
}

View File

@ -176,7 +176,7 @@ _unused_ static void test_compress_stream(const char *compression,
_cleanup_free_ char *cmd = NULL, *cmd2 = NULL;
struct stat st = {};
r = find_executable(cat, NULL);
r = find_binary(cat, NULL);
if (r < 0) {
log_error_errno(r, "Skipping %s, could not find %s binary: %m", __func__, cat);
return;

View File

@ -471,7 +471,8 @@ int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) {
if (r < 0)
return r;
CLOSE_AND_REPLACE(acd->fd, r);
safe_close(acd->fd);
acd->fd = r;
acd->defend_window = 0;
if (reset_conflicts)

View File

@ -195,7 +195,8 @@ static int session_device_start(SessionDevice *sd) {
/* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming
* into a session and logind has been restarted right before. */
CLOSE_AND_REPLACE(sd->fd, r);
safe_close(sd->fd);
sd->fd = r;
break;
case DEVICE_TYPE_UNKNOWN:

View File

@ -1720,16 +1720,12 @@ static int run(int argc, char* argv[]) {
if (r <= 0)
return r;
if (!strv_isempty(arg_cmdline) &&
arg_transport == BUS_TRANSPORT_LOCAL &&
!strv_find_startswith(arg_property, "RootDirectory=") &&
!strv_find_startswith(arg_property, "RootImage=")) {
/* Patch in an absolute path to fail early for user convenience, but only when we can do it
* (i.e. we will be running from the same file system). This also uses the user's $PATH,
* while we use a fixed search path in the manager. */
if (!strv_isempty(arg_cmdline) && arg_transport == BUS_TRANSPORT_LOCAL) {
_cleanup_free_ char *command = NULL;
r = find_executable(arg_cmdline[0], &command);
/* Patch in an absolute path */
r = find_binary(arg_cmdline[0], &command);
if (r < 0)
return log_error_errno(r, "Failed to find executable %s: %m", arg_cmdline[0]);

View File

@ -20,7 +20,7 @@ int mkfs_exists(const char *fstype) {
if (!filename_is_valid(mkfs)) /* refuse file system types with slashes and similar */
return -EINVAL;
r = find_executable(mkfs, NULL);
r = find_binary(mkfs, NULL);
if (r == -ENOENT)
return false;
if (r < 0)
@ -44,7 +44,7 @@ int make_filesystem(
assert(label);
if (streq(fstype, "swap")) {
r = find_executable("mkswap", &mkfs);
r = find_binary("mkswap", &mkfs);
if (r == -ENOENT)
return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkswap binary not available.");
if (r < 0)

View File

@ -201,16 +201,14 @@ static int load_group_database(void) {
}
static int make_backup(const char *target, const char *x) {
_cleanup_(unlink_and_freep) char *dst_tmp = NULL;
_cleanup_fclose_ FILE *dst = NULL;
_cleanup_close_ int src = -1;
const char *backup;
_cleanup_fclose_ FILE *dst = NULL;
_cleanup_free_ char *dst_tmp = NULL;
char *backup;
struct timespec ts[2];
struct stat st;
int r;
assert(target);
assert(x);
src = open(x, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (src < 0) {
if (errno == ENOENT) /* No backup necessary... */
@ -222,38 +220,43 @@ static int make_backup(const char *target, const char *x) {
if (fstat(src, &st) < 0)
return -errno;
r = fopen_temporary_label(
target, /* The path for which to the lookup the label */
x, /* Where we want the file actually to end up */
&dst,
&dst_tmp /* The temporary file we write to */);
r = fopen_temporary_label(target, x, &dst, &dst_tmp);
if (r < 0)
return r;
r = copy_bytes(src, fileno(dst), (uint64_t) -1, COPY_REFLINK);
if (r < 0)
return r;
goto fail;
/* Don't fail on chmod() or chown(). If it stays owned by us
* and/or unreadable by others, then it isn't too bad... */
backup = strjoina(x, "-");
/* Copy over the access mask. Don't fail on chmod() or chown(). If it stays owned by us and/or
* unreadable by others, then it isn't too bad... */
r = fchmod_and_chown(fileno(dst), st.st_mode & 07777, st.st_uid, st.st_gid);
/* Copy over the access mask */
r = chmod_and_chown_unsafe(dst_tmp, st.st_mode & 07777, st.st_uid, st.st_gid);
if (r < 0)
log_warning_errno(r, "Failed to change access mode or ownership of %s: %m", backup);
if (futimens(fileno(dst), (const struct timespec[2]) { st.st_atim, st.st_mtim }) < 0)
ts[0] = st.st_atim;
ts[1] = st.st_mtim;
if (futimens(fileno(dst), ts) < 0)
log_warning_errno(errno, "Failed to fix access and modification time of %s: %m", backup);
r = fsync_full(fileno(dst));
r = fflush_sync_and_check(dst);
if (r < 0)
return r;
goto fail;
if (rename(dst_tmp, backup) < 0)
return errno;
if (rename(dst_tmp, backup) < 0) {
r = -errno;
goto fail;
}
dst_tmp = mfree(dst_tmp); /* disable the unlink_and_freep() hook now that the file has been renamed*/
return 0;
fail:
(void) unlink(dst_tmp);
return r;
}
static int putgrent_with_members(const struct group *gr, FILE *group) {

View File

@ -71,8 +71,7 @@ static void wait_for_service_finish(Manager *m, Unit *unit) {
}
}
static void check_main_result(const char *file, unsigned line, const char *func,
Manager *m, Unit *unit, int status_expected, int code_expected) {
static void check_main_result(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
Service *service = NULL;
assert_se(m);
@ -84,23 +83,21 @@ static void check_main_result(const char *file, unsigned line, const char *func,
exec_status_dump(&service->main_exec_status, stdout, "\t");
if (cld_dumped_to_killed(service->main_exec_status.code) != cld_dumped_to_killed(code_expected)) {
log_error("%s:%u:%s %s: exit code %d, expected %d",
file, line, func,
unit->id,
log_error("%s: %s: exit code %d, expected %d",
func, unit->id,
service->main_exec_status.code, code_expected);
abort();
}
if (service->main_exec_status.status != status_expected) {
log_error("%s:%u:%s: %s: exit status %d, expected %d",
file, line, func, unit->id,
log_error("%s: %s: exit status %d, expected %d",
func, unit->id,
service->main_exec_status.status, status_expected);
abort();
}
}
static void check_service_result(const char *file, unsigned line, const char *func,
Manager *m, Unit *unit, ServiceResult result_expected) {
static void check_service_result(const char *func, Manager *m, Unit *unit, ServiceResult result_expected) {
Service *service = NULL;
assert_se(m);
@ -111,9 +108,8 @@ static void check_service_result(const char *file, unsigned line, const char *fu
service = SERVICE(unit);
if (service->result != result_expected) {
log_error("%s:%u:%s: %s: service end result %s, expected %s",
file, line, func,
unit->id,
log_error("%s: %s: service end result %s, expected %s",
func, unit->id,
service_result_to_string(service->result),
service_result_to_string(result_expected));
abort();
@ -202,37 +198,31 @@ static bool is_inaccessible_available(void) {
return true;
}
static void _test(const char *file, unsigned line, const char *func,
Manager *m, const char *unit_name, int status_expected, int code_expected) {
static void test(const char *func, Manager *m, const char *unit_name, int status_expected, int code_expected) {
Unit *unit;
assert_se(unit_name);
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
assert_se(unit_start(unit) >= 0);
check_main_result(file, line, func, m, unit, status_expected, code_expected);
check_main_result(func, m, unit, status_expected, code_expected);
}
#define test(m, unit_name, status_expected, code_expected) \
_test(PROJECT_FILE, __LINE__, __func__, m, unit_name, status_expected, code_expected)
static void _test_service(const char *file, unsigned line, const char *func,
Manager *m, const char *unit_name, ServiceResult result_expected) {
static void test_service(const char *func, Manager *m, const char *unit_name, ServiceResult result_expected) {
Unit *unit;
assert_se(unit_name);
assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
assert_se(unit_start(unit) >= 0);
check_service_result(file, line, func, m, unit, result_expected);
check_service_result(func, m, unit, result_expected);
}
#define test_service(m, unit_name, result_expected) \
_test_service(PROJECT_FILE, __LINE__, __func__, m, unit_name, result_expected)
static void test_exec_bindpaths(Manager *m) {
assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0);
assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0);
test(m, "exec-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
(void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
@ -249,8 +239,8 @@ static void test_exec_cpuaffinity(Manager *m) {
return;
}
test(m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
test(m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
test(__func__, m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
test(__func__, m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
if (!CPU_ISSET_S(1, c.allocated, c.set) ||
!CPU_ISSET_S(2, c.allocated, c.set)) {
@ -258,53 +248,53 @@ static void test_exec_cpuaffinity(Manager *m) {
return;
}
test(m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
test(__func__, m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
}
static void test_exec_workingdirectory(Manager *m) {
assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0);
test(m, "exec-workingdirectory.service", 0, CLD_EXITED);
test(m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED);
test(__func__, m, "exec-workingdirectory.service", 0, CLD_EXITED);
test(__func__, m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED);
(void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
}
static void test_exec_personality(Manager *m) {
#if defined(__x86_64__)
test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
test(__func__, m, "exec-personality-x86-64.service", 0, CLD_EXITED);
#elif defined(__s390__)
test(m, "exec-personality-s390.service", 0, CLD_EXITED);
test(__func__, m, "exec-personality-s390.service", 0, CLD_EXITED);
#elif defined(__powerpc64__)
# if __BYTE_ORDER == __BIG_ENDIAN
test(m, "exec-personality-ppc64.service", 0, CLD_EXITED);
test(__func__, m, "exec-personality-ppc64.service", 0, CLD_EXITED);
# else
test(m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
test(__func__, m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
# endif
#elif defined(__aarch64__)
test(m, "exec-personality-aarch64.service", 0, CLD_EXITED);
test(__func__, m, "exec-personality-aarch64.service", 0, CLD_EXITED);
#elif defined(__i386__)
test(m, "exec-personality-x86.service", 0, CLD_EXITED);
test(__func__, m, "exec-personality-x86.service", 0, CLD_EXITED);
#else
log_notice("Unknown personality, skipping %s", __func__);
#endif
}
static void test_exec_ignoresigpipe(Manager *m) {
test(m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
test(m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
test(__func__, m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
test(__func__, m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
}
static void test_exec_privatetmp(Manager *m) {
assert_se(touch("/tmp/test-exec_privatetmp") >= 0);
test(m, "exec-privatetmp-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-privatetmp-no.service", 0, CLD_EXITED);
test(m, "exec-privatetmp-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-privatetmp-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-privatetmp-no.service", 0, CLD_EXITED);
test(__func__, m, "exec-privatetmp-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
unlink("/tmp/test-exec_privatetmp");
}
@ -321,23 +311,23 @@ static void test_exec_privatedevices(Manager *m) {
return;
}
test(m, "exec-privatedevices-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
test(m, "exec-privatedevices-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-privatedevices-yes-with-group.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-privatedevices-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-privatedevices-no.service", 0, CLD_EXITED);
test(__func__, m, "exec-privatedevices-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-privatedevices-yes-with-group.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
/* We use capsh to test if the capabilities are
* properly set, so be sure that it exists */
r = find_executable("capsh", NULL);
r = find_binary("capsh", NULL);
if (r < 0) {
log_notice_errno(r, "Could not find capsh binary, skipping remaining tests in %s: %m", __func__);
return;
}
test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
test(__func__, m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
test(__func__, m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
test(__func__, m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
test(__func__, m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
}
static void test_exec_protecthome(Manager *m) {
@ -346,7 +336,7 @@ static void test_exec_protecthome(Manager *m) {
return;
}
test(m, "exec-protecthome-tmpfs-vs-protectsystem-strict.service", 0, CLD_EXITED);
test(__func__, m, "exec-protecthome-tmpfs-vs-protectsystem-strict.service", 0, CLD_EXITED);
}
static void test_exec_protectkernelmodules(Manager *m) {
@ -361,29 +351,29 @@ static void test_exec_protectkernelmodules(Manager *m) {
return;
}
r = find_executable("capsh", NULL);
r = find_binary("capsh", NULL);
if (r < 0) {
log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
return;
}
test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
test(m, "exec-protectkernelmodules-yes-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
test(__func__, m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
test(__func__, m, "exec-protectkernelmodules-yes-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_readonlypaths(Manager *m) {
test(m, "exec-readonlypaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-readonlypaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
if (path_is_read_only_fs("/var") > 0) {
log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__);
return;
}
test(m, "exec-readonlypaths.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-readonlypaths-with-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-readonlypaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-readonlypaths.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-readonlypaths-with-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-readonlypaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_readwritepaths(Manager *m) {
@ -393,7 +383,7 @@ static void test_exec_readwritepaths(Manager *m) {
return;
}
test(m, "exec-readwritepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-readwritepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_inaccessiblepaths(Manager *m) {
@ -403,22 +393,22 @@ static void test_exec_inaccessiblepaths(Manager *m) {
return;
}
test(m, "exec-inaccessiblepaths-sys.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-inaccessiblepaths-sys.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
if (path_is_read_only_fs("/") > 0) {
log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
return;
}
test(m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_temporaryfilesystem(Manager *m) {
test(m, "exec-temporaryfilesystem-options.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-temporaryfilesystem-ro.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-temporaryfilesystem-rw.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-temporaryfilesystem-usr.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-temporaryfilesystem-options.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-temporaryfilesystem-ro.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-temporaryfilesystem-rw.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-temporaryfilesystem-usr.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
}
static void test_exec_systemcallfilter(Manager *m) {
@ -430,22 +420,22 @@ static void test_exec_systemcallfilter(Manager *m) {
return;
}
test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
test(__func__, m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
test(__func__, m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
r = find_executable("python3", NULL);
r = find_binary("python3", NULL);
if (r < 0) {
log_notice_errno(r, "Skipping remaining tests in %s, could not find python3 binary: %m", __func__);
return;
}
test(m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
test(m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(m, "exec-systemcallfilter-override-error-action.service", SIGSYS, CLD_KILLED);
test(m, "exec-systemcallfilter-override-error-action2.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-override-error-action.service", SIGSYS, CLD_KILLED);
test(__func__, m, "exec-systemcallfilter-override-error-action2.service", errno_from_name("EILSEQ"), CLD_EXITED);
#endif
}
@ -458,14 +448,14 @@ static void test_exec_systemcallerrornumber(Manager *m) {
return;
}
r = find_executable("python3", NULL);
r = find_binary("python3", NULL);
if (r < 0) {
log_notice_errno(r, "Skipping %s, could not find python3 binary: %m", __func__);
return;
}
test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
test(__func__, m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
test(__func__, m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
#endif
}
@ -476,13 +466,13 @@ static void test_exec_restrictnamespaces(Manager *m) {
return;
}
test(m, "exec-restrictnamespaces-no.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
test(m, "exec-restrictnamespaces-mnt.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-restrictnamespaces-mnt-deny-list.service", 1, CLD_EXITED);
test(m, "exec-restrictnamespaces-merge-and.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-restrictnamespaces-merge-or.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(m, "exec-restrictnamespaces-merge-all.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-no.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-mnt.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-mnt-deny-list.service", 1, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-merge-and.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-merge-or.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
test(__func__, m, "exec-restrictnamespaces-merge-all.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
#endif
}
@ -498,7 +488,7 @@ static void test_exec_systemcallfilter_system(Manager *m) {
return;
}
test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
if (!check_nobody_user_and_group()) {
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
@ -510,12 +500,12 @@ static void test_exec_systemcallfilter_system(Manager *m) {
return;
}
test(m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
test(__func__, m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
#endif
}
static void test_exec_user(Manager *m) {
test(m, "exec-user.service", 0, CLD_EXITED);
test(__func__, m, "exec-user.service", 0, CLD_EXITED);
if (!check_nobody_user_and_group()) {
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
@ -527,11 +517,11 @@ static void test_exec_user(Manager *m) {
return;
}
test(m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
test(__func__, m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
}
static void test_exec_group(Manager *m) {
test(m, "exec-group.service", 0, CLD_EXITED);
test(__func__, m, "exec-group.service", 0, CLD_EXITED);
if (!check_nobody_user_and_group()) {
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
@ -543,16 +533,16 @@ static void test_exec_group(Manager *m) {
return;
}
test(m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
test(__func__, m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
}
static void test_exec_supplementarygroups(Manager *m) {
test(m, "exec-supplementarygroups.service", 0, CLD_EXITED);
test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
test(m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
test(__func__, m, "exec-supplementarygroups.service", 0, CLD_EXITED);
test(__func__, m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
test(__func__, m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
test(__func__, m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
test(__func__, m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
test(__func__, m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
}
static char* private_directory_bad(Manager *m) {
@ -579,14 +569,14 @@ static void test_exec_dynamicuser(Manager *m) {
return;
}
test(m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
if (check_user_has_group_with_same_name("adm"))
test(m, "exec-dynamicuser-fixeduser-adm.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-fixeduser-adm.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
if (check_user_has_group_with_same_name("games"))
test(m, "exec-dynamicuser-fixeduser-games.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-fixeduser-games.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
(void) rm_rf("/var/lib/quux", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
@ -597,25 +587,25 @@ static void test_exec_dynamicuser(Manager *m) {
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/waldo", REMOVE_ROOT|REMOVE_PHYSICAL);
test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
test(m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
test(m, "exec-dynamicuser-runtimedirectory1.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-dynamicuser-runtimedirectory2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(m, "exec-dynamicuser-runtimedirectory3.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-runtimedirectory1.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-runtimedirectory2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
test(__func__, m, "exec-dynamicuser-runtimedirectory3.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
}
static void test_exec_environment(Manager *m) {
test(m, "exec-environment-no-substitute.service", 0, CLD_EXITED);
test(m, "exec-environment.service", 0, CLD_EXITED);
test(m, "exec-environment-multiple.service", 0, CLD_EXITED);
test(m, "exec-environment-empty.service", 0, CLD_EXITED);
test(__func__, m, "exec-environment-no-substitute.service", 0, CLD_EXITED);
test(__func__, m, "exec-environment.service", 0, CLD_EXITED);
test(__func__, m, "exec-environment-multiple.service", 0, CLD_EXITED);
test(__func__, m, "exec-environment-empty.service", 0, CLD_EXITED);
}
static void test_exec_environmentfile(Manager *m) {
@ -635,7 +625,7 @@ static void test_exec_environmentfile(Manager *m) {
r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
assert_se(r == 0);
test(m, "exec-environmentfile.service", 0, CLD_EXITED);
test(__func__, m, "exec-environmentfile.service", 0, CLD_EXITED);
(void) unlink("/tmp/test-exec_environmentfile.conf");
}
@ -657,26 +647,26 @@ static void test_exec_passenvironment(Manager *m) {
assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
assert_se(setenv("VAR4", "new\nline", 1) == 0);
assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
test(m, "exec-passenvironment.service", 0, CLD_EXITED);
test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
test(__func__, m, "exec-passenvironment.service", 0, CLD_EXITED);
test(__func__, m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
test(__func__, m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
assert_se(unsetenv("VAR1") == 0);
assert_se(unsetenv("VAR2") == 0);
assert_se(unsetenv("VAR3") == 0);
assert_se(unsetenv("VAR4") == 0);
assert_se(unsetenv("VAR5") == 0);
test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
test(__func__, m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
}
static void test_exec_umask(Manager *m) {
test(m, "exec-umask-default.service", 0, CLD_EXITED);
test(m, "exec-umask-0177.service", 0, CLD_EXITED);
test(__func__, m, "exec-umask-default.service", 0, CLD_EXITED);
test(__func__, m, "exec-umask-0177.service", 0, CLD_EXITED);
}
static void test_exec_runtimedirectory(Manager *m) {
test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
test(__func__, m, "exec-runtimedirectory.service", 0, CLD_EXITED);
test(__func__, m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
test(__func__, m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
if (!check_nobody_user_and_group()) {
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
@ -688,13 +678,13 @@ static void test_exec_runtimedirectory(Manager *m) {
return;
}
test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
test(__func__, m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
}
static void test_exec_capabilityboundingset(Manager *m) {
int r;
r = find_executable("capsh", NULL);
r = find_binary("capsh", NULL);
if (r < 0) {
log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
return;
@ -707,14 +697,14 @@ static void test_exec_capabilityboundingset(Manager *m) {
return;
}
test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
test(__func__, m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
test(__func__, m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
test(__func__, m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
test(__func__, m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
}
static void test_exec_basic(Manager *m) {
test(m, "exec-basic.service", 0, CLD_EXITED);
test(__func__, m, "exec-basic.service", 0, CLD_EXITED);
}
static void test_exec_ambientcapabilities(Manager *m) {
@ -736,8 +726,8 @@ static void test_exec_ambientcapabilities(Manager *m) {
return;
}
test(m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
test(m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
test(__func__, m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
test(__func__, m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
if (!check_nobody_user_and_group()) {
log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
@ -749,71 +739,71 @@ static void test_exec_ambientcapabilities(Manager *m) {
return;
}
test(m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
test(m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
test(__func__, m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
test(__func__, m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
}
static void test_exec_privatenetwork(Manager *m) {
int r;
r = find_executable("ip", NULL);
r = find_binary("ip", NULL);
if (r < 0) {
log_notice_errno(r, "Skipping %s, could not find ip binary: %m", __func__);
return;
}
test(m, "exec-privatenetwork-yes.service", can_unshare ? 0 : EXIT_NETWORK, CLD_EXITED);
test(__func__, m, "exec-privatenetwork-yes.service", can_unshare ? 0 : EXIT_NETWORK, CLD_EXITED);
}
static void test_exec_oomscoreadjust(Manager *m) {
test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
test(__func__, m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
if (detect_container() > 0) {
log_notice("Testing in container, skipping remaining tests in %s", __func__);
return;
}
test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
test(__func__, m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
}
static void test_exec_ioschedulingclass(Manager *m) {
test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
test(__func__, m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
test(__func__, m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
test(__func__, m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
if (detect_container() > 0) {
log_notice("Testing in container, skipping remaining tests in %s", __func__);
return;
}
test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
test(__func__, m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
}
static void test_exec_unsetenvironment(Manager *m) {
test(m, "exec-unsetenvironment.service", 0, CLD_EXITED);
test(__func__, m, "exec-unsetenvironment.service", 0, CLD_EXITED);
}
static void test_exec_specifier(Manager *m) {
test(m, "exec-specifier.service", 0, CLD_EXITED);
test(m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
test(m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
test(__func__, m, "exec-specifier.service", 0, CLD_EXITED);
test(__func__, m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
test(__func__, m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
}
static void test_exec_standardinput(Manager *m) {
test(m, "exec-standardinput-data.service", 0, CLD_EXITED);
test(m, "exec-standardinput-file.service", 0, CLD_EXITED);
test(m, "exec-standardinput-file-cat.service", 0, CLD_EXITED);
test(__func__, m, "exec-standardinput-data.service", 0, CLD_EXITED);
test(__func__, m, "exec-standardinput-file.service", 0, CLD_EXITED);
test(__func__, m, "exec-standardinput-file-cat.service", 0, CLD_EXITED);
}
static void test_exec_standardoutput(Manager *m) {
test(m, "exec-standardoutput-file.service", 0, CLD_EXITED);
test(__func__, m, "exec-standardoutput-file.service", 0, CLD_EXITED);
}
static void test_exec_standardoutput_append(Manager *m) {
test(m, "exec-standardoutput-append.service", 0, CLD_EXITED);
test(__func__, m, "exec-standardoutput-append.service", 0, CLD_EXITED);
}
static void test_exec_condition(Manager *m) {
test_service(m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
test_service(m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
test_service(__func__, m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
test_service(__func__, m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
}
typedef struct test_entry {

View File

@ -802,6 +802,50 @@ static void test_chmod_and_chown(void) {
assert_se(S_ISLNK(st.st_mode));
}
static void test_chmod_and_chown_unsafe(void) {
_cleanup_(rm_rf_physical_and_freep) char *d = NULL;
_unused_ _cleanup_umask_ mode_t u = umask(0000);
struct stat st;
const char *p;
if (geteuid() != 0)
return;
log_info("/* %s */", __func__);
assert_se(mkdtemp_malloc(NULL, &d) >= 0);
p = strjoina(d, "/reg");
assert_se(mknod(p, S_IFREG | 0123, 0) >= 0);
assert_se(chmod_and_chown_unsafe(p, S_IFREG | 0321, 1, 2) >= 0);
assert_se(chmod_and_chown_unsafe(p, S_IFDIR | 0555, 3, 4) == -EINVAL);
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISREG(st.st_mode));
assert_se((st.st_mode & 07777) == 0321);
p = strjoina(d, "/dir");
assert_se(mkdir(p, 0123) >= 0);
assert_se(chmod_and_chown_unsafe(p, S_IFDIR | 0321, 1, 2) >= 0);
assert_se(chmod_and_chown_unsafe(p, S_IFREG | 0555, 3, 4) == -EINVAL);
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISDIR(st.st_mode));
assert_se((st.st_mode & 07777) == 0321);
p = strjoina(d, "/lnk");
assert_se(symlink("idontexist", p) >= 0);
assert_se(chmod_and_chown_unsafe(p, S_IFLNK | 0321, 1, 2) >= 0);
assert_se(chmod_and_chown_unsafe(p, S_IFREG | 0555, 3, 4) == -EINVAL);
assert_se(chmod_and_chown_unsafe(p, S_IFDIR | 0555, 3, 4) == -EINVAL);
assert_se(lstat(p, &st) >= 0);
assert_se(S_ISLNK(st.st_mode));
}
static void test_path_is_encrypted_one(const char *p, int expect) {
int r;
@ -851,6 +895,7 @@ int main(int argc, char *argv[]) {
test_fsync_directory_of_file();
test_rename_noreplace();
test_chmod_and_chown();
test_chmod_and_chown_unsafe();
test_path_is_encrypted();
return 0;

View File

@ -202,11 +202,12 @@ static void test_config_parse_exec(void) {
"-@/RValue argv0 r1 ; ; "
"/goo/goo boo",
&c, u);
assert_se(r >= 0);
assert_se(r == -ENOEXEC);
c1 = c1->command_next;
check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
c1 = c1->command_next;
check_execcommand(c1, "/goo/goo", "/goo/goo", "boo", NULL, false);
/* second command fails because the executable name is ";" */
assert_se(c1->command_next == NULL);
log_info("/* trailing semicolon */");
r = config_parse_exec(NULL, "fake", 5, "section", 1,

View File

@ -164,76 +164,31 @@ static void test_path_equal_root(void) {
assert_se(!path_equal_or_files_same("/", "/.../", AT_SYMLINK_NOFOLLOW));
}
static void test_find_executable_full(void) {
static void test_find_binary(const char *self) {
char *p;
log_info("/* %s */", __func__);
assert_se(find_executable_full("sh", true, &p) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
assert_se(find_executable_full("sh", false, &p) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
_cleanup_free_ char *oldpath = NULL;
p = getenv("PATH");
if (p)
assert_se(oldpath = strdup(p));
assert_se(unsetenv("PATH") >= 0);
assert_se(find_executable_full("sh", true, &p) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
assert_se(find_executable_full("sh", false, &p) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
if (oldpath)
assert_se(setenv("PATH", oldpath, true) >= 0);
}
static void test_find_executable(const char *self) {
char *p;
log_info("/* %s */", __func__);
assert_se(find_executable("/bin/sh", &p) == 0);
assert_se(find_binary("/bin/sh", &p) == 0);
puts(p);
assert_se(path_equal(p, "/bin/sh"));
free(p);
assert_se(find_executable(self, &p) == 0);
assert_se(find_binary(self, &p) == 0);
puts(p);
assert_se(endswith(p, "/test-path-util"));
/* libtool might prefix the binary name with "lt-" */
assert_se(endswith(p, "/lt-test-path-util") || endswith(p, "/test-path-util"));
assert_se(path_is_absolute(p));
free(p);
assert_se(find_executable("sh", &p) == 0);
assert_se(find_binary("sh", &p) == 0);
puts(p);
assert_se(endswith(p, "/sh"));
assert_se(path_is_absolute(p));
free(p);
assert_se(find_executable("/bin/touch", &p) == 0);
assert_se(streq(p, "/bin/touch"));
free(p);
assert_se(find_executable("touch", &p) == 0);
assert_se(path_is_absolute(p));
assert_se(streq(basename(p), "touch"));
free(p);
assert_se(find_executable("xxxx-xxxx", &p) == -ENOENT);
assert_se(find_executable("/some/dir/xxxx-xxxx", &p) == -ENOENT);
assert_se(find_executable("/proc/filesystems", &p) == -EACCES);
assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT);
assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT);
}
static void test_prefixes(void) {
@ -582,9 +537,6 @@ static void test_filename_is_valid(void) {
assert_se(!filename_is_valid("/"));
assert_se(!filename_is_valid("."));
assert_se(!filename_is_valid(".."));
assert_se(!filename_is_valid("bar/foo"));
assert_se(!filename_is_valid("bar/foo/"));
assert_se(!filename_is_valid("bar//"));
for (i=0; i<FILENAME_MAX+1; i++)
foo[i] = 'a';
@ -715,8 +667,7 @@ int main(int argc, char **argv) {
test_print_paths();
test_path();
test_path_equal_root();
test_find_executable_full();
test_find_executable(argv[0]);
test_find_binary(argv[0]);
test_prefixes();
test_path_join();
test_fsck_exists();

View File

@ -405,7 +405,7 @@ int xdg_autostart_format_exec_start(
/* This is the executable, find it in $PATH */
first_arg = false;
r = find_executable(c, &executable);
r = find_binary(c, &executable);
if (r < 0)
return log_info_errno(r, "Exec binary '%s' does not exist: %m", c);
@ -481,7 +481,7 @@ static int xdg_autostart_generate_desktop_condition(
if (!isempty(condition)) {
_cleanup_free_ char *gnome_autostart_condition_path = NULL, *e_autostart_condition = NULL;
r = find_executable(test_binary, &gnome_autostart_condition_path);
r = find_binary(test_binary, &gnome_autostart_condition_path);
if (r < 0) {
log_full_errno(r == -ENOENT ? LOG_INFO : LOG_WARNING, r,
"%s not found: %m", test_binary);
@ -536,10 +536,10 @@ int xdg_autostart_service_generate_unit(
/*
* The TryExec key cannot be checked properly from the systemd unit,
* it is trivial to check using find_executable though.
* it is trivial to check using find_binary though.
*/
if (service->try_exec) {
r = find_executable(service->try_exec, NULL);
r = find_binary(service->try_exec, NULL);
if (r < 0) {
log_full_errno(r == -ENOENT ? LOG_INFO : LOG_WARNING, r,
"Not generating service for XDG autostart %s, could not find TryExec= binary %s: %m",