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

Compare commits

..

No commits in common. "96d03f8e41dc7b59cc48811da65e2dc88b60e8f5" and "b5d63191cabc4b60744d743c28bc2f9a2419e711" have entirely different histories.

28 changed files with 322 additions and 412 deletions

View File

@ -39,7 +39,7 @@ jobs:
trigger: pull_request
fmf_url: https://src.fedoraproject.org/rpms/systemd
# This is automatically updated by tools/fetch-distro.py --update fedora
fmf_ref: ea1d871ecd6c2fe063523840c1e4cf9bcf200e32
fmf_ref: 7de88c66bdc26920db570e67ef74e579f8461d9c
targets:
- fedora-rawhide-x86_64
# testing-farm in the Fedora repository is explicitly configured to use testing-farm bare metal runners as

View File

@ -139,8 +139,8 @@
<term><option>-g</option></term>
<listitem><para>Switches to the specified user/group. If not specified defaults to
<literal>root</literal>, unless <option>--area=</option> or <option>--empower</option> are used (see
below), in which case this defaults to the invoking user.</para>
<literal>root</literal>, unless <option>--area=</option> is used (see below), in which case this
defaults to the invoking user.</para>
<xi:include href="version-info.xml" xpointer="v256"/>
</listitem>
@ -290,17 +290,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>--empower</option></term>
<listitem><para>If specified, run0 will elevate the privileges of the selected user (using
<option>--user=</option>) or the current user if no user is explicitly selected. Currently this means
we give the user all available capabilities, but other privileges may be granted in the future as
well when using this option.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--machine=</option></term>

View File

@ -463,7 +463,7 @@
<para>If used with <command>predict</command> and <command>make-policy</command> this will override
which PCRs to include in the prediction and policy. If unspecified this defaults to PCRs 0-5, 7,
11, 13-15. Note that these commands will not include any PCRs in the prediction/policy (even if specified
11-15. Note that these commands will not include any PCRs in the prediction/policy (even if specified
explicitly) if there are measurements in the event log that do not match the current PCR value, or
there are unrecognized measurements in the event log, or components define measurements not seen in
the event log.</para>

View File

@ -4,5 +4,5 @@
Environment=
GIT_URL=https://src.fedoraproject.org/rpms/systemd.git
GIT_BRANCH=rawhide
GIT_COMMIT=ea1d871ecd6c2fe063523840c1e4cf9bcf200e32
GIT_COMMIT=7de88c66bdc26920db570e67ef74e579f8461d9c
PKG_SUBDIR=fedora

View File

@ -82,7 +82,6 @@ CXX_LD="$( ((LLVM)) && echo lld)" \
--noprep \
--build-in-place \
--with upstream \
--without lto \
$( ((WITH_TESTS)) || echo "--nocheck") \
$( ((WITH_DOCS)) || echo "--without=docs") \
--define "_topdir /var/tmp" \

View File

@ -37,7 +37,7 @@ _run0() {
--machine --unit --property --description --slice -u --user -g --group --nice -D --chdir
--setenv --background
)
local OPTS="${opts_with_values[*]} -h --help -V --version --no-ask-password --slice-inherit --empower"
local OPTS="${opts_with_values[*]} -h --help -V --version --no-ask-password --slice-inherit"
local i
for (( i=1; i <= COMP_CWORD; i++ )); do

View File

@ -78,7 +78,6 @@ _systemd_analyze() {
[SECURITY]='security'
[CONDITION]='condition'
[INSPECT_ELF]='inspect-elf'
[DLOPEN_METADATA]='dlopen-metadata'
[PLOT]='plot'
[ARCHITECTURES]='architectures'
[FDSTORE]='fdstore'
@ -213,14 +212,6 @@ _systemd_analyze() {
compopt -o filenames
fi
elif __contains_word "$verb" ${VERBS[DLOPEN_METADATA]}; then
if [[ $cur = -* ]]; then
comps='--help --version --json=off --json=pretty --json=short'
else
comps=$( compgen -A file -- "$cur" )
compopt -o filenames
fi
elif __contains_word "$verb" ${VERBS[PLOT]}; then
if [[ $cur = -* ]]; then
comps='--help --version --system --user --global --no-pager --json=off --json=pretty --json=short --table --no-legend --scale-svg --detailed'

View File

@ -52,7 +52,6 @@ local -a args=(
'--machine=[Execute the operation on a local container]:machine:_sd_machines'
{-h,--help}'[Show the help text and exit]'
'--version[Print a short version string and exit]'
'--empower[Give privileges to selected or current user]'
)
_arguments -S $args '*:: :{_normal -p $service}'

View File

@ -79,7 +79,6 @@
'timespan:Parse a systemd syntax timespan'
'security:Analyze security settings of a service'
'inspect-elf:Parse and print ELF package metadata'
'dlopen-metadata:Parse and print ELF dlopen metadata'
'has-tpm2:Report whether TPM2 support is available'
'transient-settings:List transient settings for unit types'
# log-level, log-target, service-watchdogs have been deprecated

View File

@ -1277,6 +1277,7 @@ static int setup_pam(
uid_t uid,
gid_t gid,
char ***env, /* updated on success */
const int fds[], size_t n_fds,
bool needs_sandboxing,
int exec_fd) {
@ -1306,6 +1307,7 @@ static int setup_pam(
assert(user);
assert(uid_is_valid(uid));
assert(gid_is_valid(gid));
assert(fds || n_fds == 0);
assert(env);
/* We set up PAM in the parent process, then fork. The child will then stay around until killed via
@ -1391,7 +1393,7 @@ static int setup_pam(
/* Make sure we don't keep open the passed fds in this child. We assume that otherwise only
* those fds are open here that have been opened by PAM. */
(void) close_many(params->fds, params->n_socket_fds + params->n_stashed_fds);
(void) close_many(fds, n_fds);
/* Also close the 'exec_fd' in the child, since the service manager waits for the EOF induced
* by the execve() to wait for completion, and if we'd keep the fd open here in the child
@ -1990,6 +1992,7 @@ static int build_environment(
const ExecContext *c,
const ExecParameters *p,
const CGroupContext *cgroup_context,
size_t n_fds,
const char *home,
const char *username,
const char *shell,
@ -2014,7 +2017,7 @@ static int build_environment(
if (!our_env)
return -ENOMEM;
if (p->n_socket_fds + p->n_stashed_fds > 0) {
if (n_fds > 0) {
_cleanup_free_ char *joined = NULL;
if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid_cached()) < 0)
@ -2028,7 +2031,7 @@ static int build_environment(
our_env[n_env++] = x;
}
if (asprintf(&x, "LISTEN_FDS=%zu", p->n_socket_fds + p->n_stashed_fds) < 0)
if (asprintf(&x, "LISTEN_FDS=%zu", n_fds) < 0)
return -ENOMEM;
our_env[n_env++] = x;
@ -4324,11 +4327,12 @@ static int exec_context_cpu_affinity_from_numa(const ExecContext *c, CPUSet *ret
return 0;
}
static int add_shifted_fd(int **fds, size_t *n_fds, int *fd) {
static int add_shifted_fd(int *fds, size_t fds_size, size_t *n_fds, int *fd) {
int r;
assert(fds);
assert(n_fds);
assert(*n_fds < fds_size);
assert(fd);
if (*fd < 0)
@ -4345,10 +4349,7 @@ static int add_shifted_fd(int **fds, size_t *n_fds, int *fd) {
close_and_replace(*fd, r);
}
if (!GREEDY_REALLOC(*fds, *n_fds + 1))
return -ENOMEM;
(*fds)[(*n_fds)++] = *fd;
fds[(*n_fds)++] = *fd;
return 1;
}
@ -4425,8 +4426,9 @@ static int get_open_file_fd(const OpenFile *of) {
return TAKE_FD(fd);
}
static int collect_open_file_fds(ExecParameters *p) {
static int collect_open_file_fds(ExecParameters *p, size_t *n_fds) {
assert(p);
assert(n_fds);
LIST_FOREACH(open_files, of, p->open_files) {
_cleanup_close_ int fd = -EBADF;
@ -4444,13 +4446,13 @@ static int collect_open_file_fds(ExecParameters *p) {
return log_error_errno(fd, "Failed to get OpenFile= file descriptor for '%s': %m", of->path);
}
if (!GREEDY_REALLOC(p->fds, p->n_stashed_fds + 1))
if (!GREEDY_REALLOC(p->fds, *n_fds + 1))
return log_oom();
if (strv_extend(&p->fd_names, of->fdname) < 0)
return log_oom();
p->fds[p->n_stashed_fds++] = TAKE_FD(fd);
p->fds[(*n_fds)++] = TAKE_FD(fd);
}
return 0;
@ -4743,8 +4745,9 @@ static int exec_context_named_iofds(
const ExecParameters *p,
int named_iofds[static 3]) {
const char *stdio_fdname[3];
size_t targets;
const char* stdio_fdname[3];
size_t n_fds;
assert(c);
assert(p);
@ -4757,11 +4760,12 @@ static int exec_context_named_iofds(
for (size_t i = 0; i < 3; i++)
stdio_fdname[i] = exec_context_fdname(c, i);
/* Note that socket fds are always placed at the beginning of the fds array, no need for extra
* manipulation. */
for (size_t i = 0; i < p->n_socket_fds && targets > 0; i++)
n_fds = p->n_storage_fds + p->n_socket_fds + p->n_extra_fds;
for (size_t i = 0; i < n_fds && targets > 0; i++)
if (named_iofds[STDIN_FILENO] < 0 &&
c->std_input == EXEC_INPUT_NAMED_FD &&
stdio_fdname[STDIN_FILENO] &&
streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) {
named_iofds[STDIN_FILENO] = p->fds[i];
@ -4769,6 +4773,7 @@ static int exec_context_named_iofds(
} else if (named_iofds[STDOUT_FILENO] < 0 &&
c->std_output == EXEC_OUTPUT_NAMED_FD &&
stdio_fdname[STDOUT_FILENO] &&
streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) {
named_iofds[STDOUT_FILENO] = p->fds[i];
@ -4776,6 +4781,7 @@ static int exec_context_named_iofds(
} else if (named_iofds[STDERR_FILENO] < 0 &&
c->std_error == EXEC_OUTPUT_NAMED_FD &&
stdio_fdname[STDERR_FILENO] &&
streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) {
named_iofds[STDERR_FILENO] = p->fds[i];
@ -5026,11 +5032,14 @@ int exec_invoke(
gid_t saved_gid = getgid();
uid_t uid = UID_INVALID;
gid_t gid = GID_INVALID;
size_t n_fds, /* fds to pass to the child */
n_keep_fds; /* total number of fds not to close */
int secure_bits;
_cleanup_free_ gid_t *gids = NULL, *gids_after_pam = NULL;
int ngids = 0, ngids_after_pam = 0;
int named_iofds[3] = EBADF_TRIPLET;
_cleanup_close_ int socket_fd = -EBADF, bpffs_socket_fd = -EBADF, bpffs_errno_pipe = -EBADF;
int socket_fd = -EBADF, named_iofds[3] = EBADF_TRIPLET;
_cleanup_close_ int bpffs_socket_fd = -EBADF, bpffs_errno_pipe = -EBADF;
size_t n_storage_fds, n_socket_fds, n_extra_fds;
_cleanup_(pidref_done_sigkill_wait) PidRef bpffs_pidref = PIDREF_NULL;
assert(command);
@ -5048,30 +5057,30 @@ int exec_invoke(
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid command line arguments.");
}
rename_process_from_path(command->path);
if (context->std_input == EXEC_INPUT_SOCKET ||
context->std_output == EXEC_OUTPUT_SOCKET ||
context->std_error == EXEC_OUTPUT_SOCKET) {
if (params->n_socket_fds != 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected exactly one socket, got %zu.",
params->n_socket_fds);
if (params->n_socket_fds > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Got more than one socket.");
socket_fd = TAKE_FD(params->fds[0]);
free(params->fd_names[0]);
params->n_socket_fds = 0;
if (params->n_socket_fds == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Got no socket.");
memmove(params->fds, params->fds + 1, params->n_stashed_fds * sizeof(int));
memmove(params->fd_names, params->fd_names + 1, params->n_stashed_fds * sizeof(char*));
params->fd_names[params->n_stashed_fds] = NULL;
socket_fd = params->fds[0];
n_storage_fds = n_socket_fds = n_extra_fds = 0;
} else {
n_socket_fds = params->n_socket_fds;
n_storage_fds = params->n_storage_fds;
n_extra_fds = params->n_extra_fds;
}
n_fds = n_socket_fds + n_storage_fds + n_extra_fds;
r = exec_context_named_iofds(context, params, named_iofds);
if (r < 0) {
*exit_status = EXIT_FDS;
if (r < 0)
return log_error_errno(r, "Failed to load a named file descriptor: %m");
}
rename_process_from_path(command->path);
/* We reset exactly these signals, since they are the only ones we set to SIG_IGN in the main
* daemon. All others we leave untouched because we set them to SIG_DFL or a valid handler initially,
@ -5103,33 +5112,30 @@ int exec_invoke(
/* In case anything used libc syslog(), close this here, too */
closelog();
r = collect_open_file_fds(params);
r = collect_open_file_fds(params, &n_fds);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_error_errno(r, "Failed to get OpenFile= file descriptors: %m");
}
size_t n_keep_fds = params->n_socket_fds + params->n_stashed_fds;
_cleanup_free_ int *keep_fds = newdup(int, params->fds, n_keep_fds);
if (!keep_fds) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
int keep_fds[n_fds + 4];
memcpy_safe(keep_fds, params->fds, n_fds * sizeof(int));
n_keep_fds = n_fds;
r = add_shifted_fd(&keep_fds, &n_keep_fds, &params->exec_fd);
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, &params->exec_fd);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_error_errno(r, "Failed to collect shifted fd: %m");
}
r = add_shifted_fd(&keep_fds, &n_keep_fds, &params->handoff_timestamp_fd);
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, &params->handoff_timestamp_fd);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_error_errno(r, "Failed to collect shifted fd: %m");
}
#if HAVE_LIBBPF
r = add_shifted_fd(&keep_fds, &n_keep_fds, &params->bpf_restrict_fs_map_fd);
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, &params->bpf_restrict_fs_map_fd);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_error_errno(r, "Failed to collect shifted fd: %m");
@ -5612,6 +5618,7 @@ int exec_invoke(
context,
params,
cgroup_context,
n_fds,
pwent_home,
username,
shell,
@ -5725,7 +5732,7 @@ int exec_invoke(
/* All fds passed in the fds array will be closed in the pam child process. */
r = setup_pam(context, cgroup_context, params, username, uid, gid, &accum_env,
needs_sandboxing, params->exec_fd);
params->fds, n_fds, needs_sandboxing, params->exec_fd);
if (r < 0) {
*exit_status = EXIT_PAM;
return log_error_errno(r, "Failed to set up PAM session: %m");
@ -5918,7 +5925,7 @@ int exec_invoke(
return r != -ENOMEM && FLAGS_SET(command->flags, EXEC_COMMAND_IGNORE_FAILURE) ? 1 : r;
}
r = add_shifted_fd(&keep_fds, &n_keep_fds, &executable_fd);
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, &executable_fd);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_error_errno(r, "Failed to collect shifted fd: %m");
@ -5959,10 +5966,9 @@ int exec_invoke(
r = close_all_fds(keep_fds, n_keep_fds);
if (r >= 0)
r = pack_fds(params->fds, params->n_socket_fds + params->n_stashed_fds);
r = pack_fds(params->fds, n_fds);
if (r >= 0)
r = flag_fds(params->fds, params->n_socket_fds, params->n_socket_fds + params->n_stashed_fds,
context->non_blocking);
r = flag_fds(params->fds, n_socket_fds, n_fds, context->non_blocking);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_error_errno(r, "Failed to adjust passed file descriptors: %m");

View File

@ -1090,21 +1090,27 @@ static int exec_parameters_serialize(const ExecParameters *p, const ExecContext
return r;
}
if (p->n_stashed_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-stashed-fds", "%zu", p->n_stashed_fds);
if (p->n_storage_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-storage-fds", "%zu", p->n_storage_fds);
if (r < 0)
return r;
}
r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_stashed_fds);
if (r < 0)
return r;
if (p->n_extra_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-extra-fds", "%zu", p->n_extra_fds);
if (r < 0)
return r;
}
r = serialize_strv(f, "exec-parameters-fd-names", p->fd_names);
r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds);
if (r < 0)
return r;
}
r = serialize_strv(f, "exec-parameters-fd-names", p->fd_names);
if (r < 0)
return r;
if (p->flags != 0) {
r = serialize_item_format(f, "exec-parameters-flags", "%u", (unsigned) p->flags);
if (r < 0)
@ -1115,6 +1121,12 @@ static int exec_parameters_serialize(const ExecParameters *p, const ExecContext
if (r < 0)
return r;
if (p->cgroup_supported != 0) {
r = serialize_item_format(f, "exec-parameters-cgroup-supported", "%u", (unsigned) p->cgroup_supported);
if (r < 0)
return r;
}
r = serialize_item(f, "exec-parameters-cgroup-path", p->cgroup_path);
if (r < 0)
return r;
@ -1277,37 +1289,47 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
if (p->n_socket_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-n-stashed-fds="))) {
} else if ((val = startswith(l, "exec-parameters-n-storage-fds="))) {
if (p->fds)
return -EINVAL; /* Already received */
r = safe_atozu(val, &p->n_stashed_fds);
r = safe_atozu(val, &p->n_storage_fds);
if (r < 0)
return r;
if (p->n_stashed_fds > nr_open)
if (p->n_storage_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-n-extra-fds="))) {
if (p->fds)
return -EINVAL; /* Already received */
r = safe_atozu(val, &p->n_extra_fds);
if (r < 0)
return r;
if (p->n_extra_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-fds="))) {
if (p->n_socket_fds + p->n_stashed_fds == 0)
if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds == 0)
return log_warning_errno(
SYNTHETIC_ERRNO(EINVAL),
"Got exec-parameters-fds= without "
"prior exec-parameters-n-socket-fds= or exec-parameters-n-stashed-fds=");
if (p->n_socket_fds + p->n_stashed_fds > nr_open)
"prior exec-parameters-n-socket-fds= or exec-parameters-n-storage-fds= or exec-parameters-n-extra-fds=");
if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */
if (p->fds)
return -EINVAL; /* duplicated */
p->fds = new(int, p->n_socket_fds + p->n_stashed_fds);
p->fds = new(int, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds);
if (!p->fds)
return log_oom_debug();
/* Ensure we don't leave any FD uninitialized on error, it makes the fuzzer sad */
FOREACH_ARRAY(i, p->fds, p->n_socket_fds + p->n_stashed_fds)
FOREACH_ARRAY(i, p->fds, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds)
*i = -EBADF;
r = deserialize_fd_many(fds, val, p->n_socket_fds + p->n_stashed_fds, p->fds);
r = deserialize_fd_many(fds, val, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds, p->fds);
if (r < 0)
continue;
@ -1328,6 +1350,13 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
return r;
p->selinux_context_net = r;
} else if ((val = startswith(l, "exec-parameters-cgroup-supported="))) {
unsigned cgroup_supported;
r = safe_atou(val, &cgroup_supported);
if (r < 0)
return r;
p->cgroup_supported = cgroup_supported;
} else if ((val = startswith(l, "exec-parameters-cgroup-path="))) {
r = free_and_strdup(&p->cgroup_path, val);
if (r < 0)
@ -1505,9 +1534,9 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
log_warning("Failed to parse serialized line, ignoring: %s", l);
}
/* Bail out if we got exec-parameters-n-{socket/stashed}-fds= but no corresponding
/* Bail out if we got exec-parameters-n-{socket/storage}-fds= but no corresponding
* exec-parameters-fds= */
if (p->n_socket_fds + p->n_stashed_fds > 0 && !p->fds)
if (p->n_socket_fds + p->n_storage_fds > 0 && !p->fds)
return -EINVAL;
return 0;

View File

@ -486,8 +486,8 @@ int exec_spawn(
assert(command);
assert(context);
assert(params);
assert(params->fds || (params->n_socket_fds + params->n_stashed_fds == 0 && !params->fd_names));
assert(params->n_stashed_fds == 0 || FLAGS_SET(params->flags, EXEC_PASS_FDS));
assert(!params->fds || FLAGS_SET(params->flags, EXEC_PASS_FDS));
assert(params->fds || (params->n_socket_fds + params->n_storage_fds + params->n_extra_fds == 0));
assert(!params->files_env); /* We fill this field, ensure it comes NULL-initialized to us */
assert(ret);
@ -1048,6 +1048,7 @@ void exec_params_dump(const ExecParameters *p, FILE* f, const char *prefix) {
"%sRuntimeScope: %s\n"
"%sExecFlags: %u\n"
"%sSELinuxContextNetwork: %s\n"
"%sCgroupSupportedMask: %u\n"
"%sCgroupPath: %s\n"
"%sCrededentialsDirectory: %s\n"
"%sEncryptedCredentialsDirectory: %s\n"
@ -1060,6 +1061,7 @@ void exec_params_dump(const ExecParameters *p, FILE* f, const char *prefix) {
prefix, runtime_scope_to_string(p->runtime_scope),
prefix, p->flags,
prefix, yes_no(p->selinux_context_net),
prefix, p->cgroup_supported,
prefix, p->cgroup_path,
prefix, strempty(p->received_credentials_directory),
prefix, strempty(p->received_encrypted_credentials_directory),
@ -2826,7 +2828,7 @@ void exec_params_deep_clear(ExecParameters *p) {
* to be fully cleaned up to make sanitizers and analyzers happy, as opposed as the shallow clean
* function above. */
close_many_unset(p->fds, p->n_socket_fds + p->n_stashed_fds);
close_many_unset(p->fds, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds);
p->cgroup_path = mfree(p->cgroup_path);

View File

@ -391,16 +391,18 @@ typedef enum ExecFlags {
typedef struct ExecParameters {
RuntimeScope runtime_scope;
ExecFlags flags;
char **environment;
char **files_env;
int *fds;
char **fd_names;
size_t n_socket_fds;
size_t n_stashed_fds;
size_t n_storage_fds;
size_t n_extra_fds;
ExecFlags flags;
bool selinux_context_net:1;
CGroupMask cgroup_supported;
char *cgroup_path;
uint64_t cgroup_id;
@ -428,6 +430,7 @@ typedef struct ExecParameters {
char *fallback_smack_process_label;
char **files_env;
int user_lookup_fd;
int handoff_timestamp_fd;
int pidref_transport_fd;
@ -440,7 +443,6 @@ typedef struct ExecParameters {
char invocation_id_string[SD_ID128_STRING_MAX];
bool debug_invocation;
bool selinux_context_net;
} ExecParameters;
#define EXEC_PARAMETERS_INIT(_flags) \
@ -517,7 +519,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix);
int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_root);
int exec_context_destroy_mount_ns_dir(Unit *u);
const char* exec_context_fdname(const ExecContext *c, int fd_index) _pure_;
const char* exec_context_fdname(const ExecContext *c, int fd_index);
bool exec_context_may_touch_console(const ExecContext *c);
bool exec_context_maintains_privileges(const ExecContext *c);
@ -583,8 +585,8 @@ void exec_runtime_clear(ExecRuntime *rt);
int exec_params_needs_control_subcgroup(const ExecParameters *params);
int exec_params_get_cgroup_path(const ExecParameters *params, const CGroupContext *c, const char *prefix, char **ret);
void exec_params_shallow_clear(ExecParameters *p);
void exec_params_deep_clear(ExecParameters *p);
void exec_params_dump(const ExecParameters *p, FILE* f, const char *prefix);
void exec_params_deep_clear(ExecParameters *p);
bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c);

View File

@ -62,8 +62,8 @@ static void exec_fuzz_one(FILE *f, FDSet *fdset) {
params.user_lookup_fd = -EBADF;
params.bpf_restrict_fs_map_fd = -EBADF;
if (!params.fds)
params.n_socket_fds = params.n_stashed_fds = 0;
for (size_t i = 0; params.fds && i < params.n_socket_fds + params.n_stashed_fds; i++)
params.n_socket_fds = params.n_storage_fds = params.n_extra_fds = 0;
for (size_t i = 0; params.fds && i < params.n_socket_fds + params.n_storage_fds + params.n_extra_fds; i++)
params.fds[i] = -EBADF;
exec_command_done_array(&command, /* n= */ 1);

View File

@ -1451,7 +1451,8 @@ static int service_collect_fds(
int **fds,
char ***fd_names,
size_t *n_socket_fds,
size_t *n_stashed_fds) {
size_t *n_storage_fds,
size_t *n_extra_fds) {
_cleanup_strv_free_ char **rfd_names = NULL;
_cleanup_free_ int *rfds = NULL;
@ -1462,6 +1463,8 @@ static int service_collect_fds(
assert(fds);
assert(fd_names);
assert(n_socket_fds);
assert(n_storage_fds);
assert(n_extra_fds);
if (s->socket_fd >= 0) {
Socket *sock = ASSERT_PTR(SOCKET(UNIT_DEREF(s->accept_socket)));
@ -1508,7 +1511,7 @@ static int service_collect_fds(
}
}
if (n_stashed_fds && s->n_fd_store + s->n_extra_fds > 0) {
if (s->n_fd_store + s->n_extra_fds > 0) {
int *t = reallocarray(rfds, rn_socket_fds + s->n_fd_store + s->n_extra_fds, sizeof(int));
if (!t)
return -ENOMEM;
@ -1545,8 +1548,8 @@ static int service_collect_fds(
*fds = TAKE_PTR(rfds);
*fd_names = TAKE_PTR(rfd_names);
*n_socket_fds = rn_socket_fds;
if (n_stashed_fds)
*n_stashed_fds = s->n_fd_store + s->n_extra_fds;
*n_storage_fds = s->n_fd_store;
*n_extra_fds = s->n_extra_fds;
return 0;
}
@ -1730,32 +1733,25 @@ static int service_spawn_internal(
exec_params.flags &= ~EXEC_APPLY_CHROOT;
}
if (FLAGS_SET(exec_params.flags, EXEC_PASS_FDS)) {
if (FLAGS_SET(exec_params.flags, EXEC_PASS_FDS) ||
s->exec_context.std_input == EXEC_INPUT_SOCKET ||
s->exec_context.std_output == EXEC_OUTPUT_SOCKET ||
s->exec_context.std_error == EXEC_OUTPUT_SOCKET) {
r = service_collect_fds(s,
&exec_params.fds,
&exec_params.fd_names,
&exec_params.n_socket_fds,
&exec_params.n_stashed_fds);
&exec_params.n_storage_fds,
&exec_params.n_extra_fds);
if (r < 0)
return r;
log_unit_debug(UNIT(s), "Passing %zu fds to service", exec_params.n_socket_fds + exec_params.n_stashed_fds);
exec_params.open_files = s->open_files;
} else if (IN_SET(s->exec_context.std_input, EXEC_INPUT_SOCKET, EXEC_INPUT_NAMED_FD) ||
IN_SET(s->exec_context.std_output, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD) ||
IN_SET(s->exec_context.std_error, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD)) {
exec_params.flags |= EXEC_PASS_FDS;
r = service_collect_fds(s,
&exec_params.fds,
&exec_params.fd_names,
&exec_params.n_socket_fds,
/* n_stashed_fds = */ NULL);
if (r < 0)
return r;
log_unit_debug(UNIT(s), "Passing %zu sockets to service", exec_params.n_socket_fds);
log_unit_debug(UNIT(s), "Passing %zu fds to service", exec_params.n_socket_fds + exec_params.n_storage_fds + exec_params.n_extra_fds);
}
if (!FLAGS_SET(exec_params.flags, EXEC_IS_CONTROL) && s->type == SERVICE_EXEC) {

View File

@ -2001,6 +2001,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
if (r < 0)
return r;
exec_params.flags |= EXEC_PASS_FDS;
exec_params.fds = TAKE_PTR(fds);
exec_params.fd_names = TAKE_PTR(fd_names);
exec_params.n_socket_fds = n_fds;

View File

@ -5506,6 +5506,7 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) {
if (r < 0)
return r;
p->cgroup_supported = u->manager->cgroup_supported;
p->prefix = u->manager->prefix;
SET_FLAG(p->flags, EXEC_PASS_LOG_UNIT|EXEC_CHOWN_DIRECTORIES, MANAGER_IS_SYSTEM(u->manager));

View File

@ -53,7 +53,6 @@
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "tar-util.h"
#include "terminal-util.h"
#include "tmpfile-util.h"
#include "uid-classification.h"
@ -1433,6 +1432,109 @@ static int mtree_print_item(
return RECURSE_DIR_CONTINUE;
}
#if HAVE_LIBARCHIVE
static int archive_item(
RecurseDirEvent event,
const char *path,
int dir_fd,
int inode_fd,
const struct dirent *de,
const struct statx *sx,
void *userdata) {
struct archive *a = ASSERT_PTR(userdata);
int r;
assert(path);
if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
return RECURSE_DIR_CONTINUE;
assert(inode_fd >= 0);
assert(sx);
log_debug("Archiving %s\n", path);
_cleanup_(archive_entry_freep) struct archive_entry *entry = NULL;
entry = sym_archive_entry_new();
if (!entry)
return log_oom();
assert(FLAGS_SET(sx->stx_mask, STATX_TYPE|STATX_MODE));
sym_archive_entry_set_pathname(entry, path);
sym_archive_entry_set_filetype(entry, sx->stx_mode);
if (!S_ISLNK(sx->stx_mode))
sym_archive_entry_set_perm(entry, sx->stx_mode);
if (FLAGS_SET(sx->stx_mask, STATX_UID))
sym_archive_entry_set_uid(entry, sx->stx_uid);
if (FLAGS_SET(sx->stx_mask, STATX_GID))
sym_archive_entry_set_gid(entry, sx->stx_gid);
if (S_ISREG(sx->stx_mode)) {
if (!FLAGS_SET(sx->stx_mask, STATX_SIZE))
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Unable to determine file size of '%s'.", path);
sym_archive_entry_set_size(entry, sx->stx_size);
}
if (S_ISCHR(sx->stx_mode) || S_ISBLK(sx->stx_mode)) {
sym_archive_entry_set_rdevmajor(entry, sx->stx_rdev_major);
sym_archive_entry_set_rdevminor(entry, sx->stx_rdev_minor);
}
/* We care about a modicum of reproducibility here, hence we don't save atime/btime here */
if (FLAGS_SET(sx->stx_mask, STATX_MTIME))
sym_archive_entry_set_mtime(entry, sx->stx_mtime.tv_sec, sx->stx_mtime.tv_nsec);
if (FLAGS_SET(sx->stx_mask, STATX_CTIME))
sym_archive_entry_set_ctime(entry, sx->stx_ctime.tv_sec, sx->stx_ctime.tv_nsec);
if (S_ISLNK(sx->stx_mode)) {
_cleanup_free_ char *s = NULL;
assert(dir_fd >= 0);
assert(de);
r = readlinkat_malloc(dir_fd, de->d_name, &s);
if (r < 0)
return log_error_errno(r, "Failed to read symlink target of '%s': %m", path);
sym_archive_entry_set_symlink(entry, s);
}
if (sym_archive_write_header(a, entry) != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to write archive entry header: %s", sym_archive_error_string(a));
if (S_ISREG(sx->stx_mode)) {
_cleanup_close_ int data_fd = -EBADF;
/* Convert the O_PATH fd in a proper fd */
data_fd = fd_reopen(inode_fd, O_RDONLY|O_CLOEXEC);
if (data_fd < 0)
return log_error_errno(data_fd, "Failed to open '%s': %m", path);
for (;;) {
char buffer[64*1024];
ssize_t l;
l = read(data_fd, buffer, sizeof(buffer));
if (l < 0)
return log_error_errno(errno, "Failed to read '%s': %m", path);
if (l == 0)
break;
la_ssize_t k;
k = sym_archive_write_data(a, buffer, l);
if (k < 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to write archive data: %s", sym_archive_error_string(a));
}
}
return RECURSE_DIR_CONTINUE;
}
#endif
static int action_list_or_mtree_or_copy_or_make_archive(DissectedImage *m, LoopDevice *d, int userns_fd) {
_cleanup_(umount_and_freep) char *mounted_dir = NULL;
_cleanup_free_ char *t = NULL;
@ -1634,34 +1736,56 @@ static int action_list_or_mtree_or_copy_or_make_archive(DissectedImage *m, LoopD
case ACTION_MAKE_ARCHIVE: {
#if HAVE_LIBARCHIVE
_cleanup_(unlink_and_freep) char *tar = NULL;
_cleanup_close_ int dfd = -EBADF;
_cleanup_fclose_ FILE *f = NULL;
dfd = open(root, O_DIRECTORY|O_CLOEXEC|O_RDONLY);
if (dfd < 0)
return log_error_errno(errno, "Failed to open mount directory: %m");
_cleanup_(unlink_and_freep) char *tar = NULL;
_cleanup_close_ int tmp_fd = -EBADF;
int output_fd;
if (arg_target) {
tmp_fd = open_tmpfile_linkable(arg_target, O_WRONLY|O_CLOEXEC, &tar);
if (tmp_fd < 0)
return log_error_errno(tmp_fd, "Failed to create target file '%s': %m", arg_target);
_cleanup_(archive_write_freep) struct archive *a = sym_archive_write_new();
if (!a)
return log_oom();
output_fd = tmp_fd;
if (arg_target)
r = sym_archive_write_set_format_filter_by_ext(a, arg_target);
else
r = sym_archive_write_set_format_gnutar(a);
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set libarchive output format: %s", sym_archive_error_string(a));
if (arg_target) {
r = fopen_tmpfile_linkable(arg_target, O_WRONLY|O_CLOEXEC, &tar, &f);
if (r < 0)
return log_error_errno(r, "Failed to create target file '%s': %m", arg_target);
r = sym_archive_write_open_FILE(a, f);
} else {
if (isatty_safe(STDOUT_FILENO))
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Refusing to write archive to TTY.");
output_fd = STDOUT_FILENO;
r = sym_archive_write_open_fd(a, STDOUT_FILENO);
}
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set libarchive output file: %s", sym_archive_error_string(a));
r = tar_c(dfd, output_fd, arg_target, /* flags= */ 0);
r = recurse_dir(dfd,
".",
STATX_TYPE|STATX_MODE|STATX_UID|STATX_GID|STATX_SIZE|STATX_ATIME|STATX_CTIME,
UINT_MAX,
RECURSE_DIR_SORT|RECURSE_DIR_INODE_FD|RECURSE_DIR_TOPLEVEL,
archive_item,
a);
if (r < 0)
return r;
return log_error_errno(r, "Failed to make archive: %m");
r = sym_archive_write_close(a);
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to finish writing archive: %s", sym_archive_error_string(a));
if (arg_target) {
r = link_tmpfile(tmp_fd, tar, arg_target, LINK_TMPFILE_REPLACE);
r = flink_tmpfile(f, tar, arg_target, LINK_TMPFILE_REPLACE);
if (r < 0)
return log_error_errno(r, "Failed to move archive file into place: %m");

View File

@ -7,7 +7,6 @@
#include "alloc-util.h"
#include "btrfs-util.h"
#include "dissect-image.h"
#include "export-tar.h"
#include "fd-util.h"
#include "format-util.h"
@ -28,15 +27,11 @@ typedef struct TarExport {
TarExportFinished on_finished;
void *userdata;
ImportFlags flags;
char *path;
char *temp_path;
int output_fd; /* compressed tar file in the fs */
int tar_fd; /* uncompressed tar stream coming from child doing the libarchive loop */
int tree_fd; /* directory fd of the tree to set up */
int userns_fd;
int output_fd;
int tar_fd;
ImportCompress compress;
@ -103,8 +98,6 @@ int tar_export_new(
*e = (TarExport) {
.output_fd = -EBADF,
.tar_fd = -EBADF,
.tree_fd = -EBADF,
.userns_fd = -EBADF,
.on_finished = on_finished,
.userdata = userdata,
.quota_referenced = UINT64_MAX,
@ -278,13 +271,7 @@ static int tar_export_on_defer(sd_event_source *s, void *userdata) {
return tar_export_process(i);
}
int tar_export_start(
TarExport *e,
const char *path,
int fd,
ImportCompressType compress,
ImportFlags flags) {
int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType compress) {
_cleanup_close_ int sfd = -EBADF;
int r;
@ -312,7 +299,6 @@ int tar_export_start(
if (r < 0)
return r;
e->flags = flags;
e->quota_referenced = UINT64_MAX;
if (btrfs_might_be_subvol(&e->st)) {
@ -351,33 +337,7 @@ int tar_export_start(
if (r < 0)
return r;
const char *p = e->temp_path ?: e->path;
if (FLAGS_SET(e->flags, IMPORT_FOREIGN_UID)) {
r = import_make_foreign_userns(&e->userns_fd);
if (r < 0)
return r;
_cleanup_close_ int directory_fd = open(p, O_DIRECTORY|O_CLOEXEC|O_PATH);
if (directory_fd < 0)
return log_error_errno(r, "Failed to open '%s': %m", p);
_cleanup_close_ int mapped_fd = -EBADF;
r = mountfsd_mount_directory_fd(directory_fd, e->userns_fd, DISSECT_IMAGE_FOREIGN_UID, &mapped_fd);
if (r < 0)
return r;
/* Drop O_PATH */
e->tree_fd = fd_reopen(mapped_fd, O_DIRECTORY|O_CLOEXEC);
if (e->tree_fd < 0)
return log_error_errno(errno, "Failed to re-open mapped '%s': %m", p);
} else {
e->tree_fd = open(p, O_DIRECTORY|O_CLOEXEC);
if (e->tree_fd < 0)
return log_error_errno(errno, "Failed to open '%s': %m", p);
}
e->tar_fd = import_fork_tar_c(e->tree_fd, e->userns_fd, &e->tar_pid);
e->tar_fd = import_fork_tar_c(e->temp_path ?: e->path, &e->tar_pid);
if (e->tar_fd < 0) {
e->output_event_source = sd_event_source_unref(e->output_event_source);
return e->tar_fd;

View File

@ -1,9 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "import-common.h"
#include "import-compress.h"
#include "shared-forward.h"
#include "import-compress.h"
typedef struct TarExport TarExport;
@ -14,4 +13,4 @@ TarExport* tar_export_unref(TarExport *export);
DEFINE_TRIVIAL_CLEANUP_FUNC(TarExport*, tar_export_unref);
int tar_export_start(TarExport *export, const char *path, int fd, ImportCompressType compress, ImportFlags flags);
int tar_export_start(TarExport *export, const char *path, int fd, ImportCompressType compress);

View File

@ -21,7 +21,6 @@
#include "terminal-util.h"
#include "verbs.h"
static ImportFlags arg_import_flags = 0;
static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN;
static ImageClass arg_class = IMAGE_MACHINE;
static RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
@ -112,12 +111,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to allocate exporter: %m");
r = tar_export_start(
export,
local,
fd,
arg_compress,
arg_import_flags & IMPORT_FLAGS_MASK_TAR);
r = tar_export_start(export, local, fd, arg_compress);
if (r < 0)
return log_error_errno(r, "Failed to export image: %m");
@ -289,9 +283,6 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached();
}
if (arg_runtime_scope == RUNTIME_SCOPE_USER)
arg_import_flags |= IMPORT_FOREIGN_UID;
return 1;
}

View File

@ -90,61 +90,62 @@ int import_fork_tar_x(int tree_fd, int userns_fd, PidRef *ret_pid) {
return TAKE_FD(pipefd[1]);
}
int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid) {
int import_fork_tar_c(const char *path, PidRef *ret) {
_cleanup_close_pair_ int pipefd[2] = EBADF_PAIR;
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
bool use_selinux;
int r;
assert(tree_fd >= 0);
assert(ret_pid);
assert(path);
assert(ret);
r = dlopen_libarchive();
if (r < 0)
return r;
TarFlags flags = mac_selinux_use() ? TAR_SELINUX : 0;
_cleanup_close_pair_ int pipefd[2] = EBADF_PAIR;
if (pipe2(pipefd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pipe for tar: %m");
(void) fcntl(pipefd[0], F_SETPIPE_SZ, IMPORT_BUFFER_SIZE);
use_selinux = mac_selinux_use();
r = pidref_safe_fork_full(
"tar-c",
/* stdio_fds= */ NULL,
(int[]) { tree_fd, pipefd[1], userns_fd }, userns_fd >= 0 ? 3 : 2,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_REOPEN_LOG,
ret_pid);
"(tar)",
(int[]) { -EBADF, pipefd[1], STDERR_FILENO },
NULL, 0,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
&pid);
if (r < 0)
return r;
if (r == 0) {
static const uint64_t retain = (1ULL << CAP_DAC_OVERRIDE);
const char *cmdline[] = {
"tar",
"-C", path,
"-c",
"--xattrs",
"--xattrs-include=*",
use_selinux ? "--selinux" : "--no-selinux",
".",
NULL
};
uint64_t retain = (1ULL << CAP_DAC_OVERRIDE);
/* Child */
if (userns_fd >= 0) {
r = detach_mount_namespace_userns(userns_fd);
if (r < 0) {
log_error_errno(r, "Failed to join user namespace: %m");
_exit(EXIT_FAILURE);
}
}
if (unshare(CLONE_NEWNET) < 0)
log_debug_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
r = capability_bounding_set_drop(retain, true);
if (r < 0)
log_debug_errno(r, "Failed to drop capabilities, ignoring: %m");
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
log_warning_errno(errno, "Failed to enable PR_SET_NO_NEW_PRIVS, ignoring: %m");
execvp("gtar", (char* const*) cmdline);
execvp("tar", (char* const*) cmdline);
if (tar_c(tree_fd, pipefd[1], /* filename= */ NULL, flags) < 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
*ret = TAKE_PIDREF(pid);
return TAKE_FD(pipefd[0]);
}

View File

@ -34,7 +34,7 @@ typedef enum ImportFlags {
_IMPORT_FLAGS_INVALID = -EINVAL,
} ImportFlags;
int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid);
int import_fork_tar_c(const char *path, PidRef *ret);
int import_fork_tar_x(int tree_fd, int userns_fd, PidRef *ret_pid);
int import_mangle_os_tree(const char *path);

View File

@ -118,7 +118,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep);
(UINT32_C(1) << TPM2_PCR_BOOT_LOADER_CONFIG) | \
(UINT32_C(1) << TPM2_PCR_SECURE_BOOT_POLICY) | \
(UINT32_C(1) << TPM2_PCR_KERNEL_BOOT) | \
/* Note: we do not add PCR12/TPM2_PCR_KERNEL_CONFIG here, since our pcrlock policy ends up in there, and this would hence result in a conceptual loop */ \
(UINT32_C(1) << TPM2_PCR_KERNEL_CONFIG) | \
(UINT32_C(1) << TPM2_PCR_SYSEXTS) | \
(UINT32_C(1) << TPM2_PCR_SHIM_POLICY) | \
(UINT32_C(1) << TPM2_PCR_SYSTEM_IDENTITY))

View File

@ -25,7 +25,6 @@
#include "bus-util.h"
#include "bus-wait-for-jobs.h"
#include "calendarspec.h"
#include "capability-util.h"
#include "capsule-util.h"
#include "chase.h"
#include "env-util.h"
@ -118,7 +117,6 @@ static char *arg_shell_prompt_prefix = NULL;
static int arg_lightweight = -1;
static char *arg_area = NULL;
static bool arg_via_shell = false;
static bool arg_empower = false;
STATIC_DESTRUCTOR_REGISTER(arg_description, freep);
STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep);
@ -246,7 +244,6 @@ static int help_sudo_mode(void) {
" --lightweight=BOOLEAN Control whether to register a session with service manager\n"
" or without\n"
" --area=AREA Home area to log into\n"
" --empower Give privileges to selected or current user\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@ -256,15 +253,11 @@ static int help_sudo_mode(void) {
return 0;
}
static bool become_root(void) {
return !arg_exec_user || STR_IN_SET(arg_exec_user, "root", "0");
}
static bool privileged_execution(void) {
if (arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
return false;
return become_root() || arg_empower;
return !arg_exec_user || STR_IN_SET(arg_exec_user, "root", "0");
}
static int add_timer_property(const char *name, const char *val) {
@ -866,7 +859,6 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
ARG_LIGHTWEIGHT,
ARG_AREA,
ARG_VIA_SHELL,
ARG_EMPOWER,
};
/* If invoked as "run0" binary, let's expose a more sudo-like interface. We add various extensions
@ -896,7 +888,6 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
{ "shell-prompt-prefix", required_argument, NULL, ARG_SHELL_PROMPT_PREFIX },
{ "lightweight", required_argument, NULL, ARG_LIGHTWEIGHT },
{ "area", required_argument, NULL, ARG_AREA },
{ "empower", no_argument, NULL, ARG_EMPOWER },
{},
};
@ -1036,10 +1027,6 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
arg_via_shell = true;
break;
case ARG_EMPOWER:
arg_empower = true;
break;
case '?':
return -EINVAL;
@ -1047,13 +1034,9 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
assert_not_reached();
}
if (!arg_exec_user && (arg_area || arg_empower)) {
if (!arg_exec_user && arg_area) {
/* If the user specifies --area= but not --user= then consider this an area switch request,
* and default to logging into our own account.
*
* If the user specifies --empower but not --user= then consider this a request to empower
* the current user. */
* and default to logging into our own account */
arg_exec_user = getusername_malloc();
if (!arg_exec_user)
return log_oom();
@ -1228,8 +1211,8 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
if (arg_lightweight >= 0) {
const char *class =
arg_lightweight ? (arg_stdio == ARG_STDIO_PTY ? (become_root() ? "user-early-light" : "user-light") : "background-light") :
(arg_stdio == ARG_STDIO_PTY ? (become_root() ? "user-early" : "user") : "background");
arg_lightweight ? (arg_stdio == ARG_STDIO_PTY ? (privileged_execution() ? "user-early-light" : "user-light") : "background-light") :
(arg_stdio == ARG_STDIO_PTY ? (privileged_execution() ? "user-early" : "user") : "background");
log_debug("Setting XDG_SESSION_CLASS to '%s'.", class);
@ -1388,12 +1371,6 @@ static int transient_service_set_properties(sd_bus_message *m, const char *pty_p
return bus_log_create_error(r);
}
if (arg_empower) {
r = sd_bus_message_append(m, "(sv)", "AmbientCapabilities", "t", CAP_MASK_ALL);
if (r < 0)
return bus_log_create_error(r);
}
if (arg_nice_set) {
r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice);
if (r < 0)

View File

@ -14,7 +14,6 @@
#include "iovec-util.h"
#include "libarchive-util.h"
#include "path-util.h"
#include "recurse-dir.h"
#include "stat-util.h"
#include "string-util.h"
#include "tmpfile-util.h"
@ -675,145 +674,6 @@ int tar_x(int input_fd, int tree_fd, TarFlags flags) {
return 0;
}
static int archive_item(
RecurseDirEvent event,
const char *path,
int dir_fd,
int inode_fd,
const struct dirent *de,
const struct statx *sx,
void *userdata) {
struct archive *a = ASSERT_PTR(userdata);
int r;
assert(path);
if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
return RECURSE_DIR_CONTINUE;
assert(inode_fd >= 0);
assert(sx);
log_debug("Archiving %s\n", path);
_cleanup_(archive_entry_freep) struct archive_entry *entry = NULL;
entry = sym_archive_entry_new();
if (!entry)
return log_oom();
assert(FLAGS_SET(sx->stx_mask, STATX_TYPE|STATX_MODE));
sym_archive_entry_set_pathname(entry, path);
sym_archive_entry_set_filetype(entry, sx->stx_mode);
if (!S_ISLNK(sx->stx_mode))
sym_archive_entry_set_perm(entry, sx->stx_mode);
if (FLAGS_SET(sx->stx_mask, STATX_UID))
sym_archive_entry_set_uid(entry, sx->stx_uid);
if (FLAGS_SET(sx->stx_mask, STATX_GID))
sym_archive_entry_set_gid(entry, sx->stx_gid);
if (S_ISREG(sx->stx_mode)) {
if (!FLAGS_SET(sx->stx_mask, STATX_SIZE))
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Unable to determine file size of '%s'.", path);
sym_archive_entry_set_size(entry, sx->stx_size);
}
if (S_ISCHR(sx->stx_mode) || S_ISBLK(sx->stx_mode)) {
sym_archive_entry_set_rdevmajor(entry, sx->stx_rdev_major);
sym_archive_entry_set_rdevminor(entry, sx->stx_rdev_minor);
}
/* We care about a modicum of reproducibility here, hence we don't save atime/btime here */
if (FLAGS_SET(sx->stx_mask, STATX_MTIME))
sym_archive_entry_set_mtime(entry, sx->stx_mtime.tv_sec, sx->stx_mtime.tv_nsec);
if (FLAGS_SET(sx->stx_mask, STATX_CTIME))
sym_archive_entry_set_ctime(entry, sx->stx_ctime.tv_sec, sx->stx_ctime.tv_nsec);
if (S_ISLNK(sx->stx_mode)) {
_cleanup_free_ char *s = NULL;
assert(dir_fd >= 0);
assert(de);
r = readlinkat_malloc(dir_fd, de->d_name, &s);
if (r < 0)
return log_error_errno(r, "Failed to read symlink target of '%s': %m", path);
sym_archive_entry_set_symlink(entry, s);
}
if (sym_archive_write_header(a, entry) != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to write archive entry header: %s", sym_archive_error_string(a));
if (S_ISREG(sx->stx_mode)) {
_cleanup_close_ int data_fd = -EBADF;
/* Convert the O_PATH fd in a proper fd */
data_fd = fd_reopen(inode_fd, O_RDONLY|O_CLOEXEC);
if (data_fd < 0)
return log_error_errno(data_fd, "Failed to open '%s': %m", path);
for (;;) {
char buffer[64*1024];
ssize_t l;
l = read(data_fd, buffer, sizeof(buffer));
if (l < 0)
return log_error_errno(errno, "Failed to read '%s': %m", path);
if (l == 0)
break;
la_ssize_t k;
k = sym_archive_write_data(a, buffer, l);
if (k < 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to write archive data: %s", sym_archive_error_string(a));
}
}
return RECURSE_DIR_CONTINUE;
}
int tar_c(int tree_fd, int output_fd, const char *filename, TarFlags flags) {
int r;
assert(tree_fd >= 0);
assert(output_fd >= 0);
_cleanup_(archive_write_freep) struct archive *a = sym_archive_write_new();
if (!a)
return log_oom();
if (filename)
r = sym_archive_write_set_format_filter_by_ext(a, filename);
else
r = sym_archive_write_set_format_gnutar(a);
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set libarchive output format: %s", sym_archive_error_string(a));
r = sym_archive_write_open_fd(a, output_fd);
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set libarchive output file: %s", sym_archive_error_string(a));
r = recurse_dir(tree_fd,
".",
STATX_TYPE|STATX_MODE|STATX_UID|STATX_GID|STATX_SIZE|STATX_ATIME|STATX_CTIME,
UINT_MAX,
RECURSE_DIR_SORT|RECURSE_DIR_INODE_FD|RECURSE_DIR_TOPLEVEL,
archive_item,
a);
if (r < 0)
return log_error_errno(r, "Failed to make archive: %m");
r = sym_archive_write_close(a);
if (r != ARCHIVE_OK)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to finish writing archive: %s", sym_archive_error_string(a));
return 0;
}
#else
int tar_x(int input_fd, int tree_fd, TarFlags flags) {
@ -823,11 +683,4 @@ int tar_x(int input_fd, int tree_fd, TarFlags flags) {
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libarchive support not available.");
}
int tar_c(int tree_fd, int output_fd, const char *filename, TarFlags flags) {
assert(tree_fd >= 0);
assert(output_fd >= 0);
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "libarchive support not available.");
}
#endif

View File

@ -6,4 +6,3 @@ typedef enum TarFlags {
} TarFlags;
int tar_x(int input_fd, int tree_fd, TarFlags flags);
int tar_c(int tree_fd, int output_fd, const char *filename, TarFlags flags);

View File

@ -297,14 +297,6 @@ if [[ -e /usr/lib/pam.d/systemd-run0 ]] || [[ -e /etc/pam.d/systemd-run0 ]]; the
# Validate when we invoke run0 without a tty, that depending on --pty it either allocates a tty or not
assert_neq "$(run0 --pty tty < /dev/null)" "not a tty"
assert_eq "$(run0 --pipe tty < /dev/null)" "not a tty"
# Validate that --empower gives all capabilities to a non-root user.
caps="$(run0 -u testuser --empower systemd-analyze capability --mask "$(grep CapEff /proc/self/status | cut -d':' -f2)" --json=pretty | jq -r length)"
assert_neq "$caps" "0"
run0 -u testuser --empower touch /run/empower
assert_eq "$(stat -c "%U" /run/empower)" testuser
rm /run/empower
fi
# Tests whether intermediate disconnects corrupt us (modified testcase from https://github.com/systemd/systemd/issues/27204)