Compare commits
16 Commits
03e55e7570
...
ee7b61685b
Author | SHA1 | Date |
---|---|---|
Andres Beltran | ee7b61685b | |
Antonio Alvarez Feijoo | fb4c82b643 | |
Daan De Meyer | 4d9ccdc9ae | |
Antonio Alvarez Feijoo | bf39626d61 | |
Marius Hoch | ff831e7c50 | |
Daan De Meyer | 81af8f998e | |
chenjiayi | 4fc8a63f9e | |
Jason Yundt | dfb3155419 | |
Daan De Meyer | fc5037e7d7 | |
Yu Watanabe | 13f6ec7ce7 | |
Yu Watanabe | 6e1816ef16 | |
Yu Watanabe | 7ac1ad90d0 | |
Daan De Meyer | 099b16c3e7 | |
Yu Watanabe | d265b8afb7 | |
Yu Watanabe | 1aab0a5b10 | |
Andres Beltran | 185b7307d9 |
|
@ -760,8 +760,9 @@ sensor:modalias:i2c:bmc150_accel:dmi:*:svnLENOVO:*:pvrLenovoYoga300-11IBR:*
|
||||||
sensor:modalias:acpi:ACCL0001*:dmi:*:svnLENOVO:pn60072:pvr851*:*
|
sensor:modalias:acpi:ACCL0001*:dmi:*:svnLENOVO:pn60072:pvr851*:*
|
||||||
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
|
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
|
||||||
|
|
||||||
# IdeaPad Duet 3 10IGL5 (82AT)
|
# IdeaPad Duet 3 10IGL5 (82AT) and 10IGL5-LTE (82HK)
|
||||||
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82AT:*
|
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82AT:*
|
||||||
|
sensor:modalias:acpi:SMO8B30*:dmi:*:svnLENOVO*:pn82HK:*
|
||||||
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
|
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
|
|
|
@ -593,8 +593,6 @@ node /org/freedesktop/systemd1 {
|
||||||
|
|
||||||
<!--method GetJobBefore is not documented!-->
|
<!--method GetJobBefore is not documented!-->
|
||||||
|
|
||||||
<!--method SetShowStatus is not documented!-->
|
|
||||||
|
|
||||||
<!--method ListUnitsFiltered is not documented!-->
|
<!--method ListUnitsFiltered is not documented!-->
|
||||||
|
|
||||||
<!--method ListUnitsByPatterns is not documented!-->
|
<!--method ListUnitsByPatterns is not documented!-->
|
||||||
|
@ -673,8 +671,6 @@ node /org/freedesktop/systemd1 {
|
||||||
|
|
||||||
<!--property ConfirmSpawn is not documented!-->
|
<!--property ConfirmSpawn is not documented!-->
|
||||||
|
|
||||||
<!--property ShowStatus is not documented!-->
|
|
||||||
|
|
||||||
<!--property DefaultStandardOutput is not documented!-->
|
<!--property DefaultStandardOutput is not documented!-->
|
||||||
|
|
||||||
<!--property DefaultStandardError is not documented!-->
|
<!--property DefaultStandardError is not documented!-->
|
||||||
|
@ -1362,6 +1358,24 @@ node /org/freedesktop/systemd1 {
|
||||||
|
|
||||||
<para><function>ResetFailedUnit()</function> resets the "failed" state of a specific unit.</para>
|
<para><function>ResetFailedUnit()</function> resets the "failed" state of a specific unit.</para>
|
||||||
|
|
||||||
|
<para><function>SetShowStatus()</function> configures the display of status messages during bootup and
|
||||||
|
shutdown. The <varname>mode</varname> parameter can be set to any value that's valid for the
|
||||||
|
<varname>systemd.show_status</varname> kernel parameter. For more information about
|
||||||
|
<varname>systemd.show_status</varname>, see
|
||||||
|
<citerefentry project="man-pages"><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
|
||||||
|
The <varname>mode</varname> parameter can also be set to an empty string. When <varname>mode</varname>
|
||||||
|
is set to an empty string, <function>SetShowStatus()</function> will reset
|
||||||
|
<varname>ShowStatus</varname> back to its original value. You can use
|
||||||
|
<function>SetShowStatus()</function> create a service that does something like this:
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>Send a D-Bus message that will turn off status messages.</para></listitem>
|
||||||
|
<listitem><para>Block until a reply to that message is received.</para></listitem>
|
||||||
|
<listitem><para>Print multiples lines without being interrupted by status messages.</para></listitem>
|
||||||
|
<listitem><para>Send a D-Bus message that will reset <varname>ShowStatus</varname> back to its
|
||||||
|
original value.</para></listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
<para><function>ResetFailed()</function> resets the "failed" state of all units.</para>
|
<para><function>ResetFailed()</function> resets the "failed" state of all units.</para>
|
||||||
|
|
||||||
<para><function>ListUnits()</function> returns an array of all currently loaded units. Note that
|
<para><function>ListUnits()</function> returns an array of all currently loaded units. Note that
|
||||||
|
@ -1788,6 +1802,12 @@ node /org/freedesktop/systemd1 {
|
||||||
<para><varname>Environment</varname> encodes the environment block passed to all executed services. It
|
<para><varname>Environment</varname> encodes the environment block passed to all executed services. It
|
||||||
may be altered with bus calls such as <function>SetEnvironment()</function> (see above).</para>
|
may be altered with bus calls such as <function>SetEnvironment()</function> (see above).</para>
|
||||||
|
|
||||||
|
<para><varname>ShowStatus</varname> encodes systemd's current policy for displaying status messages
|
||||||
|
during bootup and shutdown. Its value can be any valid value for the
|
||||||
|
<varname>systemd.show_status</varname> kernel parameter (see
|
||||||
|
<citerefentry project="man-pages"><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
|
||||||
|
It may be altered using <function>SetShowStatus()</function> (see above).</para>
|
||||||
|
|
||||||
<para><varname>UnitPath</varname> encodes the currently active unit file search path. It is an array of
|
<para><varname>UnitPath</varname> encodes the currently active unit file search path. It is an array of
|
||||||
file system paths encoded as strings.</para>
|
file system paths encoded as strings.</para>
|
||||||
|
|
||||||
|
|
|
@ -483,18 +483,18 @@
|
||||||
<term><varname>ExcludeFiles=</varname></term>
|
<term><varname>ExcludeFiles=</varname></term>
|
||||||
<term><varname>ExcludeFilesTarget=</varname></term>
|
<term><varname>ExcludeFilesTarget=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Takes an absolute file system path referring to a source file or directory on the
|
<listitem><para>Takes one or more absolute paths, separated by whitespace, each referring to a
|
||||||
host. This setting may be used to exclude files or directories from the host from being copied into
|
source file or directory on the host. This setting may be used to exclude files or directories from
|
||||||
the file system when <varname>CopyFiles=</varname> is used. This option may be used multiple times to
|
the host from being copied into the file system when <varname>CopyFiles=</varname> is used. This
|
||||||
exclude multiple files or directories from host from being copied into the newly formatted file
|
option may be used multiple times to exclude multiple files or directories from host from being
|
||||||
system.</para>
|
copied into the newly formatted file system.</para>
|
||||||
|
|
||||||
<para>If the path is a directory and ends with <literal>/</literal>, only the directory's
|
<para>If the path is a directory and ends with <literal>/</literal>, only the directory's
|
||||||
contents are excluded but not the directory itself. If the path is a directory and does not end with
|
contents are excluded but not the directory itself. If the path is a directory and does not end with
|
||||||
<literal>/</literal>, both the directory and its contents are excluded.</para>
|
<literal>/</literal>, both the directory and its contents are excluded.</para>
|
||||||
|
|
||||||
<para><varname>ExcludeFilesTarget=</varname> is like <varname>ExcludeFiles=</varname> except that
|
<para><varname>ExcludeFilesTarget=</varname> is like <varname>ExcludeFiles=</varname> except that
|
||||||
instead of excluding the path on the host from being copied into the partition, we exclude any files
|
instead of excluding the path on the host from being copied into the partition, it exclude any files
|
||||||
and directories from being copied into the given path in the partition.</para>
|
and directories from being copied into the given path in the partition.</para>
|
||||||
|
|
||||||
<para>When
|
<para>When
|
||||||
|
@ -922,9 +922,9 @@
|
||||||
target for some other supplement definition. A target cannot have more than one supplement partition
|
target for some other supplement definition. A target cannot have more than one supplement partition
|
||||||
associated with it.</para>
|
associated with it.</para>
|
||||||
|
|
||||||
<para>For example, distributions can use this to implement <variable>$BOOT</variable> as defined in
|
<para>For example, distributions can use this to implement <varname>$BOOT</varname> as defined in
|
||||||
the <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification/">Boot Loader
|
the <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification/">Boot Loader
|
||||||
Specification</ulink>. Distributions may prefer to use the ESP as <variable>$BOOT</variable> whenever
|
Specification</ulink>. Distributions may prefer to use the ESP as <varname>$BOOT</varname> whenever
|
||||||
possible, but to adhere to the spec XBOOTLDR must sometimes be used instead. So, they should create
|
possible, but to adhere to the spec XBOOTLDR must sometimes be used instead. So, they should create
|
||||||
two definitions: the first defining an ESP big enough to hold just the bootloader, and a second for
|
two definitions: the first defining an ESP big enough to hold just the bootloader, and a second for
|
||||||
the XBOOTLDR that's sufficiently large to hold kernels and configured as a supplement for the ESP.
|
the XBOOTLDR that's sufficiently large to hold kernels and configured as a supplement for the ESP.
|
||||||
|
|
|
@ -1476,6 +1476,12 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||||
below the locations defined in the following table. Also, the corresponding environment variable will
|
below the locations defined in the following table. Also, the corresponding environment variable will
|
||||||
be defined with the full paths of the directories. If multiple directories are set, then in the
|
be defined with the full paths of the directories. If multiple directories are set, then in the
|
||||||
environment variable the paths are concatenated with colon (<literal>:</literal>).</para>
|
environment variable the paths are concatenated with colon (<literal>:</literal>).</para>
|
||||||
|
|
||||||
|
<para>If the kernel version suppors <ulink url="https://lwn.net/Articles/896255/">id-mapped mounts</ulink>,
|
||||||
|
the specified directories will be owned by "nobody" in the host namespace and will be mapped to (and will be
|
||||||
|
owned by) the service's UID/GUID in its own namespace. For backward compatibility, existing directories
|
||||||
|
created without id-mapped mounts will be kept untouched.</para>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<title>Automatic directory creation and environment variables</title>
|
<title>Automatic directory creation and environment variables</title>
|
||||||
<tgroup cols='4'>
|
<tgroup cols='4'>
|
||||||
|
@ -3001,7 +3007,12 @@ SystemCallErrorNumber=EPERM</programlisting>
|
||||||
|
|
||||||
<para><option>tty</option> connects standard output to a tty (as configured via <varname>TTYPath=</varname>,
|
<para><option>tty</option> connects standard output to a tty (as configured via <varname>TTYPath=</varname>,
|
||||||
see below). If the TTY is used for output only, the executed process will not become the controlling process of
|
see below). If the TTY is used for output only, the executed process will not become the controlling process of
|
||||||
the terminal, and will not fail or wait for other processes to release the terminal.</para>
|
the terminal, and will not fail or wait for other processes to release the terminal. Note: if a unit
|
||||||
|
tries to print multiple lines to a TTY during bootup or shutdown, then there's a chance that those
|
||||||
|
lines will be broken up by status messages. <function>SetShowStatus()</function> can be used to
|
||||||
|
prevent this problem. See
|
||||||
|
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
for details.</para>
|
||||||
|
|
||||||
<para><option>journal</option> connects standard output with the journal, which is accessible via
|
<para><option>journal</option> connects standard output with the journal, which is accessible via
|
||||||
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. Note
|
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>. Note
|
||||||
|
|
|
@ -568,7 +568,11 @@
|
||||||
<listitem><para>Enables display of status messages on the
|
<listitem><para>Enables display of status messages on the
|
||||||
console, as controlled via
|
console, as controlled via
|
||||||
<varname>systemd.show_status=1</varname> on the kernel command
|
<varname>systemd.show_status=1</varname> on the kernel command
|
||||||
line.</para></listitem>
|
line.</para>
|
||||||
|
<para>You may want to use <function>SetShowStatus()</function> instead of
|
||||||
|
<constant>SIGRTMIN+20</constant> in order to prevent race conditions. See
|
||||||
|
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||||
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -579,7 +583,11 @@
|
||||||
controlled via
|
controlled via
|
||||||
<varname>systemd.show_status=0</varname>
|
<varname>systemd.show_status=0</varname>
|
||||||
on the kernel command
|
on the kernel command
|
||||||
line.</para></listitem>
|
line.</para>
|
||||||
|
<para>You may want to use <function>SetShowStatus()</function> instead of
|
||||||
|
<constant>SIGRTMIN+21</constant> in order to prevent race conditions. See
|
||||||
|
<citerefentry project="man-pages"><refentrytitle>org.freedesktop.systemd1</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||||
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
@ -2280,6 +2280,42 @@ static int create_many_symlinks(const char *root, const char *source, char **sym
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_idmapping_supported(const char *path) {
|
||||||
|
_cleanup_close_ int mount_fd = -EBADF, userns_fd = -EBADF, dir_fd = -EBADF;
|
||||||
|
_cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
dir_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
|
||||||
|
if (dir_fd < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mount_fd = open_tree(dir_fd, "", AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
|
||||||
|
if (mount_fd < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
r = strextendf(&uid_map, UID_FMT " " UID_FMT " " UID_FMT "\n", UID_NOBODY, UID_NOBODY, 1u);
|
||||||
|
if (r < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
r = strextendf(&gid_map, GID_FMT " " GID_FMT " " GID_FMT "\n", GID_NOBODY, GID_NOBODY, 1u);
|
||||||
|
if (r < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
userns_fd = userns_acquire(uid_map, gid_map);
|
||||||
|
if (userns_fd < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
r = mount_setattr(mount_fd, "", AT_EMPTY_PATH,
|
||||||
|
&(struct mount_attr) {
|
||||||
|
.attr_set = MOUNT_ATTR_IDMAP,
|
||||||
|
.userns_fd = userns_fd,
|
||||||
|
}, sizeof(struct mount_attr));
|
||||||
|
if (r < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int setup_exec_directory(
|
static int setup_exec_directory(
|
||||||
const ExecContext *context,
|
const ExecContext *context,
|
||||||
const ExecParameters *params,
|
const ExecParameters *params,
|
||||||
|
@ -2563,12 +2599,37 @@ static int setup_exec_directory(
|
||||||
if (params->runtime_scope != RUNTIME_SCOPE_SYSTEM)
|
if (params->runtime_scope != RUNTIME_SCOPE_SYSTEM)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Then, change the ownership of the whole tree, if necessary. When dynamic users are used we
|
/* Use 'nobody' uid/gid for exec directories if ID-mapping is supported. For backward compatibility,
|
||||||
* drop the suid/sgid bits, since we really don't want SUID/SGID files for dynamic UID/GID
|
* continue doing chmod/chown if the directory was chmod/chowned before (if uid/gid is not 'nobody') */
|
||||||
* assignments to exist. */
|
bool idmapping_supported = is_idmapping_supported(pp ?: p);
|
||||||
r = path_chown_recursive(pp ?: p, uid, gid, context->dynamic_user ? 01777 : 07777, AT_SYMLINK_FOLLOW);
|
log_debug("ID-mapping is%s supported for exec directory %s", idmapping_supported ? "" : "not", pp ?: p);
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
r = RET_NERRNO(stat(pp ?: p, &st));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/* Change the ownership of the whole tree, if necessary. When dynamic users are used we
|
||||||
|
* drop the suid/sgid bits, since we really don't want SUID/SGID files for dynamic UID/GID
|
||||||
|
* assignments to exist. */
|
||||||
|
if (uid == 0 || gid == 0) {
|
||||||
|
i->idmapped = false;
|
||||||
|
r = path_chown_recursive(pp ?: p, uid, gid, context->dynamic_user ? 01777 : 07777, AT_SYMLINK_FOLLOW);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
}else if (idmapping_supported && st.st_uid == UID_NOBODY && st.st_gid == GID_NOBODY) {
|
||||||
|
i->idmapped = true;
|
||||||
|
}else if (idmapping_supported && st.st_uid == (uid_t)0 && st.st_gid == (gid_t)0) {
|
||||||
|
r = path_chown_recursive(pp ?: p, UID_NOBODY, GID_NOBODY, context->dynamic_user ? 01777 : 07777, AT_SYMLINK_FOLLOW);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
i->idmapped = true;
|
||||||
|
}else {
|
||||||
|
i->idmapped = false;
|
||||||
|
r = path_chown_recursive(pp ?: p, uid, gid, context->dynamic_user ? 01777 : 07777, AT_SYMLINK_FOLLOW);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are not going to run in a namespace, set up the symlinks - otherwise
|
/* If we are not going to run in a namespace, set up the symlinks - otherwise
|
||||||
|
@ -2620,6 +2681,8 @@ static int setup_smack(
|
||||||
static int compile_bind_mounts(
|
static int compile_bind_mounts(
|
||||||
const ExecContext *context,
|
const ExecContext *context,
|
||||||
const ExecParameters *params,
|
const ExecParameters *params,
|
||||||
|
uid_t uid,
|
||||||
|
gid_t gid,
|
||||||
BindMount **ret_bind_mounts,
|
BindMount **ret_bind_mounts,
|
||||||
size_t *ret_n_bind_mounts,
|
size_t *ret_n_bind_mounts,
|
||||||
char ***ret_empty_directories) {
|
char ***ret_empty_directories) {
|
||||||
|
@ -2718,6 +2781,9 @@ static int compile_bind_mounts(
|
||||||
.destination = TAKE_PTR(d),
|
.destination = TAKE_PTR(d),
|
||||||
.nosuid = context->dynamic_user, /* don't allow suid/sgid when DynamicUser= is on */
|
.nosuid = context->dynamic_user, /* don't allow suid/sgid when DynamicUser= is on */
|
||||||
.recursive = true,
|
.recursive = true,
|
||||||
|
.idmapped = i->idmapped,
|
||||||
|
.uid = uid,
|
||||||
|
.gid = gid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3040,7 +3106,9 @@ static int apply_mount_namespace(
|
||||||
ExecRuntime *runtime,
|
ExecRuntime *runtime,
|
||||||
const char *memory_pressure_path,
|
const char *memory_pressure_path,
|
||||||
bool needs_sandboxing,
|
bool needs_sandboxing,
|
||||||
char **error_path) {
|
char **error_path,
|
||||||
|
uid_t uid,
|
||||||
|
gid_t gid) {
|
||||||
|
|
||||||
_cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
|
_cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT;
|
||||||
_cleanup_strv_free_ char **empty_directories = NULL, **symlinks = NULL,
|
_cleanup_strv_free_ char **empty_directories = NULL, **symlinks = NULL,
|
||||||
|
@ -3076,7 +3144,7 @@ static int apply_mount_namespace(
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = compile_bind_mounts(context, params, &bind_mounts, &n_bind_mounts, &empty_directories);
|
r = compile_bind_mounts(context, params, uid, gid, &bind_mounts, &n_bind_mounts, &empty_directories);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -4830,7 +4898,9 @@ int exec_invoke(
|
||||||
runtime,
|
runtime,
|
||||||
memory_pressure_path,
|
memory_pressure_path,
|
||||||
needs_sandboxing,
|
needs_sandboxing,
|
||||||
&error_path);
|
&error_path,
|
||||||
|
uid,
|
||||||
|
gid);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
*exit_status = EXIT_NAMESPACE;
|
*exit_status = EXIT_NAMESPACE;
|
||||||
return log_exec_error_errno(context, params, r, "Failed to set up mount namespacing%s%s: %m",
|
return log_exec_error_errno(context, params, r, "Failed to set up mount namespacing%s%s: %m",
|
||||||
|
|
|
@ -2721,6 +2721,7 @@ int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink)
|
||||||
d->items[d->n_items++] = (ExecDirectoryItem) {
|
d->items[d->n_items++] = (ExecDirectoryItem) {
|
||||||
.path = TAKE_PTR(p),
|
.path = TAKE_PTR(p),
|
||||||
.symlinks = TAKE_PTR(s),
|
.symlinks = TAKE_PTR(s),
|
||||||
|
.idmapped = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return 1; /* new item is added */
|
return 1; /* new item is added */
|
||||||
|
|
|
@ -156,6 +156,7 @@ typedef struct ExecDirectoryItem {
|
||||||
char *path;
|
char *path;
|
||||||
char **symlinks;
|
char **symlinks;
|
||||||
bool only_create;
|
bool only_create;
|
||||||
|
bool idmapped;
|
||||||
} ExecDirectoryItem;
|
} ExecDirectoryItem;
|
||||||
|
|
||||||
typedef struct ExecDirectory {
|
typedef struct ExecDirectory {
|
||||||
|
|
|
@ -113,6 +113,9 @@ typedef struct MountEntry {
|
||||||
LIST_HEAD(MountOptions, image_options_const);
|
LIST_HEAD(MountOptions, image_options_const);
|
||||||
char **overlay_layers;
|
char **overlay_layers;
|
||||||
VeritySettings verity;
|
VeritySettings verity;
|
||||||
|
bool idmapped;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
} MountEntry;
|
} MountEntry;
|
||||||
|
|
||||||
typedef struct MountList {
|
typedef struct MountList {
|
||||||
|
@ -451,6 +454,9 @@ static int append_bind_mounts(MountList *ml, const BindMount *binds, size_t n) {
|
||||||
.flags = b->nodev ? MS_NODEV : 0,
|
.flags = b->nodev ? MS_NODEV : 0,
|
||||||
.source_const = b->source,
|
.source_const = b->source,
|
||||||
.ignore = b->ignore_enoent,
|
.ignore = b->ignore_enoent,
|
||||||
|
.idmapped = b->idmapped,
|
||||||
|
.uid = b->uid,
|
||||||
|
.gid = b->gid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1806,6 +1812,48 @@ static int apply_one_mount(
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("Successfully mounted %s to %s", what, mount_entry_path(m));
|
log_debug("Successfully mounted %s to %s", what, mount_entry_path(m));
|
||||||
|
|
||||||
|
/* Take care of id-mapped mounts */
|
||||||
|
if (m->idmapped && uid_is_valid(m->uid) && gid_is_valid(m->gid)) {
|
||||||
|
_cleanup_close_ int userns_fd = -EBADF;
|
||||||
|
_cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
|
||||||
|
|
||||||
|
log_debug("Setting an id-mapped mount on %s", mount_entry_path(m));
|
||||||
|
|
||||||
|
// Do mapping from nobody (in setup_exec_directory()) -> this uid
|
||||||
|
r = strextendf(&uid_map, UID_FMT " " UID_FMT " " UID_FMT "\n", UID_NOBODY, m->uid, 1u);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
// Consider StateDirectory=xxx aaa xxx:aaa/222
|
||||||
|
// To allow for later symlink creation (by root) in create_symlinks_from_tuples(), map root as well
|
||||||
|
if (m->uid != (uid_t)0) {
|
||||||
|
r = strextendf(&uid_map, UID_FMT " " UID_FMT " " UID_FMT "\n", (uid_t)0, (uid_t)0, 1u);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
r = strextendf(&gid_map, GID_FMT " " GID_FMT " " GID_FMT "\n", GID_NOBODY, m->gid, 1u);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (m->gid != (gid_t)0) {
|
||||||
|
r = strextendf(&gid_map, GID_FMT " " GID_FMT " " GID_FMT "\n", (gid_t)0, (gid_t)0, 1u);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
userns_fd = userns_acquire(uid_map, gid_map);
|
||||||
|
if (userns_fd < 0)
|
||||||
|
return log_error_errno(userns_fd, "Failed to allocate user namespace: %m");
|
||||||
|
|
||||||
|
r = remount_idmap_fd(STRV_MAKE(mount_entry_path(m)), userns_fd);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to create an id-mapped mount: %m");
|
||||||
|
|
||||||
|
log_debug("ID-mapped mount created successfully for %s from %u to %u", mount_entry_path(m), UID_NOBODY, m->uid);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,9 @@ struct BindMount {
|
||||||
bool noexec;
|
bool noexec;
|
||||||
bool recursive;
|
bool recursive;
|
||||||
bool ignore_enoent;
|
bool ignore_enoent;
|
||||||
|
bool idmapped;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TemporaryFileSystem {
|
struct TemporaryFileSystem {
|
||||||
|
|
|
@ -4169,7 +4169,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
* detect when the cgroup becomes empty. Note that the control process is always
|
* detect when the cgroup becomes empty. Note that the control process is always
|
||||||
* our child so it's pointless to watch all other processes. */
|
* our child so it's pointless to watch all other processes. */
|
||||||
if (!control_pid_good(s))
|
if (!control_pid_good(s))
|
||||||
if (!s->main_pid_known || s->main_pid_alien)
|
if (!s->main_pid_known || s->main_pid_alien || unit_cgroup_delegate(u))
|
||||||
(void) unit_enqueue_rewatch_pids(u);
|
(void) unit_enqueue_rewatch_pids(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -404,15 +404,16 @@ static int context_set_path_strv(Context *c, char* const* strv, const char *sour
|
||||||
|
|
||||||
static int context_set_plugins(Context *c, const char *s, const char *source) {
|
static int context_set_plugins(Context *c, const char *s, const char *source) {
|
||||||
_cleanup_strv_free_ char **v = NULL;
|
_cleanup_strv_free_ char **v = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
if (c->plugins || !s)
|
if (c->plugins || !s)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
v = strv_split(s, NULL);
|
r = strv_split_full(&v, s, NULL, EXTRACT_UNQUOTE);
|
||||||
if (!v)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_error_errno(r, "Failed to parse plugin paths from %s: %m", source);
|
||||||
|
|
||||||
return context_set_path_strv(c, v, source, "plugins", &c->plugins);
|
return context_set_path_strv(c, v, source, "plugins", &c->plugins);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,13 @@ echo 'DTBDTBDTBDTB' >"$D/sources/subdir/whatever.dtb"
|
||||||
|
|
||||||
export KERNEL_INSTALL_CONF_ROOT="$D/sources"
|
export KERNEL_INSTALL_CONF_ROOT="$D/sources"
|
||||||
# We "install" multiple plugins, but control which ones will be active via install.conf.
|
# We "install" multiple plugins, but control which ones will be active via install.conf.
|
||||||
export KERNEL_INSTALL_PLUGINS="${ukify_install} ${loaderentry_install} ${uki_copy_install}"
|
KERNEL_INSTALL_PLUGINS="'${loaderentry_install}' '${uki_copy_install}'"
|
||||||
|
if [[ -n "$ukify_install" ]]; then
|
||||||
|
# shellcheck disable=SC2089
|
||||||
|
KERNEL_INSTALL_PLUGINS="'${ukify_install}' $KERNEL_INSTALL_PLUGINS"
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2090
|
||||||
|
export KERNEL_INSTALL_PLUGINS
|
||||||
export BOOT_ROOT="$D/boot"
|
export BOOT_ROOT="$D/boot"
|
||||||
export BOOT_MNT="$D/boot"
|
export BOOT_MNT="$D/boot"
|
||||||
export MACHINE_ID='3e0484f3634a418b8e6a39e8828b03e3'
|
export MACHINE_ID='3e0484f3634a418b8e6a39e8828b03e3'
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
|
|
||||||
#include "bpf-dlopen.h"
|
#include "bpf-dlopen.h"
|
||||||
|
#if HAVE_VMLINUX_H
|
||||||
#include "bpf-link.h"
|
#include "bpf-link.h"
|
||||||
|
#endif
|
||||||
#include "build-path.h"
|
#include "build-path.h"
|
||||||
#include "common-signal.h"
|
#include "common-signal.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
|
|
|
@ -304,19 +304,6 @@ static SubvolumeFlags subvolume_flags_from_string(const char *s) {
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* subvolume_flags_to_string(SubvolumeFlags flags) {
|
|
||||||
const char *l[CONST_LOG2U(_SUBVOLUME_FLAGS_MASK + 1) + 1]; /* one string per known flag at most */
|
|
||||||
size_t m = 0;
|
|
||||||
|
|
||||||
if (FLAGS_SET(flags, SUBVOLUME_RO))
|
|
||||||
l[m++] = "ro";
|
|
||||||
|
|
||||||
assert(m < ELEMENTSOF(l));
|
|
||||||
l[m] = NULL;
|
|
||||||
|
|
||||||
return strv_join((char**) l, ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct Subvolume {
|
typedef struct Subvolume {
|
||||||
char *path;
|
char *path;
|
||||||
SubvolumeFlags flags;
|
SubvolumeFlags flags;
|
||||||
|
@ -1742,8 +1729,9 @@ static int config_parse_exclude_files(
|
||||||
const char *rvalue,
|
const char *rvalue,
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
_cleanup_free_ char *resolved = NULL;
|
|
||||||
char ***exclude_files = ASSERT_PTR(data);
|
char ***exclude_files = ASSERT_PTR(data);
|
||||||
|
const char *p = ASSERT_PTR(rvalue);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (isempty(rvalue)) {
|
if (isempty(rvalue)) {
|
||||||
|
@ -1751,20 +1739,34 @@ static int config_parse_exclude_files(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
|
for (;;) {
|
||||||
if (r < 0) {
|
_cleanup_free_ char *word = NULL, *resolved = NULL;
|
||||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
|
||||||
"Failed to expand specifiers in ExcludeFiles= path, ignoring: %s", rvalue);
|
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
|
||||||
return 0;
|
if (r == -ENOMEM)
|
||||||
|
return log_oom();
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (r == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = specifier_printf(word, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, NULL, &resolved);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Failed to expand specifiers in %s path, ignoring: %s", lvalue, word);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE|PATH_KEEP_TRAILING_SLASH, unit, filename, line, lvalue);
|
||||||
|
if (r < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strv_consume(exclude_files, TAKE_PTR(resolved)) < 0)
|
||||||
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|
||||||
r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE|PATH_KEEP_TRAILING_SLASH, unit, filename, line, lvalue);
|
|
||||||
if (r < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strv_consume(exclude_files, TAKE_PTR(resolved)) < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2423,6 +2425,14 @@ static int partition_read_definition(Partition *p, const char *path, const char
|
||||||
"SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s.",
|
"SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s.",
|
||||||
verity_mode_to_string(p->verity));
|
verity_mode_to_string(p->verity));
|
||||||
|
|
||||||
|
if (!ordered_hashmap_isempty(p->subvolumes) && arg_offline > 0)
|
||||||
|
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
"Subvolumes= cannot be used with --offline=yes.");
|
||||||
|
|
||||||
|
if (p->default_subvolume && arg_offline > 0)
|
||||||
|
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
"DefaultSubvolume= cannot be used with --offline=yes.");
|
||||||
|
|
||||||
if (p->default_subvolume && !ordered_hashmap_contains(p->subvolumes, p->default_subvolume))
|
if (p->default_subvolume && !ordered_hashmap_contains(p->subvolumes, p->default_subvolume))
|
||||||
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL),
|
||||||
"DefaultSubvolume= must be one of the paths in Subvolumes=.");
|
"DefaultSubvolume= must be one of the paths in Subvolumes=.");
|
||||||
|
@ -4271,7 +4281,7 @@ static int prepare_temporary_file(Context *context, PartitionTarget *t, uint64_t
|
||||||
|
|
||||||
static bool loop_device_error_is_fatal(const Partition *p, int r) {
|
static bool loop_device_error_is_fatal(const Partition *p, int r) {
|
||||||
assert(p);
|
assert(p);
|
||||||
return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r));
|
return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !ordered_hashmap_isempty(p->subvolumes) || p->default_subvolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int partition_target_prepare(
|
static int partition_target_prepare(
|
||||||
|
@ -5778,38 +5788,6 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int append_btrfs_subvols(char ***l, OrderedHashmap *subvolumes, const char *default_subvolume) {
|
|
||||||
Subvolume *subvolume;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(l);
|
|
||||||
|
|
||||||
ORDERED_HASHMAP_FOREACH(subvolume, subvolumes) {
|
|
||||||
_cleanup_free_ char *s = NULL, *f = NULL;
|
|
||||||
|
|
||||||
s = strdup(subvolume->path);
|
|
||||||
if (!s)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
f = subvolume_flags_to_string(subvolume->flags);
|
|
||||||
if (!f)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (streq_ptr(subvolume->path, default_subvolume) &&
|
|
||||||
!strextend_with_separator(&f, ",", "default"))
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (!isempty(f) && !strextend_with_separator(&s, ":", f))
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
r = strv_extend_many(l, "--subvol", s);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) {
|
static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) {
|
||||||
_cleanup_strv_free_ char **sv = NULL;
|
_cleanup_strv_free_ char **sv = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
@ -5823,18 +5801,6 @@ static int finalize_extra_mkfs_options(const Partition *p, const char *root, cha
|
||||||
"Failed to determine mkfs command line options for '%s': %m",
|
"Failed to determine mkfs command line options for '%s': %m",
|
||||||
p->format);
|
p->format);
|
||||||
|
|
||||||
if (partition_needs_populate(p) && root && streq(p->format, "btrfs")) {
|
|
||||||
r = append_btrfs_subvols(&sv, p->subvolumes, p->default_subvolume);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (p->suppressing) {
|
|
||||||
r = append_btrfs_subvols(&sv, p->suppressing->subvolumes, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*ret = TAKE_PTR(sv);
|
*ret = TAKE_PTR(sv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ _unused_ static void test_compress_stream(const char *compression,
|
||||||
ASSERT_OK(compress(src, dst, -1, &uncompressed_size));
|
ASSERT_OK(compress(src, dst, -1, &uncompressed_size));
|
||||||
|
|
||||||
if (cat) {
|
if (cat) {
|
||||||
assert_se(asprintf(&cmd, "%s %s | diff %s -", cat, pattern, srcfile) > 0);
|
assert_se(asprintf(&cmd, "%s %s | diff '%s' -", cat, pattern, srcfile) > 0);
|
||||||
assert_se(system(cmd) == 0);
|
assert_se(system(cmd) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ _unused_ static void test_compress_stream(const char *compression,
|
||||||
r = decompress(dst, dst2, st.st_size);
|
r = decompress(dst, dst2, st.st_size);
|
||||||
assert_se(r == 0);
|
assert_se(r == 0);
|
||||||
|
|
||||||
assert_se(asprintf(&cmd2, "diff %s %s", srcfile, pattern2) > 0);
|
assert_se(asprintf(&cmd2, "diff '%s' %s", srcfile, pattern2) > 0);
|
||||||
assert_se(system(cmd2) == 0);
|
assert_se(system(cmd2) == 0);
|
||||||
|
|
||||||
log_debug("/* test faulty decompression */");
|
log_debug("/* test faulty decompression */");
|
||||||
|
|
|
@ -52,7 +52,8 @@ static void test_event_spawn_self(const char *self, const char *arg, bool with_p
|
||||||
|
|
||||||
log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd));
|
log_debug("/* %s(%s, %s) */", __func__, arg, yes_no(with_pidfd));
|
||||||
|
|
||||||
assert_se(cmd = strjoin(self, " ", arg));
|
/* 'self' may contain spaces, hence needs to be quoted. */
|
||||||
|
assert_se(cmd = strjoin("'", self, "' ", arg));
|
||||||
|
|
||||||
test_event_spawn_core(with_pidfd, cmd, result_buf, BUF_SIZE);
|
test_event_spawn_core(with_pidfd, cmd, result_buf, BUF_SIZE);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
set -e
|
|
||||||
|
|
||||||
TEST_DESCRIPTION="Test Multi-Profile UKI Boots"
|
|
||||||
|
|
||||||
# shellcheck source=test/test-functions
|
|
||||||
. "${TEST_BASE_DIR:?}/test-functions"
|
|
||||||
|
|
||||||
do_test "$@"
|
|
|
@ -4,32 +4,32 @@ set -e
|
||||||
|
|
||||||
ANALYZE="${1:-systemd-analyze}"
|
ANALYZE="${1:-systemd-analyze}"
|
||||||
|
|
||||||
$ANALYZE compare-versions 1 lt 2
|
"$ANALYZE" compare-versions 1 lt 2
|
||||||
$ANALYZE compare-versions 1 '<' 2
|
"$ANALYZE" compare-versions 1 '<' 2
|
||||||
$ANALYZE compare-versions 1 le 2
|
"$ANALYZE" compare-versions 1 le 2
|
||||||
$ANALYZE compare-versions 1 '<=' 2
|
"$ANALYZE" compare-versions 1 '<=' 2
|
||||||
$ANALYZE compare-versions 1 ne 2
|
"$ANALYZE" compare-versions 1 ne 2
|
||||||
$ANALYZE compare-versions 1 '!=' 2
|
"$ANALYZE" compare-versions 1 '!=' 2
|
||||||
( ! $ANALYZE compare-versions 1 ge 2 )
|
( ! "$ANALYZE" compare-versions 1 ge 2 )
|
||||||
( ! $ANALYZE compare-versions 1 '>=' 2 )
|
( ! "$ANALYZE" compare-versions 1 '>=' 2 )
|
||||||
( ! $ANALYZE compare-versions 1 eq 2 )
|
( ! "$ANALYZE" compare-versions 1 eq 2 )
|
||||||
( ! $ANALYZE compare-versions 1 '==' 2 )
|
( ! "$ANALYZE" compare-versions 1 '==' 2 )
|
||||||
( ! $ANALYZE compare-versions 1 gt 2 )
|
( ! "$ANALYZE" compare-versions 1 gt 2 )
|
||||||
( ! $ANALYZE compare-versions 1 '>' 2 )
|
( ! "$ANALYZE" compare-versions 1 '>' 2 )
|
||||||
|
|
||||||
test "$($ANALYZE compare-versions 1 2)" = '1 < 2'
|
test "$("$ANALYZE" compare-versions 1 2)" = '1 < 2'
|
||||||
test "$($ANALYZE compare-versions 2 2)" = '2 == 2'
|
test "$("$ANALYZE" compare-versions 2 2)" = '2 == 2'
|
||||||
test "$($ANALYZE compare-versions 2 1)" = '2 > 1'
|
test "$("$ANALYZE" compare-versions 2 1)" = '2 > 1'
|
||||||
test "$($ANALYZE compare-versions '' '')" = "'' == ''"
|
test "$("$ANALYZE" compare-versions '' '')" = "'' == ''"
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
|
|
||||||
$ANALYZE compare-versions 1 2; ret1=$?
|
"$ANALYZE" compare-versions 1 2; ret1=$?
|
||||||
$ANALYZE compare-versions 2 2; ret2=$?
|
"$ANALYZE" compare-versions 2 2; ret2=$?
|
||||||
$ANALYZE compare-versions 2 1; ret3=$?
|
"$ANALYZE" compare-versions 2 1; ret3=$?
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
test $ret1 == 12
|
test "$ret1" == 12
|
||||||
test $ret2 == 0
|
test "$ret2" == 0
|
||||||
test $ret3 == 11
|
test "$ret3" == 11
|
||||||
|
|
|
@ -44,9 +44,9 @@ test_one() (
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${input##*/}" =~ \.fstab\.input ]]; then
|
if [[ "${input##*/}" =~ \.fstab\.input ]]; then
|
||||||
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$input" SYSTEMD_SYSROOT_FSTAB="/dev/null" $generator "$out" "$out" "$out"
|
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=yes root=fstab" SYSTEMD_FSTAB="$input" SYSTEMD_SYSROOT_FSTAB="/dev/null" "$generator" "$out" "$out" "$out"
|
||||||
else
|
else
|
||||||
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$input")" $generator "$out" "$out" "$out"
|
SYSTEMD_LOG_LEVEL=debug SYSTEMD_IN_INITRD="$initrd" SYSTEMD_SYSFS_CHECK=no SYSTEMD_PROC_CMDLINE="fstab=no $(cat "$input")" "$generator" "$out" "$out" "$out"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The option x-systemd.growfs creates symlink to system's systemd-growfs@.service in .mount.wants directory.
|
# The option x-systemd.growfs creates symlink to system's systemd-growfs@.service in .mount.wants directory.
|
||||||
|
|
|
@ -53,7 +53,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
||||||
echo "*** Running $f"
|
echo "*** Running $f"
|
||||||
prepare_testdir "${f%.input}"
|
prepare_testdir "${f%.input}"
|
||||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||||
$SYSUSERS --root="$TESTDIR"
|
"$SYSUSERS" --root="$TESTDIR"
|
||||||
|
|
||||||
compare "${f%.*}" ""
|
compare "${f%.*}" ""
|
||||||
done
|
done
|
||||||
|
@ -62,7 +62,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
||||||
echo "*** Running $f on stdin"
|
echo "*** Running $f on stdin"
|
||||||
prepare_testdir "${f%.input}"
|
prepare_testdir "${f%.input}"
|
||||||
touch "$TESTDIR/etc/sysusers.d/test.conf"
|
touch "$TESTDIR/etc/sysusers.d/test.conf"
|
||||||
$SYSUSERS --root="$TESTDIR" - <"$f"
|
"$SYSUSERS" --root="$TESTDIR" - <"$f"
|
||||||
|
|
||||||
compare "${f%.*}" "on stdin"
|
compare "${f%.*}" "on stdin"
|
||||||
done
|
done
|
||||||
|
@ -72,9 +72,9 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
||||||
prepare_testdir "${f%.input}"
|
prepare_testdir "${f%.input}"
|
||||||
touch "$TESTDIR/etc/sysusers.d/test.conf"
|
touch "$TESTDIR/etc/sysusers.d/test.conf"
|
||||||
# this overrides test.conf which is masked on disk
|
# this overrides test.conf which is masked on disk
|
||||||
$SYSUSERS --root="$TESTDIR" --replace=/etc/sysusers.d/test.conf - <"$f"
|
"$SYSUSERS" --root="$TESTDIR" --replace=/etc/sysusers.d/test.conf - <"$f"
|
||||||
# this should be ignored
|
# this should be ignored
|
||||||
$SYSUSERS --root="$TESTDIR" --replace=/usr/lib/sysusers.d/test.conf - <"$SOURCE/test-1.input"
|
"$SYSUSERS" --root="$TESTDIR" --replace=/usr/lib/sysusers.d/test.conf - <"$SOURCE/test-1.input"
|
||||||
|
|
||||||
compare "${f%.*}" "on stdin with --replace"
|
compare "${f%.*}" "on stdin with --replace"
|
||||||
done
|
done
|
||||||
|
@ -84,9 +84,9 @@ echo "*** Testing --inline"
|
||||||
prepare_testdir "$SOURCE/inline"
|
prepare_testdir "$SOURCE/inline"
|
||||||
# copy a random file to make sure it is ignored
|
# copy a random file to make sure it is ignored
|
||||||
cp "$f" "$TESTDIR/etc/sysusers.d/confuse.conf"
|
cp "$f" "$TESTDIR/etc/sysusers.d/confuse.conf"
|
||||||
$SYSUSERS --root="$TESTDIR" --inline \
|
"$SYSUSERS" --root="$TESTDIR" --inline \
|
||||||
"u u1 222 - - /bin/zsh" \
|
"u u1 222 - - /bin/zsh" \
|
||||||
"g g1 111"
|
"g g1 111"
|
||||||
|
|
||||||
compare "$SOURCE/inline" "(--inline)"
|
compare "$SOURCE/inline" "(--inline)"
|
||||||
|
|
||||||
|
@ -95,19 +95,19 @@ echo "*** Testing --inline with --replace"
|
||||||
prepare_testdir "$SOURCE/inline"
|
prepare_testdir "$SOURCE/inline"
|
||||||
# copy a random file to make sure it is ignored
|
# copy a random file to make sure it is ignored
|
||||||
cp "$f" "$TESTDIR/etc/sysusers.d/confuse.conf"
|
cp "$f" "$TESTDIR/etc/sysusers.d/confuse.conf"
|
||||||
$SYSUSERS --root="$TESTDIR" \
|
"$SYSUSERS" --root="$TESTDIR" \
|
||||||
--inline \
|
--inline \
|
||||||
--replace=/etc/sysusers.d/confuse.conf \
|
--replace=/etc/sysusers.d/confuse.conf \
|
||||||
"u u1 222 - - /bin/zsh" \
|
"u u1 222 - - /bin/zsh" \
|
||||||
"g g1 111"
|
"g g1 111"
|
||||||
|
|
||||||
compare "$SOURCE/inline" "(--inline --replace=…)"
|
compare "$SOURCE/inline" "(--inline --replace=…)"
|
||||||
|
|
||||||
echo "*** Testing --inline with no /etc"
|
echo "*** Testing --inline with no /etc"
|
||||||
rm -rf "${TESTDIR:?}/etc"
|
rm -rf "${TESTDIR:?}/etc"
|
||||||
$SYSUSERS --root="$TESTDIR" --inline \
|
"$SYSUSERS" --root="$TESTDIR" --inline \
|
||||||
"u u1 222 - - /bin/zsh" \
|
"u u1 222 - - /bin/zsh" \
|
||||||
"g g1 111"
|
"g g1 111"
|
||||||
|
|
||||||
compare "$SOURCE/inline" "(--inline)"
|
compare "$SOURCE/inline" "(--inline)"
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
||||||
echo "*** Running $f (with login.defs)"
|
echo "*** Running $f (with login.defs)"
|
||||||
prepare_testdir "${f%.input}"
|
prepare_testdir "${f%.input}"
|
||||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||||
$SYSUSERS --root="$TESTDIR"
|
"$SYSUSERS" --root="$TESTDIR"
|
||||||
|
|
||||||
# shellcheck disable=SC2050
|
# shellcheck disable=SC2050
|
||||||
[ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
|
[ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
|
||||||
|
@ -152,7 +152,7 @@ for f in $(find "$SOURCE"/test-*.input | sort -V); do
|
||||||
echo "*** Running $f (with login.defs symlinked)"
|
echo "*** Running $f (with login.defs symlinked)"
|
||||||
prepare_testdir "${f%.input}"
|
prepare_testdir "${f%.input}"
|
||||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||||
$SYSUSERS --root="$TESTDIR"
|
"$SYSUSERS" --root="$TESTDIR"
|
||||||
|
|
||||||
# shellcheck disable=SC2050
|
# shellcheck disable=SC2050
|
||||||
[ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
|
[ @ENABLE_COMPAT_MUTABLE_UID_BOUNDARIES@ = 1 ] && bound=555 || bound=$system_guid_max
|
||||||
|
@ -166,7 +166,7 @@ for f in $(find "$SOURCE"/unhappy-*.input | sort -V); do
|
||||||
echo "*** Running test $f"
|
echo "*** Running test $f"
|
||||||
prepare_testdir "${f%.input}"
|
prepare_testdir "${f%.input}"
|
||||||
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
|
||||||
SYSTEMD_LOG_LEVEL=info $SYSUSERS --root="$TESTDIR" 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >"$TESTDIR/err"
|
SYSTEMD_LOG_LEVEL=info "$SYSUSERS" --root="$TESTDIR" 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >"$TESTDIR/err"
|
||||||
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err"; then
|
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err"; then
|
||||||
echo >&2 "**** Unexpected error output for $f"
|
echo >&2 "**** Unexpected error output for $f"
|
||||||
cat >&2 "$TESTDIR/err"
|
cat >&2 "$TESTDIR/err"
|
||||||
|
|
|
@ -148,12 +148,79 @@ EOF
|
||||||
systemctl start testservice-34-check-writable.service
|
systemctl start testservice-34-check-writable.service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_check_idmapped_mounts() {
|
||||||
|
rm -rf /var/lib/testidmapped /var/lib/private/testidmapped
|
||||||
|
|
||||||
|
cat >/run/systemd/system/testservice-34-check-idmapped.service <<\EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Check id-mapped directories when DynamicUser=yes with StateDirectory
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
# Relevant only for sanitizer runs
|
||||||
|
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
|
||||||
|
Type=oneshot
|
||||||
|
|
||||||
|
MountAPIVFS=yes
|
||||||
|
DynamicUser=yes
|
||||||
|
PrivateUsers=yes
|
||||||
|
TemporaryFileSystem=/run /var/opt /var/lib /vol
|
||||||
|
UMask=0000
|
||||||
|
StateDirectory=testidmapped:sampleservice
|
||||||
|
ExecStart=/bin/bash -c ' \
|
||||||
|
set -eux; \
|
||||||
|
set -o pipefail; \
|
||||||
|
touch /var/lib/sampleservice/testfile; \
|
||||||
|
[[ $(awk "NR==2 {print \$1}" /proc/self/uid_map) == $(stat -c "%%u" /var/lib/private/testidmapped/testfile) ]]; \
|
||||||
|
'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl start testservice-34-check-idmapped.service
|
||||||
|
|
||||||
|
[[ $(stat -c "%u" /var/lib/private/testidmapped/testfile) == 65534 ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
test_check_idmapped_mounts_root() {
|
||||||
|
rm -rf /var/lib/testidmapped /var/lib/private/testidmapped
|
||||||
|
|
||||||
|
cat >/run/systemd/system/testservice-34-check-idmapped.service <<\EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Check id-mapped directories when DynamicUser=no with StateDirectory
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
# Relevant only for sanitizer runs
|
||||||
|
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
|
||||||
|
Type=oneshot
|
||||||
|
|
||||||
|
MountAPIVFS=yes
|
||||||
|
User=root
|
||||||
|
DynamicUser=no
|
||||||
|
PrivateUsers=no
|
||||||
|
TemporaryFileSystem=/run /var/opt /var/lib /vol
|
||||||
|
UMask=0000
|
||||||
|
StateDirectory=testidmapped:sampleservice
|
||||||
|
ExecStart=/bin/bash -c ' \
|
||||||
|
set -eux; \
|
||||||
|
set -o pipefail; \
|
||||||
|
touch /var/lib/sampleservice/testfile; \
|
||||||
|
[[ 0 == $(stat -c "%%u" /var/lib/testidmapped/testfile) ]]; \
|
||||||
|
'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl start testservice-34-check-idmapped.service
|
||||||
|
|
||||||
|
[[ $(stat -c "%u" /var/lib/testidmapped/testfile) == 0 ]]
|
||||||
|
}
|
||||||
|
|
||||||
test_directory "StateDirectory" "/var/lib"
|
test_directory "StateDirectory" "/var/lib"
|
||||||
test_directory "RuntimeDirectory" "/run"
|
test_directory "RuntimeDirectory" "/run"
|
||||||
test_directory "CacheDirectory" "/var/cache"
|
test_directory "CacheDirectory" "/var/cache"
|
||||||
test_directory "LogsDirectory" "/var/log"
|
test_directory "LogsDirectory" "/var/log"
|
||||||
|
|
||||||
test_check_writable
|
test_check_writable
|
||||||
|
test_check_idmapped_mounts
|
||||||
|
test_check_idmapped_mounts_root
|
||||||
|
|
||||||
systemd-analyze log-level info
|
systemd-analyze log-level info
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ if test -f /run/systemd/stub/profile; then
|
||||||
fi
|
fi
|
||||||
echo "CURRENT MEASUREMENT:"
|
echo "CURRENT MEASUREMENT:"
|
||||||
/usr/lib/systemd/systemd-measure --current
|
/usr/lib/systemd/systemd-measure --current
|
||||||
if test -f /run/systemd/tpm2-pcr-signature.json ; then
|
if test -f /run/systemd/tpm2-pcr-signature.json; then
|
||||||
echo "CURRENT SIGNATURE:"
|
echo "CURRENT SIGNATURE:"
|
||||||
jq < /run/systemd/tpm2-pcr-signature.json
|
jq </run/systemd/tpm2-pcr-signature.json
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "CURRENT EVENT LOG + PCRS:"
|
echo "CURRENT EVENT LOG + PCRS:"
|
||||||
|
@ -45,7 +45,7 @@ TITLE="Profile Two"' --measure-base=/tmp/extended1.efi --cmdline="testprofile2=1
|
||||||
|
|
||||||
# Prepare a disk image, locked to the PCR measurements of the UKI we just generated
|
# Prepare a disk image, locked to the PCR measurements of the UKI we just generated
|
||||||
truncate -s 32M /root/encrypted.raw
|
truncate -s 32M /root/encrypted.raw
|
||||||
echo -n "geheim" > /root/encrypted.secret
|
echo -n "geheim" >/root/encrypted.secret
|
||||||
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom /root/encrypted.raw --key-file=/root/encrypted.secret
|
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom /root/encrypted.raw --key-file=/root/encrypted.secret
|
||||||
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs= --tpm2-public-key=/root/pcrsign.public.pem --unlock-key-file=/root/encrypted.secret /root/encrypted.raw
|
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs= --tpm2-public-key=/root/pcrsign.public.pem --unlock-key-file=/root/encrypted.secret /root/encrypted.raw
|
||||||
rm -f /root/encrypted.secret
|
rm -f /root/encrypted.secret
|
||||||
|
@ -62,12 +62,12 @@ else
|
||||||
|
|
||||||
if [ "$ID" = "profile0" ]; then
|
if [ "$ID" = "profile0" ]; then
|
||||||
grep -v testprofile /proc/cmdline
|
grep -v testprofile /proc/cmdline
|
||||||
echo "default $(basename "$CURRENT_UKI")@profile1" > "$(bootctl -p)/loader/loader.conf"
|
echo "default $(basename "$CURRENT_UKI")@profile1" >"$(bootctl -p)/loader/loader.conf"
|
||||||
reboot
|
reboot
|
||||||
exit 0
|
exit 0
|
||||||
elif [ "$ID" = "profile1" ]; then
|
elif [ "$ID" = "profile1" ]; then
|
||||||
grep testprofile1=1 /proc/cmdline
|
grep testprofile1=1 /proc/cmdline
|
||||||
echo "default $(basename "$CURRENT_UKI")@profile2" > "$(bootctl -p)/loader/loader.conf"
|
echo "default $(basename "$CURRENT_UKI")@profile2" >"$(bootctl -p)/loader/loader.conf"
|
||||||
reboot
|
reboot
|
||||||
exit 0
|
exit 0
|
||||||
elif [ "$ID" = "profile2" ]; then
|
elif [ "$ID" = "profile2" ]; then
|
||||||
|
|
|
@ -19,5 +19,5 @@ Q /var/lib/machines 0700 - - -
|
||||||
# systemd-nspawn --ephemeral places snapshots) we are more strict, to
|
# systemd-nspawn --ephemeral places snapshots) we are more strict, to
|
||||||
# avoid removing unrelated temporary files.
|
# avoid removing unrelated temporary files.
|
||||||
|
|
||||||
R!$ /var/lib/machines/.#*
|
R! /var/lib/machines/.#*
|
||||||
R!$ /.#machine.*
|
R! /.#machine.*
|
||||||
|
|
|
@ -14,10 +14,10 @@ x /var/tmp/systemd-private-%b-*
|
||||||
X /var/tmp/systemd-private-%b-*/tmp
|
X /var/tmp/systemd-private-%b-*/tmp
|
||||||
|
|
||||||
# Remove top-level private temporary directories on each boot
|
# Remove top-level private temporary directories on each boot
|
||||||
R!$ /tmp/systemd-private-*
|
R! /tmp/systemd-private-*
|
||||||
R!$ /var/tmp/systemd-private-*
|
R! /var/tmp/systemd-private-*
|
||||||
|
|
||||||
# Handle lost systemd-coredump temp files. They could be lost on old filesystems,
|
# Handle lost systemd-coredump temp files. They could be lost on old filesystems,
|
||||||
# for example, after hard reboot.
|
# for example, after hard reboot.
|
||||||
x /var/lib/systemd/coredump/.#core*.%b*
|
x /var/lib/systemd/coredump/.#core*.%b*
|
||||||
r!$ /var/lib/systemd/coredump/.#*
|
r! /var/lib/systemd/coredump/.#*
|
||||||
|
|
Loading…
Reference in New Issue