1
0
mirror of https://github.com/systemd/systemd synced 2026-03-28 17:54:51 +01:00

Compare commits

...

22 Commits

Author SHA1 Message Date
Lennart Poettering
1641c2b112 cryptsetup: handle more gracefully if "keyslots" LUKS2 JSON header field is invalid
The field is not owned by us (even though is in our JSON objects) but by
the LUKS2 spec. Hence let's handle this a bit more gracefully: let's not
get confused by it, just warn and skip over it.

Fixes: #20847
2021-09-28 16:47:08 +02:00
Albert Brox
5918a93355 core: implement RuntimeMaxDeltaSec directive 2021-09-28 16:46:20 +02:00
Daan De Meyer
64782655e1 mkosi: Remove build script umask workaround
A fix for this landed in meson 3 years ago so the workaround in the
build script can now be removed (https://github.com/mesonbuild/meson/pull/3225).
2021-09-28 23:09:11 +09:00
alexlzhu
8c35c10d20 core: Add ExecSearchPath parameter to specify the directory relative to which binaries executed by Exec*= should be found
Currently there does not exist a way to specify a path relative to which
all binaries executed by Exec should be found. The only way is to
specify the absolute path.

This change implements the functionality to specify a path relative to which
binaries executed by Exec*= can be found.

Closes #6308
2021-09-28 14:52:27 +01:00
Zbigniew Jędrzejewski-Szmek
5b32e48f6e
Merge pull request #20837 from bluca/coveralls
CI: add code coverage reports via lcov and coveralls.io
2021-09-28 13:45:59 +02:00
Yu Watanabe
545c30c9ba
Merge pull request #20861 from yuwata/sd-lldp-rx-cleanups
sd-lldp-rx: several trivial cleanups
2021-09-28 20:22:21 +09:00
Yu Watanabe
35777f5178 sd-lldp-rx: make lldp_rx_free() and lldp_neighbor_free() accept NULL 2021-09-28 17:55:19 +09:00
Yu Watanabe
92466b8da2 sd-lldp-rx: sd_event should be attached when lldp_rx_start_timer() is called 2021-09-28 17:55:19 +09:00
Yu Watanabe
3e4a202519 sd-lldp-rx: do not enable timer event source in sd_lldp_rx_get_neighbors()
It must be just a simple getter.
2021-09-28 17:55:19 +09:00
Yu Watanabe
0cd7e072b4 sd-lldp-rx: use _cleanup_ attribute at one more place 2021-09-28 17:55:19 +09:00
Yu Watanabe
71c4f7e895 sd-lldp-rx: wrap long line 2021-09-28 17:55:19 +09:00
Yu Watanabe
90496cc68c sd-lldp-rx: add missing assertions 2021-09-28 17:55:19 +09:00
Yu Watanabe
b0a67b202d sd-lldp-rx: delay allocating hashmap and prioq to store neighbors 2021-09-28 17:55:16 +09:00
Yu Watanabe
5bff20ea62 prioq: introduce prioq_ensure_put() 2021-09-28 15:15:12 +09:00
Yu Watanabe
aa3f8d4ca1 sd-lldp-rx: ensure no event will be triggered after sd_lldp_rx_detach_event() is called 2021-09-28 15:07:37 +09:00
Yu Watanabe
e9ea43136c sd-lldp-rx: add comments about the three multicast addresses 2021-09-28 15:07:13 +09:00
Yu Watanabe
b5dce07a5e sd-lldp-rx: introduce sd_lldp_rx_is_running() 2021-09-28 14:51:24 +09:00
Yu Watanabe
4be699a8db sd-lldp-rx: ignore all errors in processing datagram 2021-09-28 14:44:12 +09:00
Luca Boccassi
3bf94dac91 CI: do manpages build only on the clang unit test run
It's slow and unaffected by compiler/flags, so no point in repeating it
2021-09-27 12:24:48 +01:00
Luca Boccassi
1f1d48f96e CI: add code coverage reports via lcov and coveralls.io 2021-09-27 12:22:22 +01:00
Luca Boccassi
8b036b223a CI: run unit tests in a network namespace
It seems some of the tests break network connectivity on the host,
as the code coverage upload fails to establish a connection.
Run them in a network namespace with 'unshare -n'.
2021-09-27 12:22:22 +01:00
Luca Boccassi
059c0578d7 test: double test-hashmap timeout
When coverage flags are used, sometimes it goes just over 90s on a
slow CI machine
2021-09-27 12:22:22 +01:00
52 changed files with 598 additions and 104 deletions

View File

@ -6,7 +6,9 @@ ADDITIONAL_DEPS=(
clang
expect
fdisk
iproute2
jekyll
lcov
libfdisk-dev
libfido2-dev
libp11-kit-dev
@ -18,6 +20,7 @@ ADDITIONAL_DEPS=(
perl
python3-libevdev
python3-pyparsing
util-linux
zstd
)
@ -42,10 +45,21 @@ for phase in "${PHASES[@]}"; do
if [[ "$phase" = "RUN_CLANG" ]]; then
export CC=clang
export CXX=clang++
# The docs build is slow and is not affected by compiler/flags, so do it just once
MESON_ARGS+=(-Dman=true)
fi
meson --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true -Dman=true build
if [[ "$phase" = "RUN_GCC" ]]; then
MESON_ARGS+=(-Db_coverage=true)
# See FIXME below
(set +x; while :; do echo -ne "\n[WATCHDOG] $(date)\n"; sleep 30; done) &
fi
meson --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true "${MESON_ARGS[@]}" build
ninja -C build -v
meson test -C build --print-errorlogs
# Some of the unsafe tests irreparably break the host's network connectivity, so run them in a namespace
unshare -n bash -c 'ip link set dev lo up; meson test -C build --print-errorlogs'
if [[ "$phase" = "RUN_GCC" ]]; then
ninja -C build coverage
fi
;;
RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN)
MESON_ARGS=(--optimization=1)
@ -74,7 +88,7 @@ for phase in "${PHASES[@]}"; do
# during debugging, wonderful), so let's at least keep a workaround
# here to make the builds stable for the time being.
(set +x; while :; do echo -ne "\n[WATCHDOG] $(date)\n"; sleep 30; done) &
meson test --timeout-multiplier=3 -C build --print-errorlogs
unshare -n bash -c 'ip link set dev lo up; meson test --timeout-multiplier=3 -C build --print-errorlogs'
;;
CLEANUP)
info "Cleanup phase"

View File

@ -16,8 +16,14 @@ jobs:
run_phase: [GCC, GCC_ASAN_UBSAN, CLANG, CLANG_ASAN_UBSAN]
steps:
- name: Repository checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Install build dependencies
run: sudo -E .github/workflows/unit_tests.sh SETUP
- name: Build & test (${{ matrix.run_phase }})
run: sudo -E .github/workflows/unit_tests.sh RUN_${{ matrix.run_phase }}
- name: Coveralls
if: matrix.run_phase == 'GCC' && github.repository == 'systemd/systemd'
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./build/meson-logs/coverage.info

View File

@ -14,6 +14,7 @@ System and Service Manager
[![CentOS CI - Arch](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Arch&job=upstream-vagrant-archlinux)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-vagrant-archlinux/)<br/>
[![CentOS CI - Arch (sanitizers)](https://jenkins-systemd.apps.ocp.ci.centos.org/buildStatus/icon?subject=CentOS%20CI%20-%20Arch%20(sanitizers)&job=upstream-vagrant-archlinux-sanitizers)](https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-vagrant-archlinux-sanitizers/)<br/>
[![Fossies codespell report](https://fossies.org/linux/test/systemd-main.tar.gz/codespell.svg)](https://fossies.org/linux/test/systemd-main.tar.gz/codespell.html)</br>
[![Coverage Status](https://coveralls.io/repos/github/systemd/systemd/badge.svg?branch=main)](https://coveralls.io/github/systemd/systemd?branch=main)</br>
[![Packaging status](https://repology.org/badge/tiny-repos/systemd.svg)](https://repology.org/project/systemd/versions)
## Details

View File

@ -320,6 +320,7 @@ Most service unit settings are available for transient units.
✓ RestartSec=
✓ RootDirectoryStartOnly=
✓ RuntimeMaxSec=
✓ RuntimeRandomizedExtraSec=
Sockets=
✓ SuccessExitStatus=
✓ TimeoutAbortSec=
@ -395,6 +396,7 @@ such).
```
✓ RuntimeMaxSec=
✓ RuntimeRandomizedExtraSec=
✓ TimeoutStopSec=
```

View File

@ -2317,6 +2317,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
readonly s TimeoutStopFailureMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeMaxUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeRandomizedExtraUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t WatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@ -2737,6 +2739,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@ -2888,6 +2892,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property RuntimeMaxUSec is not documented!-->
<!--property RuntimeRandomizedExtraUSec is not documented!-->
<!--property WatchdogUSec is not documented!-->
<!--property RootDirectoryStartOnly is not documented!-->
@ -3260,6 +3266,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property NoExecPaths is not documented!-->
<!--property ExecSearchPath is not documented!-->
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
@ -3422,6 +3430,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeMaxUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeRandomizedExtraUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="WatchdogUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="WatchdogTimestamp"/>
@ -3858,6 +3868,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@ -4567,6 +4579,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@ -5118,6 +5132,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property NoExecPaths is not documented!-->
<!--property ExecSearchPath is not documented!-->
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
@ -5714,6 +5730,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@ -6320,6 +6338,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@ -6799,6 +6819,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property NoExecPaths is not documented!-->
<!--property ExecSearchPath is not documented!-->
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
@ -7313,6 +7335,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@ -8040,6 +8064,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@ -8505,6 +8531,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property NoExecPaths is not documented!-->
<!--property ExecSearchPath is not documented!-->
<!--property PrivateTmp is not documented!-->
<!--property PrivateDevices is not documented!-->
@ -9005,6 +9033,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
@ -9721,6 +9751,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
readonly s Result = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeMaxUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeRandomizedExtraUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@ -9891,6 +9923,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<!--property RuntimeMaxUSec is not documented!-->
<!--property RuntimeRandomizedExtraUSec is not documented!-->
<!--property Slice is not documented!-->
<!--property MemoryCurrent is not documented!-->
@ -10069,6 +10103,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeMaxUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="RuntimeRandomizedExtraUSec"/>
<variablelist class="dbus-property" generated="True" extra-ref="Slice"/>
<variablelist class="dbus-property" generated="True" extra-ref="ControlGroup"/>

View File

@ -89,6 +89,20 @@
<variablelist class='unit-directives'>
<varlistentry>
<term><varname>ExecSearchPath=</varname></term>
<listitem><para>Takes a colon separated list of absolute paths relative to which the executable
used by the <varname>Exec*=</varname> (e.g. <varname>ExecStart=</varname>,
<varname>ExecStop=</varname>, etc.) properties can be found. <varname>ExecSearchPath=</varname>
overrides <varname>$PATH</varname> if <varname>$PATH</varname> is not supplied by the user through
<varname>Environment=</varname>, <varname>EnvironmentFile=</varname> or
<varname>PassEnvironment=</varname>. Assigning an empty string removes previous assignments
and setting <varname>ExecSearchPath=</varname> to a value multiple times will append
to the previous setting.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>WorkingDirectory=</varname></term>

View File

@ -112,6 +112,15 @@
active for longer than the specified time it is terminated and put into a failure state. Pass
<literal>infinity</literal> (the default) to configure no runtime limit.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>RuntimeRandomizedExtraSec=</varname></term>
<listitem><para>This option modifies <varname>RuntimeMaxSec=</varname> by increasing the maximum runtime by an
evenly distributed duration between 0 and the specified value (in seconds). If <varname>RuntimeMaxSec=</varname> is
unspecified, then this feature will be disabled.
</para></listitem>
</varlistentry>
</variablelist>
<xi:include href="systemd.service.xml" xpointer="shared-unit-options" />

View File

@ -695,6 +695,15 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>RuntimeRandomizedExtraSec=</varname></term>
<listitem><para>This option modifies <varname>RuntimeMaxSec=</varname> by increasing the maximum runtime by an
evenly distributed duration between 0 and the specified value (in seconds). If <varname>RuntimeMaxSec=</varname> is
unspecified, then this feature will be disabled.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>WatchdogSec=</varname></term>
<listitem><para>Configures the watchdog timeout for a service.

View File

@ -4,16 +4,6 @@ set -e
# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
# Reset the permissions of the tree. Since Meson keeps the permissions
# all the way to the installed files, reset them to one of 0644 or 0755
# so the files keep those permissions, otherwise details of what umask
# was set at the time the git tree was cloned will leak all the way
# through. Also set umask explicitly during the build.
if ! mountpoint -q "$SRCDIR"; then
chmod -R u+w,go-w,a+rX .
umask 022
fi
# On Fedora "ld" is (unfortunately — if you ask me) managed via
# "alternatives". Since we'd like to support building images in environments
# with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem

View File

@ -142,7 +142,7 @@ int verify_executable(Unit *u, const ExecCommand *exec, const char *root) {
if (exec->flags & EXEC_COMMAND_IGNORE_FAILURE)
return 0;
r = find_executable_full(exec->path, root, false, NULL, NULL);
r = find_executable_full(exec->path, root, NULL, false, NULL, NULL);
if (r < 0)
return log_unit_error_errno(u, r, "Command %s is not executable: %m", exec->path);

View File

@ -682,8 +682,8 @@ static int find_executable_impl(const char *name, const char *root, char **ret_f
return 0;
}
int find_executable_full(const char *name, const char *root, bool use_path_envvar, char **ret_filename, int *ret_fd) {
int last_error, r;
int find_executable_full(const char *name, const char *root, char **exec_search_path, bool use_path_envvar, char **ret_filename, int *ret_fd) {
int last_error = -ENOENT, r = 0;
const char *p = NULL;
assert(name);
@ -698,7 +698,27 @@ int find_executable_full(const char *name, const char *root, bool use_path_envva
if (!p)
p = DEFAULT_PATH;
last_error = -ENOENT;
if (exec_search_path) {
char **element;
STRV_FOREACH(element, exec_search_path) {
_cleanup_free_ char *full_path = NULL;
if (!path_is_absolute(*element))
continue;
full_path = path_join(*element, name);
if (!full_path)
return -ENOMEM;
r = find_executable_impl(full_path, root, ret_filename, ret_fd);
if (r < 0) {
if (r != -EACCES)
last_error = r;
continue;
}
return 0;
}
return last_error;
}
/* Resolve a single-component name to a full path */
for (;;) {

View File

@ -99,9 +99,9 @@ int path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *root);
char** path_strv_resolve_uniq(char **l, const char *root);
int find_executable_full(const char *name, const char *root, bool use_path_envvar, char **ret_filename, int *ret_fd);
int find_executable_full(const char *name, const char *root, char **exec_search_path, bool use_path_envvar, char **ret_filename, int *ret_fd);
static inline int find_executable(const char *name, char **ret_filename) {
return find_executable_full(name, /* root= */ NULL, true, ret_filename, NULL);
return find_executable_full(name, /* root= */ NULL, NULL, true, ret_filename, NULL);
}
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);

View File

@ -173,6 +173,16 @@ int prioq_put(Prioq *q, void *data, unsigned *idx) {
return 0;
}
int prioq_ensure_put(Prioq **q, compare_func_t compare_func, void *data, unsigned *idx) {
int r;
r = prioq_ensure_allocated(q, compare_func);
if (r < 0)
return r;
return prioq_put(*q, data, idx);
}
static void remove_item(Prioq *q, struct prioq_item *i) {
struct prioq_item *l;

View File

@ -16,6 +16,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Prioq*, prioq_free);
int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func);
int prioq_put(Prioq *q, void *data, unsigned *idx);
int prioq_ensure_put(Prioq **q, compare_func_t compare_func, void *data, unsigned *idx);
int prioq_remove(Prioq *q, void *data, unsigned *idx);
int prioq_reshuffle(Prioq *q, void *data, unsigned *idx);

View File

@ -1161,6 +1161,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ExecPaths", "as", NULL, offsetof(ExecContext, exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NoExecPaths", "as", NULL, offsetof(ExecContext, no_exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ExecSearchPath", "as", NULL, offsetof(ExecContext, exec_search_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
@ -3140,6 +3141,36 @@ int bus_exec_context_set_transient_property(
return 1;
} else if (streq(name, "ExecSearchPath")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
STRV_FOREACH(p, l) {
if (!path_is_absolute(*p) || !path_is_normalized(*p) || strchr(*p, ':'))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (strv_isempty(l)) {
c->exec_search_path = strv_free(c->exec_search_path);
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ExecSearchPath=");
} else {
_cleanup_free_ char *joined = NULL;
r = strv_extend_strv(&c->exec_search_path, l, true);
if (r < 0)
return -ENOMEM;
joined = strv_join(c->exec_search_path, ":");
if (!joined)
return log_oom();
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ExecSearchPath=%s", joined);
}
}
return 1;
} else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
_cleanup_strv_free_ char **l = NULL;
char **p;

View File

@ -47,6 +47,7 @@ const sd_bus_vtable bus_scope_vtable[] = {
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Scope, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeRandomizedExtraUSec", "t", bus_property_get_usec, offsetof(Scope, runtime_rand_extra_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_SIGNAL("RequestStop", NULL, 0),
SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_method_abandon, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
@ -74,6 +75,9 @@ static int bus_scope_set_transient_property(
if (streq(name, "RuntimeMaxUSec"))
return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error);
if (streq(name, "RuntimeRandomizedExtraUSec"))
return bus_set_transient_usec(u, name, &s->runtime_rand_extra_usec, message, flags, error);
if (streq(name, "PIDs")) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
unsigned n = 0;

View File

@ -202,6 +202,7 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("TimeoutStartFailureMode", "s", property_get_timeout_failure_mode, offsetof(Service, timeout_start_failure_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimeoutStopFailureMode", "s", property_get_timeout_failure_mode, offsetof(Service, timeout_stop_failure_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeRandomizedExtraUSec", "t", bus_property_get_usec, offsetof(Service, runtime_rand_extra_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WatchdogUSec", "t", property_get_watchdog_usec, 0, 0),
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* 😷 deprecated */
@ -447,6 +448,9 @@ static int bus_service_set_transient_property(
if (streq(name, "RuntimeMaxUSec"))
return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error);
if (streq(name, "RuntimeRandomizedExtraUSec"))
return bus_set_transient_usec(u, name, &s->runtime_rand_extra_usec, message, flags, error);
if (streq(name, "WatchdogUSec"))
return bus_set_transient_usec(u, name, &s->watchdog_usec, message, flags, error);

View File

@ -3742,7 +3742,7 @@ static int exec_child(
int user_lookup_fd,
int *exit_status) {
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **replaced_argv = NULL;
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL, **replaced_argv = NULL;
int r, ngids = 0, exec_fd;
_cleanup_free_ gid_t *supplementary_gids = NULL;
const char *username = NULL, *groupname = NULL;
@ -4158,8 +4158,31 @@ static int exec_child(
return log_oom();
}
/* The PATH variable is set to the default path in params->environment.
* However, this is overridden if user specified fields have PATH set.
* The intention is to also override PATH if the user does
* not specify PATH and the user has specified ExecSearchPath
*/
if (!strv_isempty(context->exec_search_path)) {
_cleanup_free_ char *joined = NULL;
joined = strv_join(context->exec_search_path, ":");
if (!joined) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
r = strv_env_assign(&joined_exec_search_path, "PATH", joined);
if (r < 0) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
}
accum_env = strv_env_merge(params->environment,
our_env,
joined_exec_search_path,
pass_env,
context->environment,
files_env);
@ -4350,7 +4373,7 @@ static int exec_child(
_cleanup_free_ char *executable = NULL;
_cleanup_close_ int executable_fd = -1;
r = find_executable_full(command->path, /* root= */ NULL, false, &executable, &executable_fd);
r = find_executable_full(command->path, /* root= */ NULL, context->exec_search_path, false, &executable, &executable_fd);
if (r < 0) {
if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
log_unit_struct_errno(unit, LOG_INFO, r,
@ -4926,6 +4949,7 @@ void exec_context_done(ExecContext *c) {
c->inaccessible_paths = strv_free(c->inaccessible_paths);
c->exec_paths = strv_free(c->exec_paths);
c->no_exec_paths = strv_free(c->no_exec_paths);
c->exec_search_path = strv_free(c->exec_search_path);
bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
c->bind_mounts = NULL;
@ -5597,6 +5621,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
strv_dump(f, prefix, "InaccessiblePaths", c->inaccessible_paths);
strv_dump(f, prefix, "ExecPaths", c->exec_paths);
strv_dump(f, prefix, "NoExecPaths", c->no_exec_paths);
strv_dump(f, prefix, "ExecSearchPath", c->exec_search_path);
for (size_t i = 0; i < c->n_bind_mounts; i++)
fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,

View File

@ -254,6 +254,7 @@ struct ExecContext {
char *smack_process_label;
char **read_write_paths, **read_only_paths, **inaccessible_paths, **exec_paths, **no_exec_paths;
char **exec_search_path;
unsigned long mount_flags;
BindMount *bind_mounts;
size_t n_bind_mounts;

View File

@ -105,6 +105,7 @@
{{type}}.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.inaccessible_paths)
{{type}}.ExecPaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.exec_paths)
{{type}}.NoExecPaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.no_exec_paths)
{{type}}.ExecSearchPath, config_parse_colon_separated_paths, 0, offsetof({{type}}, exec_context.exec_search_path)
{{type}}.BindPaths, config_parse_bind_paths, 0, offsetof({{type}}, exec_context)
{{type}}.BindReadOnlyPaths, config_parse_bind_paths, 0, offsetof({{type}}, exec_context)
{{type}}.TemporaryFileSystem, config_parse_temporary_filesystems, 0, offsetof({{type}}, exec_context)
@ -381,6 +382,7 @@ Service.TimeoutAbortSec, config_parse_service_timeout_abort,
Service.TimeoutStartFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_start_failure_mode)
Service.TimeoutStopFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_stop_failure_mode)
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
Service.RuntimeRandomizedExtraSec, config_parse_sec, 0, offsetof(Service, runtime_rand_extra_usec)
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
{# The following five only exist for compatibility, they moved into Unit, see above #}
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval)
@ -533,6 +535,7 @@ Path.DirectoryMode, config_parse_mode,
{{ CGROUP_CONTEXT_CONFIG_ITEMS('Scope') }}
{{ KILL_CONTEXT_CONFIG_ITEMS('Scope') }}
Scope.RuntimeMaxSec, config_parse_sec, 0, offsetof(Scope, runtime_max_usec)
Scope.RuntimeRandomizedExtraSec, config_parse_sec, 0, offsetof(Scope, runtime_rand_extra_usec)
Scope.TimeoutStopSec, config_parse_sec, 0, offsetof(Scope, timeout_stop_usec)
{# The [Install] section is ignored here #}
Install.Alias, NULL, 0, 0

View File

@ -305,6 +305,64 @@ int config_parse_unit_path_printf(
return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
}
int config_parse_colon_separated_paths(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char ***sv = data;
const Unit *u = userdata;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
/* Empty assignment resets the list */
*sv = strv_free(*sv);
return 0;
}
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
break;
r = unit_path_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", word);
return 0;
}
r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
if (r < 0)
return 0;
r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
}
return 0;
}
int config_parse_unit_path_strv_printf(
const char *unit,
const char *filename,
@ -5915,6 +5973,7 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_string, "STRING" },
{ config_parse_path, "PATH" },
{ config_parse_unit_path_printf, "PATH" },
{ config_parse_colon_separated_paths, "PATH" },
{ config_parse_strv, "STRING [...]" },
{ config_parse_exec_nice, "NICE" },
{ config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },

View File

@ -19,6 +19,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_obsolete_unit_deps);
CONFIG_PARSER_PROTOTYPE(config_parse_unit_string_printf);
CONFIG_PARSER_PROTOTYPE(config_parse_unit_strv_printf);
CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_printf);
CONFIG_PARSER_PROTOTYPE(config_parse_colon_separated_paths);
CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_strv_printf);
CONFIG_PARSER_PROTOTYPE(config_parse_documentation);
CONFIG_PARSER_PROTOTYPE(config_parse_socket_listen);

View File

@ -9,6 +9,7 @@
#include "load-dropin.h"
#include "log.h"
#include "process-util.h"
#include "random-util.h"
#include "scope.h"
#include "serialize.h"
#include "special.h"
@ -51,6 +52,21 @@ static void scope_done(Unit *u) {
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
}
static int scope_running_timeout(Scope *s) {
usec_t delta = 0;
assert(s);
if (s->runtime_rand_extra_usec != 0) {
delta = random_u64_range(s->runtime_rand_extra_usec);
log_unit_debug(UNIT(s), "Adding delta of %s sec to timeout", FORMAT_TIMESPAN(delta, USEC_PER_SEC));
}
return usec_add(usec_add(UNIT(s)->active_enter_timestamp.monotonic,
s->runtime_max_usec),
delta);
}
static int scope_arm_timer(Scope *s, usec_t usec) {
int r;
@ -209,7 +225,7 @@ static usec_t scope_coldplug_timeout(Scope *s) {
switch (s->deserialized_state) {
case SCOPE_RUNNING:
return usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec);
return scope_running_timeout(s);
case SCOPE_STOP_SIGKILL:
case SCOPE_STOP_SIGTERM:
@ -262,10 +278,12 @@ static void scope_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sScope State: %s\n"
"%sResult: %s\n"
"%sRuntimeMaxSec: %s\n",
"%sRuntimeMaxSec: %s\n"
"%sRuntimeRandomizedExtraSec: %s\n",
prefix, scope_state_to_string(s->state),
prefix, scope_result_to_string(s->result),
prefix, FORMAT_TIMESPAN(s->runtime_max_usec, USEC_PER_SEC));
prefix, FORMAT_TIMESPAN(s->runtime_max_usec, USEC_PER_SEC),
prefix, FORMAT_TIMESPAN(s->runtime_rand_extra_usec, USEC_PER_SEC));
cgroup_context_dump(UNIT(s), f, prefix);
kill_context_dump(&s->kill_context, f, prefix);
@ -379,7 +397,7 @@ static int scope_start(Unit *u) {
scope_set_state(s, SCOPE_RUNNING);
/* Set the maximum runtime timeout. */
scope_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec));
scope_arm_timer(s, scope_running_timeout(s));
/* On unified we use proper notifications hence we can unwatch the PIDs
* we just attached to the scope. This can also be done on legacy as

View File

@ -25,6 +25,7 @@ struct Scope {
ScopeResult result;
usec_t runtime_max_usec;
usec_t runtime_rand_extra_usec;
usec_t timeout_stop_usec;
char *controller;

View File

@ -29,6 +29,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "serialize.h"
#include "service.h"
#include "signal-util.h"
@ -514,6 +515,21 @@ static void service_remove_fd_store(Service *s, const char *name) {
}
}
static int service_running_timeout(Service *s) {
usec_t delta = 0;
assert(s);
if (s->runtime_rand_extra_usec != 0) {
delta = random_u64_range(s->runtime_rand_extra_usec);
log_unit_debug(UNIT(s), "Adding delta of %s sec to timeout", FORMAT_TIMESPAN(delta, USEC_PER_SEC));
}
return usec_add(usec_add(UNIT(s)->active_enter_timestamp.monotonic,
s->runtime_max_usec),
delta);
}
static int service_arm_timer(Service *s, usec_t usec) {
int r;
@ -587,6 +603,9 @@ static int service_verify(Service *s) {
if (s->runtime_max_usec != USEC_INFINITY && s->type == SERVICE_ONESHOT)
log_unit_warning(UNIT(s), "RuntimeMaxSec= has no effect in combination with Type=oneshot. Ignoring.");
if (s->runtime_max_usec == USEC_INFINITY && s->runtime_rand_extra_usec != 0)
log_unit_warning(UNIT(s), "Service has RuntimeRandomizedExtraSec= setting, but no RuntimeMaxSec=. Ignoring.");
return 0;
}
@ -855,8 +874,10 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sRuntimeMaxSec: %s\n"
"%sRuntimeRandomizedExtraSec: %s\n"
"%sWatchdogSec: %s\n",
prefix, FORMAT_TIMESPAN(s->runtime_max_usec, USEC_PER_SEC),
prefix, FORMAT_TIMESPAN(s->runtime_rand_extra_usec, USEC_PER_SEC),
prefix, FORMAT_TIMESPAN(s->watchdog_usec, USEC_PER_SEC));
kill_context_dump(&s->kill_context, f, prefix);
@ -1118,7 +1139,7 @@ static usec_t service_coldplug_timeout(Service *s) {
return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_start_usec);
case SERVICE_RUNNING:
return usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec);
return service_running_timeout(s);
case SERVICE_STOP:
case SERVICE_STOP_SIGTERM:
@ -1989,7 +2010,7 @@ static void service_enter_running(Service *s, ServiceResult f) {
service_enter_stop_by_notify(s);
else {
service_set_state(s, SERVICE_RUNNING);
service_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec));
service_arm_timer(s, service_running_timeout(s));
}
} else if (s->remain_after_exit)

View File

@ -111,6 +111,7 @@ struct Service {
usec_t timeout_abort_usec;
bool timeout_abort_set;
usec_t runtime_max_usec;
usec_t runtime_rand_extra_usec;
ServiceTimeoutFailureMode timeout_start_failure_mode;
ServiceTimeoutFailureMode timeout_stop_failure_mode;

View File

@ -34,8 +34,12 @@ static int search_policy_hash(
return log_error_errno(r, "Failed to read JSON token data off disk: %m");
keyslot = cryptsetup_get_keyslot_from_token(v);
if (keyslot < 0)
return log_error_errno(keyslot, "Failed to determine keyslot of JSON token: %m");
if (keyslot < 0) {
/* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by
* us, but by the LUKS2 spec */
log_warning_errno(keyslot, "Failed to determine keyslot of JSON token %i, skipping: %m", token);
continue;
}
w = json_variant_by_key(v, "tpm2-policy-hash");
if (!w || !json_variant_is_string(w))

View File

@ -133,6 +133,7 @@ int find_fido2_auto_data(
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token ++) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
JsonVariant *w;
int ks;
r = cryptsetup_get_token_as_json(cd, token, "systemd-fido2", &v);
if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
@ -140,10 +141,21 @@ int find_fido2_auto_data(
if (r < 0)
return log_error_errno(r, "Failed to read JSON token data off disk: %m");
ks = cryptsetup_get_keyslot_from_token(v);
if (ks < 0) {
/* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by
* us, but by the LUKS2 spec */
log_warning_errno(ks, "Failed to extract keyslot index from FIDO2 JSON data token %i, skipping: %m", token);
continue;
}
if (cid)
return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
"Multiple FIDO2 tokens enrolled, cannot automatically determine token.");
assert(keyslot < 0);
keyslot = ks;
w = json_variant_by_key(v, "fido2-credential");
if (!w || !json_variant_is_string(w))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -165,11 +177,6 @@ int find_fido2_auto_data(
if (r < 0)
return log_error_errno(r, "Failed to decode base64 encoded salt.");
assert(keyslot < 0);
keyslot = cryptsetup_get_keyslot_from_token(v);
if (keyslot < 0)
return log_error_errno(keyslot, "Failed to extract keyslot index from FIDO2 JSON data: %m");
w = json_variant_by_key(v, "fido2-rp");
if (w) {
/* The "rp" field is optional. */

View File

@ -111,6 +111,7 @@ int find_pkcs11_auto_data(
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
JsonVariant *w;
int ks;
r = cryptsetup_get_token_as_json(cd, token, "systemd-pkcs11", &v);
if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
@ -118,10 +119,21 @@ int find_pkcs11_auto_data(
if (r < 0)
return log_error_errno(r, "Failed to read JSON token data off disk: %m");
ks = cryptsetup_get_keyslot_from_token(v);
if (ks < 0) {
/* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by
* us, but by the LUKS2 spec */
log_warning_errno(ks, "Failed to extract keyslot index from PKCS#11 JSON data token %i, skipping: %m", token);
continue;
}
if (uri)
return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
"Multiple PKCS#11 tokens enrolled, cannot automatically determine token.");
assert(keyslot < 0);
keyslot = ks;
w = json_variant_by_key(v, "pkcs11-uri");
if (!w || !json_variant_is_string(w))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -145,11 +157,6 @@ int find_pkcs11_auto_data(
r = unbase64mem(json_variant_string(w), SIZE_MAX, &key, &key_size);
if (r < 0)
return log_error_errno(r, "Failed to decode base64 encoded key.");
assert(keyslot < 0);
keyslot = cryptsetup_get_keyslot_from_token(v);
if (keyslot < 0)
return log_error_errno(keyslot, "Failed to extract keyslot index from PKCS#11 JSON data: %m");
}
if (!uri)

View File

@ -93,6 +93,7 @@ int find_tpm2_auto_data(
for (token = start_token; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
JsonVariant *w, *e;
int ks;
r = cryptsetup_get_token_as_json(cd, token, "systemd-tpm2", &v);
if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
@ -100,6 +101,14 @@ int find_tpm2_auto_data(
if (r < 0)
return log_error_errno(r, "Failed to read JSON token data off disk: %m");
ks = cryptsetup_get_keyslot_from_token(v);
if (ks < 0) {
/* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by
* us, but by the LUKS2 spec */
log_warning_errno(ks, "Failed to extract keyslot index from TPM2 JSON data token %i, skipping: %m", token);
continue;
}
w = json_variant_by_key(v, "tpm2-pcrs");
if (!w || !json_variant_is_array(w))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -125,6 +134,9 @@ int find_tpm2_auto_data(
search_pcr_mask != pcr_mask) /* PCR mask doesn't match what is configured, ignore this entry */
continue;
assert(keyslot < 0);
keyslot = ks;
assert(pcr_bank == UINT16_MAX);
assert(primary_alg == TPM2_ALG_ECC);
@ -184,11 +196,6 @@ int find_tpm2_auto_data(
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid base64 data in 'tpm2-policy-hash' field.");
assert(keyslot < 0);
keyslot = cryptsetup_get_keyslot_from_token(v);
if (keyslot < 0)
return log_error_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data: %m");
break;
}

View File

@ -11,6 +11,9 @@
#include "unaligned.h"
static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) {
assert(id);
assert(state);
siphash24_compress(id->chassis_id, id->chassis_id_size, state);
siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state);
siphash24_compress(id->port_id, id->port_id_size, state);
@ -18,16 +21,27 @@ static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash
}
int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) {
assert(x);
assert(y);
return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size)
?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size);
}
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(lldp_neighbor_hash_ops, LLDPNeighborID, lldp_neighbor_id_hash_func, lldp_neighbor_id_compare_func,
sd_lldp_neighbor, lldp_neighbor_unlink);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
lldp_neighbor_hash_ops,
LLDPNeighborID,
lldp_neighbor_id_hash_func,
lldp_neighbor_id_compare_func,
sd_lldp_neighbor,
lldp_neighbor_unlink);
int lldp_neighbor_prioq_compare_func(const void *a, const void *b) {
const sd_lldp_neighbor *x = a, *y = b;
assert(x);
assert(y);
return CMP(x->until, y->until);
}
@ -41,8 +55,9 @@ _public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) {
return n;
}
static void lldp_neighbor_free(sd_lldp_neighbor *n) {
assert(n);
static sd_lldp_neighbor *lldp_neighbor_free(sd_lldp_neighbor *n) {
if (!n)
return NULL;
free(n->id.port_id);
free(n->id.chassis_id);
@ -52,7 +67,7 @@ static void lldp_neighbor_free(sd_lldp_neighbor *n) {
free(n->mud_url);
free(n->chassis_id_as_string);
free(n->port_id_as_string);
free(n);
return mfree(n);
}
_public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) {

View File

@ -56,15 +56,18 @@ int lldp_network_bind_raw_socket(int ifindex) {
if (r < 0)
return -errno;
/* customer bridge */
r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (r < 0)
return -errno;
/* non TPMR bridge */
mreq.mr_address[ETH_ALEN - 1] = 0x03;
r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (r < 0)
return -errno;
/* nearest bridge */
mreq.mr_address[ETH_ALEN - 1] = 0x0E;
r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (r < 0)

View File

@ -147,11 +147,11 @@ static int lldp_rx_add_neighbor(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) {
/* Then, make room for at least one new neighbor */
lldp_rx_make_space(lldp_rx, 1);
r = hashmap_put(lldp_rx->neighbor_by_id, &n->id, n);
r = hashmap_ensure_put(&lldp_rx->neighbor_by_id, &lldp_neighbor_hash_ops, &n->id, n);
if (r < 0)
goto finish;
r = prioq_put(lldp_rx->neighbor_by_expiry, n, &n->prioq_idx);
r = prioq_ensure_put(&lldp_rx->neighbor_by_expiry, lldp_neighbor_prioq_compare_func, n, &n->prioq_idx);
if (r < 0) {
assert_se(hashmap_remove(lldp_rx->neighbor_by_id, &n->id) == n);
goto finish;
@ -178,16 +178,12 @@ static int lldp_rx_handle_datagram(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) {
assert(n);
r = lldp_neighbor_parse(n);
if (r == -EBADMSG) /* Ignore bad messages */
return 0;
if (r < 0)
return r;
r = lldp_rx_add_neighbor(lldp_rx, n);
if (r < 0) {
log_lldp_rx_errno(lldp_rx, r, "Failed to add datagram. Ignoring.");
return 0;
}
if (r < 0)
return log_lldp_rx_errno(lldp_rx, r, "Failed to add datagram. Ignoring.");
log_lldp_rx(lldp_rx, "Successfully processed LLDP datagram.");
return 0;
@ -209,8 +205,10 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents
}
n = lldp_neighbor_new(space);
if (!n)
return -ENOMEM;
if (!n) {
log_oom_debug();
return 0;
}
length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
if (length < 0) {
@ -232,7 +230,8 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents
else
triple_timestamp_get(&n->timestamp);
return lldp_rx_handle_datagram(lldp_rx, n);
(void) lldp_rx_handle_datagram(lldp_rx, n);
return 0;
}
static void lldp_rx_reset(sd_lldp_rx *lldp_rx) {
@ -243,6 +242,13 @@ static void lldp_rx_reset(sd_lldp_rx *lldp_rx) {
lldp_rx->fd = safe_close(lldp_rx->fd);
}
int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx) {
if (!lldp_rx)
return false;
return lldp_rx->fd >= 0;
}
_public_ int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) {
int r;
@ -250,7 +256,7 @@ _public_ int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) {
assert_return(lldp_rx->event, -EINVAL);
assert_return(lldp_rx->ifindex > 0, -EINVAL);
if (lldp_rx->fd >= 0)
if (sd_lldp_rx_is_running(lldp_rx))
return 0;
assert(!lldp_rx->io_event_source);
@ -278,10 +284,7 @@ fail:
}
_public_ int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx) {
if (!lldp_rx)
return 0;
if (lldp_rx->fd < 0)
if (!sd_lldp_rx_is_running(lldp_rx))
return 0;
log_lldp_rx(lldp_rx, "Stopping LLDP client");
@ -296,7 +299,7 @@ _public_ int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64
int r;
assert_return(lldp_rx, -EINVAL);
assert_return(lldp_rx->fd < 0, -EBUSY);
assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY);
assert_return(!lldp_rx->event, -EBUSY);
if (event)
@ -313,10 +316,11 @@ _public_ int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64
}
_public_ int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx) {
assert_return(lldp_rx, -EINVAL);
assert_return(lldp_rx->fd < 0, -EBUSY);
assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY);
lldp_rx->io_event_source = sd_event_source_disable_unref(lldp_rx->io_event_source);
lldp_rx->timer_event_source = sd_event_source_disable_unref(lldp_rx->timer_event_source);
lldp_rx->event = sd_event_unref(lldp_rx->event);
return 0;
}
@ -339,7 +343,7 @@ _public_ int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t
_public_ int sd_lldp_rx_set_ifindex(sd_lldp_rx *lldp_rx, int ifindex) {
assert_return(lldp_rx, -EINVAL);
assert_return(ifindex > 0, -EINVAL);
assert_return(lldp_rx->fd < 0, -EBUSY);
assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY);
lldp_rx->ifindex = ifindex;
return 0;
@ -363,11 +367,11 @@ const char *sd_lldp_rx_get_ifname(sd_lldp_rx *lldp_rx) {
}
static sd_lldp_rx *lldp_rx_free(sd_lldp_rx *lldp_rx) {
assert(lldp_rx);
if (!lldp_rx)
return NULL;
lldp_rx_reset(lldp_rx);
sd_event_source_unref(lldp_rx->timer_event_source);
sd_lldp_rx_detach_event(lldp_rx);
lldp_rx_flush_neighbors(lldp_rx);
@ -382,7 +386,6 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp_rx, sd_lldp_rx, lldp_rx_free);
_public_ int sd_lldp_rx_new(sd_lldp_rx **ret) {
_cleanup_(sd_lldp_rx_unrefp) sd_lldp_rx *lldp_rx = NULL;
int r;
assert_return(ret, -EINVAL);
@ -397,23 +400,10 @@ _public_ int sd_lldp_rx_new(sd_lldp_rx **ret) {
.capability_mask = UINT16_MAX,
};
lldp_rx->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops);
if (!lldp_rx->neighbor_by_id)
return -ENOMEM;
r = prioq_ensure_allocated(&lldp_rx->neighbor_by_expiry, lldp_neighbor_prioq_compare_func);
if (r < 0)
return r;
*ret = TAKE_PTR(lldp_rx);
return 0;
}
static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) {
return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id);
}
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
sd_lldp_rx *lldp_rx = userdata;
int r;
@ -437,6 +427,7 @@ static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor)
sd_lldp_neighbor *n;
assert(lldp_rx);
assert(lldp_rx->event);
if (neighbor)
lldp_neighbor_start_ttl(neighbor);
@ -445,9 +436,6 @@ static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor)
if (!n)
return event_source_disable(lldp_rx->timer_event_source);
if (!lldp_rx->event)
return 0;
return event_reset_time(lldp_rx->event, &lldp_rx->timer_event_source,
clock_boottime_or_monotonic(),
n->until, 0,
@ -455,9 +443,19 @@ static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor)
lldp_rx->event_priority, "lldp-rx-timer", true);
}
static inline int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) {
assert(a);
assert(b);
assert(*a);
assert(*b);
return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id);
}
_public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***ret) {
sd_lldp_neighbor **l = NULL, *n;
int k = 0, r;
_cleanup_free_ sd_lldp_neighbor **l = NULL;
sd_lldp_neighbor *n;
int k = 0;
assert_return(lldp_rx, -EINVAL);
assert_return(ret, -EINVAL);
@ -471,12 +469,6 @@ _public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***r
if (!l)
return -ENOMEM;
r = lldp_rx_start_timer(lldp_rx, NULL);
if (r < 0) {
free(l);
return r;
}
HASHMAP_FOREACH(n, lldp_rx->neighbor_by_id)
l[k++] = sd_lldp_neighbor_ref(n);
@ -484,7 +476,7 @@ _public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***r
/* Return things in a stable order */
typesafe_qsort(l, k, neighbor_compare_func);
*ret = l;
*ret = TAKE_PTR(l);
return k;
}

View File

@ -1714,6 +1714,7 @@ static int run(int argc, char* argv[]) {
if (!strv_isempty(arg_cmdline) &&
arg_transport == BUS_TRANSPORT_LOCAL &&
!strv_find_startswith(arg_property, "RootDirectory=") &&
!strv_find_startswith(arg_property, "ExecSearchPath=") &&
!strv_find_startswith(arg_property, "RootImage=")) {
/* Patch in an absolute path to fail early for user convenience, but only when we can do it
* (i.e. we will be running from the same file system). This also uses the user's $PATH,

View File

@ -969,6 +969,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
"InaccessiblePaths",
"ExecPaths",
"NoExecPaths",
"ExecSearchPath",
"RuntimeDirectory",
"StateDirectory",
"CacheDirectory",
@ -1998,6 +1999,9 @@ static int bus_append_scope_property(sd_bus_message *m, const char *field, const
if (streq(field, "RuntimeMaxSec"))
return bus_append_parse_sec_rename(m, field, eq);
if (streq(field, "RuntimeRandomizedExtraSec"))
return bus_append_parse_sec_rename(m, field, eq);
if (streq(field, "TimeoutStopSec"))
return bus_append_parse_sec_rename(m, field, eq);
@ -2030,6 +2034,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
"TimeoutStopSec",
"TimeoutAbortSec",
"RuntimeMaxSec",
"RuntimeRandomizedExtraSec",
"WatchdogSec"))
return bus_append_parse_sec_rename(m, field, eq);

View File

@ -50,6 +50,7 @@ sd_lldp_rx *sd_lldp_rx_unref(sd_lldp_rx *lldp_rx);
int sd_lldp_rx_start(sd_lldp_rx *lldp_rx);
int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx);
int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx);
int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64_t priority);
int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx);

View File

@ -371,7 +371,7 @@ tests += [
[['src/test/test-hashmap.c',
'src/test/test-hashmap-plain.c',
test_hashmap_ordered_c],
[], [], [], '', 'timeout=90'],
[], [], [], '', 'timeout=180'],
[['src/test/test-set.c'],
[libbasic]],

View File

@ -8,6 +8,7 @@
#include "capability-util.h"
#include "cpu-set-util.h"
#include "copy.h"
#include "dropin.h"
#include "errno-list.h"
#include "fd-util.h"
@ -28,6 +29,7 @@
#include "static-destruct.h"
#include "stat-util.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "unit.h"
#include "user-util.h"
#include "util.h"
@ -273,6 +275,93 @@ static void test_exec_workingdirectory(Manager *m) {
(void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
}
static void test_exec_execsearchpath(Manager *m) {
assert_se(mkdir_p("/tmp/test-exec_execsearchpath", 0755) >= 0);
assert_se(copy_file("/bin/ls", "/tmp/test-exec_execsearchpath/ls_temp", 0, 0777, 0, 0, COPY_REPLACE) >= 0);
test(m, "exec-execsearchpath.service", 0, CLD_EXITED);
assert_se(rm_rf("/tmp/test-exec_execsearchpath", REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
test(m, "exec-execsearchpath.service", EXIT_EXEC, CLD_EXITED);
}
static void test_exec_execsearchpath_specifier(Manager *m) {
test(m, "exec-execsearchpath-unit-specifier.service", 0, CLD_EXITED);
}
static void test_exec_execsearchpath_environment(Manager *m) {
test(m, "exec-execsearchpath-environment.service", 0, CLD_EXITED);
test(m, "exec-execsearchpath-environment-path-set.service", 0, CLD_EXITED);
}
static void test_exec_execsearchpath_environment_files(Manager *m) {
static const char path_not_set[] =
"VAR1='word1 word2'\n"
"VAR2=word3 \n"
"# comment1\n"
"\n"
"; comment2\n"
" ; # comment3\n"
"line without an equal\n"
"VAR3='$word 5 6'\n"
"VAR4='new\nline'\n"
"VAR5=password\\with\\backslashes";
static const char path_set[] =
"VAR1='word1 word2'\n"
"VAR2=word3 \n"
"# comment1\n"
"\n"
"; comment2\n"
" ; # comment3\n"
"line without an equal\n"
"VAR3='$word 5 6'\n"
"VAR4='new\nline'\n"
"VAR5=password\\with\\backslashes\n"
"PATH=/usr";
int r;
r = write_string_file("/tmp/test-exec_execsearchpath_environmentfile.conf", path_not_set, WRITE_STRING_FILE_CREATE);
assert_se(r == 0);
test(m, "exec-execsearchpath-environmentfile.service", 0, CLD_EXITED);
(void) unlink("/tmp/test-exec_environmentfile.conf");
r = write_string_file("/tmp/test-exec_execsearchpath_environmentfile-set.conf", path_set, WRITE_STRING_FILE_CREATE);
assert_se(r == 0);
test(m, "exec-execsearchpath-environmentfile-set.service", 0, CLD_EXITED);
(void) unlink("/tmp/test-exec_environmentfile-set.conf");
}
static void test_exec_execsearchpath_passenvironment(Manager *m) {
assert_se(setenv("VAR1", "word1 word2", 1) == 0);
assert_se(setenv("VAR2", "word3", 1) == 0);
assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
assert_se(setenv("VAR4", "new\nline", 1) == 0);
assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
test(m, "exec-execsearchpath-passenvironment.service", 0, CLD_EXITED);
assert_se(setenv("PATH", "/usr", 1) == 0);
test(m, "exec-execsearchpath-passenvironment-set.service", 0, CLD_EXITED);
assert_se(unsetenv("VAR1") == 0);
assert_se(unsetenv("VAR2") == 0);
assert_se(unsetenv("VAR3") == 0);
assert_se(unsetenv("VAR4") == 0);
assert_se(unsetenv("VAR5") == 0);
assert_se(unsetenv("PATH") == 0);
}
static void test_exec_personality(Manager *m) {
#if defined(__x86_64__)
test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
@ -1089,11 +1178,16 @@ int main(int argc, char *argv[]) {
entry(test_exec_unsetenvironment),
entry(test_exec_user),
entry(test_exec_workingdirectory),
entry(test_exec_execsearchpath),
entry(test_exec_execsearchpath_environment),
entry(test_exec_execsearchpath_environment_files),
entry(test_exec_execsearchpath_passenvironment),
{},
};
static const test_entry system_tests[] = {
entry(test_exec_dynamicuser),
entry(test_exec_specifier),
entry(test_exec_execsearchpath_specifier),
entry(test_exec_systemcallfilter_system),
{},
};

View File

@ -6,6 +6,7 @@
#include "alloc-util.h"
#include "exec-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
#include "path-util.h"
#include "process-util.h"
@ -14,6 +15,7 @@
#include "string-util.h"
#include "strv.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "util.h"
static void test_print_paths(void) {
@ -201,15 +203,18 @@ static void test_path_equal_root(void) {
static void test_find_executable_full(void) {
char *p;
char* test_file_name;
_cleanup_close_ int fd = -1;
char fn[] = "/tmp/test-XXXXXX";
log_info("/* %s */", __func__);
assert_se(find_executable_full("sh", NULL, true, &p, NULL) == 0);
assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
assert_se(find_executable_full("sh", NULL, false, &p, NULL) == 0);
assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
@ -221,18 +226,31 @@ static void test_find_executable_full(void) {
assert_se(unsetenv("PATH") == 0);
assert_se(find_executable_full("sh", NULL, true, &p, NULL) == 0);
assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
assert_se(find_executable_full("sh", NULL, false, &p, NULL) == 0);
assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0);
puts(p);
assert_se(streq(basename(p), "sh"));
free(p);
if (oldpath)
assert_se(setenv("PATH", oldpath, true) >= 0);
assert_se((fd = mkostemp_safe(fn)) >= 0);
assert_se(fchmod(fd, 0755) >= 0);
test_file_name = basename(fn);
assert_se(find_executable_full(test_file_name, NULL, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p, NULL) == 0);
puts(p);
assert_se(streq(p, fn));
free(p);
(void) unlink(fn);
assert_se(find_executable_full(test_file_name, NULL, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p, NULL) == -ENOENT);
}
static void test_find_executable(const char *self) {
@ -277,7 +295,7 @@ static void test_find_executable_exec_one(const char *path) {
pid_t pid;
int r;
r = find_executable_full(path, NULL, false, &t, &fd);
r = find_executable_full(path, NULL, NULL, false, &t, &fd);
log_info_errno(r, "%s: %s → %s: %d/%m", __func__, path, t ?: "-", fd);

View File

@ -5,6 +5,7 @@ AllowedMemoryNodes=
AmbientCapabilities=
AppArmorProfile=
BPFProgram=
ExecSearchPath=
BindPaths=
BindReadOnlyPaths=
BlockIOAccounting=

View File

@ -50,6 +50,7 @@ NetClass=
RestartKillSignal=
RestrictNetworkInterfaces=
RuntimeMaxSec=
RuntimeRandomizedExtraSec=
SendSIGHUP=
SendSIGKILL=
Slice=

View File

@ -31,6 +31,7 @@ AssertUser=
AssertVirtualization=
BPFProgram=
Before=
ExecSearchPath=
BindTo=
BindsTo=
CollectMode=
@ -289,6 +290,7 @@ RuntimeDirectory=
RuntimeDirectoryMode=
RuntimeDirectoryPreserve=
RuntimeMaxSec=
RuntimeRandomizedExtraSec=
SELinuxContext=
SecureBits=
SendSIGHUP=

View File

@ -7,6 +7,7 @@ AmbientCapabilities=
AppArmorProfile=
BPFProgram=
Backlog=
ExecSearchPath=
BindIPv6Only=
BindPaths=
BindReadOnlyPaths=

View File

@ -5,6 +5,7 @@ AllowedMemoryNodes=
AmbientCapabilities=
AppArmorProfile=
BPFProgram=
ExecSearchPath=
BindPaths=
BindReadOnlyPaths=
BlockIOAccounting=

View File

@ -0,0 +1,5 @@
[Service]
ExecStart=/bin/sh -x -c 'test "$$PATH" = "/usr" && test "$$VAR1" = word3 && test "$$VAR2" = "\\$$word 5 6"'
Type=oneshot
ExecSearchPath=/tmp:/bin
Environment="PATH=/usr" VAR1=word3 "VAR2=$word 5 6"

View File

@ -0,0 +1,5 @@
[Service]
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$PATH" = "/tmp:/bin"'
Type=oneshot
ExecSearchPath=/tmp:/bin
Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for ExecSearchPath with EnvironmentFile where EnvironmentFile sets PATH
[Service]
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = /usr'
Type=oneshot
EnvironmentFile=/tmp/test-exec_execsearchpath_environmentfile-set.conf
ExecSearchPath=/tmp:/bin

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for ExecSearchPath with EnvironmentFile where EnvironmentFile does not set PATH
[Service]
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = "/tmp:/bin"'
Type=oneshot
ExecSearchPath=/tmp:/bin
EnvironmentFile=/tmp/test-exec_execsearchpath_environmentfile.conf

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for PassEnvironment with ExecSearchPath with PATH set by user
[Service]
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = "/usr"'
Type=oneshot
PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5 PATH
ExecSearchPath=/tmp:/bin

View File

@ -0,0 +1,8 @@
[Unit]
Description=Test for PassEnvironment with ExecSearchPath with PATH not set by user
[Service]
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = "/tmp:/bin"'
Type=oneshot
PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
ExecSearchPath=/tmp:/bin

View File

@ -0,0 +1,7 @@
[Unit]
Description=Test for specifiers with exec search path
[Service]
Type=oneshot
ExecSearchPath=/tmp:/bin:/usr/bin:%V
ExecStart=/bin/sh -x -c 'test %V = /var/tmp && test "$$PATH" = "/tmp:/bin:/usr/bin:/var/tmp"'

View File

@ -0,0 +1,4 @@
[Service]
ExecStart=ls_temp
Type=oneshot
ExecSearchPath=/tmp/test-exec_execsearchpath