]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #11897 from mrc0mmand/parallelize-TEST-24-UNIT-TESTS
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 12 Mar 2019 10:21:06 +0000 (11:21 +0100)
committerGitHub <noreply@github.com>
Tue, 12 Mar 2019 10:21:06 +0000 (11:21 +0100)
test: parallelize tasks in TEST-24-UNIT-TESTS

138 files changed:
.lgtm/cpp-queries/PotentiallyDangerousFunction.ql [new file with mode: 0644]
.lgtm/cpp-queries/fgets.ql [deleted file]
TODO
docs/DISTRO_PORTING.md
docs/ENVIRONMENT.md
hwdb/60-evdev.hwdb
hwdb/60-input-id.hwdb
hwdb/60-keyboard.hwdb
man/systemctl.xml
man/systemd.exec.xml
man/systemd.network.xml
man/udevadm.xml
meson.build
po/pl.po
semaphoreci/setup.sh
src/basic/fs-util.c
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/meson.build
src/basic/refcnt.h [deleted file]
src/boot/bootctl.c
src/core/dbus-service.c
src/core/dbus-unit.c
src/core/device.c
src/core/execute.c
src/core/load-fragment.c
src/core/meson.build
src/core/systemd.pc.in
src/core/unit.c
src/fuzz/fuzz-bus-label.c [new file with mode: 0644]
src/fuzz/fuzz-dhcp6-client.c
src/fuzz/fuzz-dhcp6-client.options [new file with mode: 0644]
src/fuzz/fuzz-env-file.c [new file with mode: 0644]
src/fuzz/fuzz-hostname-util.c [new file with mode: 0644]
src/fuzz/fuzz-nspawn-settings.c [new file with mode: 0644]
src/fuzz/meson.build
src/import/import-common.c
src/journal-remote/journal-remote-main.c
src/journal/catalog.c
src/libsystemd-network/dhcp-identifier.c
src/libsystemd-network/test-lldp.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-address.c
src/libsystemd/sd-bus/test-bus-cleanup.c
src/libsystemd/sd-bus/test-bus-introspect.c
src/libsystemd/sd-bus/test-bus-queue-ref-cycle.c
src/libsystemd/sd-bus/test-bus-watch-bind.c
src/libsystemd/sd-device/device-internal.h
src/libsystemd/sd-device/device-private.c
src/libsystemd/sd-device/device-private.h
src/libsystemd/sd-hwdb/sd-hwdb.c
src/libsystemd/sd-netlink/netlink-internal.h
src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-socket.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-util.c
src/libsystemd/sd-netlink/rtnl-message.c
src/libsystemd/sd-netlink/sd-netlink.c
src/locale/test-keymap-util.c
src/login/71-seat.rules.in
src/login/loginctl.c
src/login/logind-dbus.c
src/login/org.freedesktop.login1.conf
src/login/org.freedesktop.login1.policy
src/machine/machinectl.c
src/network/networkd-address-pool.c
src/network/networkd-address-pool.h
src/network/networkd-address.c
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-route.c
src/nspawn/nspawn-mount.c
src/nspawn/nspawn.c
src/random-seed/random-seed.c
src/resolve/resolved-dns-answer.c
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-question.c
src/resolve/resolved-dns-question.h
src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h
src/resolve/test-resolved-etc-hosts.c
src/resolve/test-resolved-packet.c
src/shared/bootspec.c
src/shared/bootspec.h
src/shared/bus-util.c
src/shared/bus-util.h
src/shared/efivars.c
src/shared/efivars.h
src/shared/json.c
src/shared/udev-util.c
src/shared/udev-util.h
src/shutdown/meson.build [new file with mode: 0644]
src/shutdown/shutdown.c [moved from src/core/shutdown.c with 97% similarity]
src/shutdown/umount.c [moved from src/core/umount.c with 100% similarity]
src/shutdown/umount.h [moved from src/core/umount.h with 100% similarity]
src/systemctl/systemctl.c
src/test/meson.build
src/test/test-chown-rec.c
src/test/test-execute.c
src/test/test-fs-util.c
src/test/test-in-addr-util.c
src/test/test-nss.c
src/test/test-tables.c
src/timedate/timedatectl.c
src/timedate/timedated.c
src/tmpfiles/tmpfiles.c
src/udev/udev-event.c
src/udev/udev-node.c
src/udev/udev-node.h
src/udev/udev-rules.c
src/udev/udev.h
src/udev/udevadm-test.c
src/udev/udevadm-trigger.c
test/TEST-22-TMPFILES/test-08.sh [new file with mode: 0755]
test/TEST-29-UDEV-ID_RENAMING/Makefile [new symlink]
test/TEST-29-UDEV-ID_RENAMING/test.sh [new file with mode: 0755]
test/TEST-29-UDEV-ID_RENAMING/testsuite.sh [new file with mode: 0755]
test/fuzz/fuzz-dns-packet/oss-fuzz-13422 [new file with mode: 0644]
test/fuzz/fuzz-env-file/simple-env-file [new file with mode: 0644]
test/fuzz/fuzz-network-parser/directives.network
test/fuzz/fuzz-nspawn-settings/basic-config [new file with mode: 0644]
test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f [new file with mode: 0644]
test/test-network/conf/21-vlan-test1.network [new file with mode: 0644]
test/test-network/conf/21-vlan-test1.network.d/override.conf [new file with mode: 0644]
test/test-network/conf/21-vlan.network
test/test-network/conf/21-vlan.network.d/override.conf [deleted file]
test/test-network/conf/25-address-section.network
test/test-network/systemd-networkd-tests.py
travis-ci/managers/debian.sh
units/system-update-cleanup.service
units/systemd-journald.service.in
units/systemd-logind.service.in
units/systemd-networkd.service.in
units/systemd-resolved.service.in

diff --git a/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql b/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql
new file mode 100644 (file)
index 0000000..ba80f4a
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * @name Use of potentially dangerous function
+ * @description Certain standard library functions are dangerous to call.
+ * @kind problem
+ * @problem.severity error
+ * @precision high
+ * @id cpp/potentially-dangerous-function
+ * @tags reliability
+ *       security
+ *
+ * Borrowed from
+ * https://github.com/Semmle/ql/blob/master/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql
+ */
+import cpp
+
+predicate potentiallyDangerousFunction(Function f, string message) {
+  (
+    f.getQualifiedName() = "fgets" and
+    message = "Call to fgets is potentially dangerous. Use read_line() instead."
+  ) or (
+    f.getQualifiedName() = "strtok" and
+    message = "Call to strtok is potentially dangerous. Use extract_first_word() instead."
+  )
+}
+
+from FunctionCall call, Function target, string message
+where
+  call.getTarget() = target and
+  potentiallyDangerousFunction(target, message)
+select call, message
diff --git a/.lgtm/cpp-queries/fgets.ql b/.lgtm/cpp-queries/fgets.ql
deleted file mode 100644 (file)
index a4181e4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * @name Use of fgets()
- * @description fgets() is dangerous to call. Use read_line() instead.
- * @kind problem
- * @problem.severity error
- * @precision high
- * @id cpp/fgets
- * @tags reliability
- *       security
- */
-import cpp
-
-predicate dangerousFunction(Function function) {
-  exists (string name | name = function.getQualifiedName() |
-    name = "fgets")
-}
-
-from FunctionCall call, Function target
-where call.getTarget() = target
-  and dangerousFunction(target)
-select call, target.getQualifiedName() + " is potentially dangerous"
diff --git a/TODO b/TODO
index 0178d431d5b16ae31e99243384b538fb4fdb7782..9e4e07da5eff9e024401a68449b36ca5cb73d374 100644 (file)
--- a/TODO
+++ b/TODO
@@ -63,7 +63,7 @@ Features:
 
 * paranoia: whenever we process passwords, call mlock() on the memory
   first. i.e. look for all places we use string_erase()/string_free_erase() and
-  augment them with mlock()
+  augment them with mlock(). Also use MADV_DONTDUMP
 
 * whenever oom_kill memory.event event is triggered print a nice log message
 
@@ -88,17 +88,12 @@ Features:
   show state of these flags, and optionally trigger such a factory reset on
   next boot by setting the flag.
 
-* sd-boot: add "oneshot boot timeout" variable support
-
 * sd-boot: automatically load EFI modules from some drop-in dir, so that people
   can add in file system drivers and such
 
 * sd-boot: optionally, show boot menu when previous default boot item has
   non-zero "tries done" count
 
-* logind: add "boot into bootmenu" API, and possibly even "boot into windows"
-  and "boot into macos".
-
 * maybe set a special xattr on cgroups that have delegate=yes set, to make it
   easy to mark cut points
 
index 0099a1334aed6473231a5abf087f1a173aa03374..620e47e823c8ead9243313b98eab0f8d6505a32c 100644 (file)
@@ -31,6 +31,20 @@ distribution:
    print the initial transaction it would execute during boot-up.
    This will also inform you about ordering loops and suchlike.
 
+## Compilation options
+
+The default configuration does not enable any optimization or hardening
+options. This is suitable for development and testing, but not for end-user
+installations.
+
+For deployment, optimization (`-O2` or `-O3` compiler options), link time
+optimization (`-Db_lto=true` meson option), and hardening (e.g.
+`-D_FORTIFY_SOURCE=2`, `-fstack-protector-strong`, `-fstack-clash-protection`,
+`-fcf-protection`, `-pie` compiler options, and `-z relro`, `-z now`,
+`--as-needed` linker options) are recommended. The most appropriate set of
+options depends on the architecture and distribution specifics so no default is
+provided.
+
 ## NTP Pool
 
 By default, systemd-timesyncd uses the Google Public NTP servers
index 99b5b03b68755ce632c017e9259d1e22789d16d3..f72ed20dd0fc094a2bcbe7c76134df614704eb96 100644 (file)
@@ -107,6 +107,51 @@ systemd-udevd:
   with `:` in which case the kernel command line option takes precedence, if it
   is specified as well.
 
+* `$SYSTEMD_REBOOT_TO_FIRMWARE_SETUP` â€” if set overrides systemd-logind's
+  built-in EFI logic of requesting a reboot into the firmware. Takes a
+  boolean. If set to false the functionality is turned off entirely. If set to
+  true instead of requesting a reboot into the firmware setup UI through EFI a
+  file `/run/systemd/reboot-to-firmware-setup` is created whenever this is
+  requested. This file may be checked for by services run during system
+  shutdown in order to request the appropriate operation from the firmware in
+  an alternative fashion.
+
+* `$SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU` â€” similar to the above, allows
+  overriding of systemd-logind's built-in EFI logic of requesting a reboot into
+  the boot loader menu. Takes a boolean. If set to false the functionality is
+  turned off entirely. If set to true instead of requesting a reboot into the
+  boot loader menu through EFI a file `/run/systemd/reboot-to-boot-loader-menu`
+  is created whenever this is requested. The file contains the requested boot
+  loader menu timeout in Âµs, formatted in ASCII decimals, or zero in case no
+  time-out is requested. This file may be checked for by services run during
+  system shutdown in order to request the appropriate operation from the boot
+  loader in an alternative fashion.
+
+* `$SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY` â€” similar to the above, allows
+  overriding of systemd-logind's built-in EFI logic of requesting a reboot into
+  a specific boot loader entry. Takes a boolean. If set to false the
+  functionality is turned off entirely. If set to true instead of requesting a
+  reboot into a specific boot loader entry through EFI a file
+  `/run/systemd/reboot-to-boot-loader-entry` is created whenever this is
+  requested. The file contains the requested boot loader entry identifier. This
+  file may be checked for by services run during system shutdown in order to
+  request the appropriate operation from the boot loader in an alternative
+  fashion. Note that by default only boot loader entries which follow the [Boot
+  Loader Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION) and are
+  placed in the ESP or the Extended Boot Loader partition may be selected this
+  way. However, if a directory `/run/boot-loader-entries/` exists, the entries
+  are loaded from there instead. The directory should contain the usual
+  directory hierarchy mandated by the Boot Loader Specification, i.e. the entry
+  drop-ins should be placed in
+  `/run/boot-loader-entries/loader/entries/*.conf`, and the files referenced by
+  the drop-ins (including the kernels and initrds) somewhere else below
+  `/run/boot-loader-entries/`. Note that all these files may be (and are
+  supposed to be) symlinks. systemd-logind will load these files on-demand,
+  these files can hence be updated (ideally atomically) whenever the boot
+  loader configuration changes. A foreign boot loader installer script should
+  hence synthesize drop-in snippets and symlinks for all boot entries at boot
+  or whenever they change if it wants to integrate with systemd-logind's APIs.
+
 installed systemd tests:
 
 * `$SYSTEMD_TEST_DATA` â€” override the location of test data. This is useful if
index 3ebdeb6564aa3a113089d951ef4d9fefeb20ec44..4f94342a095bdd62e2cf1db33e33a989d24b2b5b 100644 (file)
@@ -100,6 +100,32 @@ evdev:input:b0003v05ACp025B*
  EVDEV_ABS_35=::94
  EVDEV_ABS_36=::92
 
+# MacBook8,1 (2015), MacBook9,1 (2016), MacBook10,1 (2017)
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook8,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook9,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook10,1:*
+ EVDEV_ABS_00=::95
+ EVDEV_ABS_01=::90
+ EVDEV_ABS_35=::95
+ EVDEV_ABS_36=::90
+
+# MacBookPro13,* (Late 2016), MacBookPro14,* (Mid 2017)
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,2:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,1:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,2:*
+ EVDEV_ABS_00=::96
+ EVDEV_ABS_01=::94
+ EVDEV_ABS_35=::96
+ EVDEV_ABS_36=::94
+
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,3:*
+evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,3:*
+ EVDEV_ABS_00=::96
+ EVDEV_ABS_01=::95
+ EVDEV_ABS_35=::96
+ EVDEV_ABS_36=::95
+
 #########################################
 # ASUS
 #########################################
index 7e9dc99220b2426d25c000b4a8fa1a7eaa1446fd..20c1e7ea0da26a6d80f5a4404a3e07e25d27c9f9 100644 (file)
@@ -66,3 +66,7 @@ id-input:modalias:input:b0003v5543p0081*
 # XP-PEN STAR 06
 id-input:modalias:input:b0003v28bdp0078*
  ID_INPUT_TABLET=1
+
+# Lite-On Tech IBM USB Travel Keyboard with Ultra Nav Mouse
+id-input:modalias:input:b0003v04B3p301Ee0100-e0,1,2,4*
+ ID_INPUT_POINTINGSTICK=1
index 355544030ba197327cfba2d71344feacdabbbaaf..f9ae0fe78c4ad3ae6d46e14323e27b734696c7f0 100644 (file)
@@ -188,6 +188,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:pvr*
 ###########################################################
 
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*
+ KEYBOARD_KEY_81=f21                                    # Touchpad toggle
  KEYBOARD_KEY_8a=ejectcd
 
 # Alienware/Dell reserves these keys; safe to apply on all their devices
@@ -802,6 +803,10 @@ evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr*
  KEYBOARD_KEY_ae=!volumedown
  KEYBOARD_KEY_b0=!volumeup
 
+# Lenovo Y50-70
+evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*20378*:pvr*
+ KEYBOARD_KEY_f3=f21      # Fn+F6 (toggle touchpad)
+
 # V480
 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
  KEYBOARD_KEY_f1=f21
index 08aacd8f41c9ae7e9e7628ffd741d55ffc5aa768..512c255b39eb96f29d68e70d0a3b6da65453fe82 100644 (file)
         <term><option>--firmware-setup</option></term>
 
         <listitem>
-          <para>When used with the <command>reboot</command> command,
-          indicate to the system's firmware to boot into setup
-          mode. Note that this is currently only supported on some EFI
-          systems and only if the system was booted in EFI
-          mode.</para>
+          <para>When used with the <command>reboot</command> command, indicate to the system's firmware to reboot into
+          the firmware setup interface. Note that this functionality is not available on all systems.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--boot-loader-menu=</option></term>
+
+        <listitem>
+          <para>When used with the <command>reboot</command> command, indicate to the system's boot loader to show the
+          boot loader menu on the following boot. Takes a time value as parameter â€” indicating the menu time-out. Pass
+          zero in order to disable the menu time-out. Note that not all boot loaders support this
+          functionality.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--boot-loader-entry=</option></term>
+
+        <listitem>
+          <para>When used with the <command>reboot</command> command, indicate to the system's boot loader to boot into
+          a specific boot loader entry on the following boot. Takes a boot loader entry identifier as argument, or
+          <literal>help</literal> in order to list available entries. Note that not all boot loaders support this
+          functionality.</para>
         </listitem>
       </varlistentry>
 
index b8843f1ea0bb7e869de35d3db6347189f3596df1..19c7b26bcee3571a9146daf8f50e05ce9ed9d278 100644 (file)
@@ -1135,9 +1135,13 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
         <listitem><para>Takes a boolean argument. When set, sets up a new UTS namespace for the executed
         processes. In addition, changing hostname or domainname is prevented. Defaults to off.</para>
 
-        <para>Note that the implementation of this setting might be impossible (for example if UTS namespaces are not
-        available), and the unit should be written in a way that does not solely rely on this setting for
-        security.</para></listitem>
+        <para>Note that the implementation of this setting might be impossible (for example if UTS namespaces
+        are not available), and the unit should be written in a way that does not solely rely on this setting
+        for security.</para>
+
+        <para>Note that when this option is enabled for a service hostname changes no longer propagate from
+        the system into the service, it is hence not suitable for services that need to take notice of system
+        hostname changes dynamically.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 8b6c187f346190cd7433ab9566a786d9d3b7a4e5..1a3d24aa7633144e1a28984b6bbdd97ec0af8e2a 100644 (file)
         <varlistentry>
           <term><varname>DHCPServer=</varname></term>
           <listitem>
-            <para>Takes a boolean. If set to <literal>yes</literal>, DHCPv4 server will be start. Defaults
+            <para>Takes a boolean. If set to <literal>yes</literal>, DHCPv4 server will be started. Defaults
             to <literal>no</literal>. Further settings for the DHCP
             server may be set in the <literal>[DHCPServer]</literal>
             section described below.</para>
             specified more than once.
             </para>
 
-            <para>If the specified address is 0.0.0.0 (for IPv4) or
-            [::] (for IPv6), a new address range of the requested size
-            is automatically allocated from a system-wide pool of
-            unused ranges. The allocated range is checked against all
-            current network interfaces and all known network
-            configuration files to avoid address range conflicts. The
-            default system-wide pool consists of 192.168.0.0/16,
-            172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fc00::/7 for
-            IPv6. This functionality is useful to manage a large
-            number of dynamically created network interfaces with the
-            same network configuration and automatic address range
-            assignment.</para>
+            <para>If the specified address is <literal>0.0.0.0</literal> (for IPv4) or <literal>::</literal>
+            (for IPv6), a new address range of the requested size is automatically allocated from a
+            system-wide pool of unused ranges. Note that the prefix length must be equal or larger than 8 for
+            IPv4, and 64 for IPv6. The allocated range is checked against all current network interfaces and
+            all known network configuration files to avoid address range conflicts. The default system-wide
+            pool consists of 192.168.0.0/16, 172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fd00::/8 for IPv6.
+            This functionality is useful to manage a large number of dynamically created network interfaces
+            with the same network configuration and automatic address range assignment.</para>
 
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><varname>Address=</varname></term>
           <listitem>
-            <para>As in the <literal>[Network]</literal> section. This
-            key is mandatory.</para>
+            <para>As in the <literal>[Network]</literal> section. This key is mandatory. Each
+            <literal>[Address]</literal> section can contain one <varname>Address=</varname> setting.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><varname>Peer=</varname></term>
           <listitem>
             <para>The peer address in a point-to-point connection.
-            Accepts the same format as the <literal>Address</literal>
+            Accepts the same format as the <varname>Address=</varname>
             key.</para>
           </listitem>
         </varlistentry>
             described in
             <citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
             This key only applies to IPv4 addresses. If it is not
-            given, it is derived from the <literal>Address</literal>
+            given, it is derived from the <varname>Address=</varname>
             key.</para>
           </listitem>
         </varlistentry>
             automatic restart off. By default automatic restart is disabled.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>TripleSampling=</varname></term>
+          <listitem>
+            <para>Takes a boolean. When <literal>yes</literal>, three samples (instead of one) are used to determine
+            the value of a received bit by majority rule. When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
   </refsect1>
 
index f25a1dfb48b2a6be9fe53b8e0a153393a7562b24..d4fdaea6fffd9ad3ae4f23c83d7a60c11caeb125 100644 (file)
           <term><option>-c</option></term>
           <term><option>--action=<replaceable>ACTION</replaceable></option></term>
           <listitem>
-            <para>Type of event to be triggered. The default value is
-            <command>change</command>.</para>
+            <para>Type of event to be triggered. Possible actions are <literal>add</literal>,
+            <literal>remove</literal>, <literal>change</literal>, <literal>move</literal>,
+            <literal>online</literal>, <literal>offline</literal>, <literal>bind</literal>,
+            and <literal>unbind</literal>. The default value is <literal>change</literal>.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index 239f13c061455ec5f43d2c99ad977a8087e7bda0..3d8220e1549a271ebb45b2d11744371eff350c6e 100644 (file)
@@ -66,6 +66,7 @@ rootprefix_default = split_usr ? '/' : '/usr'
 if rootprefixdir == ''
         rootprefixdir = rootprefix_default
 endif
+rootprefixdir_noslash = rootprefixdir == '/' ? '' : rootprefixdir
 
 sysvinit_path = get_option('sysvinit-path')
 sysvrcnd_path = get_option('sysvrcnd-path')
@@ -76,7 +77,7 @@ conf.set10('BUMP_PROC_SYS_FS_FILE_MAX', get_option('bump-proc-sys-fs-file-max'))
 conf.set10('BUMP_PROC_SYS_FS_NR_OPEN',  get_option('bump-proc-sys-fs-nr-open'))
 conf.set('HIGH_RLIMIT_NOFILE',          512*1024)
 
-# join_paths ignore the preceding arguments if an absolute component is
+# join_paths ignores the preceding arguments if an absolute component is
 # encountered, so this should canonicalize various paths when they are
 # absolute or relative.
 prefixdir = get_option('prefix')
@@ -235,6 +236,7 @@ conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO',           memory_accounting_
 
 substs.set('prefix',                                          prefixdir)
 substs.set('rootprefix',                                      rootprefixdir)
+substs.set('rootprefix_noslash',                              rootprefixdir_noslash)
 substs.set('exec_prefix',                                     prefixdir)
 substs.set('libdir',                                          libdir)
 substs.set('rootlibdir',                                      rootlibdir)
@@ -334,7 +336,8 @@ possible_cc_flags = [
         '-Wno-missing-field-initializers',
         '-Wno-unused-result',
         '-Wno-format-signedness',
-        '-Wno-error=#warnings',
+        '-Wno-error=#warnings',  # clang
+        '-Wno-string-plus-int',  # clang
 
         # work-around for gcc 7.1 turning this on on its own.
         '-Wno-error=nonnull',
@@ -1441,6 +1444,7 @@ includes = include_directories('src/basic',
                                'src/udev',
                                'src/libudev',
                                'src/core',
+                               'src/shutdown',
                                'src/libsystemd/sd-bus',
                                'src/libsystemd/sd-device',
                                'src/libsystemd/sd-event',
@@ -1527,6 +1531,7 @@ public_programs = []
 subdir('src/libudev')
 subdir('src/shared')
 subdir('src/core')
+subdir('src/shutdown')
 subdir('src/udev')
 subdir('src/network')
 
@@ -1711,9 +1716,9 @@ executable('systemd-run-generator',
 
 executable('systemd-fstab-generator',
            'src/fstab-generator/fstab-generator.c',
-           'src/core/mount-setup.c',
            include_directories : includes,
-           link_with : [libshared],
+           link_with : [libcore_shared,
+                        libshared],
            install_rpath : rootlibexecdir,
            install : true,
            install_dir : systemgeneratordir)
@@ -2351,20 +2356,18 @@ endif
 
 executable('systemd-remount-fs',
            'src/remount-fs/remount-fs.c',
-           'src/core/mount-setup.c',
-           'src/core/mount-setup.h',
            include_directories : includes,
-           link_with : [libshared],
+           link_with : [libcore_shared,
+                        libshared],
            install_rpath : rootlibexecdir,
            install : true,
            install_dir : rootlibexecdir)
 
 executable('systemd-machine-id-setup',
            'src/machine-id-setup/machine-id-setup-main.c',
-           'src/core/machine-id-setup.c',
-           'src/core/machine-id-setup.h',
            include_directories : includes,
-           link_with : [libshared],
+           link_with : [libcore_shared,
+                        libshared],
            install_rpath : rootlibexecdir,
            install : true,
            install_dir : rootbindir)
@@ -2677,7 +2680,8 @@ public_programs += exe
 executable('systemd-shutdown',
            systemd_shutdown_sources,
            include_directories : includes,
-           link_with : [libshared],
+           link_with : [libcore_shared,
+                        libshared],
            dependencies : [libmount],
            install_rpath : rootlibexecdir,
            install : true,
@@ -2718,12 +2722,9 @@ endif
 
 exe = executable('systemd-nspawn',
                  systemd_nspawn_sources,
-                 'src/core/mount-setup.c', # FIXME: use a variable?
-                 'src/core/mount-setup.h',
-                 'src/core/loopback-setup.c',
-                 'src/core/loopback-setup.h',
                  include_directories : includes,
-                 link_with : [libnspawn_core,
+                 link_with : [libcore_shared,
+                              libnspawn_core,
                               libshared],
                  dependencies : [libblkid],
                  install_rpath : rootlibexecdir,
index 80c9c97e9721a875acc0be248a9ce0b66ff73ce4..ccfac25975d2466b0f6a3655751a4dd9d7b584c1 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,8 +6,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
 "Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2018-10-26 19:14+0000\n"
-"PO-Revision-Date: 2018-10-26 21:15+0200\n"
+"POT-Creation-Date: 2019-03-06 17:54+0000\n"
+"PO-Revision-Date: 2019-03-06 18:58+0100\n"
 "Last-Translator: Piotr DrÄ…g <piotrdrag@gmail.com>\n"
 "Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
 "Language: pl\n"
@@ -469,7 +469,7 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje."
 
 #: src/login/org.freedesktop.login1.policy:341
-msgid "Allow indication to the firmware to boot to setup interface"
+msgid "Indicate to the firmware to boot to setup interface"
 msgstr "Wskazanie oprogramowaniu sprzÄ™towemu, aby uruchomić interfejs ustawieÅ„"
 
 #: src/login/org.freedesktop.login1.policy:342
@@ -480,11 +480,35 @@ msgstr ""
 "Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzÄ™towemu, Å¼e "
 "należy uruchomić interfejs ustawieÅ„."
 
-#: src/login/org.freedesktop.login1.policy:351
+#: src/login/org.freedesktop.login1.policy:352
+msgid "Indicate to the boot loader to boot to the boot loader menu"
+msgstr "Wskazanie programowi startowemu, aby uruchomić jego menu"
+
+#: src/login/org.freedesktop.login1.policy:353
+msgid ""
+"Authentication is required to indicate to the boot loader to boot to the "
+"boot loader menu."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, Å¼e należy "
+"uruchomić jego menu."
+
+#: src/login/org.freedesktop.login1.policy:363
+msgid "Indicate to the boot loader to boot a specific entry"
+msgstr "Wskazanie programowi startowemu, aby uruchomić podany wpis"
+
+#: src/login/org.freedesktop.login1.policy:364
+msgid ""
+"Authentication is required to indicate to the boot loader to boot into a "
+"specific boot loader entry."
+msgstr ""
+"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, Å¼e należy "
+"uruchomić podany wpis."
+
+#: src/login/org.freedesktop.login1.policy:374
 msgid "Set a wall message"
 msgstr "Ustawienie komunikatu wall"
 
-#: src/login/org.freedesktop.login1.policy:352
+#: src/login/org.freedesktop.login1.policy:375
 msgid "Authentication is required to set a wall message"
 msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall"
 
index b8cdba8033b8c3db2989c1467f848efc5c455127..c904a300a15154d2fb99f250d312c8c623724485 100755 (executable)
@@ -7,6 +7,36 @@ DISTRO=${DISTRO:-debian}
 RELEASE=${RELEASE:-buster}
 ARCH=${ARCH:-amd64}
 CONTAINER=${RELEASE}-${ARCH}
+MAX_CACHE_AGE=604800  # one week
+CACHE=${SEMAPHORE_CACHE_DIR:=/tmp}/${CONTAINER}.img.tar.gz
+
+create_container() {
+    # create autopkgtest LXC image; this sometimes fails with "Unable to fetch
+    # GPG key from keyserver", so retry a few times
+    for retry in $(seq 5); do
+        sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH && break
+        sleep $((retry*retry))
+    done
+
+    # unconfine the container, otherwise some tests fail
+    echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config
+
+    sudo lxc-start -n $CONTAINER
+
+    # enable source repositories so that apt-get build-dep works
+    sudo lxc-attach -n $CONTAINER -- sh -ex <<EOF
+sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
+# wait until online
+while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
+apt-get -q update
+apt-get -y dist-upgrade
+apt-get install -y eatmydata
+EOF
+    sudo lxc-stop -n $CONTAINER
+
+    # cache it
+    sudo tar cpzf "$CACHE" /var/lib/lxc/$CONTAINER
+}
 
 # remove semaphore repos, some of them don't work and cause error messages
 sudo rm -f /etc/apt/sources.list.d/*
@@ -17,25 +47,12 @@ sudo apt-get -q update
 sudo apt-get install -y -t xenial-backports lxc
 sudo apt-get install -y python3-debian git dpkg-dev fakeroot
 
-AUTOPKGTESTDIR=${SEMAPHORE_CACHE_DIR:-/tmp}/autopkgtest
+AUTOPKGTESTDIR=$SEMAPHORE_CACHE_DIR/autopkgtest
 [ -d $AUTOPKGTESTDIR ] || git clone --quiet --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTESTDIR"
 
-# TODO: cache container image (though downloading/building it takes < 1 min)
-# create autopkgtest LXC image
-sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH
-
-# unconfine the container, otherwise some tests fail
-echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config
-
-sudo lxc-start -n $CONTAINER
-
-# enable source repositories so that apt-get build-dep works
-sudo lxc-attach -n $CONTAINER -- sh -ex <<EOF
-sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
-# wait until online
-while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
-apt-get -q update
-apt-get -y dist-upgrade
-apt-get install -y eatmydata
-EOF
-sudo lxc-stop -n $CONTAINER
+# use cached container image, unless older than a week
+if [ -e "$CACHE" ] && [ $(( $(date +%s) - $(stat -c %Y "$CACHE") )) -le $MAX_CACHE_AGE ]; then
+    sudo tar -C / -xpzf "$CACHE"
+else
+    create_container
+fi
index 0d631093b29fabac8ef20ed74b1a57b8d1825300..431c8501eafcc1ef0f14a064baabfca98f58ad7c 100644 (file)
@@ -926,6 +926,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
                 if (fstat(child, &st) < 0)
                         return -errno;
                 if ((flags & CHASE_SAFE) &&
+                    (empty_or_root(root) || (size_t)(todo - buffer) > strlen(root)) &&
                     unsafe_transition(&previous_stat, &st))
                         return log_unsafe_transition(fd, child, path, flags);
 
index c715075c14f9f16446a36edbce0acfa6f9d7c43b..f5cabc65346c97c40346226205fffaa23f9bcfc0 100644 (file)
@@ -11,6 +11,8 @@
 #include "in-addr-util.h"
 #include "macro.h"
 #include "parse-util.h"
+#include "random-util.h"
+#include "strxcpyx.h"
 #include "util.h"
 
 bool in4_addr_is_null(const struct in_addr *a) {
@@ -215,8 +217,85 @@ int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen)
         return -EAFNOSUPPORT;
 }
 
+int in_addr_random_prefix(
+                int family,
+                union in_addr_union *u,
+                unsigned prefixlen_fixed_part,
+                unsigned prefixlen) {
+
+        assert(u);
+
+        /* Random network part of an address by one. */
+
+        if (prefixlen <= 0)
+                return 0;
+
+        if (family == AF_INET) {
+                uint32_t c, n;
+
+                if (prefixlen_fixed_part > 32)
+                        prefixlen_fixed_part = 32;
+                if (prefixlen > 32)
+                        prefixlen = 32;
+                if (prefixlen_fixed_part >= prefixlen)
+                        return -EINVAL;
+
+                c = be32toh(u->in.s_addr);
+                c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part);
+
+                random_bytes(&n, sizeof(n));
+                n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen);
+
+                u->in.s_addr = htobe32(n | c);
+                return 1;
+        }
+
+        if (family == AF_INET6) {
+                struct in6_addr n;
+                unsigned i, j;
+
+                if (prefixlen_fixed_part > 128)
+                        prefixlen_fixed_part = 128;
+                if (prefixlen > 128)
+                        prefixlen = 128;
+                if (prefixlen_fixed_part >= prefixlen)
+                        return -EINVAL;
+
+                random_bytes(&n, sizeof(n));
+
+                for (i = 0; i < 16; i++) {
+                        uint8_t mask_fixed_part = 0, mask = 0;
+
+                        if (i < (prefixlen_fixed_part + 7) / 8) {
+                                if (i < prefixlen_fixed_part / 8)
+                                        mask_fixed_part = 0xffu;
+                                else {
+                                        j = prefixlen_fixed_part % 8;
+                                        mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j);
+                                }
+                        }
+
+                        if (i < (prefixlen + 7) / 8) {
+                                if (i < prefixlen / 8)
+                                        mask = 0xffu ^ mask_fixed_part;
+                                else {
+                                        j = prefixlen % 8;
+                                        mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part;
+                                }
+                        }
+
+                        u->in6.s6_addr[i] &= mask_fixed_part;
+                        u->in6.s6_addr[i] |= n.s6_addr[i] & mask;
+                }
+
+                return 1;
+        }
+
+        return -EAFNOSUPPORT;
+}
+
 int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
-        char *x;
+        _cleanup_free_ char *x = NULL;
         size_t l;
 
         assert(u);
@@ -234,18 +313,50 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
                 return -ENOMEM;
 
         errno = 0;
-        if (!inet_ntop(family, u, x, l)) {
-                free(x);
+        if (!inet_ntop(family, u, x, l))
+                return errno > 0 ? -errno : -EINVAL;
+
+        *ret = TAKE_PTR(x);
+        return 0;
+}
+
+int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret) {
+        _cleanup_free_ char *x = NULL;
+        char *p;
+        size_t l;
+
+        assert(u);
+        assert(ret);
+
+        if (family == AF_INET)
+                l = INET_ADDRSTRLEN + 3;
+        else if (family == AF_INET6)
+                l = INET6_ADDRSTRLEN + 4;
+        else
+                return -EAFNOSUPPORT;
+
+        if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
+                return -EINVAL;
+
+        x = new(char, l);
+        if (!x)
+                return -ENOMEM;
+
+        errno = 0;
+        if (!inet_ntop(family, u, x, l))
                 return errno > 0 ? -errno : -EINVAL;
-        }
 
-        *ret = x;
+        p = x + strlen(x);
+        l -= strlen(x);
+        (void) strpcpyf(&p, l, "/%u", prefixlen);
+
+        *ret = TAKE_PTR(x);
         return 0;
 }
 
 int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
+        _cleanup_free_ char *x = NULL;
         size_t l;
-        char *x;
         int r;
 
         assert(u);
@@ -271,14 +382,12 @@ int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifin
                 return -ENOMEM;
 
         errno = 0;
-        if (!inet_ntop(family, u, x, l)) {
-                free(x);
+        if (!inet_ntop(family, u, x, l))
                 return errno > 0 ? -errno : -EINVAL;
-        }
 
         sprintf(strchr(x, 0), "%%%i", ifindex);
-        *ret = x;
 
+        *ret = TAKE_PTR(x);
         return 0;
 
 fallback:
index c21567122caf254d39882f7e8ff620bb56f8332b..a6a685b9188b5084e1b699a0afbb535cf77a1c41 100644 (file)
@@ -35,7 +35,9 @@ bool in4_addr_is_non_local(const struct in_addr *a);
 int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
 int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
 int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
+int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
 int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
+int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
 int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
 int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
 int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret);
index e5852f32f9ae0c4140615df24f10d4872df7bcb3..c62e4a3b593101af976064d7188b642ffcc096ce 100644 (file)
@@ -148,7 +148,6 @@ basic_sources = files('''
         ratelimit.h
         raw-clone.h
         raw-reboot.h
-        refcnt.h
         replace-var.c
         replace-var.h
         rlimit-util.c
diff --git a/src/basic/refcnt.h b/src/basic/refcnt.h
deleted file mode 100644 (file)
index 40f9a84..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-#pragma once
-
-/* A type-safe atomic refcounter.
- *
- * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
-
-typedef struct {
-        volatile unsigned _value;
-} RefCount;
-
-#define REFCNT_GET(r) ((r)._value)
-#define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1))
-#define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1))
-
-#define REFCNT_INIT ((RefCount) { ._value = 1 })
-
-#define _DEFINE_ATOMIC_REF_FUNC(type, name, scope)                    \
-        scope type *name##_ref(type *p) {                               \
-                if (!p)                                                 \
-                        return NULL;                                    \
-                                                                        \
-                assert_se(REFCNT_INC(p->n_ref) >= 2);                   \
-                return p;                                               \
-        }
-
-#define _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func, scope)       \
-        scope type *name##_unref(type *p) {                             \
-                if (!p)                                                 \
-                        return NULL;                                    \
-                                                                        \
-                if (REFCNT_DEC(p->n_ref) > 0)                           \
-                        return NULL;                                    \
-                                                                        \
-                return free_func(p);                                    \
-        }
-
-#define DEFINE_ATOMIC_REF_FUNC(type, name)    \
-        _DEFINE_ATOMIC_REF_FUNC(type, name,)
-#define DEFINE_PUBLIC_ATOMIC_REF_FUNC(type, name)     \
-        _DEFINE_ATOMIC_REF_FUNC(type, name, _public_)
-
-#define DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func)       \
-        _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func,)
-#define DEFINE_PUBLIC_ATOMIC_UNREF_FUNC(type, name, free_func)        \
-        _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func, _public_)
-
-#define DEFINE_ATOMIC_REF_UNREF_FUNC(type, name, free_func)   \
-        DEFINE_ATOMIC_REF_FUNC(type, name);                   \
-        DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func);
-
-#define DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(type, name, free_func)   \
-        DEFINE_PUBLIC_ATOMIC_REF_FUNC(type, name);                   \
-        DEFINE_PUBLIC_ATOMIC_UNREF_FUNC(type, name, free_func);
index 1e0d115fe3ebbf6fee2e3555b3cbcb18d7530f2a..b5f4b8e5a3d3c49dd58da99784bc435d687faec2 100644 (file)
@@ -311,13 +311,15 @@ static int status_variables(void) {
 static int boot_entry_show(const BootEntry *e, bool show_as_default) {
         assert(e);
 
-        printf("        title: %s%s%s%s%s%s\n",
+        printf("        title: %s%s%s%s%s%s\n"
+               "         type: %s\n",
                ansi_highlight(),
                boot_entry_title(e),
                ansi_normal(),
                ansi_highlight_green(),
                show_as_default ? " (default)" : "",
-               ansi_normal());
+               ansi_normal(),
+               boot_entry_type_to_string(e->type));
 
         if (e->id)
                 printf("           id: %s\n", e->id);
@@ -1173,7 +1175,6 @@ static int verb_status(int argc, char *argv[], void *userdata) {
 
 static int verb_list(int argc, char *argv[], void *userdata) {
         _cleanup_(boot_config_free) BootConfig config = {};
-        _cleanup_free_ char **found_by_loader = NULL;
         int r;
 
         /* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
@@ -1196,9 +1197,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
-        r = efi_loader_get_entries(&found_by_loader);
-        if (r < 0 && !IN_SET(r, -ENOENT, -EOPNOTSUPP))
-                log_debug_errno(r, "Failed to acquire boot loader discovered entries: %m");
+        (void) boot_entries_augment_from_loader(&config, false);
 
         if (config.n_entries == 0)
                 log_info("No boot loader entries found.");
@@ -1214,21 +1213,11 @@ static int verb_list(int argc, char *argv[], void *userdata) {
                         if (r < 0)
                                 return r;
 
-                        puts("");
-
-                        strv_remove(found_by_loader, config.entries[n].id);
+                        if (n+1 < config.n_entries)
+                                putchar('\n');
                 }
         }
 
-        if (!strv_isempty(found_by_loader)) {
-                char **i;
-
-                printf("Automatic/Other Entries Found by Boot Loader:\n\n");
-
-                STRV_FOREACH(i, found_by_loader)
-                        puts(*i);
-        }
-
         return 0;
 }
 
index 0904cc09c020e8ec536d2d9c30568d365234601f..0eb336cf03d1563cb5662fd4ad9ca81478bec838 100644 (file)
@@ -55,7 +55,7 @@ static int property_get_exit_status_set(
                 return r;
 
         SET_FOREACH(id, status_set->status, i) {
-                int val = PTR_TO_INT(id);
+                int32_t val = PTR_TO_INT(id);
 
                 if (val < 0 || val > 255)
                         continue;
@@ -74,10 +74,10 @@ static int property_get_exit_status_set(
                 return r;
 
         SET_FOREACH(id, status_set->signal, i) {
-                int val = PTR_TO_INT(id);
+                int32_t val = PTR_TO_INT(id);
                 const char *str;
 
-                str = signal_to_string(val);
+                str = signal_to_string((int) val);
                 if (!str)
                         continue;
 
@@ -151,7 +151,7 @@ static int bus_set_transient_exit_status(
                 UnitWriteFlags flags,
                 sd_bus_error *error) {
 
-        const int *status, *signal;
+        const int32_t *status, *signal;
         size_t sz_status, sz_signal, i;
         int r;
 
@@ -171,6 +171,9 @@ static int bus_set_transient_exit_status(
         if (r < 0)
                 return r;
 
+        sz_status /= sizeof(int32_t);
+        sz_signal /= sizeof(int32_t);
+
         if (sz_status == 0 && sz_signal == 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) {
                 exit_status_set_free(status_set);
                 unit_write_settingf(u, flags, name, "%s=", name);
@@ -179,34 +182,34 @@ static int bus_set_transient_exit_status(
 
         for (i = 0; i < sz_status; i++) {
                 if (status[i] < 0 || status[i] > 255)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid status code in %s: %i", name, status[i]);
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid status code in %s: %"PRIi32, name, status[i]);
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         r = set_ensure_allocated(&status_set->status, NULL);
                         if (r < 0)
                                 return r;
 
-                        r = set_put(status_set->status, INT_TO_PTR(status[i]));
+                        r = set_put(status_set->status, INT_TO_PTR((int) status[i]));
                         if (r < 0)
                                 return r;
 
-                        unit_write_settingf(u, flags, name, "%s=%i", name, status[i]);
+                        unit_write_settingf(u, flags, name, "%s=%"PRIi32, name, status[i]);
                 }
         }
 
         for (i = 0; i < sz_signal; i++) {
                 const char *str;
 
-                str = signal_to_string(signal[i]);
+                str = signal_to_string((int) signal[i]);
                 if (!str)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal in %s: %i", name, signal[i]);
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal in %s: %"PRIi32, name, signal[i]);
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         r = set_ensure_allocated(&status_set->signal, NULL);
                         if (r < 0)
                                 return r;
 
-                        r = set_put(status_set->signal, INT_TO_PTR(signal[i]));
+                        r = set_put(status_set->signal, INT_TO_PTR((int) signal[i]));
                         if (r < 0)
                                 return r;
 
index 17c2003c8fbb50c1763c2becd286916453c317f3..28ae6070a60d0a0cbd8ec184d99322e6ebbbe2f6 100644 (file)
@@ -1674,9 +1674,17 @@ static int bus_unit_set_transient_property(
                         return r;
 
                 STRV_FOREACH(p, l) {
+                        path_simplify(*p, true);
+
                         if (!path_is_absolute(*p))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p);
 
+                        if (!path_is_valid(*p))
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s has invalid length: %s", name, *p);
+
+                        if (!path_is_normalized(*p))
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p);
+
                         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE);
                                 if (r < 0)
index b006add40513e7c3e19d1192468a6a44af5c0e1f..a979caf21ce5b289393dc098bf61175f990c26ce 100644 (file)
@@ -17,6 +17,7 @@
 #include "stat-util.h"
 #include "string-util.h"
 #include "swap.h"
+#include "udev-util.h"
 #include "unit-name.h"
 #include "unit.h"
 
@@ -729,6 +730,9 @@ static bool device_is_ready(sd_device *dev) {
 
         assert(dev);
 
+        if (device_is_renaming(dev) > 0)
+                return false;
+
         if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0)
                 return true;
 
index 39d9f07518be500a829ad43997ee81c1cfb40eae..3f784dd1797ae42f3d11f213225eb858719fad32 100644 (file)
@@ -4567,11 +4567,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
                 else
                         fprintf(f, "%d\n", c->syscall_errno);
         }
-
-        if (c->apparmor_profile)
-                fprintf(f,
-                        "%sAppArmorProfile: %s%s\n",
-                        prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
 }
 
 bool exec_context_maintains_privileges(const ExecContext *c) {
index a4efd309003f5bd70ce567a5b298a2ea6cca4108..084c61d9820e1c6745445f3797992df3644a277a 100644 (file)
@@ -2512,6 +2512,8 @@ int config_parse_unit_condition_null(
         assert(rvalue);
         assert(data);
 
+        log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue);
+
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
                 *list = condition_free_list(*list);
index 88fb093732b6bb464c4adb6f6e0733cc0f92ab62..86ab35d818d2c032cae4ff5da646d380d22bbc0f 100644 (file)
@@ -1,6 +1,17 @@
 # SPDX-License-Identifier: LGPL-2.1+
 
-libcore_la_sources = '''
+libcore_shared_sources = '''
+        killall.c
+        killall.h
+        loopback-setup.c
+        loopback-setup.h
+        machine-id-setup.c
+        machine-id-setup.h
+        mount-setup.c
+        mount-setup.h
+'''.split()
+
+libcore_sources = '''
         audit-fd.c
         audit-fd.h
         automount.c
@@ -69,8 +80,6 @@ libcore_la_sources = '''
         job.h
         kill.c
         kill.h
-        killall.c
-        killall.h
         kmod-setup.c
         kmod-setup.h
         load-dropin.c
@@ -79,14 +88,8 @@ libcore_la_sources = '''
         load-fragment.h
         locale-setup.c
         locale-setup.h
-        loopback-setup.c
-        loopback-setup.h
-        machine-id-setup.c
-        machine-id-setup.h
         manager.c
         manager.h
-        mount-setup.c
-        mount-setup.h
         mount.c
         mount.h
         namespace.c
@@ -144,12 +147,22 @@ load_fragment_gperf_nulstr_c = custom_target(
         command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
         capture : true)
 
+# A convenience library to share code with other binaries:
+# systemd-shutdown, systemd-remount-fs, systemd-machine-id-setup, â€¦
+libcore_shared = static_library(
+        'core-shared',
+        libcore_shared_sources,
+        include_directories : includes,
+        dependencies : [versiondep,
+                        libmount])
+
 libcore = static_library(
         'core',
-        libcore_la_sources,
+        libcore_sources,
         load_fragment_gperf_c,
         load_fragment_gperf_nulstr_c,
         include_directories : includes,
+        link_whole : libcore_shared,
         dependencies : [versiondep,
                         threads,
                         librt,
@@ -163,16 +176,6 @@ libcore = static_library(
 
 systemd_sources = files('main.c')
 
-systemd_shutdown_sources = files('''
-        shutdown.c
-        umount.c
-        umount.h
-        mount-setup.c
-        mount-setup.h
-        killall.c
-        killall.h
-'''.split())
-
 in_files = [['macros.systemd',   rpmmacrosdir],
             ['system.conf',      pkgsysconfdir],
             ['systemd.pc',       pkgconfigdatadir],
index f6a9d30ab5280158fd7514f19b8b05c1803f157a..5d1ddd7620c9666e751bbb0b11360d602a3095b9 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 prefix=@prefix@
-rootprefix=@rootprefix@
+rootprefix=@rootprefix_noslash@
 sysconfdir=@sysconfdir@
 systemdutildir=${rootprefix}/lib/systemd
 systemdsystemunitdir=${rootprefix}/lib/systemd/system
index 4e6323d1bdf3a76e13df8e5af2e62eea22d15f1f..185ec3f6a7ad951bfde2a759410862b1902fcced 100644 (file)
@@ -4609,7 +4609,7 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
         if (!p)
                 return -ENOMEM;
 
-        path = path_simplify(p, false);
+        path = path_simplify(p, true);
 
         if (!path_is_normalized(path))
                 return -EPERM;
diff --git a/src/fuzz/fuzz-bus-label.c b/src/fuzz/fuzz-bus-label.c
new file mode 100644 (file)
index 0000000..46a3d23
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "bus-label.h"
+#include "fuzz.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        _cleanup_free_ char *unescaped = NULL, *escaped = NULL;
+
+        unescaped = bus_label_unescape_n((const char*)data, size);
+        assert_se(unescaped != NULL);
+        escaped = bus_label_escape(unescaped);
+        assert_se(escaped != NULL);
+
+        return 0;
+}
index c9bc2b381553d95431691659d0f431529e4fd2ae..6d887eaf1f8d1c07baa95b7312621053699af791 100644 (file)
@@ -49,6 +49,9 @@ static void fuzz_client(const uint8_t *data, size_t size, bool is_information_re
 }
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        if (size > 65536)
+                return 0;
+
         /* This triggers client_receive_advertise */
         fuzz_client(data, size, false);
 
diff --git a/src/fuzz/fuzz-dhcp6-client.options b/src/fuzz/fuzz-dhcp6-client.options
new file mode 100644 (file)
index 0000000..678d526
--- /dev/null
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65536
diff --git a/src/fuzz/fuzz-env-file.c b/src/fuzz/fuzz-env-file.c
new file mode 100644 (file)
index 0000000..51df1aa
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "env-file.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "strv.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_strv_free_ char **rl = NULL, **rlp =  NULL;
+
+        if (size == 0)
+                return 0;
+
+        f = fmemopen((char*) data, size, "re");
+        assert_se(f);
+
+        /* We don't want to fill the logs with messages about parse errors.
+         * Disable most logging if not running standalone */
+        if (!getenv("SYSTEMD_LOG_LEVEL"))
+                log_set_max_level(LOG_CRIT);
+
+        (void) load_env_file(f, NULL, &rl);
+        assert_se(fseek(f, 0, SEEK_SET) == 0);
+        (void) load_env_file_pairs(f, NULL, &rlp);
+
+        return 0;
+}
diff --git a/src/fuzz/fuzz-hostname-util.c b/src/fuzz/fuzz-hostname-util.c
new file mode 100644 (file)
index 0000000..deaf811
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "hostname-util.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_free_ char *ret = NULL;
+
+        if (size == 0)
+                return 0;
+
+        f = fmemopen((char*) data, size, "re");
+        assert_se(f);
+
+        /* We don't want to fill the logs with messages about parse errors.
+         * Disable most logging if not running standalone */
+        if (!getenv("SYSTEMD_LOG_LEVEL"))
+                log_set_max_level(LOG_CRIT);
+
+        (void) read_etc_hostname_stream(f, &ret);
+
+        return 0;
+}
diff --git a/src/fuzz/fuzz-nspawn-settings.c b/src/fuzz/fuzz-nspawn-settings.c
new file mode 100644 (file)
index 0000000..6c81eb7
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "nspawn-settings.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_(settings_freep) Settings *s = NULL;
+
+        if (size == 0)
+                return 0;
+
+        f = fmemopen((char*) data, size, "re");
+        assert_se(f);
+
+        /* We don't want to fill the logs with messages about parse errors.
+         * Disable most logging if not running standalone */
+        if (!getenv("SYSTEMD_LOG_LEVEL"))
+                log_set_max_level(LOG_CRIT);
+
+        (void) settings_load(f, "/dev/null", &s);
+
+        return 0;
+}
index 5138a2c4165303adfd0b84c5c58b0499bd7dd561..4a242f8a6ce17917c2e656612ce6ca8a7ea50e75 100644 (file)
@@ -112,4 +112,21 @@ fuzzers += [
         [['src/fuzz/fuzz-compress.c'],
          [libshared],
          []],
+
+        [['src/fuzz/fuzz-bus-label.c'],
+         [libshared],
+         []],
+
+        [['src/fuzz/fuzz-env-file.c'],
+         [libshared],
+         []],
+
+        [['src/fuzz/fuzz-hostname-util.c'],
+         [libshared],
+         []],
+
+        [['src/fuzz/fuzz-nspawn-settings.c'],
+         [libshared,
+          libnspawn_core],
+         []],
 ]
index 89f03010d1349a972e9097f1b12b32d659d0936c..1f63ebb7619448307b24bf31f50bbe7ee5ea514f 100644 (file)
@@ -15,6 +15,7 @@
 #include "import-common.h"
 #include "os-util.h"
 #include "process-util.h"
+#include "selinux-util.h"
 #include "signal-util.h"
 #include "tmpfile-util.h"
 #include "util.h"
@@ -62,6 +63,7 @@ int import_make_read_only(const char *path) {
 
 int import_fork_tar_x(const char *path, pid_t *ret) {
         _cleanup_close_pair_ int pipefd[2] = { -1, -1 };
+        bool use_selinux;
         pid_t pid;
         int r;
 
@@ -71,6 +73,8 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
         if (pipe2(pipefd, O_CLOEXEC) < 0)
                 return log_error_errno(errno, "Failed to create pipe for tar: %m");
 
+        use_selinux = mac_selinux_use();
+
         r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
         if (r < 0)
                 return r;
@@ -100,7 +104,8 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
                 if (r < 0)
                         log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
 
-                execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", NULL);
+                execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*",
+                       use_selinux ? "--selinux" : "--no-selinux", NULL);
                 log_error_errno(errno, "Failed to execute tar: %m");
                 _exit(EXIT_FAILURE);
         }
@@ -112,6 +117,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
 
 int import_fork_tar_c(const char *path, pid_t *ret) {
         _cleanup_close_pair_ int pipefd[2] = { -1, -1 };
+        bool use_selinux;
         pid_t pid;
         int r;
 
@@ -121,6 +127,8 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
         if (pipe2(pipefd, O_CLOEXEC) < 0)
                 return log_error_errno(errno, "Failed to create pipe for tar: %m");
 
+        use_selinux = mac_selinux_use();
+
         r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
         if (r < 0)
                 return r;
@@ -144,7 +152,8 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
                 if (r < 0)
                         log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
 
-                execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", ".", NULL);
+                execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*",
+                       use_selinux ? "--selinux" : "--no-selinux", ".", NULL);
                 log_error_errno(errno, "Failed to execute tar: %m");
                 _exit(EXIT_FAILURE);
         }
index 802c3ea6089a88018f2066e919d14e3d35f588bb..2321a91e7bd57d0e1a6b0642ca5ab9b2ec9f284e 100644 (file)
@@ -265,6 +265,7 @@ static int request_handler(
         const char *header;
         int r, code, fd;
         _cleanup_free_ char *hostname = NULL;
+        bool chunked = false;
         size_t len;
 
         assert(connection);
@@ -290,21 +291,33 @@ static int request_handler(
                 return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
                                    "Content-Type: application/vnd.fdo.journal is required.");
 
+        header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Transfer-Encoding");
+        if (header) {
+                if (!strcaseeq(header, "chunked"))
+                        return mhd_respondf(connection, 0, MHD_HTTP_BAD_REQUEST,
+                                            "Unsupported Transfer-Encoding type: %s", header);
+
+                chunked = true;
+        }
+
         header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length");
-        if (!header)
-                return mhd_respond(connection, MHD_HTTP_LENGTH_REQUIRED,
-                                   "Content-Length header is required.");
-        r = safe_atozu(header, &len);
-        if (r < 0)
-                return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED,
-                                    "Content-Length: %s cannot be parsed: %m", header);
-
-        if (len > ENTRY_SIZE_MAX)
-                /* When serialized, an entry of maximum size might be slightly larger,
-                 * so this does not correspond exactly to the limit in journald. Oh well.
-                 */
-                return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE,
-                                    "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX);
+        if (header) {
+                if (chunked)
+                        return mhd_respond(connection, MHD_HTTP_BAD_REQUEST,
+                                           "Content-Length must not specified when Transfer-Encoding type is 'chuncked'");
+
+                r = safe_atozu(header, &len);
+                if (r < 0)
+                        return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED,
+                                            "Content-Length: %s cannot be parsed: %m", header);
+
+                if (len > ENTRY_SIZE_MAX)
+                        /* When serialized, an entry of maximum size might be slightly larger,
+                         * so this does not correspond exactly to the limit in journald. Oh well.
+                         */
+                        return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE,
+                                            "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX);
+        }
 
         {
                 const union MHD_ConnectionInfo *ci;
index 4062f12c2dfc574eae5d602602d180f29d8e5252..ccee950d1d65df77cb29b91b7289e67e0b81051f 100644 (file)
@@ -33,7 +33,7 @@ const char * const catalog_file_dirs[] = {
         NULL
 };
 
-#define CATALOG_SIGNATURE (uint8_t[]) { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' }
+#define CATALOG_SIGNATURE { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' }
 
 typedef struct CatalogHeader {
         uint8_t signature[8];  /* "RHHHKSLP" */
@@ -209,34 +209,38 @@ int catalog_file_lang(const char* filename, char **lang) {
         return 1;
 }
 
-static int catalog_entry_lang(const char* filename, int line,
-                              const char* t, const char* deflang, char **lang) {
+static int catalog_entry_lang(
+                const char* filename,
+                unsigned line,
+                const char* t,
+                const char* deflang,
+                char **ret) {
+
         size_t c;
+        char *z;
 
         c = strlen(t);
         if (c < 2)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "[%s:%u] Language too short.",
-                                       filename, line);
+                                       "[%s:%u] Language too short.", filename, line);
         if (c > 31)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "[%s:%u] language too long.", filename,
-                                       line);
+                                       "[%s:%u] language too long.", filename, line);
 
         if (deflang) {
                 if (streq(t, deflang)) {
-                        log_warning("[%s:%u] language specified unnecessarily",
-                                    filename, line);
+                        log_warning("[%s:%u] language specified unnecessarily", filename, line);
                         return 0;
-                } else
-                        log_warning("[%s:%u] language differs from default for file",
-                                    filename, line);
+                }
+
+                log_warning("[%s:%u] language differs from default for file", filename, line);
         }
 
-        *lang = strdup(t);
-        if (!*lang)
-                        return -ENOMEM;
+        z = strdup(t);
+        if (!z)
+                return -ENOMEM;
 
+        *ret = z;
         return 0;
 }
 
@@ -367,32 +371,33 @@ int catalog_import_file(Hashmap *h, const char *path) {
         return 0;
 }
 
-static int64_t write_catalog(const char *database, struct strbuf *sb,
-                             CatalogItem *items, size_t n) {
-        CatalogHeader header;
+static int64_t write_catalog(
+                const char *database,
+                struct strbuf *sb,
+                CatalogItem *items,
+                size_t n) {
+
         _cleanup_fclose_ FILE *w = NULL;
-        int r;
-        _cleanup_free_ char *d, *p = NULL;
+        _cleanup_free_ char *p = NULL;
+        CatalogHeader header;
         size_t k;
+        int r;
 
-        d = dirname_malloc(database);
-        if (!d)
-                return log_oom();
-
-        r = mkdir_p(d, 0775);
+        r = mkdir_parents(database, 0755);
         if (r < 0)
-                return log_error_errno(r, "Recursive mkdir %s: %m", d);
+                return log_error_errno(r, "Failed to create parent directories of %s: %m", database);
 
         r = fopen_temporary(database, &w, &p);
         if (r < 0)
                 return log_error_errno(r, "Failed to open database for writing: %s: %m",
                                        database);
 
-        zero(header);
-        memcpy(header.signature, CATALOG_SIGNATURE, sizeof(header.signature));
-        header.header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8));
-        header.catalog_item_size = htole64(sizeof(CatalogItem));
-        header.n_items = htole64(n);
+        header = (CatalogHeader) {
+                .signature = CATALOG_SIGNATURE,
+                .header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8)),
+                .catalog_item_size = htole64(sizeof(CatalogItem)),
+                .n_items = htole64(n),
+        };
 
         r = -EIO;
 
@@ -420,7 +425,7 @@ static int64_t write_catalog(const char *database, struct strbuf *sb,
                 goto error;
         }
 
-        fchmod(fileno(w), 0644);
+        (void) fchmod(fileno(w), 0644);
 
         if (rename(p, database) < 0) {
                 r = log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database);
@@ -503,10 +508,10 @@ int catalog_update(const char* database, const char* root, const char* const* di
 }
 
 static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) {
+        _cleanup_close_ int fd = -1;
         const CatalogHeader *h;
-        int fd;
-        void *p;
         struct stat st;
+        void *p;
 
         assert(_fd);
         assert(_st);
@@ -516,35 +521,28 @@ static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p
         if (fd < 0)
                 return -errno;
 
-        if (fstat(fd, &st) < 0) {
-                safe_close(fd);
+        if (fstat(fd, &st) < 0)
                 return -errno;
-        }
 
-        if (st.st_size < (off_t) sizeof(CatalogHeader)) {
-                safe_close(fd);
+        if (st.st_size < (off_t) sizeof(CatalogHeader))
                 return -EINVAL;
-        }
 
         p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
-        if (p == MAP_FAILED) {
-                safe_close(fd);
+        if (p == MAP_FAILED)
                 return -errno;
-        }
 
         h = p;
-        if (memcmp(h->signature, CATALOG_SIGNATURE, sizeof(h->signature)) != 0 ||
+        if (memcmp(h->signature, (const uint8_t[]) CATALOG_SIGNATURE, sizeof(h->signature)) != 0 ||
             le64toh(h->header_size) < sizeof(CatalogHeader) ||
             le64toh(h->catalog_item_size) < sizeof(CatalogItem) ||
             h->incompatible_flags != 0 ||
             le64toh(h->n_items) <= 0 ||
             st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) {
-                safe_close(fd);
                 munmap(p, st.st_size);
                 return -EBADMSG;
         }
 
-        *_fd = fd;
+        *_fd = TAKE_FD(fd);
         *_st = st;
         *_p = p;
 
index 04bf64cce5f2f702423094f31e17021128c73732..0c1ff34e5de339b22de17c1381fa0fa5ccee5293 100644 (file)
@@ -12,6 +12,7 @@
 #include "siphash24.h"
 #include "sparse-endian.h"
 #include "stdio-util.h"
+#include "udev-util.h"
 #include "virt.h"
 
 #define SYSTEMD_PEN    43793
@@ -182,6 +183,13 @@ int dhcp_identifier_set_iaid(
                                 /* not yet ready */
                                 return -EBUSY;
 
+                        r = device_is_renaming(device);
+                        if (r < 0)
+                                return r;
+                        if (r > 0)
+                                /* device is under renaming */
+                                return -EBUSY;
+
                         name = net_get_name(device);
                 }
         }
index b6c896f0a1a150c73a8912249cbcb20a5d32eab7..7406f94ce06ec492da7996f2bd3b36a49eb74e3f 100644 (file)
@@ -15,6 +15,7 @@
 #include "lldp-network.h"
 #include "macro.h"
 #include "string-util.h"
+#include "tests.h"
 
 #define TEST_LLDP_PORT "em1"
 #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
@@ -365,7 +366,7 @@ static void test_multiple_neighbors_sorted(sd_event *e) {
 int main(int argc, char *argv[]) {
         _cleanup_(sd_event_unrefp) sd_event *e = NULL;
 
-        log_set_max_level(LOG_DEBUG);
+        test_setup_logging(LOG_DEBUG);
 
         /* LLDP reception tests */
         assert_se(sd_event_new(&e) == 0);
index 04864d4df01b8db6697749bfbda525f312270117..63f14047583d05a5df840039c48b16ce608168b9 100644 (file)
@@ -13,7 +13,6 @@
 #include "hashmap.h"
 #include "list.h"
 #include "prioq.h"
-#include "refcnt.h"
 #include "socket-util.h"
 #include "util.h"
 
@@ -171,15 +170,7 @@ enum bus_auth {
 };
 
 struct sd_bus {
-        /* We use atomic ref counting here since sd_bus_message
-           objects retain references to their originating sd_bus but
-           we want to allow them to be processed in a different
-           thread. We won't provide full thread safety, but only the
-           bare minimum that makes it possible to use sd_bus and
-           sd_bus_message objects independently and on different
-           threads as long as each object is used only once at the
-           same time. */
-        RefCount n_ref;
+        unsigned n_ref;
 
         enum bus_state state;
         int input_fd, output_fd;
index 69f15199763e8db965998ee8712981310c56746f..ba791db4f2e2225729be7114a4acadb364634581 100644 (file)
@@ -236,7 +236,7 @@ _public_ int sd_bus_new(sd_bus **ret) {
                 return -ENOMEM;
 
         *b = (sd_bus) {
-                .n_ref = REFCNT_INIT,
+                .n_ref = 1,
                 .input_fd = -1,
                 .output_fd = -1,
                 .inotify_fd = -1,
@@ -1585,7 +1585,7 @@ void bus_enter_closing(sd_bus *bus) {
         bus_set_state(bus, BUS_CLOSING);
 }
 
-DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
 
 _public_ int sd_bus_is_open(sd_bus *bus) {
         assert_return(bus, -EINVAL);
index c58c52a778bf6b6843aa87d82cfdfa6863f7e5f6..70a6df10f96e2f34fd0050defbe39c0f2e56e7a7 100644 (file)
@@ -4,6 +4,7 @@
 #include "log.h"
 #include "string-util.h"
 #include "strv.h"
+#include "tests.h"
 
 static void test_one_address(sd_bus *b,
                              const char *host,
@@ -59,9 +60,7 @@ static void test_bus_set_address_system_remote(char **args) {
 }
 
 int main(int argc, char *argv[]) {
-        log_set_max_level(LOG_INFO);
-        log_parse_environment();
-        log_open();
+        test_setup_logging(LOG_INFO);
 
         test_bus_set_address_system_remote(argv + 1);
 
index bea722ba06ed3edb3a079b360ab047136ef62a38..99d335e3fceb852a8556f5a68e7046da84a14a82 100644 (file)
@@ -7,7 +7,6 @@
 #include "bus-internal.h"
 #include "bus-message.h"
 #include "bus-util.h"
-#include "refcnt.h"
 #include "tests.h"
 
 static bool use_system_bus = false;
@@ -16,7 +15,7 @@ static void test_bus_new(void) {
         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
 
         assert_se(sd_bus_new(&bus) == 0);
-        printf("after new: refcount %u\n", REFCNT_GET(bus->n_ref));
+        assert_se(bus->n_ref == 1);
 }
 
 static int test_bus_open(void) {
@@ -32,7 +31,7 @@ static int test_bus_open(void) {
         }
 
         assert_se(r >= 0);
-        printf("after open: refcount %u\n", REFCNT_GET(bus->n_ref));
+        assert_se(bus->n_ref >= 1); /* we send a hello message when opening, so the count is above 1 */
 
         return 0;
 }
@@ -45,10 +44,10 @@ static void test_bus_new_method_call(void) {
 
         assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path", "an.interface.name", "AMethodName") >= 0);
 
-        printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref));
-
+        assert_se(m->n_ref == 1); /* We hold the only reference to the message */
+        assert_se(bus->n_ref >= 2);
         sd_bus_flush_close_unref(bus);
-        printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
+        assert_se(m->n_ref == 1);
 }
 
 static void test_bus_new_signal(void) {
@@ -59,10 +58,10 @@ static void test_bus_new_signal(void) {
 
         assert_se(sd_bus_message_new_signal(bus, &m, "/an/object/path", "an.interface.name", "Name") >= 0);
 
-        printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref));
-
+        assert_se(m->n_ref == 1); /* We hold the only reference to the message */
+        assert_se(bus->n_ref >= 2);
         sd_bus_flush_close_unref(bus);
-        printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
+        assert_se(m->n_ref == 1);
 }
 
 int main(int argc, char **argv) {
index 940dbfe0e7e82a5ccb518876168fb51e0c3812bc..9c8e93e897a01322eef8c06f457fd7948b9c1922 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "bus-introspect.h"
 #include "log.h"
+#include "tests.h"
 
 static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
         return -EINVAL;
@@ -29,7 +30,7 @@ static const sd_bus_vtable vtable[] = {
 int main(int argc, char *argv[]) {
         struct introspect intro;
 
-        log_set_max_level(LOG_DEBUG);
+        test_setup_logging(LOG_DEBUG);
 
         assert_se(introspect_begin(&intro, false) >= 0);
 
index 70901c30b0e31b9416af977b4cc59b0e1fce03dd..f6506fb93f8887b5953edfbe08702e252a987eb5 100644 (file)
@@ -1,10 +1,10 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
+#include "sd-bus.h"
 
 #include "main-func.h"
-#include "sd-bus.h"
 #include "tests.h"
 
-static int run(int argc, char *argv[]) {
+static int test_ref_unref(void) {
         sd_bus_message *m = NULL;
         sd_bus *bus = NULL;
         int r;
@@ -41,4 +41,16 @@ static int run(int argc, char *argv[]) {
         return 0;
 }
 
+static int run(int argc, char *argv[]) {
+        int r;
+
+        test_setup_logging(LOG_INFO);
+
+        r = test_ref_unref();
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 DEFINE_MAIN_FUNCTION(run);
index 4b3da30079764cf66ea5500b120a74530e0cf6b1..2723866e08472c837466dd8da108318e34247517 100644 (file)
@@ -16,6 +16,7 @@
 #include "socket-util.h"
 #include "string-util.h"
 #include "tmpfile-util.h"
+#include "tests.h"
 
 static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
         log_info("Got Foobar() call.");
@@ -198,7 +199,7 @@ int main(int argc, char *argv[]) {
         pthread_t server, client1, client2;
         char *path;
 
-        log_set_max_level(LOG_DEBUG);
+        test_setup_logging(LOG_DEBUG);
 
         /* We use /dev/shm here rather than /tmp, since some weird distros might set up /tmp as some weird fs that
          * doesn't support inotify properly. */
index 3ffca35cbef610381a81d83a0be0685c7117e252..4d03d09cd68887a11bec0aac4ab0c6606b88819d 100644 (file)
@@ -81,19 +81,6 @@ struct sd_device {
         bool db_persist:1; /* don't clean up the db when switching from initrd to real root */
 };
 
-typedef enum DeviceAction {
-        DEVICE_ACTION_ADD,
-        DEVICE_ACTION_REMOVE,
-        DEVICE_ACTION_CHANGE,
-        DEVICE_ACTION_MOVE,
-        DEVICE_ACTION_ONLINE,
-        DEVICE_ACTION_OFFLINE,
-        DEVICE_ACTION_BIND,
-        DEVICE_ACTION_UNBIND,
-        _DEVICE_ACTION_MAX,
-        _DEVICE_ACTION_INVALID = -1,
-} DeviceAction;
-
 int device_new_aux(sd_device **ret);
 int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db);
 int device_add_property_internal(sd_device *device, const char *key, const char *value);
@@ -108,6 +95,3 @@ int device_set_devnum(sd_device *device, const char *major, const char *minor);
 int device_set_subsystem(sd_device *device, const char *_subsystem);
 int device_set_driver(sd_device *device, const char *_driver);
 int device_set_usec_initialized(sd_device *device, usec_t when);
-
-DeviceAction device_action_from_string(const char *s) _pure_;
-const char *device_action_to_string(DeviceAction a) _const_;
index 76267a1e748d8f48a50453bd1b9d9feda19347ef..0d0bdca800feb9d838b4bf420cfd4eed4d4c4314 100644 (file)
@@ -18,7 +18,6 @@
 #include "mkdir.h"
 #include "parse-util.h"
 #include "path-util.h"
-#include "refcnt.h"
 #include "set.h"
 #include "string-table.h"
 #include "string-util.h"
index 49e02db81edcc7a2f5cf7df250b5bab47d45e325..46e10105c9808a66f80c15d2a78e46a3f3cae979 100644 (file)
@@ -8,6 +8,8 @@
 
 #include "sd-device.h"
 
+#include "macro.h"
+
 int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len);
 int device_new_from_strv(sd_device **ret, char **strv);
 int device_new_from_stat_rdev(sd_device **ret, const struct stat *st);
@@ -55,3 +57,19 @@ int device_read_db_internal(sd_device *device, bool force);
 static inline int device_read_db(sd_device *device) {
         return device_read_db_internal(device, false);
 }
+
+typedef enum DeviceAction {
+        DEVICE_ACTION_ADD,
+        DEVICE_ACTION_REMOVE,
+        DEVICE_ACTION_CHANGE,
+        DEVICE_ACTION_MOVE,
+        DEVICE_ACTION_ONLINE,
+        DEVICE_ACTION_OFFLINE,
+        DEVICE_ACTION_BIND,
+        DEVICE_ACTION_UNBIND,
+        _DEVICE_ACTION_MAX,
+        _DEVICE_ACTION_INVALID = -1,
+} DeviceAction;
+
+DeviceAction device_action_from_string(const char *s) _pure_;
+const char *device_action_to_string(DeviceAction a) _const_;
index 233944c0782013cc6d8764f574c2a11caa28d8fe..d8c37c3fd4735fbb7ae7a95a6d30c19f58776c66 100644 (file)
 #include "hashmap.h"
 #include "hwdb-internal.h"
 #include "hwdb-util.h"
-#include "refcnt.h"
 #include "string-util.h"
 #include "util.h"
 
 struct sd_hwdb {
-        RefCount n_ref;
+        unsigned n_ref;
 
         FILE *f;
         struct stat st;
@@ -316,27 +315,27 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) {
         if (!hwdb)
                 return -ENOMEM;
 
-        hwdb->n_ref = REFCNT_INIT;
+        hwdb->n_ref = 1;
 
         /* find hwdb.bin in hwdb_bin_paths */
         NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) {
+                log_debug("Trying to open \"%s\"...", hwdb_bin_path);
                 hwdb->f = fopen(hwdb_bin_path, "re");
                 if (hwdb->f)
                         break;
-                else if (errno == ENOENT)
-                        continue;
-                else
+                if (errno != ENOENT)
                         return log_debug_errno(errno, "Failed to open %s: %m", hwdb_bin_path);
         }
 
-        if (!hwdb->f) {
-                log_debug("hwdb.bin does not exist, please run 'systemd-hwdb update'");
-                return -ENOENT;
-        }
+        if (!hwdb->f)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
+                                       "hwdb.bin does not exist, please run 'systemd-hwdb update'");
 
-        if (fstat(fileno(hwdb->f), &hwdb->st) < 0 ||
-            (size_t) hwdb->st.st_size < offsetof(struct trie_header_f, strings_len) + 8)
-                return log_debug_errno(errno, "Failed to read %s: %m", hwdb_bin_path);
+        if (fstat(fileno(hwdb->f), &hwdb->st) < 0)
+                return log_debug_errno(errno, "Failed to stat %s: %m", hwdb_bin_path);
+        if (hwdb->st.st_size < (off_t) offsetof(struct trie_header_f, strings_len) + 8)
+                return log_debug_errno(SYNTHETIC_ERRNO(EIO),
+                                       "File %s is too short: %m", hwdb_bin_path);
 
         hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0);
         if (hwdb->map == MAP_FAILED)
@@ -370,7 +369,7 @@ static sd_hwdb *hwdb_free(sd_hwdb *hwdb) {
         return mfree(hwdb);
 }
 
-DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free)
 
 bool hwdb_validate(sd_hwdb *hwdb) {
         bool found = false;
@@ -383,12 +382,11 @@ bool hwdb_validate(sd_hwdb *hwdb) {
                 return false;
 
         /* if hwdb.bin doesn't exist anywhere, we need to update */
-        NULSTR_FOREACH(p, hwdb_bin_paths) {
+        NULSTR_FOREACH(p, hwdb_bin_paths)
                 if (stat(p, &st) >= 0) {
                         found = true;
                         break;
                 }
-        }
         if (!found)
                 return true;
 
index 98de4f0a8378cfeb100813a1a91d907ee181e22a..a8af3fc63b5289d0e97d00fb795b3680b866f0c7 100644 (file)
@@ -8,7 +8,6 @@
 #include "list.h"
 #include "netlink-types.h"
 #include "prioq.h"
-#include "refcnt.h"
 
 #define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
 
@@ -56,7 +55,7 @@ struct sd_netlink_slot {
 };
 
 struct sd_netlink {
-        RefCount n_ref;
+        unsigned n_ref;
 
         int fd;
 
@@ -114,7 +113,7 @@ struct netlink_container {
 };
 
 struct sd_netlink_message {
-        RefCount n_ref;
+        unsigned n_ref;
 
         sd_netlink *rtnl;
 
index f878fc94714065235775c58fcce0e2a7475c11b3..bf3ac954003b2e386d6145f7ec6f752b3aaf4501 100644 (file)
@@ -12,7 +12,6 @@
 #include "netlink-internal.h"
 #include "netlink-types.h"
 #include "netlink-util.h"
-#include "refcnt.h"
 #include "socket-util.h"
 #include "util.h"
 
@@ -36,7 +35,7 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
         if (!m)
                 return -ENOMEM;
 
-        m->n_ref = REFCNT_INIT;
+        m->n_ref = 1;
         m->protocol = rtnl->protocol;
         m->sealed = false;
 
@@ -96,12 +95,10 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
         return 0;
 }
 
-DEFINE_ATOMIC_REF_FUNC(sd_netlink_message, sd_netlink_message);
+DEFINE_TRIVIAL_REF_FUNC(sd_netlink_message, sd_netlink_message);
 
 sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
-        sd_netlink_message *t;
-
-        while (m && REFCNT_DEC(m->n_ref) == 0) {
+        while (m && --m->n_ref == 0) {
                 unsigned i;
 
                 free(m->hdr);
@@ -109,7 +106,7 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
                 for (i = 0; i <= m->n_containers; i++)
                         free(m->containers[i].attributes);
 
-                t = m;
+                sd_netlink_message *t = m;
                 m = m->next;
                 free(t);
         }
index 432e8e8c06c9b93529751445a58d1678e47bb521..d1c95b260f8f91b275b623a93668f65203a28857 100644 (file)
@@ -14,7 +14,6 @@
 #include "netlink-internal.h"
 #include "netlink-types.h"
 #include "netlink-util.h"
-#include "refcnt.h"
 #include "socket-util.h"
 #include "util.h"
 
index 5ef2ba37809fcc10473f0392df5f3936a0268bbb..803de54712a0099107aed8ca4df2660fce21d113 100644 (file)
@@ -308,6 +308,7 @@ static const NLType rtnl_link_info_data_geneve_types[] = {
 static const NLType rtnl_link_info_data_can_types[] = {
         [IFLA_CAN_BITTIMING]            = { .size = sizeof(struct can_bittiming) },
         [IFLA_CAN_RESTART_MS]           = { .type = NETLINK_TYPE_U32 },
+        [IFLA_CAN_CTRLMODE]             = { .size = sizeof(struct can_ctrlmode) },
 };
 
 /* these strings must match the .kind entries in the kernel */
index 3928dfbabf352c149827a4c19ffa271916974ca5..628ce507a058e0f955333d13f57c6a251e5faa0d 100644 (file)
@@ -13,6 +13,9 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
         assert(ifindex > 0);
         assert(name);
 
+        if (!ifname_valid(name))
+                return -EINVAL;
+
         if (!*rtnl) {
                 r = sd_netlink_open(rtnl);
                 if (r < 0)
index 2d4d00e0eb128571b191f0c1629be9685c4ba215..ccc497de09b78efcee69fbfbf3b9716d6099c35c 100644 (file)
@@ -12,7 +12,6 @@
 #include "netlink-internal.h"
 #include "netlink-types.h"
 #include "netlink-util.h"
-#include "refcnt.h"
 #include "socket-util.h"
 #include "util.h"
 
index d83952d0cc69f0be929eb6f30029cc81ab8b1811..f3e267f00767e03f82befa5619ba1cdfb751f30e 100644 (file)
@@ -28,7 +28,7 @@ static int sd_netlink_new(sd_netlink **ret) {
                 return -ENOMEM;
 
         *rtnl = (sd_netlink) {
-                .n_ref = REFCNT_INIT,
+                .n_ref = 1,
                 .fd = -1,
                 .sockaddr.nl.nl_family = AF_NETLINK,
                 .original_pid = getpid_cached(),
@@ -182,7 +182,7 @@ static sd_netlink *netlink_free(sd_netlink *rtnl) {
         return mfree(rtnl);
 }
 
-DEFINE_ATOMIC_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free);
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free);
 
 static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) {
         assert(rtnl);
index 2f82891d60c0b0d1251c8e3f2bdd97b20c764410..f96f5b07ec7faf8414793006e688e4c5acfa6bc4 100644 (file)
@@ -4,6 +4,7 @@
 #include "keymap-util.h"
 #include "log.h"
 #include "string-util.h"
+#include "tests.h"
 
 static void test_find_language_fallback(void) {
         _cleanup_free_ char *ans = NULL, *ans2 = NULL;
@@ -189,8 +190,7 @@ static void test_x11_convert_to_vconsole(void) {
 }
 
 int main(int argc, char **argv) {
-        log_set_max_level(LOG_DEBUG);
-        log_parse_environment();
+        test_setup_logging(LOG_DEBUG);
 
         test_find_language_fallback();
         test_find_converted_keymap();
index 8049be48c71bf55254a181045b719f4410beb004..a5928b0a4f3915d023270cc502afbfb6924cf31f 100644 (file)
@@ -13,6 +13,10 @@ TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat"
 SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
 SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat"
 SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
+
+# HyperV currently doesn't do DRM, hence we need to synthesize for HyperV's fb device instead
+SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", DRIVERS=="hyperv_fb", TAG+="master-of-seat"
+
 SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat"
 SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
 
index ab1b56201a37be0f0be339721ddb95c26ce8932e..69850724daa7c24c928e2abcf6bb246558663aac 100644 (file)
@@ -755,7 +755,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         if (all || !isempty(s))
-                                bus_print_property_value(name, expected_value, value, "%s", s);
+                                bus_print_property_value(name, expected_value, value, s);
 
                         return 1;
 
@@ -771,7 +771,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                                        "Invalid user ID: " UID_FMT,
                                                        uid);
 
-                        bus_print_property_value(name, expected_value, value, UID_FMT, uid);
+                        bus_print_property_valuef(name, expected_value, value, UID_FMT, uid);
                         return 1;
                 }
                 break;
index b9ea370ec009ab9ccdf95c4440ddc2a8b9e93d9e..13e7d3bcdaf74f9fd81bab4e189bb33b93581fb5 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "alloc-util.h"
 #include "audit-util.h"
+#include "bootspec.h"
 #include "bus-common-errors.h"
 #include "bus-error.h"
 #include "bus-unit-util.h"
@@ -18,6 +19,7 @@
 #include "device-util.h"
 #include "dirent-util.h"
 #include "efivars.h"
+#include "env-util.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio-label.h"
 #include "logind.h"
 #include "missing_capability.h"
 #include "mkdir.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "selinux-util.h"
 #include "sleep-config.h"
 #include "special.h"
+#include "stdio-util.h"
 #include "strv.h"
 #include "terminal-util.h"
 #include "tmpfile-util.h"
@@ -2392,9 +2396,24 @@ static int property_get_reboot_to_firmware_setup(
         assert(reply);
         assert(userdata);
 
-        r = efi_get_reboot_to_firmware();
-        if (r < 0 && r != -EOPNOTSUPP)
-                log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
+        r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+        if (r == -ENXIO) {
+                /* EFI case: let's see what is currently configured in the EFI variables */
+                r = efi_get_reboot_to_firmware();
+                if (r < 0 && r != -EOPNOTSUPP)
+                        log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m");
+        } else if (r < 0)
+                log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+        else if (r > 0) {
+                /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */
+                if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) {
+                        if (errno != ENOENT)
+                                log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m");
+
+                        r = false;
+                } else
+                        r = true;
+        }
 
         return sd_bus_message_append(reply, "b", r > 0);
 }
@@ -2404,8 +2423,9 @@ static int method_set_reboot_to_firmware_setup(
                 void *userdata,
                 sd_bus_error *error) {
 
-        int b, r;
         Manager *m = userdata;
+        bool use_efi;
+        int b, r;
 
         assert(message);
         assert(m);
@@ -2414,6 +2434,29 @@ static int method_set_reboot_to_firmware_setup(
         if (r < 0)
                 return r;
 
+        r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+        if (r == -ENXIO) {
+                /* EFI case: let's see what the firmware supports */
+
+                r = efi_reboot_to_firmware_supported();
+                if (r == -EOPNOTSUPP)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+                if (r < 0)
+                        return r;
+
+                use_efi = true;
+
+        } else if (r <= 0) {
+                /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */
+
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
+        } else
+                /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
+                use_efi = false;
+
         r = bus_verify_polkit_async(message,
                                     CAP_SYS_ADMIN,
                                     "org.freedesktop.login1.set-reboot-to-firmware-setup",
@@ -2427,11 +2470,48 @@ static int method_set_reboot_to_firmware_setup(
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
-        r = efi_set_reboot_to_firmware(b);
+        if (use_efi) {
+                r = efi_set_reboot_to_firmware(b);
+                if (r < 0)
+                        return r;
+        } else {
+                if (b) {
+                        r = touch("/run/systemd/reboot-to-firmware-setup");
+                        if (r < 0)
+                                return r;
+                } else {
+                        if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT)
+                                return -errno;
+                }
+        }
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+static int return_test_polkit(
+                sd_bus_message *message,
+                int capability,
+                const char *action,
+                const char **details,
+                uid_t good_user,
+                sd_bus_error *e) {
+
+        const char *result;
+        bool challenge;
+        int r;
+
+        r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
         if (r < 0)
                 return r;
 
-        return sd_bus_reply_method_return(message, NULL);
+        if (r > 0)
+                result = "yes";
+        else if (challenge)
+                result = "challenge";
+        else
+                result = "no";
+
+        return sd_bus_reply_method_return(message, "s", result);
 }
 
 static int method_can_reboot_to_firmware_setup(
@@ -2439,40 +2519,459 @@ static int method_can_reboot_to_firmware_setup(
                 void *userdata,
                 sd_bus_error *error) {
 
+        Manager *m = userdata;
         int r;
-        bool challenge;
-        const char *result;
+
+        assert(message);
+        assert(m);
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
+        if (r == -ENXIO) {
+                /* EFI case: let's see what the firmware supports */
+
+                r = efi_reboot_to_firmware_supported();
+                if (r < 0) {
+                        if (r != -EOPNOTSUPP)
+                                log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
+
+                        return sd_bus_reply_method_return(message, "s", "na");
+                }
+
+        } else if (r <= 0) {
+                /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */
+
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
+
+                return sd_bus_reply_method_return(message, "s", "na");
+        }
+
+        return return_test_polkit(
+                        message,
+                        CAP_SYS_ADMIN,
+                        "org.freedesktop.login1.set-reboot-to-firmware-setup",
+                        NULL,
+                        UID_INVALID,
+                        error);
+}
+
+static int property_get_reboot_to_boot_loader_menu(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        uint64_t x = UINT64_MAX;
+        int r;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
+        if (r == -ENXIO) {
+                _cleanup_free_ char *v = NULL;
+
+                /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
+                 *
+                 *     1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
+                 *     2. Variable set to "0", boot into boot loader menu is enabled with no timeout (we return 0 to the user)
+                 *     3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
+                 */
+
+                r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
+                if (r < 0) {
+                        if (r != -ENOENT)
+                                log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
+                } else {
+                        uint64_t sec;
+
+                        r = safe_atou64(v, &sec);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
+                        else if (sec > (USEC_INFINITY / USEC_PER_SEC))
+                                log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
+                        else
+                                x = sec * USEC_PER_SEC; /* return in Âµs */
+                }
+
+        } else if (r < 0)
+                log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
+        else if (r > 0) {
+                _cleanup_free_ char *v = NULL;
+
+                /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-menu. */
+
+                r = read_one_line_file("/run/systemd/reboot-to-boot-loader-menu", &v);
+                if (r < 0) {
+                        if (r != -ENOENT)
+                                log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-menu: %m");
+                } else {
+                        r = safe_atou64(v, &x);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to parse /run/systemd/reboot-to-boot-loader-menu: %m");
+                }
+        }
+
+        return sd_bus_message_append(reply, "t", x);
+}
+
+static int method_set_reboot_to_boot_loader_menu(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
         Manager *m = userdata;
+        bool use_efi;
+        uint64_t x;
+        int r;
 
         assert(message);
         assert(m);
 
-        r = efi_reboot_to_firmware_supported();
-        if (r < 0) {
-                if (r != -EOPNOTSUPP)
-                        log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
+        r = sd_bus_message_read(message, "t", &x);
+        if (r < 0)
+                return r;
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
+        if (r == -ENXIO) {
+                uint64_t features;
+
+                /* EFI case: let's see if booting into boot loader menu is supported. */
+
+                r = efi_loader_get_features(&features);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
+                if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
+
+                use_efi = true;
+
+        } else if (r <= 0) {
+                /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to off */
+
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
+
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
+        } else
+                /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */
+                use_efi = false;
+
+        r = bus_verify_polkit_async(message,
+                                    CAP_SYS_ADMIN,
+                                    "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
+                                    NULL,
+                                    false,
+                                    UID_INVALID,
+                                    &m->polkit_registry,
+                                    error);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+        if (use_efi) {
+                if (x == UINT64_MAX)
+                        r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0);
+                else {
+                        char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+                        xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */
+
+                        r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf);
+                }
+                if (r < 0)
+                        return r;
+        } else {
+                if (x == UINT64_MAX) {
+                        if (unlink("/run/systemd/reboot-to-loader-menu") < 0 && errno != ENOENT)
+                                return -errno;
+                } else {
+                        char buf[DECIMAL_STR_MAX(uint64_t) + 1];
+
+                        xsprintf(buf, "%" PRIu64, x); /* Âµs granularity */
+
+                        r = write_string_file_atomic_label("/run/systemd/reboot-to-loader-menu", buf);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_boot_loader_menu(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+        int r;
+
+
+        assert(message);
+        assert(m);
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
+        if (r == -ENXIO) {
+                uint64_t features = 0;
+
+                /* EFI case, let's see if booting into boot loader menu is supported. */
+
+                r = efi_loader_get_features(&features);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
+                if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
+                        return sd_bus_reply_method_return(message, "s", "na");
+
+        } else if (r <= 0) {
+                /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU */
+
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
 
                 return sd_bus_reply_method_return(message, "s", "na");
         }
 
-        r = bus_test_polkit(message,
-                            CAP_SYS_ADMIN,
-                            "org.freedesktop.login1.set-reboot-to-firmware-setup",
-                            NULL,
-                            UID_INVALID,
-                            &challenge,
-                            error);
+        return return_test_polkit(
+                        message,
+                        CAP_SYS_ADMIN,
+                        "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
+                        NULL,
+                        UID_INVALID,
+                        error);
+}
+
+static int property_get_reboot_to_boot_loader_entry(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        _cleanup_free_ char *v = NULL;
+        int r;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
+        if (r == -ENXIO) {
+                /* EFI case: let's read the LoaderEntryOneShot variable */
+
+                r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
+                if (r < 0) {
+                        if (r != -ENOENT)
+                                log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m");
+                } else if (!efi_loader_entry_name_valid(v)) {
+                        log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v);
+                        v = mfree(v);
+                }
+        } else if (r < 0)
+                log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
+        else if (r > 0) {
+
+                /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-entry. */
+
+                r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v);
+                if (r < 0) {
+                        if (r != -ENOENT)
+                                log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m");
+                } else if (!efi_loader_entry_name_valid(v)) {
+                        log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring.");
+                        v = mfree(v);
+                }
+        }
+
+        return sd_bus_message_append(reply, "s", v);
+}
+
+static int boot_loader_entry_exists(const char *id) {
+        _cleanup_(boot_config_free) BootConfig config = {};
+        int r;
+
+        assert(id);
+
+        r = boot_entries_load_config_auto(NULL, NULL, &config);
         if (r < 0)
                 return r;
 
-        if (r > 0)
-                result = "yes";
-        else if (challenge)
-                result = "challenge";
-        else
-                result = "no";
+        (void) boot_entries_augment_from_loader(&config, true);
 
-        return sd_bus_reply_method_return(message, "s", result);
+        return boot_config_has_entry(&config, id);
+}
+
+static int method_set_reboot_to_boot_loader_entry(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+        bool use_efi;
+        const char *v;
+        int r;
+
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &v);
+        if (r < 0)
+                return r;
+
+        if (isempty(v))
+                v = NULL;
+        else if (efi_loader_entry_name_valid(v)) {
+                r = boot_loader_entry_exists(v);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader entry '%s' is not known.", v);
+        } else
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Boot loader entry name '%s' is not valid, refusing.", v);
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
+        if (r == -ENXIO) {
+                uint64_t features;
+
+                /* EFI case: let's see if booting into boot loader entry is supported. */
+
+                r = efi_loader_get_features(&features);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m");
+                if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
+
+                use_efi = true;
+
+        } else if (r <= 0) {
+                /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to off */
+
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
+
+                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
+        } else
+                /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */
+                use_efi = false;
+
+        r = bus_verify_polkit_async(message,
+                                    CAP_SYS_ADMIN,
+                                    "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
+                                    NULL,
+                                    false,
+                                    UID_INVALID,
+                                    &m->polkit_registry,
+                                    error);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+        if (use_efi) {
+                if (isempty(v))
+                        /* Delete item */
+                        r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0);
+                else
+                        r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v);
+                if (r < 0)
+                        return r;
+        } else {
+                if (isempty(v)) {
+                        if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT)
+                                return -errno;
+                } else {
+                        r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_boot_loader_entry(
+                sd_bus_message *message,
+                void *userdata,
+                sd_bus_error *error) {
+
+        Manager *m = userdata;
+        int r;
+
+        assert(message);
+        assert(m);
+
+        r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
+        if (r == -ENXIO) {
+                uint64_t features = 0;
+
+                /* EFI case, let's see if booting into boot loader entry is supported. */
+
+                r = efi_loader_get_features(&features);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to determine whether reboot to boot loader entry is supported: %m");
+                if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
+                        return sd_bus_reply_method_return(message, "s", "na");
+
+        } else if (r <= 0) {
+                /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY */
+
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
+
+                return sd_bus_reply_method_return(message, "s", "na");
+        }
+
+        return return_test_polkit(
+                        message,
+                        CAP_SYS_ADMIN,
+                        "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
+                        NULL,
+                        UID_INVALID,
+                        error);
+}
+
+static int property_get_boot_loader_entries(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        _cleanup_(boot_config_free) BootConfig config = {};
+        size_t i;
+        int r;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
+
+        r = boot_entries_load_config_auto(NULL, NULL, &config);
+        if (r < 0)
+                return r;
+
+        (void) boot_entries_augment_from_loader(&config, true);
+
+        r = sd_bus_message_open_container(reply, 'a', "s");
+        if (r < 0)
+                return r;
+
+        for (i = 0; i < config.n_entries; i++) {
+                BootEntry *e = config.entries + i;
+
+                r = sd_bus_message_append(reply, "s", e->id);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
 }
 
 static int method_set_wall_message(
@@ -2640,6 +3139,9 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0),
+        SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0),
+        SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0),
+        SD_BUS_PROPERTY("BootLoaderEntries", "as", property_get_boot_loader_entries, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -2714,6 +3216,10 @@ const sd_bus_vtable manager_vtable[] = {
         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("SetRebootToBootLoaderMenu", "t", NULL, method_set_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("CanRebootToBootLoaderEntry", NULL, "s", method_can_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("SetRebootToBootLoaderEntry", "s", NULL, method_set_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
 
         SD_BUS_SIGNAL("SessionNew", "so", 0),
index f880f3e2da40257d445786cfb2055c3c461d698d..5677c15b8a963bdb694b227429794a32137f79d1 100644 (file)
                        send_interface="org.freedesktop.login1.Manager"
                        send_member="SetRebootToFirmwareSetup"/>
 
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
+                       send_member="CanRebootToBootLoaderMenu"/>
+
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
+                       send_member="SetRebootToBootLoaderMenu"/>
+
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
+                       send_member="CanRebootToBootLoaderEntry"/>
+
+                <allow send_destination="org.freedesktop.login1"
+                       send_interface="org.freedesktop.login1.Manager"
+                       send_member="SetRebootToBootLoaderEntry"/>
+
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
                        send_member="SetWallMessage"/>
index 5ee62ab5b49eda6847beafde9f1df616b0aaaeb9..671384d34e88bd8ecc8ee8d39404772ab15ef9ce 100644 (file)
         </action>
 
         <action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
-                <description gettext-domain="systemd">Allow indication to the firmware to boot to setup interface</description>
+                <description gettext-domain="systemd">Indicate to the firmware to boot to setup interface</description>
                 <message gettext-domain="systemd">Authentication is required to indicate to the firmware to boot to setup interface.</message>
                 <defaults>
                         <allow_any>auth_admin_keep</allow_any>
                 <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
         </action>
 
+        <action id="org.freedesktop.login1.set-reboot-to-boot-loader-menu">
+                <description gettext-domain="systemd">Indicate to the boot loader to boot to the boot loader menu</description>
+                <message gettext-domain="systemd">Authentication is required to indicate to the boot loader to boot to the boot loader menu.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
+        </action>
+
+        <action id="org.freedesktop.login1.set-reboot-to-boot-loader-entry">
+                <description gettext-domain="systemd">Indicate to the boot loader to boot a specific entry</description>
+                <message gettext-domain="systemd">Authentication is required to indicate to the boot loader to boot into a specific boot loader entry.</message>
+                <defaults>
+                        <allow_any>auth_admin_keep</allow_any>
+                        <allow_inactive>auth_admin_keep</allow_inactive>
+                        <allow_active>yes</allow_active>
+                </defaults>
+                <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.reboot</annotate>
+        </action>
+
         <action id="org.freedesktop.login1.set-wall-message">
                 <description gettext-domain="systemd">Set a wall message</description>
                 <message gettext-domain="systemd">Authentication is required to set a wall message</message>
index 30f2e26a1e8cf89f897628d4ca6cad6c0b1fd502..8b97b4d8cef02248f382963a80c67a77fe0b8964 100644 (file)
@@ -2666,10 +2666,15 @@ static int clean_images(int argc, char *argv[], void *userdata) {
                 return bus_log_parse_error(r);
 
         while ((r = sd_bus_message_read(reply, "(st)", &name, &usage)) > 0) {
-                log_info("Removed image '%s'. Freed exclusive disk space: %s",
-                         name, format_bytes(fb, sizeof(fb), usage));
-
-                total += usage;
+                if (usage == UINT64_MAX) {
+                        log_info("Removed image '%s'", name);
+                        total = UINT64_MAX;
+                } else {
+                        log_info("Removed image '%s'. Freed exclusive disk space: %s",
+                                 name, format_bytes(fb, sizeof(fb), usage));
+                        if (total != UINT64_MAX)
+                                total += usage;
+                }
                 c++;
         }
 
@@ -2677,8 +2682,11 @@ static int clean_images(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        log_info("Removed %u images in total. Total freed exclusive disk space %s.",
-                 c, format_bytes(fb, sizeof(fb), total));
+        if (total == UINT64_MAX)
+                log_info("Removed %u images in total.", c);
+        else
+                log_info("Removed %u images in total. Total freed exclusive disk space: %s.",
+                         c, format_bytes(fb, sizeof(fb), total));
 
         return 0;
 }
index 1650515064fa7430ac4cf1fbbbfa05a4e613f5db..eaf056d11864d2625ff1c7cc3002448ee10da4d3 100644 (file)
@@ -6,7 +6,9 @@
 #include "set.h"
 #include "string-util.h"
 
-int address_pool_new(
+#define RANDOM_PREFIX_TRIAL_MAX  1024
+
+static int address_pool_new(
                 Manager *m,
                 AddressPool **ret,
                 int family,
@@ -121,35 +123,34 @@ static bool address_pool_prefix_is_taken(
 
 int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) {
         union in_addr_union u;
+        unsigned i;
+        int r;
 
         assert(p);
         assert(prefixlen > 0);
         assert(found);
 
-        if (p->prefixlen > prefixlen)
+        if (p->prefixlen >= prefixlen)
                 return 0;
 
         u = p->in_addr;
-        for (;;) {
-                if (!address_pool_prefix_is_taken(p, &u, prefixlen)) {
-                        _cleanup_free_ char *s = NULL;
-                        int r;
 
-                        r = in_addr_to_string(p->family, &u, &s);
-                        if (r < 0)
-                                return r;
+        for (i = 0; i < RANDOM_PREFIX_TRIAL_MAX; i++) {
+                r = in_addr_random_prefix(p->family, &u, p->prefixlen, prefixlen);
+                if (r <= 0)
+                        return r;
 
-                        log_debug("Found range %s/%u", strna(s), prefixlen);
+                if (!address_pool_prefix_is_taken(p, &u, prefixlen)) {
+                        if (DEBUG_LOGGING) {
+                                _cleanup_free_ char *s = NULL;
+
+                                (void) in_addr_to_string(p->family, &u, &s);
+                                log_debug("Found range %s/%u", strna(s), prefixlen);
+                        }
 
                         *found = u;
                         return 1;
                 }
-
-                if (!in_addr_prefix_next(p->family, &u, prefixlen))
-                        return 0;
-
-                if (!in_addr_prefix_intersect(p->family, &p->in_addr, p->prefixlen, &u, prefixlen))
-                        return 0;
         }
 
         return 0;
index bd479a517dbb46bb956de2f3040b8ac517342f1d..7db1c4f26c17f6fee24a82b0c583ca25de107ef7 100644 (file)
@@ -19,7 +19,6 @@ struct AddressPool {
         LIST_FIELDS(AddressPool, address_pools);
 };
 
-int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen);
 int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen);
 void address_pool_free(AddressPool *p);
 
index 7c1ee754052ccb49066631ce7459274950727830..7712fd6ae3d97161a655c5759d8ea7ab2a249481 100644 (file)
@@ -223,7 +223,7 @@ static int address_establish(Address *address, Link *link) {
 
                 r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
                 if (r < 0)
-                        log_link_warning_errno(link, r, "Could not enable IP masquerading: %m");
+                        return r;
 
                 address->ip_masquerade_done = masq;
         }
@@ -321,7 +321,7 @@ static int address_release(Address *address) {
 
                 r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
                 if (r < 0)
-                        log_link_warning_errno(address->link, r, "Failed to disable IP masquerading: %m");
+                        return r;
 
                 address->ip_masquerade_done = false;
         }
@@ -371,13 +371,17 @@ int address_update(
 int address_drop(Address *address) {
         Link *link;
         bool ready;
+        int r;
 
         assert(address);
 
         ready = address_is_ready(address);
         link = address->link;
 
-        address_release(address);
+        r = address_release(address);
+        if (r < 0)
+                log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m");
+
         address_free(address);
 
         link_update_operstate(link, true);
@@ -445,7 +449,6 @@ int address_remove(
                 link_netlink_message_handler_t callback) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        _cleanup_free_ char *b = NULL;
         int r;
 
         assert(address);
@@ -456,28 +459,30 @@ int address_remove(
         assert(link->manager->rtnl);
 
         if (DEBUG_LOGGING) {
-                if (in_addr_to_string(address->family, &address->in_addr, &b) >= 0)
-                        log_link_debug(link, "Removing address %s", b);
+                _cleanup_free_ char *b = NULL;
+
+                (void) in_addr_to_string(address->family, &address->in_addr, &b);
+                log_link_debug(link, "Removing address %s", strna(b));
         }
 
         r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
                                      link->ifindex, address->family);
         if (r < 0)
-                return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m");
+                return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
 
         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
         if (r < 0)
-                return log_error_errno(r, "Could not set prefixlen: %m");
+                return log_link_error_errno(link, r, "Could not set prefixlen: %m");
 
         r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
         if (r < 0)
-                return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
+                return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
 
         r = netlink_call_async(link->manager->rtnl, NULL, req,
                                callback ?: address_remove_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
-                return log_error_errno(r, "Could not send rtnetlink message: %m");
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
 
         link_ref(link);
 
@@ -495,18 +500,17 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
         assert(ret);
 
         /* Something useful was configured? just use it */
-        if (in_addr_is_null(original->family, &original->in_addr) <= 0)
-                return 0;
+        r = in_addr_is_null(original->family, &original->in_addr);
+        if (r <= 0)
+                return r;
 
         /* The address is configured to be 0.0.0.0 or [::] by the user?
          * Then let's acquire something more useful from the pool. */
         r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
         if (r < 0)
-                return log_link_error_errno(link, r, "Failed to acquire address from pool: %m");
-        if (r == 0) {
-                log_link_error(link, "Couldn't find free address for interface, all taken.");
+                return r;
+        if (r == 0)
                 return -EBUSY;
-        }
 
         if (original->family == AF_INET) {
                 /* Pick first address in range for ourselves ... */
@@ -565,11 +569,12 @@ int address_configure(
         /* If this is a new address, then refuse adding more than the limit */
         if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
             set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
-                return -E2BIG;
+                return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
+                                            "Too many addresses are configured, refusing: %m");
 
         r = address_acquire(link, address, &address);
         if (r < 0)
-                return r;
+                return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
 
         if (update)
                 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
@@ -578,11 +583,11 @@ int address_configure(
                 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
                                              link->ifindex, address->family);
         if (r < 0)
-                return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
+                return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
 
         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
         if (r < 0)
-                return log_error_errno(r, "Could not set prefixlen: %m");
+                return log_link_error_errno(link, r, "Could not set prefixlen: %m");
 
         address->flags |= IFA_F_PERMANENT;
 
@@ -603,50 +608,50 @@ int address_configure(
 
         r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
         if (r < 0)
-                return log_error_errno(r, "Could not set flags: %m");
+                return log_link_error_errno(link, r, "Could not set flags: %m");
 
         if (address->flags & ~0xff) {
                 r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
                 if (r < 0)
-                        return log_error_errno(r, "Could not set extended flags: %m");
+                        return log_link_error_errno(link, r, "Could not set extended flags: %m");
         }
 
         r = sd_rtnl_message_addr_set_scope(req, address->scope);
         if (r < 0)
-                return log_error_errno(r, "Could not set scope: %m");
+                return log_link_error_errno(link, r, "Could not set scope: %m");
 
         r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
         if (r < 0)
-                return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
+                return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
 
         if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
                 r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
         } else if (address->family == AF_INET && address->prefixlen <= 30) {
                 r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
         }
 
         if (address->label) {
                 r = sd_netlink_message_append_string(req, IFA_LABEL, address->label);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
         }
 
         r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
         if (r < 0)
-                return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
+                return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
 
         r = address_establish(address, link);
         if (r < 0)
-                return r;
+                log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m");
 
         r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link);
         if (r < 0) {
                 address_release(address);
-                return log_error_errno(r, "Could not send rtnetlink message: %m");
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
         }
 
         link_ref(link);
@@ -657,7 +662,7 @@ int address_configure(
                 r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
         if (r < 0) {
                 address_release(address);
-                return log_error_errno(r, "Could not add address: %m");
+                return log_link_error_errno(link, r, "Could not add address: %m");
         }
 
         return 0;
@@ -761,6 +766,19 @@ int config_parse_address(const char *unit,
                 return 0;
         }
 
+        if (in_addr_is_null(f, &buffer)) {
+                /* Will use address from address pool. Note that for ipv6 case, prefix of the address
+                 * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
+                 * let's limit the prefix length to 64 or larger. See RFC4193. */
+                if ((f == AF_INET && prefixlen < 8) ||
+                    (f == AF_INET6 && prefixlen < 64)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Null address with invalid prefixlen='%u', ignoring assignment: %s",
+                                   prefixlen, rvalue);
+                        return 0;
+                }
+        }
+
         n->family = f;
         n->prefixlen = prefixlen;
 
index 1738a0d944ab1d6df44631a48087642fb20402ed..de112a2ef80bf69ea5c0fcc0f0b1369eafafebbe 100644 (file)
@@ -31,6 +31,7 @@
 #include "strv.h"
 #include "sysctl-util.h"
 #include "tmpfile-util.h"
+#include "udev-util.h"
 #include "util.h"
 #include "virt.h"
 
@@ -2162,6 +2163,19 @@ static int link_set_can(Link *link) {
                         return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
         }
 
+        if (link->network->can_triple_sampling >= 0) {
+                struct can_ctrlmode cm = {
+                        .mask = CAN_CTRLMODE_3_SAMPLES,
+                        .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0,
+                };
+
+                log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis");
+
+                r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
+        }
+
         r = sd_netlink_message_close_container(m);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to close netlink container: %m");
@@ -3624,6 +3638,16 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
                         return 0;
                 }
 
+                r = device_is_renaming(device);
+                if (r < 0) {
+                        log_link_warning_errno(link, r, "Failed to determine the device is renamed or not: %m");
+                        goto failed;
+                }
+                if (r > 0) {
+                        log_link_debug(link, "Interface is under renaming, pending initialization.");
+                        return 0;
+                }
+
                 r = link_initialized(link, device);
                 if (r < 0)
                         goto failed;
@@ -3767,20 +3791,14 @@ int link_update(Link *link, sd_netlink_message *m) {
 
         r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
         if (r >= 0 && !streq(ifname, link->ifname)) {
-                log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname);
+                Manager *manager = link->manager;
 
-                if (link->state == LINK_STATE_PENDING) {
-                        r = free_and_strdup(&link->ifname, ifname);
-                        if (r < 0)
-                                return r;
-                } else {
-                        Manager *manager = link->manager;
+                log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname);
 
-                        link_drop(link);
-                        r = link_add(manager, m, &link);
-                        if (r < 0)
-                                return r;
-                }
+                link_drop(link);
+                r = link_add(manager, m, &link);
+                if (r < 0)
+                        return r;
         }
 
         r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
index 00f6545e24f9e5580d95335d0546c36e14484602..c87f907957a9d688e1e96144c331243c07f993b4 100644 (file)
@@ -26,6 +26,7 @@
 #include "strv.h"
 #include "sysctl-util.h"
 #include "tmpfile-util.h"
+#include "udev-util.h"
 #include "virt.h"
 
 /* use 8 MB for receive socket kernel queue. */
@@ -39,11 +40,11 @@ static int setup_default_address_pool(Manager *m) {
 
         /* Add in the well-known private address ranges. */
 
-        r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7);
+        r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8);
         if (r < 0)
                 return r;
 
-        r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
+        r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
         if (r < 0)
                 return r;
 
@@ -51,7 +52,7 @@ static int setup_default_address_pool(Manager *m) {
         if (r < 0)
                 return r;
 
-        r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
+        r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
         if (r < 0)
                 return r;
 
@@ -194,7 +195,7 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
                 return 0;
         }
 
-        if (!STR_IN_SET(action, "add", "change")) {
+        if (!STR_IN_SET(action, "add", "change", "move")) {
                 log_device_debug(device, "Ignoring udev %s event for device.", action);
                 return 0;
         }
@@ -205,6 +206,16 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi
                 return 0;
         }
 
+        r = device_is_renaming(device);
+        if (r < 0) {
+                log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m", action);
+                return 0;
+        }
+        if (r > 0) {
+                log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed: %m");
+                return 0;
+        }
+
         r = link_get(m, ifindex, &link);
         if (r < 0) {
                 if (r != -ENODEV)
index 7888bdf07af270140600abf67c03a12bc2cab9c4..51123d12ef0cacd1751b55cd7f3e6d15db6beb90 100644 (file)
@@ -195,6 +195,7 @@ IPv6Prefix.PreferredLifetimeSec,        config_parse_prefix_lifetime,
 CAN.BitRate,                            config_parse_si_size,                           0,                             offsetof(Network, can_bitrate)
 CAN.SamplePoint,                        config_parse_permille,                          0,                             offsetof(Network, can_sample_point)
 CAN.RestartSec,                         config_parse_sec,                               0,                             offsetof(Network, can_restart_us)
+CAN.TripleSampling,                     config_parse_tristate,                          0,                             offsetof(Network, can_triple_sampling)
 /* backwards compatibility: do not add new entries to this section */
 Network.IPv4LL,                         config_parse_ipv4ll,                            0,                             offsetof(Network, link_local)
 DHCPv4.UseDNS,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
index ab4e90543c3a67e3101a9693db5f6c9b190e2f40..5f12df907afe9afcc8127c89fa2f49b44fac116f 100644 (file)
@@ -428,6 +428,8 @@ int network_load_one(Manager *manager, const char *filename) {
                 .ipv6_accept_ra_use_onlink_prefix = true,
                 .ipv6_accept_ra_route_table = RT_TABLE_MAIN,
                 .ipv6_accept_ra_route_table_set = false,
+
+                .can_triple_sampling = -1,
         };
 
         r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
index 63d0328750f37e85acf89f1c649c1f2dd01cc11a..2f7b6133fd506a3ebdda3b0d6f8cbeb7b2adbb02 100644 (file)
@@ -202,6 +202,7 @@ struct Network {
         size_t can_bitrate;
         unsigned can_sample_point;
         usec_t can_restart_us;
+        int can_triple_sampling;
 
         AddressFamilyBoolean ip_forward;
         bool ip_masquerade;
index 5594ba1224e9553dfc6cd4f9049751e491f83fba..207469878055785b539a32a3fab41d23f6c86eef 100644 (file)
@@ -407,59 +407,59 @@ int route_remove(Route *route, Link *link,
                                       RTM_DELROUTE, route->family,
                                       route->protocol);
         if (r < 0)
-                return log_error_errno(r, "Could not create RTM_DELROUTE message: %m");
+                return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
 
         if (in_addr_is_null(route->family, &route->gw) == 0) {
                 r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
         }
 
         if (route->dst_prefixlen) {
                 r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_DST attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
 
                 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
                 if (r < 0)
-                        return log_error_errno(r, "Could not set destination prefix length: %m");
+                        return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
         }
 
         if (route->src_prefixlen) {
                 r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_SRC attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
 
                 r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
                 if (r < 0)
-                        return log_error_errno(r, "Could not set source prefix length: %m");
+                        return log_link_error_errno(link, r, "Could not set source prefix length: %m");
         }
 
         if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
                 r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
         }
 
         r = sd_rtnl_message_route_set_scope(req, route->scope);
         if (r < 0)
-                return log_error_errno(r, "Could not set scope: %m");
+                return log_link_error_errno(link, r, "Could not set scope: %m");
 
         r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+                return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
 
         if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
                 r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
         }
 
         r = netlink_call_async(link->manager->rtnl, NULL, req,
                                callback ?: route_remove_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
-                return log_error_errno(r, "Could not send rtnetlink message: %m");
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
 
         link_ref(link);
 
@@ -500,7 +500,8 @@ int route_configure(
 
         if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
             set_size(link->routes) >= routes_max())
-                return -E2BIG;
+                return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
+                                            "Too many routes are configured, refusing: %m");
 
         if (DEBUG_LOGGING) {
                 _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
@@ -524,133 +525,133 @@ int route_configure(
                                       RTM_NEWROUTE, route->family,
                                       route->protocol);
         if (r < 0)
-                return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
+                return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
 
         if (in_addr_is_null(route->family, &route->gw) == 0) {
                 r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m");
 
                 r = sd_rtnl_message_route_set_family(req, route->family);
                 if (r < 0)
-                        return log_error_errno(r, "Could not set route family: %m");
+                        return log_link_error_errno(link, r, "Could not set route family: %m");
         }
 
         if (route->dst_prefixlen) {
                 r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_DST attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m");
 
                 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
                 if (r < 0)
-                        return log_error_errno(r, "Could not set destination prefix length: %m");
+                        return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
         }
 
         if (route->src_prefixlen) {
                 r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_SRC attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m");
 
                 r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
                 if (r < 0)
-                        return log_error_errno(r, "Could not set source prefix length: %m");
+                        return log_link_error_errno(link, r, "Could not set source prefix length: %m");
         }
 
         if (in_addr_is_null(route->family, &route->prefsrc) == 0) {
                 r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m");
         }
 
         r = sd_rtnl_message_route_set_scope(req, route->scope);
         if (r < 0)
-                return log_error_errno(r, "Could not set scope: %m");
+                return log_link_error_errno(link, r, "Could not set scope: %m");
 
         if (route->gateway_onlink >= 0)
                 SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink);
 
         r = sd_rtnl_message_route_set_flags(req, route->flags);
         if (r < 0)
-                return log_error_errno(r, "Could not set flags: %m");
+                return log_link_error_errno(link, r, "Could not set flags: %m");
 
         if (route->table != RT_TABLE_MAIN) {
                 if (route->table < 256) {
                         r = sd_rtnl_message_route_set_table(req, route->table);
                         if (r < 0)
-                                return log_error_errno(r, "Could not set route table: %m");
+                                return log_link_error_errno(link, r, "Could not set route table: %m");
                 } else {
                         r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
                         if (r < 0)
-                                return log_error_errno(r, "Could not set route table: %m");
+                                return log_link_error_errno(link, r, "Could not set route table: %m");
 
                         /* Table attribute to allow more than 256. */
                         r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table));
                         if (r < 0)
-                                return log_error_errno(r, "Could not append RTA_TABLE attribute: %m");
+                                return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m");
                 }
         }
 
         r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+                return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m");
 
         r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
+                return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m");
 
         if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) {
                 r = sd_netlink_message_append_u32(req, RTA_EXPIRES,
                         DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC));
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_EXPIRES attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
         }
 
         r = sd_rtnl_message_route_set_type(req, route->type);
         if (r < 0)
-                return log_error_errno(r, "Could not set route type: %m");
+                return log_link_error_errno(link, r, "Could not set route type: %m");
 
         if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) {
                 r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
         }
 
         r = sd_netlink_message_open_container(req, RTA_METRICS);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_METRICS attribute: %m");
+                return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
 
         if (route->mtu > 0) {
                 r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTAX_MTU attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m");
         }
 
         if (route->initcwnd > 0) {
                 r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTAX_INITCWND attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m");
         }
 
         if (route->initrwnd > 0) {
                 r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTAX_INITRWND attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
         }
 
         if (route->quickack != -1) {
                 r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
                 if (r < 0)
-                        return log_error_errno(r, "Could not append RTAX_QUICKACK attribute: %m");
+                        return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
         }
 
         r = sd_netlink_message_close_container(req);
         if (r < 0)
-                return log_error_errno(r, "Could not append RTA_METRICS attribute: %m");
+                return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
 
         r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
                                link_netlink_destroy_callback, link);
         if (r < 0)
-                return log_error_errno(r, "Could not send rtnetlink message: %m");
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
 
         link_ref(link);
 
@@ -658,7 +659,7 @@ int route_configure(
 
         r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route);
         if (r < 0)
-                return log_error_errno(r, "Could not add route: %m");
+                return log_link_error_errno(link, r, "Could not add route: %m");
 
         /* TODO: drop expiration handling once it can be pushed into the kernel */
         route->lifetime = lifetime;
@@ -667,7 +668,7 @@ int route_configure(
                 r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
                                       route->lifetime, 0, route_expire_handler, route);
                 if (r < 0)
-                        return log_error_errno(r, "Could not arm expiration timer: %m");
+                        return log_link_error_errno(link, r, "Could not arm expiration timer: %m");
         }
 
         sd_event_source_unref(route->expire);
index eb0a26ef35bf491d935c77312fb142b37b46b67a..13f50b2d37b9cca7f020b2fc4de5e4cdb4a0f8a3 100644 (file)
@@ -206,7 +206,7 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only)
         }
 
         if (isempty(source))
-                source = NULL;
+                source = mfree(source);
         else if (!source_path_is_valid(source))
                 return -EINVAL;
 
@@ -219,12 +219,10 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only)
         if (!m)
                 return -ENOMEM;
 
-        m->source = source;
-        m->destination = destination;
+        m->source = TAKE_PTR(source);
+        m->destination = TAKE_PTR(destination);
         m->read_only = read_only;
-        m->options = opts;
-
-        source = destination = opts = NULL;
+        m->options = TAKE_PTR(opts);
         return 0;
 }
 
index 5cb049e5f734fe4ac6dd2e32405388182976f93a..64a30a5b9a800bce23932b4488fcae1b949fc998 100644 (file)
@@ -3962,11 +3962,11 @@ static int run(int master,
         } else if (arg_slice || arg_property)
                 log_notice("Machine and scope registration turned off, --slice= and --property= settings will have no effect.");
 
-        r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
+        r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
         if (r < 0)
                 return r;
 
-        r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
+        r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
         if (r < 0)
                 return r;
 
index 0c5f3297567f1c1f37d873eb6b0b4b98a6423148..71c2dba4318b73b74e3296a53b00ccab518b4893 100644 (file)
@@ -51,7 +51,7 @@ static int run(int argc, char *argv[]) {
         if (buf_size < POOL_SIZE_MIN)
                 buf_size = POOL_SIZE_MIN;
 
-        r = mkdir_parents_label(RANDOM_SEED, 0755);
+        r = mkdir_parents(RANDOM_SEED, 0755);
         if (r < 0)
                 return log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
 
index d7252d3dac133ac287d679c5ca133dcfa07cc6dd..44dc6552b4f06cbd49cd270799365105923fd889 100644 (file)
@@ -87,40 +87,33 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFl
                 if (a->items[i].ifindex != ifindex)
                         continue;
 
-                r = dns_resource_record_equal(a->items[i].rr, rr);
+                r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        /* Don't mix contradicting TTLs (see below) */
-                        if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
-                                return -EINVAL;
-
-                        /* Entry already exists, keep the entry with
-                         * the higher RR. */
-                        if (rr->ttl > a->items[i].rr->ttl) {
-                                dns_resource_record_ref(rr);
-                                dns_resource_record_unref(a->items[i].rr);
-                                a->items[i].rr = rr;
-                        }
+                if (r == 0)
+                        continue;
 
-                        a->items[i].flags |= flags;
-                        return 0;
-                }
+                /* There's already an RR of the same RRset in place! Let's see if the TTLs more or less
+                 * match. We don't really care if they match precisely, but we do care whether one is 0 and
+                 * the other is not. See RFC 2181, Section 5.2. */
+                if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
+                        return -EINVAL;
 
-                r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
+                r = dns_resource_record_payload_equal(a->items[i].rr, rr);
                 if (r < 0)
                         return r;
-                if (r > 0) {
-                        /* There's already an RR of the same RRset in
-                         * place! Let's see if the TTLs more or less
-                         * match. We don't really care if they match
-                         * precisely, but we do care whether one is 0
-                         * and the other is not. See RFC 2181, Section
-                         * 5.2. */
-
-                        if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
-                                return -EINVAL;
+                if (r == 0)
+                        continue;
+
+                /* Entry already exists, keep the entry with the higher RR. */
+                if (rr->ttl > a->items[i].rr->ttl) {
+                        dns_resource_record_ref(rr);
+                        dns_resource_record_unref(a->items[i].rr);
+                        a->items[i].rr = rr;
                 }
+
+                a->items[i].flags |= flags;
+                return 0;
         }
 
         return dns_answer_add_raw(a, rr, ifindex, flags);
index 572271be95c37c8ebd1338eb4f52bd88bb4043a0..278546da8489633ecc5bd8525aca5ea30d650a66 100644 (file)
@@ -7,6 +7,7 @@
 #include "alloc-util.h"
 #include "dns-domain.h"
 #include "resolved-dns-packet.h"
+#include "set.h"
 #include "string-table.h"
 #include "strv.h"
 #include "unaligned.h"
@@ -2133,6 +2134,17 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
                 if (!question)
                         return -ENOMEM;
 
+                _cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */
+
+                keys = set_new(&dns_resource_key_hash_ops);
+                if (!keys)
+                        return log_oom();
+
+                r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through
+                                               * hash collisions, but the gains quickly drop of after 2. */
+                if (r < 0)
+                        return r;
+
                 for (i = 0; i < n; i++) {
                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
                         bool cache_flush;
@@ -2147,7 +2159,14 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
                         if (!dns_type_is_valid_query(key->type))
                                 return -EBADMSG;
 
-                        r = dns_question_add(question, key);
+                        r = set_put(keys, key);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                /* Already in the Question, let's skip */
+                                continue;
+
+                        r = dns_question_add_raw(question, key);
                         if (r < 0)
                                 return r;
                 }
@@ -2239,7 +2258,7 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
                                          * be contained in questions, never in replies. Crappy
                                          * Belkin routers copy the OPT data for example, hence let's
                                          * detect this so that we downgrade early. */
-                                        log_debug("OPT RR contained RFC6975 data, ignoring.");
+                                        log_debug("OPT RR contains RFC6975 data, ignoring.");
                                         bad_opt = true;
                                         continue;
                                 }
index 1ed9171564a5c2bb572152a40fb5b700d5aa1ff5..60cd34bcfc1d5677e4f3f46fe010ba2d55386055 100644 (file)
@@ -32,8 +32,20 @@ static DnsQuestion *dns_question_free(DnsQuestion *q) {
 
 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsQuestion, dns_question, dns_question_free);
 
+int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key) {
+        /* Insert without checking for duplicates. */
+
+        assert(key);
+        assert(q);
+
+        if (q->n_keys >= q->n_allocated)
+                return -ENOSPC;
+
+        q->keys[q->n_keys++] = dns_resource_key_ref(key);
+        return 0;
+}
+
 int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
-        size_t i;
         int r;
 
         assert(key);
@@ -41,7 +53,7 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
         if (!q)
                 return -ENOSPC;
 
-        for (i = 0; i < q->n_keys; i++) {
+        for (size_t i = 0; i < q->n_keys; i++) {
                 r = dns_resource_key_equal(q->keys[i], key);
                 if (r < 0)
                         return r;
@@ -49,11 +61,7 @@ int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
                         return 0;
         }
 
-        if (q->n_keys >= q->n_allocated)
-                return -ENOSPC;
-
-        q->keys[q->n_keys++] = dns_resource_key_ref(key);
-        return 0;
+        return dns_question_add_raw(q, key);
 }
 
 int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
index f513bf03282634da3fb05528c0f718a62378849a..0803f49b8bb1c8f5eb713d782384bfe0eff61e52 100644 (file)
@@ -22,6 +22,7 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
 int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a);
 int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna);
 
+int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key);
 int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
 
 int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain);
index 477d5170aadaac7dac796d35e603b4e0d41b3aad..4cbb9723e21f69a1247215327cc114a766b6eb69 100644 (file)
@@ -557,18 +557,10 @@ int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const u
         ((a).field ## _size == (b).field ## _size &&  \
          memcmp((a).field, (b).field, (a).field ## _size) == 0)
 
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
+int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
         int r;
 
-        assert(a);
-        assert(b);
-
-        if (a == b)
-                return 1;
-
-        r = dns_resource_key_equal(a->key, b->key);
-        if (r <= 0)
-                return r;
+        /* Check if a and b are the same, but don't look at their keys */
 
         if (a->unparseable != b->unparseable)
                 return 0;
@@ -692,6 +684,22 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
         }
 }
 
+int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
+        int r;
+
+        assert(a);
+        assert(b);
+
+        if (a == b)
+                return 1;
+
+        r = dns_resource_key_equal(a->key, b->key);
+        if (r <= 0)
+                return r;
+
+        return dns_resource_record_payload_equal(a, b);
+}
+
 static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
                              uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
         char *s;
index e02fa2d53b1a4c40d93b49715a4b6e81e7574df1..3d278366519c2636070048b42698f90b3f4ec0bd 100644 (file)
@@ -308,6 +308,8 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr);
 int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
 int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
+int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
+
 const char* dns_resource_record_to_string(DnsResourceRecord *rr);
 DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
index dbff889e3ead91edc16e82fc547090cce87925f2..ca3590066c83e7260de5849a27d67440e7452207 100644 (file)
@@ -10,6 +10,7 @@
 #include "log.h"
 #include "resolved-etc-hosts.h"
 #include "strv.h"
+#include "tests.h"
 #include "tmpfile-util.h"
 
 static void test_parse_etc_hosts_system(void) {
@@ -137,9 +138,7 @@ static void test_parse_file(const char *fname) {
 }
 
 int main(int argc, char **argv) {
-        log_set_max_level(LOG_DEBUG);
-        log_parse_environment();
-        log_open();
+        test_setup_logging(LOG_DEBUG);
 
         if (argc == 1) {
                 test_parse_etc_hosts_system();
index 22ae26ce12ca6e6d3da456e024e26340ad596ac0..c9a511beba9ea6c8f9e2bb3c9b60b64f53c548fb 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "log.h"
 #include "resolved-dns-packet.h"
+#include "tests.h"
 
 static void test_dns_packet_new(void) {
         size_t i;
@@ -23,10 +24,7 @@ static void test_dns_packet_new(void) {
 }
 
 int main(int argc, char **argv) {
-
-        log_set_max_level(LOG_DEBUG);
-        log_parse_environment();
-        log_open();
+        test_setup_logging(LOG_DEBUG);
 
         test_dns_packet_new();
 
index 53ab042404674a208dac87b21a134055cc751ff0..afcf6f7ac13eaabcf9fb7a2207487fe59e908e50 100644 (file)
@@ -22,6 +22,7 @@
 #include "path-util.h"
 #include "pe-header.h"
 #include "stat-util.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "unaligned.h"
@@ -50,7 +51,10 @@ static int boot_entry_load(
                 const char *path,
                 BootEntry *entry) {
 
-        _cleanup_(boot_entry_free) BootEntry tmp = {};
+        _cleanup_(boot_entry_free) BootEntry tmp = {
+                .type = BOOT_ENTRY_CONF,
+        };
+
         _cleanup_fclose_ FILE *f = NULL;
         unsigned line = 1;
         char *b, *c;
@@ -62,13 +66,16 @@ static int boot_entry_load(
 
         c = endswith_no_case(path, ".conf");
         if (!c)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry filename: %s", path);
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path);
 
         b = basename(path);
         tmp.id = strndup(b, c - b);
         if (!tmp.id)
                 return log_oom();
 
+        if (!efi_loader_entry_name_valid(tmp.id))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry filename: %s", path);
+
         tmp.path = strdup(path);
         if (!tmp.path)
                 return log_oom();
@@ -272,7 +279,9 @@ static int boot_entry_load_unified(
                 BootEntry *ret) {
 
         _cleanup_free_ char *os_pretty_name = NULL, *os_id = NULL, *version_id = NULL, *build_id = NULL;
-        _cleanup_(boot_entry_free) BootEntry tmp = {};
+        _cleanup_(boot_entry_free) BootEntry tmp = {
+                .type = BOOT_ENTRY_UNIFIED,
+        };
         _cleanup_fclose_ FILE *f = NULL;
         const char *k;
         int r;
@@ -304,6 +313,9 @@ static int boot_entry_load_unified(
         if (!tmp.id)
                 return log_oom();
 
+        if (!efi_loader_entry_name_valid(tmp.id))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry: %s", tmp.id);
+
         tmp.path = strdup(path);
         if (!tmp.path)
                 return log_oom();
@@ -476,7 +488,7 @@ static int boot_entries_find_unified(
 
                 r = fd_verify_regular(fd);
                 if (r < 0) {
-                        log_warning_errno(errno, "File %s/%s is not regular, ignoring: %m", dir, de->d_name);
+                        log_warning_errno(r, "File %s/%s is not regular, ignoring: %m", dir, de->d_name);
                         continue;
                 }
 
@@ -652,18 +664,127 @@ int boot_entries_load_config(
 
         if (is_efi_boot()) {
                 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot);
-                if (r < 0 && r != -ENOENT)
-                        return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m");
+                if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+                        log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
+                        if (r == -ENOMEM)
+                                return r;
+                }
 
                 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryDefault", &config->entry_default);
-                if (r < 0 && r != -ENOENT)
-                        return log_error_errno(r, "Failed to read EFI var \"LoaderEntryDefault\": %m");
+                if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+                        log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
+                        if (r == -ENOMEM)
+                                return r;
+                }
         }
 
         config->default_entry = boot_entries_select_default(config);
         return 0;
 }
 
+int boot_entries_load_config_auto(
+                const char *override_esp_path,
+                const char *override_xbootldr_path,
+                BootConfig *config) {
+
+        _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
+        int r;
+
+        assert(config);
+
+        /* This function is similar to boot_entries_load_config(), however we automatically search for the
+         * ESP and the XBOOTLDR partition unless it is explicitly specified. Also, if the user did not pass
+         * an ESP or XBOOTLDR path directly, let's see if /run/boot-loader-entries/ exists. If so, let's
+         * read data from there, as if it was an ESP (i.e. loading both entries and loader.conf data from
+         * it). This allows other boot loaders to pass boot loader entry information to our tools if they
+         * want to. */
+
+        if (!override_esp_path && !override_xbootldr_path) {
+                if (access("/run/boot-loader-entries/", F_OK) >= 0)
+                        return boot_entries_load_config("/run/boot-loader-entries/", NULL, config);
+
+                if (errno != ENOENT)
+                        return log_error_errno(errno,
+                                               "Failed to determine whether /run/boot-loader-entries/ exists: %m");
+        }
+
+        r = find_esp_and_warn(override_esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
+        if (r == -ENOKEY) /* find_esp_and_warn() doesn't warn about this case */
+                return log_error_errno(r, "Cannot find the ESP partition mount point.");
+        if (r < 0) /* But it logs about all these cases, hence don't log here again */
+                return r;
+
+        r = find_xbootldr_and_warn(override_xbootldr_path, false, &xbootldr_where, NULL);
+        if (r < 0 && r != -ENOKEY)
+                return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
+
+        return boot_entries_load_config(esp_where, xbootldr_where, config);
+}
+
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
+
+        static const char * const title_table[] = {
+                /* Pretty names for a few well-known automatically discovered entries. */
+                "auto-osx",                      "macOS",
+                "auto-windows",                  "Windows Boot Manager",
+                "auto-efi-shell",                "EFI Shell",
+                "auto-efi-default",              "EFI Default Loader",
+                "auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface",
+        };
+
+        _cleanup_free_ char **found_by_loader = NULL;
+        size_t n_allocated;
+        char **i;
+        int r;
+
+        assert(config);
+
+        /* Let's add the entries discovered by the boot loader to the end of our list, unless they are
+         * already included there. */
+
+        r = efi_loader_get_entries(&found_by_loader);
+        if (IN_SET(r, -ENOENT, -EOPNOTSUPP))
+                return log_debug_errno(r, "Boot loader reported no entries.");
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
+
+        n_allocated = config->n_entries;
+
+        STRV_FOREACH(i, found_by_loader) {
+                _cleanup_free_ char *c = NULL, *t = NULL;
+                char **a, **b;
+
+                if (boot_config_has_entry(config, *i))
+                        continue;
+
+                if (only_auto && !startswith(*i, "auto-"))
+                        continue;
+
+                c = strdup(*i);
+                if (!c)
+                        return log_oom();
+
+                STRV_FOREACH_PAIR(a, b, (char**) title_table)
+                        if (streq(*a, *i)) {
+                                t = strdup(*b);
+                                if (!t)
+                                        return log_oom();
+                                break;
+                        }
+
+                if (!GREEDY_REALLOC0(config->entries, n_allocated, config->n_entries + 1))
+                        return log_oom();
+
+                config->entries[config->n_entries++] = (BootEntry) {
+                        .type = BOOT_ENTRY_LOADER,
+                        .id = TAKE_PTR(c),
+                        .title = TAKE_PTR(t),
+                };
+        }
+
+        return 0;
+}
+
 /********************************************************************************/
 
 static int verify_esp_blkid(
@@ -1294,36 +1415,10 @@ found:
         return 0;
 }
 
-int find_default_boot_entry(
-                const char *esp_path,
-                const char *xbootldr_path,
-                BootConfig *config,
-                const BootEntry **e) {
+static const char* const boot_entry_type_table[_BOOT_ENTRY_MAX] = {
+        [BOOT_ENTRY_CONF] = "conf",
+        [BOOT_ENTRY_UNIFIED] = "unified",
+        [BOOT_ENTRY_LOADER] = "loader",
+};
 
-        _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
-        int r;
-
-        assert(config);
-        assert(e);
-
-        r = find_esp_and_warn(esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
-        if (r < 0)
-                return r;
-
-        r = find_xbootldr_and_warn(xbootldr_path, false, &xbootldr_where, NULL);
-        if (r < 0 && r != -ENOKEY)
-                return r;
-
-        r = boot_entries_load_config(esp_where, xbootldr_where, config);
-        if (r < 0)
-                return log_error_errno(r, "Failed to load boot loader entries: %m");
-
-        if (config->default_entry < 0)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
-                                       "No boot loader entry suitable as default, refusing to guess.");
-
-        *e = &config->entries[config->default_entry];
-        log_debug("Found default boot loader entry in file \"%s\"", (*e)->path);
-
-        return 0;
-}
+DEFINE_STRING_TABLE_LOOKUP(boot_entry_type, BootEntryType);
index f1849025586c253b082049b3ad1ac43878effb4b..45e1fc37c65c7c114e8b3300a05c75ea4e8bdb6e 100644 (file)
@@ -8,7 +8,18 @@
 
 #include "sd-id128.h"
 
+#include "string-util.h"
+
+typedef enum BootEntryType {
+        BOOT_ENTRY_CONF,     /* Type #1 entries: *.conf files */
+        BOOT_ENTRY_UNIFIED,  /* Type #2 entries: *.efi files */
+        BOOT_ENTRY_LOADER,   /* Additional entries augmented from LoaderEntries EFI var */
+        _BOOT_ENTRY_MAX,
+        _BOOT_ENTRY_INVALID = -1,
+} BootEntryType;
+
 typedef struct BootEntry {
+        BootEntryType type;
         char *id;       /* This is the file basename without extension */
         char *path;     /* This is the full path to the drop-in file */
         char *root;     /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
@@ -40,8 +51,27 @@ typedef struct BootConfig {
         ssize_t default_entry;
 } BootConfig;
 
+static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
+        size_t j;
+
+        for (j = 0; j < config->n_entries; j++)
+                if (streq(config->entries[j].id, id))
+                        return true;
+
+        return false;
+}
+
+static inline BootEntry* boot_config_default_entry(BootConfig *config) {
+        if (config->default_entry < 0)
+                return NULL;
+
+        return config->entries + config->default_entry;
+}
+
 void boot_config_free(BootConfig *config);
 int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
+int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto);
 
 static inline const char* boot_entry_title(const BootEntry *entry) {
         return entry->show_title ?: entry->title ?: entry->id;
@@ -50,4 +80,5 @@ static inline const char* boot_entry_title(const BootEntry *entry) {
 int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid);
 int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);
 
-int find_default_boot_entry(const char *esp_path, const char *xbootldr_path, BootConfig *config, const BootEntry **e);
+const char* boot_entry_type_to_string(BootEntryType t) _const_;
+BootEntryType boot_entry_type_from_string(const char *s) _pure_;
index cbcf698e965f5f2db8141759f34d3c0c9ecd779e..1911dd0ce642f875db511e9b5c56da66752d1942 100644 (file)
@@ -628,7 +628,21 @@ int bus_connect_user_systemd(sd_bus **_bus) {
         return 0;
 }
 
-int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
+int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value) {
+        assert(name);
+
+        if (expected_value && !streq_ptr(expected_value, value))
+                return 0;
+
+        if (only_value)
+                puts(value);
+        else
+                printf("%s=%s\n", name, value);
+
+        return 0;
+}
+
+int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) {
         va_list ap;
         int r;
 
@@ -691,7 +705,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         /* This property has a single value, so we need to take
                          * care not to print a new line, everything else is OK. */
                         good = !strchr(s, '\n');
-                        bus_print_property_value(name, expected_value, value, "%s", good ? s : "[unprintable]");
+                        bus_print_property_value(name, expected_value, value, good ? s : "[unprintable]");
                 }
 
                 return 1;
@@ -707,7 +721,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (expected_value && parse_boolean(expected_value) != b)
                         return 1;
 
-                bus_print_property_value(name, NULL, value, "%s", yes_no(b));
+                bus_print_property_value(name, NULL, value, yes_no(b));
                 return 1;
         }
 
@@ -728,13 +742,13 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
 
                         t = format_timestamp(timestamp, sizeof(timestamp), u);
                         if (t || all)
-                                bus_print_property_value(name, expected_value, value, "%s", strempty(t));
+                                bus_print_property_value(name, expected_value, value, strempty(t));
 
                 } else if (strstr(name, "USec")) {
                         char timespan[FORMAT_TIMESPAN_MAX];
 
                         (void) format_timespan(timespan, sizeof(timespan), u, 0);
-                        bus_print_property_value(name, expected_value, value, "%s", timespan);
+                        bus_print_property_value(name, expected_value, value, timespan);
 
                 } else if (streq(name, "RestrictNamespaces")) {
                         _cleanup_free_ char *s = NULL;
@@ -752,7 +766,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                                 result = s;
                         }
 
-                        bus_print_property_value(name, expected_value, value, "%s", result);
+                        bus_print_property_value(name, expected_value, value, result);
 
                 } else if (streq(name, "MountFlags")) {
                         const char *result;
@@ -761,7 +775,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (!result)
                                 return -EINVAL;
 
-                        bus_print_property_value(name, expected_value, value, "%s", result);
+                        bus_print_property_value(name, expected_value, value, result);
 
                 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
                         _cleanup_free_ char *s = NULL;
@@ -770,7 +784,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         if (r < 0)
                                 return r;
 
-                        bus_print_property_value(name, expected_value, value, "%s", s);
+                        bus_print_property_value(name, expected_value, value, s);
 
                 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
                            (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
@@ -778,16 +792,18 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                            (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
                            (endswith(name, "NSec") && u == (uint64_t) -1))
 
-                        bus_print_property_value(name, expected_value, value, "%s", "[not set]");
+                        bus_print_property_value(name, expected_value, value, "[not set]");
 
                 else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
                          (startswith(name, "Limit") && u == (uint64_t) -1) ||
                          (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
 
-                        bus_print_property_value(name, expected_value, value, "%s", "infinity");
+                        bus_print_property_value(name, expected_value, value, "infinity");
+                else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == (uint64_t) -1)
+                        bus_print_property_value(name, expected_value, value, "[no data]");
                 else
-                        bus_print_property_value(name, expected_value, value, "%"PRIu64, u);
+                        bus_print_property_valuef(name, expected_value, value, "%"PRIu64, u);
 
                 return 1;
         }
@@ -799,7 +815,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                bus_print_property_value(name, expected_value, value, "%"PRIi64, i);
+                bus_print_property_valuef(name, expected_value, value, "%"PRIi64, i);
                 return 1;
         }
 
@@ -811,20 +827,20 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                         return r;
 
                 if (strstr(name, "UMask") || strstr(name, "Mode"))
-                        bus_print_property_value(name, expected_value, value, "%04o", u);
+                        bus_print_property_valuef(name, expected_value, value, "%04o", u);
 
                 else if (streq(name, "UID")) {
                         if (u == UID_INVALID)
-                                bus_print_property_value(name, expected_value, value, "%s", "[not set]");
+                                bus_print_property_value(name, expected_value, value, "[not set]");
                         else
-                                bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+                                bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
                 } else if (streq(name, "GID")) {
                         if (u == GID_INVALID)
-                                bus_print_property_value(name, expected_value, value, "%s", "[not set]");
+                                bus_print_property_value(name, expected_value, value, "[not set]");
                         else
-                                bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+                                bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
                 } else
-                        bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+                        bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
 
                 return 1;
         }
@@ -836,7 +852,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                bus_print_property_value(name, expected_value, value, "%"PRIi32, i);
+                bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
                 return 1;
         }
 
@@ -847,7 +863,7 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
                 if (r < 0)
                         return r;
 
-                bus_print_property_value(name, expected_value, value, "%g", d);
+                bus_print_property_valuef(name, expected_value, value, "%g", d);
                 return 1;
         }
 
index 71c248fe3c7106ded9f3fd587b80e48deedf9854..2e42c45740be3c02c96f7dfeb9c9628327284bfc 100644 (file)
@@ -64,7 +64,8 @@ int bus_connect_transport_systemd(BusTransport transport, const char *host, bool
 
 typedef int (*bus_message_print_t) (const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all);
 
-int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) _printf_(4,5);
+int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value);
+int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) _printf_(4,5);
 int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties);
 
index 26f905bfaa6c2c39405e95846b7c2e4265458a21..04c0a697b4803fc31b6691370097c85a1d4d1172 100644 (file)
@@ -223,7 +223,7 @@ int efi_get_variable(
         if (fstat(fd, &st) < 0)
                 return -errno;
         if (st.st_size < 4)
-                return -EIO;
+                return -ENODATA;
         if (st.st_size > 4*1024*1024 + 4)
                 return -E2BIG;
 
@@ -789,16 +789,6 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
         return 0;
 }
 
-bool efi_loader_entry_name_valid(const char *s) {
-        if (isempty(s))
-                return false;
-
-        if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */
-                return false;
-
-        return in_charset(s, ALPHANUMERICAL "-");
-}
-
 int efi_loader_get_entries(char ***ret) {
         _cleanup_free_ char16_t *entries = NULL;
         _cleanup_strv_free_ char **l = NULL;
@@ -903,6 +893,16 @@ int efi_loader_get_features(uint64_t *ret) {
 
 #endif
 
+bool efi_loader_entry_name_valid(const char *s) {
+        if (isempty(s))
+                return false;
+
+        if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */
+                return false;
+
+        return in_charset(s, ALPHANUMERICAL "-_.");
+}
+
 char *efi_tilt_backslashes(char *s) {
         char *p;
 
index 92670c82c7d9c2aa5a59c248178f3071b6b14d9c..d8f18aae90e1d3bb893295e760c5d1fbd45d8ccb 100644 (file)
@@ -50,8 +50,6 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader);
 
 int efi_loader_get_entries(char ***ret);
 
-bool efi_loader_entry_name_valid(const char *s);
-
 int efi_loader_get_features(uint64_t *ret);
 
 #else
@@ -138,4 +136,6 @@ static inline int efi_loader_get_features(uint64_t *ret) {
 
 #endif
 
+bool efi_loader_entry_name_valid(const char *s);
+
 char *efi_tilt_backslashes(char *s);
index f46ea682042751d3d9f869400b69b74f4c093ac5..2a858d4cc4fcc5c2a2b6d29bd4e8e235eff87b51 100644 (file)
@@ -3164,7 +3164,7 @@ int json_log_internal(
                                 "CONFIG_FILE=%s", source,
                                 "CONFIG_LINE=%u", source_line,
                                 "CONFIG_COLUMN=%u", source_column,
-                                LOG_MESSAGE("%s:%u: %s", source, line, buffer),
+                                LOG_MESSAGE("%s:%u:%u: %s", source, source_line, source_column, buffer),
                                 NULL);
         else
                 return log_struct_internal(
index 4200032b3b6c15aeaddedae3cdc3ae4c35cb0268..6847d715f6660f58504489865b692f5357ab0922 100644 (file)
@@ -169,3 +169,15 @@ int device_wait_for_initialization(sd_device *device, const char *subsystem, sd_
                 *ret = TAKE_PTR(data.device);
         return 0;
 }
+
+int device_is_renaming(sd_device *dev) {
+        int r;
+
+        assert(dev);
+
+        r = sd_device_get_property_value(dev, "ID_RENAMING", NULL);
+        if (r < 0 && r != -ENOENT)
+                return r;
+
+        return r >= 0;
+}
index 932c4a9cd5f6083e8329f1d79c4830fa1188f9d0..c45d6a11fd7838ad80e15a3b0a4e2bdb95973c5a 100644 (file)
@@ -27,3 +27,4 @@ static inline int udev_parse_config(void) {
 }
 
 int device_wait_for_initialization(sd_device *device, const char *subsystem, sd_device **ret);
+int device_is_renaming(sd_device *dev);
diff --git a/src/shutdown/meson.build b/src/shutdown/meson.build
new file mode 100644 (file)
index 0000000..ebf0bed
--- /dev/null
@@ -0,0 +1,5 @@
+systemd_shutdown_sources = files('''
+        shutdown.c
+        umount.c
+        umount.h
+'''.split())
similarity index 97%
rename from src/core/shutdown.c
rename to src/shutdown/shutdown.c
index 56e9a2480ae046f0b3cd6b33f55974d6aa744717..842ba57f1306f466a8624fb065e7bac482c62b75 100644 (file)
@@ -169,10 +169,10 @@ static int switch_root_initramfs(void) {
  * value input. For all other issues, report the failure and indicate that
  * the sync is not making progress.
  */
-static bool sync_making_progress(unsigned long long *prev_dirty) {
+static int sync_making_progress(unsigned long long *prev_dirty) {
         _cleanup_fclose_ FILE *f = NULL;
         unsigned long long val = 0;
-        bool r = false;
+        int ret;
 
         f = fopen("/proc/meminfo", "re");
         if (!f)
@@ -205,11 +205,9 @@ static bool sync_making_progress(unsigned long long *prev_dirty) {
                 val += ull;
         }
 
-        r = *prev_dirty > val;
-
+        ret = *prev_dirty > val;
         *prev_dirty = val;
-
-        return r;
+        return ret;
 }
 
 static void sync_with_progress(void) {
@@ -243,7 +241,7 @@ static void sync_with_progress(void) {
                 else if (r == -ETIMEDOUT) {
                         /* Reset the check counter if the "Dirty" value is
                          * decreasing */
-                        if (sync_making_progress(&dirty))
+                        if (sync_making_progress(&dirty) > 0)
                                 checks = 0;
                 } else {
                         log_error_errno(r, "Failed to sync filesystems and block devices: %m");
@@ -345,14 +343,14 @@ int main(int argc, char *argv[]) {
                 bool changed = false;
 
                 if (use_watchdog)
-                        watchdog_ping();
+                        (void) watchdog_ping();
 
                 /* Let's trim the cgroup tree on each iteration so
                    that we leave an empty cgroup tree around, so that
                    container managers get a nice notify event when we
                    are down */
                 if (cgroup)
-                        cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
+                        (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
 
                 if (need_umount) {
                         log_info("Unmounting file systems.");
@@ -442,7 +440,7 @@ int main(int argc, char *argv[]) {
         arguments[0] = NULL;
         arguments[1] = arg_verb;
         arguments[2] = NULL;
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
+        (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
 
         (void) rlimit_nofile_safe();
 
similarity index 100%
rename from src/core/umount.c
rename to src/shutdown/umount.c
similarity index 100%
rename from src/core/umount.h
rename to src/shutdown/umount.h
index 57e3111b8d661ae662b34ab2c83d6a170e6c20dd..38897ecefba7e2698a3a46269bfec36331183777 100644 (file)
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/mount.h>
 #include <sys/prctl.h>
 #include <sys/reboot.h>
 #include <sys/socket.h>
@@ -41,7 +42,9 @@
 #include "hostname-util.h"
 #include "initreq.h"
 #include "install.h"
+#include "in-addr-util.h"
 #include "io-util.h"
+#include "journal-util.h"
 #include "list.h"
 #include "locale-util.h"
 #include "log.h"
@@ -73,6 +76,7 @@
 #include "unit-def.h"
 #include "unit-name.h"
 #include "user-util.h"
+#include "utf8.h"
 #include "util.h"
 #include "utmp-wtmp.h"
 #include "verbs.h"
@@ -166,6 +170,8 @@ static unsigned arg_lines = 10;
 static OutputMode arg_output = OUTPUT_SHORT;
 static bool arg_plain = false;
 static bool arg_firmware_setup = false;
+static usec_t arg_boot_loader_menu = USEC_INFINITY;
+static const char *arg_boot_loader_entry = NULL;
 static bool arg_now = false;
 static bool arg_jobs_before = false;
 static bool arg_jobs_after = false;
@@ -3469,7 +3475,11 @@ static int logind_check_inhibitors(enum action a) {
 #endif
 }
 
-static int logind_prepare_firmware_setup(void) {
+static int prepare_firmware_setup(void) {
+
+        if (!arg_firmware_setup)
+                return 0;
+
 #if ENABLE_LOGIND
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus *bus;
@@ -3493,27 +3503,75 @@ static int logind_prepare_firmware_setup(void) {
 
         return 0;
 #else
-        log_error("Cannot remotely indicate to EFI to boot into setup mode.");
+        log_error("Booting into firmware setup not supported.");
         return -ENOSYS;
 #endif
 }
 
-static int prepare_firmware_setup(void) {
+static int prepare_boot_loader_menu(void) {
+
+        if (arg_boot_loader_menu == USEC_INFINITY)
+                return 0;
+
+#if ENABLE_LOGIND
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        sd_bus *bus;
         int r;
 
-        if (!arg_firmware_setup)
+        r = acquire_bus(BUS_FULL, &bus);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "SetRebootToBootLoaderMenu",
+                        &error,
+                        NULL,
+                        "t", arg_boot_loader_menu);
+        if (r < 0)
+                return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
+
+        return 0;
+#else
+        log_error("Booting into boot loader menu not supported.");
+        return -ENOSYS;
+#endif
+}
+
+static int prepare_boot_loader_entry(void) {
+
+        if (!arg_boot_loader_entry)
                 return 0;
 
-        if (arg_transport == BUS_TRANSPORT_LOCAL) {
+#if ENABLE_LOGIND
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        sd_bus *bus;
+        int r;
+
+        r = acquire_bus(BUS_FULL, &bus);
+        if (r < 0)
+                return r;
 
-                r = efi_set_reboot_to_firmware(true);
-                if (r < 0)
-                        log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
-                else
-                        return r;
-        }
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "SetRebootToBootLoaderEntry",
+                        &error,
+                        NULL,
+                        "s", arg_boot_loader_entry);
+        if (r < 0)
+                return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
 
-        return logind_prepare_firmware_setup();
+        return 0;
+#else
+        log_error("Booting into boot loader entry not supported.");
+        return -ENOSYS;
+#endif
 }
 
 static int load_kexec_kernel(void) {
@@ -3531,15 +3589,22 @@ static int load_kexec_kernel(void) {
         if (access(KEXEC, X_OK) < 0)
                 return log_error_errno(errno, KEXEC" is not available: %m");
 
-        r = find_default_boot_entry(NULL, NULL, &config, &e);
-        if (r == -ENOKEY) /* find_default_boot_entry() doesn't warn about this case */
-                return log_error_errno(r, "Cannot find the ESP partition mount point.");
+        r = boot_entries_load_config_auto(NULL, NULL, &config);
         if (r < 0)
-                /* But it logs about all these cases, hence don't log here again */
                 return r;
 
+        e = boot_config_default_entry(&config);
+        if (!e)
+                return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+                                       "No boot loader entry suitable as default, refusing to guess.");
+
+        log_debug("Found default boot loader entry in file \"%s\"", e->path);
+
+        if (!e->kernel)
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                       "Boot entry does not refer to Linux kernel, which is not supported currently.");
         if (strv_length(e->initrd) > 1)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
                                        "Boot entry specifies multiple initrds, which is not supported currently.");
 
         kernel = path_join(e->root, e->kernel);
@@ -3547,7 +3612,7 @@ static int load_kexec_kernel(void) {
                 return log_oom();
 
         if (!strv_isempty(e->initrd)) {
-                initrd = path_join(e->root, *e->initrd);
+                initrd = path_join(e->root, e->initrd[0]);
                 if (!initrd)
                         return log_oom();
         }
@@ -3565,7 +3630,7 @@ static int load_kexec_kernel(void) {
         if (arg_dry_run)
                 return 0;
 
-        r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+        r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
@@ -3574,19 +3639,14 @@ static int load_kexec_kernel(void) {
                         "--load", kernel,
                         "--append", options,
                         initrd ? "--initrd" : NULL, initrd,
-                        NULL };
+                        NULL
+                };
 
                 /* Child */
                 execv(args[0], (char * const *) args);
                 _exit(EXIT_FAILURE);
         }
 
-        r = wait_for_terminate_and_check("kexec", pid, WAIT_LOG);
-        if (r < 0)
-                return r;
-        if (r > 0)
-                /* Command failed */
-                return -EPROTO;
         return 0;
 }
 
@@ -3638,6 +3698,14 @@ static int start_special(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
+        r = prepare_boot_loader_menu();
+        if (r < 0)
+                return r;
+
+        r = prepare_boot_loader_entry();
+        if (r < 0)
+                return r;
+
         if (a == ACTION_REBOOT && argc > 1) {
                 r = update_reboot_parameter_and_warn(argv[1]);
                 if (r < 0)
@@ -4669,6 +4737,23 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
 
         switch (bus_type) {
 
+        case SD_BUS_TYPE_INT32:
+                if (endswith(name, "ActionExitStatus")) {
+                        int32_t i;
+
+                        r = sd_bus_message_read_basic(m, bus_type, &i);
+                        if (r < 0)
+                                return r;
+
+                        if (i >= 0 && i <= 255)
+                                bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i);
+                        else if (all)
+                                bus_print_property_value(name, expected_value, value, "[not set]");
+
+                        return 1;
+                }
+                break;
+
         case SD_BUS_TYPE_STRUCT:
 
                 if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
@@ -4679,9 +4764,9 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         if (u > 0)
-                                bus_print_property_value(name, expected_value, value, "%"PRIu32, u);
+                                bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u);
                         else if (all)
-                                bus_print_property_value(name, expected_value, value, "%s", "");
+                                bus_print_property_value(name, expected_value, value, "");
 
                         return 1;
 
@@ -4693,7 +4778,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         if (all || !isempty(s))
-                                bus_print_property_value(name, expected_value, value, "%s", s);
+                                bus_print_property_value(name, expected_value, value, s);
 
                         return 1;
 
@@ -4704,11 +4789,14 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        if (all || !isempty(a) || !isempty(b))
-                                bus_print_property_value(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
+                        if (!isempty(a) || !isempty(b))
+                                bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b));
+                        else if (all)
+                                bus_print_property_value(name, expected_value, value, "");
 
                         return 1;
-                } else if (streq_ptr(name, "SystemCallFilter")) {
+
+                } else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) {
                         _cleanup_strv_free_ char **l = NULL;
                         int whitelist;
 
@@ -4752,6 +4840,83 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         }
 
                         return 1;
+
+                } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) {
+                        int ignore;
+                        const char *s;
+
+                        r = sd_bus_message_read(m, "(bs)", &ignore, &s);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (!isempty(s))
+                                bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s);
+                        else if (all)
+                                bus_print_property_value(name, expected_value, value, "");
+
+                        return 1;
+
+                } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) {
+                        const int32_t *status, *signal;
+                        size_t sz_status, sz_signal, i;
+
+                        r = sd_bus_message_enter_container(m, 'r', "aiai");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_read_array(m, 'i', (const void **) &status, &sz_status);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &sz_signal);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        sz_status /= sizeof(int32_t);
+                        sz_signal /= sizeof(int32_t);
+
+                        if (all || sz_status > 0 || sz_signal > 0) {
+                                bool first = true;
+
+                                if (!value) {
+                                        fputs(name, stdout);
+                                        fputc('=', stdout);
+                                }
+
+                                for (i = 0; i < sz_status; i++) {
+                                        if (status[i] < 0 || status[i] > 255)
+                                                continue;
+
+                                        if (first)
+                                                first = false;
+                                        else
+                                                fputc(' ', stdout);
+
+                                        printf("%"PRIi32, status[i]);
+                                }
+
+                                for (i = 0; i < sz_signal; i++) {
+                                        const char *str;
+
+                                        str = signal_to_string((int) signal[i]);
+                                        if (!str)
+                                                continue;
+
+                                        if (first)
+                                                first = false;
+                                        else
+                                                fputc(' ', stdout);
+
+                                        fputs(str, stdout);
+                                }
+
+                                fputc('\n', stdout);
+                        }
+                        return 1;
                 }
 
                 break;
@@ -4767,7 +4932,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
+                                bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore));
 
                         if (r < 0)
                                 return bus_log_parse_error(r);
@@ -4786,7 +4951,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s (%s)", path, type);
+                                bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -4804,7 +4969,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s (%s)", path, type);
+                                bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -4825,9 +4990,9 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) {
                                 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
 
-                                bus_print_property_value(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base,
-                                                         format_timespan(timespan1, sizeof(timespan1), v, 0),
-                                                         format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
+                                bus_print_property_valuef(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base,
+                                                          format_timespan(timespan1, sizeof(timespan1), v, 0),
+                                                          format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
                         }
                         if (r < 0)
                                 return bus_log_parse_error(r);
@@ -4849,8 +5014,8 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) {
                                 char timestamp[FORMAT_TIMESTAMP_MAX];
 
-                                bus_print_property_value(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base, spec,
-                                                         format_timestamp(timestamp, sizeof(timestamp), next_elapse));
+                                bus_print_property_valuef(name, expected_value, value, "{ %s=%s ; next_elapse=%s }", base, spec,
+                                                          format_timestamp(timestamp, sizeof(timestamp), next_elapse));
                         }
                         if (r < 0)
                                 return bus_log_parse_error(r);
@@ -4874,18 +5039,18 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
 
                                 tt = strv_join(info.argv, " ");
 
-                                 bus_print_property_value(name, expected_value, value,
-                                                          "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
-                                                          strna(info.path),
-                                                          strna(tt),
-                                                          yes_no(info.ignore),
-                                                          strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
-                                                          strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
-                                                          info.pid,
-                                                          sigchld_code_to_string(info.code),
-                                                          info.status,
-                                                          info.code == CLD_EXITED ? "" : "/",
-                                                          strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
+                                 bus_print_property_valuef(name, expected_value, value,
+                                                           "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
+                                                           strna(info.path),
+                                                           strna(tt),
+                                                           yes_no(info.ignore),
+                                                           strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
+                                                           strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
+                                                           info.pid,
+                                                           sigchld_code_to_string(info.code),
+                                                           info.status,
+                                                           info.code == CLD_EXITED ? "" : "/",
+                                                           strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
 
                                 free(info.path);
                                 strv_free(info.argv);
@@ -4906,7 +5071,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s %s", strna(path), strna(rwm));
+                                bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm));
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -4926,7 +5091,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
+                                bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -4947,7 +5112,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
+                                bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -4968,8 +5133,8 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                 return bus_log_parse_error(r);
 
                         while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0)
-                                bus_print_property_value(name, expected_value, value, "%s %s", strna(path),
-                                                         format_timespan(ts, sizeof(ts), target, 1));
+                                bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path),
+                                                          format_timespan(ts, sizeof(ts), target, 1));
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
@@ -4993,7 +5158,187 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         if (n < 0)
                                 return log_oom();
 
-                        bus_print_property_value(name, expected_value, value, "%s", h);
+                        bus_print_property_value(name, expected_value, value, h);
+
+                        return 1;
+
+                } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
+                        _cleanup_free_ char *addresses = NULL;
+
+                        r = sd_bus_message_enter_container(m, 'a', "(iayu)");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        for (;;) {
+                                _cleanup_free_ char *str = NULL;
+                                uint32_t prefixlen;
+                                int32_t family;
+                                const void *ap;
+                                size_t an;
+
+                                r = sd_bus_message_enter_container(m, 'r', "iayu");
+                                if (r < 0)
+                                        return bus_log_parse_error(r);
+                                if (r == 0)
+                                        break;
+
+                                r = sd_bus_message_read(m, "i", &family);
+                                if (r < 0)
+                                        return bus_log_parse_error(r);
+
+                                r = sd_bus_message_read_array(m, 'y', &ap, &an);
+                                if (r < 0)
+                                        return bus_log_parse_error(r);
+
+                                r = sd_bus_message_read(m, "u", &prefixlen);
+                                if (r < 0)
+                                        return bus_log_parse_error(r);
+
+                                r = sd_bus_message_exit_container(m);
+                                if (r < 0)
+                                        return bus_log_parse_error(r);
+
+                                if (!IN_SET(family, AF_INET, AF_INET6))
+                                        continue;
+
+                                if (an != FAMILY_ADDRESS_SIZE(family))
+                                        continue;
+
+                                if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
+                                        continue;
+
+                                if (in_addr_prefix_to_string(family, (union in_addr_union *) ap, prefixlen, &str) < 0)
+                                        continue;
+
+                                if (!strextend_with_separator(&addresses, " ", str, NULL))
+                                        return log_oom();
+                        }
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (all || !isempty(addresses))
+                                bus_print_property_value(name, expected_value, value, strempty(addresses));
+
+                        return 1;
+
+                } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) {
+                        _cleanup_free_ char *paths = NULL;
+                        const char *source, *dest;
+                        int ignore_enoent;
+                        uint64_t rbind;
+
+                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) {
+                                _cleanup_free_ char *str = NULL;
+
+                                if (isempty(source))
+                                        continue;
+
+                                if (asprintf(&str, "%s%s%s%s%s",
+                                             ignore_enoent ? "-" : "",
+                                             source,
+                                             isempty(dest) ? "" : ":",
+                                             strempty(dest),
+                                             rbind == MS_REC ? ":rbind" : "") < 0)
+                                        return log_oom();
+
+                                if (!strextend_with_separator(&paths, " ", str, NULL))
+                                        return log_oom();
+                        }
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (all || !isempty(paths))
+                                bus_print_property_value(name, expected_value, value, strempty(paths));
+
+                        return 1;
+
+                } else if (streq(name, "TemporaryFileSystem")) {
+                        _cleanup_free_ char *paths = NULL;
+                        const char *target, *option;
+
+                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) {
+                                _cleanup_free_ char *str = NULL;
+
+                                if (isempty(target))
+                                        continue;
+
+                                if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0)
+                                        return log_oom();
+
+                                if (!strextend_with_separator(&paths, " ", str, NULL))
+                                        return log_oom();
+                        }
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (all || !isempty(paths))
+                                bus_print_property_value(name, expected_value, value, strempty(paths));
+
+                        return 1;
+
+                } else if (streq(name, "LogExtraFields")) {
+                        _cleanup_free_ char *fields = NULL;
+                        const void *p;
+                        size_t sz;
+
+                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) {
+                                _cleanup_free_ char *str = NULL;
+                                const char *eq;
+
+                                if (memchr(p, 0, sz))
+                                        continue;
+
+                                eq = memchr(p, '=', sz);
+                                if (!eq)
+                                        continue;
+
+                                if (!journal_field_valid(p, eq - (const char*) p, false))
+                                        continue;
+
+                                str = malloc(sz + 1);
+                                if (!str)
+                                        return log_oom();
+
+                                memcpy(str, p, sz);
+                                str[sz] = '\0';
+
+                                if (!utf8_is_valid(str))
+                                        continue;
+
+                                if (!strextend_with_separator(&fields, " ", str, NULL))
+                                        return log_oom();
+                        }
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (all || !isempty(fields))
+                                bus_print_property_value(name, expected_value, value, strempty(fields));
 
                         return 1;
                 }
@@ -7239,6 +7584,10 @@ static int systemctl_help(void) {
                "                             short-monotonic, short-unix,\n"
                "                             verbose, export, json, json-pretty, json-sse, cat)\n"
                "     --firmware-setup Tell the firmware to show the setup menu on next boot\n"
+               "     --boot-loader-menu=TIME\n"
+               "                      Boot into boot loader menu on next boot\n"
+               "     --boot-loader-entry=NAME\n"
+               "                      Boot into a specific boot loader entry on next boot\n"
                "     --plain          Print unit dependencies as a list instead of a tree\n\n"
                "Unit Commands:\n"
                "  list-units [PATTERN...]             List units currently in memory\n"
@@ -7493,6 +7842,39 @@ static void help_states(void) {
         DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
 }
 
+static int help_boot_loader_entry(void) {
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char **l = NULL;
+        sd_bus *bus;
+        char **i;
+        int r;
+
+        r = acquire_bus(BUS_FULL, &bus);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_get_property_strv(
+                        bus,
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "BootLoaderEntries",
+                        &error,
+                        &l);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
+
+        if (strv_isempty(l)) {
+                log_error("No boot loader entries discovered.");
+                return -ENODATA;
+        }
+
+        STRV_FOREACH(i, l)
+                puts(*i);
+
+        return 0;
+}
+
 static int systemctl_parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_FAIL = 0x100,
@@ -7523,6 +7905,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_JOB_MODE,
                 ARG_PRESET_MODE,
                 ARG_FIRMWARE_SETUP,
+                ARG_BOOT_LOADER_MENU,
+                ARG_BOOT_LOADER_ENTRY,
                 ARG_NOW,
                 ARG_MESSAGE,
                 ARG_WAIT,
@@ -7572,6 +7956,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "recursive",           no_argument,       NULL, 'r'                     },
                 { "preset-mode",         required_argument, NULL, ARG_PRESET_MODE         },
                 { "firmware-setup",      no_argument,       NULL, ARG_FIRMWARE_SETUP      },
+                { "boot-loader-menu",    required_argument, NULL, ARG_BOOT_LOADER_MENU    },
+                { "boot-loader-entry",   required_argument, NULL, ARG_BOOT_LOADER_ENTRY   },
                 { "now",                 no_argument,       NULL, ARG_NOW                 },
                 { "message",             required_argument, NULL, ARG_MESSAGE             },
                 {}
@@ -7845,6 +8231,27 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_firmware_setup = true;
                         break;
 
+                case ARG_BOOT_LOADER_MENU:
+
+                        r = parse_sec(optarg, &arg_boot_loader_menu);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg);
+
+                        break;
+
+                case ARG_BOOT_LOADER_ENTRY:
+
+                        if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */
+                                r = help_boot_loader_entry();
+                                if (r < 0)
+                                        return r;
+
+                                return 0;
+                        }
+
+                        arg_boot_loader_entry = empty_to_null(optarg);
+                        break;
+
                 case ARG_STATE: {
                         if (isempty(optarg))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
index c53b9653f95222bacdc9a025da5f99ccb85829e9..19f7a1e48647667e57984b4e3f60aa468879bcc3 100644 (file)
@@ -714,11 +714,10 @@ tests += [
          'ENABLE_NSS', 'manual'],
 
         [['src/test/test-umount.c',
-          'src/core/mount-setup.c',
-          'src/core/mount-setup.h',
-          'src/core/umount.c',
-          'src/core/umount.h'],
-         [],
+          'src/shutdown/umount.c',
+          'src/shutdown/umount.h'],
+         [libcore_shared,
+          libshared],
          [libmount]],
 
         [['src/test/test-bus-util.c'],
index 305d44f568b001f01fd3a1f2ca9919e12d0199a8..9e14672b2fab61f5cf15f1a07be77628e683e291 100644 (file)
@@ -43,6 +43,8 @@ static void test_chown_recursive(void) {
         _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
         struct stat st;
         const char *p;
+        const uid_t uid = getuid();
+        const gid_t gid = getgid();
 
         umask(022);
         assert_se(mkdtemp_malloc(NULL, &t) >= 0);
@@ -52,8 +54,8 @@ static void test_chown_recursive(void) {
         assert_se(lstat(p, &st) >= 0);
         assert_se(S_ISDIR(st.st_mode));
         assert_se((st.st_mode & 07777) == 0755);
-        assert_se(st.st_uid == 0);
-        assert_se(st.st_gid == 0);
+        assert_se(st.st_uid == uid);
+        assert_se(st.st_gid == gid);
         assert_se(!has_xattr(p));
 
         p = strjoina(t, "/dir/symlink");
@@ -61,8 +63,8 @@ static void test_chown_recursive(void) {
         assert_se(lstat(p, &st) >= 0);
         assert_se(S_ISLNK(st.st_mode));
         assert_se((st.st_mode & 07777) == 0777);
-        assert_se(st.st_uid == 0);
-        assert_se(st.st_gid == 0);
+        assert_se(st.st_uid == uid);
+        assert_se(st.st_gid == gid);
         assert_se(!has_xattr(p));
 
         p = strjoina(t, "/dir/reg");
@@ -70,8 +72,8 @@ static void test_chown_recursive(void) {
         assert_se(lstat(p, &st) >= 0);
         assert_se(S_ISREG(st.st_mode));
         assert_se((st.st_mode & 07777) == 0755);
-        assert_se(st.st_uid == 0);
-        assert_se(st.st_gid == 0);
+        assert_se(st.st_uid == uid);
+        assert_se(st.st_gid == gid);
         assert_se(!has_xattr(p));
 
         p = strjoina(t, "/dir/sock");
@@ -79,8 +81,8 @@ static void test_chown_recursive(void) {
         assert_se(lstat(p, &st) >= 0);
         assert_se(S_ISSOCK(st.st_mode));
         assert_se((st.st_mode & 07777) == 0755);
-        assert_se(st.st_uid == 0);
-        assert_se(st.st_gid == 0);
+        assert_se(st.st_uid == uid);
+        assert_se(st.st_gid == gid);
         assert_se(!has_xattr(p));
 
         p = strjoina(t, "/dir/fifo");
@@ -88,8 +90,8 @@ static void test_chown_recursive(void) {
         assert_se(lstat(p, &st) >= 0);
         assert_se(S_ISFIFO(st.st_mode));
         assert_se((st.st_mode & 07777) == 0755);
-        assert_se(st.st_uid == 0);
-        assert_se(st.st_gid == 0);
+        assert_se(st.st_uid == uid);
+        assert_se(st.st_gid == gid);
         assert_se(!has_xattr(p));
 
         /* We now apply an xattr to the dir, and check it again */
@@ -99,8 +101,8 @@ static void test_chown_recursive(void) {
         assert_se(lstat(p, &st) >= 0);
         assert_se(S_ISDIR(st.st_mode));
         assert_se((st.st_mode & 07777) == 0775); /* acl change changed the mode too */
-        assert_se(st.st_uid == 0);
-        assert_se(st.st_gid == 0);
+        assert_se(st.st_uid == uid);
+        assert_se(st.st_gid == gid);
         assert_se(has_xattr(p));
 
         assert_se(path_chown_recursive(t, 1, 2) >= 0);
index 195711215938dcc69cd9a6743a5742d49cbf5c5e..b34b207a40824740f6cf79da52611bd30209dc56 100644 (file)
@@ -714,7 +714,6 @@ static int run_tests(UnitFileScope scope, const test_function_t *tests) {
 int main(int argc, char *argv[]) {
         _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
         _cleanup_free_ char *test_execute_path = NULL;
-        _cleanup_hashmap_free_ Hashmap *s = NULL;
         static const test_function_t user_tests[] = {
                 test_exec_basic,
                 test_exec_ambientcapabilities,
@@ -812,6 +811,7 @@ int main(int argc, char *argv[]) {
                 return 0;
         }
 
+        _cleanup_hashmap_free_ Hashmap *s = NULL;
         assert_se(s = hashmap_new(NULL));
         r = seccomp_syscall_resolve_name("unshare");
         assert_se(r != __NR_SCMP_ERROR);
index e049abc4a40b03ee66c6d55e7b249024112d477b..f0f015056e24d78c73e2625bbd91dfa8933fa801 100644 (file)
@@ -154,6 +154,30 @@ static void test_chase_symlinks(void) {
         assert_se(path_equal(result, q));
         result = mfree(result);
 
+        /* Paths underneath the "root" with different UIDs while using CHASE_SAFE */
+
+        if (geteuid() == 0) {
+                p = strjoina(temp, "/user");
+                assert_se(mkdir(p, 0755) >= 0);
+                assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0);
+
+                q = strjoina(temp, "/user/root");
+                assert_se(mkdir(q, 0755) >= 0);
+
+                p = strjoina(q, "/link");
+                assert_se(symlink("/", p) >= 0);
+
+                /* Fail when user-owned directories contain root-owned subdirectories. */
+                r = chase_symlinks(p, temp, CHASE_SAFE, &result);
+                assert_se(r == -ENOLINK);
+                result = mfree(result);
+
+                /* Allow this when the user-owned directories are all in the "root". */
+                r = chase_symlinks(p, q, CHASE_SAFE, &result);
+                assert_se(r > 0);
+                result = mfree(result);
+        }
+
         /* Paths using . */
 
         r = chase_symlinks("/etc/./.././", NULL, 0, &result);
index 16844e95652533316e24cebf1da05bffc8b56abc..916bd35f0d7e835850f5183f230f413f12abe0bb 100644 (file)
@@ -1,11 +1,13 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <fnmatch.h>
 #include <netinet/in.h>
 
 #include "log.h"
+#include "strv.h"
 #include "in-addr-util.h"
 
-static void test_in_addr_prefix_from_string(
+static void test_in_addr_prefix_from_string_one(
                 const char *p,
                 int family,
                 int ret,
@@ -55,32 +57,130 @@ static void test_in_addr_prefix_from_string(
         }
 }
 
+static void test_in_addr_prefix_from_string(void) {
+        test_in_addr_prefix_from_string_one("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+        test_in_addr_prefix_from_string_one("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+        test_in_addr_prefix_from_string_one("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+        test_in_addr_prefix_from_string_one("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8);
+        test_in_addr_prefix_from_string_one("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0);
+        test_in_addr_prefix_from_string_one("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1);
+        test_in_addr_prefix_from_string_one("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2);
+        test_in_addr_prefix_from_string_one("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32);
+        test_in_addr_prefix_from_string_one("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+        test_in_addr_prefix_from_string_one("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+        test_in_addr_prefix_from_string_one("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+
+        test_in_addr_prefix_from_string_one("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+        test_in_addr_prefix_from_string_one("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+        test_in_addr_prefix_from_string_one("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
+        test_in_addr_prefix_from_string_one("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0);
+        test_in_addr_prefix_from_string_one("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0);
+        test_in_addr_prefix_from_string_one("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1);
+        test_in_addr_prefix_from_string_one("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2);
+        test_in_addr_prefix_from_string_one("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32);
+        test_in_addr_prefix_from_string_one("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33);
+        test_in_addr_prefix_from_string_one("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64);
+        test_in_addr_prefix_from_string_one("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128);
+        test_in_addr_prefix_from_string_one("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+        test_in_addr_prefix_from_string_one("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+}
+
+static void test_in_addr_prefix_to_string_valid(int family, const char *p) {
+        _cleanup_free_ char *str = NULL;
+        union in_addr_union u;
+        unsigned char l;
+
+        log_info("/* %s */", p);
+
+        assert_se(in_addr_prefix_from_string(p, family, &u, &l) >= 0);
+        assert_se(in_addr_prefix_to_string(family, &u, l, &str) >= 0);
+        assert_se(streq(str, p));
+}
+
+static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) {
+        _cleanup_free_ char *str1 = NULL, *str2 = NULL;
+        union in_addr_union u1, u2;
+        unsigned char len1, len2;
+
+        log_info("/* %s */", p);
+
+        assert_se(in_addr_prefix_from_string(p, family, &u1, &len1) >= 0);
+        assert_se(in_addr_prefix_to_string(family, &u1, len1, &str1) >= 0);
+        assert_se(in_addr_prefix_from_string(str1, family, &u2, &len2) >= 0);
+        assert_se(in_addr_prefix_to_string(family, &u2, len2, &str2) >= 0);
+
+        assert_se(streq(str1, str2));
+        assert_se(len1 == len2);
+        assert_se(in_addr_equal(family, &u1, &u2) > 0);
+}
+
+static void test_in_addr_prefix_to_string(void) {
+        test_in_addr_prefix_to_string_valid(AF_INET, "0.0.0.0/32");
+        test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/0");
+        test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/24");
+        test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/32");
+        test_in_addr_prefix_to_string_valid(AF_INET, "255.255.255.255/32");
+
+        test_in_addr_prefix_to_string_valid(AF_INET6, "::1/128");
+        test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1/64");
+        test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1234:1/64");
+        test_in_addr_prefix_to_string_valid(AF_INET6, "1111:2222:3333:4444:5555:6666:7777:8888/128");
+
+        test_in_addr_prefix_to_string_unoptimized(AF_INET, "0.0.0.0");
+        test_in_addr_prefix_to_string_unoptimized(AF_INET, "192.168.0.1");
+
+        test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:0000:0000:0000:0000:0000:0000:0001/64");
+        test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:1111::0000:2222:3333:4444:0001/64");
+}
+
+static void test_in_addr_random_prefix(void) {
+        _cleanup_free_ char *str = NULL;
+        union in_addr_union a;
+
+        assert_se(in_addr_from_string(AF_INET, "192.168.10.1", &a) >= 0);
+
+        assert_se(in_addr_random_prefix(AF_INET, &a, 31, 32) >= 0);
+        assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+        assert_se(STR_IN_SET(str, "192.168.10.0", "192.168.10.1"));
+        str = mfree(str);
+
+        assert_se(in_addr_random_prefix(AF_INET, &a, 24, 26) >= 0);
+        assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+        assert_se(startswith(str, "192.168.10."));
+        str = mfree(str);
+
+        assert_se(in_addr_random_prefix(AF_INET, &a, 16, 24) >= 0);
+        assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+        assert_se(fnmatch("192.168.[0-9]*.0", str, 0) == 0);
+        str = mfree(str);
+
+        assert_se(in_addr_random_prefix(AF_INET, &a, 8, 24) >= 0);
+        assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+        assert_se(fnmatch("192.[0-9]*.[0-9]*.0", str, 0) == 0);
+        str = mfree(str);
+
+        assert_se(in_addr_random_prefix(AF_INET, &a, 8, 16) >= 0);
+        assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0);
+        assert_se(fnmatch("192.[0-9]*.0.0", str, 0) == 0);
+        str = mfree(str);
+
+        assert_se(in_addr_from_string(AF_INET6, "fd00::1", &a) >= 0);
+
+        assert_se(in_addr_random_prefix(AF_INET6, &a, 16, 64) >= 0);
+        assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
+        assert_se(startswith(str, "fd00:"));
+        str = mfree(str);
+
+        assert_se(in_addr_random_prefix(AF_INET6, &a, 8, 16) >= 0);
+        assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0);
+        assert_se(fnmatch("fd??::", str, 0) == 0);
+        str = mfree(str);
+}
+
 int main(int argc, char *argv[]) {
-        test_in_addr_prefix_from_string("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-        test_in_addr_prefix_from_string("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-        test_in_addr_prefix_from_string("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-        test_in_addr_prefix_from_string("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8);
-        test_in_addr_prefix_from_string("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0);
-        test_in_addr_prefix_from_string("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1);
-        test_in_addr_prefix_from_string("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2);
-        test_in_addr_prefix_from_string("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32);
-        test_in_addr_prefix_from_string("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
-        test_in_addr_prefix_from_string("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
-        test_in_addr_prefix_from_string("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-
-        test_in_addr_prefix_from_string("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-        test_in_addr_prefix_from_string("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-        test_in_addr_prefix_from_string("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0);
-        test_in_addr_prefix_from_string("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0);
-        test_in_addr_prefix_from_string("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0);
-        test_in_addr_prefix_from_string("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1);
-        test_in_addr_prefix_from_string("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2);
-        test_in_addr_prefix_from_string("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32);
-        test_in_addr_prefix_from_string("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33);
-        test_in_addr_prefix_from_string("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64);
-        test_in_addr_prefix_from_string("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128);
-        test_in_addr_prefix_from_string("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
-        test_in_addr_prefix_from_string("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0);
+        test_in_addr_prefix_from_string();
+        test_in_addr_random_prefix();
+        test_in_addr_prefix_to_string();
 
         return 0;
 }
index 20aa6cf01ff9c15005c8ea2a6a6628a9d707eb6a..f1bba2a353fd0435833e315a847fdea9757b7c20 100644 (file)
 #include "in-addr-util.h"
 #include "local-addresses.h"
 #include "log.h"
+#include "main-func.h"
 #include "nss-util.h"
 #include "path-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
+#include "tests.h"
 
 static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) {
         switch (status) {
@@ -485,7 +487,7 @@ static int parse_argv(int argc, char **argv,
         return 0;
 }
 
-int main(int argc, char **argv) {
+static int run(int argc, char **argv) {
         _cleanup_free_ char *dir = NULL;
         _cleanup_strv_free_ char **modules = NULL, **names = NULL;
         _cleanup_free_ struct local_address *addresses = NULL;
@@ -493,8 +495,7 @@ int main(int argc, char **argv) {
         char **module;
         int r;
 
-        log_set_max_level(LOG_INFO);
-        log_parse_environment();
+        test_setup_logging(LOG_INFO);
 
         r = parse_argv(argc, argv, &modules, &names, &addresses, &n_addresses);
         if (r < 0) {
@@ -504,13 +505,15 @@ int main(int argc, char **argv) {
 
         dir = dirname_malloc(argv[0]);
         if (!dir)
-                return EXIT_FAILURE;
+                return log_oom();
 
         STRV_FOREACH(module, modules) {
                 r = test_one_module(dir, *module, names, addresses, n_addresses);
                 if (r < 0)
-                        return EXIT_FAILURE;
+                        return r;
         }
 
-        return EXIT_SUCCESS;
+        return 0;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 49268eae22766eba1520595ea67d4488d7dac920..070d1b4fe094fe7735a5e8b4ecd539c586fe009d 100644 (file)
@@ -5,7 +5,7 @@
 #include "cgroup.h"
 #include "compress.h"
 #include "condition.h"
-#include "device-internal.h"
+#include "device-private.h"
 #include "device.h"
 #include "execute.h"
 #include "import-util.h"
index 1e7b26276a9f61a2d0f8d65bc952b7fc812fa7c5..406ca1df6616d95b02ba84e288b78ee921a6282b 100644 (file)
@@ -670,7 +670,7 @@ static int print_timesync_property(const char *name, const char *expected_value,
                                 return r;
 
                         if (arg_all || !isempty(str))
-                                bus_print_property_value(name, expected_value, value, "%s", str);
+                                bus_print_property_value(name, expected_value, value, str);
 
                         return 1;
                 }
index eeb17b613e7f9d339c47ae4088733ec34724cefd..324d4a41c76634f89138b2896066ba17eecec95c 100644 (file)
@@ -377,9 +377,9 @@ static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *er
                         n += !!u->path;
 
         if (n == 0) {
-                (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
-
                 c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
+
+                (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
         }
 
         return 0;
index 6296a8acdf2dbf40bd4b4ac09d11647b0d1f7bbe..801e79b01d7c660025d8f65a6fc96c315f01c5a5 100644 (file)
@@ -856,7 +856,7 @@ static int path_open_parent_safe(const char *path) {
         if (!dn)
                 return log_oom();
 
-        fd = chase_symlinks(dn, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
+        fd = chase_symlinks(dn, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL);
         if (fd < 0 && fd != -ENOLINK)
                 return log_error_errno(fd, "Failed to validate path %s: %m", path);
 
@@ -877,7 +877,7 @@ static int path_open_safe(const char *path) {
                                        "Failed to open invalid path '%s'.",
                                        path);
 
-        fd = chase_symlinks(path, NULL, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
+        fd = chase_symlinks(path, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL);
         if (fd < 0 && fd != -ENOLINK)
                 return log_error_errno(fd, "Failed to validate path %s: %m", path);
 
@@ -2256,7 +2256,7 @@ static int process_item(Item *i, OperationMask operation) {
 
         i->done |= operation;
 
-        r = chase_symlinks(i->path, NULL, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
+        r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL);
         if (r == -EREMOTE) {
                 log_notice_errno(r, "Skipping %s", i->path);
                 return 0;
index 6f90516ff6dc0edfa3e0ffae1acbe9392043d104..cefc2f4445fd824d5649bba7697290b9bb87d91b 100644 (file)
@@ -71,8 +71,8 @@ UdevEvent *udev_event_free(UdevEvent *event) {
         sd_device_unref(event->dev);
         sd_device_unref(event->dev_db_clone);
         sd_netlink_unref(event->rtnl);
-        hashmap_free_free_key(event->run_list);
-        hashmap_free_free_free(event->seclabel_list);
+        ordered_hashmap_free_free_key(event->run_list);
+        ordered_hashmap_free_free_free(event->seclabel_list);
         free(event->program_result);
         free(event->name);
 
@@ -696,7 +696,6 @@ int udev_event_spawn(UdevEvent *event,
 static int rename_netif(UdevEvent *event) {
         sd_device *dev = event->dev;
         const char *action, *oldname;
-        char name[IFNAMSIZ];
         int ifindex, r;
 
         if (!event->name)
@@ -722,16 +721,21 @@ static int rename_netif(UdevEvent *event) {
         if (r < 0)
                 return log_device_error_errno(dev, r, "Failed to get ifindex: %m");
 
-        strscpy(name, IFNAMSIZ, event->name);
-        r = rtnl_set_link_name(&event->rtnl, ifindex, name);
+        r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
         if (r < 0)
-                return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m", ifindex, oldname, name);
+                return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
+                                              ifindex, oldname, event->name);
+
+        /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */
+        r = device_add_property(dev, "ID_RENAMING", "1");
+        if (r < 0)
+                log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m");
 
         r = device_rename(dev, event->name);
         if (r < 0)
-                return log_warning_errno(r, "Network interface %i is renamed from '%s' to '%s', but could not update sd_device object: %m", ifindex, oldname, name);
+                log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name);
 
-        log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, name);
+        log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name);
 
         return 1;
 }
@@ -816,17 +820,38 @@ static void event_execute_rules_on_remove(
                 (void) udev_node_remove(dev);
 }
 
+static int udev_event_on_move(UdevEvent *event) {
+        sd_device *dev = event->dev;
+        int r;
+
+        if (event->dev_db_clone &&
+            sd_device_get_devnum(dev, NULL) < 0) {
+                r = device_copy_properties(dev, event->dev_db_clone);
+                if (r < 0)
+                        log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m");
+        }
+
+        /* Drop previously added property */
+        r = device_add_property(dev, "ID_RENAMING", NULL);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property, ignoring: %m");
+
+        return 0;
+}
+
 int udev_event_execute_rules(UdevEvent *event,
                              usec_t timeout_usec,
                              Hashmap *properties_list,
                              UdevRules *rules) {
-        sd_device *dev = event->dev;
         const char *subsystem, *action;
+        sd_device *dev;
         int r;
 
         assert(event);
         assert(rules);
 
+        dev = event->dev;
+
         r = sd_device_get_subsystem(dev, &subsystem);
         if (r < 0)
                 return log_device_error_errno(dev, r, "Failed to get subsystem: %m");
@@ -844,21 +869,12 @@ int udev_event_execute_rules(UdevEvent *event,
         if (r < 0)
                 log_device_debug_errno(dev, r, "Failed to clone sd_device object, ignoring: %m");
 
-        if (event->dev_db_clone) {
-                r = sd_device_get_devnum(dev, NULL);
-                if (r < 0) {
-                        if (r != -ENOENT)
-                                log_device_debug_errno(dev, r, "Failed to get devnum, ignoring: %m");
+        if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0)
+                /* Disable watch during event processing. */
+                (void) udev_watch_end(event->dev_db_clone);
 
-                        if (streq(action, "move")) {
-                                r = device_copy_properties(dev, event->dev_db_clone);
-                                if (r < 0)
-                                        log_device_debug_errno(dev, r, "Failed to copy properties from cloned device, ignoring: %m");
-                        }
-                } else
-                        /* Disable watch during event processing. */
-                        (void) udev_watch_end(event->dev_db_clone);
-        }
+        if (streq(action, "move"))
+                (void) udev_event_on_move(event);
 
         (void) udev_rules_apply_to_event(rules, event, timeout_usec, properties_list);
 
@@ -891,7 +907,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) {
         void *val;
         Iterator i;
 
-        HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
+        ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
                 enum udev_builtin_cmd builtin_cmd = PTR_TO_INT(val);
                 char command[UTIL_PATH_SIZE];
 
index 1c00dd1e9e739148a41f7e699841d7d3e1f8b5de..cfbbd7b2832da7e2f8ba5f04fa102a54e41005ed 100644 (file)
@@ -272,7 +272,7 @@ int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
 
 static int node_permissions_apply(sd_device *dev, bool apply,
                                   mode_t mode, uid_t uid, gid_t gid,
-                                  Hashmap *seclabel_list) {
+                                  OrderedHashmap *seclabel_list) {
         const char *devnode, *subsystem, *id_filename = NULL;
         struct stat stats;
         dev_t devnum;
@@ -318,7 +318,7 @@ static int node_permissions_apply(sd_device *dev, bool apply,
                         log_device_debug(dev, "Preserve permissions of %s, %#o, uid=%u, gid=%u", devnode, mode, uid, gid);
 
                 /* apply SECLABEL{$module}=$label */
-                HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) {
+                ORDERED_HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) {
                         int q;
 
                         if (streq(name, "selinux")) {
@@ -386,7 +386,7 @@ static int xsprintf_dev_num_path_from_sd_device(sd_device *dev, char **ret) {
 
 int udev_node_add(sd_device *dev, bool apply,
                   mode_t mode, uid_t uid, gid_t gid,
-                  Hashmap *seclabel_list) {
+                  OrderedHashmap *seclabel_list) {
         const char *devnode, *devlink;
         _cleanup_free_ char *filename = NULL;
         int r;
index 223c8f0e4395654a47ee1546ea26cb4507026b54..5ae816d66f12c3a27a960f39f1d3693838bdb98d 100644 (file)
@@ -10,6 +10,6 @@
 
 int udev_node_add(sd_device *dev, bool apply,
                   mode_t mode, uid_t uid, gid_t gid,
-                  Hashmap *seclabel_list);
+                  OrderedHashmap *seclabel_list);
 int udev_node_remove(sd_device *dev);
 int udev_node_update_old_links(sd_device *dev, sd_device *dev_old);
index 178a41906ff8200f6b5e8523ebcc7b20cad368a5..d4aeca2fd328b2251183de8135688cc06cd3f01d 100644 (file)
@@ -602,7 +602,7 @@ static int import_program_into_properties(UdevEvent *event,
         char *line;
         int r;
 
-        r = udev_event_spawn(event, timeout_usec, false, program, result, sizeof result);
+        r = udev_event_spawn(event, timeout_usec, true, program, result, sizeof result);
         if (r < 0)
                 return r;
         if (r > 0)
@@ -2260,13 +2260,13 @@ int udev_rules_apply_to_event(
                                 return log_oom();
 
                         if (IN_SET(cur->key.op, OP_ASSIGN, OP_ASSIGN_FINAL))
-                                hashmap_clear_free_free(event->seclabel_list);
+                                ordered_hashmap_clear_free_free(event->seclabel_list);
 
-                        r = hashmap_ensure_allocated(&event->seclabel_list, NULL);
+                        r = ordered_hashmap_ensure_allocated(&event->seclabel_list, NULL);
                         if (r < 0)
                                 return log_oom();
 
-                        r = hashmap_put(event->seclabel_list, name, label);
+                        r = ordered_hashmap_put(event->seclabel_list, name, label);
                         if (r < 0)
                                 return log_oom();
                         log_device_debug(dev, "SECLABEL{%s}='%s' %s:%u",
@@ -2443,9 +2443,9 @@ int udev_rules_apply_to_event(
                         _cleanup_free_ char *cmd = NULL;
 
                         if (IN_SET(cur->key.op, OP_ASSIGN, OP_ASSIGN_FINAL))
-                                hashmap_clear_free_key(event->run_list);
+                                ordered_hashmap_clear_free_key(event->run_list);
 
-                        r = hashmap_ensure_allocated(&event->run_list, NULL);
+                        r = ordered_hashmap_ensure_allocated(&event->run_list, NULL);
                         if (r < 0)
                                 return log_oom();
 
@@ -2453,7 +2453,7 @@ int udev_rules_apply_to_event(
                         if (!cmd)
                                 return log_oom();
 
-                        r = hashmap_put(event->run_list, cmd, INT_TO_PTR(cur->key.builtin_cmd));
+                        r = ordered_hashmap_put(event->run_list, cmd, INT_TO_PTR(cur->key.builtin_cmd));
                         if (r < 0)
                                 return log_oom();
 
index 3bc69ff6c40171e820f5b0a3af62f7e48a286d13..2fb49dc974cd1ca67454a7333d51d6f1f23ffac3 100644 (file)
@@ -25,8 +25,8 @@ typedef struct UdevEvent {
         mode_t mode;
         uid_t uid;
         gid_t gid;
-        Hashmap *seclabel_list;
-        Hashmap *run_list;
+        OrderedHashmap *seclabel_list;
+        OrderedHashmap *run_list;
         usec_t exec_delay_usec;
         usec_t birth_usec;
         sd_netlink *rtnl;
index 54c525e02ca4492537124036223ff465740a99a9..9c1784489a86602f554fe657998605f0cb9b6b76 100644 (file)
@@ -135,7 +135,7 @@ int test_main(int argc, char *argv[], void *userdata) {
         FOREACH_DEVICE_PROPERTY(dev, key, value)
                 printf("%s=%s\n", key, value);
 
-        HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
+        ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) {
                 char program[UTIL_PATH_SIZE];
 
                 udev_event_apply_format(event, cmd, program, sizeof(program), false);
index 63ceaaf957f9cf01edc6fe329011c7c5f79fec71..b7dafb775575d7e6bbafc8d4a4413ba266750fcc 100644 (file)
@@ -7,6 +7,7 @@
 #include "sd-event.h"
 
 #include "device-enumerator-private.h"
+#include "device-private.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "path-util.h"
@@ -59,6 +60,7 @@ static int exec_list(sd_device_enumerator *e, const char *action, Set *settle_se
 }
 
 static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) {
+        _cleanup_free_ char *val = NULL;
         Set *settle_set = userdata;
         const char *syspath;
 
@@ -71,7 +73,8 @@ static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *us
         if (arg_verbose)
                 printf("settle %s\n", syspath);
 
-        if (!set_remove(settle_set, syspath))
+        val = set_remove(settle_set, syspath);
+        if (!val)
                 log_debug("Got epoll event on syspath %s not present in syspath set", syspath);
 
         if (set_isempty(settle_set))
@@ -199,11 +202,10 @@ int trigger_main(int argc, char *argv[], void *userdata) {
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
                         break;
                 case 'c':
-                        if (STR_IN_SET(optarg, "add", "remove", "change"))
-                                action = optarg;
-                        else
-                                log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
+                        if (device_action_from_string(optarg) < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg);
 
+                        action = optarg;
                         break;
                 case 's':
                         r = sd_device_enumerator_add_match_subsystem(e, optarg, true);
diff --git a/test/TEST-22-TMPFILES/test-08.sh b/test/TEST-22-TMPFILES/test-08.sh
new file mode 100755 (executable)
index 0000000..e7bf044
--- /dev/null
@@ -0,0 +1,32 @@
+#! /bin/bash
+#
+# Verify tmpfiles can run in a root directory under a path prefix that contains
+# directories owned by unprivileged users, for example when a root file system
+# is mounted in a regular user's home directory.
+#
+# https://github.com/systemd/systemd/pull/11820
+#
+
+set -e
+
+rm -fr /tmp/root /tmp/user
+mkdir -p /tmp/root /tmp/user/root
+chown daemon:daemon /tmp/user
+
+# Verify the command works as expected with no prefix or a root-owned prefix.
+echo 'd /tmp/root/test1' | systemd-tmpfiles --create -
+test -d /tmp/root/test1
+echo 'd /test2' | systemd-tmpfiles --root=/tmp/root --create -
+test -d /tmp/root/test2
+
+# Verify the command fails to write to a root-owned subdirectory under an
+# unprivileged user's directory when it's not part of the prefix, as expected
+# by the unsafe_transition function.
+! echo 'd /tmp/user/root/test' | systemd-tmpfiles --create -
+! test -e /tmp/user/root/test
+! echo 'd /user/root/test' | systemd-tmpfiles --root=/tmp --create -
+! test -e /tmp/user/root/test
+
+# Verify the above works when all user-owned directories are in the prefix.
+echo 'd /test' | systemd-tmpfiles --root=/tmp/user/root --create -
+test -d /tmp/user/root/test
diff --git a/test/TEST-29-UDEV-ID_RENAMING/Makefile b/test/TEST-29-UDEV-ID_RENAMING/Makefile
new file mode 120000 (symlink)
index 0000000..e9f93b1
--- /dev/null
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-29-UDEV-ID_RENAMING/test.sh b/test/TEST-29-UDEV-ID_RENAMING/test.sh
new file mode 100755 (executable)
index 0000000..74362c0
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -e
+TEST_DESCRIPTION="UDEV ID_RENAMING property"
+TEST_NO_NSPAWN=1
+
+. $TEST_BASE_DIR/test-functions
+QEMU_TIMEOUT=300
+
+test_setup() {
+    create_empty_image
+    mkdir -p $TESTDIR/root
+    mount ${LOOPDEV}p1 $TESTDIR/root
+
+    (
+        LOG_LEVEL=5
+        eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
+
+        setup_basic_environment
+
+        # mask some services that we do not want to run in these tests
+        ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+        ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+        ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+        ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+        ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+
+        # setup the testsuite service
+        cat >$initdir/etc/systemd/system/testsuite.service <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/bin/bash -x /testsuite.sh
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+EOF
+        cp testsuite.sh $initdir/
+
+        setup_testsuite
+    ) || return 1
+
+    ddebug "umount $TESTDIR/root"
+    umount $TESTDIR/root
+}
+
+do_test "$@"
diff --git a/test/TEST-29-UDEV-ID_RENAMING/testsuite.sh b/test/TEST-29-UDEV-ID_RENAMING/testsuite.sh
new file mode 100755 (executable)
index 0000000..e5c2b5c
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+set -ex
+set -o pipefail
+
+mkdir -p /run/udev/rules.d/
+
+cat > /run/udev/rules.d/50-testsuite.rules <<EOF
+ACTION=="remove", GOTO="lo_end"
+
+SUBSYSTEM=="net", KERNEL=="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/lo"
+
+ACTION!="change", GOTO="lo_end"
+
+SUBSYSTEM=="net", KERNEL=="lo", ENV{ID_RENAMING}="1"
+
+LABEL="lo_end"
+EOF
+
+udevadm control --log-priority=debug --reload
+udevadm trigger --action=add --settle /sys/devices/virtual/net/lo
+udevadm info /sys/devices/virtual/net/lo
+
+STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo.device)
+[[ $STATE == "active" ]] || exit 1
+
+udevadm trigger --action=change --settle /sys/devices/virtual/net/lo
+udevadm info /sys/devices/virtual/net/lo
+
+STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo.device)
+[[ $STATE == "inactive" ]] || exit 1
+
+udevadm trigger --action=move --settle /sys/devices/virtual/net/lo
+udevadm info /sys/devices/virtual/net/lo
+
+STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo.device)
+[[ $STATE == "active" ]] || exit 1
+
+rm -f /run/udev/rules.d/50-testsuite.rules
+udevadm control --reload
+
+echo OK > /testok
+
+exit 0
diff --git a/test/fuzz/fuzz-dns-packet/oss-fuzz-13422 b/test/fuzz/fuzz-dns-packet/oss-fuzz-13422
new file mode 100644 (file)
index 0000000..439aec5
Binary files /dev/null and b/test/fuzz/fuzz-dns-packet/oss-fuzz-13422 differ
diff --git a/test/fuzz/fuzz-env-file/simple-env-file b/test/fuzz/fuzz-env-file/simple-env-file
new file mode 100644 (file)
index 0000000..2cad6f7
--- /dev/null
@@ -0,0 +1,5 @@
+VARIABLE="value"
+OPTION="--option=1234"
+NUMBER=1
+EMPTY=""
+PATH=/var/lib/xxx
index d77c6989cddf56980c1fc7252859b3e23a125df7..9a60eb712df2ce2fcdb85ce26431412b9a399cd2 100644 (file)
@@ -132,6 +132,7 @@ PVID=
 SamplePoint=
 BitRate=
 RestartSec=
+TripleSampling=
 [Address]
 DuplicateAddressDetection=
 AutoJoin=
diff --git a/test/fuzz/fuzz-nspawn-settings/basic-config b/test/fuzz/fuzz-nspawn-settings/basic-config
new file mode 100644 (file)
index 0000000..be0d4e7
--- /dev/null
@@ -0,0 +1,36 @@
+[Exec]
+Boot=off
+ProcessTwo=off
+Parameters=/sbin/init -x=1
+Environment=THIS=that
+User=user
+WorkingDirectory=/cwd
+PivotRoot=/newroot
+Capability=CAP_NET
+DropCapability=CAP_ADMIN
+KillSignal=SIGTERM
+Personality=shy
+MachineID=edbfea3309ba41ea83e2318c58a8d498
+PrivateUser=1:2
+NotifyReady=no
+SystemCallFilters=write
+
+[Files]
+ReadOnly=no
+Volatile=no
+Bind=/bindthis
+BindReadOnly=/bindthisro
+TemporaryFileSystem=/thisismytmpfs:rw
+Overlay=/thisisanoverlay:/thisisanoverlaytoo
+PrivateUsersChown=no
+
+[Network]
+Private=off
+VirtualEthernet=yes
+VirtualEthernetExtra=veth1:veth2
+Interface=eth1 enp0s1
+MacVLAN=eno1 eno2
+IPVLAN=eno3 enp2s124
+Bridge=bridge123 bridge125
+Zone=myzone
+Port=1234 156 -1
diff --git a/test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f b/test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f
new file mode 100644 (file)
index 0000000..7be2d2c
Binary files /dev/null and b/test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f differ
diff --git a/test/test-network/conf/21-vlan-test1.network b/test/test-network/conf/21-vlan-test1.network
new file mode 100644 (file)
index 0000000..afe1deb
--- /dev/null
@@ -0,0 +1,2 @@
+[Match]
+Name=test1
diff --git a/test/test-network/conf/21-vlan-test1.network.d/override.conf b/test/test-network/conf/21-vlan-test1.network.d/override.conf
new file mode 100644 (file)
index 0000000..06307ff
--- /dev/null
@@ -0,0 +1,5 @@
+[Network]
+VLAN=vlan99
+Address=192.168.24.5/24
+Address=192.168.25.5/24
+IPv6AcceptRA=false
index afe1debe081b766c2f79663e3816bc13e6893fe7..0cd901def89cbac6c34c172a97eb5be330f0b04b 100644 (file)
@@ -1,2 +1,6 @@
 [Match]
-Name=test1
+Name=vlan99
+
+[Network]
+IPv6AcceptRA=false
+Address=192.168.23.5/24
diff --git a/test/test-network/conf/21-vlan.network.d/override.conf b/test/test-network/conf/21-vlan.network.d/override.conf
deleted file mode 100644 (file)
index 363fc90..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[Network]
-VLAN=vlan99
index 3904953443a0318355868d49a82e3e136a6699a7..29bbee4f60b49f5890b6157f1ee33fb790559c61 100644 (file)
@@ -16,3 +16,14 @@ Label=33
 [Address]
 Address=2001:db8::20
 Peer=2001:db8::10/128
+
+[Address]
+Address=0.0.0.0/24
+Label=34
+
+[Address]
+Address=0.0.0.0/16
+Label=35
+
+[Address]
+Address=::/64
index ced5e048f9a1e98414de3dbcc230fb3e7b9cd2fd..856960ad65f8d761f57b0adab3813fae2b07ff3e 100755 (executable)
@@ -214,6 +214,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '12-dummy.netdev',
         '21-macvlan.netdev',
         '21-macvtap.netdev',
+        '21-vlan-test1.network',
         '21-vlan.netdev',
         '21-vlan.network',
         '25-6rd-tunnel.netdev',
@@ -341,7 +342,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertEqual('1',             self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
 
     def test_vlan(self):
-        self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
+        self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
+                                             '21-vlan.network', '21-vlan-test1.network')
         self.start_networkd()
 
         self.assertTrue(self.link_exits('test1'))
@@ -360,6 +362,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(output, 'MVRP')
         self.assertTrue(output, ' id 99 ')
 
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
+        self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
+
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
+
     def test_macvtap(self):
         self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
         self.start_networkd()
@@ -765,11 +776,28 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        # This also tests address pool
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '32']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '33']).rstrip().decode('utf-8')
+        print(output)
         self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '34']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
+
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '35']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
+
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        print(output)
         self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
+        self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
 
         output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
         print(output)
index dbd12c4759b7b299b834b4f4de538ebef0e27e91..72ffcee439b92f2ad31f154cf1bd15cfda79a00b 100755 (executable)
@@ -34,7 +34,7 @@ for phase in "${PHASES[@]}"; do
             info "Starting container $CONT_NAME"
             $DOCKER_RUN -v $REPO_ROOT:/build:rw \
                         -w /build --privileged=true --name $CONT_NAME \
-                        -dit --net=host debian-with-systemd/latest /usr/bin/systemd
+                        -dit --net=host debian-with-systemd/latest /bin/systemd
             $DOCKER_EXEC bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list"
             $DOCKER_EXEC apt-get -y update
             $DOCKER_EXEC apt-get -y build-dep systemd
index 58baab3023d76bb8b6b16029443d7c1281760a0a..d5eca2546b237e980e41b67858c0eceeb9165fa7 100644 (file)
@@ -9,7 +9,7 @@
 
 [Unit]
 Description=Remove the Offline System Updates symlink
-Documentation=man:systemd.special(5) man:systemd.offline-updates(7)
+Documentation=man:systemd.special(7) man:systemd.offline-updates(7)
 After=system-update.target
 DefaultDependencies=no
 Conflicts=shutdown.target
index 1807d73c68586297776b2053816670ce56f79e45..4684f095c0778f4d21d376bab2c6c1e36dba9bab 100644 (file)
@@ -23,7 +23,6 @@ IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
-ProtectHostname=yes
 Restart=always
 RestartSec=0
 RestrictAddressFamilies=AF_UNIX AF_NETLINK
index fb6fda49077742d746fb106c194bc88da884a59c..a864f66c688326286a8bcca6a32e9665536ccf37 100644 (file)
@@ -21,7 +21,7 @@ After=dbus.socket
 
 [Service]
 BusName=org.freedesktop.login1
-CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG
+CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG CAP_LINUX_IMMUTABLE
 ExecStart=@rootlibexecdir@/systemd-logind
 FileDescriptorStoreMax=512
 IPAddressDeny=any
index 5da0e1e3307e720e6558d22b6b95fe322a702cce..472ef045de9e5cce5f421ef27a2ff4643a0be22b 100644 (file)
@@ -27,7 +27,6 @@ MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
 ProtectControlGroups=yes
 ProtectHome=yes
-ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectSystem=strict
 Restart=on-failure
index eac3f31012ca8f59b1dfc41f26aaf0bd495f4fb4..3144b70063ee3acc4bd4a1fb704e7824143b1d23 100644 (file)
@@ -30,7 +30,6 @@ PrivateDevices=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
-ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict