mirror of
https://github.com/systemd/systemd
synced 2025-11-21 09:44:44 +01:00
Compare commits
44 Commits
e9043181fd
...
05be1adb99
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05be1adb99 | ||
|
|
89e8a47f7a | ||
|
|
8dfe0844fc | ||
|
|
d4802151b0 | ||
|
|
91d1176b4f | ||
|
|
5c803eda3b | ||
|
|
c69ecfc6d3 | ||
|
|
98322a0561 | ||
|
|
ac74faec86 | ||
|
|
f207d22c78 | ||
|
|
c91f3b6928 | ||
|
|
f9553d5d14 | ||
|
|
6add7bf611 | ||
|
|
96784edb71 | ||
|
|
9face7bb64 | ||
|
|
2cd1762a1f | ||
|
|
fc563bf786 | ||
|
|
68e65c9d12 | ||
|
|
0d4b6b362e | ||
|
|
a7fe667531 | ||
|
|
a297ebe818 | ||
|
|
d4f88c6da2 | ||
|
|
0b4c2ef2e0 | ||
|
|
9f84d3ef7a | ||
|
|
b465e4816e | ||
|
|
0db08364fc | ||
|
|
b2d0e73ee1 | ||
|
|
1220347e3b | ||
|
|
a45a2a9e65 | ||
|
|
4b365bc034 | ||
|
|
49f6a01b04 | ||
|
|
2caecb5353 | ||
|
|
5a5326bda9 | ||
|
|
abaa3f14cb | ||
|
|
61e8972bfc | ||
|
|
e5c0bc6101 | ||
|
|
a513e7e57c | ||
|
|
d43e0d7d58 | ||
|
|
708fb198c4 | ||
|
|
35f3a771fa | ||
|
|
e67e514567 | ||
|
|
b365d34a0c | ||
|
|
d21fa647d2 | ||
|
|
c32062c533 |
@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -485,7 +485,7 @@ convey the exclusion of warranty; and each file should have at least the
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
@ -158,7 +158,7 @@ To apply these terms, attach the following notices to the library. It is safest
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
||||
2
NEWS
2
NEWS
@ -30,6 +30,8 @@ CHANGES WITH 258:
|
||||
ACTION!="remove", SUBSYSTEM=="hidraw", TAG+="uaccess"
|
||||
The following example does not work since v258:
|
||||
ACTION=="add", SUBSYSTEM=="hidraw", TAG+="uaccess"
|
||||
Udev rules files setting the "uaccess" tag need to have a file name
|
||||
starting with a number smaller than 73 to be applied.
|
||||
|
||||
* systemd-run's --expand-environment= switch, which was disabled
|
||||
by default when combined with --scope, has been changed to be
|
||||
|
||||
@ -67,7 +67,7 @@ options root=PARTUUID=084917b7-8be2-4e86-838d-f771a9902e08
|
||||
title My kernel with initrd
|
||||
linux /bzImage
|
||||
initrd /initrd.img
|
||||
options root=PARTUUID=084917b7-8be2-4e86-838d-f771a9902e08 quiet`
|
||||
options root=PARTUUID=084917b7-8be2-4e86-838d-f771a9902e08 quiet
|
||||
```
|
||||
|
||||
|
||||
|
||||
@ -1054,6 +1054,11 @@ sensor:modalias:acpi:KIOX010A*:dmi:bvn*:bvr*:svnPositivoTecnologiaSA:pn*:pvr*:rv
|
||||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
|
||||
ACCEL_LOCATION=display
|
||||
|
||||
# Positivo Duo K116J
|
||||
sensor:modalias:acpi:MDA6655*:dmi:bvn*:bvr*:svnPositivoTecnologiaSA:pn*:pvr*:rvnPositivoTecnologiaSA:rnK116J*
|
||||
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
|
||||
ACCEL_LOCATION=display
|
||||
|
||||
########################################
|
||||
# Predia
|
||||
#########################################
|
||||
|
||||
@ -821,6 +821,20 @@ mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000:*
|
||||
mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
|
||||
MOUSE_DPI=*800@126 1600@126
|
||||
|
||||
##########################################
|
||||
# Nulea
|
||||
##########################################
|
||||
|
||||
# Note: it is possible that other devices may use the same wireless dongle,
|
||||
# as such this could require revisiting if it causes issues with other mice
|
||||
# Nulea M501 Wireless Trackball (USB Receiver)
|
||||
mouse:usb:v25a7pfa61:name:Compx 2.4G Receiver Mouse:*
|
||||
ID_INPUT_TRACKBALL=1
|
||||
|
||||
# Nulea M501 Wireless Trackball (Bluetooth)
|
||||
mouse:bluetooth:v000ep3412:name:Nulea BT5.0 Mouse:*
|
||||
ID_INPUT_TRACKBALL=1
|
||||
|
||||
##########################################
|
||||
# Oklick
|
||||
##########################################
|
||||
|
||||
@ -205,6 +205,16 @@
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--prompt-new-user</option></term>
|
||||
|
||||
<listitem><para>If used in conjunction with <command>firstboot</command> and no regular user account
|
||||
exists on the system so far the tool will interactively query for user information and create an
|
||||
account.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--match=</option></term>
|
||||
<term><option>-A</option></term>
|
||||
@ -1424,9 +1434,10 @@ $ ssh lennart@targetsystem</programlisting>
|
||||
|
||||
<listitem><para>This command is supposed to be invoked during the initial boot of the system. It
|
||||
checks whether any regular home area exists so far, and if not queries the user interactively on the
|
||||
console for user name and password and creates one. Alternatively, if one or more service credentials
|
||||
whose name starts with <literal>home.create.</literal> are passed to the command (containing a user
|
||||
record in JSON format) these users are automatically created at boot.</para>
|
||||
console for user name and password and creates one (only if <option>--prompt-new-user</option> is
|
||||
specified). Alternatively, if one or more service credentials whose name starts with
|
||||
<literal>home.create.</literal> are passed to the command (containing a user record in JSON format)
|
||||
these users are automatically created at boot.</para>
|
||||
|
||||
<para>This command is invoked by the <filename>systemd-homed-firstboot.service</filename> service
|
||||
unit.</para>
|
||||
|
||||
@ -737,8 +737,8 @@
|
||||
<varlistentry>
|
||||
<term><option>--no-hostname</option></term>
|
||||
|
||||
<listitem><para>Do not show the hostname field of log messages originating from the local host. This
|
||||
switch has an effect only on the <option>short</option> family of output modes (see above).</para>
|
||||
<listitem><para>Do not show the hostname field of log messages. This switch has an effect only on the
|
||||
<option>short</option> family of output modes (see above).</para>
|
||||
|
||||
<para>Note: this option does not remove occurrences of the hostname from log entries themselves, so
|
||||
it does not prevent the hostname from being visible in the logs.</para>
|
||||
|
||||
@ -478,11 +478,14 @@
|
||||
<varlistentry>
|
||||
<term><varname>Audit=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean value. If enabled <command>systemd-journald</command> will turn on
|
||||
kernel auditing on start-up. If disabled it will turn it off. If unset it will neither enable nor
|
||||
disable it, leaving the previous state unchanged. This means if another tool turns on auditing even
|
||||
if <command>systemd-journald</command> left it off, it will still collect the generated
|
||||
messages. Defaults to on in the default journal namespace, and unset otherwise.</para>
|
||||
<listitem><para>Takes a boolean value or special value <literal>keep</literal>. If enabled
|
||||
<command>systemd-journald</command> will turn on kernel auditing on start-up. If disabled it will
|
||||
turn it off. When <literal>keep</literal> it will neither enable nor disable it, leaving the previous
|
||||
state unchanged. This means if another tool turns on auditing even if
|
||||
<command>systemd-journald</command> left it off, it will still collect the generated messages.
|
||||
Defaults to yes in the default journal namespace, and <literal>keep</literal> otherwise.</para>
|
||||
|
||||
<!-- Explicit assignment of an empty string is equivalent to 'keep', for backward compatibility. -->
|
||||
|
||||
<para>Note that this option does not control whether <command>systemd-journald</command> collects
|
||||
generated audit records, it just controls whether it tells the kernel to generate them. If you need
|
||||
|
||||
@ -75,13 +75,14 @@
|
||||
<refsect1>
|
||||
<title>Thread safety</title>
|
||||
|
||||
<para>Functions that operate on <structname>sd_journal</structname> objects are thread agnostic — given
|
||||
<structname>sd_journal</structname> pointer may only be used from one specific thread at all times (and it has to
|
||||
be the very same one during the entire lifetime of the object), but multiple, independent threads may use multiple,
|
||||
independent objects safely. Other functions — those that are used to send entries to the journal, like
|
||||
<citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> and similar,
|
||||
or those that are used to retrieve global information like
|
||||
<citerefentry><refentrytitle>sd_journal_stream_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
|
||||
<para>Functions that operate on <structname>sd_journal</structname> objects are thread agnostic — a given
|
||||
<structname>sd_journal</structname> pointer may only be used from one thread at a time, but multiple
|
||||
independent threads may use multiple objects concurrently. Some functions — those that are used to send
|
||||
entries to the journal, like
|
||||
<citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
|
||||
similar, or those that are used to retrieve global information like
|
||||
<citerefentry><refentrytitle>sd_journal_stream_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
and
|
||||
<citerefentry><refentrytitle>sd_journal_get_catalog_for_message_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
— are fully thread-safe and may be called from multiple threads in parallel.</para>
|
||||
</refsect1>
|
||||
|
||||
@ -41,10 +41,10 @@
|
||||
system.</para>
|
||||
|
||||
<para>Note that these APIs only allow purely passive access and
|
||||
monitoring of seats, sessions and users. To actively make changes
|
||||
monitoring of seats, sessions, and users. To actively make changes
|
||||
to the seat configuration, terminate login sessions, or switch
|
||||
session on a seat you need to utilize the D-Bus API of
|
||||
systemd-logind, instead.</para>
|
||||
systemd-logind instead.</para>
|
||||
|
||||
<para>These functions synchronously access data in
|
||||
<filename>/proc/</filename>, <filename>/sys/fs/cgroup/</filename>
|
||||
@ -62,7 +62,7 @@
|
||||
other.</para>
|
||||
|
||||
<para>If the functions return string arrays, these are generally
|
||||
<constant>NULL</constant> terminated and need to be freed by the
|
||||
<constant>NULL</constant>-terminated and need to be freed by the
|
||||
caller with the libc
|
||||
<citerefentry project='man-pages'><refentrytitle>free</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
call after use, including the strings referenced therein.
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>void <function>sd_bus_can_send</function></funcdef>
|
||||
<funcdef>int <function>sd_bus_can_send</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>char <parameter>type</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
@ -33,6 +33,12 @@
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>typedef int (*<function>sd_bus_track_handler_t</function>)</funcdef>
|
||||
<paramdef>sd_bus_track *<parameter>track</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_track_new</function></funcdef>
|
||||
<paramdef>sd_bus* <parameter>bus</parameter></paramdef>
|
||||
@ -221,6 +227,7 @@
|
||||
<refsect1>
|
||||
<title>History</title>
|
||||
<para><function>sd_bus_track_new()</function>,
|
||||
<function>sd_bus_track_handler_t()</function>,
|
||||
<function>sd_bus_track_ref()</function>,
|
||||
<function>sd_bus_track_unref()</function>,
|
||||
<function>sd_bus_track_unrefp()</function>,
|
||||
|
||||
@ -84,14 +84,12 @@
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para>Function <function>sd_journal_get_catalog()</function> is thread-agnostic and only
|
||||
a single specific thread may operate on a given object during its entire lifetime. It is safe to allocate multiple
|
||||
independent objects and use each from a specific thread in parallel. However, it is not safe to allocate such an
|
||||
object in one thread, and operate or free it from any other, even if locking is used to ensure these threads do not
|
||||
operate on it at the very same time.</para>
|
||||
<para>Function <function>sd_journal_get_catalog()</function> is thread-agnostic and only a single thread
|
||||
may operate on a given object at any given time. Multiple independent objects may be used from different
|
||||
threads in parallel.</para>
|
||||
|
||||
<para>Function <function>sd_journal_get_catalog_for_message_id()</function> is are thread-safe and may be called in
|
||||
parallel from multiple threads.</para>
|
||||
<para>Function <function>sd_journal_get_catalog_for_message_id()</function> is thread-safe and may be
|
||||
called from multiple threads in parallel.</para>
|
||||
|
||||
<xi:include href="libsystemd-pkgconfig.xml" xpointer="pkgconfig-text"/>
|
||||
</refsect1>
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
<para>Some of the functionality is also available via the
|
||||
<filename>/run/systemd/io.systemd.FactoryReset</filename> Varlink service (implemented via the
|
||||
<filename>systemd-factory-reset.socket</filename>/<filename>systemd-factory-reset@.service</filename>
|
||||
units.</para>
|
||||
units).</para>
|
||||
|
||||
<para>See <ulink url="https://systemd.io/FACTORY_RESET">Factory Reset</ulink> for an overview of the
|
||||
factory reset logic.</para>
|
||||
@ -81,7 +81,7 @@
|
||||
factory reset operation is by starting the <filename>factory-reset.target</filename>
|
||||
unit.</para>
|
||||
|
||||
<para>This sets the <varname>FactoryResetRequested</varname> EFI variable, see below.</para>
|
||||
<para>This sets the <varname>FactoryResetRequest</varname> EFI variable, see below.</para>
|
||||
|
||||
<para>This operation is executed when the <filename>systemd-factory-reset-request.service</filename>
|
||||
unit is started (which is typically one of the services hooked into
|
||||
|
||||
@ -35,7 +35,9 @@
|
||||
compatibility. It may also pick up statically defined JSON user/group records from files in
|
||||
<filename>/etc/userdb/</filename>, <filename>/run/userdb/</filename>,
|
||||
<filename>/run/host/userdb/</filename> and <filename>/usr/lib/userdb/</filename> with the
|
||||
<literal>.user</literal> or <literal>.group</literal> extension.</para>
|
||||
<literal>.user</literal> or <literal>.group</literal> extension. For more details about the extensions
|
||||
read the <citerefentry><refentrytitle>nss-systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
manpage.</para>
|
||||
|
||||
<para>Most of <command>systemd-userdbd</command>'s functionality is accessible through the
|
||||
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
|
||||
@ -3915,6 +3915,13 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
|
||||
<varname>LoadCredential=</varname> and <varname>LoadCredentialEncrypted=</varname> take priority over
|
||||
credentials found by <varname>ImportCredential=</varname>.</para>
|
||||
|
||||
<para>Note that if decryption or authentication of a credential picked up as result of
|
||||
<varname>ImportCredential=</varname> fails it will be skipped gracefully (a warning is generated, but
|
||||
the credential will not be made available to the invoked service). This is different for those
|
||||
configured via
|
||||
<varname>SetCredentialEncrypted=</varname>/<varname>LoadCredentialEncrypted=</varname>, where failed
|
||||
decryption/authentication will result in service failure.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@ -563,7 +563,7 @@ CPUWeight=20 DisableControllers=cpu / \
|
||||
an absolute number of tasks or a percentage value that is taken relative to the configured maximum
|
||||
number of tasks on the system. If assigned the special value <literal>infinity</literal>, no tasks
|
||||
limit is applied. This controls the <literal>pids.max</literal> control group attribute. For
|
||||
details about this control group attribute, the
|
||||
details about this control group attribute, see the
|
||||
<ulink url="https://docs.kernel.org/admin-guide/cgroup-v2.html#pid">pids controller
|
||||
</ulink>.
|
||||
The effective configuration is reported as <varname>EffectiveTasksMax=</varname>.</para>
|
||||
|
||||
@ -6,10 +6,9 @@
|
||||
<refsect1>
|
||||
<title/>
|
||||
|
||||
<para id="strict">All functions listed here are thread-agnostic and only a single specific thread may operate on a
|
||||
given object during its entire lifetime. It is safe to allocate multiple independent objects and use each from a
|
||||
specific thread in parallel. However, it is not safe to allocate such an object in one thread, and operate or free it
|
||||
from any other, even if locking is used to ensure these threads do not operate on it at the very same time.</para>
|
||||
<para id="strict">All functions listed here are thread-agnostic and only a single thread may operate on a
|
||||
given object at any given time. Different threads may access the same object at different times. Multiple
|
||||
independent objects may be used from different threads in parallel.</para>
|
||||
|
||||
<para id="safe">All functions listed here are thread-safe and may be called in parallel from multiple threads.</para>
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
[ -n "${BASH_VERSION:-}" ] || return 0
|
||||
|
||||
__systemd_osc_context_escape() {
|
||||
# Escape according to the OSC 8003 spec. Since this requires shelling out
|
||||
# Escape according to the OSC 3008 spec. Since this requires shelling out
|
||||
# to 'sed' we'll only do it where it's strictly necessary, and skip it when
|
||||
# processing strings we are pretty sure we won't need it for, such as
|
||||
# uuids, id128, hostnames, usernames, since they all come with syntax
|
||||
@ -33,11 +33,11 @@ __systemd_osc_context_precmdline() {
|
||||
# Close previous command
|
||||
if [ -n "${systemd_osc_context_cmd_id:-}" ]; then
|
||||
if [ "$systemd_exitstatus" -ge 127 ]; then
|
||||
printf "\033]8003;end=%s;exit=interrupt;signal=%s\033\\" "$systemd_osc_context_cmd_id" $((systemd_exitstatus-127))
|
||||
printf "\033]3008;end=%s;exit=interrupt;signal=%s\033\\" "$systemd_osc_context_cmd_id" $((systemd_exitstatus-127))
|
||||
elif [ "$systemd_exitstatus" -ne 0 ]; then
|
||||
printf "\033]8003;end=%s;exit=failure;status=%s\033\\" "$systemd_osc_context_cmd_id" $((systemd_exitstatus))
|
||||
printf "\033]3008;end=%s;exit=failure;status=%s\033\\" "$systemd_osc_context_cmd_id" $((systemd_exitstatus))
|
||||
else
|
||||
printf "\033]8003;end=%s;exit=success\033\\" "$systemd_osc_context_cmd_id"
|
||||
printf "\033]3008;end=%s;exit=success\033\\" "$systemd_osc_context_cmd_id"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -47,7 +47,7 @@ __systemd_osc_context_precmdline() {
|
||||
fi
|
||||
|
||||
# Create or update the shell session
|
||||
printf "\033]8003;start=%s%s;type=shell;cwd=%s\033\\" "$systemd_osc_context_shell_id" "$(__systemd_osc_context_common)" "$(__systemd_osc_context_escape "$PWD")"
|
||||
printf "\033]3008;start=%s%s;type=shell;cwd=%s\033\\" "$systemd_osc_context_shell_id" "$(__systemd_osc_context_common)" "$(__systemd_osc_context_escape "$PWD")"
|
||||
|
||||
# Prepare cmd id for next command
|
||||
read -r systemd_osc_context_cmd_id </proc/sys/kernel/random/uuid
|
||||
@ -58,5 +58,5 @@ if [[ -n "${BASH_VERSION:-}" ]] && [[ "${TERM:-}" != "dumb" ]]; then
|
||||
PROMPT_COMMAND+=(__systemd_osc_context_precmdline)
|
||||
|
||||
# PS0 is shown right after a prompt completed, but before the command is executed
|
||||
PS0='\033]8003;start=$systemd_osc_context_cmd_id$(__systemd_osc_context_common);type=command;cwd=$(__systemd_osc_context_escape "$PWD")\033\\'"${PS0:-}"
|
||||
PS0='\033]3008;start=$systemd_osc_context_cmd_id$(__systemd_osc_context_common);type=command;cwd=$(__systemd_osc_context_escape "$PWD")\033\\'"${PS0:-}"
|
||||
fi
|
||||
|
||||
@ -36,7 +36,8 @@ _systemd-confext() {
|
||||
[ARG]='--root
|
||||
--json
|
||||
--noexec
|
||||
--image-policy'
|
||||
--image-policy
|
||||
--mutable'
|
||||
)
|
||||
|
||||
local -A VERBS=(
|
||||
@ -59,11 +60,14 @@ _systemd-confext() {
|
||||
comps='pretty short off'
|
||||
;;
|
||||
--noexec)
|
||||
comps='false true'
|
||||
comps='no yes'
|
||||
;;
|
||||
--image-policy)
|
||||
comps=''
|
||||
;;
|
||||
--mutable)
|
||||
comps=$( systemd-confext --no-legend --mutable=help 2>/dev/null; echo help )
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
return 0
|
||||
|
||||
@ -31,9 +31,13 @@ _systemd-sysext() {
|
||||
[STANDALONE]='-h --help --version
|
||||
--no-pager
|
||||
--no-legend
|
||||
--no-reload
|
||||
--force'
|
||||
[ARG]='--root
|
||||
--json'
|
||||
--json
|
||||
--noexec
|
||||
--image-policy
|
||||
--mutable'
|
||||
)
|
||||
|
||||
local -A VERBS=(
|
||||
@ -55,6 +59,15 @@ _systemd-sysext() {
|
||||
--json)
|
||||
comps='pretty short off'
|
||||
;;
|
||||
--noexec)
|
||||
comps='no yes'
|
||||
;;
|
||||
--image-policy)
|
||||
comps=''
|
||||
;;
|
||||
--mutable)
|
||||
comps=$( systemd-sysext --no-legend --mutable=help 2>/dev/null; echo help )
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
return 0
|
||||
|
||||
@ -99,7 +99,7 @@ _arguments -s \
|
||||
'(- *)'{-h,--help}'[Show this help]' \
|
||||
'(- *)--version[Show package version]' \
|
||||
'--no-pager[Do not pipe output into a pager]' \
|
||||
--no-hostname"[Don't show the hostname of local log messages]" \
|
||||
--no-hostname"[Don't show the hostname of log messages]" \
|
||||
'(-l --full)'{-l,--full}'[Show long fields in full]' \
|
||||
'(-a --all)'{-a,--all}'[Show all fields, including long and unprintable]' \
|
||||
'(-f --follow)'{-f,--follow}'[Follow journal]' \
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -31,12 +32,7 @@ int efi_get_variable(
|
||||
void **ret_value,
|
||||
size_t *ret_size) {
|
||||
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_free_ void *buf = NULL;
|
||||
struct stat st;
|
||||
usec_t begin = 0; /* Unnecessary initialization to appease gcc */
|
||||
uint32_t a;
|
||||
ssize_t n;
|
||||
|
||||
assert(variable);
|
||||
|
||||
@ -56,79 +52,100 @@ int efi_get_variable(
|
||||
begin = now(CLOCK_MONOTONIC);
|
||||
}
|
||||
|
||||
fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
_cleanup_close_ int fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return log_debug_errno(errno, "open(\"%s\") failed: %m", p);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_debug_errno(errno, "fstat(\"%s\") failed: %m", p);
|
||||
if (st.st_size < 4)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "EFI variable %s is shorter than 4 bytes, refusing.", p);
|
||||
if (st.st_size > 4*1024*1024 + 4)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "EFI variable %s is ridiculously large, refusing.", p);
|
||||
uint32_t attr;
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
ssize_t n;
|
||||
|
||||
if (ret_value || ret_attribute) {
|
||||
/* The kernel ratelimits reads from the efivarfs because EFI is inefficient, and we'll
|
||||
* occasionally fail with EINTR here. A slowdown is better than a failure for us, so
|
||||
* retry a few times and eventually fail with -EBUSY.
|
||||
*
|
||||
* See https://github.com/torvalds/linux/blob/master/fs/efivarfs/file.c#L75
|
||||
* and
|
||||
* https://github.com/torvalds/linux/commit/bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.
|
||||
*/
|
||||
for (unsigned try = 0;; try++) {
|
||||
n = read(fd, &a, sizeof(a));
|
||||
if (n >= 0)
|
||||
break;
|
||||
log_debug_errno(errno, "Reading from \"%s\" failed: %m", p);
|
||||
if (errno != EINTR)
|
||||
return -errno;
|
||||
if (try >= EFI_N_RETRIES_TOTAL)
|
||||
return -EBUSY;
|
||||
/* The kernel ratelimits reads from the efivarfs because EFI is inefficient, and we'll occasionally
|
||||
* fail with EINTR here. A slowdown is better than a failure for us, so retry a few times and
|
||||
* eventually fail with -EBUSY.
|
||||
*
|
||||
* See https://github.com/torvalds/linux/blob/master/fs/efivarfs/file.c#L75 and
|
||||
* https://github.com/torvalds/linux/commit/bef3efbeb897b56867e271cdbc5f8adaacaeb9cd.
|
||||
*
|
||||
* The variable may also be overwritten between the stat and read. If we find out that the new
|
||||
* contents are longer, try again.
|
||||
*/
|
||||
for (unsigned try = 0;; try++) {
|
||||
struct stat st;
|
||||
|
||||
if (try >= EFI_N_RETRIES_NO_DELAY)
|
||||
(void) usleep_safe(EFI_RETRY_DELAY);
|
||||
}
|
||||
|
||||
/* Unfortunately kernel reports EOF if there's an inconsistency between efivarfs var list
|
||||
* and what's actually stored in firmware, c.f. #34304. A zero size env var is not allowed in
|
||||
* efi and hence the variable doesn't really exist in the backing store as long as it is zero
|
||||
* sized, and the kernel calls this "uncommitted". Hence we translate EOF back to ENOENT here,
|
||||
* as with kernel behavior before
|
||||
* https://github.com/torvalds/linux/commit/3fab70c165795431f00ddf9be8b84ddd07bd1f8f
|
||||
*
|
||||
* If the kernel changes behaviour (to flush dentries on resume), we can drop
|
||||
* this at some point in the future. But note that the commit is 11
|
||||
* years old at this point so we'll need to deal with the current behaviour for
|
||||
* a long time.
|
||||
*/
|
||||
if (n == 0)
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_debug_errno(errno, "fstat(\"%s\") failed: %m", p);
|
||||
if (st.st_size == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
|
||||
"EFI variable %s is uncommitted", p);
|
||||
if (st.st_size < 4)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "EFI variable %s is shorter than 4 bytes, refusing.", p);
|
||||
if (st.st_size > 4*1024*1024 + 4)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "EFI variable %s is ridiculously large, refusing.", p);
|
||||
|
||||
if (n != sizeof(a))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Read %zi bytes from EFI variable %s, expected %zu.", n, p, sizeof(a));
|
||||
if (!ret_attribute && !ret_value) {
|
||||
/* No need to read anything, return the reported size. */
|
||||
n = st.st_size;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We want +1 for the read call, and +3 for the additional terminating bytes added below. */
|
||||
char *t = realloc(buf, (size_t) st.st_size + MAX(1, 3));
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
buf = t;
|
||||
|
||||
const struct iovec iov[] = {
|
||||
{ &attr, sizeof(attr) },
|
||||
{ buf, (size_t) st.st_size + 1 },
|
||||
};
|
||||
|
||||
n = readv(fd, iov, 2);
|
||||
assert(n <= st.st_size + 1);
|
||||
if (n == st.st_size + 1)
|
||||
/* We need to try again with a bigger buffer. */
|
||||
continue;
|
||||
if (n >= 0)
|
||||
break;
|
||||
|
||||
log_debug_errno(errno, "Reading from \"%s\" failed: %m", p);
|
||||
if (errno != EINTR)
|
||||
return -errno;
|
||||
if (try >= EFI_N_RETRIES_TOTAL)
|
||||
return -EBUSY;
|
||||
if (try >= EFI_N_RETRIES_NO_DELAY)
|
||||
(void) usleep_safe(EFI_RETRY_DELAY);
|
||||
}
|
||||
|
||||
/* Unfortunately kernel reports EOF if there's an inconsistency between efivarfs var list and
|
||||
* what's actually stored in firmware, c.f. #34304. A zero size env var is not allowed in EFI
|
||||
* and hence the variable doesn't really exist in the backing store as long as it is zero
|
||||
* sized, and the kernel calls this "uncommitted". Hence we translate EOF back to ENOENT
|
||||
* here, as with kernel behavior before
|
||||
* https://github.com/torvalds/linux/commit/3fab70c165795431f00ddf9be8b84ddd07bd1f8f.
|
||||
*
|
||||
* If the kernel changes behaviour (to flush dentries on resume), we can drop this at some
|
||||
* point in the future. But note that the commit is 11 years old at this point so we'll need
|
||||
* to deal with the current behaviour for a long time.
|
||||
*/
|
||||
if (n == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
|
||||
"EFI variable %s is uncommitted", p);
|
||||
if (n < 4)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Read %zi bytes from EFI variable %s, expected >= 4", n, p);
|
||||
|
||||
if (ret_attribute)
|
||||
*ret_attribute = attr;
|
||||
if (ret_value) {
|
||||
buf = malloc(st.st_size - 4 + 3);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
n = read(fd, buf, (size_t) st.st_size - 4);
|
||||
if (n < 0)
|
||||
return log_debug_errno(errno, "Failed to read value of EFI variable %s: %m", p);
|
||||
assert(n <= st.st_size - 4);
|
||||
|
||||
/* Always NUL-terminate (3 bytes, to properly protect UTF-16, even if truncated in the middle
|
||||
* of a character) */
|
||||
((char*) buf)[n] = 0;
|
||||
((char*) buf)[n + 1] = 0;
|
||||
((char*) buf)[n + 2] = 0;
|
||||
} else
|
||||
/* Assume that the reported size is accurate */
|
||||
n = st.st_size - 4;
|
||||
assert(buf);
|
||||
/* Always NUL-terminate (3 bytes, to properly protect UTF-16, even if truncated in
|
||||
* the middle of a character) */
|
||||
buf[n - 4] = 0;
|
||||
buf[n - 4 + 1] = 0;
|
||||
buf[n - 4 + 2] = 0;
|
||||
*ret_value = TAKE_PTR(buf);
|
||||
}
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
usec_t end = now(CLOCK_MONOTONIC);
|
||||
@ -140,14 +157,8 @@ int efi_get_variable(
|
||||
/* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable
|
||||
* with a smaller value. */
|
||||
|
||||
if (ret_attribute)
|
||||
*ret_attribute = a;
|
||||
|
||||
if (ret_value)
|
||||
*ret_value = TAKE_PTR(buf);
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = n;
|
||||
*ret_size = n - 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -288,15 +288,20 @@ int fchmod_opath(int fd, mode_t m) {
|
||||
* - fchmod(2) only operates on open files (i. e., fds with an open file description);
|
||||
* - fchmodat(2) does not have a flag arg like fchownat(2) does, so no way to pass AT_EMPTY_PATH;
|
||||
* + it should not be confused with the libc fchmodat(3) interface, which adds 4th flag argument,
|
||||
* but does not support AT_EMPTY_PATH (only supports AT_SYMLINK_NOFOLLOW);
|
||||
* and supports AT_EMPTY_PATH since v2.39 (previously only supported AT_SYMLINK_NOFOLLOW). So if
|
||||
* the kernel has fchmodat2(2), since v2.39 glibc will call into it directly. If the kernel
|
||||
* doesn't, or glibc is older than v2.39, glibc's internal fallback will return EINVAL if
|
||||
* AT_EMPTY_PATH is passed.
|
||||
* - fchmodat2(2) supports all the AT_* flags, but is still very recent.
|
||||
*
|
||||
* We try to use fchmodat2(), and, if it is not supported, resort
|
||||
* to the /proc/self/fd dance. */
|
||||
* We try to use fchmodat(3) first, and on EINVAL fall back to fchmodat2(), and, if that is also not
|
||||
* supported, resort to the /proc/self/fd dance. */
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if (fchmodat2(fd, "", m, AT_EMPTY_PATH) >= 0)
|
||||
if (fchmodat(fd, "", m, AT_EMPTY_PATH) >= 0)
|
||||
return 0;
|
||||
if (errno == EINVAL && fchmodat2(fd, "", m, AT_EMPTY_PATH) >= 0) /* glibc too old? */
|
||||
return 0;
|
||||
if (!IN_SET(errno, ENOSYS, EPERM)) /* Some container managers block unknown syscalls with EPERM */
|
||||
return -errno;
|
||||
|
||||
@ -16,8 +16,8 @@
|
||||
#include "log.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@ -816,16 +816,19 @@ int running_in_chroot(void) {
|
||||
if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
|
||||
return 0;
|
||||
|
||||
r = pidref_from_same_root_fs(&PIDREF_MAKE_FROM_PID(1), NULL);
|
||||
if (r == -ENOSYS) {
|
||||
if (getpid_cached() == 1)
|
||||
return false; /* We will mount /proc, assuming we're not in a chroot. */
|
||||
r = inode_same("/proc/1/root", "/", /* flags = */ 0);
|
||||
if (r == -ENOENT) {
|
||||
r = proc_mounted();
|
||||
if (r == 0) {
|
||||
if (getpid_cached() == 1)
|
||||
return false; /* We will mount /proc, assuming we're not in a chroot. */
|
||||
|
||||
log_debug("/proc/ is not mounted, assuming we're in a chroot.");
|
||||
return true;
|
||||
log_debug("/proc/ is not mounted, assuming we're in a chroot.");
|
||||
return true;
|
||||
}
|
||||
if (r > 0) /* If we have fake /proc/, we can't do the check properly. */
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (r == -ESRCH) /* We must have a fake /proc/, we can't do the check properly. */
|
||||
return -ENOSYS;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -1165,6 +1165,10 @@ static void boot_entry_parse_tries(
|
||||
if (!strcaseeq16(counter, suffix))
|
||||
return;
|
||||
|
||||
entry->id = xasprintf("%.*ls%ls",
|
||||
(int) prefix_len - 1,
|
||||
file,
|
||||
suffix);
|
||||
entry->tries_left = tries_left;
|
||||
entry->tries_done = tries_done;
|
||||
entry->path = xstrdup16(path);
|
||||
@ -1395,7 +1399,9 @@ static void boot_entry_add_type1(
|
||||
}
|
||||
|
||||
entry->device = device;
|
||||
entry->id = xstrdup16(file);
|
||||
|
||||
if (!entry->id)
|
||||
entry->id = xstrdup16(file);
|
||||
strtolower16(entry->id);
|
||||
|
||||
config_add_entry(config, entry);
|
||||
|
||||
@ -20,9 +20,6 @@
|
||||
#include "shim.h"
|
||||
#include "util.h"
|
||||
|
||||
#define STUB_PAYLOAD_GUID \
|
||||
{ 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
|
||||
|
||||
typedef struct {
|
||||
MEMMAP_DEVICE_PATH memmap_path;
|
||||
EFI_DEVICE_PATH end_path;
|
||||
@ -56,22 +53,12 @@ static EFI_STATUS load_via_boot_services(
|
||||
uint32_t compat_entry_point,
|
||||
const char16_t *cmdline,
|
||||
const struct iovec *kernel,
|
||||
const struct iovec *initrd) {
|
||||
const struct iovec *initrd,
|
||||
KERNEL_FILE_PATH *kernel_file_path) {
|
||||
_cleanup_(unload_imagep) EFI_HANDLE kernel_image = NULL;
|
||||
EFI_LOADED_IMAGE_PROTOCOL* loaded_image = NULL;
|
||||
EFI_STATUS err;
|
||||
|
||||
VENDOR_DEVICE_PATH device_node = {
|
||||
.Header = {
|
||||
.Type = MEDIA_DEVICE_PATH,
|
||||
.SubType = MEDIA_VENDOR_DP,
|
||||
.Length = sizeof(device_node),
|
||||
},
|
||||
.Guid = STUB_PAYLOAD_GUID,
|
||||
};
|
||||
|
||||
_cleanup_free_ EFI_DEVICE_PATH* file_path = device_path_replace_node(parent_loaded_image->FilePath, NULL, &device_node.Header);
|
||||
|
||||
/* When running with shim < v16 and booting a UKI directly from it, without a second stage loader,
|
||||
* the shim verify protocol needs to be called or it will raise a security violation when starting
|
||||
* the image (e.g.: Fedora Cloud Base UKI). TODO: drop once support for shim < v16 is not needed. */
|
||||
@ -81,13 +68,13 @@ static EFI_STATUS load_via_boot_services(
|
||||
&(ValidationContext) {
|
||||
.addr = kernel->iov_base,
|
||||
.len = kernel->iov_len,
|
||||
.device_path = file_path,
|
||||
.device_path = &kernel_file_path->memmap_path.Header,
|
||||
});
|
||||
|
||||
|
||||
err = BS->LoadImage(/* BootPolicy= */false,
|
||||
parent,
|
||||
file_path,
|
||||
&kernel_file_path->memmap_path.Header,
|
||||
kernel->iov_base,
|
||||
kernel->iov_len,
|
||||
&kernel_image);
|
||||
@ -204,17 +191,27 @@ EFI_STATUS linux_exec(
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Bad kernel image: %m");
|
||||
|
||||
/* Re-use the parent_image(_handle) and parent_loaded_image for the kernel image we are about to execute.
|
||||
* We have to do this, because if kernel stub code passes its own handle to certain firmware functions,
|
||||
* the firmware could cast EFI_LOADED_IMAGE_PROTOCOL * to a larger struct to access its own private data,
|
||||
* and if we allocated a smaller struct, that could cause problems.
|
||||
* This is modeled exactly after GRUB behaviour, which has proven to be functional. */
|
||||
EFI_LOADED_IMAGE_PROTOCOL *parent_loaded_image;
|
||||
err = BS->HandleProtocol(
|
||||
parent_image, MAKE_GUID_PTR(EFI_LOADED_IMAGE_PROTOCOL), (void **) &parent_loaded_image);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Cannot get parent loaded image: %m");
|
||||
|
||||
_cleanup_free_ KERNEL_FILE_PATH *kernel_file_path = xnew(KERNEL_FILE_PATH, 1);
|
||||
*kernel_file_path = (KERNEL_FILE_PATH) {
|
||||
.memmap_path = {
|
||||
.Header = {
|
||||
.Type = HARDWARE_DEVICE_PATH,
|
||||
.SubType = HW_MEMMAP_DP,
|
||||
.Length = sizeof(MEMMAP_DEVICE_PATH),
|
||||
},
|
||||
.MemoryType = EfiLoaderData,
|
||||
.StartingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base),
|
||||
.EndingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base) + kernel->iov_len,
|
||||
},
|
||||
.end_path = DEVICE_PATH_END_NODE,
|
||||
};
|
||||
|
||||
/* If shim provides LoadImage, it comes from the new SHIM_IMAGE_LOADER interface added in shim 16,
|
||||
* and implements the following:
|
||||
* - shim hashes PE sections of PE binaries it authenticates and stores the hashes in a global
|
||||
@ -241,7 +238,8 @@ EFI_STATUS linux_exec(
|
||||
compat_entry_point,
|
||||
cmdline,
|
||||
kernel,
|
||||
initrd);
|
||||
initrd,
|
||||
kernel_file_path);
|
||||
|
||||
err = pe_kernel_check_no_relocation(kernel->iov_base);
|
||||
if (err != EFI_SUCCESS)
|
||||
@ -300,26 +298,13 @@ EFI_STATUS linux_exec(
|
||||
}
|
||||
}
|
||||
|
||||
_cleanup_free_ KERNEL_FILE_PATH *kernel_file_path = xnew(KERNEL_FILE_PATH, 1);
|
||||
|
||||
*kernel_file_path = (KERNEL_FILE_PATH) {
|
||||
.memmap_path = {
|
||||
.Header = {
|
||||
.Type = HARDWARE_DEVICE_PATH,
|
||||
.SubType = HW_MEMMAP_DP,
|
||||
.Length = sizeof(MEMMAP_DEVICE_PATH),
|
||||
},
|
||||
.MemoryType = EfiLoaderData,
|
||||
.StartingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base),
|
||||
.EndingAddress = POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base) + kernel->iov_len,
|
||||
},
|
||||
.end_path = {
|
||||
.Type = END_DEVICE_PATH_TYPE,
|
||||
.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
||||
.Length = sizeof(EFI_DEVICE_PATH),
|
||||
},
|
||||
};
|
||||
|
||||
/* Patch the parent_image(_handle) and parent_loaded_image for the kernel image we are about to execute.
|
||||
* We have to do this, because if kernel stub code passes its own handle to certain firmware functions,
|
||||
* the firmware could cast EFI_LOADED_IMAGE_PROTOCOL * to a larger struct to access its own private data,
|
||||
* and if we allocated a smaller struct, that could cause problems.
|
||||
* This is modeled exactly after GRUB behaviour, which has proven to be functional. */
|
||||
EFI_LOADED_IMAGE_PROTOCOL original_parent_loaded_image = *parent_loaded_image;
|
||||
parent_loaded_image->FilePath = &kernel_file_path->memmap_path.Header;
|
||||
parent_loaded_image->ImageBase = loaded_kernel;
|
||||
parent_loaded_image->ImageSize = kernel_size_in_memory;
|
||||
|
||||
@ -346,6 +331,9 @@ EFI_STATUS linux_exec(
|
||||
err = compat_entry(parent_image, ST);
|
||||
}
|
||||
|
||||
/* Restore */
|
||||
*parent_loaded_image = original_parent_loaded_image;
|
||||
|
||||
/* On failure we'll free the buffers. EDK2 requires the memory buffers to be writable and
|
||||
* non-executable, as in some configurations it will overwrite them with a fixed pattern, so if the
|
||||
* attributes are not restored FreePages() will crash. */
|
||||
|
||||
@ -150,48 +150,59 @@ static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) {
|
||||
return cc;
|
||||
}
|
||||
|
||||
static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
|
||||
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
|
||||
.Size = sizeof(capability),
|
||||
};
|
||||
static EFI_TCG2_PROTOCOL* tcg2_interface_check(EFI_TCG2_VERSION *ret_version) {
|
||||
EFI_STATUS err;
|
||||
EFI_TCG2_PROTOCOL *tcg;
|
||||
|
||||
EFI_TCG2_PROTOCOL *tcg;
|
||||
err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_TCG2_PROTOCOL), NULL, (void **) &tcg);
|
||||
if (err != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
|
||||
.Size = sizeof(capability),
|
||||
};
|
||||
err = tcg->GetCapability(tcg, &capability);
|
||||
if (err != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
if (capability.StructureVersion.Major == 1 &&
|
||||
capability.StructureVersion.Minor == 0) {
|
||||
EFI_TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
|
||||
(EFI_TCG_BOOT_SERVICE_CAPABILITY*) &capability;
|
||||
if (caps_1_0->TPMPresentFlag)
|
||||
return tcg;
|
||||
}
|
||||
assert(capability.Size >= endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, Size));
|
||||
|
||||
/* This is a paranoia check, given these fields existed from day one of the spec. But the spec also
|
||||
* suggests checking the structure size before accessing any fields, hence let's do so, for extra
|
||||
* paranoia. */
|
||||
if (capability.Size < CONST_MAX(endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, TPMPresentFlag),
|
||||
endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, ProtocolVersion)))
|
||||
return NULL;
|
||||
|
||||
if (!capability.TPMPresentFlag)
|
||||
return NULL;
|
||||
|
||||
if (ret_version)
|
||||
*ret_version = capability.ProtocolVersion;
|
||||
|
||||
return tcg;
|
||||
}
|
||||
|
||||
bool tpm_present(void) {
|
||||
return tcg2_interface_check();
|
||||
return tcg2_interface_check(/* ret_version= */ NULL);
|
||||
}
|
||||
|
||||
uint32_t tpm_get_active_pcr_banks(void) {
|
||||
uint32_t active_pcr_banks = 0;
|
||||
EFI_TCG2_PROTOCOL *tpm2;
|
||||
EFI_STATUS err;
|
||||
|
||||
tpm2 = tcg2_interface_check();
|
||||
EFI_TCG2_PROTOCOL *tpm2;
|
||||
EFI_TCG2_VERSION version;
|
||||
tpm2 = tcg2_interface_check(&version);
|
||||
if (!tpm2)
|
||||
return 0;
|
||||
|
||||
/* GetActivePcrBanks() was added only in version 1.1 of the spec */
|
||||
if (version.Major < 1 || (version.Major == 1 && version.Minor < 1)) {
|
||||
log_debug("TCG protocol too old for GetActivePcrBanks(), claiming no active banks.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t active_pcr_banks = 0;
|
||||
err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks);
|
||||
if (err != EFI_SUCCESS) {
|
||||
log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m");
|
||||
@ -207,7 +218,7 @@ static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buf
|
||||
|
||||
assert(ret_measured);
|
||||
|
||||
tpm2 = tcg2_interface_check();
|
||||
tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
|
||||
if (!tpm2) {
|
||||
*ret_measured = false;
|
||||
return EFI_SUCCESS;
|
||||
@ -289,7 +300,7 @@ EFI_STATUS tpm_log_tagged_event(
|
||||
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
|
||||
* something, or false if measurement was turned off. */
|
||||
|
||||
tpm2 = tcg2_interface_check();
|
||||
tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
|
||||
if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */
|
||||
if (ret_measured)
|
||||
*ret_measured = false;
|
||||
|
||||
@ -10,27 +10,11 @@
|
||||
#define EV_IPL 13
|
||||
#define EV_EVENT_TAG UINT32_C(6)
|
||||
|
||||
typedef struct {
|
||||
uint8_t Major;
|
||||
uint8_t Minor;
|
||||
uint8_t RevMajor;
|
||||
uint8_t RevMinor;
|
||||
} TCG_VERSION;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Major;
|
||||
uint8_t Minor;
|
||||
} EFI_TCG2_VERSION;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Size;
|
||||
TCG_VERSION StructureVersion;
|
||||
TCG_VERSION ProtocolSpecVersion;
|
||||
uint8_t HashAlgorithmBitmap;
|
||||
bool TPMPresentFlag;
|
||||
bool TPMDeactivatedFlag;
|
||||
} EFI_TCG_BOOT_SERVICE_CAPABILITY;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Size;
|
||||
EFI_TCG2_VERSION StructureVersion;
|
||||
|
||||
@ -468,7 +468,8 @@ static int maybe_decrypt_and_write_credential(
|
||||
struct load_cred_args *args,
|
||||
const char *id,
|
||||
const char *data,
|
||||
size_t size) {
|
||||
size_t size,
|
||||
bool graceful) {
|
||||
|
||||
_cleanup_(iovec_done_erase) struct iovec plaintext = {};
|
||||
size_t add;
|
||||
@ -522,8 +523,14 @@ static int maybe_decrypt_and_write_credential(
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
if (graceful) {
|
||||
log_warning_errno(r, "Unable to decrypt credential '%s', skipping.", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
data = plaintext.iov_base;
|
||||
size = plaintext.iov_len;
|
||||
@ -612,7 +619,7 @@ static int load_credential_glob(
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read credential '%s': %m", *p);
|
||||
|
||||
r = maybe_decrypt_and_write_credential(args, fn, data, size);
|
||||
r = maybe_decrypt_and_write_credential(args, fn, data, size, /* graceful= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -737,7 +744,7 @@ static int load_credential(
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read credential '%s': %m", path);
|
||||
|
||||
return maybe_decrypt_and_write_credential(args, id, data, size);
|
||||
return maybe_decrypt_and_write_credential(args, id, data, size, /* graceful= */ true);
|
||||
}
|
||||
|
||||
static int load_cred_recurse_dir_cb(
|
||||
@ -874,10 +881,11 @@ static int acquire_credentials(
|
||||
|
||||
args.encrypted = false;
|
||||
|
||||
r = load_credential_glob(&args,
|
||||
ic,
|
||||
search_path,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER);
|
||||
r = load_credential_glob(
|
||||
&args,
|
||||
ic,
|
||||
search_path,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -889,10 +897,11 @@ static int acquire_credentials(
|
||||
|
||||
args.encrypted = true;
|
||||
|
||||
r = load_credential_glob(&args,
|
||||
ic,
|
||||
search_path,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER|READ_FULL_FILE_UNBASE64);
|
||||
r = load_credential_glob(
|
||||
&args,
|
||||
ic,
|
||||
search_path,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_FAIL_WHEN_LARGER|READ_FULL_FILE_UNBASE64);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -910,7 +919,7 @@ static int acquire_credentials(
|
||||
if (errno != ENOENT)
|
||||
return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sc->id);
|
||||
|
||||
r = maybe_decrypt_and_write_credential(&args, sc->id, sc->data, sc->size);
|
||||
r = maybe_decrypt_and_write_credential(&args, sc->id, sc->data, sc->size, /* graceful= */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -144,15 +144,15 @@
|
||||
#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
|
||||
#define UNIQ __COUNTER__
|
||||
|
||||
/* Note that this works differently from pthread_once(): this macro does
|
||||
* not synchronize code execution, i.e. code that is run conditionalized
|
||||
* on this macro will run concurrently to all other code conditionalized
|
||||
* the same way, there's no ordering or completion enforced. */
|
||||
/* The macro is true when the code block is called first time, and is false for the second and later times.
|
||||
* Note that this works differently from pthread_once(): this macro does not synchronize code execution, i.e.
|
||||
* code that is run conditionalized on this macro will run concurrently to all other code conditionalized the
|
||||
* same way, there's no ordering or completion enforced. */
|
||||
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
!__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
})
|
||||
|
||||
#define U64_KB UINT64_C(1024)
|
||||
|
||||
@ -126,17 +126,37 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
|
||||
if (!j || IN_SET(j->state, PULL_JOB_DONE, PULL_JOB_FAILED))
|
||||
return;
|
||||
|
||||
if (result != CURLE_OK) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Transfer failed: %s", curl_easy_strerror(result));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
code = curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
|
||||
if (code != CURLE_OK || !scheme) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to retrieve URL scheme.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (strcaseeq(scheme, "FILE") && result == CURLE_FILE_COULDNT_READ_FILE && j->on_not_found) {
|
||||
_cleanup_free_ char *new_url = NULL;
|
||||
|
||||
/* This resource wasn't found, but the implementor wants to maybe let us know a new URL, query for it. */
|
||||
r = j->on_not_found(j, &new_url);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
if (r > 0) { /* A new url to use */
|
||||
assert(new_url);
|
||||
|
||||
r = pull_job_restart(j, new_url);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* if this didn't work, handle like any other error below */
|
||||
}
|
||||
|
||||
if (result != CURLE_OK) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Transfer failed: %s", curl_easy_strerror(result));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (STRCASE_IN_SET(scheme, "HTTP", "HTTPS")) {
|
||||
long status;
|
||||
|
||||
@ -739,7 +759,7 @@ int pull_job_begin(PullJob *j) {
|
||||
if (curl_easy_setopt(j->curl, CURLOPT_XFERINFODATA, j) != CURLE_OK)
|
||||
return -EIO;
|
||||
|
||||
if (curl_easy_setopt(j->curl, CURLOPT_NOPROGRESS, 0) != CURLE_OK)
|
||||
if (curl_easy_setopt(j->curl, CURLOPT_NOPROGRESS, 0L) != CURLE_OK)
|
||||
return -EIO;
|
||||
|
||||
r = curl_glue_add(j->glue, j->curl);
|
||||
|
||||
@ -308,7 +308,7 @@ int start_upload(Uploader *u,
|
||||
}
|
||||
|
||||
if (STRPTR_IN_SET(arg_trust, "-", "all"))
|
||||
easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0,
|
||||
easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L,
|
||||
LOG_ERR, return -EUCLEAN);
|
||||
else if (arg_trust || startswith(u->url, "https://"))
|
||||
easy_setopt(curl, CURLOPT_CAINFO, arg_trust ?: TRUST_FILE,
|
||||
|
||||
@ -465,10 +465,14 @@ static int manager_set_kernel_audit(Manager *m) {
|
||||
|
||||
assert(m);
|
||||
assert(m->audit_fd >= 0);
|
||||
assert(m->config.set_audit >= 0);
|
||||
|
||||
if (m->config.set_audit < 0)
|
||||
if (m->config.set_audit == AUDIT_KEEP)
|
||||
return 0;
|
||||
|
||||
/* In the following, we can handle 'set_audit' as a boolean. */
|
||||
assert(IN_SET(m->config.set_audit, AUDIT_NO, AUDIT_YES));
|
||||
|
||||
struct {
|
||||
union {
|
||||
struct nlmsghdr header;
|
||||
@ -557,7 +561,7 @@ int manager_open_audit(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void manager_reset_kernel_audit(Manager *m, int old_set_audit) {
|
||||
void manager_reset_kernel_audit(Manager *m, AuditSetMode old_set_audit) {
|
||||
assert(m);
|
||||
|
||||
if (m->audit_fd < 0)
|
||||
|
||||
@ -10,4 +10,4 @@ void manager_process_audit_message(Manager *m, const void *buffer, size_t buffer
|
||||
void process_audit_string(Manager *m, int type, const char *data, size_t size);
|
||||
|
||||
int manager_open_audit(Manager *m);
|
||||
void manager_reset_kernel_audit(Manager *m, int old_set_audit);
|
||||
void manager_reset_kernel_audit(Manager *m, AuditSetMode old_set_audit);
|
||||
|
||||
@ -46,7 +46,7 @@ void journal_config_set_defaults(JournalConfig *c) {
|
||||
.compress.threshold_bytes = UINT64_MAX,
|
||||
.seal = -1,
|
||||
.read_kmsg = -1,
|
||||
.set_audit = -1,
|
||||
.set_audit = _AUDIT_SET_MODE_INVALID,
|
||||
.ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL,
|
||||
.ratelimit_burst = DEFAULT_RATE_LIMIT_BURST,
|
||||
.forward_to_syslog = -1,
|
||||
@ -59,6 +59,7 @@ void journal_config_set_defaults(JournalConfig *c) {
|
||||
.max_level_console = -1,
|
||||
.max_level_wall = -1,
|
||||
.max_level_socket = -1,
|
||||
.split_mode = _SPLIT_INVALID,
|
||||
};
|
||||
|
||||
journal_reset_metrics(&c->system_storage_metrics);
|
||||
@ -122,7 +123,7 @@ void manager_merge_configs(Manager *m) {
|
||||
MERGE_NON_NEGATIVE(read_kmsg, !m->namespace);
|
||||
/* By default, kernel auditing is enabled by the main namespace instance, and not controlled by
|
||||
* non-default namespace instances. */
|
||||
MERGE_NON_NEGATIVE(set_audit, m->namespace ? -1 : true);
|
||||
MERGE_NON_NEGATIVE(set_audit, m->namespace ? AUDIT_KEEP : AUDIT_YES);
|
||||
MERGE_NON_ZERO(sync_interval_usec, DEFAULT_SYNC_INTERVAL_USEC);
|
||||
|
||||
/* TODO: also merge them when comdline or credentials support to configure them. */
|
||||
@ -401,6 +402,16 @@ static const char* const split_mode_table[_SPLIT_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode);
|
||||
|
||||
static const char* const audit_set_mode_table[_AUDIT_SET_MODE_MAX] = {
|
||||
[AUDIT_NO] = "no",
|
||||
[AUDIT_YES] = "yes",
|
||||
[AUDIT_KEEP] = "keep",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(audit_set_mode, AuditSetMode, AUDIT_YES);
|
||||
/* For backward compatibility, an empty string has special meaning and equals to 'keep'. */
|
||||
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_audit_set_mode, audit_set_mode, AuditSetMode, AUDIT_KEEP);
|
||||
|
||||
int config_parse_line_max(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@ -27,6 +27,14 @@ typedef struct JournalCompressOptions {
|
||||
uint64_t threshold_bytes;
|
||||
} JournalCompressOptions;
|
||||
|
||||
typedef enum AuditSetMode {
|
||||
AUDIT_NO = 0, /* Disables the kernel audit subsystem on start. */
|
||||
AUDIT_YES, /* Enables the kernel audit subsystem on start. */
|
||||
AUDIT_KEEP, /* Keep the current kernel audit subsystem state. */
|
||||
_AUDIT_SET_MODE_MAX,
|
||||
_AUDIT_SET_MODE_INVALID = -EINVAL,
|
||||
} AuditSetMode;
|
||||
|
||||
typedef struct JournalConfig {
|
||||
/* Storage=, cred: journal.storage */
|
||||
Storage storage;
|
||||
@ -37,7 +45,7 @@ typedef struct JournalConfig {
|
||||
/* ReadKMsg= */
|
||||
int read_kmsg;
|
||||
/* Audit= */
|
||||
int set_audit;
|
||||
AuditSetMode set_audit;
|
||||
/* SyncIntervalSec= */
|
||||
usec_t sync_interval_usec;
|
||||
/* RateLimitIntervalSec= */
|
||||
@ -102,3 +110,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_line_max);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_compress);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_forward_to_socket);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_audit_set_mode);
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
typedef enum Storage Storage;
|
||||
typedef enum SplitMode SplitMode;
|
||||
typedef enum AuditSetMode AuditSetMode;
|
||||
typedef struct JournalCompressOptions JournalCompressOptions;
|
||||
typedef struct JournalConfig JournalConfig;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ Journal.Storage, config_parse_storage, 0, offsetof(Journa
|
||||
Journal.Compress, config_parse_compress, 0, offsetof(JournalConfig, compress)
|
||||
Journal.Seal, config_parse_tristate, 0, offsetof(JournalConfig, seal)
|
||||
Journal.ReadKMsg, config_parse_tristate, 0, offsetof(JournalConfig, read_kmsg)
|
||||
Journal.Audit, config_parse_tristate, 0, offsetof(JournalConfig, set_audit)
|
||||
Journal.Audit, config_parse_audit_set_mode, 0, offsetof(JournalConfig, set_audit)
|
||||
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(JournalConfig, sync_interval_usec)
|
||||
# The following is a legacy name for compatibility
|
||||
Journal.RateLimitInterval, config_parse_sec, 0, offsetof(JournalConfig, ratelimit_interval)
|
||||
|
||||
@ -150,8 +150,8 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
|
||||
r = chase(_syspath, NULL, 0, &syspath, &fd);
|
||||
if (r == -ENOENT)
|
||||
/* the device does not exist (any more?) */
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
|
||||
"sd-device: Failed to chase symlinks in \"%s\".", _syspath);
|
||||
return log_trace_errno(SYNTHETIC_ERRNO(ENODEV),
|
||||
"sd-device: Device \"%s\" not found.", _syspath);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "sd-device: Failed to get target of '%s': %m", _syspath);
|
||||
|
||||
|
||||
@ -4,31 +4,42 @@
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
GetInfo,
|
||||
SD_VARLINK_FIELD_COMMENT("String identifying the vendor of this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(vendor, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("String identifying the product implementing this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(product, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Version string of this product"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(version, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Web URL pointing to additional information about this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(url, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("List of interfaces implemented by this service"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(interfaces, SD_VARLINK_STRING, SD_VARLINK_ARRAY));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
GetInterfaceDescription,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of interface to query interface description of"),
|
||||
SD_VARLINK_DEFINE_INPUT(interface, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("Interface description in Varlink IDL format"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(description, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
InterfaceNotFound,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of interface that was called but does not exist"),
|
||||
SD_VARLINK_DEFINE_FIELD(interface, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
MethodNotFound,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of method that was called but does not exist"),
|
||||
SD_VARLINK_DEFINE_FIELD(method, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
MethodNotImplemented,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of method that was called but is not implemented."),
|
||||
SD_VARLINK_DEFINE_FIELD(method, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(
|
||||
InvalidParameter,
|
||||
SD_VARLINK_FIELD_COMMENT("Name of the invalid parameter"),
|
||||
SD_VARLINK_DEFINE_FIELD(parameter, SD_VARLINK_STRING, 0));
|
||||
|
||||
static SD_VARLINK_DEFINE_ERROR(PermissionDenied);
|
||||
@ -39,11 +50,20 @@ static SD_VARLINK_DEFINE_ERROR(ExpectedMore);
|
||||
SD_VARLINK_DEFINE_INTERFACE(
|
||||
org_varlink_service,
|
||||
"org.varlink.service",
|
||||
SD_VARLINK_INTERFACE_COMMENT("General Varlink service interface"),
|
||||
SD_VARLINK_SYMBOL_COMMENT("Get service meta information"),
|
||||
&vl_method_GetInfo,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Get description of an implemented interface in Varlink IDL format"),
|
||||
&vl_method_GetInterfaceDescription,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if a method is called on an unknown interface"),
|
||||
&vl_error_InterfaceNotFound,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if an unknown method is called on an known interface"),
|
||||
&vl_error_MethodNotFound,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if an method is called that is known but not implemented"),
|
||||
&vl_error_MethodNotImplemented,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Error returned if a method is called with an invalid parameter"),
|
||||
&vl_error_InvalidParameter,
|
||||
SD_VARLINK_SYMBOL_COMMENT("General permission error"),
|
||||
&vl_error_PermissionDenied,
|
||||
SD_VARLINK_SYMBOL_COMMENT("A method was called with the 'more' flag off, but it may only be called with the flag turned on"),
|
||||
&vl_error_ExpectedMore);
|
||||
|
||||
@ -1712,9 +1712,10 @@ static int close_osc_context(pam_handle_t *handle) {
|
||||
if (r < 0)
|
||||
return pam_syslog_errno(handle, LOG_ERR, r, "Failed to prepare OSC sequence: %m");
|
||||
|
||||
/* When we are closing things, the TTY might not take our writes anymore. Accept that gracefully. */
|
||||
r = loop_write(fd, osc, SIZE_MAX);
|
||||
if (r < 0)
|
||||
return pam_syslog_errno(handle, LOG_ERR, r, "Failed to write OSC sequence to TTY: %m");
|
||||
pam_syslog_errno(handle, LOG_DEBUG, r, "Failed to write OSC sequence to TTY, ignoring: %m");
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "machine-dbus.h"
|
||||
#include "machined.h"
|
||||
#include "mount-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "operation.h"
|
||||
#include "path-util.h"
|
||||
#include "signal-util.h"
|
||||
@ -355,6 +356,25 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
if (r < 0)
|
||||
return r;
|
||||
user = isempty(user) ? "root" : user;
|
||||
|
||||
/* Ensure only root can shell into the root namespace, unless it's specifically the host machine,
|
||||
* which is owned by uid 0 anyway and cannot be self-registered. This is to avoid unprivileged
|
||||
* users registering a process they own in the root user namespace, and then shelling in as root
|
||||
* or another user. Note that the shell operation is privileged and requires 'auth_admin', so we
|
||||
* do not need to check the caller's uid, as that will be checked by polkit, and if they machine's
|
||||
* and the caller's do not match, authorization will be required. It's only the case where the
|
||||
* caller owns the machine that will be shortcut and needs to be checked here. */
|
||||
if (m->uid != 0 && m->class != MACHINE_HOST) {
|
||||
r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &m->leader, NAMESPACE_USER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != 0)
|
||||
return sd_bus_error_set(
|
||||
error,
|
||||
SD_BUS_ERROR_ACCESS_DENIED,
|
||||
"Only root may shell into the root user namespace");
|
||||
}
|
||||
|
||||
r = sd_bus_message_read_strv(message, &args_wire);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
ip={dhcp|on|any|dhcp6|auto6|either6|link6|link-local}
|
||||
ip=<interface>:{dhcp|on|any|dhcp6|auto6|link6|link-local}[:[<mtu>][:<macaddr>]]
|
||||
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|link6|ibft|link-local}[:[<mtu>][:<macaddr>]]
|
||||
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|link6|ibft|link-local}[:[<dns1>][:<dns2>]]
|
||||
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|link6|ibft|link-local}[:[<dns1>][:[<dns2>][:[<ntp>]]]]
|
||||
rd.route=<net>/<netmask>:<gateway>[:<interface>]
|
||||
nameserver=<IP> [nameserver=<IP> ...]
|
||||
rd.peerdns=0
|
||||
@ -197,6 +197,7 @@ static Network* network_free(Network *network) {
|
||||
strv_free(network->vlan);
|
||||
free(network->bridge);
|
||||
free(network->bond);
|
||||
free(network->ntp);
|
||||
|
||||
while ((address = network->addresses))
|
||||
address_free(address);
|
||||
@ -650,6 +651,27 @@ static int network_set_bond(Context *context, const char *ifname, const char *va
|
||||
return free_and_strdup(&network->bond, value);
|
||||
}
|
||||
|
||||
static int network_set_ntp(Context *context, const char *ifname, const char *value) {
|
||||
Network *network;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
assert(ifname);
|
||||
|
||||
if (isempty(value))
|
||||
return 0;
|
||||
|
||||
r = in_addr_from_string_auto(value, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Invalid NTP address '%s' for '%s'", value, ifname);
|
||||
|
||||
r = network_acquire(context, ifname, &network);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to acquire network for '%s': %m", ifname);
|
||||
|
||||
return free_and_strdup(&network->ntp, value);
|
||||
}
|
||||
|
||||
static int parse_cmdline_ip_mtu_mac(Context *context, const char *ifname, const char *value) {
|
||||
_cleanup_free_ char *mtu = NULL;
|
||||
int r;
|
||||
@ -865,6 +887,18 @@ static int parse_cmdline_ip_address(Context *context, int family, const char *va
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Next, try [:<ntp>] */
|
||||
_cleanup_free_ char *ntp = NULL;
|
||||
r = extract_ip_address_str(AF_UNSPEC, &p, &ntp);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse NTP address in ip=%s: %m", value);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
r = network_set_ntp(context, ifname, ntp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* refuse unexpected trailing strings */
|
||||
if (!isempty(p))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected trailing string in 'ip=%s'.", value);
|
||||
@ -1373,6 +1407,9 @@ void network_dump(Network *network, FILE *f) {
|
||||
if (network->bond)
|
||||
fprintf(f, "Bond=%s\n", network->bond);
|
||||
|
||||
if (network->ntp)
|
||||
fprintf(f, "NTP=%s\n", network->ntp);
|
||||
|
||||
fputs("\n[DHCP]\n", f);
|
||||
|
||||
if (!isempty(network->hostname))
|
||||
|
||||
@ -65,6 +65,7 @@ struct Network {
|
||||
char **vlan;
|
||||
char *bridge;
|
||||
char *bond;
|
||||
char *ntp;
|
||||
|
||||
/* [DHCP] */
|
||||
char *hostname;
|
||||
|
||||
@ -213,6 +213,51 @@ int main(int argc, char *argv[]) {
|
||||
"Gateway=192.168.0.1\n"
|
||||
);
|
||||
|
||||
test_network_one("eth0", "ip", "192.168.0.10::192.168.0.1:255.255.255.0::eth0:on:10.10.10.10:10.10.10.11:10.10.10.161",
|
||||
"[Match]\n"
|
||||
"Name=eth0\n"
|
||||
"\n[Link]\n"
|
||||
"\n[Network]\n"
|
||||
"DHCP=yes\n"
|
||||
"DNS=10.10.10.10\n"
|
||||
"DNS=10.10.10.11\n"
|
||||
"NTP=10.10.10.161\n"
|
||||
"\n[DHCP]\n"
|
||||
"\n[Address]\n"
|
||||
"Address=192.168.0.10/24\n"
|
||||
"\n[Route]\n"
|
||||
"Gateway=192.168.0.1\n"
|
||||
);
|
||||
|
||||
test_network_one("eth0", "ip", "192.168.0.10::192.168.0.1:255.255.255.0::eth0:on:10.10.10.10::10.10.10.161",
|
||||
"[Match]\n"
|
||||
"Name=eth0\n"
|
||||
"\n[Link]\n"
|
||||
"\n[Network]\n"
|
||||
"DHCP=yes\n"
|
||||
"DNS=10.10.10.10\n"
|
||||
"NTP=10.10.10.161\n"
|
||||
"\n[DHCP]\n"
|
||||
"\n[Address]\n"
|
||||
"Address=192.168.0.10/24\n"
|
||||
"\n[Route]\n"
|
||||
"Gateway=192.168.0.1\n"
|
||||
);
|
||||
|
||||
test_network_one("eth0", "ip", "192.168.0.10::192.168.0.1:255.255.255.0::eth0:on:::10.10.10.161",
|
||||
"[Match]\n"
|
||||
"Name=eth0\n"
|
||||
"\n[Link]\n"
|
||||
"\n[Network]\n"
|
||||
"DHCP=yes\n"
|
||||
"NTP=10.10.10.161\n"
|
||||
"\n[DHCP]\n"
|
||||
"\n[Address]\n"
|
||||
"Address=192.168.0.10/24\n"
|
||||
"\n[Route]\n"
|
||||
"Gateway=192.168.0.1\n"
|
||||
);
|
||||
|
||||
test_network_one("eth0", "ip", "[2001:1234:56:8f63::10]::[2001:1234:56:8f63::1]:64:hogehoge:eth0:on",
|
||||
"[Match]\n"
|
||||
"Name=eth0\n"
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-network.h"
|
||||
|
||||
@ -14,7 +13,6 @@
|
||||
#include "networkctl-util.h"
|
||||
|
||||
int list_links(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
_cleanup_(link_info_array_freep) LinkInfo *links = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
@ -25,10 +23,6 @@ int list_links(int argc, char *argv[], void *userdata) {
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = acquire_bus(&bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_open(&rtnl);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||
|
||||
@ -768,7 +768,7 @@ static int link_status_one(
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = table_add_cell_stringf(table, NULL, "%sbps/%sbps",
|
||||
r = table_add_cell_stringf(table, NULL, "%sBps/%sBps",
|
||||
FORMAT_BYTES_FULL(info->tx_bitrate, 0),
|
||||
FORMAT_BYTES_FULL(info->rx_bitrate, 0));
|
||||
if (r < 0)
|
||||
|
||||
@ -444,14 +444,15 @@ static int network_append_json(Network *network, sd_json_variant **v) {
|
||||
v,
|
||||
SD_JSON_BUILD_PAIR_STRING("NetworkFile", network->filename),
|
||||
SD_JSON_BUILD_PAIR_STRV("NetworkFileDropins", network->dropins),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("RequiredForOnline", network->required_for_online),
|
||||
SD_JSON_BUILD_PAIR("RequiredOperationalStateForOnline",
|
||||
SD_JSON_BUILD_ARRAY(SD_JSON_BUILD_STRING(link_operstate_to_string(network->required_operstate_for_online.min)),
|
||||
SD_JSON_BUILD_STRING(link_operstate_to_string(network->required_operstate_for_online.max)))),
|
||||
SD_JSON_BUILD_PAIR_STRING("RequiredFamilyForOnline",
|
||||
link_required_address_family_to_string(network->required_family_for_online)),
|
||||
SD_JSON_BUILD_PAIR_STRING("ActivationPolicy",
|
||||
activation_policy_to_string(network->activation_policy)));
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("RequiredForOnline", network->required_for_online > 0),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(
|
||||
operational_state_range_is_valid(&network->required_operstate_for_online),
|
||||
"RequiredOperationalStateForOnline",
|
||||
SD_JSON_BUILD_ARRAY(
|
||||
SD_JSON_BUILD_STRING(link_operstate_to_string(network->required_operstate_for_online.min)),
|
||||
SD_JSON_BUILD_STRING(link_operstate_to_string(network->required_operstate_for_online.max)))),
|
||||
SD_JSON_BUILD_PAIR_STRING("RequiredFamilyForOnline", link_required_address_family_to_string(network->required_family_for_online)),
|
||||
SD_JSON_BUILD_PAIR_STRING("ActivationPolicy", activation_policy_to_string(network->activation_policy)));
|
||||
}
|
||||
|
||||
static int netdev_append_json(NetDev *netdev, sd_json_variant **v) {
|
||||
|
||||
@ -202,6 +202,7 @@ static AppendMode arg_append_fstab = APPEND_NO;
|
||||
static char *arg_generate_fstab = NULL;
|
||||
static char *arg_generate_crypttab = NULL;
|
||||
static Set *arg_verity_settings = NULL;
|
||||
static bool arg_relax_copy_block_security = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
@ -8737,6 +8738,9 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY *
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_relax_copy_block_security = false;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_IMAGE_POLICY:
|
||||
@ -9157,6 +9161,8 @@ static int parse_argv(int argc, char *argv[], X509 **ret_certificate, EVP_PKEY *
|
||||
arg_root = strdup("/sysusr");
|
||||
if (!arg_root)
|
||||
return log_oom();
|
||||
|
||||
arg_relax_copy_block_security = true;
|
||||
}
|
||||
|
||||
if (argc > optind) {
|
||||
@ -9831,7 +9837,9 @@ static int run(int argc, char *argv[]) {
|
||||
r = context_open_copy_block_paths(
|
||||
context,
|
||||
loop_device ? loop_device->devno : /* if --image= is specified, only allow partitions on the loopback device */
|
||||
arg_root && !arg_image ? 0 : /* if --root= is specified, don't accept any block device */
|
||||
/* if --root= is specified, don't accept any block device, unless it
|
||||
* was set automatically because we are in the initrd */
|
||||
arg_root && !arg_image && !arg_relax_copy_block_security ? 0 :
|
||||
(dev_t) -1); /* if neither is specified, make no restrictions */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -147,7 +147,7 @@ static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
|
||||
dns_search_domain_unref(c->search_domain);
|
||||
c->search_domain = dns_search_domain_ref(next);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dns_query_candidate_add_transaction(
|
||||
|
||||
@ -1365,7 +1365,7 @@ int decrypt_credential_and_warn(
|
||||
/* srk= */ NULL,
|
||||
&tpm2_key);
|
||||
if (r == -EREMOTE)
|
||||
return log_error_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM.");
|
||||
return log_error_errno(r, "TPM key integrity check failed. Key most likely does not belong to this TPM.");
|
||||
if (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r))
|
||||
return log_error_errno(r, "TPM policy does not match current system state. Either system has been tempered with or policy out-of-date: %m");
|
||||
if (r < 0)
|
||||
|
||||
@ -104,7 +104,7 @@ static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||
SD_VARLINK_FIELD_COMMENT("Return the base UID/GID of the machine"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(UIDShift, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Subcgroup path of the machine, relative to the unit's cgroup path"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(Subgroup, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_DEFINE_OUTPUT(subgroup, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Numeric UNIX UID of the user who registered the machine"),
|
||||
SD_VARLINK_DEFINE_OUTPUT(UID, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
|
||||
|
||||
|
||||
@ -349,6 +349,7 @@ static int help(void) {
|
||||
" --tldr Show non-comment parts of configuration\n"
|
||||
" --prefix=PATH Only apply rules with the specified prefix\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --strict Fail on any kind of failures\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
link);
|
||||
|
||||
@ -42,6 +42,22 @@ static void test_file(void) {
|
||||
assert_se(startswith(__FILE__, RELATIVE_SOURCE_PATH "/"));
|
||||
}
|
||||
|
||||
static void test_log_once_impl(void) {
|
||||
log_once(LOG_INFO, "This should be logged in LOG_INFO at first, then in LOG_DEBUG later.");
|
||||
log_once(LOG_DEBUG, "This should be logged only once in LOG_DEBUG.");
|
||||
ASSERT_ERROR(log_once_errno(LOG_INFO, SYNTHETIC_ERRNO(ENOANO),
|
||||
"This should be logged with errno in LOG_INFO at first, then in LOG_DEBUG later: %m"),
|
||||
ENOANO);
|
||||
ASSERT_ERROR(log_once_errno(LOG_DEBUG, SYNTHETIC_ERRNO(EBADMSG),
|
||||
"This should be logged only once with errno in LOG_DEBUG: %m"),
|
||||
EBADMSG);
|
||||
}
|
||||
|
||||
static void test_log_once(void) {
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
test_log_once_impl();
|
||||
}
|
||||
|
||||
static void test_log_struct(void) {
|
||||
log_struct(LOG_INFO,
|
||||
"MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(),
|
||||
@ -233,6 +249,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
assert_se(log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "foo") == -EUCLEAN);
|
||||
|
||||
test_log_once();
|
||||
|
||||
for (int target = 0; target < _LOG_TARGET_MAX; target++) {
|
||||
log_set_target(target);
|
||||
log_open();
|
||||
|
||||
@ -1102,4 +1102,20 @@ TEST(u64_multiply_safe) {
|
||||
assert_se(u64_multiply_safe(UINT64_MAX, UINT64_MAX) == 0);
|
||||
}
|
||||
|
||||
static void test_once_impl(void) {
|
||||
static unsigned count = 0;
|
||||
|
||||
if (ONCE) {
|
||||
log_info("This should be logged only once.");
|
||||
count++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(count, 1u);
|
||||
}
|
||||
|
||||
TEST(once) {
|
||||
for (unsigned i = 0; i < 20; i++)
|
||||
test_once_impl();
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
@ -69,4 +69,22 @@ machinectl terminate zurps
|
||||
"$(systemctl show -p MainPID --value systemd-logind.service)" \
|
||||
"$PWD")
|
||||
|
||||
run0 -u testuser \
|
||||
busctl call \
|
||||
org.freedesktop.machine1 \
|
||||
/org/freedesktop/machine1 \
|
||||
org.freedesktop.machine1.Manager \
|
||||
RegisterMachine \
|
||||
'sayssus' \
|
||||
shouldnotwork2 \
|
||||
16 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 \
|
||||
"" \
|
||||
container \
|
||||
"$(systemctl show -p MainPID --value user@4711.service)" \
|
||||
"$PWD"
|
||||
(! run0 -u testuser machinectl shell shouldnotwork2 /usr/bin/id -u)
|
||||
(! run0 -u testuser machinectl shell root@shouldnotwork2 /usr/bin/id -u)
|
||||
(! run0 -u testuser machinectl shell 0@shouldnotwork2 /usr/bin/id -u)
|
||||
(! run0 -u testuser machinectl shell testuser@shouldnotwork2 /usr/bin/id -u)
|
||||
|
||||
loginctl disable-linger testuser
|
||||
|
||||
@ -836,7 +836,7 @@ EOF
|
||||
btrfs filesystem show
|
||||
helper_check_device_symlinks
|
||||
helper_check_device_units
|
||||
wipefs -a -f "${devices[0]}"
|
||||
udevadm lock --timeout=30 --device="${devices[0]}" wipefs -a "${devices[0]}"
|
||||
udevadm wait --settle --timeout=30 --removed /dev/disk/by-partlabel/diskpart{1..4}
|
||||
|
||||
echo "Multiple devices: using disks, data: raid10, metadata: raid10, mixed mode"
|
||||
|
||||
@ -49,10 +49,9 @@ FSTAB_GENERAL=(
|
||||
"/dev/test25 /x-systemd.validatefs xfs x-systemd.validatefs 0 0"
|
||||
|
||||
# Incomplete, but valid entries
|
||||
"/dev/incomplete1 /incomplete1"
|
||||
"/dev/incomplete2 /incomplete2 ext4"
|
||||
"/dev/incomplete3 /incomplete3 ext4 defaults"
|
||||
"/dev/incomplete4 /incomplete4 ext4 defaults 0"
|
||||
"/dev/incomplete1 /incomplete1 ext4"
|
||||
"/dev/incomplete2 /incomplete2 ext4 defaults"
|
||||
"/dev/incomplete3 /incomplete3 ext4 defaults 0"
|
||||
|
||||
# Remote filesystems
|
||||
"/dev/remote1 /nfs nfs bg 0 0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user