1
0
mirror of https://github.com/systemd/systemd synced 2025-12-28 11:54:45 +01:00

Compare commits

..

No commits in common. "ce9fb09e968db773d2cf01cbea62595d1b4534c4" and "7509c7fdf94df385661ab9818df0dc5f0a3b7247" have entirely different histories.

28 changed files with 312 additions and 536 deletions

2
TODO
View File

@ -113,6 +113,8 @@ Features:
* systemd-firstboot: make sure to always use chase_symlinks() before * systemd-firstboot: make sure to always use chase_symlinks() before
reading/writing files reading/writing files
* add ConditionSecurity=tpm2
* Remove any support for booting without /usr pre-mounted in the initrd entirely. * Remove any support for booting without /usr pre-mounted in the initrd entirely.
Update INITRD_INTERFACE.md accordingly. Update INITRD_INTERFACE.md accordingly.

View File

@ -1257,9 +1257,9 @@
<listitem><para><varname>ConditionSecurity=</varname> may be used to check whether the given <listitem><para><varname>ConditionSecurity=</varname> may be used to check whether the given
security technology is enabled on the system. Currently, the recognized values are security technology is enabled on the system. Currently, the recognized values are
<literal>selinux</literal>, <literal>apparmor</literal>, <literal>tomoyo</literal>, <literal>selinux</literal>, <literal>apparmor</literal>, <literal>tomoyo</literal>,
<literal>ima</literal>, <literal>smack</literal>, <literal>audit</literal>, <literal>ima</literal>, <literal>smack</literal>, <literal>audit</literal> and
<literal>uefi-secureboot</literal> and <literal>tpm2</literal>. The test may be negated by prepending <literal>uefi-secureboot</literal>. The test may be negated by prepending an exclamation
an exclamation mark.</para> mark.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -216,7 +216,6 @@ conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local')) conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper()) conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
conf.set10('ENABLE_FEXECVE', get_option('fexecve'))
conf.set_quoted('USER_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'user')) conf.set_quoted('USER_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'user'))
conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir) conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir)
@ -535,7 +534,6 @@ foreach ident : [
#include <signal.h> #include <signal.h>
#include <sys/wait.h>'''], #include <sys/wait.h>'''],
['mallinfo', '''#include <malloc.h>'''], ['mallinfo', '''#include <malloc.h>'''],
['execveat', '''#include <unistd.h>'''],
['close_range', '''#include <unistd.h>'''], ['close_range', '''#include <unistd.h>'''],
] ]
@ -3834,7 +3832,6 @@ foreach tuple : [
['link-timesyncd-shared', get_option('link-timesyncd-shared')], ['link-timesyncd-shared', get_option('link-timesyncd-shared')],
['kernel-install', get_option('kernel-install')], ['kernel-install', get_option('kernel-install')],
['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1], ['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1],
['fexecve'],
] ]
if tuple.length() >= 2 if tuple.length() >= 2

View File

@ -375,15 +375,13 @@ option('fuzz-tests', type : 'boolean', value : 'false',
option('install-tests', type : 'boolean', value : 'false', option('install-tests', type : 'boolean', value : 'false',
description : 'install test executables') description : 'install test executables')
option('ok-color', type : 'combo', option('ok-color', type: 'combo',
choices : ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', choices : ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan',
'white', 'highlight-black', 'highlight-red', 'highlight-green', 'white', 'highlight-black', 'highlight-red', 'highlight-green',
'highlight-yellow', 'highlight-blue', 'highlight-magenta', 'highlight-yellow', 'highlight-blue', 'highlight-magenta',
'highlight-cyan', 'highlight-white'], 'highlight-cyan', 'highlight-white'],
value : 'green', value : 'green',
description: 'color of the "OK" status message') description: 'color of the "OK" status message')
option('fexecve', type : 'boolean', value : 'false',
description : 'use fexecve() to spawn children')
option('oss-fuzz', type : 'boolean', value : 'false', option('oss-fuzz', type : 'boolean', value : 'false',
description : 'build against oss-fuzz') description : 'build against oss-fuzz')

View File

@ -1,216 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "build.h"
const char* const systemd_features =
/* PAM and MAC frameworks */
#if HAVE_PAM
"+PAM"
#else
"-PAM"
#endif
#if HAVE_AUDIT
" +AUDIT"
#else
" -AUDIT"
#endif
#if HAVE_SELINUX
" +SELINUX"
#else
" -SELINUX"
#endif
#if HAVE_APPARMOR
" +APPARMOR"
#else
" -APPARMOR"
#endif
#if ENABLE_IMA
" +IMA"
#else
" -IMA"
#endif
#if ENABLE_SMACK
" +SMACK"
#else
" -SMACK"
#endif
#if HAVE_SECCOMP
" +SECCOMP"
#else
" -SECCOMP"
#endif
/* crypto libraries */
#if HAVE_GCRYPT
" +GCRYPT"
#else
" -GCRYPT"
#endif
#if HAVE_GNUTLS
" +GNUTLS"
#else
" -GNUTLS"
#endif
#if HAVE_OPENSSL
" +OPENSSL"
#else
" -OPENSSL"
#endif
/* all other libraries, sorted alphabetically */
#if HAVE_ACL
" +ACL"
#else
" -ACL"
#endif
#if HAVE_BLKID
" +BLKID"
#else
" -BLKID"
#endif
#if HAVE_LIBCURL
" +CURL"
#else
" -CURL"
#endif
#if HAVE_ELFUTILS
" +ELFUTILS"
#else
" -ELFUTILS"
#endif
#if HAVE_LIBFIDO2
" +FIDO2"
#else
" -FIDO2"
#endif
#if HAVE_LIBIDN2
" +IDN2"
#else
" -IDN2"
#endif
#if HAVE_LIBIDN
" +IDN"
#else
" -IDN"
#endif
#if HAVE_LIBIPTC
" +IPTC"
#else
" -IPTC"
#endif
#if HAVE_KMOD
" +KMOD"
#else
" -KMOD"
#endif
#if HAVE_LIBCRYPTSETUP
" +LIBCRYPTSETUP"
#else
" -LIBCRYPTSETUP"
#endif
#if HAVE_LIBFDISK
" +LIBFDISK"
#else
" -LIBFDISK"
#endif
#if HAVE_PCRE2
" +PCRE2"
#else
" -PCRE2"
#endif
#if HAVE_PWQUALITY
" +PWQUALITY"
#else
" -PWQUALITY"
#endif
#if HAVE_P11KIT
" +P11KIT"
#else
" -P11KIT"
#endif
#if HAVE_QRENCODE
" +QRENCODE"
#else
" -QRENCODE"
#endif
/* compressors */
#if HAVE_BZIP2
" +BZIP2"
#else
" -BZIP2"
#endif
#if HAVE_LZ4
" +LZ4"
#else
" -LZ4"
#endif
#if HAVE_XZ
" +XZ"
#else
" -XZ"
#endif
#if HAVE_ZLIB
" +ZLIB"
#else
" -ZLIB"
#endif
#if HAVE_ZSTD
" +ZSTD"
#else
" -ZSTD"
#endif
/* other stuff that doesn't fit above */
#if HAVE_XKBCOMMON
" +XKBCOMMON"
#else
" -XKBCOMMON"
#endif
#if ENABLE_UTMP
" +UTMP"
#else
" -UTMP"
#endif
#if HAVE_SYSV_COMPAT
" +SYSVINIT"
#else
" -SYSVINIT"
#endif
" default-hierarchy=" DEFAULT_HIERARCHY_NAME
;

View File

@ -3,7 +3,164 @@
#include "version.h" #include "version.h"
extern const char* const systemd_features; #if HAVE_PAM
#define _PAM_FEATURE_ "+PAM"
#else
#define _PAM_FEATURE_ "-PAM"
#endif
#if HAVE_AUDIT
#define _AUDIT_FEATURE_ "+AUDIT"
#else
#define _AUDIT_FEATURE_ "-AUDIT"
#endif
#if HAVE_SELINUX
#define _SELINUX_FEATURE_ "+SELINUX"
#else
#define _SELINUX_FEATURE_ "-SELINUX"
#endif
#if HAVE_APPARMOR
#define _APPARMOR_FEATURE_ "+APPARMOR"
#else
#define _APPARMOR_FEATURE_ "-APPARMOR"
#endif
#if ENABLE_IMA
#define _IMA_FEATURE_ "+IMA"
#else
#define _IMA_FEATURE_ "-IMA"
#endif
#if ENABLE_SMACK
#define _SMACK_FEATURE_ "+SMACK"
#else
#define _SMACK_FEATURE_ "-SMACK"
#endif
#if HAVE_SYSV_COMPAT
#define _SYSVINIT_FEATURE_ "+SYSVINIT"
#else
#define _SYSVINIT_FEATURE_ "-SYSVINIT"
#endif
#if ENABLE_UTMP
#define _UTMP_FEATURE_ "+UTMP"
#else
#define _UTMP_FEATURE_ "-UTMP"
#endif
#if HAVE_LIBCRYPTSETUP
#define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP"
#else
#define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP"
#endif
#if HAVE_GCRYPT
#define _GCRYPT_FEATURE_ "+GCRYPT"
#else
#define _GCRYPT_FEATURE_ "-GCRYPT"
#endif
#if HAVE_GNUTLS
#define _GNUTLS_FEATURE_ "+GNUTLS"
#else
#define _GNUTLS_FEATURE_ "-GNUTLS"
#endif
#if HAVE_ACL
#define _ACL_FEATURE_ "+ACL"
#else
#define _ACL_FEATURE_ "-ACL"
#endif
#if HAVE_XZ
#define _XZ_FEATURE_ "+XZ"
#else
#define _XZ_FEATURE_ "-XZ"
#endif
#if HAVE_LZ4
#define _LZ4_FEATURE_ "+LZ4"
#else
#define _LZ4_FEATURE_ "-LZ4"
#endif
#if HAVE_ZSTD
#define _ZSTD_FEATURE_ "+ZSTD"
#else
#define _ZSTD_FEATURE_ "-ZSTD"
#endif
#if HAVE_SECCOMP
#define _SECCOMP_FEATURE_ "+SECCOMP"
#else
#define _SECCOMP_FEATURE_ "-SECCOMP"
#endif
#if HAVE_BLKID
#define _BLKID_FEATURE_ "+BLKID"
#else
#define _BLKID_FEATURE_ "-BLKID"
#endif
#if HAVE_ELFUTILS
#define _ELFUTILS_FEATURE_ "+ELFUTILS"
#else
#define _ELFUTILS_FEATURE_ "-ELFUTILS"
#endif
#if HAVE_KMOD
#define _KMOD_FEATURE_ "+KMOD"
#else
#define _KMOD_FEATURE_ "-KMOD"
#endif
#if HAVE_LIBIDN2
#define _IDN2_FEATURE_ "+IDN2"
#else
#define _IDN2_FEATURE_ "-IDN2"
#endif
#if HAVE_LIBIDN
#define _IDN_FEATURE_ "+IDN"
#else
#define _IDN_FEATURE_ "-IDN"
#endif
#if HAVE_PCRE2
#define _PCRE2_FEATURE_ "+PCRE2"
#else
#define _PCRE2_FEATURE_ "-PCRE2"
#endif
#define _CGROUP_HIERARCHY_ "default-hierarchy=" DEFAULT_HIERARCHY_NAME
#define SYSTEMD_FEATURES \
_PAM_FEATURE_ " " \
_AUDIT_FEATURE_ " " \
_SELINUX_FEATURE_ " " \
_IMA_FEATURE_ " " \
_APPARMOR_FEATURE_ " " \
_SMACK_FEATURE_ " " \
_SYSVINIT_FEATURE_ " " \
_UTMP_FEATURE_ " " \
_LIBCRYPTSETUP_FEATURE_ " " \
_GCRYPT_FEATURE_ " " \
_GNUTLS_FEATURE_ " " \
_ACL_FEATURE_ " " \
_XZ_FEATURE_ " " \
_LZ4_FEATURE_ " " \
_ZSTD_FEATURE_ " " \
_SECCOMP_FEATURE_ " " \
_BLKID_FEATURE_ " " \
_ELFUTILS_FEATURE_ " " \
_KMOD_FEATURE_ " " \
_IDN2_FEATURE_ " " \
_IDN_FEATURE_ " " \
_PCRE2_FEATURE_ " " \
_CGROUP_HIERARCHY_
enum { enum {
BUILD_MODE_DEVELOPER, BUILD_MODE_DEVELOPER,

View File

@ -19,7 +19,6 @@ basic_sources = files('''
blockdev-util.h blockdev-util.h
btrfs-util.c btrfs-util.c
btrfs-util.h btrfs-util.h
build.c
build.h build.h
bus-label.c bus-label.c
bus-label.h bus-label.h

View File

@ -751,25 +751,6 @@ static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info)
/* ======================================================================= */ /* ======================================================================= */
#if !HAVE_EXECVEAT
static inline int missing_execveat(int dirfd, const char *pathname,
char *const argv[], char *const envp[],
int flags) {
# if defined __NR_execveat && __NR_execveat >= 0
return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# undef AT_EMPTY_PATH
# define AT_EMPTY_PATH 0x1000
# define execveat missing_execveat
#endif
/* ======================================================================= */
#define systemd_NR_close_range systemd_SC_arch_bias(436) #define systemd_NR_close_range systemd_SC_arch_bias(436)
/* may be (invalid) negative number due to libseccomp, see PR 13319 */ /* may be (invalid) negative number due to libseccomp, see PR 13319 */

View File

@ -585,53 +585,22 @@ char* path_join_internal(const char *first, ...) {
return joined; return joined;
} }
static int check_x_access(const char *path, int *ret_fd) { int find_executable_full(const char *name, bool use_path_envvar, char **ret) {
if (ret_fd) {
_cleanup_close_ int fd = -1;
int r;
/* We need to use O_PATH because there may be executables for which we have only exec
* permissions, but not read (usually suid executables). */
fd = open(path, O_PATH|O_CLOEXEC);
if (fd < 0)
return -errno;
r = access_fd(fd, X_OK);
if (r < 0)
return r;
*ret_fd = TAKE_FD(fd);
} else {
/* Let's optimize things a bit by not opening the file if we don't need the fd. */
if (access(path, X_OK) < 0)
return -errno;
}
return 0;
}
int find_executable_full(const char *name, bool use_path_envvar, char **ret_filename, int *ret_fd) {
int last_error, r; int last_error, r;
const char *p = NULL; const char *p = NULL;
assert(name); assert(name);
if (is_path(name)) { if (is_path(name)) {
_cleanup_close_ int fd = -1; if (access(name, X_OK) < 0)
return -errno;
r = check_x_access(name, ret_fd ? &fd : NULL); if (ret) {
if (r < 0) r = path_make_absolute_cwd(name, ret);
return r;
if (ret_filename) {
r = path_make_absolute_cwd(name, ret_filename);
if (r < 0) if (r < 0)
return r; return r;
} }
if (ret_fd)
*ret_fd = TAKE_FD(fd);
return 0; return 0;
} }
@ -644,10 +613,8 @@ int find_executable_full(const char *name, bool use_path_envvar, char **ret_file
last_error = -ENOENT; last_error = -ENOENT;
/* Resolve a single-component name to a full path */
for (;;) { for (;;) {
_cleanup_free_ char *j = NULL, *element = NULL; _cleanup_free_ char *j = NULL, *element = NULL;
_cleanup_close_ int fd = -1;
r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS); r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0) if (r < 0)
@ -662,8 +629,7 @@ int find_executable_full(const char *name, bool use_path_envvar, char **ret_file
if (!j) if (!j)
return -ENOMEM; return -ENOMEM;
r = check_x_access(j, ret_fd ? &fd : NULL); if (access(j, X_OK) >= 0) {
if (r >= 0) {
_cleanup_free_ char *with_dash; _cleanup_free_ char *with_dash;
with_dash = strjoin(j, "/"); with_dash = strjoin(j, "/");
@ -677,10 +643,8 @@ int find_executable_full(const char *name, bool use_path_envvar, char **ret_file
/* 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) { if (errno == ENOTDIR) {
/* Found it! */ /* Found it! */
if (ret_filename) if (ret)
*ret_filename = path_simplify(TAKE_PTR(j), false); *ret = path_simplify(TAKE_PTR(j), false);
if (ret_fd)
*ret_fd = TAKE_FD(fd);
return 0; return 0;
} }

View File

@ -88,9 +88,9 @@ int path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *root); char** path_strv_resolve(char **l, const char *root);
char** path_strv_resolve_uniq(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_filename, int *ret_fd); int find_executable_full(const char *name, bool use_path_envvar, char **ret);
static inline int find_executable(const char *name, char **ret_filename) { static inline int find_executable(const char *name, char **ret) {
return find_executable_full(name, true, ret_filename, NULL); return find_executable_full(name, true, ret);
} }
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);

View File

@ -452,21 +452,10 @@ size_t random_pool_size(void) {
} }
int random_write_entropy(int fd, const void *seed, size_t size, bool credit) { int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
_cleanup_close_ int opened_fd = -1;
int r; int r;
assert(seed || size == 0); assert(fd >= 0);
assert(seed && size > 0);
if (size == 0)
return 0;
if (fd < 0) {
opened_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (opened_fd < 0)
return -errno;
fd = opened_fd;
}
if (credit) { if (credit) {
_cleanup_free_ struct rand_pool_info *info = NULL; _cleanup_free_ struct rand_pool_info *info = NULL;
@ -492,5 +481,5 @@ int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
return r; return r;
} }
return 1; return 0;
} }

View File

@ -193,8 +193,8 @@ int container_get_leader(const char *machine, pid_t *pid) {
} }
int version(void) { int version(void) {
printf("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n%s\n", puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n"
systemd_features); SYSTEMD_FEATURES);
return 0; return 0;
} }

View File

@ -49,7 +49,7 @@ static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_oom_policy, oom_policy, OOMPolicy); BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_oom_policy, oom_policy, OOMPolicy);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", systemd_features); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", SYSTEMD_FEATURES);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture())); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture()));
static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string); static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK)); static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));

View File

@ -43,6 +43,7 @@ static void lock_down_efi_variables(void) {
int efi_take_random_seed(void) { int efi_take_random_seed(void) {
_cleanup_free_ void *value = NULL; _cleanup_free_ void *value = NULL;
_cleanup_close_ int random_fd = -1;
size_t size; size_t size;
int r; int r;
@ -76,13 +77,17 @@ int efi_take_random_seed(void) {
if (size == 0) if (size == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring."); return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring.");
random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (random_fd < 0)
return log_warning_errno(errno, "Failed to open /dev/urandom for writing, ignoring: %m");
/* Before we use the seed, let's mark it as used, so that we never credit it twice. Also, it's a nice /* Before we use the seed, let's mark it as used, so that we never credit it twice. Also, it's a nice
* way to let users known that we successfully acquired entropy from the boot laoder. */ * way to let users known that we successfully acquired entropy from the boot laoder. */
r = touch("/run/systemd/efi-random-seed-taken"); r = touch("/run/systemd/efi-random-seed-taken");
if (r < 0) if (r < 0)
return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m"); return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m");
r = random_write_entropy(-1, value, size, true); r = random_write_entropy(random_fd, value, size, true);
if (r < 0) if (r < 0)
return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m"); return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m");

View File

@ -1248,8 +1248,8 @@ static int setup_pam(
* termination */ * termination */
barrier_set_role(&barrier, BARRIER_CHILD); barrier_set_role(&barrier, BARRIER_CHILD);
/* Make sure we don't keep open the passed fds in this child. We assume that otherwise only /* Make sure we don't keep open the passed fds in this child. We assume that otherwise only those fds
* those fds are open here that have been opened by PAM. */ * are open here that have been opened by PAM. */
(void) close_many(fds, n_fds); (void) close_many(fds, n_fds);
/* Drop privileges - we don't need any to pam_close_session /* Drop privileges - we don't need any to pam_close_session
@ -2893,11 +2893,11 @@ static int setup_credentials(
#if ENABLE_SMACK #if ENABLE_SMACK
static int setup_smack( static int setup_smack(
const ExecContext *context, const ExecContext *context,
int executable_fd) { const char *executable) {
int r; int r;
assert(context); assert(context);
assert(executable_fd >= 0); assert(executable);
if (context->smack_process_label) { if (context->smack_process_label) {
r = mac_smack_apply_pid(0, context->smack_process_label); r = mac_smack_apply_pid(0, context->smack_process_label);
@ -2908,7 +2908,7 @@ static int setup_smack(
else { else {
_cleanup_free_ char *exec_label = NULL; _cleanup_free_ char *exec_label = NULL;
r = mac_smack_read_fd(executable_fd, SMACK_ATTR_EXEC, &exec_label); r = mac_smack_read(executable, SMACK_ATTR_EXEC, &exec_label);
if (r < 0 && !IN_SET(r, -ENODATA, -EOPNOTSUPP)) if (r < 0 && !IN_SET(r, -ENODATA, -EOPNOTSUPP))
return r; return r;
@ -3419,6 +3419,7 @@ static int close_remaining_fds(
const DynamicCreds *dcreds, const DynamicCreds *dcreds,
int user_lookup_fd, int user_lookup_fd,
int socket_fd, int socket_fd,
int exec_fd,
const int *fds, size_t n_fds) { const int *fds, size_t n_fds) {
size_t n_dont_close = 0; size_t n_dont_close = 0;
@ -3435,6 +3436,8 @@ static int close_remaining_fds(
if (socket_fd >= 0) if (socket_fd >= 0)
dont_close[n_dont_close++] = socket_fd; dont_close[n_dont_close++] = socket_fd;
if (exec_fd >= 0)
dont_close[n_dont_close++] = exec_fd;
if (n_fds > 0) { if (n_fds > 0) {
memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds); memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
n_dont_close += n_fds; n_dont_close += n_fds;
@ -3611,35 +3614,6 @@ bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c) {
return c->cpu_affinity_from_numa; return c->cpu_affinity_from_numa;
} }
static int add_shifted_fd(int *fds, size_t fds_size, size_t *n_fds, int fd, int *ret_fd) {
int r;
assert(fds);
assert(n_fds);
assert(*n_fds < fds_size);
assert(ret_fd);
if (fd < 0) {
*ret_fd = -1;
return 0;
}
if (fd < 3 + (int) *n_fds) {
/* Let's move the fd up, so that it's outside of the fd range we will use to store
* the fds we pass to the process (or which are closed only during execve). */
r = fcntl(fd, F_DUPFD_CLOEXEC, 3 + (int) *n_fds);
if (r < 0)
return -errno;
CLOSE_AND_REPLACE(fd, r);
}
*ret_fd = fds[*n_fds] = fd;
(*n_fds) ++;
return 1;
}
static int exec_child( static int exec_child(
Unit *unit, Unit *unit,
const ExecCommand *command, const ExecCommand *command,
@ -3657,7 +3631,7 @@ static int exec_child(
int *exit_status) { int *exit_status) {
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **replaced_argv = NULL; _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **replaced_argv = NULL;
int r, ngids = 0, exec_fd; int *fds_with_exec_fd, n_fds_with_exec_fd, r, ngids = 0, exec_fd = -1;
_cleanup_free_ gid_t *supplementary_gids = NULL; _cleanup_free_ gid_t *supplementary_gids = NULL;
const char *username = NULL, *groupname = NULL; const char *username = NULL, *groupname = NULL;
_cleanup_free_ char *home_buffer = NULL; _cleanup_free_ char *home_buffer = NULL;
@ -3684,8 +3658,7 @@ static int exec_child(
gid_t saved_gid = getgid(); gid_t saved_gid = getgid();
uid_t uid = UID_INVALID; uid_t uid = UID_INVALID;
gid_t gid = GID_INVALID; gid_t gid = GID_INVALID;
size_t n_fds = n_socket_fds + n_storage_fds, /* fds to pass to the child */ size_t n_fds;
n_keep_fds; /* total number of fds not to close */
int secure_bits; int secure_bits;
_cleanup_free_ gid_t *gids_after_pam = NULL; _cleanup_free_ gid_t *gids_after_pam = NULL;
int ngids_after_pam = 0; int ngids_after_pam = 0;
@ -3729,17 +3702,8 @@ static int exec_child(
/* In case anything used libc syslog(), close this here, too */ /* In case anything used libc syslog(), close this here, too */
closelog(); closelog();
int keep_fds[n_fds + 2]; n_fds = n_socket_fds + n_storage_fds;
memcpy_safe(keep_fds, fds, n_fds * sizeof(int)); r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, params->exec_fd, fds, n_fds);
n_keep_fds = n_fds;
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, params->exec_fd, &exec_fd);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_unit_error_errno(unit, r, "Failed to shift fd and set FD_CLOEXEC: %m");
}
r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, keep_fds, n_keep_fds);
if (r < 0) { if (r < 0) {
*exit_status = EXIT_FDS; *exit_status = EXIT_FDS;
return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m"); return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m");
@ -4131,7 +4095,6 @@ static int exec_child(
/* Let's call into PAM after we set up our own idea of resource limits to that pam_limits /* Let's call into PAM after we set up our own idea of resource limits to that pam_limits
* wins here. (See above.) */ * wins here. (See above.) */
/* All fds passed in the fds array will be closed in the pam child process. */
r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds); r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds);
if (r < 0) { if (r < 0) {
*exit_status = EXIT_PAM; *exit_status = EXIT_PAM;
@ -4239,8 +4202,7 @@ static int exec_child(
* shall execute. */ * shall execute. */
_cleanup_free_ char *executable = NULL; _cleanup_free_ char *executable = NULL;
_cleanup_close_ int executable_fd = -1; r = find_executable_full(command->path, false, &executable);
r = find_executable_full(command->path, false, &executable, &executable_fd);
if (r < 0) { if (r < 0) {
if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) { if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
log_struct_errno(LOG_INFO, r, log_struct_errno(LOG_INFO, r,
@ -4263,12 +4225,6 @@ static int exec_child(
"EXECUTABLE=%s", command->path); "EXECUTABLE=%s", command->path);
} }
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, executable_fd, &executable_fd);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_unit_error_errno(unit, r, "Failed to shift fd and set FD_CLOEXEC: %m");
}
#if HAVE_SELINUX #if HAVE_SELINUX
if (needs_sandboxing && use_selinux && params->selinux_context_net && socket_fd >= 0) { 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); r = mac_selinux_get_child_mls_label(socket_fd, executable, context->selinux_context, &mac_selinux_context_net);
@ -4283,7 +4239,41 @@ static int exec_child(
* more aggressive this time since socket_fd and the netns fds we don't need anymore. We do keep the exec_fd * 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(). */ * however if we have it as we want to keep it open until the final execve(). */
r = close_all_fds(keep_fds, n_keep_fds); if (params->exec_fd >= 0) {
exec_fd = params->exec_fd;
if (exec_fd < 3 + (int) n_fds) {
int moved_fd;
/* Let's move the exec fd far up, so that it's outside of the fd range we want to pass to the
* process we are about to execute. */
moved_fd = fcntl(exec_fd, F_DUPFD_CLOEXEC, 3 + (int) n_fds);
if (moved_fd < 0) {
*exit_status = EXIT_FDS;
return log_unit_error_errno(unit, errno, "Couldn't move exec fd up: %m");
}
CLOSE_AND_REPLACE(exec_fd, moved_fd);
} else {
/* This fd should be FD_CLOEXEC already, but let's make sure. */
r = fd_cloexec(exec_fd, true);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_unit_error_errno(unit, r, "Failed to make exec fd FD_CLOEXEC: %m");
}
}
fds_with_exec_fd = newa(int, n_fds + 1);
memcpy_safe(fds_with_exec_fd, fds, n_fds * sizeof(int));
fds_with_exec_fd[n_fds] = exec_fd;
n_fds_with_exec_fd = n_fds + 1;
} else {
fds_with_exec_fd = fds;
n_fds_with_exec_fd = n_fds;
}
r = close_all_fds(fds_with_exec_fd, n_fds_with_exec_fd);
if (r >= 0) if (r >= 0)
r = shift_fds(fds, n_fds); r = shift_fds(fds, n_fds);
if (r >= 0) if (r >= 0)
@ -4317,7 +4307,7 @@ static int exec_child(
/* LSM Smack needs the capability CAP_MAC_ADMIN to change the current execution security context of the /* 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. */ * process. This is the latest place before dropping capabilities. Other MAC context are set later. */
if (use_smack) { if (use_smack) {
r = setup_smack(context, executable_fd); r = setup_smack(context, executable);
if (r < 0) { if (r < 0) {
*exit_status = EXIT_SMACK_PROCESS_LABEL; *exit_status = EXIT_SMACK_PROCESS_LABEL;
return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m"); return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m");
@ -4587,7 +4577,8 @@ static int exec_child(
} }
} }
r = fexecve_or_execve(executable_fd, executable, final_argv, accum_env); execve(executable, final_argv, accum_env);
r = -errno;
if (exec_fd >= 0) { if (exec_fd >= 0) {
uint8_t hot = 0; uint8_t hot = 0;

View File

@ -1605,6 +1605,7 @@ static void apply_clock_update(void) {
} }
static void cmdline_take_random_seed(void) { static void cmdline_take_random_seed(void) {
_cleanup_close_ int random_fd = -1;
size_t suggested; size_t suggested;
int r; int r;
@ -1621,7 +1622,13 @@ static void cmdline_take_random_seed(void) {
log_warning("Random seed specified on kernel command line has size %zu, but %zu bytes required to fill entropy pool.", log_warning("Random seed specified on kernel command line has size %zu, but %zu bytes required to fill entropy pool.",
arg_random_seed_size, suggested); arg_random_seed_size, suggested);
r = random_write_entropy(-1, arg_random_seed, arg_random_seed_size, true); random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (random_fd < 0) {
log_warning_errno(errno, "Failed to open /dev/urandom for writing, ignoring: %m");
return;
}
r = random_write_entropy(random_fd, arg_random_seed, arg_random_seed_size, true);
if (r < 0) { if (r < 0) {
log_warning_errno(r, "Failed to credit entropy specified on kernel command line, ignoring: %m"); log_warning_errno(r, "Failed to credit entropy specified on kernel command line, ignoring: %m");
return; return;
@ -1980,9 +1987,8 @@ static void log_execution_mode(bool *ret_first_boot) {
if (arg_system) { if (arg_system) {
int v; int v;
log_info("systemd " GIT_VERSION " running in %ssystem mode. (%s)", log_info("systemd " GIT_VERSION " running in %ssystem mode. (" SYSTEMD_FEATURES ")",
arg_action == ACTION_TEST ? "test " : "", arg_action == ACTION_TEST ? "test " : "" );
systemd_features);
v = detect_virtualization(); v = detect_virtualization();
if (v > 0) if (v > 0)
@ -2020,9 +2026,8 @@ static void log_execution_mode(bool *ret_first_boot) {
_cleanup_free_ char *t; _cleanup_free_ char *t;
t = uid_to_name(getuid()); t = uid_to_name(getuid());
log_debug("systemd " GIT_VERSION " running in %suser mode for user " UID_FMT "/%s. (%s)", log_debug("systemd " GIT_VERSION " running in %suser mode for user " UID_FMT "/%s. (" SYSTEMD_FEATURES ")",
arg_action == ACTION_TEST ? " test" : "", arg_action == ACTION_TEST ? " test" : "", getuid(), strna(t));
getuid(), strna(t), systemd_features);
} }
*ret_first_boot = false; *ret_first_boot = false;

View File

@ -144,35 +144,29 @@ Address *address_free(Address *address) {
return mfree(address); return mfree(address);
} }
static bool address_may_have_broadcast(const Address *a) {
assert(a);
/* A /31 or /32 IPv4 address does not have a broadcast address.
* See https://tools.ietf.org/html/rfc3021 */
return a->family == AF_INET && in4_addr_is_null(&a->in_addr_peer.in) && a->prefixlen <= 30;
}
void address_hash_func(const Address *a, struct siphash *state) { void address_hash_func(const Address *a, struct siphash *state) {
assert(a); assert(a);
siphash24_compress(&a->family, sizeof(a->family), state); siphash24_compress(&a->family, sizeof(a->family), state);
if (!IN_SET(a->family, AF_INET, AF_INET6)) switch (a->family) {
/* treat non-IPv4 or IPv6 address family as AF_UNSPEC */ case AF_INET:
return; siphash24_compress(&a->broadcast, sizeof(a->broadcast), state);
if (a->family == AF_INET)
siphash24_compress_string(a->label, state); siphash24_compress_string(a->label, state);
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state); _fallthrough_;
/* local address */ case AF_INET6:
siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state); siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
/* peer address */ /* local address */
siphash24_compress(&a->in_addr_peer, FAMILY_ADDRESS_SIZE(a->family), state); siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
/* peer address */
siphash24_compress(&a->in_addr_peer, FAMILY_ADDRESS_SIZE(a->family), state);
if (address_may_have_broadcast(a)) break;
siphash24_compress(&a->broadcast, sizeof(a->broadcast), state); default:
/* treat any other address family as AF_UNSPEC */
break;
}
} }
int address_compare_func(const Address *a1, const Address *a2) { int address_compare_func(const Address *a1, const Address *a2) {
@ -182,32 +176,32 @@ int address_compare_func(const Address *a1, const Address *a2) {
if (r != 0) if (r != 0)
return r; return r;
if (!IN_SET(a1->family, AF_INET, AF_INET6)) switch (a1->family) {
/* treat non-IPv4 or IPv6 address family as AF_UNSPEC */ /* use the same notion of equality as the kernel does */
return 0; case AF_INET:
r = CMP(a1->broadcast.s_addr, a2->broadcast.s_addr);
if (r != 0)
return r;
if (a1->family == AF_INET) {
r = strcmp_ptr(a1->label, a2->label); r = strcmp_ptr(a1->label, a2->label);
if (r != 0) if (r != 0)
return r; return r;
_fallthrough_;
case AF_INET6:
r = CMP(a1->prefixlen, a2->prefixlen);
if (r != 0)
return r;
r = memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
if (r != 0)
return r;
return memcmp(&a1->in_addr_peer, &a2->in_addr_peer, FAMILY_ADDRESS_SIZE(a1->family));
default:
/* treat any other address family as AF_UNSPEC */
return 0;
} }
r = CMP(a1->prefixlen, a2->prefixlen);
if (r != 0)
return r;
r = memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
if (r != 0)
return r;
r = memcmp(&a1->in_addr_peer, &a2->in_addr_peer, FAMILY_ADDRESS_SIZE(a1->family));
if (r != 0)
return r;
if (address_may_have_broadcast(a1))
return CMP(a1->broadcast.s_addr, a2->broadcast.s_addr);
return 0;
} }
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free); DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
@ -228,21 +222,18 @@ static int address_copy(Address *dest, const Address *src) {
assert(dest); assert(dest);
assert(src); assert(src);
if (src->family == AF_INET) { r = free_and_strdup(&dest->label, src->label);
r = free_and_strdup(&dest->label, src->label); if (r < 0)
if (r < 0) return r;
return r;
}
dest->family = src->family; dest->family = src->family;
dest->prefixlen = src->prefixlen; dest->prefixlen = src->prefixlen;
dest->scope = src->scope; dest->scope = src->scope;
dest->flags = src->flags; dest->flags = src->flags;
dest->broadcast = src->broadcast;
dest->cinfo = src->cinfo; dest->cinfo = src->cinfo;
dest->in_addr = src->in_addr; dest->in_addr = src->in_addr;
dest->in_addr_peer = src->in_addr_peer; dest->in_addr_peer = src->in_addr_peer;
if (address_may_have_broadcast(src))
dest->broadcast = src->broadcast;
dest->duplicate_address_detection = src->duplicate_address_detection; dest->duplicate_address_detection = src->duplicate_address_detection;
return 0; return 0;
@ -849,13 +840,13 @@ int address_configure(
r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer); r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
} else if (address_may_have_broadcast(address)) { } else if (address->family == AF_INET && address->prefixlen <= 30) {
r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m"); return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
} }
if (address->family == AF_INET && address->label) { if (address->label) {
r = sd_netlink_message_append_string(req, IFA_LABEL, address->label); r = sd_netlink_message_append_string(req, IFA_LABEL, address->label);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m"); return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
@ -1818,10 +1809,10 @@ static int address_section_verify(Address *address) {
address->section->filename, address->section->line); address->section->filename, address->section->line);
} }
if (address_may_have_broadcast(address)) { if (address->family == AF_INET && in_addr_is_null(address->family, &address->in_addr_peer) &&
if (address->broadcast.s_addr == 0) address->broadcast.s_addr == 0 && address->prefixlen <= 30)
address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen); address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen);
} else if (address->broadcast.s_addr != 0) { else if (address->broadcast.s_addr != 0) {
log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. " log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. "
"Ignoring Broadcast= setting in the [Address] section from line %u.", "Ignoring Broadcast= setting in the [Address] section from line %u.",
address->section->filename, address->section->line); address->section->filename, address->section->line);

View File

@ -865,8 +865,7 @@ static int dhcp4_update_address(Link *link, bool announce) {
addr->cinfo.ifa_prefered = lifetime; addr->cinfo.ifa_prefered = lifetime;
addr->cinfo.ifa_valid = lifetime; addr->cinfo.ifa_valid = lifetime;
addr->prefixlen = prefixlen; addr->prefixlen = prefixlen;
if (prefixlen <= 30) addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link)); SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
/* allow reusing an existing address and simply update its lifetime /* allow reusing an existing address and simply update its lifetime

View File

@ -480,21 +480,6 @@ static int condition_test_ac_power(Condition *c, char **env) {
return (on_ac_power() != 0) == !!r; return (on_ac_power() != 0) == !!r;
} }
static int has_tpm2(void) {
int r;
/* Checks whether the system has at least one TPM2 resource manager device, i.e. at least one "tpmrm"
* class device */
r = dir_is_empty("/sys/class/tpmrm");
if (r == -ENOENT)
return false;
if (r < 0)
return log_debug_errno(r, "Failed to determine whether system has TPM2 support: %m");
return !r;
}
static int condition_test_security(Condition *c, char **env) { static int condition_test_security(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
@ -514,8 +499,6 @@ static int condition_test_security(Condition *c, char **env) {
return mac_tomoyo_use(); return mac_tomoyo_use();
if (streq(c->parameter, "uefi-secureboot")) if (streq(c->parameter, "uefi-secureboot"))
return is_efi_secure_boot(); return is_efi_secure_boot();
if (streq(c->parameter, "tpm2"))
return has_tpm2();
return false; return false;
} }

View File

@ -11,13 +11,11 @@
#include "conf-files.h" #include "conf-files.h"
#include "env-file.h" #include "env-file.h"
#include "env-util.h" #include "env-util.h"
#include "errno-util.h"
#include "exec-util.h" #include "exec-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "hashmap.h" #include "hashmap.h"
#include "macro.h" #include "macro.h"
#include "missing_syscall.h"
#include "process-util.h" #include "process-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
#include "serialize.h" #include "serialize.h"
@ -35,6 +33,7 @@
assert_cc(EAGAIN == EWOULDBLOCK); assert_cc(EAGAIN == EWOULDBLOCK);
static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) { static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
pid_t _pid; pid_t _pid;
int r; int r;
@ -445,26 +444,3 @@ ExecCommandFlags exec_command_flags_from_string(const char *s) {
else else
return 1 << idx; return 1 << idx;
} }
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]) {
#if ENABLE_FEXECVE
execveat(executable_fd, "", argv, envp, AT_EMPTY_PATH);
if (IN_SET(errno, ENOSYS, ENOENT) || ERRNO_IS_PRIVILEGE(errno))
/* Old kernel or a script or an overzealous seccomp filter? Let's fall back to execve().
*
* fexecve(3): "If fd refers to a script (i.e., it is an executable text file that names a
* script interpreter with a first line that begins with the characters #!) and the
* close-on-exec flag has been set for fd, then fexecve() fails with the error ENOENT. This
* error occurs because, by the time the script interpreter is executed, fd has already been
* closed because of the close-on-exec flag. Thus, the close-on-exec flag can't be set on fd
* if it refers to a script."
*
* Unfortunately, if we unset close-on-exec, the script will be executed just fine, but (at
* least in case of bash) the script name, $0, will be shown as /dev/fd/nnn, which breaks
* scripts which make use of $0. Thus, let's fall back to execve() in this case.
*/
#endif
execve(executable, argv, envp);
return -errno;
}

View File

@ -45,5 +45,3 @@ extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX];
const char* exec_command_flags_to_string(ExecCommandFlags i); const char* exec_command_flags_to_string(ExecCommandFlags i);
ExecCommandFlags exec_command_flags_from_string(const char *s); ExecCommandFlags exec_command_flags_from_string(const char *s);
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]);

View File

@ -671,6 +671,7 @@ int pkcs11_token_acquire_rng(
CK_SESSION_HANDLE session) { CK_SESSION_HANDLE session) {
_cleanup_free_ void *buffer = NULL; _cleanup_free_ void *buffer = NULL;
_cleanup_close_ int fd = -1;
size_t rps; size_t rps;
CK_RV rv; CK_RV rv;
int r; int r;
@ -695,7 +696,11 @@ int pkcs11_token_acquire_rng(
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Failed to generate RNG data on security token: %s", p11_kit_strerror(rv)); "Failed to generate RNG data on security token: %s", p11_kit_strerror(rv));
r = random_write_entropy(-1, buffer, rps, false); fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return log_debug_errno(errno, "Failed to open /dev/urandom for writing: %m");
r = loop_write(fd, buffer, rps, false);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to write PKCS#11 acquired random data to /dev/urandom: %m"); return log_debug_errno(r, "Failed to write PKCS#11 acquired random data to /dev/urandom: %m");

View File

@ -18,7 +18,7 @@ static void test_is_wanted_print(bool header) {
assert_se(proc_cmdline(&cmdline) >= 0); assert_se(proc_cmdline(&cmdline) >= 0);
log_info("cmdline: %s", cmdline); log_info("cmdline: %s", cmdline);
if (header) { if (header) {
log_info("default-hierarchy=" DEFAULT_HIERARCHY_NAME); log_info(_CGROUP_HIERARCHY_);
(void) system("findmnt -n /sys/fs/cgroup"); (void) system("findmnt -n /sys/fs/cgroup");
} }

View File

@ -4,12 +4,10 @@
#include <unistd.h> #include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "exec-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "macro.h" #include "macro.h"
#include "mountpoint-util.h" #include "mountpoint-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h"
#include "rm-rf.h" #include "rm-rf.h"
#include "stat-util.h" #include "stat-util.h"
#include "string-util.h" #include "string-util.h"
@ -171,12 +169,12 @@ static void test_find_executable_full(void) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
assert_se(find_executable_full("sh", true, &p, NULL) == 0); assert_se(find_executable_full("sh", true, &p) == 0);
puts(p); puts(p);
assert_se(streq(basename(p), "sh")); assert_se(streq(basename(p), "sh"));
free(p); free(p);
assert_se(find_executable_full("sh", false, &p, NULL) == 0); assert_se(find_executable_full("sh", false, &p) == 0);
puts(p); puts(p);
assert_se(streq(basename(p), "sh")); assert_se(streq(basename(p), "sh"));
free(p); free(p);
@ -188,12 +186,12 @@ static void test_find_executable_full(void) {
assert_se(unsetenv("PATH") == 0); assert_se(unsetenv("PATH") == 0);
assert_se(find_executable_full("sh", true, &p, NULL) == 0); assert_se(find_executable_full("sh", true, &p) == 0);
puts(p); puts(p);
assert_se(streq(basename(p), "sh")); assert_se(streq(basename(p), "sh"));
free(p); free(p);
assert_se(find_executable_full("sh", false, &p, NULL) == 0); assert_se(find_executable_full("sh", false, &p) == 0);
puts(p); puts(p);
assert_se(streq(basename(p), "sh")); assert_se(streq(basename(p), "sh"));
free(p); free(p);
@ -238,43 +236,6 @@ static void test_find_executable(const char *self) {
assert_se(find_executable("/proc/filesystems", &p) == -EACCES); assert_se(find_executable("/proc/filesystems", &p) == -EACCES);
} }
static void test_find_executable_exec_one(const char *path) {
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -1;
pid_t pid;
int r;
r = find_executable_full(path, false, &t, &fd);
log_info_errno(r, "%s: %s → %s: %d/%m", __func__, path, t ?: "-", fd);
assert_se(fd > STDERR_FILENO);
assert_se(path_is_absolute(t));
if (path_is_absolute(path))
assert_se(streq(t, path));
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL));
log_error_errno(r, "[f]execve: %m");
_exit(EXIT_FAILURE);
}
assert_se(wait_for_terminate_and_check(t, pid, WAIT_LOG) == 0);
}
static void test_find_executable_exec(void) {
log_info("/* %s */", __func__);
test_find_executable_exec_one("touch");
test_find_executable_exec_one("/bin/touch");
_cleanup_free_ char *script = NULL;
assert_se(get_testdata_dir("test-path-util/script.sh", &script) >= 0);
test_find_executable_exec_one(script);
}
static void test_prefixes(void) { static void test_prefixes(void) {
static const char* const values[] = { static const char* const values[] = {
"/a/b/c/d", "/a/b/c/d",
@ -756,7 +717,6 @@ int main(int argc, char **argv) {
test_path_equal_root(); test_path_equal_root();
test_find_executable_full(); test_find_executable_full();
test_find_executable(argv[0]); test_find_executable(argv[0]);
test_find_executable_exec();
test_prefixes(); test_prefixes();
test_path_join(); test_path_join();
test_fsck_exists(); test_fsck_exists();

View File

@ -11,8 +11,6 @@ if install_tests
install_dir : testdata_dir) install_dir : testdata_dir)
install_subdir('test-path', install_subdir('test-path',
install_dir : testdata_dir) install_dir : testdata_dir)
install_subdir('test-path-util',
install_dir : testdata_dir)
install_subdir('test-umount', install_subdir('test-umount',
install_dir : testdata_dir) install_dir : testdata_dir)
install_subdir('test-network-generator-conversion', install_subdir('test-network-generator-conversion',

View File

@ -2,7 +2,7 @@
Description=Test for SystemCallFilter Description=Test for SystemCallFilter
[Service] [Service]
ExecStart=/bin/sh -c '/bin/echo "This should not be seen"' ExecStart=/bin/sh -c 'echo "This should not be seen"'
Type=oneshot Type=oneshot
LimitCORE=0 LimitCORE=0
SystemCallFilter=ioperm SystemCallFilter=ioperm

View File

@ -2,7 +2,7 @@
Description=Test for SystemCallFilter Description=Test for SystemCallFilter
[Service] [Service]
ExecStart=/bin/sh -c '/bin/echo "This should not be seen"' ExecStart=/bin/sh -c 'echo "This should not be seen"'
Type=oneshot Type=oneshot
LimitCORE=0 LimitCORE=0
SystemCallFilter=~write open execve fexecve execveat exit_group close mmap munmap fstat DONOTEXIST SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST

View File

@ -1,6 +0,0 @@
#!/bin/sh
echo "$0 $@"
test "$(basename $0)" = "script.sh" || exit 1
test "$1" = "--version" || exit 2
echo "Life is good"