1
0
mirror of https://github.com/systemd/systemd synced 2026-03-13 00:24:48 +01:00

Compare commits

..

No commits in common. "14519d7dfa806a1d2d999e4c88037f3ce6a84c08" and "dd8c12e5ec2416838401350a75f1df24f3bcb6cf" have entirely different histories.

80 changed files with 849 additions and 2253 deletions

View File

@ -38,5 +38,4 @@ Stable branches with backported patches are available in the [stable repo](https
We have a security bug bounty program sponsored by the [Sovereign Tech Fund](https://www.sovereigntechfund.de/) hosted on [YesWeHack](https://yeswehack.com/programs/systemd-bug-bounty-program)
Repositories with distribution packages built from git main are [available on OBS](https://software.opensuse.org//download.html?project=system%3Asystemd&package=systemd),
and also repositories with [packages built from the latest stable release](https://software.opensuse.org//download.html?project=system%3Asystemd%3Astable&package=systemd)
Repositories with distribution packages built from git main are [available on OBS](https://software.opensuse.org//download.html?project=system%3Asystemd&package=systemd)

19
TODO
View File

@ -116,25 +116,10 @@ Deprecations and removals:
* Consider removing root=gpt-auto, and push people to use root=dissect instead.
* remove any trace of "cpuacct" cgroup controller, it's a cgroupv1 thing.
similar "devices"
Features:
* report:
- should the list of metrics use JSON-SEQ? or maybe be wrapped in a json
array (the latter might be necessary, once we sign the combination)
- "io.systemd.Manager.unit_active_state" is a weird mix of CamelCase and snake_case
- metrics from pid1: suppress metrics form units that are inactive and have nothing to report
- how to plug facts into this? i.e. hostname, ssh keys, and so on
- switch to daan's suggested hierarchy?
* implement a varlink registry service, similar to the one of the reference
implementation, backed by /run/varlink/registry/. Then, also implement
connect-via-registry-resolution in sd-varlink and varlinkctl. Care needs to
be taken to do the resolution asynchronousy. Also, note that the Varlink
reference implementation uses a different address syntax, which needs to be
taken into account.
* mountfsd: when looking for non-foreign uid owned inodes up the tree, stop at
mounts
* downgrade the uid/gid disposition enforcement in udev

View File

@ -42,7 +42,7 @@ Thus code that is used by "higher-level" components (e.g. our binaries which are
would go to a subdirectory specific to that component if it is only used there.
If the code is to be shared between components, it'd go to `src/shared/`.
Shared code that is used by multiple components that do not link to `libsystemd-shared-<nnn>.so` may live either in `src/libsystemd/`, `src/basic/`, or `src/fundamental/`.
Code used only for EFI goes under `src/boot/`, and under `src/fundamental/` if it is shared with non-EFI components.
Any code that is used only for EFI goes under `src/boot/efi/`, and in `src/fundamental/` if it is shared with non-EFI components.
To summarize:

View File

@ -671,10 +671,6 @@ SYSTEMD_HOME_DEBUG_SUFFIX=foo \
specified algorithm takes an effect immediately, you need to explicitly run
`journalctl --rotate`.
* `$SYSTEMD_JOURNAL_FD_SIZE_MAX` Takes a size with the usual suffixes (K, M, ...) in
string format. Overrides the default maximum allowed size for a file-descriptor
based input record to be stored in the journal.
* `$SYSTEMD_CATALOG` path to the compiled catalog database file to use for
`journalctl -x`, `journalctl --update-catalog`, `journalctl --list-catalog`
and related calls.

View File

@ -26,15 +26,14 @@ SPDX-License-Identifier: LGPL-2.1-or-later
17. Check that announcement to systemd-devel, with a copy&paste from NEWS, was sent. This should happen automatically.
18. Update IRC topic (`/msg chanserv TOPIC #systemd Version NNN released | Online resources https://systemd.io/`)
19. [FINAL] Create an empty -stable branch: `git push systemd origin/main:refs/heads/v${version}-stable`.
20. [FINAL] Edit in the new -stable branch `.obs/workflows.yml`, changing `project` from `system:systemd` to `system:systemd:stable` and the branch from `main` to `v${version}-stable`. This should be backported to older active stable branches too.
21. [FINAL] Build and upload the documentation (on the -stable branch): `ninja -C build doc-sync`
22. [FINAL] Create a new `ci/v${version}-stable` branch for deb package builds on https://salsa.debian.org/systemd-team/systemd
23. [FINAL] Switch `.semaphore/semaphore-runner.sh` and `mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf`
20. [FINAL] Build and upload the documentation (on the -stable branch): `ninja -C build doc-sync`
21. [FINAL] Create a new `ci/v${version}-stable` branch for deb package builds on https://salsa.debian.org/systemd-team/systemd
22. [FINAL] Switch `.semaphore/semaphore-runner.sh` and `mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf`
to the new `ci/v${version}-stable` branch on the -stable branch
24. [FINAL] Switch `versionrewrite-pattern` and `versionrewrite-replacement` to release mode in https://build.opensuse.org/projects/system:systemd/packages/systemd/files/_service?expand=1
25. [FINAL] Change the Github Pages branch to the newly created branch (https://github.com/systemd/systemd/settings/pages) and set the 'Custom domain' to 'systemd.io'
26. [FINAL] Update version number in `meson.version` to the devel version of the next release (e.g. from `256` to `257~devel`)
27. [FINAL] Build and upload the documentation (on the main branch): `ninja -C build doc-sync`
23. [FINAL] Switch `versionrewrite-pattern` and `versionrewrite-replacement` to release mode in https://build.opensuse.org/projects/system:systemd/packages/systemd/files/_service?expand=1
24. [FINAL] Change the Github Pages branch to the newly created branch (https://github.com/systemd/systemd/settings/pages) and set the 'Custom domain' to 'systemd.io'
25. [FINAL] Update version number in `meson.version` to the devel version of the next release (e.g. from `256` to `257~devel`)
26. [FINAL] Build and upload the documentation (on the main branch): `ninja -C build doc-sync`
# Steps to a Successful Stable Release

View File

@ -266,12 +266,12 @@ def check_matches(groups):
if gr:
# we check this first to provide an easy error message
if rest[-1] not in '*:':
error('Pattern {!r} does not end with "*" or ":"', match)
error('Pattern {} does not end with "*" or ":"', match)
try:
gr.parseString(rest)
except ParseBaseException as e:
error('Pattern {!r} is invalid: {}', match, e)
error('Pattern {} is invalid: {}', match, e)
continue
matches.sort()
@ -353,11 +353,12 @@ def print_summary(fname, groups):
error(f'{fname}: no matches or props')
if __name__ == '__main__':
args = sys.argv[1:] or sorted([
args = sys.argv[1:] or sorted(
[
os.path.dirname(sys.argv[0]) + '/20-dmi-id.hwdb',
os.path.dirname(sys.argv[0]) + '/20-net-ifname.hwdb',
*glob.glob(os.path.dirname(sys.argv[0]) + '/[678][0-9]-*.hwdb'),
])
] + glob.glob(os.path.dirname(sys.argv[0]) + '/[678][0-9]-*.hwdb')
)
for fname in args:
groups = parse(fname)

View File

@ -524,18 +524,6 @@
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--efi-boot-option-description-with-device=</option></term>
<listitem><para>Takes a boolean, defaults to false. Controls whether to append disk model information
to the firmware boot option item description (as configured with
<option>--efi-boot-option-description=</option> above). This is useful when installing multiple
operating systems on separate disks on the same system, as it ensures the firmware boot options are discernable
and give a hint which disk is booted into. Note that this uses hardware model information, and hence
might not be too useful in case multiple disks of an identical model are used.</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--dry-run</option></term>
<listitem><para>Dry run for <option>unlink</option> and <option>cleanup</option>.</para>

View File

@ -1132,7 +1132,6 @@ manpages = [
'ENABLE_RANDOMSEED'],
['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''],
['systemd-repart', '8', ['systemd-repart.service'], 'ENABLE_REPART'],
['systemd-report', '1', [], ''],
['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVE'],
['systemd-rfkill.service',
'8',

View File

@ -1,74 +0,0 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd-report"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-report</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-report</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-report</refname>
<refpurpose>Generate report of system facts and metrics</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>systemd-report</command> <arg choice="opt" rep="repeat">OPTIONS</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-report</command> requests facts and metrics from the system and writes them to
standard output.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--system</option></term>
<term><option>--user</option></term>
<listitem>
<para>Query per-system metrics sources (the default), or the per-user metrics sources.</para>
<xi:include href="version-info.xml" xpointer="v260"/>
</listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="json" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure code
otherwise.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
</refentry>

View File

@ -181,16 +181,6 @@
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<varlistentry>
<term><command>list-registry</command></term>
<listitem><para>Shows a list of Varlink services currently registered in the service registry, plus
their entrypoint sockets. (Currently, this simply enumerates the sockets and symlinked sockets in
<filename>/run/varlink/registry/</filename>, see below.)</para>
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
</varlistentry>
<varlistentry>
<term><command>validate-idl</command> [<replaceable>FILE</replaceable>]</term>
@ -364,18 +354,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>--system</option></term>
<term><option>--user</option></term>
<listitem>
<para>Determines whether to query to the per-system or per-user registry when using the
<command>list-registry</command> command. By default, the per-system registry is queried.</para>
</listitem>
<xi:include href="version-info.xml" xpointer="v260"/>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-ask-password" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
@ -383,31 +361,6 @@
</variablelist>
</refsect1>
<refsect1>
<title>Files &amp; Directories</title>
<variablelist>
<varlistentry>
<term><filename>/run/varlink/registry/</filename></term>
<listitem>
<para>Directory containing <constant>AF_UNIX</constant> entrypoint socket inodes (or symlinks to
them) of well-known, public Varlink interfaces on the local system. They are named after the
Varlink interface they implement.</para>
<para>Use <command>varlinkctl list-registry</command> to show the contents of this
directory.</para>
<para>(Inodes that neither qualify as socket inodes nor as symlinks to them shall be ignored. A
future extension might introduce regular files and directories to enhance the registry
functionality.)</para>
<xi:include href="version-info.xml" xpointer="v260"/>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>

View File

@ -3,7 +3,7 @@
install_data('70-systemd-shell-extra.sh', install_dir : shellprofiledir.startswith('/usr/') ? shellprofiledir : libexecdir / 'profile.d')
install_data('80-systemd-osc-context.sh', install_dir : shellprofiledir.startswith('/usr/') ? shellprofiledir : libexecdir / 'profile.d')
if (not shellprofiledir.startswith(sysconfdir) or install_sysconfdir) and conf.get('LINK_SHELL_EXTRA_DROPIN') == 1
if conf.get('LINK_SHELL_EXTRA_DROPIN') == 1
if meson.version().version_compare('>=1.3.0')
install_symlink(
'70-systemd-shell-extra.sh',
@ -19,7 +19,7 @@ if (not shellprofiledir.startswith(sysconfdir) or install_sysconfdir) and conf.g
endif
endif
if (not shellprofiledir.startswith(sysconfdir) or install_sysconfdir) and conf.get('LINK_OSC_CONTEXT_DROPIN') == 1
if conf.get('LINK_OSC_CONTEXT_DROPIN') == 1
if meson.version().version_compare('>=1.3.0')
install_symlink(
'80-systemd-osc-context.sh',

View File

@ -63,7 +63,7 @@ _varlinkctl() {
fi
local -A VERBS=(
[STANDALONE]='help list-registry'
[STANDALONE]='help'
[CALL]='call'
[FILE]='info list-interfaces validate-idl'
[ADDRESS_INTERFACES]='list-methods introspect'

View File

@ -26,10 +26,7 @@
CHASE_STEP | \
CHASE_PROHIBIT_SYMLINKS | \
CHASE_PARENT | \
CHASE_MKDIR_0755 | \
CHASE_MUST_BE_DIRECTORY | \
CHASE_MUST_BE_REGULAR | \
CHASE_MUST_BE_SOCKET)
CHASE_MKDIR_0755)
bool unsafe_transition(const struct stat *a, const struct stat *b) {
/* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to
@ -136,6 +133,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
int r;
assert(!FLAGS_SET(flags, CHASE_PREFIX_ROOT));
assert(!FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_REGULAR));
assert(!FLAGS_SET(flags, CHASE_STEP|CHASE_EXTRACT_FILENAME));
assert(!FLAGS_SET(flags, CHASE_NO_AUTOFS|CHASE_TRIGGER_AUTOFS));
assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
@ -330,10 +328,6 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
if (FLAGS_SET(flags, CHASE_PARENT))
flags |= CHASE_MUST_BE_DIRECTORY;
/* If multiple flags are set now, fail immediately */
if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY) + FLAGS_SET(flags, CHASE_MUST_BE_REGULAR) + FLAGS_SET(flags, CHASE_MUST_BE_SOCKET) > 1)
return -EBADSLT;
for (todo = buffer;;) {
_cleanup_free_ char *first = NULL;
_cleanup_close_ int child = -EBADF;
@ -572,12 +566,6 @@ success:
if (r < 0)
return r;
}
if (FLAGS_SET(flags, CHASE_MUST_BE_SOCKET)) {
r = stat_verify_socket(&st);
if (r < 0)
return r;
}
}
if (ret_path) {
@ -884,7 +872,7 @@ int chase_and_opendir(const char *path, const char *root, ChaseFlags chase_flags
DIR *d;
int r;
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR|CHASE_MUST_BE_SOCKET)));
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR)));
assert(ret_dir);
if (empty_or_root(root) && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) {
@ -982,7 +970,7 @@ int chase_and_fopen_unlocked(
int mode_flags, r;
assert(path);
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT|CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_SOCKET)));
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_PARENT|CHASE_MUST_BE_DIRECTORY)));
assert(open_flags);
assert(ret_file);
@ -1052,7 +1040,7 @@ int chase_and_openat(
_cleanup_free_ char *p = NULL, *fname = NULL;
int r;
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_SOCKET)));
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP)));
XOpenFlags xopen_flags = 0;
if (FLAGS_SET(chase_flags, CHASE_MUST_BE_DIRECTORY))
@ -1098,7 +1086,7 @@ int chase_and_opendirat(int dir_fd, const char *path, ChaseFlags chase_flags, ch
DIR *d;
int r;
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR|CHASE_MUST_BE_SOCKET)));
assert(!(chase_flags & (CHASE_NONEXISTENT|CHASE_STEP|CHASE_MUST_BE_REGULAR)));
assert(ret_dir);
if (dir_fd == AT_FDCWD && !ret_path && (chase_flags & CHASE_NO_SHORTCUT_MASK) == 0) {

View File

@ -29,7 +29,6 @@ typedef enum ChaseFlags {
CHASE_EXTRACT_FILENAME = 1 << 13, /* Only return the last component of the resolved path */
CHASE_MUST_BE_DIRECTORY = 1 << 14, /* Fail if returned inode fd is not a dir */
CHASE_MUST_BE_REGULAR = 1 << 15, /* Fail if returned inode fd is not a regular file */
CHASE_MUST_BE_SOCKET = 1 << 16, /* Fail if returned inode fd is not a socket */
} ChaseFlags;
bool unsafe_transition(const struct stat *a, const struct stat *b);

View File

@ -5,11 +5,10 @@
#include "dirent-util.h"
#include "path-util.h"
#include "stat-util.h"
#include "string-util.h"
int dirent_ensure_type(int dir_fd, struct dirent *de) {
int r;
struct statx sx;
assert(dir_fd >= 0);
assert(de);
@ -23,16 +22,8 @@ int dirent_ensure_type(int dir_fd, struct dirent *de) {
}
/* Let's ask only for the type, nothing else. */
struct statx sx;
r = xstatx_full(dir_fd,
de->d_name,
AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
/* mandatory_mask= */ STATX_TYPE,
/* optional_mask= */ STATX_INO,
/* mandatory_attributes= */ 0,
&sx);
if (r < 0)
return r;
if (statx(dir_fd, de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx) < 0)
return -errno;
assert(FLAGS_SET(sx.stx_mask, STATX_TYPE));
de->d_type = IFTODT(sx.stx_mode);

View File

@ -69,14 +69,15 @@ int make_lock_file_for(const char *p, int operation, LockFile *ret) {
assert(p);
assert(ret);
r = path_split_prefix_filename(p, &dn, &fn);
r = path_extract_filename(p, &fn);
if (r < 0)
return r;
r = path_extract_directory(p, &dn);
if (r < 0)
return r;
if (dn)
t = strjoin(dn, "/.#", fn, ".lck");
else
t = strjoin(".#", fn, ".lck");
if (!t)
return -ENOMEM;

View File

@ -263,14 +263,9 @@ int is_mount_point_at(int dir_fd, const char *path, int flags) {
/* When running on chroot environment, the root may not be a mount point, but we unconditionally
* return true when the input is "/" in the above, but the shortcut may not work e.g. when the path
* is relative. */
struct statx sx2;
r = xstatx(AT_FDCWD,
"/",
AT_STATX_DONT_SYNC,
STATX_TYPE|STATX_INO,
&sx2);
if (r < 0)
return r;
struct statx sx2 = {}; /* explicitly initialize the struct to make msan silent. */
if (statx(AT_FDCWD, "/", AT_STATX_DONT_SYNC, STATX_TYPE|STATX_INO, &sx2) < 0)
return -errno;
return statx_inode_same(&sx, &sx2);
}

View File

@ -1027,7 +1027,8 @@ int path_find_last_component(const char *path, bool accept_dot_dot, const char *
q = path + strlen(path) - 1;
q = skip_slash_or_dot_backward(path, q);
if (!q) { /* the root directory, "." or "./" */
if (!q || /* the root directory */
(q == path && *q == '.')) { /* path is "." or "./" */
if (next)
*next = path;
if (ret)
@ -1101,17 +1102,18 @@ const char* last_path_component(const char *path) {
return path + k;
}
int path_split_prefix_filename(const char *path, char **ret_dir, char **ret_filename) {
_cleanup_free_ char *d = NULL;
int path_extract_filename(const char *path, char **ret) {
_cleanup_free_ char *a = NULL;
const char *c, *next = NULL;
int r;
/* Split the path into dir prefix/filename pair. Returns:
/* Extracts the filename part (i.e. right-most component) from a path, i.e. string that passes
* filename_is_valid(). A wrapper around last_path_component(), but eats up trailing
* slashes. Returns:
*
* -EINVAL if the path is not valid
* -EADDRNOTAVAIL if the path refers to the uppermost directory in hierarchy (i.e. has neither
* dir prefix nor filename - the root dir itself or ".")
* -EDESTADDRREQ if only a filename was passed, and caller only specifies ret_dir
* -EADDRNOTAVAIL if only a directory was specified, but no filename, i.e. the root dir
* itself or "." is specified
* -ENOMEM no memory
*
* Returns >= 0 on success. If the input path has a trailing slash, returns O_DIRECTORY, to
@ -1120,54 +1122,65 @@ int path_split_prefix_filename(const char *path, char **ret_dir, char **ret_file
* This function guarantees to return a fully valid filename, i.e. one that passes
* filename_is_valid() this means "." and ".." are not accepted. */
if (isempty(path))
if (!path_is_valid(path))
return -EINVAL;
r = path_find_last_component(path, /* accept_dot_dot = */ false, &next, &c);
r = path_find_last_component(path, false, &next, &c);
if (r < 0)
return r;
if (r == 0) /* root directory or "." */
if (r == 0) /* root directory */
return -EADDRNOTAVAIL;
if (ret_dir) {
if (next == path) {
if (*path != '/') { /* filename only */
if (!ret_filename)
return -EDESTADDRREQ;
} else {
d = strdup("/");
if (!d)
return -ENOMEM;
}
} else {
d = strndup(path, next - path);
if (!d)
a = strndup(c, r);
if (!a)
return -ENOMEM;
path_simplify(d);
if (!path_is_valid(d))
return -EINVAL;
}
} else if (!path_is_valid(path))
/* We didn't validate the dir prefix, hence check if the whole path is valid now */
return -EINVAL;
if (ret_filename) {
char *fn = strndup(c, r);
if (!fn)
return -ENOMEM;
*ret_filename = fn;
}
if (ret_dir)
*ret_dir = TAKE_PTR(d);
*ret = TAKE_PTR(a);
return strlen(c) > (size_t) r ? O_DIRECTORY : 0;
}
int path_extract_directory(const char *path, char **ret) {
const char *c, *next = NULL;
int r;
/* The inverse of path_extract_filename(), i.e. returns the directory path prefix. Returns:
*
* -EINVAL if the path is not valid
* -EDESTADDRREQ if no directory was specified in the passed in path, i.e. only a filename was passed
* -EADDRNOTAVAIL if the passed in parameter had no filename but did have a directory, i.e.
* the root dir itself or "." was specified
* -ENOMEM no memory (surprise!)
*
* This function guarantees to return a fully valid path, i.e. one that passes path_is_valid().
*/
r = path_find_last_component(path, false, &next, &c);
if (r < 0)
return r;
if (r == 0) /* empty or root */
return isempty(path) ? -EINVAL : -EADDRNOTAVAIL;
if (next == path) {
if (*path != '/') /* filename only */
return -EDESTADDRREQ;
return strdup_to(ret, "/");
}
_cleanup_free_ char *a = strndup(path, next - path);
if (!a)
return -ENOMEM;
path_simplify(a);
if (!path_is_valid(a))
return -EINVAL;
if (ret)
*ret = TAKE_PTR(a);
return 0;
}
bool filename_part_is_valid(const char *p) {
const char *e;

View File

@ -135,15 +135,8 @@ int fsck_exists_for_fstype(const char *fstype);
int path_find_first_component(const char **p, bool accept_dot_dot, const char **ret);
int path_find_last_component(const char *path, bool accept_dot_dot, const char **next, const char **ret);
const char* last_path_component(const char *path);
int path_split_prefix_filename(const char *path, char **ret_dir, char **ret_filename);
static inline int path_extract_filename(const char *path, char **ret) {
return path_split_prefix_filename(path, NULL, ret);
}
static inline int path_extract_directory(const char *path, char **ret) {
int r = path_split_prefix_filename(path, ret, NULL);
return r < 0 ? r : 0; /* suppress O_DIRECTORY */
}
int path_extract_filename(const char *path, char **ret);
int path_extract_directory(const char *path, char **ret);
bool filename_part_is_valid(const char *p) _pure_;
bool filename_is_valid(const char *p) _pure_;

View File

@ -90,21 +90,6 @@ int stat_verify_directory(const struct stat *st) {
return 0;
}
int statx_verify_directory(const struct statx *stx) {
assert(stx);
if (!FLAGS_SET(stx->stx_mask, STATX_TYPE))
return -ENODATA;
if (S_ISLNK(stx->stx_mode))
return -ELOOP;
if (!S_ISDIR(stx->stx_mode))
return -ENOTDIR;
return 0;
}
int fd_verify_directory(int fd) {
if (IN_SET(fd, AT_FDCWD, XAT_FDROOT))
return 0;
@ -142,21 +127,6 @@ int is_symlink(const char *path) {
return verify_stat_at(AT_FDCWD, path, false, stat_verify_symlink, false);
}
int stat_verify_socket(const struct stat *st) {
assert(st);
if (S_ISLNK(st->st_mode))
return -ELOOP;
if (S_ISDIR(st->st_mode))
return -EISDIR;
if (!S_ISSOCK(st->st_mode))
return -ENOTSOCK;
return 0;
}
int stat_verify_linked(const struct stat *st) {
assert(st);

View File

@ -11,7 +11,6 @@ int verify_regular_at(int fd, const char *path, bool follow);
int fd_verify_regular(int fd);
int stat_verify_directory(const struct stat *st);
int statx_verify_directory(const struct statx *stx);
int fd_verify_directory(int fd);
int is_dir_at(int fd, const char *path, bool follow);
int is_dir(const char *path, bool follow);
@ -20,8 +19,6 @@ int stat_verify_symlink(const struct stat *st);
int fd_verify_symlink(int fd);
int is_symlink(const char *path);
int stat_verify_socket(const struct stat *st);
int stat_verify_linked(const struct stat *st);
int fd_verify_linked(int fd);

View File

@ -161,12 +161,17 @@ static int tempfn_build(const char *p, const char *pre, const char *post, bool c
if (!d)
return -ENOMEM;
} else {
r = path_split_prefix_filename(p, &d, &fn);
r = path_extract_directory(p, &d);
if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → No directory specified, just a filename */
return r;
r = path_extract_filename(p, &fn);
if (r < 0)
return r;
/* Truncate the filename if it would become too long after mangling. */
strshorten(fn, NAME_MAX - len_add);
if (strlen(fn) > NAME_MAX - len_add)
/* We cannot simply prepend and append strings to the filename. Let's truncate the filename. */
fn[NAME_MAX - len_add] = '\0';
}
nf = strjoin(".#", strempty(pre), strempty(fn), strempty(post));

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "shared-forward.h"
int verb_install(int argc, char *argv[], void *userdata);
int verb_remove(int argc, char *argv[], void *userdata);
int verb_is_installed(int argc, char *argv[], void *userdata);
int vl_method_install(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);

View File

@ -75,8 +75,6 @@ int get_file_version(int fd, char **ret) {
assert(fd >= 0);
assert(ret);
/* Does not reposition file offset (as it uses mmap()) */
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat EFI binary: %m");

View File

@ -31,7 +31,6 @@
#include "parse-argument.h"
#include "path-util.h"
#include "pretty-print.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
@ -40,6 +39,12 @@
#include "verbs.h"
#include "virt.h"
/* EFI_BOOT_OPTION_DESCRIPTION_MAX sets the maximum length for the boot option description
* stored in NVRAM. The UEFI spec does not specify a minimum or maximum length for this
* string, but we limit the length to something reasonable to prevent from the firmware
* having to deal with a potentially too long string. */
#define EFI_BOOT_OPTION_DESCRIPTION_MAX ((size_t) 255)
static GracefulMode _arg_graceful = ARG_GRACEFUL_NO;
char *arg_esp_path = NULL;
@ -64,7 +69,6 @@ char *arg_root = NULL;
char *arg_image = NULL;
InstallSource arg_install_source = INSTALL_SOURCE_AUTO;
char *arg_efi_boot_option_description = NULL;
bool arg_efi_boot_option_description_with_device = false;
bool arg_dry_run = false;
ImagePolicy *arg_image_policy = NULL;
bool arg_varlink = false;
@ -89,14 +93,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_certificate_source, freep);
STATIC_DESTRUCTOR_REGISTER(arg_private_key, freep);
STATIC_DESTRUCTOR_REGISTER(arg_private_key_source, freep);
static const char* const install_source_table[_INSTALL_SOURCE_MAX] = {
[INSTALL_SOURCE_IMAGE] = "image",
[INSTALL_SOURCE_HOST] = "host",
[INSTALL_SOURCE_AUTO] = "auto",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(install_source, InstallSource);
int acquire_esp(
int unprivileged_mode,
bool graceful,
@ -344,8 +340,6 @@ static int help(int argc, char *argv[], void *userdata) {
" Install all supported EFI architectures\n"
" --efi-boot-option-description=DESCRIPTION\n"
" Description of the entry in the boot option list\n"
" --efi-boot-option-description-with-device=yes\n"
" Suffix description with disk vendor/model/serial\n"
" --dry-run Dry run (unlink and cleanup)\n"
" --secure-boot-auto-enroll=yes|no\n"
" Set up secure boot auto-enrollment\n"
@ -395,7 +389,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_JSON,
ARG_ARCH_ALL,
ARG_EFI_BOOT_OPTION_DESCRIPTION,
ARG_EFI_BOOT_OPTION_DESCRIPTION_WITH_DEVICE,
ARG_DRY_RUN,
ARG_PRINT_LOADER_PATH,
ARG_PRINT_STUB_PATH,
@ -434,7 +427,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "json", required_argument, NULL, ARG_JSON },
{ "all-architectures", no_argument, NULL, ARG_ARCH_ALL },
{ "efi-boot-option-description", required_argument, NULL, ARG_EFI_BOOT_OPTION_DESCRIPTION },
{ "efi-boot-option-description-with-device", required_argument, NULL, ARG_EFI_BOOT_OPTION_DESCRIPTION_WITH_DEVICE },
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
{ "secure-boot-auto-enroll", required_argument, NULL, ARG_SECURE_BOOT_AUTO_ENROLL },
{ "certificate", required_argument, NULL, ARG_CERTIFICATE },
@ -489,14 +481,18 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
case ARG_INSTALL_SOURCE: {
InstallSource is = install_source_from_string(optarg);
if (is < 0)
return log_error_errno(is, "Unexpected parameter for --install-source=: %s", optarg);
case ARG_INSTALL_SOURCE:
if (streq(optarg, "auto"))
arg_install_source = INSTALL_SOURCE_AUTO;
else if (streq(optarg, "image"))
arg_install_source = INSTALL_SOURCE_IMAGE;
else if (streq(optarg, "host"))
arg_install_source = INSTALL_SOURCE_HOST;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unexpected parameter for --install-source=: %s", optarg);
arg_install_source = is;
break;
}
case 'p':
arg_print_esp_path = true;
@ -576,7 +572,9 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_EFI_BOOT_OPTION_DESCRIPTION:
if (isempty(optarg) || !(string_is_safe(optarg) && utf8_is_valid(optarg))) {
_cleanup_free_ char *escaped = cescape(optarg);
_cleanup_free_ char *escaped = NULL;
escaped = cescape(optarg);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid --efi-boot-option-description=: %s", strna(escaped));
}
@ -589,13 +587,6 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
case ARG_EFI_BOOT_OPTION_DESCRIPTION_WITH_DEVICE:
r = parse_boolean_argument("--efi-boot-option-description-with-device=", optarg, &arg_efi_boot_option_description_with_device);
if (r < 0)
return r;
break;
case ARG_DRY_RUN:
arg_dry_run = true;
break;
@ -720,7 +711,7 @@ static int vl_server(void) {
r = varlink_server_new(
&varlink_server,
SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ALLOW_FD_PASSING_INPUT,
SD_VARLINK_SERVER_ROOT_ONLY,
/* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
@ -733,8 +724,7 @@ static int vl_server(void) {
varlink_server,
"io.systemd.BootControl.ListBootEntries", vl_method_list_boot_entries,
"io.systemd.BootControl.SetRebootToFirmware", vl_method_set_reboot_to_firmware,
"io.systemd.BootControl.GetRebootToFirmware", vl_method_get_reboot_to_firmware,
"io.systemd.BootControl.Install", vl_method_install);
"io.systemd.BootControl.GetRebootToFirmware", vl_method_get_reboot_to_firmware);
if (r < 0)
return log_error_errno(r, "Failed to bind Varlink methods: %m");

View File

@ -37,7 +37,6 @@ extern char *arg_root;
extern char *arg_image;
extern InstallSource arg_install_source;
extern char *arg_efi_boot_option_description;
extern bool arg_efi_boot_option_description_with_device;
extern bool arg_dry_run;
extern ImagePolicy *arg_image_policy;
extern bool arg_varlink;
@ -60,9 +59,3 @@ int acquire_esp(int unprivileged_mode, bool graceful, uint32_t *ret_part, uint64
int acquire_xbootldr(int unprivileged_mode, sd_id128_t *ret_uuid, dev_t *ret_devid);
bool touch_variables(void);
/* EFI_BOOT_OPTION_DESCRIPTION_MAX sets the maximum length for the boot option description
* stored in NVRAM. The UEFI spec does not specify a minimum or maximum length for this
* string, but we limit the length to something reasonable to prevent from the firmware
* having to deal with a potentially too long string. */
#define EFI_BOOT_OPTION_DESCRIPTION_MAX ((size_t) 255)

View File

@ -328,52 +328,6 @@ void manager_process_native_message(
} while (r == 0);
}
static size_t entry_size_max_by_ucred(Manager *m, const struct ucred *ucred, const char *label) {
static uint64_t entry_size_max = UINT64_MAX;
static bool entry_size_max_checked = false;
int r;
if (entry_size_max != UINT64_MAX)
return entry_size_max;
if (!entry_size_max_checked) {
const char *p;
entry_size_max_checked = true;
p = secure_getenv("SYSTEMD_JOURNAL_FD_SIZE_MAX");
if (p) {
r = parse_size(p, 1024, &entry_size_max);
if (r < 0)
log_warning_errno(r, "Failed to parse $SYSTEMD_JOURNAL_FD_SIZE_MAX, ignoring: %m");
else
return entry_size_max;
}
}
/* Check for unprivileged senders, as the default limit of 768M is quite high and the socket is
* unprivileged, to avoid abuses. */
if (!ucred)
return ENTRY_SIZE_UNPRIV_MAX;
if (ucred->uid == 0) /* Shortcut for root senders */
return ENTRY_SIZE_MAX;
/* As an exception, allow coredumps to use the old max size for backward compatibility */
if (pid_is_valid(ucred->pid)) {
ClientContext *context = NULL;
r = client_context_get(m, ucred->pid, ucred, label, /* unit_id= */ NULL, &context);
if (r < 0)
log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
"Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
ucred->pid);
else if (context->unit && startswith(context->unit, "systemd-coredump@"))
return ENTRY_SIZE_MAX;
}
return ENTRY_SIZE_UNPRIV_MAX;
}
int manager_process_native_file(
Manager *m,
int fd,
@ -438,7 +392,7 @@ int manager_process_native_file(
/* When !sealed, set a lower memory limit. We have to read the file, effectively doubling memory
* use. */
if ((size_t) st.st_size > entry_size_max_by_ucred(m, ucred, label) / (sealed ? 1 : 2))
if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2))
return log_ratelimit_error_errno(SYNTHETIC_ERRNO(EFBIG), JOURNAL_LOG_RATELIMIT,
"File passed too large (%"PRIu64" bytes), refusing.",
(uint64_t) st.st_size);

View File

@ -51,16 +51,12 @@ static char *arg_root = NULL;
static char *arg_image = NULL;
static ImagePolicy *arg_image_policy = NULL;
static bool arg_legend = true;
static BootEntryTokenType arg_entry_token_type = BOOT_ENTRY_TOKEN_AUTO;
static char *arg_entry_token = NULL;
static BootEntryType arg_boot_entry_type = _BOOT_ENTRY_TYPE_INVALID;
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep);
typedef enum Action {
ACTION_ADD,
@ -113,15 +109,7 @@ typedef struct Context {
char **envp;
} Context;
#define CONTEXT_NULL \
(Context) { \
.rfd = XAT_FDROOT, \
.action = _ACTION_INVALID, \
.kernel_image_type = _KERNEL_IMAGE_TYPE_INVALID, \
.layout = _LAYOUT_INVALID, \
.entry_type = _BOOT_ENTRY_TYPE_INVALID, \
.entry_token_type = _BOOT_ENTRY_TOKEN_TYPE_INVALID, \
}
#define CONTEXT_NULL (Context) { .rfd = -EBADF }
static void context_done(Context *c) {
assert(c);
@ -441,6 +429,20 @@ static int context_set_initrds(Context *c, char* const* strv) {
return context_set_path_strv(c, strv, "command line", "initrds", &c->initrds);
}
static int context_set_entry_type(Context *c, const char *s) {
assert(c);
BootEntryType e;
if (isempty(s) || streq(s, "all")) {
c->entry_type = _BOOT_ENTRY_TYPE_INVALID;
return 0;
}
e = boot_entry_type_from_string(s);
if (e < 0)
return log_error_errno(e, "Invalid entry type: %s", s);
c->entry_type = e;
return 1;
}
static int context_load_environment(Context *c) {
assert(c);
@ -693,16 +695,11 @@ static int context_load_plugins(Context *c) {
return 0;
}
static int context_setup(Context *c) {
static int context_init(Context *c) {
int r;
assert(c);
if (c->kernel_image_type < 0)
c->kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN;
if (c->entry_token_type < 0)
c->entry_token_type = BOOT_ENTRY_TOKEN_AUTO;
r = context_open_root(c);
if (r < 0)
return r;
@ -738,24 +735,6 @@ static int context_setup(Context *c) {
return 0;
}
static int context_from_cmdline(Context *c, Action action) {
int r;
assert(c);
c->action = action;
c->entry_type = arg_boot_entry_type;
r = free_and_strdup_warn(&c->entry_token, arg_entry_token);
if (r < 0)
return r;
c->entry_token_type = arg_entry_token_type;
return context_setup(c);
}
static int context_inspect_kernel(Context *c) {
assert(c);
@ -789,18 +768,9 @@ static int context_ensure_layout(Context *c) {
if (!srel_path)
return log_oom();
_cleanup_fclose_ FILE *f = NULL;
r = chase_and_fopenat_unlocked(c->rfd, srel_path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, "re", /* ret_path= */ NULL, &f);
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to open '%s': %m", srel_path);
} else {
_cleanup_free_ char *srel = NULL;
r = read_line(f, LONG_LINE_MAX, &srel);
if (r < 0)
return log_error_errno(r, "Failed to read %s: %m", srel_path);
r = read_one_line_file_at(c->rfd, srel_path, &srel);
if (r >= 0) {
if (streq(srel, "type1"))
/* The loader/entries.srel file clearly indicates that the installed boot loader
* implements the proper standard upstream boot loader spec for Type #1 entries.
@ -814,17 +784,17 @@ static int context_ensure_layout(Context *c) {
log_debug("%s with '%s' found, using layout=%s.", srel_path, srel, layout_to_string(c->layout));
return 0;
}
} else if (r != -ENOENT)
return log_error_errno(r, "Failed to read %s: %m", srel_path);
_cleanup_free_ char *entry_token_path = path_join(c->boot_root, c->entry_token);
if (!entry_token_path)
return log_oom();
r = chaseat(c->rfd, entry_token_path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_DIRECTORY, /* ret_path= */ NULL, /* ret_fd= */ NULL);
if (r < 0) {
if (!IN_SET(r, -ENOENT, -ENOTDIR))
return log_error_errno(r, "Failed to check if '%s' exists and is a directory: %m", entry_token_path);
} else {
r = is_dir_at(c->rfd, entry_token_path, /* follow= */ false);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to check if '%s' is a directory: %m", entry_token_path);
if (r > 0) {
/* If the metadata in $BOOT_ROOT doesn't tell us anything, then check if the entry token
* directory already exists. If so, let's assume it's the standard boot loader spec, too. */
c->layout = LAYOUT_BLS;
@ -1121,26 +1091,6 @@ static bool bypass(void) {
return should_bypass("KERNEL_INSTALL");
}
static int kernel_from_version(const char *version, char **ret_kernel) {
_cleanup_free_ char *vmlinuz = NULL;
int r;
assert(version);
vmlinuz = path_join("/usr/lib/modules/", version, "/vmlinuz");
if (!vmlinuz)
return log_oom();
r = access_nofollow(vmlinuz, F_OK);
if (r == -ENOENT)
return log_error_errno(r, "Kernel image not installed to '%s', specify kernel kernel image path explicitly.", vmlinuz);
if (r < 0)
return log_error_errno(r, "Failed to determine if kernel image is installed to '%s': %m", vmlinuz);
*ret_kernel = TAKE_PTR(vmlinuz);
return 0;
}
static int do_add(
Context *c,
const char *version,
@ -1150,21 +1100,8 @@ static int do_add(
int r;
assert(c);
struct utsname un;
if (!version) {
assert_se(uname(&un) >= 0);
version = un.release;
}
_cleanup_free_ char *vmlinuz = NULL;
if (!kernel) {
r = kernel_from_version(version, &vmlinuz);
if (r < 0)
return r;
kernel = vmlinuz;
}
assert(version);
assert(kernel);
r = context_set_version(c, version);
if (r < 0)
@ -1185,9 +1122,32 @@ static int do_add(
return context_execute(c);
}
static int kernel_from_version(const char *version, char **ret_kernel) {
_cleanup_free_ char *vmlinuz = NULL;
int r;
assert(version);
vmlinuz = path_join("/usr/lib/modules/", version, "/vmlinuz");
if (!vmlinuz)
return log_oom();
r = access_nofollow(vmlinuz, F_OK);
if (r == -ENOENT)
return log_error_errno(r, "Kernel image not installed to '%s', requiring manual kernel image path specification.", vmlinuz);
if (r < 0)
return log_error_errno(r, "Failed to determine if kernel image is installed to '%s': %m", vmlinuz);
*ret_kernel = TAKE_PTR(vmlinuz);
return 0;
}
static int verb_add(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
_cleanup_free_ char *vmlinuz = NULL;
const char *version, *kernel;
char **initrds;
struct utsname un;
int r;
assert(argv);
@ -1198,10 +1158,7 @@ static int verb_add(int argc, char *argv[], void *userdata) {
if (bypass())
return 0;
_cleanup_(context_done) Context c = CONTEXT_NULL;
r = context_from_cmdline(&c, ACTION_ADD);
if (r < 0)
return r;
c->action = ACTION_ADD;
/* We use the same order of arguments that "inspect" introduced, i.e. if only on argument is
* specified we take it as the kernel path, not the version, i.e. it's the first argument that is
@ -1211,10 +1168,24 @@ static int verb_add(int argc, char *argv[], void *userdata) {
(argc > 1 ? empty_or_dash_to_null(argv[1]) : NULL);
initrds = strv_skip(argv, 3);
return do_add(&c, version, kernel, initrds);
if (!version) {
assert_se(uname(&un) >= 0);
version = un.release;
}
if (!kernel) {
r = kernel_from_version(version, &vmlinuz);
if (r < 0)
return r;
kernel = vmlinuz;
}
return do_add(c, version, kernel, initrds);
}
static int verb_add_all(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
_cleanup_close_ int fd = -EBADF;
size_t n = 0;
int ret = 0, r;
@ -1227,12 +1198,9 @@ static int verb_add_all(int argc, char *argv[], void *userdata) {
if (bypass())
return 0;
_cleanup_(context_done) Context c = CONTEXT_NULL;
r = context_from_cmdline(&c, ACTION_ADD);
if (r < 0)
return r;
c->action = ACTION_ADD;
fd = chase_and_openat(c.rfd, "/usr/lib/modules", CHASE_AT_RESOLVE_IN_ROOT, O_DIRECTORY|O_RDONLY|O_CLOEXEC, NULL);
fd = chase_and_openat(c->rfd, "/usr/lib/modules", CHASE_AT_RESOLVE_IN_ROOT, O_DIRECTORY|O_RDONLY|O_CLOEXEC, NULL);
if (fd < 0)
return log_error_errno(fd, "Failed to open %s/usr/lib/modules/: %m", strempty(arg_root));
@ -1266,7 +1234,7 @@ static int verb_add_all(int argc, char *argv[], void *userdata) {
_cleanup_(context_done) Context copy = CONTEXT_NULL;
r = context_copy(&c, &copy);
r = context_copy(c, &copy);
if (r < 0)
return log_error_errno(r, "Failed to copy execution context: %m");
@ -1294,17 +1262,18 @@ static int verb_add_all(int argc, char *argv[], void *userdata) {
return ret;
}
static int run_as_installkernel(int argc, char *argv[]) {
static int run_as_installkernel(int argc, char *argv[], Context *c) {
/* kernel's install.sh invokes us as
* /sbin/installkernel <version> <vmlinuz> <map> <installation-dir>
* We ignore the last two arguments. */
if (optind + 2 > argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "'installkernel' command requires at least two arguments.");
return verb_add(3, STRV_MAKE("add", argv[optind], argv[optind+1]), /* userdata= */ NULL);
return verb_add(3, STRV_MAKE("add", argv[optind], argv[optind+1]), c);
}
static int verb_remove(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
int r;
assert(argc >= 2);
@ -1320,27 +1289,25 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
if (bypass())
return 0;
_cleanup_(context_done) Context c = CONTEXT_NULL;
r = context_from_cmdline(&c, ACTION_REMOVE);
if (r < 0)
return r;
c->action = ACTION_REMOVE;
/* Note, we do not automatically derive the kernel version to remove from uname() here (unlike we do
* it for the "add" verb), since we don't want to make it too easy to uninstall your running
* kernel, as a safety precaution */
r = context_set_version(&c, argv[1]);
r = context_set_version(c, argv[1]);
if (r < 0)
return r;
r = context_prepare_execution(&c);
r = context_prepare_execution(c);
if (r < 0)
return r;
return context_execute(&c);
return context_execute(c);
}
static int verb_inspect(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
_cleanup_(table_unrefp) Table *t = NULL;
_cleanup_free_ char *vmlinuz = NULL;
const char *version, *kernel;
@ -1348,10 +1315,7 @@ static int verb_inspect(int argc, char *argv[], void *userdata) {
struct utsname un;
int r;
_cleanup_(context_done) Context c = CONTEXT_NULL;
r = context_from_cmdline(&c, ACTION_INSPECT);
if (r < 0)
return r;
c->action = ACTION_INSPECT;
/* When only a single parameter is specified 'inspect' it's the kernel image path, and not the kernel
* version. i.e. it's the first argument that is optional, not the 2nd. That's a bit unfortunate, but
@ -1376,19 +1340,19 @@ static int verb_inspect(int argc, char *argv[], void *userdata) {
kernel = vmlinuz;
}
r = context_set_version(&c, version);
r = context_set_version(c, version);
if (r < 0)
return r;
r = context_set_kernel(&c, kernel);
r = context_set_kernel(c, kernel);
if (r < 0)
return r;
r = context_set_initrds(&c, initrds);
r = context_set_initrds(c, initrds);
if (r < 0)
return r;
r = context_prepare_execution(&c);
r = context_prepare_execution(c);
if (r < 0)
return r;
@ -1398,40 +1362,40 @@ static int verb_inspect(int argc, char *argv[], void *userdata) {
r = table_add_many(t,
TABLE_FIELD, "Machine ID",
TABLE_ID128, c.machine_id,
TABLE_ID128, c->machine_id,
TABLE_FIELD, "Kernel Image Type",
TABLE_STRING, kernel_image_type_to_string(c.kernel_image_type),
TABLE_STRING, kernel_image_type_to_string(c->kernel_image_type),
TABLE_FIELD, "Layout",
TABLE_STRING, context_get_layout(&c),
TABLE_STRING, context_get_layout(c),
TABLE_FIELD, "Boot Root",
TABLE_STRING, c.boot_root,
TABLE_STRING, c->boot_root,
TABLE_FIELD, "Entry Token Type",
TABLE_STRING, boot_entry_token_type_to_string(c.entry_token_type),
TABLE_STRING, boot_entry_token_type_to_string(c->entry_token_type),
TABLE_FIELD, "Entry Token",
TABLE_STRING, c.entry_token,
TABLE_STRING, c->entry_token,
TABLE_FIELD, "Entry Directory",
TABLE_STRING, c.entry_dir,
TABLE_STRING, c->entry_dir,
TABLE_FIELD, "Kernel Version",
TABLE_VERSION, c.version,
TABLE_VERSION, c->version,
TABLE_FIELD, "Kernel",
TABLE_STRING, c.kernel,
TABLE_STRING, c->kernel,
TABLE_FIELD, "Initrds",
TABLE_STRV, c.initrds,
TABLE_STRV, c->initrds,
TABLE_FIELD, "Initrd Generator",
TABLE_STRING, c.initrd_generator,
TABLE_STRING, c->initrd_generator,
TABLE_FIELD, "UKI Generator",
TABLE_STRING, c.uki_generator,
TABLE_STRING, c->uki_generator,
TABLE_FIELD, "Plugins",
TABLE_STRV, c.plugins,
TABLE_STRV, c->plugins,
TABLE_FIELD, "Plugin Environment",
TABLE_STRV, c.envp);
TABLE_STRV, c->envp);
if (r < 0)
return table_log_add_error(r);
if (!sd_json_format_enabled(arg_json_format_flags)) {
r = table_add_many(t,
TABLE_FIELD, "Plugin Arguments",
TABLE_STRV, strv_skip(c.argv, 1));
TABLE_STRV, strv_skip(c->argv, 1));
if (r < 0)
return table_log_add_error(r);
}
@ -1454,15 +1418,11 @@ static int verb_inspect(int argc, char *argv[], void *userdata) {
}
static int verb_list(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
_cleanup_close_ int fd = -EBADF;
int r;
_cleanup_(context_done) Context c = CONTEXT_NULL;
r = context_from_cmdline(&c, ACTION_INSPECT);
if (r < 0)
return r;
fd = chase_and_openat(c.rfd, "/usr/lib/modules", CHASE_AT_RESOLVE_IN_ROOT, O_DIRECTORY|O_RDONLY|O_CLOEXEC, NULL);
fd = chase_and_openat(c->rfd, "/usr/lib/modules", CHASE_AT_RESOLVE_IN_ROOT, O_DIRECTORY|O_RDONLY|O_CLOEXEC, NULL);
if (fd < 0)
return log_error_errno(fd, "Failed to open %s/usr/lib/modules/: %m", strempty(arg_root));
@ -1572,7 +1532,7 @@ static int help(void) {
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static int parse_argv(int argc, char *argv[], Context *c) {
enum {
ARG_VERSION = 0x100,
ARG_NO_LEGEND,
@ -1608,6 +1568,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
assert(c);
while ((t = getopt_long(argc, argv, "hv", options, NULL)) >= 0)
switch (t) {
@ -1651,7 +1612,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_ENTRY_TOKEN:
r = parse_boot_entry_token_type(optarg, &arg_entry_token_type, &arg_entry_token);
r = parse_boot_entry_token_type(optarg, &c->entry_token_type, &c->entry_token);
if (r < 0)
return r;
break;
@ -1684,18 +1645,11 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
case ARG_BOOT_ENTRY_TYPE: {
if (isempty(optarg) || streq(optarg, "all")) {
arg_boot_entry_type = _BOOT_ENTRY_TYPE_INVALID;
case ARG_BOOT_ENTRY_TYPE:
r = context_set_entry_type(c, optarg);
if (r < 0)
return r;
break;
}
BootEntryType e = boot_entry_type_from_string(optarg);
if (e < 0)
return log_error_errno(e, "Invalid entry type: %s", optarg);
arg_boot_entry_type = e;
break;
}
case '?':
return -EINVAL;
@ -1710,7 +1664,7 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
static int kernel_install_main(int argc, char *argv[]) {
static int run(int argc, char* argv[]) {
static const Verb verbs[] = {
{ "add", 1, VERB_ANY, 0, verb_add },
{ "add-all", 1, 1, 0, verb_add_all },
@ -1719,21 +1673,24 @@ static int kernel_install_main(int argc, char *argv[]) {
{ "list", 1, 1, 0, verb_list },
{}
};
return dispatch_verb(argc, argv, verbs, /* userdata= */ NULL);
}
static int run(int argc, char* argv[]) {
_cleanup_(context_done) Context c = {
.rfd = AT_FDCWD,
.action = _ACTION_INVALID,
.kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN,
.layout = _LAYOUT_INVALID,
.entry_type = _BOOT_ENTRY_TYPE_INVALID,
.entry_token_type = BOOT_ENTRY_TOKEN_AUTO,
};
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(umount_and_freep) char *mounted_dir = NULL;
int r;
log_setup();
r = parse_argv(argc, argv);
r = parse_argv(argc, argv, &c);
if (r <= 0)
return r;
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_cleanup_(umount_and_freep) char *mounted_dir = NULL;
if (arg_image) {
assert(!arg_root);
@ -1756,10 +1713,14 @@ static int run(int argc, char* argv[]) {
return log_oom();
}
if (invoked_as(argv, "installkernel"))
return run_as_installkernel(argc, argv);
r = context_init(&c);
if (r < 0)
return r;
return kernel_install_main(argc, argv);
if (invoked_as(argv, "installkernel"))
return run_as_installkernel(argc, argv, &c);
return dispatch_verb(argc, argv, verbs, &c);
}
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);

View File

@ -387,19 +387,6 @@ _public_ int sd_journal_stream_fd_with_namespace(
assert_return(priority >= 0, -EINVAL);
assert_return(priority <= 7, -EINVAL);
if (name_space) {
/* If $LOG_NAMESPACE is set, we're already placed in a mountns with /run/systemd/journal/
* being a bind mount for the journald namespace instance, in which case we shall go by
* the standard journal socket path. */
const char *env = secure_getenv("LOG_NAMESPACE");
if (env) {
if (!streq(name_space, env))
return -EREMOTE;
name_space = NULL;
}
}
path = journal_stream_path(name_space);
if (!path)
return -EINVAL;

View File

@ -801,18 +801,11 @@ static DirectoryOwnership validate_directory_fd(
* check if the directory is owned by the peer UID or by the foreign UID range (in the latter case
* one of the parent directories must be owned by the peer though). */
struct statx stx;
r = xstatx_full(fd,
/* path= */ NULL,
AT_EMPTY_PATH,
/* mandatory_mask= */ STATX_TYPE|STATX_UID|STATX_MNT_ID|STATX_INO,
/* optional_mask= */ 0,
/* mandatory_attributes= */ STATX_ATTR_MOUNT_ROOT,
&stx);
if (r < 0)
return log_debug_errno(r, "Failed to statx() directory fd: %m");
struct stat st;
if (fstat(fd, &st) < 0)
return log_debug_errno(errno, "Failed to stat() directory fd: %m");
r = statx_verify_directory(&stx);
r = stat_verify_directory(&st);
if (r < 0)
return r;
@ -820,8 +813,8 @@ static DirectoryOwnership validate_directory_fd(
if (fl < 0)
return log_debug_errno(fl, "Directory file descriptor has unsafe flags set: %m");
if (stx.stx_uid == 0) {
*ret_current_owner_uid = stx.stx_uid;
if (st.st_uid == 0) {
*ret_current_owner_uid = st.st_uid;
if (peer_uid == 0) {
log_debug("Directory file descriptor points to root owned directory (%s), who is also the peer.", strna(path));
return DIRECTORY_IS_ROOT_PEER_OWNED;
@ -829,9 +822,9 @@ static DirectoryOwnership validate_directory_fd(
log_debug("Directory file descriptor points to root owned directory (%s).", strna(path));
return DIRECTORY_IS_ROOT_OWNED;
}
if (stx.stx_uid == peer_uid) {
if (st.st_uid == peer_uid) {
log_debug("Directory file descriptor points to peer owned directory (%s).", strna(path));
*ret_current_owner_uid = stx.stx_uid;
*ret_current_owner_uid = st.st_uid;
return DIRECTORY_IS_PEER_OWNED;
}
@ -842,24 +835,17 @@ static DirectoryOwnership validate_directory_fd(
_cleanup_close_ int parent_fd = -EBADF;
unsigned n_level;
for (n_level = 0; n_level < 16; n_level++) {
/* Do not go above bind mounts */
if (FLAGS_SET(stx.stx_attributes, STATX_ATTR_MOUNT_ROOT)) {
log_debug("Directory is a mount point, not checking for parent's ownership.");
*ret_current_owner_uid = stx.stx_uid;
return DIRECTORY_IS_OTHERWISE_OWNED;
}
/* Stop iteration if we find a directory up the tree that is neither owned by the user, nor is from the foreign UID range */
if (!uid_is_foreign(stx.stx_uid) || !gid_is_foreign(stx.stx_gid)) {
if (!uid_is_foreign(st.st_uid) || !gid_is_foreign(st.st_gid)) {
log_debug("Directory file descriptor points to directory which itself or its parents is neither owned by foreign UID range nor by the user.");
*ret_current_owner_uid = stx.stx_uid;
*ret_current_owner_uid = st.st_uid;
return DIRECTORY_IS_OTHERWISE_OWNED;
}
/* If the peer is root, then it doesn't matter if we find a parent owned by root, let's shortcut things. */
if (peer_uid == 0) {
log_debug("Directory referenced by file descriptor is owned by foreign UID range, and peer is root.");
*ret_current_owner_uid = stx.stx_uid;
*ret_current_owner_uid = st.st_uid;
return DIRECTORY_IS_FOREIGN_OWNED;
}
@ -868,46 +854,29 @@ static DirectoryOwnership validate_directory_fd(
if (new_parent_fd < 0)
return log_debug_errno(errno, "Failed to open parent directory of directory file descriptor: %m");
struct statx new_stx;
r = xstatx_full(new_parent_fd,
/* path= */ NULL,
AT_EMPTY_PATH,
/* mandatory_mask= */ STATX_UID|STATX_MNT_ID|STATX_INO,
/* optional_mask= */ 0,
/* mandatory_attributes= */ STATX_ATTR_MOUNT_ROOT,
&new_stx);
if (r < 0)
return log_debug_errno(r, "Failed to statx() parent directory of directory file descriptor: %m");
struct stat new_st;
if (fstat(new_parent_fd, &new_st) < 0)
return log_debug_errno(errno, "Failed to stat parent directory of directory file descriptor: %m");
/* Safety check to see if we hit the root dir */
if (statx_inode_same(&stx, &new_stx)) {
if (stat_inode_same(&st, &new_st)) {
log_debug("Directory file descriptor is owned by foreign UID range, but didn't find parent directory that is owned by peer among ancestors.");
*ret_current_owner_uid = stx.stx_uid;
*ret_current_owner_uid = st.st_uid;
return DIRECTORY_IS_OTHERWISE_OWNED;
}
if (stx.stx_mnt_id != new_stx.stx_mnt_id) {
/* NB, this check is probably redundant, given we also check
* STATX_ATTR_MOUNT_ROOT. The only reason we have it here is to provide extra safety
* in case the mount tree is rearranged concurrently with our traversal, so that
* STATX_ATTR_MOUNT_ROOT might be out of date. */
log_debug("Won't cross mount boundaries, not checking for parent's ownership.");
*ret_current_owner_uid = stx.stx_uid;
return DIRECTORY_IS_OTHERWISE_OWNED;
}
if (new_stx.stx_uid == peer_uid) { /* Parent inode is owned by the peer. That's good! Everything's fine. */
if (new_st.st_uid == peer_uid) { /* Parent inode is owned by the peer. That's good! Everything's fine. */
log_debug("Directory file descriptor is owned by foreign UID range, and ancestor is owned by peer.");
*ret_current_owner_uid = stx.stx_uid;
*ret_current_owner_uid = st.st_uid;
return DIRECTORY_IS_FOREIGN_OWNED;
}
close_and_replace(parent_fd, new_parent_fd);
stx = new_stx;
st = new_st;
}
log_debug("Failed to find peer owned parent directory after %u levels, refusing.", n_level);
*ret_current_owner_uid = stx.stx_uid;
*ret_current_owner_uid = st.st_uid;
return DIRECTORY_IS_OTHERWISE_OWNED;
}

View File

@ -12,28 +12,22 @@
#include "fd-util.h"
#include "log.h"
#include "main-func.h"
#include "parse-argument.h"
#include "path-lookup.h"
#include "pretty-print.h"
#include "runtime-scope.h"
#include "set.h"
#include "sort-util.h"
#include "string-util.h"
#include "time-util.h"
#include "varlink-util.h"
#define METRICS_MAX 1024U
#define METRICS_LINKS_MAX 128U
#define MAX_CONCURRENT_METRICS_SOCKETS 20
#define TIMEOUT_USEC (30 * USEC_PER_SEC) /* 30 seconds */
static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO;
typedef struct Context {
sd_event *event;
Set *links;
unsigned n_open_connections;
sd_json_variant **metrics; /* Collected metrics for sorting */
size_t n_metrics, n_skipped_metrics;
size_t n_metrics;
} Context;
static int metric_compare(sd_json_variant *const *a, sd_json_variant *const *b) {
@ -86,11 +80,6 @@ static int metrics_on_query_reply(
else
log_error("Varlink error: %s", error_id);
} else {
if (context->n_metrics >= METRICS_MAX) {
context->n_skipped_metrics++;
return 0;
}
/* Collect metrics for later sorting */
if (!GREEDY_REALLOC(context->metrics, context->n_metrics + 1))
return log_oom();
@ -98,22 +87,24 @@ static int metrics_on_query_reply(
}
if (!FLAGS_SET(flags, SD_VARLINK_REPLY_CONTINUES)) {
assert_se(set_remove(context->links, link) == link);
link = sd_varlink_close_unref(link);
assert(context->n_open_connections > 0);
context->n_open_connections--;
if (set_isempty(context->links))
(void) sd_event_exit(context->event, EXIT_SUCCESS);
if (context->n_open_connections == 0)
(void) sd_event_exit(ASSERT_PTR(sd_varlink_get_event(link)), EXIT_SUCCESS);
}
return 0;
}
static int metrics_call(Context *context, const char *path) {
static int metrics_call(const char *path, sd_event *event, sd_varlink **ret, Context *context) {
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
int r;
assert(context);
assert(path);
assert(event);
assert(ret);
assert(context);
r = sd_varlink_connect_address(&vl, path);
if (r < 0)
@ -125,7 +116,7 @@ static int metrics_call(Context *context, const char *path) {
if (r < 0)
return log_error_errno(r, "Failed to set varlink timeout: %m");
r = sd_varlink_attach_event(vl, context->event, SD_EVENT_PRIORITY_NORMAL);
r = sd_varlink_attach_event(vl, event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0)
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
@ -137,42 +128,42 @@ static int metrics_call(Context *context, const char *path) {
if (r < 0)
return log_error_errno(r, "Failed to issue io.systemd.Metrics.List call: %m");
if (set_ensure_put(&context->links, &varlink_hash_ops, vl) < 0)
return log_oom();
*ret = TAKE_PTR(vl);
TAKE_PTR(vl);
return 0;
}
static void sd_varlink_unref_many(sd_varlink **array, size_t n) {
assert(array);
FOREACH_ARRAY(v, array, n)
sd_varlink_unref(*v);
free(array);
}
static void context_done(Context *context) {
assert(context);
set_free(context->links);
sd_json_variant_unref_many(context->metrics, context->n_metrics);
sd_event_unref(context->event);
for (size_t i = 0; i < context->n_metrics; i++)
sd_json_variant_unref(context->metrics[i]);
free(context->metrics);
}
static int metrics_output_sorted(Context *context) {
int r;
static void metrics_output_sorted(Context *context) {
assert(context);
typesafe_qsort(context->metrics, context->n_metrics, metric_compare);
FOREACH_ARRAY(m, context->metrics, context->n_metrics) {
r = sd_json_variant_dump(
FOREACH_ARRAY(m, context->metrics, context->n_metrics)
sd_json_variant_dump(
*m,
arg_json_format_flags | SD_JSON_FORMAT_FLUSH,
SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO | SD_JSON_FORMAT_FLUSH,
stdout,
/* prefix= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to write JSON: %m");
}
NULL);
if (context->n_metrics == 0)
log_info("No metrics collected.");
return 0;
log_warning("No reporting sockets found.");
}
static int metrics_query(void) {
@ -185,63 +176,58 @@ static int metrics_query(void) {
log_debug("Looking for reports in %s/", metrics_path);
_cleanup_(context_done) Context context = {};
_cleanup_closedir_ DIR *d = opendir(metrics_path);
if (!d)
return log_full_errno(errno == ENOENT ? LOG_WARNING : LOG_ERR, errno,
"Failed to open metrics directory %s: %m", metrics_path);
r = sd_event_default(&context.event);
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to get event loop: %m");
r = sd_event_set_signal_exit(context.event, true);
r = sd_event_set_signal_exit(event, true);
if (r < 0)
return log_error_errno(r, "Failed to enable exit on SIGINT/SIGTERM: %m");
size_t n_skipped_sources = 0;
_cleanup_closedir_ DIR *d = opendir(metrics_path);
if (!d) {
if (errno != ENOENT)
return log_error_errno(errno, "Failed to open metrics directory %s: %m", metrics_path);
} else {
size_t n_varlinks = MAX_CONCURRENT_METRICS_SOCKETS;
sd_varlink **varlinks = new0(sd_varlink *, n_varlinks);
if (!varlinks)
return log_oom();
CLEANUP_ARRAY(varlinks, n_varlinks, sd_varlink_unref_many);
_cleanup_(context_done) Context context = {};
FOREACH_DIRENT(de, d,
return log_warning_errno(errno, "Failed to read %s: %m", metrics_path)) {
if (!IN_SET(de->d_type, DT_SOCK, DT_UNKNOWN))
continue;
if (set_size(context.links) >= METRICS_LINKS_MAX) {
n_skipped_sources++;
break;
}
_cleanup_free_ char *p = path_join(metrics_path, de->d_name);
if (!p)
return log_oom();
(void) metrics_call(&context, p);
r = metrics_call(p, event, &varlinks[context.n_open_connections], &context);
if (r < 0)
continue;
if (++context.n_open_connections >= MAX_CONCURRENT_METRICS_SOCKETS) {
log_warning("Too many concurrent metrics sockets, stop iterating");
break;
}
}
if (set_isempty(context.links))
log_info("No metrics sources found.");
else {
r = sd_event_loop(context.event);
if (context.n_open_connections > 0) {
r = sd_event_loop(event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
r = metrics_output_sorted(&context);
if (r < 0)
return r;
if (n_skipped_sources > 0)
log_warning("Too many metrics sources, only %u sources contacted, %zu sources skipped.", set_size(context.links), n_skipped_sources);
if (context.n_skipped_metrics > 0)
log_warning("Too many metrics, only %zu metrics collected, %zu metrics skipped.", context.n_metrics, context.n_skipped_metrics);
if (n_skipped_sources > 0 ||
context.n_skipped_metrics > 0)
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
metrics_output_sorted(&context);
return 0;
}
static int help(void) {
@ -258,8 +244,6 @@ static int help(void) {
" --version Show package version\n"
" --user Connect to user service manager\n"
" --system Connect to system service manager (default)\n"
" --json=pretty|short\n"
" Configure JSON output\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@ -274,7 +258,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERSION = 0x100,
ARG_USER,
ARG_SYSTEM,
ARG_JSON,
};
static const struct option options[] = {
@ -282,41 +265,28 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "json", required_argument, NULL, ARG_JSON },
{}
};
int c, r;
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
while ((c = getopt_long(argc, argv, "hp", options, NULL)) >= 0)
switch (c) {
case 'h':
return help();
case ARG_VERSION:
return version();
case ARG_USER:
arg_runtime_scope = RUNTIME_SCOPE_USER;
break;
case ARG_SYSTEM:
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
break;
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}

View File

@ -922,7 +922,6 @@ int blockdev_get_root(int level, dev_t *ret) {
}
int partition_node_of(const char *node, unsigned nr, char **ret) {
_cleanup_free_ char *fn = NULL, *dn = NULL;
int r;
assert(node);
@ -932,12 +931,18 @@ int partition_node_of(const char *node, unsigned nr, char **ret) {
/* Given a device node path to a block device returns the device node path to the partition block
* device of the specified partition */
r = path_split_prefix_filename(node, &dn, &fn);
_cleanup_free_ char *fn = NULL;
r = path_extract_filename(node, &fn);
if (r < 0)
return r;
if (r == O_DIRECTORY)
return -EISDIR;
_cleanup_free_ char *dn = NULL;
r = path_extract_directory(node, &dn);
if (r < 0 && r != -EDESTADDRREQ) /* allow if only filename is specified */
return r;
size_t l = strlen(fn);
assert(l > 0); /* underflow check for the subtraction below */

View File

@ -155,8 +155,6 @@ int boot_entry_token_ensure_at(
assert(type);
assert(token);
/* Returns -EUNATCH if the selected token is not set */
if (*token)
return 0; /* Already set. */
@ -183,7 +181,7 @@ int boot_entry_token_ensure_at(
return r;
}
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No machine ID set, and /etc/os-release carries no ID=/IMAGE_ID= fields.");
case BOOT_ENTRY_TOKEN_MACHINE_ID:
@ -191,14 +189,14 @@ int boot_entry_token_ensure_at(
if (r != 0)
return r;
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH), "No machine ID set.");
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No machine ID set.");
case BOOT_ENTRY_TOKEN_OS_IMAGE_ID:
r = entry_token_from_os_release(rfd, type, token);
if (r != 0)
return r;
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"IMAGE_ID= field not set in /etc/os-release.");
case BOOT_ENTRY_TOKEN_OS_ID:
@ -206,12 +204,12 @@ int boot_entry_token_ensure_at(
if (r != 0)
return r;
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH),
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"ID= field not set in /etc/os-release.");
case BOOT_ENTRY_TOKEN_LITERAL:
/* In this case, the token should be already set by the user input. */
return log_error_errno(SYNTHETIC_ERRNO(EUNATCH), "Literal token indicated but not specified.");
return -EINVAL;
default:
assert_not_reached();
@ -293,4 +291,4 @@ static const char *const boot_entry_token_type_table[] = {
[BOOT_ENTRY_TOKEN_AUTO] = "auto",
};
DEFINE_STRING_TABLE_LOOKUP(boot_entry_token_type, BootEntryTokenType);
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_token_type, BootEntryTokenType);

View File

@ -34,4 +34,4 @@ int boot_entry_token_ensure_at(
int parse_boot_entry_token_type(const char *s, BootEntryTokenType *type, char **token);
DECLARE_STRING_TABLE_LOOKUP(boot_entry_token_type, BootEntryTokenType);
DECLARE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_token_type, BootEntryTokenType);

View File

@ -480,13 +480,14 @@ int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret) {
if (!path_is_absolute(e))
return -EINVAL;
r = path_split_prefix_filename(e, &_dirname, &_filename);
r = path_extract_directory(e, &_dirname);
if (r < 0)
return r;
r = path_extract_filename(e, &_filename);
if (r < 0)
return r;
if (r == O_DIRECTORY)
return -EINVAL;
/* We validate that the path is absolute above, hence dirname must be extractable. */
dirname = _dirname;
filename = _filename;
} else {
@ -497,8 +498,7 @@ int get_credential_host_secret(CredentialSecretFlags flags, struct iovec *ret) {
assert(dirname);
assert(filename);
(void) mkdir_parents(dirname, 0755);
mkdir_parents(dirname, 0755);
dfd = open_mkdir(dirname, O_CLOEXEC, 0755);
if (dfd < 0)
return log_debug_errno(dfd, "Failed to create or open directory '%s': %m", dirname);

View File

@ -109,9 +109,13 @@ int generator_add_symlink_full(
*
* If <instance> is specified, then <src> must be a template unit name, and we'll instantiate it. */
r = path_split_prefix_filename(src, &dn, &fn);
r = path_extract_directory(src, &dn);
if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → just a file name was passed */
return log_error_errno(r, "Failed to extract directory name from '%s': %m", src);
r = path_extract_filename(src, &fn);
if (r < 0)
return log_error_errno(r, "Failed to split '%s' into directory prefix and filename: %m", src);
return log_error_errno(r, "Failed to extract file name from '%s': %m", src);
if (r == O_DIRECTORY)
return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Expected path to regular file name, but got '%s', refusing.", src);

View File

@ -12,11 +12,9 @@
* See JOURNAL_SIZE_MAX in coredump.c */
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
#define ENTRY_SIZE_MAX (1024*1024*770u)
#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*32u)
#define DATA_SIZE_MAX (1024*1024*768u)
#else
#define ENTRY_SIZE_MAX (1024*1024*13u)
#define ENTRY_SIZE_UNPRIV_MAX (1024*1024*8u)
#define DATA_SIZE_MAX (1024*1024*11u)
#endif
#define LINE_CHUNK 8*1024u

View File

@ -12,8 +12,6 @@
#include "string-table.h"
#include "string-util.h"
/* Note: none of these function change the file position of the provided fd, as they use pread() */
bool pe_header_is_64bit(const PeHeader *h) {
assert(h);

View File

@ -7,7 +7,6 @@
#include "discover-image.h"
#include "log.h"
#include "mountpoint-util.h"
#include "runtime-scope.h"
#include "snapshot-util.h"
#include "signal-util.h"
#include "tmpfile-util.h"

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "shared-forward.h"
#include "runtime-scope.h"
/* create_ephemeral_snapshot - create a snapshot of the given directory.
*

View File

@ -291,15 +291,17 @@ int unit_file_resolve_symlink(
dir, dir ? "/" : "", filename);
if (!dir) {
r = path_split_prefix_filename(filename, &_dir, &_filename);
r = path_extract_directory(filename, &_dir);
if (r < 0)
return r;
dir = _dir;
r = path_extract_filename(filename, &_filename);
if (r < 0)
return r;
if (r == O_DIRECTORY)
return log_warning_errno(SYNTHETIC_ERRNO(EISDIR),
"Unexpected path to a directory \"%s\", refusing.", filename);
/* We validate that the path is absolute above, hence dir must be extractable. */
dir = ASSERT_PTR(_dir);
filename = _filename;
}

View File

@ -36,37 +36,21 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD_BY_TYPE(source, BootEntrySource, 0),
SD_VARLINK_FIELD_COMMENT("The string identifier of the entry"),
SD_VARLINK_DEFINE_FIELD(id, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the primary definition file for the entry"),
SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Directory path of the file system root the entry was found on"),
SD_VARLINK_DEFINE_FIELD(root, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The entry's title string"),
SD_VARLINK_DEFINE_FIELD(title, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The possibly mangled/augmented title to show for the entry"),
SD_VARLINK_DEFINE_FIELD(showTitle, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("An explicitly configured sorting key for the enry"),
SD_VARLINK_DEFINE_FIELD(sortKey, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The version of the entry"),
SD_VARLINK_DEFINE_FIELD(version, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Machine ID of the OS installation belonging to the entry, if known"),
SD_VARLINK_DEFINE_FIELD(machineId, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("EFI architecture name for this entry"),
SD_VARLINK_DEFINE_FIELD(architecture, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Command line options to pass to the invoked kernel or EFI binary"),
SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the Linux kernel to invoke, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(linux, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the EFI binary to invoke, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(efi, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to an UKI EFI binary to invoke, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(uki, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("An UKI profile index to invoke. If not specified defaults to the first profile."),
SD_VARLINK_DEFINE_FIELD(profile, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Path to the initrd image to pass to the invoked kernel, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(initrd, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("Devicetree file to pass to the invoked kernel, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(devicetree, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Devicetree overlay file to pass to the invoked kernel, relative to the root directory of the file system containing the entry file"),
SD_VARLINK_DEFINE_FIELD(devicetreeOverlay, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("Indicates whether the boot loader reported this entry on the current boot"),
SD_VARLINK_DEFINE_FIELD(isReported, SD_VARLINK_BOOL, 0),
@ -99,53 +83,12 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_FIELD_COMMENT("The current state of the reboot-to-firmware-UI flag"),
SD_VARLINK_DEFINE_OUTPUT(state, SD_VARLINK_BOOL, 0));
static SD_VARLINK_DEFINE_ENUM_TYPE(
Operation,
SD_VARLINK_FIELD_COMMENT("Install the boot loader afresh, creating everything it needs"),
SD_VARLINK_DEFINE_ENUM_VALUE(new),
SD_VARLINK_FIELD_COMMENT("Just update existing boot loader binaries"),
SD_VARLINK_DEFINE_ENUM_VALUE(update));
static SD_VARLINK_DEFINE_ENUM_TYPE(
BootEntryTokenType,
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on /etc/machine-id"),
SD_VARLINK_DEFINE_ENUM_VALUE(machine_id),
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on the IMAGE_ID= field from /etc/os-release"),
SD_VARLINK_DEFINE_ENUM_VALUE(os_image_id),
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on the ID= field from /etc/os-release"),
SD_VARLINK_DEFINE_ENUM_VALUE(os_id),
SD_VARLINK_FIELD_COMMENT("Pick identifiers for type #1 boot entries based on a manually chosen string"),
SD_VARLINK_DEFINE_ENUM_VALUE(literal),
SD_VARLINK_FIELD_COMMENT("Choose automatically how to pick identifiers for type #1 boot entries"),
SD_VARLINK_DEFINE_ENUM_VALUE(auto));
static SD_VARLINK_DEFINE_METHOD(
Install,
SD_VARLINK_FIELD_COMMENT("Operation, either 'new' or 'update'"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(operation, Operation, 0),
SD_VARLINK_FIELD_COMMENT("If true, continue on various failures"),
SD_VARLINK_DEFINE_INPUT(graceful, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Index into array of file descriptors passed along with this message, pointing to file descriptor to root file system to operate on"),
SD_VARLINK_DEFINE_INPUT(rootFileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Root directory to operate relative to. If both this and rootFileDescriptor is specified, this is purely informational. If only this is specified, it is what will be used."),
SD_VARLINK_DEFINE_INPUT(rootDirectory, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Selects how to identify boot entries"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(bootEntryTokenType, BootEntryTokenType, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("If true the boot loader will be registered in an EFI boot entry via EFI variables, otherwise this is omitted"),
SD_VARLINK_DEFINE_INPUT(touchVariables, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ERROR(
RebootToFirmwareNotSupported);
static SD_VARLINK_DEFINE_ERROR(
NoSuchBootEntry);
static SD_VARLINK_DEFINE_ERROR(
NoESPFound);
static SD_VARLINK_DEFINE_ERROR(
BootEntryTokenUnavailable);
SD_VARLINK_DEFINE_INTERFACE(
io_systemd_BootControl,
"io.systemd.BootControl",
@ -158,23 +101,13 @@ SD_VARLINK_DEFINE_INTERFACE(
&vl_type_BootEntryAddon,
SD_VARLINK_SYMBOL_COMMENT("A structure encapsulating a boot entry"),
&vl_type_BootEntry,
SD_VARLINK_SYMBOL_COMMENT("The operation to execute"),
&vl_type_Operation,
SD_VARLINK_SYMBOL_COMMENT("Enumerates boot entries. Method call must be called with 'more' flag set. Each response returns one entry. If no entries are defined returns the NoSuchBootEntry error."),
&vl_method_ListBootEntries,
SD_VARLINK_SYMBOL_COMMENT("Sets the reboot-to-firmware-UI flag of the firmware, if this concept exists. Returns the RebootToFirmwareNotSupported error if not."),
&vl_method_SetRebootToFirmware,
SD_VARLINK_SYMBOL_COMMENT("Gets the current state of the reboot-to-firmware-UI flag of the firmware, if this concept exists. Returns the RebootToFirmwareNotSupported error if not."),
&vl_method_GetRebootToFirmware,
SD_VARLINK_SYMBOL_COMMENT("The boot entry token type to use."),
&vl_type_BootEntryTokenType,
SD_VARLINK_SYMBOL_COMMENT("Install the boot loader on the ESP."),
&vl_method_Install,
SD_VARLINK_SYMBOL_COMMENT("SetRebootToFirmware() and GetRebootToFirmware() return this if the firmware does not actually support the reboot-to-firmware-UI concept."),
&vl_error_RebootToFirmwareNotSupported,
SD_VARLINK_SYMBOL_COMMENT("No boot entry defined."),
&vl_error_NoSuchBootEntry,
SD_VARLINK_SYMBOL_COMMENT("No EFI System Partition (ESP) found."),
&vl_error_NoESPFound,
SD_VARLINK_SYMBOL_COMMENT("The select boot entry token could not be determined."),
&vl_error_BootEntryTokenUnavailable);
&vl_error_NoSuchBootEntry);

View File

@ -25,7 +25,7 @@ if conf.get('ENABLE_SSH_PROXY_CONFIG') == 1
install : true,
install_dir : sshconfdir.startswith('/usr/') ? sshconfdir : libexecdir / 'ssh_config.d')
if (not sshconfdir.startswith(sysconfdir) or install_sysconfdir) and conf.get('LINK_SSH_PROXY_DROPIN') == 1
if conf.get('LINK_SSH_PROXY_DROPIN') == 1
if meson.version().version_compare('>=1.3.0')
install_symlink(
'20-systemd-ssh-proxy.conf',

View File

@ -26,7 +26,7 @@ int verb_preset_all(int argc, char *argv[], void *userdata) {
CLEANUP_ARRAY(changes, n_changes, install_changes_free);
r = unit_file_preset_all(arg_runtime_scope, unit_file_flags_from_args(), arg_root, arg_preset_mode, &changes, &n_changes);
/* We do not propagate failure for individual units here. */
/* We do not treat propagate failure of individual units here. */
(void) install_changes_dump(r, "preset all", changes, n_changes, arg_quiet);
if (r < 0)
return r;

View File

@ -1027,7 +1027,7 @@ TEST(last_path_component) {
}
static void test_path_extract_filename_one(const char *input, const char *output, int ret) {
_cleanup_free_ char *k = NULL, *k2 = NULL;
_cleanup_free_ char *k = NULL;
int r;
r = path_extract_filename(input, &k);
@ -1037,13 +1037,6 @@ static void test_path_extract_filename_one(const char *input, const char *output
strnull(output), ret < 0 ? STRERROR(ret) : "-");
ASSERT_STREQ(k, output);
assert_se(r == ret);
/* Extra safety check: make sure that path_split_prefix_filename() behaves the same */
r = path_split_prefix_filename(input, NULL, &k2);
if (r >= 0) {
ASSERT_STREQ(k2, k);
assert_se(r == ret);
}
}
TEST(path_extract_filename) {
@ -1078,7 +1071,7 @@ TEST(path_extract_filename) {
}
static void test_path_extract_directory_one(const char *input, const char *output, int ret) {
_cleanup_free_ char *k = NULL, *k2 = NULL;
_cleanup_free_ char *k = NULL;
int r;
r = path_extract_directory(input, &k);
@ -1089,18 +1082,10 @@ static void test_path_extract_directory_one(const char *input, const char *outpu
ASSERT_STREQ(k, output);
assert_se(r == ret);
/* Extra safety check: make sure that path_split_prefix_filename() behaves the same.
* We cant check the return value from it though as that differs based on the filename component.
* We can only assert that if path_extract_directory() fails, then
* path_split_prefix_filename() must also fail. */
r = path_split_prefix_filename(input, &k2, NULL);
ASSERT_STREQ(k2, k);
assert_se(!(ret < 0) || r < 0);
/* Extra safety check: let's make sure that if we split out the filename too (and it works) the
* joined parts are identical to the original again */
if (r >= 0) {
_cleanup_free_ char *f = NULL, *k3 = NULL, *f2 = NULL;
_cleanup_free_ char *f = NULL;
r = path_extract_filename(input, &f);
if (r >= 0) {
@ -1109,13 +1094,6 @@ static void test_path_extract_directory_one(const char *input, const char *outpu
assert_se(j = path_join(k, f));
assert_se(path_equal(input, j));
}
/* And the same, but for path_split_prefix_filename() */
r = path_split_prefix_filename(input, &k3, &f2);
if (r >= 0) {
ASSERT_STREQ(k3, k);
ASSERT_STREQ(f2, f);
}
}
}

View File

@ -32,7 +32,7 @@ if conf.get('ENABLE_SSH_USERDB_CONFIG') == 1
install : true,
install_dir : sshdconfdir.startswith('/usr/') ? sshdconfdir : libexecdir / 'sshd_config.d')
if (not sshdconfdir.startswith(sysconfdir) or install_sysconfdir) and conf.get('LINK_SSHD_USERDB_DROPIN') == 1
if conf.get('LINK_SSHD_USERDB_DROPIN') == 1
if meson.version().version_compare('>=1.3.0')
install_symlink(
'20-systemd-userdb.conf',

View File

@ -10,7 +10,6 @@
#include "build.h"
#include "bus-util.h"
#include "chase.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
@ -22,14 +21,10 @@
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
#include "pidfd-util.h"
#include "polkit-agent.h"
#include "pretty-print.h"
#include "process-util.h"
#include "recurse-dir.h"
#include "runtime-scope.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
@ -54,8 +49,6 @@ static usec_t arg_timeout = 0;
static bool arg_exec = false;
static PushFds arg_push_fds = {};
static bool arg_ask_password = true;
static bool arg_legend = true;
static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
static void push_fds_done(PushFds *p) {
assert(p);
@ -92,7 +85,6 @@ static int help(void) {
" Invoke method\n"
" --exec call ADDRESS METHOD PARAMS -- CMDLINE…\n"
" Invoke method and pass response and fds to command\n"
" list-registry Show list of services in the service registry\n"
" validate-idl [FILE] Validate interface description\n"
" help Show this help\n"
"\n%3$sOptions:%4$s\n"
@ -100,8 +92,6 @@ static int help(void) {
" --version Show package version\n"
" --no-ask-password Do not prompt for password\n"
" --no-pager Do not pipe output into a pager\n"
" --system Enumerate system registry\n"
" --user Enumerate user registry\n"
" --more Request multiple responses\n"
" --collect Collect multiple responses in a JSON array\n"
" --oneway Do not request response\n"
@ -141,8 +131,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_EXEC,
ARG_PUSH_FD,
ARG_NO_ASK_PASSWORD,
ARG_USER,
ARG_SYSTEM,
};
static const struct option options[] = {
@ -159,8 +147,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "exec", no_argument, NULL, ARG_EXEC },
{ "push-fd", required_argument, NULL, ARG_PUSH_FD },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
{},
};
@ -277,14 +263,6 @@ static int parse_argv(int argc, char *argv[]) {
arg_ask_password = false;
break;
case ARG_USER:
arg_runtime_scope = RUNTIME_SCOPE_USER;
break;
case ARG_SYSTEM:
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
break;
case '?':
return -EINVAL;
@ -995,105 +973,6 @@ static int verb_validate_idl(int argc, char *argv[], void *userdata) {
return 0;
}
static int verb_list_registry(int argc, char *argv[], void *userdata) {
int r;
assert(argc <= 1);
_cleanup_free_ char *reg_path = NULL;
r = runtime_directory_generic(arg_runtime_scope, "varlink/registry", &reg_path);
if (r < 0)
return log_error_errno(r, "Failed to determine registry path: %m");
_cleanup_(table_unrefp) Table *table = table_new("interface", "entrypoint");
if (!table)
return log_oom();
(void) table_set_sort(table, (size_t) 0);
_cleanup_close_ int regfd = open(reg_path, O_DIRECTORY|O_CLOEXEC);
if (regfd < 0) {
if (errno != ENOENT)
return log_error_errno(errno, "Failed to open '%s': %m", reg_path);
} else {
_cleanup_free_ DirectoryEntries *des = NULL;
r = readdir_all(regfd, RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE, &des);
if (r < 0)
return log_error_errno(r, "Failed to enumerate '%s': %m", reg_path);
FOREACH_ARRAY(i, des->entries, des->n_entries) {
struct dirent *de = *i;
if (!varlink_idl_interface_name_is_valid(de->d_name)) {
log_debug("Found file '%s' whose names does not qualify as valid Varlink interface name, skipping.", de->d_name);
continue;
}
_cleanup_free_ char *j = path_join(reg_path, de->d_name);
if (!j)
return log_oom();
switch (de->d_type) {
case DT_LNK: {
_cleanup_free_ char *resolved = NULL;
r = chase(j, /* root= */ NULL, CHASE_MUST_BE_SOCKET, &resolved, /* ret_fd= */ NULL);
if (r < 0) {
log_warning_errno(r, "Failed to resolve '%s', skipping: %m", j);
continue;
}
_cleanup_free_ char *address = strjoin("unix:", resolved);
if (!address)
return log_oom();
r = table_add_many(
table,
TABLE_STRING, de->d_name,
TABLE_STRING, address);
if (r < 0)
return r;
break;
}
case DT_SOCK: {
_cleanup_free_ char *address = strjoin("unix:", j);
if (!address)
return log_oom();
r = table_add_many(
table,
TABLE_STRING, de->d_name,
TABLE_STRING, address);
if (r < 0)
return r;
break;
}
default:
log_debug("Ignoring inode '%s' of unexpected type: %m", de->d_name);
}
}
}
if (!table_isempty(table) || sd_json_format_enabled(arg_json_format_flags)) {
r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, /* show_header= */ true);
if (r < 0)
return log_error_errno(r, "Failed to output table: %m");
}
if (arg_legend && !sd_json_format_enabled(arg_json_format_flags)) {
if (table_isempty(table))
printf("No services registered.\n");
else
printf("\n%zu registered services listed.\n", table_get_rows(table) - 1);
}
return 0;
}
static int varlinkctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "info", 2, 2, 0, verb_info },
@ -1101,7 +980,6 @@ static int varlinkctl_main(int argc, char *argv[]) {
{ "introspect", 2, VERB_ANY, 0, verb_introspect },
{ "list-methods", 2, VERB_ANY, 0, verb_introspect },
{ "call", 3, VERB_ANY, 0, verb_call },
{ "list-registry", VERB_ANY, 1, 0, verb_list_registry },
{ "validate-idl", 1, 2, 0, verb_validate_idl },
{ "help", VERB_ANY, VERB_ANY, 0, verb_help },
{}

View File

@ -42,7 +42,7 @@ if git.found() and fs.is_dir(meson.project_source_root() / '.git')
'ls-files', ':/@0@/*/*'.format(fuzz_testsdir),
check: true)
else
out = run_command(sh, '-c', 'cd "@0@"; printf "%s " @1@/*/*'.format(meson.project_source_root(), fuzz_testsdir), check: true)
out = run_command(sh, '-c', 'cd "@0@"; echo @1@/*/*'.format(meson.project_source_root(), fuzz_testsdir), check: true)
endif
# Add crafted fuzz inputs we have in the repo

View File

@ -37,10 +37,6 @@ varlinkctl introspect -j /run/systemd/journal/io.systemd.journal | jq --seq .
varlinkctl introspect /run/systemd/journal/io.systemd.journal io.systemd.Journal
varlinkctl introspect -j /run/systemd/journal/io.systemd.journal io.systemd.Journal | jq .
varlinkctl list-registry
varlinkctl list-registry -j | jq .
varlinkctl list-registry | grep io.systemd.Manager
if command -v userdbctl >/dev/null; then
systemctl start systemd-userdbd
varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{ "userName" : "testuser", "service" : "io.systemd.Multiplexer" }'

View File

@ -27,11 +27,9 @@ restore_esp() {
fi
if [ -d /tmp/esp.bak/EFI/ ]; then
mkdir -p "$(bootctl --print-esp-path)/EFI/"
cp -r /tmp/esp.bak/EFI/* "$(bootctl --print-esp-path)/EFI/"
fi
if [ -d /tmp/esp.bak/loader/ ]; then
mkdir -p "$(bootctl --print-esp-path)/loader/"
cp -r /tmp/esp.bak/loader/* "$(bootctl --print-esp-path)/loader/"
fi
rm -rf /tmp/esp.bak
@ -42,19 +40,13 @@ backup_esp() {
return
fi
# make a backup of the two key dirs in the ESP, and delete them
if [[ -d "$(bootctl --print-esp-path)/EFI" ]]; then
mkdir -p /tmp/esp.bak
cp -r "$(bootctl --print-esp-path)/EFI/" /tmp/esp.bak/
rm -rf "$(bootctl --print-esp-path)/EFI"
mkdir "$(bootctl --print-esp-path)/EFI"
fi
if [[ -d "$(bootctl --print-esp-path)/loader" ]]; then
mkdir -p /tmp/esp.bak
cp -r "$(bootctl --print-esp-path)/loader/" /tmp/esp.bak/
rm -rf "$(bootctl --print-esp-path)/loader"
mkdir "$(bootctl --print-esp-path)/loader"
fi
}
@ -372,22 +364,4 @@ testcase_00_secureboot() {
grep -q addonfoobar /proc/cmdline
}
remove_root_dir() {
rm -rf "$ROOTDIR"
}
testcase_install_varlink() {
varlinkctl introspect "$(type -p bootctl)"
if [ $# -eq 0 ]; then
backup_esp
trap restore_esp RETURN ERR
fi
(! bootctl is-installed )
SYSTEMD_LOG_TARGET=console varlinkctl call "$(type -p bootctl)" io.systemd.BootControl.Install "{\"operation\":\"new\",\"touchVariables\":false}"
bootctl is-installed
}
run_testcases

View File

@ -1,18 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# See tmpfiles.d(5) for details.
# Varlink AF_UNIX entrypoint socket inodes of relevant system services may be
# linked into this directory, to make them "well-known". Typically, tools such
# as the Varlink HTTP bridge expose services linked in here as public
# interfaces. The symlink should be named after the Varlink interface to
# expose. Interfaces that may be implemented by multiple services (such as
# the generic "io.systemd.service") should not be symlinked here.
d /run/varlink/registry/ 0755 root root
# Socket activated services should use Symlinks= in the .socket unit file to
# create these symlinks. If that's not applicable, consider creating the
# symlinks via a tmpfiles.d/ snippet, like we do here, so that registration can
# be influenced by the administrator.
L /run/varlink/registry/io.systemd.Unit - - - - ../../systemd/io.systemd.Manager
L /run/varlink/registry/io.systemd.Manager - - - - ../../systemd/io.systemd.Manager
L /run/varlink/registry/io.systemd.Journal - - - - ../../systemd/journal/io.systemd.journal

View File

@ -13,7 +13,6 @@ files = [['README' ],
['systemd-nspawn.conf', 'ENABLE_MACHINED' ],
['systemd-pstore.conf', 'ENABLE_PSTORE' ],
['systemd-resolve.conf', 'ENABLE_RESOLVE' ],
['20-systemd-varlink.conf' ],
['systemd-tmp.conf' ],
['tmp.conf' ],
['x11.conf' ],
@ -60,5 +59,3 @@ endforeach
if install_sysconfdir
install_emptydir(sysconfdir / 'tmpfiles.d')
endif
subdir('user')

View File

@ -1,7 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# See tmpfiles.d(5) for details.
d %t/varlink/registry/ 0755
L %t/varlink/registry/io.systemd.Unit - - - - ../../systemd/io.systemd.Manager
L %t/varlink/registry/io.systemd.Manager - - - - ../../systemd/io.systemd.Manager

View File

@ -1,11 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
files = [ '20-systemd-varlink.conf' ]
foreach f : files
install_data(f, install_dir : usertmpfilesdir)
endforeach
if install_sysconfdir
install_emptydir(sysconfdir / 'user-tmpfiles.d')
endif

View File

@ -572,4 +572,3 @@ loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="rebo
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="auto"]
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="reboot"]
loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]
varlinkctl.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--system"]

View File

@ -15,7 +15,6 @@ Before=sockets.target
[Socket]
ListenStream=/run/systemd/io.systemd.AskPassword
Symlinks=/run/varlink/registry/io.systemd.AskPassword
FileDescriptorName=varlink
SocketMode=0666
Accept=yes

View File

@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Boot Loader Control Service Socket
Description=Boot Entries Service Socket
Documentation=man:bootctl(1)
DefaultDependencies=no
After=local-fs.target
@ -16,7 +16,6 @@ Before=sockets.target
[Socket]
ListenStream=/run/systemd/io.systemd.BootControl
Symlinks=/run/varlink/registry/io.systemd.BootControl
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Boot Loader Control Service
Description=Boot Entries Service
Documentation=man:bootctl(1)
DefaultDependencies=no
Conflicts=shutdown.target

View File

@ -15,7 +15,6 @@ Before=sockets.target
[Socket]
ListenStream=/run/systemd/io.systemd.Credentials
Symlinks=/run/varlink/registry/io.systemd.Credentials
FileDescriptorName=varlink
SocketMode=0666
Accept=yes

View File

@ -15,7 +15,6 @@ Before=sockets.target
[Socket]
ListenStream=/run/systemd/io.systemd.FactoryReset
Symlinks=/run/varlink/registry/io.systemd.FactoryReset
FileDescriptorName=varlink
SocketMode=0666
Accept=yes

View File

@ -15,6 +15,5 @@ Documentation=man:machine-info(5)
[Socket]
ListenStream=/run/systemd/io.systemd.Hostname
Symlinks=/run/varlink/registry/io.systemd.Hostname
FileDescriptorName=varlink
SocketMode=0666

View File

@ -20,6 +20,5 @@ Before=shutdown.target
[Socket]
ListenStream=/run/systemd/io.systemd.Import
Symlinks=/run/varlink/registry/io.systemd.Import
FileDescriptorName=varlink
SocketMode=0666

View File

@ -13,7 +13,6 @@ Documentation=man:systemd-logind.service(8)
[Socket]
ListenStream=/run/systemd/io.systemd.Login
Symlinks=/run/varlink/registry/io.systemd.Login
FileDescriptorName=varlink
SocketMode=0666
Service=systemd-logind.service

View File

@ -13,6 +13,6 @@ Documentation=man:systemd-machined.service(8)
[Socket]
ListenStream=/run/systemd/machine/io.systemd.Machine
Symlinks=/run/systemd/machine/io.systemd.MachineImage /run/varlink/registry/io.systemd.Machine /run/varlink/registry/io.systemd.MachineImage
ListenStream=/run/systemd/machine/io.systemd.MachineImage
FileDescriptorName=varlink
SocketMode=0666

View File

@ -16,8 +16,6 @@ Before=sockets.target shutdown.target
[Socket]
ListenStream=/run/systemd/io.systemd.MountFileSystem
Symlinks=/run/varlink/registry/io.systemd.MountFileSystem
FileDescriptorName=varlink
SocketMode=0666
[Install]

View File

@ -17,7 +17,6 @@ Before=shutdown.target
[Socket]
ListenStream=/run/systemd/io.systemd.MuteConsole
Symlinks=/run/varlink/registry/io.systemd.MuteConsole
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -17,7 +17,6 @@ Conflicts=shutdown.target
[Socket]
ListenStream=/run/systemd/netif/io.systemd.Network
Symlinks=/run/varlink/registry/io.systemd.Network
FileDescriptorName=varlink
SocketMode=0666
Service=systemd-networkd.service

View File

@ -16,8 +16,7 @@ Before=sockets.target shutdown.target
[Socket]
ListenStream=/run/systemd/io.systemd.NamespaceResource
Symlinks=/run/systemd/userdb/io.systemd.NamespaceResource /run/varlink/registry/io.systemd.NamespaceResource
FileDescriptorName=varlink
Symlinks=/run/systemd/userdb/io.systemd.NamespaceResource
SocketMode=0666
[Install]

View File

@ -17,7 +17,6 @@ ConditionSecurity=measured-uki
[Socket]
ListenStream=/run/systemd/io.systemd.PCRExtend
Symlinks=/run/varlink/registry/io.systemd.PCRExtend
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -17,7 +17,6 @@ ConditionSecurity=measured-uki
[Socket]
ListenStream=/run/systemd/io.systemd.PCRLock
Symlinks=/run/varlink/registry/io.systemd.PCRLock
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -17,7 +17,6 @@ Before=shutdown.target
[Socket]
ListenStream=/run/systemd/io.systemd.Repart
Symlinks=/run/varlink/registry/io.systemd.Repart
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -17,7 +17,6 @@ Conflicts=shutdown.target
[Socket]
Service=systemd-resolved.service
ListenStream=/run/systemd/resolve/io.systemd.Resolve.Monitor
Symlinks=/run/varlink/registry/io.systemd.Resolve.Monitor
FileDescriptorName=varlink-monitor
SocketMode=0666

View File

@ -17,7 +17,6 @@ Conflicts=shutdown.target
[Socket]
Service=systemd-resolved.service
ListenStream=/run/systemd/resolve/io.systemd.Resolve
Symlinks=/run/varlink/registry/io.systemd.Resolve
FileDescriptorName=varlink
SocketMode=0666

View File

@ -17,7 +17,6 @@ ConditionCapability=CAP_SYS_ADMIN
[Socket]
ListenStream=/run/systemd/io.systemd.sysext
Symlinks=/run/varlink/registry/io.systemd.sysext
FileDescriptorName=varlink
SocketMode=0666
Accept=yes

View File

@ -17,7 +17,6 @@ ConditionPathIsReadWrite=/sys
[Socket]
Service=systemd-udevd.service
ListenStream=/run/udev/io.systemd.Udev
Symlinks=/run/varlink/registry/io.systemd.Udev
FileDescriptorName=varlink
SocketMode=0600
RemoveOnStop=yes

View File

@ -15,8 +15,7 @@ Before=sockets.target
[Socket]
ListenStream=/run/systemd/userdb/io.systemd.Multiplexer
Symlinks=/run/systemd/userdb/io.systemd.NameServiceSwitch /run/systemd/userdb/io.systemd.DropIn /run/varlink/registry/io.systemd.UserDatabase
FileDescriptorName=varlink
Symlinks=/run/systemd/userdb/io.systemd.NameServiceSwitch /run/systemd/userdb/io.systemd.DropIn
SocketMode=0666
RemoveOnStop=yes

View File

@ -15,7 +15,6 @@ Before=sockets.target
[Socket]
ListenStream=%t/systemd/io.systemd.AskPassword
Symlinks=%t/varlink/registry/io.systemd.AskPassword
FileDescriptorName=varlink
SocketMode=0600
Accept=yes

View File

@ -14,6 +14,5 @@ Documentation=man:org.freedesktop.import1(5)
[Socket]
ListenStream=%t/systemd/io.systemd.Import
Symlinks=%t/varlink/registry/io.systemd.Import
FileDescriptorName=varlink
SocketMode=0600

View File

@ -13,6 +13,6 @@ Documentation=man:systemd-machined.service(8)
[Socket]
ListenStream=%t/systemd/machine/io.systemd.Machine
Symlinks=%t/systemd/machine/io.systemd.MachineImage %t/varlink/registry/io.systemd.Machine %t/varlink/registry/io.systemd.MachineImage
ListenStream=%t/systemd/machine/io.systemd.MachineImage
FileDescriptorName=varlink
SocketMode=0600