mirror of
https://github.com/systemd/systemd.git
synced 2025-08-25 13:49:55 +03:00
core: ensure execute/spawn functions can work without Unit object
When switching to serialization later, the Unit object will not be serialized, move parameters around instead
This commit is contained in:
@ -154,20 +154,14 @@ int lsm_bpf_setup(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer_map_fd, bool allow_list) {
|
||||
_cleanup_close_ int outer_map_fd_cleanup = -EBADF;
|
||||
int lsm_bpf_restrict_filesystems(const Set *filesystems, uint64_t cgroup_id, int outer_map_fd, bool allow_list) {
|
||||
uint32_t dummy_value = 1, zero = 0;
|
||||
const char *fs;
|
||||
const statfs_f_type_t *magic;
|
||||
int r;
|
||||
|
||||
assert(filesystems);
|
||||
assert(u);
|
||||
assert(outer_map_fd >= 0 || u->manager);
|
||||
|
||||
if (u->manager && !u->manager->restrict_fs) /* Might be called in sd-executor with no manager object */
|
||||
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL),
|
||||
"bpf-lsm: BPF LSM object is not installed, has setup failed?");
|
||||
assert(outer_map_fd >= 0);
|
||||
|
||||
int inner_map_fd = compat_bpf_map_create(
|
||||
BPF_MAP_TYPE_HASH,
|
||||
@ -177,41 +171,35 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer
|
||||
128U, /* Should be enough for all filesystem types */
|
||||
NULL);
|
||||
if (inner_map_fd < 0)
|
||||
return log_unit_error_errno(u, errno, "bpf-lsm: Failed to create inner BPF map: %m");
|
||||
return log_error_errno(errno, "bpf-lsm: Failed to create inner BPF map: %m");
|
||||
|
||||
if (outer_map_fd < 0) {
|
||||
outer_map_fd_cleanup = outer_map_fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash);
|
||||
if (outer_map_fd < 0)
|
||||
return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m");
|
||||
}
|
||||
|
||||
if (sym_bpf_map_update_elem(outer_map_fd, &u->cgroup_id, &inner_map_fd, BPF_ANY) != 0)
|
||||
return log_unit_error_errno(u, errno, "bpf-lsm: Error populating BPF map: %m");
|
||||
if (sym_bpf_map_update_elem(outer_map_fd, &cgroup_id, &inner_map_fd, BPF_ANY) != 0)
|
||||
return log_error_errno(errno, "bpf-lsm: Error populating BPF map: %m");
|
||||
|
||||
uint32_t allow = allow_list;
|
||||
|
||||
/* Use key 0 to store whether this is an allow list or a deny list */
|
||||
if (sym_bpf_map_update_elem(inner_map_fd, &zero, &allow, BPF_ANY) != 0)
|
||||
return log_unit_error_errno(u, errno, "bpf-lsm: Error initializing map: %m");
|
||||
return log_error_errno(errno, "bpf-lsm: Error initializing map: %m");
|
||||
|
||||
SET_FOREACH(fs, filesystems) {
|
||||
r = fs_type_from_string(fs, &magic);
|
||||
if (r < 0) {
|
||||
log_unit_warning(u, "bpf-lsm: Invalid filesystem name '%s', ignoring.", fs);
|
||||
log_warning("bpf-lsm: Invalid filesystem name '%s', ignoring.", fs);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_unit_debug(u, "bpf-lsm: Restricting filesystem access to '%s'", fs);
|
||||
log_debug("bpf-lsm: Restricting filesystem access to '%s'", fs);
|
||||
|
||||
for (int i = 0; i < FILESYSTEM_MAGIC_MAX; i++) {
|
||||
if (magic[i] == 0)
|
||||
break;
|
||||
|
||||
if (sym_bpf_map_update_elem(inner_map_fd, &magic[i], &dummy_value, BPF_ANY) != 0) {
|
||||
r = log_unit_error_errno(u, errno, "bpf-lsm: Failed to update BPF map: %m");
|
||||
r = log_error_errno(errno, "bpf-lsm: Failed to update BPF map: %m");
|
||||
|
||||
if (sym_bpf_map_delete_elem(outer_map_fd, &u->cgroup_id) != 0)
|
||||
log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from BPF map: %m");
|
||||
if (sym_bpf_map_delete_elem(outer_map_fd, &cgroup_id) != 0)
|
||||
log_debug_errno(errno, "bpf-lsm: Failed to delete cgroup entry from BPF map: %m");
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -267,8 +255,8 @@ int lsm_bpf_setup(Manager *m) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to set up LSM BPF: %m");
|
||||
}
|
||||
|
||||
int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer_map_fd, const bool allow_list) {
|
||||
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to restrict filesystems using LSM BPF: %m");
|
||||
int lsm_bpf_restrict_filesystems(const Set *filesystems, uint64_t cgroup_id, int outer_map_fd, const bool allow_list) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to restrict filesystems using LSM BPF: %m");
|
||||
}
|
||||
|
||||
int lsm_bpf_cleanup(const Unit *u) {
|
||||
|
@ -16,7 +16,7 @@ typedef struct restrict_fs_bpf restrict_fs_bpf;
|
||||
|
||||
bool lsm_bpf_supported(bool initialize);
|
||||
int lsm_bpf_setup(Manager *m);
|
||||
int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, int outer_map_fd, bool allow_list);
|
||||
int lsm_bpf_restrict_filesystems(const Set *filesystems, uint64_t cgroup_id, int outer_map_fd, bool allow_list);
|
||||
int lsm_bpf_cleanup(const Unit *u);
|
||||
int lsm_bpf_map_restrict_fs_fd(Unit *u);
|
||||
void lsm_bpf_destroy(struct restrict_fs_bpf *prog);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -421,6 +421,7 @@ struct ExecParameters {
|
||||
|
||||
CGroupMask cgroup_supported;
|
||||
const char *cgroup_path;
|
||||
uint64_t cgroup_id;
|
||||
|
||||
char **prefix;
|
||||
const char *received_credentials_directory;
|
||||
@ -449,8 +450,24 @@ struct ExecParameters {
|
||||
char **files_env;
|
||||
int user_lookup_fd;
|
||||
int bpf_outer_map_fd;
|
||||
|
||||
/* Used for logging in the executor functions */
|
||||
char *unit_id;
|
||||
sd_id128_t invocation_id;
|
||||
char invocation_id_string[SD_ID128_STRING_MAX];
|
||||
};
|
||||
|
||||
#define EXEC_PARAMETERS_INIT(_flags) \
|
||||
(ExecParameters) { \
|
||||
.flags = (_flags), \
|
||||
.stdin_fd = -EBADF, \
|
||||
.stdout_fd = -EBADF, \
|
||||
.stderr_fd = -EBADF, \
|
||||
.exec_fd = -EBADF, \
|
||||
.bpf_outer_map_fd = -EBADF, \
|
||||
.user_lookup_fd = -EBADF, \
|
||||
};
|
||||
|
||||
#include "unit.h"
|
||||
#include "dynamic-user.h"
|
||||
|
||||
@ -551,3 +568,103 @@ ExecDirectoryType exec_resource_type_from_string(const char *s) _pure_;
|
||||
|
||||
bool exec_needs_mount_namespace(const ExecContext *context, const ExecParameters *params, const ExecRuntime *runtime);
|
||||
bool exec_needs_network_namespace(const ExecContext *context);
|
||||
|
||||
/* These logging macros do the same logging as those in unit.h, but using ExecContext and ExecParameters
|
||||
* instead of the unit object, so that it can be used in the sd-executor context (where the unit object is
|
||||
* not available). */
|
||||
|
||||
#define LOG_EXEC_ID_FIELD(ep) \
|
||||
((ep)->runtime_scope == RUNTIME_SCOPE_USER ? "USER_UNIT=" : "UNIT=")
|
||||
#define LOG_EXEC_ID_FIELD_FORMAT(ep) \
|
||||
((ep)->runtime_scope == RUNTIME_SCOPE_USER ? "USER_UNIT=%s" : "UNIT=%s")
|
||||
#define LOG_EXEC_INVOCATION_ID_FIELD(ep) \
|
||||
((ep)->runtime_scope == RUNTIME_SCOPE_USER ? "USER_INVOCATION_ID=" : "INVOCATION_ID=")
|
||||
#define LOG_EXEC_INVOCATION_ID_FIELD_FORMAT(ep) \
|
||||
((ep)->runtime_scope == RUNTIME_SCOPE_USER ? "USER_INVOCATION_ID=%s" : "INVOCATION_ID=%s")
|
||||
|
||||
#define log_exec_full_errno_zerook(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = !(log_get_max_level() < LOG_PRI(_l) || \
|
||||
!(_c->log_level_max < 0 || \
|
||||
_c->log_level_max >= LOG_PRI(_l))); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
!_do_log ? -ERRNO_VALUE(error) : \
|
||||
log_object_internal(_l, error, PROJECT_FILE, \
|
||||
__LINE__, __func__, \
|
||||
LOG_EXEC_ID_FIELD(_p), \
|
||||
_p->unit_id, \
|
||||
LOG_EXEC_INVOCATION_ID_FIELD(_p), \
|
||||
_p->invocation_id_string, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_exec_full_errno(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
int _error = (error); \
|
||||
ASSERT_NON_ZERO(_error); \
|
||||
log_exec_full_errno_zerook(ec, ep, level, _error, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_exec_full(ec, ep, level, ...) (void) log_exec_full_errno_zerook(ec, ep, level, 0, __VA_ARGS__)
|
||||
|
||||
#define log_exec_debug(ec, ep, ...) log_exec_full(ec, ep, LOG_DEBUG, __VA_ARGS__)
|
||||
#define log_exec_info(ec, ep, ...) log_exec_full(ec, ep, LOG_INFO, __VA_ARGS__)
|
||||
#define log_exec_notice(ec, ep, ...) log_exec_full(ec, ep, LOG_NOTICE, __VA_ARGS__)
|
||||
#define log_exec_warning(ec, ep, ...) log_exec_full(ec, ep, LOG_WARNING, __VA_ARGS__)
|
||||
#define log_exec_error(ec, ep, ...) log_exec_full(ec, ep, LOG_ERR, __VA_ARGS__)
|
||||
|
||||
#define log_exec_debug_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_DEBUG, error, __VA_ARGS__)
|
||||
#define log_exec_info_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_INFO, error, __VA_ARGS__)
|
||||
#define log_exec_notice_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_NOTICE, error, __VA_ARGS__)
|
||||
#define log_exec_warning_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_WARNING, error, __VA_ARGS__)
|
||||
#define log_exec_error_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_ERR, error, __VA_ARGS__)
|
||||
|
||||
#define log_exec_struct_errno(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = !(_c->log_level_max < 0 || \
|
||||
_c->log_level_max >= LOG_PRI(_l)); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
_do_log ? \
|
||||
log_struct_errno(_l, error, __VA_ARGS__, LOG_EXEC_ID_FIELD_FORMAT(_p), _p->unit_id) : \
|
||||
-ERRNO_VALUE(error); \
|
||||
})
|
||||
|
||||
#define log_exec_struct(ec, ep, level, ...) log_exec_struct_errno(ec, ep, level, 0, __VA_ARGS__)
|
||||
|
||||
#define log_exec_struct_iovec_errno(ec, ep, level, error, iovec, n_iovec) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = !(_c->log_level_max < 0 || \
|
||||
_c->log_level_max >= LOG_PRI(_l)); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
_do_log ? \
|
||||
log_struct_iovec_errno(_l, error, iovec, n_iovec) : \
|
||||
-ERRNO_VALUE(error); \
|
||||
})
|
||||
|
||||
#define log_exec_struct_iovec(ec, ep, level, iovec, n_iovec) log_exec_struct_iovec_errno(ec, ep, level, 0, iovec, n_iovec)
|
||||
|
||||
/* Like LOG_MESSAGE(), but with the unit name prefixed. */
|
||||
#define LOG_EXEC_MESSAGE(ep, fmt, ...) LOG_MESSAGE("%s: " fmt, (ep)->unit_id, ##__VA_ARGS__)
|
||||
#define LOG_EXEC_ID(ep) LOG_EXEC_ID_FIELD_FORMAT(ep), (ep)->unit_id
|
||||
#define LOG_EXEC_INVOCATION_ID(ep) LOG_EXEC_INVOCATION_ID_FIELD_FORMAT(ep), (ep)->invocation_id_string
|
||||
|
||||
#define _LOG_CONTEXT_PUSH_EXEC(ec, ep, p, c) \
|
||||
const ExecContext *c = (ec); \
|
||||
const ExecParameters *p = (ep); \
|
||||
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_ID_FIELD(p), p->unit_id); \
|
||||
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_INVOCATION_ID_FIELD(p), p->invocation_id_string); \
|
||||
LOG_CONTEXT_PUSH_IOV(c->log_extra_fields, c->n_log_extra_fields)
|
||||
|
||||
#define LOG_CONTEXT_PUSH_EXEC(ec, ep) \
|
||||
_LOG_CONTEXT_PUSH_EXEC(ec, ep, UNIQ_T(p, UNIQ), UNIQ_T(c, UNIQ))
|
||||
|
@ -144,6 +144,15 @@ static usec_t manager_watch_jobs_next_time(Manager *m) {
|
||||
return usec_add(now(CLOCK_MONOTONIC), timeout);
|
||||
}
|
||||
|
||||
static bool manager_is_confirm_spawn_disabled(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
if (!m->confirm_spawn)
|
||||
return true;
|
||||
|
||||
return access("/run/systemd/confirm_spawn_disabled", F_OK) >= 0;
|
||||
}
|
||||
|
||||
static void manager_watch_jobs_in_progress(Manager *m) {
|
||||
usec_t next;
|
||||
int r;
|
||||
@ -4430,13 +4439,6 @@ void manager_disable_confirm_spawn(void) {
|
||||
(void) touch("/run/systemd/confirm_spawn_disabled");
|
||||
}
|
||||
|
||||
bool manager_is_confirm_spawn_disabled(Manager *m) {
|
||||
if (!m->confirm_spawn)
|
||||
return true;
|
||||
|
||||
return access("/run/systemd/confirm_spawn_disabled", F_OK) >= 0;
|
||||
}
|
||||
|
||||
static bool manager_should_show_status(Manager *m, StatusType type) {
|
||||
assert(m);
|
||||
|
||||
|
@ -616,7 +616,6 @@ const char *manager_state_to_string(ManagerState m) _const_;
|
||||
ManagerState manager_state_from_string(const char *s) _pure_;
|
||||
|
||||
const char *manager_get_confirm_spawn(Manager *m);
|
||||
bool manager_is_confirm_spawn_disabled(Manager *m);
|
||||
void manager_disable_confirm_spawn(void);
|
||||
|
||||
const char *manager_timestamp_to_string(ManagerTimestamp m) _const_;
|
||||
|
@ -889,15 +889,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
|
||||
static int mount_spawn(Mount *m, ExecCommand *c, PidRef *ret_pid) {
|
||||
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = {
|
||||
.flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
|
||||
.stdin_fd = -EBADF,
|
||||
.stdout_fd = -EBADF,
|
||||
.stderr_fd = -EBADF,
|
||||
.exec_fd = -EBADF,
|
||||
.bpf_outer_map_fd = -EBADF,
|
||||
.user_lookup_fd = -EBADF,
|
||||
};
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
|
||||
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
@ -1602,15 +1602,7 @@ static int service_spawn_internal(
|
||||
ExecFlags flags,
|
||||
PidRef *ret_pid) {
|
||||
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = {
|
||||
.flags = flags,
|
||||
.stdin_fd = -EBADF,
|
||||
.stdout_fd = -EBADF,
|
||||
.stderr_fd = -EBADF,
|
||||
.exec_fd = -EBADF,
|
||||
.bpf_outer_map_fd = -EBADF,
|
||||
.user_lookup_fd = -EBADF,
|
||||
};
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(flags);
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *exec_fd_source = NULL;
|
||||
_cleanup_strv_free_ char **final_env = NULL, **our_env = NULL;
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
|
@ -1913,15 +1913,8 @@ static int socket_coldplug(Unit *u) {
|
||||
|
||||
static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
|
||||
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = {
|
||||
.flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
|
||||
.stdin_fd = -EBADF,
|
||||
.stdout_fd = -EBADF,
|
||||
.stderr_fd = -EBADF,
|
||||
.exec_fd = -EBADF,
|
||||
.bpf_outer_map_fd = -EBADF,
|
||||
.user_lookup_fd = -EBADF,
|
||||
};
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
|
||||
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
@ -632,15 +632,8 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
|
||||
static int swap_spawn(Swap *s, ExecCommand *c, PidRef *ret_pid) {
|
||||
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = {
|
||||
.flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
|
||||
.stdin_fd = -EBADF,
|
||||
.stdout_fd = -EBADF,
|
||||
.stderr_fd = -EBADF,
|
||||
.exec_fd = -EBADF,
|
||||
.bpf_outer_map_fd = -EBADF,
|
||||
.user_lookup_fd = -EBADF,
|
||||
};
|
||||
_cleanup_(exec_params_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
|
||||
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
@ -1854,18 +1854,6 @@ int unit_test_start_limit(Unit *u) {
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
bool unit_shall_confirm_spawn(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
if (manager_is_confirm_spawn_disabled(u->manager))
|
||||
return false;
|
||||
|
||||
/* For some reasons units remaining in the same process group
|
||||
* as PID 1 fail to acquire the console even if it's not used
|
||||
* by any process. So skip the confirmation question for them. */
|
||||
return !unit_get_exec_context(u)->same_pgrp;
|
||||
}
|
||||
|
||||
static bool unit_verify_deps(Unit *u) {
|
||||
Unit *other;
|
||||
|
||||
@ -5405,9 +5393,14 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) {
|
||||
p->bpf_outer_map_fd = fd;
|
||||
}
|
||||
|
||||
p->user_lookup_fd = fcntl(u->manager->user_lookup_fds[1], F_DUPFD_CLOEXEC, 3);
|
||||
if (p->user_lookup_fd < 0)
|
||||
return -errno;
|
||||
p->user_lookup_fd = u->manager->user_lookup_fds[1];
|
||||
|
||||
p->cgroup_id = u->cgroup_id;
|
||||
p->invocation_id = u->invocation_id;
|
||||
sd_id128_to_string(p->invocation_id, p->invocation_id_string);
|
||||
p->unit_id = strdup(u->id);
|
||||
if (!p->unit_id)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1024,8 +1024,6 @@ void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid);
|
||||
int unit_set_invocation_id(Unit *u, sd_id128_t id);
|
||||
int unit_acquire_invocation_id(Unit *u);
|
||||
|
||||
bool unit_shall_confirm_spawn(Unit *u);
|
||||
|
||||
int unit_set_exec_params(Unit *s, ExecParameters *p);
|
||||
|
||||
int unit_fork_helper_process(Unit *u, const char *name, PidRef *ret);
|
||||
|
Reference in New Issue
Block a user