Compare commits

..

26 Commits

Author SHA1 Message Date
Yu Watanabe 1294661381 polkit: remove unused variable
Follow-up for 6374862615.
2020-02-05 12:47:32 +00:00
Zbigniew Jędrzejewski-Szmek c450335bf7 github: remove direct paypal link
Fixes #14786. I think it is enough if we provide the link to
SPI which sports a prominent paypal link too.
2020-02-05 21:29:34 +09:00
Zbigniew Jędrzejewski-Szmek 384db814ee meson: bump version numbers for v245 2020-02-05 10:20:56 +01:00
Zbigniew Jędrzejewski-Szmek 901d1ce8ef NEWS: add contributors for v245 2020-02-05 10:20:56 +01:00
Zbigniew Jędrzejewski-Szmek 573e58f62f NEWS: mention the operational state changes 2020-02-05 10:20:56 +01:00
Zbigniew Jędrzejewski-Szmek ea0d0ede03 Merge branch 'polkit-ref-count' 2020-02-05 10:16:59 +01:00
Zbigniew Jędrzejewski-Szmek 239bf9409d
Merge pull request #14536 from DaanDeMeyer/wait-online-max-operstate
wait-online: add maximum operational state option
2020-02-05 10:16:29 +01:00
Yu Watanabe f05c0615f4 NEWS: mention SuppressPrefixLength= 2020-02-05 10:13:27 +01:00
Frantisek Sumsal 9569e38503 test: adapt to the new capsh format
Since libcap v2.29 the format of cap_to_text() has been changed which
makes certain `test-execute` subtest fail. Let's remove the offending
part of the output (dropped capabilities) to make it compatible with
both the old and the new libcap.
2020-02-05 10:11:42 +01:00
Zbigniew Jędrzejewski-Szmek f2394ddb08 Merge pull request #14779 from keszybz/news-v245 2020-02-05 09:35:58 +01:00
Zbigniew Jędrzejewski-Szmek 69f173477b NEWS: mention the TrafficControlQueueingDiscipline rename 2020-02-05 09:32:16 +01:00
Zbigniew Jędrzejewski-Szmek 823b035271 NEWS: mention empty .link and .network files 2020-02-05 09:32:16 +01:00
Zbigniew Jędrzejewski-Szmek 2ad988896c NEWS: reword and shorten a bunch of stuff 2020-02-05 09:32:16 +01:00
Yu Watanabe 641aa41200 test-network: use udevd in build directory
Fixes #14764.
2020-02-05 17:25:35 +09:00
Zbigniew Jędrzejewski-Szmek bc130b6858 Fix typo in function name 2020-02-04 18:54:12 +01:00
Lennart Poettering 5c11632735 man: document the new sd_bus_enqueue_for_read() API call 2020-02-04 18:47:32 +01:00
Lennart Poettering 6374862615 polkit: when authorizing via PK let's re-resolve callback/userdata instead of caching it
Previously, when doing an async PK query we'd store the original
callback/userdata pair and call it again after the PK request is
complete. This is problematic, since PK queries might be slow and in the
meantime the userdata might be released and re-acquired. Let's avoid
this by always traversing through the message handlers so that we always
re-resolve the callback and userdata pair and thus can be sure it's
up-to-date and properly valid.
2020-02-04 18:47:32 +01:00
Lennart Poettering 1068447e69 sd-bus: introduce API for re-enqueuing incoming messages
When authorizing via PolicyKit we want to process incoming method calls
twice: once to process and figure out that we need PK authentication,
and a second time after we aquired PK authentication to actually execute
the operation. With this new call sd_bus_enqueue_for_read() we have a
way to put an incoming message back into the read queue for this
purpose.

This might have other uses too, for example debugging.
2020-02-04 18:47:31 +01:00
Lennart Poettering f4425c72c7 polkit: use structured initialization 2020-02-04 18:45:22 +01:00
Lennart Poettering 7f56982289 polkit: on async pk requests, re-validate action/details
When we do an async pk request, let's store which action/details we used
for the original request, and when we are called for the second time,
let's compare. If the action/details changed, let's not allow the access
to go through.
2020-02-04 18:45:22 +01:00
Lennart Poettering 95f82ae9d7 polkit: reuse some common bus message appending code 2020-02-04 18:45:22 +01:00
Lennart Poettering 773b1a7916 bus-polkit: rename return error parameter to ret_error 2020-02-04 18:45:22 +01:00
Zbigniew Jędrzejewski-Szmek 6bdd90fbcd man: add "quick-help" to sysusers.d synopsis
We have that in tmpfiles.d and it is makes looking up the syntax
very easy.

While at it, add an example for "r" and use the underscrore as prefix
as described in the text.
2020-02-04 18:20:28 +01:00
Zbigniew Jędrzejewski-Szmek 8e92d92fb8 man: tweak description of blockdev@.target
In particular, let's just say "is" and "must" instead of "may be" and
"should". The weaker forms are obviously correct, but the text is easier to
understand if non-conditional forms are used.
2020-02-04 16:40:52 +01:00
Daan De Meyer 5cbaf95ee3 wait-online: Support waiting for interfaces to disappear 2020-01-18 18:17:25 +01:00
Daan De Meyer 75cd4a5d92 wait-online: Add maximum operational state option 2020-01-18 18:17:22 +01:00
35 changed files with 601 additions and 280 deletions

2
.github/FUNDING.yml vendored
View File

@ -1 +1 @@
custom: ['https://spi-inc.org/projects/systemd/', 'https://www.paypal.com/donate/?token=fBGzXDOyIGobZH3oEhYQlYlA61OMRXVnF9XXQqNNehRs-nliAU5XxozIh9z-hlmE-xXC-m'] custom: ['https://spi-inc.org/projects/systemd/']

265
NEWS
View File

@ -1,31 +1,28 @@
systemd System and Service Manager systemd System and Service Manager
CHANGES WITH 245 in spe: CHANGES WITH 245:
* A new tool "systemd-repart" has been added, that operates as an * A new tool "systemd-repart" has been added, that operates as an
idempotent, robust, incremental, elastic and declarative idempotent declarative repartitioner for GPT partition tables.
repartitioner. It takes inspiration from Specifically, a set of partitions that must or may exist can be
systemd-tmpfiles/systemd-sysusers but applies the algorithmic configured via drop-in files, and during every boot the partition
concepts to GPT partition tables. Specifically, a set of partitions table on disk is compared with these files, creating missing
that must or may exist can be configured via drop-in files, and partitions or growing existing ones based on configurable relative
during every boot the partition table on disk is compared with these and absolute size constraints. The tool is strictly incremental,
files, creating missing partitions or growing existing ones based on i.e. does not delete, shrink or move partitions, but only adds and
configurable relative and absolute size constraints. The tool is grows them. The primary use-case is OS images that ship in minimized
strictly incremental, i.e. does not delete, shrink or move form, that on first boot are grown to the size of the underlying
partitions, but only adds and grows them. The primary use-case is OS block device or augmented with additional partitions. For example,
images that shall ship in minimized form, with only a minimal boot the root partition could be extended to cover the whole disk, or a
and root partition, that on first boot is grown to the size of the swap or /home partitions could be added on first boot. It can also be
underlying block device or augmented with additional partitions. For used for systems that use an A/B update scheme but ship images with
example, the root partition could be extended to cover the whole just the A partition, with B added on first boot. The tool is
disk, or a swap or /home partitions could be added implicitly on primarily intended to be run in the initrd, shortly before
first boot. It also has uses on systems that use an A/B update scheme transitioning into the host OS, but can also be run after the
to allow shipping minimal images with just the A set of partition, transition took place. It automatically discovers the disk backing
and with the B set added on first boot. The tool is primarily the root file system, and should hence not require any additional
intended to be run in the initrd, shortly before transitioning into configuration besides the partition definition drop-ins. If no
the host OS, but also can be run after the transition took place. It configuration drop-ins are present, no action is taken.
automatically discovers the disk backing the root file system, and
should hence not require any additional configuration besides the
partition definition drop-ins.
* A new component "userdb" has been added, along with a small daemon * A new component "userdb" has been added, along with a small daemon
"systemd-userdb.service" and a client tool "userdbctl". The framework "systemd-userdb.service" and a client tool "userdbctl". The framework
@ -43,22 +40,21 @@ CHANGES WITH 245 in spe:
that for the first time resource management and various other that for the first time resource management and various other
per-user settings can be configured in LDAP directories and then per-user settings can be configured in LDAP directories and then
provided to systemd (specifically to systemd-logind and pam-system) provided to systemd (specifically to systemd-logind and pam-system)
to enforce on log-in. For further details see: to apply on login. For further details see:
https://systemd.io/USER_RECORD https://systemd.io/USER_RECORD
https://systemd.io/GROUP_RECORD https://systemd.io/GROUP_RECORD
https://systemd.io/USER_GROUP_API https://systemd.io/USER_GROUP_API
* A small new service systemd-homed.service has been added, that may be * A small new service systemd-homed.service has been added, that may be
used to securely manage home directories, with built-in encryption used to securely manage home directories with built-in encryption.
and unifying the user's own home directory data together with The complete user record data is unified with the home directory,
complete user record data in a single place, thus making home thus making home directories naturally migratable. Its primary
directories naturally migratable. Its primary back-end is based on back-end is based on LUKS volumes, but fscrypt, plain directories,
LUKS volumes, but it also supports fscrypt, plain directories and and other storage schemes are also supported. This solves a couple of
more. It solves a couple of problems we saw with traditional ways to problems we saw with traditional ways to manage home directories, in
manage home directories, in particular when it comes to particular when it comes to encryption. For further discussion of
encryption. For further discussion of this, see the video of this, see the video of Lennart's talk at AllSystemsGo! 2019:
Lennart's talk at AllSystemsGo! 2019:
https://media.ccc.de/v/ASG2019-164-reinventing-home-directories https://media.ccc.de/v/ASG2019-164-reinventing-home-directories
@ -69,49 +65,49 @@ CHANGES WITH 245 in spe:
* systemd-journald is now multi-instantiable. In addition to the main * systemd-journald is now multi-instantiable. In addition to the main
instance systemd-journald.service there's now a template unit instance systemd-journald.service there's now a template unit
systemd-journald@.service that can be instantiated multiple times, systemd-journald@.service, with each instance defining a new named
each time defining a new named log 'namespace' (whose name is log 'namespace' (whose name is specified via the instance part of the
specified via the instance part of the instance unit name). A new unit name). A new unit file setting LogNamespace= has been added,
unit file setting LogNamespace= has been added, taking such a taking such a namespace name, that assigns services to the specified
namespace name, that allows assigning services to such log log namespaces. As each log namespace is serviced by its own
namespaces. As each log namespace is serviced by its own, independent independent journal daemon, this functionality may be used to improve
journal daemon this functionality may be use to improve performance performance and increase isolation of applications, at the price of
and increase isolation of applications, at the price of losing global losing global message ordering. Each instance of journald has a
message ordering. Each daemon may have a separate set of separate set of configuration files, with possibly different disk
configuration files, with possibly different disk space settings and usage limitations and other settings.
such. journalctl has been updated to take a new option --namespace=
which allows viewing logs from a specific log namespace. The journalctl now takes a new option --namespace= to show logs from a
sd-journal.h API gained sd_journal_open_namespace() for opening the specific log namespace. The sd-journal.h API gained
log stream of a specific log namespace. systemd-journald also gained sd_journal_open_namespace() for opening the log stream of a specific
the ability to exit on idle, which is useful in the context of log log namespace. systemd-journald also gained the ability to exit on
namespaces, as this means log daemons for log namespaces can be idle, which is useful in the context of log namespaces, as this means
activated automatically on demand and stop automatically when no log daemons for log namespaces can be activated automatically on
longer used, minimizing resource usage. demand and will stop automatically when no longer used, minimizing
resource usage.
* When systemd-tmpfiles copies a file tree using the 'C' line type it * When systemd-tmpfiles copies a file tree using the 'C' line type it
will now implicitly label every copied file matching the SELinux will now label every copied file according to the SELinux database.
database.
* When systemd/PID 1 detects it is used in the initrd it will now boot * When systemd/PID 1 detects it is used in the initrd it will now boot
into initrd.target rather than default.target by default. This should into initrd.target rather than default.target by default. This should
make it simpler to build initrds with systemd as for many cases the make it simpler to build initrds with systemd as for many cases the
only difference between a host OS image and an initrd image now is only difference between a host OS image and an initrd image now is
the /etc/initrd-release file that identifies the initrd as one. the presence of the /etc/initrd-release file.
* A new kernel command line option systemd.cpu_affinity= is now * A new kernel command line option systemd.cpu_affinity= is now
understood. It's equivalent to the CPUAffinity= option in understood. It's equivalent to the CPUAffinity= option in
/etc/systemd/system.conf and allows setting the CPU mask for PID 1 /etc/systemd/system.conf and allows setting the CPU mask for PID 1
itself and the default for all forked off processes. itself and the default for all other processes.
* When systemd/PID 1 is reloaded (with systemctl daemon-reload or an * When systemd/PID 1 is reloaded (with systemctl daemon-reload or
equivalent tool) the SELinux database is now reloaded, ensuring that equivalent), the SELinux database is now reloaded, ensuring that
sockets and other file system objects are generated taking the new sockets and other file system objects are generated taking the new
database into account. database into account.
* The sd-event.h API now has native support for the new Linux "pidfd" * The sd-event.h API gained native support for the new Linux "pidfd"
concept. This permits watching processes using file descriptors concept. This permits watching processes using file descriptors
instead of PID numbers, which fixes a number of races and makes instead of PID numbers, which fixes a number of races and makes
process supervision more robust and more efficient. All of systemd's process supervision more robust and efficient. All of systemd's
components will now use pidfds if the kernel supports it for process components will now use pidfds if the kernel supports it for process
watching, with the exception of PID 1 itself, unfortunately. We hope watching, with the exception of PID 1 itself, unfortunately. We hope
to move PID 1 to exclusively using pidfds too eventually, but this to move PID 1 to exclusively using pidfds too eventually, but this
@ -122,13 +118,13 @@ CHANGES WITH 245 in spe:
* Closely related to this, the sd-event.h API gained two new calls * Closely related to this, the sd-event.h API gained two new calls
sd_event_source_send_child_signal() (for sending a signal to a sd_event_source_send_child_signal() (for sending a signal to a
watched process) and sd_event_source_get_child_process_own() (for watched process) and sd_event_source_get_child_process_own() (for
marking a process so that it is killed implicitly whenever the event marking a process so that it is killed automatically whenever the
source watching it is freed). event source watching it is freed).
* systemd-networkd gained support for configuring Token Bucket Filter * systemd-networkd gained support for configuring Token Bucket Filter
(TBF) parameters in its qdisc configuration support. Similar, support (TBF) parameters in its qdisc configuration support. Similarly,
for Stochastic Fairness Queuing (SFQ), Controlled-Delay Active support for Stochastic Fairness Queuing (SFQ), Controlled-Delay
Queue Management (CoDel), Fair Queueing (FQ) has been added. Active Queue Management (CoDel), and Fair Queue (FQ) has been added.
* systemd-networkd gained support for Intermediate Functional Block * systemd-networkd gained support for Intermediate Functional Block
(IFB) network devices. (IFB) network devices.
@ -136,40 +132,39 @@ CHANGES WITH 245 in spe:
* systemd-networkd gained support for configuring multi-path IP routes, * systemd-networkd gained support for configuring multi-path IP routes,
using the new MultiPathRoute= setting in the [Route] section. using the new MultiPathRoute= setting in the [Route] section.
* systemd-networkd's DHCPv4 support has been updated to support a new * systemd-networkd's DHCPv4 client has been updated to support a new
SendDecline= option. If enabled duplicate address detection is done SendDecline= option. If enabled, duplicate address detection is done
after a DHCP offer is received from a server. If a conflict is after a DHCP offer is received from the server. If a conflict is
detected the address is declined. The DHCPv4 support also gained detected, the address is declined. The DHCPv4 client also gained
support for a new RouteMTUBytes= setting that allows to configure the support for a new RouteMTUBytes= setting that allows to configure the
MTU size to be used for routes generated from DHCPv4 leases. MTU size to be used for routes generated from DHCPv4 leases.
* The PrefixRoute= setting in systemd-networkd's [Address] section of * The PrefixRoute= setting in systemd-networkd's [Address] section of
.network files has been deprecated, and replaced by AddPrefixRoute=, .network files has been deprecated, and replaced by AddPrefixRoute=,
with it's sense inverted. with its sense inverted.
* The Gateway= setting of [Route] sections of .network files gained * The Gateway= setting of [Route] sections of .network files gained
support for a special new value "_dhcp". If set, the configured support for a special new value "_dhcp". If set, the configured
static route uses the gateway host configured via DHCP. static route uses the gateway host configured via DHCP.
* A new User= setting has been implemented for the [RoutingPolicyRule] * New User= and SuppressPrefixLength= settings have been implemented
section of .network files for configuring source routing based on UID for the [RoutingPolicyRule] section of .network files to configure
ranges. source routing based on UID ranges and prefix length, respectively.
* sd-bus gained a new API call sd_bus_message_sensitive() for marking a * sd-bus gained a new API call sd_bus_message_sensitive() that marks a
D-Bus message object as "sensitive". Objects that are marked that way D-Bus message object as "sensitive". Those objects are erased from
are erased from memory when they are freed. This concept is intended memory when they are freed. This concept is intended to be used for
to be used for messages that contain security sensitive data that messages that contain security sensitive data. A new flag
should be erased after use. A new flag SD_BUS_VTABLE_SENSITIVE has SD_BUS_VTABLE_SENSITIVE has been introduced as well to mark methods
been introduced as well that allows marking method calls in sd-bus in sd-bus vtables, causing any incoming and outgoing messages of
vtables like this, so that this new message flag is implicitly set those methods to be implicitly marked as "sensitive".
for incoming and outgoing messages of specific methods.
* sd-bus gained a new API call sd_bus_message_dump() for dumping the * sd-bus gained a new API call sd_bus_message_dump() for dumping the
contents of a message (or parts thereof) onto standard output, for contents of a message (or parts thereof) to standard output for
debugging purposes. debugging purposes.
* systemd-sysusers gained support for creating users with primary * systemd-sysusers gained support for creating users with the primary
groups named differently than the user itself. group named differently than the user.
* systemd-resolved's DNS-over-TLS support gained SNI validation. * systemd-resolved's DNS-over-TLS support gained SNI validation.
@ -178,8 +173,8 @@ CHANGES WITH 245 in spe:
only ext4 and btrfs partitions. only ext4 and btrfs partitions.
* The support for /etc/crypttab gained a new x-initrd.attach option. If * The support for /etc/crypttab gained a new x-initrd.attach option. If
set the specified encrypted volume is unlocked in the initrd set, the specified encrypted volume is unlocked already in the
already. This concept corresponds to the x-initrd.mount option in initrd. This concept corresponds to the x-initrd.mount option in
/etc/fstab. /etc/fstab.
* systemd-cryptsetup gained native support for unlocking encrypted * systemd-cryptsetup gained native support for unlocking encrypted
@ -194,42 +189,41 @@ CHANGES WITH 245 in spe:
* The https://systemd.io/ web site has been relaunched, directly * The https://systemd.io/ web site has been relaunched, directly
populated with most of the documentation included in the systemd populated with most of the documentation included in the systemd
repository. In particular, systemd acquired a new logo, thanks to repository. systemd also acquired a new logo, thanks to Tobias
Tobias Bernard. Bernard.
* systemd-udevd gained support for managing "alternative" network * systemd-udevd gained support for managing "alternative" network
interface names, as supported by new Linux kernels. For the first interface names, as supported by new Linux kernels. For the first
time this permits assigning multiple (and longer!) names to a network time this permits assigning multiple (and longer!) names to a network
interface. systemd-udevd will now by default assign the names interface. systemd-udevd will now by default assign the names
generated via all supported naming schemes to each interface in generated via all supported naming schemes to each interface. This
parallel. This may be further tweaked with .link drop-in files, and may be further tweaked with .link files and the AlternativeName= and
the AlternativeName= and AlternativeNamesPolicy= settings. All other AlternativeNamesPolicy= settings. Other components of systemd have
components of systemd have been updated to support the new been updated to support the new alternative names wherever
alternative names too, wherever that is appropriate. For example, appropriate. For example, systemd-nspawn will now generate
systemd-nspawn will now generate alternative interface names for the alternative interface names for the host-facing side of container
host-facing side of container veth links based on the full container veth links based on the full container name without truncation.
name without truncation.
* systemd-nspawn interface naming logic has been updated in another way * systemd-nspawn interface naming logic has been updated in another way
too: if the main interface name (i.e. as opposed to new-style too: if the main interface name (i.e. as opposed to new-style
"alternative" names) is the truncated result of container name a "alternative" names) based on the container name is truncated, a
simple hashing scheme is used that ensures that multiple containers simple hashing scheme is used to give different interface names to
whose name all begin the same are likely resulting in different multiple containers whose names all begin with the same prefix. Since
interface names. Since this changes the primary interface names this changes the primary interface names pointing to containers if
pointing to containers if truncation happens the old scheme may still truncation happens, the old scheme may still be requested by
be requested by selecting a different naming scheme than the v245 selecting an older naming scheme, via the net.naming-scheme= kernel
one, via the net.naming-scheme= kernel command line option. command line option.
* PrivateUsers= in service files now works in services run by the * PrivateUsers= in service files now works in services run by the
systemd --user per-user instance of the service manager. systemd --user per-user instance of the service manager.
* A new per-service sandboxing option ProtectClock= has been added that * A new per-service sandboxing option ProtectClock= has been added that
locks down write access to the system clock. It takes away device locks down write access to the system clock. It takes away device
node access to /dev/rtc as well as the system calls that allow to set node access to /dev/rtc as well as the system calls that set the
the system clock. It also removes the CAP_SYS_TIME and CAP_WAKE_ALARM system clock and the CAP_SYS_TIME and CAP_WAKE_ALARM capabilities.
capabilities. Note that this option does not affect access to Note that this option does not affect access to auxiliary services
auxiliary services that allow changing the clock, for example access that allow changing the clock, for example access to
to systemd-timedated. systemd-timedated.
* The systemd-id128 tool gained a new "show" verb for listing or * The systemd-id128 tool gained a new "show" verb for listing or
resolving a number of well-known UUIDs/128bit IDs, currently mostly resolving a number of well-known UUIDs/128bit IDs, currently mostly
@ -252,20 +246,54 @@ CHANGES WITH 245 in spe:
* networkctl gained support for showing per-interface logs in its * networkctl gained support for showing per-interface logs in its
"status" output. "status" output.
* systemd-networkd-wait-online gain support for specifying the maximum
operational state to wait for, and to wait for interfaces to
disappear.
* The [Match] section of .link and .network files now supports a new * The [Match] section of .link and .network files now supports a new
option PermanentMACAddress= which may be used to check against the option PermanentMACAddress= which may be used to check against the
permanent MAC address of a network device even if a randomized MAC permanent MAC address of a network device even if a randomized MAC
address is used. address is used.
* systemd-logind will now validate access to the operation for changing * The [TrafficControlQueueingDiscipline] section in .network files has
virtual terminals via a PolicyKit action. By default only users with been renamed to [NetworkEmulator] with the "NetworkEmulator" prefix
at least one session on a local VT will get access to the method call. dropped from the individual setting names.
* When systemd sets up PAM sessions that invoked service processes shall * Any .link and .network files that have an empty [Match] section (this
run in, the pam_setcred() API is now invoked, thus permitting PAM also includes empty and commented-out files) will now be
modules to set additional credentials for the processes. rejected. systemd-udev and systemd-networkd started warning about
such files in version 243.
* systemd-logind will now validate access to the operation of changing
the virtual terminal via a PolicyKit action. By default, only users
with at least one session on a local VT are granted permission.
* When systemd sets up PAM sessions that invoked service processes
shall run in, the pam_setcred() API is now invoked, thus permitting
PAM modules to set additional credentials for the processes.
Contributions from: AJ Bagwell, Andreas Rammhold, Anita Zhang, Ansgar
Burchardt, Antonio Russo, Arian van Putten, Ashley Davis, Bart Willems,
Bastien Nocera, Benjamin Dahlhoff, Charles (Chas) Williams, cheese1,
Chris Down, Christian Ehrhardt, Christian Göttsche, cvoinf, Daan De
Meyer, Daniele Medri, Daniel Rusek, Daniel Shahaf, dann frazier, Dan
Streetman, Dariusz Gadomski, David Michael, Dimitri John Ledkov,
Emmanuel Bourg, Evgeny Vereshchagin, ezst036, Felipe Sateler, Filipe
Brandenburger, Florian Klink, Franck Bui, Fran Dieguez, Frantisek
Sumsal, Greg "GothAck" Miell, Guilhem Lettron, Hans de Goede, HATAYAMA
Daisuke, Iain Lane, Jan Alexander Steffens (heftig), Jérémy Rosen, Jin
Park, Jun'ichi Nomura, Kai Krakow, Kevin Kuehler, Lennart Poettering,
Leonid Bloch, Leonid Evdokimov, lothrond, Luca Boccassi, Michael Biebl,
Mike Auty, Mike Gilbert, mtron, nabijaczleweli, Naïm Favier, Paul
Davey, Piotr Drąg, Rafa Couto, Raphael, rhn, Robert Scheck, Sascha
Dewald, Shengjing Zhu, Slava Kardakov, Spencer Michaels, splantefeve,
Stanislav Angelovič, Susant Sahani, Thomas Haller, Thomas Schmitt, Timo
Schlüßler, Timo Wilken, Tobias Bernard, Tobias Klauser, Tobias
Stoeckmann, Topi Miettinen, WataruMatsuoka, Wieland Hoffmann, Wilhelm
Schuster, xduugu, Yong Cong Sin, Yu Watanabe, Zach Smith, Zbigniew
Jędrzejewski-Szmek, Zeyu DONG
Warsaw, 2020-02-05
CHANGES WITH 244: CHANGES WITH 244:
@ -7181,10 +7209,9 @@ CHANGES WITH 213:
* A new fsck.repair= kernel option has been added to control * A new fsck.repair= kernel option has been added to control
how fsck shall deal with unclean file systems at boot. how fsck shall deal with unclean file systems at boot.
* The (.ini) configuration file parser will now silently * The (.ini) configuration file parser will now silently ignore
ignore sections whose name begins with "X-". This may be sections whose names begin with "X-". This may be used to maintain
used to maintain application-specific extension sections in unit application-specific extension sections in unit files.
files.
* machined gained a new API to query the IP addresses of * machined gained a new API to query the IP addresses of
registered containers. "machinectl status" has been updated registered containers. "machinectl status" has been updated

2
TODO
View File

@ -328,7 +328,7 @@ Features:
* the a-posteriori stopping of units bound to units that disappeared logic * the a-posteriori stopping of units bound to units that disappeared logic
should be reworked: there should be a queue of units, and we should only should be reworked: there should be a queue of units, and we should only
enqeue stop jobs from a defer event that processes queue instead of enqueue stop jobs from a defer event that processes queue instead of
right-away when we find a unit that is bound to one that doesn't exist right-away when we find a unit that is bound to one that doesn't exist
anymore. (similar to how the stop-unneeded queue has been reworked the same anymore. (similar to how the stop-unneeded queue has been reworked the same
way) way)

View File

@ -69,6 +69,12 @@
<para>The operational status is one of the following: <para>The operational status is one of the following:
<variablelist> <variablelist>
<varlistentry>
<term>missing</term>
<listitem>
<para>the device is missing</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>off</term> <term>off</term>
<listitem> <listitem>

View File

@ -195,6 +195,7 @@ manpages = [
'sd_bus_open_user_with_description', 'sd_bus_open_user_with_description',
'sd_bus_open_with_description'], 'sd_bus_open_with_description'],
''], ''],
['sd_bus_enqueue_for_read', '3', [], ''],
['sd_bus_error', ['sd_bus_error',
'3', '3',
['SD_BUS_ERROR_MAKE_CONST', ['SD_BUS_ERROR_MAKE_CONST',

View File

@ -0,0 +1,88 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="sd_bus_enqueue_for_read"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_enqueue_for_read</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sd_bus_enqueue_for_read</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_bus_enqueue_for_read</refname>
<refpurpose>Re-enqueue a bus message on a bus connection, for reading.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_bus_enqueue_for_read</function></funcdef>
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
<paramdef>sd_bus_message *<parameter>message</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_bus_enqueue_for_read()</function> may be used to re-enqueue an incoming bus message on
the local read queue, so that it is processed and dispatched locally again, similar to how an incoming
message from the peer is processed. Takes a bus connection object and the message to enqueue. A reference
is taken of the message and the caller's reference thus remains in possession of the caller. The message
is enqueued at the end of the queue, thus will be dispatched after all other already queued messages are
dispatched.</para>
<para>This call is primarily useful for dealing with incoming method calls that may be processed only
after an additional asynchronous operation completes. One example are PolicyKit authorization requests
that are determined to be necessary to authorize a newly incoming method call: when the PolicyKit response
is received the original method call may be re-enqueued to process it again, this time with the
authorization result known.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, this function return 0 or a positive integer. On failure, it returns a negative errno-style
error code.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<varlistentry>
<term><constant>-ECHILD</constant></term>
<listitem><para>The bus connection has been created in a different process.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
</para>
</refsect1>
</refentry>

View File

@ -47,16 +47,16 @@
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><option>-i</option> <replaceable>INTERFACE</replaceable><optional>:<replaceable>OPERSTATE</replaceable></optional></term> <term><option>-i</option> <replaceable>INTERFACE</replaceable><optional>:<replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></optional></term>
<term><option>--interface=</option><replaceable>INTERFACE</replaceable><optional>:<replaceable>OPERSTATE</replaceable></optional></term> <term><option>--interface=</option><replaceable>INTERFACE</replaceable><optional>:<replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></optional></term>
<listitem><para>Network interface to wait for before deciding if the system is online. This <listitem><para>Network interface to wait for before deciding if the system is online. This
is useful when a system has several interfaces which will be configured, but a particular is useful when a system has several interfaces which will be configured, but a particular
one is necessary to access some network resources. When used, all other interfaces are ignored. one is necessary to access some network resources. When used, all other interfaces are ignored.
This option may be used more than once to wait for multiple network interfaces. When this This option may be used more than once to wait for multiple network interfaces. When this
option is specified multiple times, then <command>systemd-networkd-wait-online</command> waits option is specified multiple times, then <command>systemd-networkd-wait-online</command> waits
for all specified interfaces to be online. Optionally, required minimum operational state can be for all specified interfaces to be online. Optionally, required minimum and maximum operational
specified after a colon <literal>:</literal>. Please see states can be specified after a colon <literal>:</literal>. Please see
<citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for possible operational states. If the operational state is not specified here, then for possible operational states. If the operational state is not specified here, then
the value from <varname>RequiredForOnline=</varname> in the corresponding the value from <varname>RequiredForOnline=</varname> in the corresponding
@ -74,11 +74,11 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>-o</option> <replaceable>OPERSTATE</replaceable></term> <term><option>-o</option> <replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></term>
<term><option>--operational-state=</option><replaceable>OPERSTATE</replaceable></term> <term><option>--operational-state=</option><replaceable>MIN_OPERSTATE</replaceable><optional>:<replaceable>MAX_OPERSTATE</replaceable></optional></term>
<listitem><para>Takes an operational state. Please see <listitem><para>Takes a minimum operational state and an optional maximum operational state.
<citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> Please see <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for possible operational states. If set, the specified value overrides for possible operational states. If set, the specified value overrides
<varname>RequiredForOnline=</varname> settings in <filename>.network</filename> files. <varname>RequiredForOnline=</varname> settings in <filename>.network</filename> files.
But this does not override operational states specified in <option>--interface=</option> option. But this does not override operational states specified in <option>--interface=</option> option.

View File

@ -206,13 +206,14 @@
<varlistentry> <varlistentry>
<term><varname>RequiredForOnline=</varname></term> <term><varname>RequiredForOnline=</varname></term>
<listitem> <listitem>
<para>Takes a boolean or operational state. Please see <para>Takes a boolean or a minimum operational state and an optional maximum operational state.
<citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> Please see <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for possible operational states. When <literal>yes</literal>, the network is deemed required when for possible operational states. When <literal>yes</literal>, the network is deemed required when
determining whether the system is online when running determining whether the system is online when running
<command>systemd-networkd-wait-online</command>. When <literal>no</literal>, the network is ignored <command>systemd-networkd-wait-online</command>. When <literal>no</literal>, the network is ignored
when checking for online state. When an operational state is set, <literal>yes</literal> is implied, when checking for online state. When a minimum operational state and an optional maximum operational
and this controls the operational state required for the network interface to be considered online. state are set, <literal>yes</literal> is implied, and this controls the minimum and maximum
operational state required for the network interface to be considered online.
Defaults to <literal>yes</literal>.</para> Defaults to <literal>yes</literal>.</para>
<para>The network will be brought up normally in all cases, but in <para>The network will be brought up normally in all cases, but in

View File

@ -848,20 +848,19 @@
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><filename>blockdev@.target</filename></term> <term><filename>blockdev@.target</filename></term>
<listitem><para>This template unit may be used to order mount units and other consumers of block <listitem><para>This template unit is used to order mount units and other consumers of block
devices against services that synthesize these block devices. This is intended to be used to order devices after services that synthesize these block devices. In particular, this is intended to be
storage services (such as used with storage services (such as
<citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>) <citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
that allocate and manage a virtual block device against mount units and other consumers of that allocate and manage a virtual block device. Storage services are ordered before an instance of
it. Specifically, the storage services are supposed to be orderd before an instance of <filename>blockdev@.target</filename>, and the consumer units after it. The ordering is
<filename>blockdev@.target</filename>, and the mount unit (or other consuming unit, such as a swap particularly relevant during shutdown, as it ensures that the mount is deactivated first and the
unit) after it. The ordering is particular relevant during shutdown, as it ensures that the mount service backing the mount later. The <filename>blockdev@.target</filename> instance should be
is deactivated first and the service backing the mount only deactivated after that completed. The pulled in via a <option>Wants=</option> dependency of the storage daemon and thus generally not be
<filename>blockdev@.target</filename> instance should be pulled in via a <option>Wants=</option> part of any transaction unless a storage daemon is used. The instance name for instances of this
dependency of the storage daemon and thus generally not be part of any transaction unless a storage template unit must be a properly escaped block device node path, e.g.
daemon is used. The instance name for instances of this template unit is supposed to be the <filename>blockdev@dev-mapper-foobar.target</filename> for the storage device
properly escaped bock device node path, e.g. <filename>blockdev@dev-mapper-foobar.target</filename> <filename>/dev/mapper/foobar</filename>.</para></listitem>
for a storage device <filename>/dev/mapper/foobar</filename>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><filename>cryptsetup-pre.target</filename></term> <term><filename>cryptsetup-pre.target</filename></term>

View File

@ -25,6 +25,16 @@
<para><filename>/etc/sysusers.d/*.conf</filename></para> <para><filename>/etc/sysusers.d/*.conf</filename></para>
<para><filename>/run/sysusers.d/*.conf</filename></para> <para><filename>/run/sysusers.d/*.conf</filename></para>
<para><filename>/usr/lib/sysusers.d/*.conf</filename></para> <para><filename>/usr/lib/sysusers.d/*.conf</filename></para>
<programlisting>
#Type Name ID GECOS Home directory Shell
u user_name uid "User Description" /path/to/shell
u user_name uid:gid - -
u user_name /file/owned/by/user - -
g group_name gid "Group Description"
g group_name /file/owned/by/group -
m user_name group_name
r - lowest-highest</programlisting>
</refsynopsisdiv> </refsynopsisdiv>
<refsect1> <refsect1>
@ -81,11 +91,13 @@
<programlisting>#Type Name ID GECOS Home directory Shell <programlisting>#Type Name ID GECOS Home directory Shell
u httpd 404 "HTTP User" u httpd 404 "HTTP User"
u authd /usr/bin/authd "Authorization user" u _authd /usr/bin/authd "Authorization user"
u postgres - "Postgresql Database" /var/lib/pgsql /usr/libexec/postgresdb u postgres - "Postgresql Database" /var/lib/pgsql /usr/libexec/postgresdb
g input - - g input - -
m authd input m _authd input
u root 0 "Superuser" /root /bin/zsh</programlisting> u root 0 "Superuser" /root /bin/zsh
r - 500-900
</programlisting>
<para>Empty lines and lines beginning with the <literal>#</literal> character are ignored, and may be used for <para>Empty lines and lines beginning with the <literal>#</literal> character are ignored, and may be used for
commenting.</para> commenting.</para>
@ -109,7 +121,7 @@ u root 0 "Superuser" /root /bin/zsh</pro
<term><varname>g</varname></term> <term><varname>g</varname></term>
<listitem><para>Create a system group of the specified name <listitem><para>Create a system group of the specified name
should it not exist yet. Note that <varname>u</varname> should it not exist yet. Note that <varname>u</varname>
implicitly create a matching group. The group will be implicitly creates a matching group. The group will be
created with no password set.</para></listitem> created with no password set.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+ # SPDX-License-Identifier: LGPL-2.1+
project('systemd', 'c', project('systemd', 'c',
version : '244', version : '245',
license : 'LGPLv2+', license : 'LGPLv2+',
default_options: [ default_options: [
'c_std=gnu99', 'c_std=gnu99',
@ -13,8 +13,8 @@ project('systemd', 'c',
meson_version : '>= 0.46', meson_version : '>= 0.46',
) )
libsystemd_version = '0.27.1' libsystemd_version = '0.28.0'
libudev_version = '1.6.16' libudev_version = '1.6.17'
# We need the same data in two different formats, ugh! # We need the same data in two different formats, ugh!
# Also, for hysterical reasons, we use different variable # Also, for hysterical reasons, we use different variable

View File

@ -685,6 +685,7 @@ global:
LIBSYSTEMD_245 { LIBSYSTEMD_245 {
global: global:
sd_bus_enqueue_for_read;
sd_bus_message_dump; sd_bus_message_dump;
sd_bus_message_sensitive; sd_bus_message_sensitive;
sd_event_add_child_pidfd; sd_event_add_child_pidfd;

View File

@ -4207,3 +4207,27 @@ _public_ int sd_bus_get_close_on_exit(sd_bus *bus) {
return bus->close_on_exit; return bus->close_on_exit;
} }
_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
int r;
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(m, -EINVAL);
assert_return(m->sealed, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
/* Re-enqueue a message for reading. This is primarily useful for PolicyKit-style authentication,
* where we accept a message, then determine we need to interactively authenticate the user, and then
* we want to process the message again. */
r = bus_rqueue_make_room(bus);
if (r < 0)
return r;
bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus);
return 0;
}

View File

@ -26,6 +26,7 @@ bool network_is_online(void) {
} }
static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
[LINK_OPERSTATE_MISSING] = "missing",
[LINK_OPERSTATE_OFF] = "off", [LINK_OPERSTATE_OFF] = "off",
[LINK_OPERSTATE_NO_CARRIER] = "no-carrier", [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
[LINK_OPERSTATE_DORMANT] = "dormant", [LINK_OPERSTATE_DORMANT] = "dormant",
@ -56,3 +57,49 @@ static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = {
}; };
DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState); DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState);
int parse_operational_state_range(const char *str, LinkOperationalStateRange *out) {
LinkOperationalStateRange range = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
_cleanup_free_ const char *min = NULL;
const char *p;
assert(str);
assert(out);
p = strchr(str, ':');
if (p) {
min = strndup(str, p - str);
if (!isempty(p + 1)) {
range.max = link_operstate_from_string(p + 1);
if (range.max < 0)
return -EINVAL;
}
} else
min = strdup(str);
if (!min)
return -ENOMEM;
if (!isempty(min)) {
range.min = link_operstate_from_string(min);
if (range.min < 0)
return -EINVAL;
}
/* Fail on empty strings. */
if (range.min == _LINK_OPERSTATE_INVALID && range.max == _LINK_OPERSTATE_INVALID)
return -EINVAL;
if (range.min == _LINK_OPERSTATE_INVALID)
range.min = LINK_OPERSTATE_MISSING;
if (range.max == _LINK_OPERSTATE_INVALID)
range.max = LINK_OPERSTATE_ROUTABLE;
if (range.min > range.max)
return -EINVAL;
*out = range;
return 0;
}

View File

@ -8,6 +8,7 @@
bool network_is_online(void); bool network_is_online(void);
typedef enum LinkOperationalState { typedef enum LinkOperationalState {
LINK_OPERSTATE_MISSING,
LINK_OPERSTATE_OFF, LINK_OPERSTATE_OFF,
LINK_OPERSTATE_NO_CARRIER, LINK_OPERSTATE_NO_CARRIER,
LINK_OPERSTATE_DORMANT, LINK_OPERSTATE_DORMANT,
@ -47,3 +48,13 @@ LinkCarrierState link_carrier_state_from_string(const char *s) _pure_;
const char* link_address_state_to_string(LinkAddressState s) _const_; const char* link_address_state_to_string(LinkAddressState s) _const_;
LinkAddressState link_address_state_from_string(const char *s) _pure_; LinkAddressState link_address_state_from_string(const char *s) _pure_;
typedef struct LinkOperationalStateRange {
LinkOperationalState min;
LinkOperationalState max;
} LinkOperationalStateRange;
#define LINK_OPERSTATE_RANGE_DEFAULT (LinkOperationalStateRange) { LINK_OPERSTATE_DEGRADED, \
LINK_OPERSTATE_ROUTABLE }
int parse_operational_state_range(const char *str, LinkOperationalStateRange *out);

View File

@ -3957,8 +3957,14 @@ int link_save(Link *link) {
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n", fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
yes_no(link->network->required_for_online)); yes_no(link->network->required_for_online));
fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s\n", fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s",
strempty(link_operstate_to_string(link->network->required_operstate_for_online))); strempty(link_operstate_to_string(link->network->required_operstate_for_online.min)));
if (link->network->required_operstate_for_online.max != LINK_OPERSTATE_RANGE_DEFAULT.max)
fprintf(f, ":%s",
strempty(link_operstate_to_string(link->network->required_operstate_for_online.max)));
fprintf(f, "\n");
if (link->dhcp6_client) { if (link->dhcp6_client) {
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);

View File

@ -375,7 +375,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.n_ref = 1, .n_ref = 1,
.required_for_online = true, .required_for_online = true,
.required_operstate_for_online = LINK_OPERSTATE_DEGRADED, .required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT,
.dhcp = ADDRESS_FAMILY_NO, .dhcp = ADDRESS_FAMILY_NO,
.dhcp_critical = -1, .dhcp_critical = -1,
.dhcp_use_ntp = true, .dhcp_use_ntp = true,
@ -1306,18 +1306,18 @@ int config_parse_required_for_online(
void *userdata) { void *userdata) {
Network *network = data; Network *network = data;
LinkOperationalState s; LinkOperationalStateRange range;
bool required = true; bool required = true;
int r; int r;
if (isempty(rvalue)) { if (isempty(rvalue)) {
network->required_for_online = true; network->required_for_online = true;
network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED; network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
return 0; return 0;
} }
s = link_operstate_from_string(rvalue); r = parse_operational_state_range(rvalue, &range);
if (s < 0) { if (r < 0) {
r = parse_boolean(rvalue); r = parse_boolean(rvalue);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, r,
@ -1327,11 +1327,11 @@ int config_parse_required_for_online(
} }
required = r; required = r;
s = LINK_OPERSTATE_DEGRADED; range = LINK_OPERSTATE_RANGE_DEFAULT;
} }
network->required_for_online = required; network->required_for_online = required;
network->required_operstate_for_online = s; network->required_operstate_for_online = range;
return 0; return 0;
} }

View File

@ -237,7 +237,7 @@ struct Network {
bool iaid_set; bool iaid_set;
bool required_for_online; /* Is this network required to be considered online? */ bool required_for_online; /* Is this network required to be considered online? */
LinkOperationalState required_operstate_for_online; LinkOperationalStateRange required_operstate_for_online;
LLDPMode lldp_mode; /* LLDP reception */ LLDPMode lldp_mode; /* LLDP reception */
LLDPEmit lldp_emit; /* LLDP transmission */ LLDPEmit lldp_emit; /* LLDP transmission */

View File

@ -36,7 +36,7 @@ int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) {
.manager = m, .manager = m,
.ifname = TAKE_PTR(n), .ifname = TAKE_PTR(n),
.ifindex = ifindex, .ifindex = ifindex,
.required_operstate = LINK_OPERSTATE_DEGRADED, .required_operstate = LINK_OPERSTATE_RANGE_DEFAULT,
}; };
r = hashmap_put(m->links_by_name, l->ifname, l); r = hashmap_put(m->links_by_name, l->ifname, l);
@ -105,7 +105,6 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
int link_update_monitor(Link *l) { int link_update_monitor(Link *l) {
_cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL; _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL;
LinkOperationalState s;
int r, ret = 0; int r, ret = 0;
assert(l); assert(l);
@ -121,19 +120,21 @@ int link_update_monitor(Link *l) {
r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate); r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate);
if (r < 0) if (r < 0)
ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m"); ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m");
else if (isempty(required_operstate))
l->required_operstate = LINK_OPERSTATE_RANGE_DEFAULT;
else { else {
s = link_operstate_from_string(required_operstate); r = parse_operational_state_range(required_operstate, &l->required_operstate);
if (s < 0) if (r < 0)
ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),
"Failed to parse required operational state, ignoring: %m"); "Failed to parse required operational state, ignoring: %m");
else
l->required_operstate = s;
} }
r = sd_network_link_get_operational_state(l->ifindex, &operstate); r = sd_network_link_get_operational_state(l->ifindex, &operstate);
if (r < 0) if (r < 0)
ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m"); ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m");
else { else {
LinkOperationalState s;
s = link_operstate_from_string(operstate); s = link_operstate_from_string(operstate);
if (s < 0) if (s < 0)
ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL),

View File

@ -17,7 +17,7 @@ struct Link {
unsigned flags; unsigned flags;
bool required_for_online; bool required_for_online;
LinkOperationalState required_operstate; LinkOperationalStateRange required_operstate;
LinkOperationalState operational_state; LinkOperationalState operational_state;
char *state; char *state;
}; };

View File

@ -32,7 +32,7 @@ static bool manager_ignore_link(Manager *m, Link *link) {
return strv_fnmatch(m->ignore, link->ifname); return strv_fnmatch(m->ignore, link->ifname);
} }
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) { static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange s) {
/* This returns the following: /* This returns the following:
* -EAGAIN: not processed by udev or networkd * -EAGAIN: not processed by udev or networkd
* 0: operstate is not enough * 0: operstate is not enough
@ -46,13 +46,18 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) {
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN), return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN),
"link is being processed by networkd"); "link is being processed by networkd");
if (s < 0) if (s.min < 0)
s = m->required_operstate >= 0 ? m->required_operstate : l->required_operstate; s.min = m->required_operstate.min >= 0 ? m->required_operstate.min
: l->required_operstate.min;
if (l->operational_state < s) { if (s.max < 0)
log_link_debug(l, "Operational state '%s' is below '%s'", s.max = m->required_operstate.max >= 0 ? m->required_operstate.max
: l->required_operstate.max;
if (l->operational_state < s.min || l->operational_state > s.max) {
log_link_debug(l, "Operational state '%s' is not in range ['%s':'%s']",
link_operstate_to_string(l->operational_state), link_operstate_to_string(l->operational_state),
link_operstate_to_string(s)); link_operstate_to_string(s.min), link_operstate_to_string(s.max));
return 0; return 0;
} }
@ -70,9 +75,14 @@ bool manager_configured(Manager *m) {
if (!hashmap_isempty(m->interfaces)) { if (!hashmap_isempty(m->interfaces)) {
/* wait for all the links given on the command line to appear */ /* wait for all the links given on the command line to appear */
HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) { HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) {
LinkOperationalState s = PTR_TO_INT(p); LinkOperationalStateRange *range = p;
l = hashmap_get(m->links_by_name, ifname); l = hashmap_get(m->links_by_name, ifname);
if (!l && range->min == LINK_OPERSTATE_MISSING) {
one_ready = true;
continue;
}
if (!l) { if (!l) {
log_debug("still waiting for %s", ifname); log_debug("still waiting for %s", ifname);
if (!m->any) if (!m->any)
@ -80,7 +90,7 @@ bool manager_configured(Manager *m) {
continue; continue;
} }
if (manager_link_is_online(m, l, s) <= 0) { if (manager_link_is_online(m, l, *range) <= 0) {
if (!m->any) if (!m->any)
return false; return false;
continue; continue;
@ -102,7 +112,9 @@ bool manager_configured(Manager *m) {
continue; continue;
} }
r = manager_link_is_online(m, l, _LINK_OPERSTATE_INVALID); r = manager_link_is_online(m, l,
(LinkOperationalStateRange) { _LINK_OPERSTATE_INVALID,
_LINK_OPERSTATE_INVALID });
if (r < 0 && !m->any) if (r < 0 && !m->any)
return false; return false;
if (r > 0) if (r > 0)
@ -289,7 +301,7 @@ static int manager_network_monitor_listen(Manager *m) {
} }
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore, int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
LinkOperationalState required_operstate, LinkOperationalStateRange required_operstate,
bool any, usec_t timeout) { bool any, usec_t timeout) {
_cleanup_(manager_freep) Manager *m = NULL; _cleanup_(manager_freep) Manager *m = NULL;
int r; int r;

View File

@ -20,7 +20,7 @@ struct Manager {
Hashmap *interfaces; Hashmap *interfaces;
char **ignore; char **ignore;
LinkOperationalState required_operstate; LinkOperationalStateRange required_operstate;
bool any; bool any;
sd_netlink *rtnl; sd_netlink *rtnl;
@ -34,7 +34,7 @@ struct Manager {
void manager_free(Manager *m); void manager_free(Manager *m);
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore, int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
LinkOperationalState required_operstate, LinkOperationalStateRange required_operstate,
bool any, usec_t timeout); bool any, usec_t timeout);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);

View File

@ -18,10 +18,10 @@ static bool arg_quiet = false;
static usec_t arg_timeout = 120 * USEC_PER_SEC; static usec_t arg_timeout = 120 * USEC_PER_SEC;
static Hashmap *arg_interfaces = NULL; static Hashmap *arg_interfaces = NULL;
static char **arg_ignore = NULL; static char **arg_ignore = NULL;
static LinkOperationalState arg_required_operstate = _LINK_OPERSTATE_INVALID; static LinkOperationalStateRange arg_required_operstate = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
static bool arg_any = false; static bool arg_any = false;
STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_keyp); STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_freep);
STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep);
static int help(void) { static int help(void) {
@ -37,10 +37,10 @@ static int help(void) {
" -h --help Show this help\n" " -h --help Show this help\n"
" --version Print version string\n" " --version Print version string\n"
" -q --quiet Do not show status information\n" " -q --quiet Do not show status information\n"
" -i --interface=INTERFACE[:OPERSTATE]\n" " -i --interface=INTERFACE[:MIN_OPERSTATE[:MAX_OPERSTATE]]\n"
" Block until at least these interfaces have appeared\n" " Block until at least these interfaces have appeared\n"
" --ignore=INTERFACE Don't take these interfaces into account\n" " --ignore=INTERFACE Don't take these interfaces into account\n"
" -o --operational-state=OPERSTATE\n" " -o --operational-state=MIN_OPERSTATE[:MAX_OPERSTATE]\n"
" Required operational state\n" " Required operational state\n"
" --any Wait until at least one of the interfaces is online\n" " --any Wait until at least one of the interfaces is online\n"
" --timeout=SECS Maximum time to wait for network connectivity\n" " --timeout=SECS Maximum time to wait for network connectivity\n"
@ -52,28 +52,28 @@ static int help(void) {
return 0; return 0;
} }
static int parse_interface_with_operstate(const char *str) { static int parse_interface_with_operstate_range(const char *str) {
_cleanup_free_ char *ifname = NULL; _cleanup_free_ char *ifname = NULL;
LinkOperationalState s; _cleanup_free_ LinkOperationalStateRange *range;
const char *p; const char *p;
int r; int r;
assert(str); assert(str);
range = new(LinkOperationalStateRange, 1);
if (!range)
return log_oom();
p = strchr(str, ':'); p = strchr(str, ':');
if (p) { if (p) {
if (isempty(p + 1)) r = parse_operational_state_range(p + 1, range);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), if (r < 0)
"Operational state is empty."); log_error_errno(r, "Invalid operational state range '%s'", p + 1);
s = link_operstate_from_string(p + 1);
if (s < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid operational state '%s'", p + 1);
ifname = strndup(optarg, p - optarg); ifname = strndup(optarg, p - optarg);
} else { } else {
s = _LINK_OPERSTATE_INVALID; range->min = _LINK_OPERSTATE_INVALID;
range->max = _LINK_OPERSTATE_INVALID;
ifname = strdup(str); ifname = strdup(str);
} }
if (!ifname) if (!ifname)
@ -87,7 +87,7 @@ static int parse_interface_with_operstate(const char *str) {
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
r = hashmap_put(arg_interfaces, ifname, INT_TO_PTR(s)); r = hashmap_put(arg_interfaces, ifname, TAKE_PTR(range));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to store interface name: %m"); return log_error_errno(r, "Failed to store interface name: %m");
if (r == 0) if (r == 0)
@ -140,7 +140,7 @@ static int parse_argv(int argc, char *argv[]) {
return version(); return version();
case 'i': case 'i':
r = parse_interface_with_operstate(optarg); r = parse_interface_with_operstate_range(optarg);
if (r < 0) if (r < 0)
return r; return r;
break; break;
@ -152,14 +152,14 @@ static int parse_argv(int argc, char *argv[]) {
break; break;
case 'o': { case 'o': {
LinkOperationalState s; LinkOperationalStateRange range;
s = link_operstate_from_string(optarg); r = parse_operational_state_range(optarg, &range);
if (s < 0) if (r < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(r, "Invalid operational state range '%s'", optarg);
"Invalid operational state '%s'", optarg);
arg_required_operstate = range;
arg_required_operstate = s;
break; break;
} }
case ARG_ANY: case ARG_ANY:

View File

@ -30,6 +30,34 @@ static int check_good_user(sd_bus_message *m, uid_t good_user) {
return sender_uid == good_user; return sender_uid == good_user;
} }
#if ENABLE_POLKIT
static int bus_message_append_strv_key_value(
sd_bus_message *m,
const char **l) {
const char **k, **v;
int r;
assert(m);
r = sd_bus_message_open_container(m, 'a', "{ss}");
if (r < 0)
return r;
STRV_FOREACH_PAIR(k, v, l) {
r = sd_bus_message_append(m, "{ss}", *k, *v);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return r;
}
#endif
int bus_test_polkit( int bus_test_polkit(
sd_bus_message *call, sd_bus_message *call,
int capability, int capability,
@ -37,7 +65,7 @@ int bus_test_polkit(
const char **details, const char **details,
uid_t good_user, uid_t good_user,
bool *_challenge, bool *_challenge,
sd_bus_error *e) { sd_bus_error *ret_error) {
int r; int r;
@ -60,7 +88,7 @@ int bus_test_polkit(
_cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int authorized = false, challenge = false; int authorized = false, challenge = false;
const char *sender, **k, **v; const char *sender;
sender = sd_bus_message_get_sender(call); sender = sd_bus_message_get_sender(call);
if (!sender) if (!sender)
@ -84,17 +112,7 @@ int bus_test_polkit(
if (r < 0) if (r < 0)
return r; return r;
r = sd_bus_message_open_container(request, 'a', "{ss}"); r = bus_message_append_strv_key_value(request, details);
if (r < 0)
return r;
STRV_FOREACH_PAIR(k, v, details) {
r = sd_bus_message_append(request, "{ss}", *k, *v);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(request);
if (r < 0) if (r < 0)
return r; return r;
@ -102,11 +120,11 @@ int bus_test_polkit(
if (r < 0) if (r < 0)
return r; return r;
r = sd_bus_call(call->bus, request, 0, e, &reply); r = sd_bus_call(call->bus, request, 0, ret_error, &reply);
if (r < 0) { if (r < 0) {
/* Treat no PK available as access denied */ /* Treat no PK available as access denied */
if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) { if (sd_bus_error_has_name(ret_error, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
sd_bus_error_free(e); sd_bus_error_free(ret_error);
return -EACCES; return -EACCES;
} }
@ -137,15 +155,17 @@ int bus_test_polkit(
#if ENABLE_POLKIT #if ENABLE_POLKIT
typedef struct AsyncPolkitQuery { typedef struct AsyncPolkitQuery {
char *action;
char **details;
sd_bus_message *request, *reply; sd_bus_message *request, *reply;
sd_bus_message_handler_t callback;
void *userdata;
sd_bus_slot *slot; sd_bus_slot *slot;
Hashmap *registry; Hashmap *registry;
sd_event_source *defer_event_source;
} AsyncPolkitQuery; } AsyncPolkitQuery;
static void async_polkit_query_free(AsyncPolkitQuery *q) { static void async_polkit_query_free(AsyncPolkitQuery *q) {
if (!q) if (!q)
return; return;
@ -157,32 +177,72 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) {
sd_bus_message_unref(q->request); sd_bus_message_unref(q->request);
sd_bus_message_unref(q->reply); sd_bus_message_unref(q->reply);
free(q->action);
strv_free(q->details);
sd_event_source_disable_unref(q->defer_event_source);
free(q); free(q);
} }
static int async_polkit_defer(sd_event_source *s, void *userdata) {
AsyncPolkitQuery *q = userdata;
assert(s);
/* This is called as idle event source after we processed the async polkit reply, hopefully after the
* method call we re-enqueued has been properly processed. */
async_polkit_query_free(q);
return 0;
}
static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
AsyncPolkitQuery *q = userdata; AsyncPolkitQuery *q = userdata;
int r; int r;
assert(reply); assert(reply);
assert(q); assert(q);
assert(q->slot);
q->slot = sd_bus_slot_unref(q->slot); q->slot = sd_bus_slot_unref(q->slot);
assert(!q->reply);
q->reply = sd_bus_message_ref(reply); q->reply = sd_bus_message_ref(reply);
/* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the
* whole message processing again, and thus re-validating and re-retrieving the "userdata" field
* again.
*
* We install an idle event loop event to clean-up the PolicyKit request data when we are idle again,
* i.e. after the second time the message is processed is complete. */
assert(!q->defer_event_source);
r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q);
if (r < 0)
goto fail;
r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE);
if (r < 0)
goto fail;
r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT);
if (r < 0)
goto fail;
r = sd_bus_message_rewind(q->request, true); r = sd_bus_message_rewind(q->request, true);
if (r < 0) { if (r < 0)
r = sd_bus_reply_method_errno(q->request, r, NULL); goto fail;
goto finish;
}
r = q->callback(q->request, q->userdata, &error_buffer); r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request);
r = bus_maybe_reply_error(q->request, r, &error_buffer); if (r < 0)
goto fail;
finish: return 1;
fail:
log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m");
(void) sd_bus_reply_method_errno(q->request, r, NULL);
async_polkit_query_free(q); async_polkit_query_free(q);
return r; return r;
} }
@ -196,16 +256,14 @@ int bus_verify_polkit_async(
bool interactive, bool interactive,
uid_t good_user, uid_t good_user,
Hashmap **registry, Hashmap **registry,
sd_bus_error *error) { sd_bus_error *ret_error) {
#if ENABLE_POLKIT #if ENABLE_POLKIT
_cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
AsyncPolkitQuery *q; AsyncPolkitQuery *q;
const char *sender, **k, **v;
sd_bus_message_handler_t callback;
void *userdata;
int c; int c;
#endif #endif
const char *sender;
int r; int r;
assert(call); assert(call);
@ -221,11 +279,17 @@ int bus_verify_polkit_async(
if (q) { if (q) {
int authorized, challenge; int authorized, challenge;
/* This is the second invocation of this function, and /* This is the second invocation of this function, and there's already a response from
* there's already a response from polkit, let's * polkit, let's process it */
* process it */
assert(q->reply); assert(q->reply);
/* If the operation we want to authenticate changed between the first and the second time,
* let's not use this authentication, it might be out of date as the object and context we
* operate on might have changed. */
if (!streq(q->action, action) ||
!strv_equal(q->details, (char**) details))
return -ESTALE;
if (sd_bus_message_is_method_error(q->reply, NULL)) { if (sd_bus_message_is_method_error(q->reply, NULL)) {
const sd_bus_error *e; const sd_bus_error *e;
@ -237,7 +301,7 @@ int bus_verify_polkit_async(
return -EACCES; return -EACCES;
/* Copy error from polkit reply */ /* Copy error from polkit reply */
sd_bus_error_copy(error, e); sd_bus_error_copy(ret_error, e);
return -sd_bus_error_get_errno(e); return -sd_bus_error_get_errno(e);
} }
@ -251,7 +315,7 @@ int bus_verify_polkit_async(
return 1; return 1;
if (challenge) if (challenge)
return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required."); return sd_bus_error_set(ret_error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
return -EACCES; return -EACCES;
} }
@ -263,20 +327,11 @@ int bus_verify_polkit_async(
else if (r > 0) else if (r > 0)
return 1; return 1;
#if ENABLE_POLKIT
if (sd_bus_get_current_message(call->bus) != call)
return -EINVAL;
callback = sd_bus_get_current_handler(call->bus);
if (!callback)
return -EINVAL;
userdata = sd_bus_get_current_userdata(call->bus);
sender = sd_bus_message_get_sender(call); sender = sd_bus_message_get_sender(call);
if (!sender) if (!sender)
return -EBADMSG; return -EBADMSG;
#if ENABLE_POLKIT
c = sd_bus_message_get_allow_interactive_authorization(call); c = sd_bus_message_get_allow_interactive_authorization(call);
if (c < 0) if (c < 0)
return c; return c;
@ -305,17 +360,7 @@ int bus_verify_polkit_async(
if (r < 0) if (r < 0)
return r; return r;
r = sd_bus_message_open_container(pk, 'a', "{ss}"); r = bus_message_append_strv_key_value(pk, details);
if (r < 0)
return r;
STRV_FOREACH_PAIR(k, v, details) {
r = sd_bus_message_append(pk, "{ss}", *k, *v);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(pk);
if (r < 0) if (r < 0)
return r; return r;
@ -323,13 +368,25 @@ int bus_verify_polkit_async(
if (r < 0) if (r < 0)
return r; return r;
q = new0(AsyncPolkitQuery, 1); q = new(AsyncPolkitQuery, 1);
if (!q) if (!q)
return -ENOMEM; return -ENOMEM;
q->request = sd_bus_message_ref(call); *q = (AsyncPolkitQuery) {
q->callback = callback; .request = sd_bus_message_ref(call),
q->userdata = userdata; };
q->action = strdup(action);
if (!q->action) {
async_polkit_query_free(q);
return -ENOMEM;
}
q->details = strv_copy((char**) details);
if (!q->details) {
async_polkit_query_free(q);
return -ENOMEM;
}
r = hashmap_put(*registry, call, q); r = hashmap_put(*registry, call, q);
if (r < 0) { if (r < 0) {

View File

@ -207,6 +207,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r);
int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
int sd_bus_flush(sd_bus *bus); int sd_bus_flush(sd_bus *bus);
int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m);
sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
sd_bus_message* sd_bus_get_current_message(sd_bus *bus); sd_bus_message* sd_bus_get_current_message(sd_bus *bus);

View File

@ -2,6 +2,7 @@
Description=Test for CapabilityBoundingSet Description=Test for CapabilityBoundingSet
[Service] [Service]
ExecStart=/bin/sh -x -c '! capsh --print | grep "^Bounding set .*cap_chown"' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep "^Bounding set .*cap_chown"'
Type=oneshot Type=oneshot
CapabilityBoundingSet=~CAP_CHOWN CapabilityBoundingSet=~CAP_CHOWN

View File

@ -3,5 +3,6 @@ Description=Test CAP_MKNOD capability for PrivateDevices=no
[Service] [Service]
PrivateDevices=no PrivateDevices=no
ExecStart=/bin/sh -x -c 'capsh --print | grep cap_mknod' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_SYS_RAWIO capability for PrivateDevices=no
[Service] [Service]
PrivateDevices=no PrivateDevices=no
ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_rawio' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_MKNOD capability for PrivateDevices=yes
[Service] [Service]
PrivateDevices=yes PrivateDevices=yes
ExecStart=/bin/sh -x -c '! capsh --print | grep cap_mknod' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_SYS_RAWIO capability for PrivateDevices=yes
[Service] [Service]
PrivateDevices=yes PrivateDevices=yes
ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_rawio' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_SYSLOG for ProtectKernelLogs=no
[Service] [Service]
ProtectKernelLogs=no ProtectKernelLogs=no
ExecStart=/bin/sh -x -c 'capsh --print | grep cap_syslog' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_syslog'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_SYSLOG for ProtectKernelLogs=yes
[Service] [Service]
ProtectKernelLogs=yes ProtectKernelLogs=yes
ExecStart=/bin/sh -x -c '! capsh --print | grep cap_syslog' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_syslog'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_SYS_MODULE ProtectKernelModules=no
[Service] [Service]
ProtectKernelModules=no ProtectKernelModules=no
ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_module' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module'
Type=oneshot Type=oneshot

View File

@ -3,5 +3,6 @@ Description=Test CAP_SYS_MODULE for ProtectKernelModules=yes
[Service] [Service]
ProtectKernelModules=yes ProtectKernelModules=yes
ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_module' # sed: remove dropped capabilities (cap_xxx-[epi]) from the output
ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module'
Type=oneshot Type=oneshot

View File

@ -27,6 +27,7 @@ which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':
networkd_bin=shutil.which('systemd-networkd', path=which_paths) networkd_bin=shutil.which('systemd-networkd', path=which_paths)
resolved_bin=shutil.which('systemd-resolved', path=which_paths) resolved_bin=shutil.which('systemd-resolved', path=which_paths)
udevd_bin=shutil.which('systemd-udevd', path=which_paths)
wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths) wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
networkctl_bin=shutil.which('networkctl', path=which_paths) networkctl_bin=shutil.which('networkctl', path=which_paths)
resolvectl_bin=shutil.which('resolvectl', path=which_paths) resolvectl_bin=shutil.which('resolvectl', path=which_paths)
@ -164,7 +165,7 @@ def setUpModule():
shutil.rmtree(networkd_ci_path) shutil.rmtree(networkd_ci_path)
copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path) copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'firewalld.service']: for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'systemd-udevd.service', 'firewalld.service']:
if call(f'systemctl is-active --quiet {u}') == 0: if call(f'systemctl is-active --quiet {u}') == 0:
check_output(f'systemctl stop {u}') check_output(f'systemctl stop {u}')
running_units.append(u) running_units.append(u)
@ -226,21 +227,34 @@ def setUpModule():
with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f: with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f:
f.write('\n'.join(drop_in)) f.write('\n'.join(drop_in))
drop_in = [
'[Service]',
'ExecStart=',
'ExecStart=!!' + udevd_bin,
]
os.makedirs('/run/systemd/system/systemd-udevd.service.d', exist_ok=True)
with open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode='w') as f:
f.write('\n'.join(drop_in))
check_output('systemctl daemon-reload') check_output('systemctl daemon-reload')
print(check_output('systemctl cat systemd-networkd.service')) print(check_output('systemctl cat systemd-networkd.service'))
print(check_output('systemctl cat systemd-resolved.service')) print(check_output('systemctl cat systemd-resolved.service'))
print(check_output('systemctl cat systemd-udevd.service'))
check_output('systemctl restart systemd-resolved') check_output('systemctl restart systemd-resolved')
check_output('systemctl restart systemd-udevd')
def tearDownModule(): def tearDownModule():
global running_units global running_units
shutil.rmtree(networkd_ci_path) shutil.rmtree(networkd_ci_path)
for u in ['systemd-networkd.service', 'systemd-resolved.service']: for u in ['systemd-networkd.service', 'systemd-resolved.service', 'systemd-udevd.service']:
check_output(f'systemctl stop {u}') check_output(f'systemctl stop {u}')
shutil.rmtree('/run/systemd/system/systemd-networkd.service.d') shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
shutil.rmtree('/run/systemd/system/systemd-resolved.service.d') shutil.rmtree('/run/systemd/system/systemd-resolved.service.d')
shutil.rmtree('/run/systemd/system/systemd-udevd.service.d')
check_output('systemctl daemon-reload') check_output('systemctl daemon-reload')
for u in running_units: for u in running_units:
@ -3568,6 +3582,7 @@ if __name__ == '__main__':
parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir') parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin') parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin') parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin') parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin') parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin') parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
@ -3580,10 +3595,11 @@ if __name__ == '__main__':
ns, args = parser.parse_known_args(namespace=unittest) ns, args = parser.parse_known_args(namespace=unittest)
if ns.build_dir: if ns.build_dir:
if ns.networkd_bin or ns.resolved_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin: if ns.networkd_bin or ns.resolved_bin or ns.udevd_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin:
print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.') print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd') networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved') resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online') wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
networkctl_bin = os.path.join(ns.build_dir, 'networkctl') networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl') resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
@ -3593,6 +3609,8 @@ if __name__ == '__main__':
networkd_bin = ns.networkd_bin networkd_bin = ns.networkd_bin
if ns.resolved_bin: if ns.resolved_bin:
resolved_bin = ns.resolved_bin resolved_bin = ns.resolved_bin
if ns.udevd_bin:
udevd_bin = ns.udevd_bin
if ns.wait_online_bin: if ns.wait_online_bin:
wait_online_bin = ns.wait_online_bin wait_online_bin = ns.wait_online_bin
if ns.networkctl_bin: if ns.networkctl_bin: