]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #23683 from keszybz/status-format
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 10 Jun 2022 12:11:53 +0000 (14:11 +0200)
committerGitHub <noreply@github.com>
Fri, 10 Jun 2022 12:11:53 +0000 (14:11 +0200)
Default to default-status-unit-format=name in developer mode

53 files changed:
docs/BOOT_LOADER_SPECIFICATION.md
docs/CODING_STYLE.md
docs/style.css
man/loader.conf.xml
meson.build
meson_options.txt
po/et.po
src/boot/efi/boot.c
src/boot/efi/console.c
src/boot/efi/cpio.c
src/boot/efi/devicetree.c
src/boot/efi/disk.c
src/boot/efi/drivers.c
src/boot/efi/efi-string.c
src/boot/efi/efi-string.h
src/boot/efi/graphics.c
src/boot/efi/initrd.c
src/boot/efi/measure.c
src/boot/efi/pe.c
src/boot/efi/random-seed.c
src/boot/efi/shim.c
src/boot/efi/splash.c
src/boot/efi/stub.c
src/boot/efi/test-efi-string.c
src/boot/efi/util.c
src/boot/efi/util.h
src/boot/efi/xbootldr.c
src/core/bpf/meson.build
src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c
src/core/dynamic-user.c
src/fundamental/macro-fundamental.h
src/libsystemd/sd-id128/sd-id128.c
src/shared/bus-util.c
src/shared/bus-util.h
src/shared/firewall-util-nft.c
src/shared/libfido2-util.c
src/shutdown/shutdown.c
src/shutdown/umount.c
src/shutdown/umount.h
src/systemctl/systemctl-util.c
src/test/test-dns-domain.c
src/test/test-fstab-util.c
src/test/test-process-util.c
src/test/test-seccomp.c
src/test/test-udev-util.c
test/TEST-03-JOBS/test.sh
test/TEST-17-UDEV/test.sh
test/TEST-45-TIMEDATE/Makefile [new symlink]
test/TEST-45-TIMEDATE/test.sh [new file with mode: 0755]
test/TEST-64-UDEV-STORAGE/test.sh
test/units/assert.sh [new file with mode: 0644]
test/units/testsuite-45.service [new file with mode: 0644]
test/units/testsuite-45.sh [new file with mode: 0755]

index 8a6a16c63f80e9c761894eda33edce4348cff7f3..6e8a3316a7ff6d1ec52445510edb1613a7851ba8 100644 (file)
@@ -402,7 +402,7 @@ boots is exhausted, the entry is marked as "bad".
 
 Which boots are "successful" is determined by the operating system. systemd
 provides a generic mechanism that can be extended with arbitrary checks and
-actions, see [Automatic Boot Assesment](AUTOMATIC_BOOT_ASSESSMENT.md), but the
+actions, see [Automatic Boot Assessment](AUTOMATIC_BOOT_ASSESSMENT.md), but the
 boot counting mechanism described in this specifaction can also be used with
 other implementations.
 
index 3599db57fb38a00b2351505a596f001c3f8db935..b7e700237ad98b5f4297f4e8287c9ec05b0cef50 100644 (file)
@@ -648,7 +648,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
 - Use `typesafe_inet_ntop()`, `typesafe_inet_ntop4()`, and
   `typesafe_inet_ntop6()` instead of `inet_ntop()`. But better yet, use the
   `IN_ADDR_TO_STRING()`, `IN4_ADDR_TO_STRING()`, and `IN6_ADDR_TO_STRING()`
-  macros which allocate an anynomous buffer internally.
+  macros which allocate an anonymous buffer internally.
 
 - Please never use `dup()`. Use `fcntl(fd, F_DUPFD_CLOEXEC, 3)` instead. For
   two reasons: first, you want `O_CLOEXEC` set on the new `fd` (see
index 56ed036603ae1c808db77cc5e1afe60cfdf9b652..ee0fc7f754ec637029b8ec9babfa880216c78cf4 100644 (file)
@@ -18,6 +18,7 @@
   --sd-brand-green: hsl(145, 66%, 51%); /* #30D475; */
   --sd-brand-white: #fff;
 
+  --sd-black: hsl(270, 7%, 13%);
   --sd-green: hsl(145, 66%, 43%); /* #26b763 */
   --sd-gray-extralight: hsl(30, 10%, 96%); /* #f6f5f4 */
   --sd-gray-light: hsl(30, 10%, 92%);
@@ -51,7 +52,7 @@
   :root {
     color-scheme: dark;
     --sd-foreground-color: var(--sd-gray);
-    --sd-background-color: var(--sd-brand-black);
+    --sd-background-color: var(--sd-black);
     --sd-logo-color: var(--sd-brand-white);
     --sd-link-color: var(--sd-brand-green);
     --sd-small-color: var(--sd-gray);
index 509412ec9dcc6e03e2e7d40cbc82b1650af56be4..43a115dcad791949bf9a16ceb52948eaa93e9a73 100644 (file)
               </row>
             </tbody>
           </tgroup>
-        </table></listitem>
+        </table>
+
+        <para>Supported glob wilcard patterns are <literal>?</literal>, <literal>*</literal>, and
+        <literal>[…]</literal> (including ranges). Note that these patterns use the same syntax as
+        <citerefentry><refentrytitle>glob</refentrytitle><manvolnum>7</manvolnum></citerefentry>, but do not
+        support all features. In particular, set negation and named character classes are not supported. The
+        matching is done case-insensitively on the entry ID (as shown by <command>bootctl
+        list</command>).</para></listitem>
       </varlistentry>
 
       <varlistentry>
index d6391d45a25c94441f2618d0616bcb59849e234a..e3b68a8dccdb7f334585c8d856d02a0d8307ff7b 100644 (file)
@@ -453,6 +453,10 @@ if get_option('buildtype') != 'debug'
         possible_link_flags += '-Wl,--gc-sections'
 endif
 
+if get_option('mode') == 'developer'
+        possible_cc_flags += '-fno-omit-frame-pointer'
+endif
+
 add_project_arguments(cc.get_supported_arguments(basic_disabled_warnings), language : 'c')
 add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c')
 add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language : 'c')
@@ -1019,58 +1023,74 @@ conf.set10('HAVE_LIBBPF', libbpf.found())
 if want_bpf_framework == 'false' or not libbpf.found() or skip_deps
         conf.set10('BPF_FRAMEWORK', false)
 else
-        # Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
-        # (like clang-10/llvm-strip-10)
-        if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
-                r = find_program('clang', required : bpf_framework_required, version : '>= 10.0.0')
-                clang_found = r.found()
-                if clang_found
-                        clang = r.path()
+        bpf_compiler = get_option('bpf-compiler')
+        clang_found = false
+        clang_supports_bpf = false
+        bpf_gcc_found = false
+        deps_found = false
+
+        if bpf_compiler == 'clang'
+                # Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
+                # (like clang-10/llvm-strip-10)
+                if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
+                        r = find_program('clang', required : bpf_framework_required, version : '>= 10.0.0')
+                        clang_found = r.found()
+                        if clang_found
+                                clang = r.path()
+                        endif
+                        # Assume that the required flags are supported by the found clang.
+                        clang_supports_flags = clang_found
+                else
+                        clang_found = true
+                        clang = cc.cmd_array()
+                        clang_supports_flags = cc.has_argument('-Wno-compare-distinct-pointer-types')
                 endif
-                # Assume that the required flags are supported by the found clang.
-                clang_supports_flags = clang_found
-        else
-                clang_found = true
-                clang = cc.cmd_array()
-                clang_supports_flags = cc.has_argument('-Wno-compare-distinct-pointer-types')
-        endif
 
-        if clang_found
-                # Check if 'clang -target bpf' is supported.
-                clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
-        else
-                clang_supports_bpf = false
+                if clang_found
+                        # Check if 'clang -target bpf' is supported.
+                        clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
+                endif
+        elif bpf_compiler == 'gcc'
+                warning('GCC BPF Compiler support is experimental and not recommended.')
+                bpf_gcc = find_program('bpf-gcc',
+                                       required : true,
+                                       version : '>= 12.1.0')
+                bpf_gcc_found = bpf_gcc.found()
         endif
 
-        # Debian installs this in /usr/sbin/ which is not in $PATH.
-        # We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
-        # We use 'bpftool gen' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
-        bpftool = find_program('bpftool',
-                               '/usr/sbin/bpftool',
-                               required : false,
-                               version : '>= 5.13.0')
-
-        if bpftool.found()
-                bpftool_strip = true
-        else
-                bpftool_strip = false
+        if clang_supports_bpf or bpf_gcc_found
+                # Debian installs this in /usr/sbin/ which is not in $PATH.
+                # We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
+                # We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
                 bpftool = find_program('bpftool',
                                        '/usr/sbin/bpftool',
-                                       required : bpf_framework_required,
-                                       version : '>= 5.6.0')
-        endif
+                                       required : false,
+                                       version : '>= 5.13.0')
 
-        if not bpftool_strip
-                if not meson.is_cross_build() and clang_found
-                        llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
-                                                     check : true).stdout().strip()
+                if bpftool.found()
+                        bpftool_strip = true
+                        deps_found = true
                 else
-                        llvm_strip_bin = 'llvm-strip'
+                        bpftool_strip = false
+                        # We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
+                        bpftool = find_program('bpftool',
+                                               '/usr/sbin/bpftool',
+                                               required : bpf_framework_required,
+                                               version : '>= 5.6.0')
                 endif
-                llvm_strip = find_program(llvm_strip_bin, required : bpf_framework_required, version : '>= 10.0.0')
-        endif
 
-        deps_found = clang_found and clang_supports_bpf and clang_supports_flags and (bpftool_strip or llvm_strip.found()) and bpftool.found()
+                # We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
+                if not bpftool_strip and bpftool.found() and clang_supports_bpf
+                        if not meson.is_cross_build()
+                                llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
+                                                             check : true).stdout().strip()
+                        else
+                                llvm_strip_bin = 'llvm-strip'
+                        endif
+                        llvm_strip = find_program(llvm_strip_bin, required : bpf_framework_required, version : '>= 10.0.0')
+                        deps_found = llvm_strip.found()
+                endif
+        endif
 
         # Can build BPF program from source code in restricted C
         conf.set10('BPF_FRAMEWORK', deps_found)
index 267c8293686734690559aa3663589f1abaa5ac20..b42ae0d90be5af9254690a1eb0ecc044403b631d 100644 (file)
@@ -496,6 +496,8 @@ option('kernel-install', type: 'boolean', value: 'true',
 option('analyze', type: 'boolean', value: 'true',
        description : 'install systemd-analyze')
 
+option('bpf-compiler', type : 'combo', choices : ['clang', 'gcc'],
+    description: 'compiler used to build BPF programs, note: gcc is experimental')
 option('bpf-framework', type : 'combo', choices : ['auto', 'true', 'false'],
     description: 'build BPF programs from source code in restricted C')
 
index fff89814b98e9c3b9b7895c6e78612bbb50beac1..0e9ed7d2905e673d0156ceae8a5737fb7c0da39d 100644 (file)
--- a/po/et.po
+++ b/po/et.po
@@ -5,13 +5,16 @@ msgid ""
 msgstr ""
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2021-01-08 17:48+0100\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
+"PO-Revision-Date: 2022-06-09 21:18+0000\n"
+"Last-Translator: H A <contact+fedora@hen.ee>\n"
+"Language-Team: Estonian <https://translate.fedoraproject.org/projects/"
+"systemd/master/et/>\n"
 "Language: et\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.12.2\n"
 
 #: src/core/org.freedesktop.systemd1.policy.in:22
 msgid "Send passphrase back to system"
@@ -509,7 +512,7 @@ msgstr ""
 
 #: src/login/org.freedesktop.login1.policy:406
 msgid "Change Session"
-msgstr ""
+msgstr "Vaheta sessiooni"
 
 #: src/login/org.freedesktop.login1.policy:407
 msgid "Authentication is required to change the virtual terminal."
@@ -575,145 +578,147 @@ msgstr ""
 
 #: src/machine/org.freedesktop.machine1.policy:95
 msgid "Manage local virtual machine and container images"
-msgstr ""
+msgstr "Halda kohalikke virtuaalmasinaid ja konteinerpilte"
 
 #: src/machine/org.freedesktop.machine1.policy:96
 msgid ""
 "Authentication is required to manage local virtual machine and container "
 "images."
 msgstr ""
+"Autentimine on vajalik, et hallata kohalikke virtuaalmasinaid ja "
+"konteinerpilte."
 
 #: src/network/org.freedesktop.network1.policy:22
 msgid "Set NTP servers"
-msgstr ""
+msgstr "Säti NTP servereid"
 
 #: src/network/org.freedesktop.network1.policy:23
 msgid "Authentication is required to set NTP servers."
-msgstr ""
+msgstr "Autentimine on vajalik, et seadistada NTP servereid."
 
 #: src/network/org.freedesktop.network1.policy:33
 #: src/resolve/org.freedesktop.resolve1.policy:44
 msgid "Set DNS servers"
-msgstr ""
+msgstr "Säti DNS serverid"
 
 #: src/network/org.freedesktop.network1.policy:34
 #: src/resolve/org.freedesktop.resolve1.policy:45
 msgid "Authentication is required to set DNS servers."
-msgstr ""
+msgstr "Autentimine on vajalik, et seadistada DNS servereid."
 
 #: src/network/org.freedesktop.network1.policy:44
 #: src/resolve/org.freedesktop.resolve1.policy:55
 msgid "Set domains"
-msgstr ""
+msgstr "Säti domeenid"
 
 #: src/network/org.freedesktop.network1.policy:45
 #: src/resolve/org.freedesktop.resolve1.policy:56
 msgid "Authentication is required to set domains."
-msgstr ""
+msgstr "Autentimine on vajalik, et seadistada domeene."
 
 #: src/network/org.freedesktop.network1.policy:55
 #: src/resolve/org.freedesktop.resolve1.policy:66
 msgid "Set default route"
-msgstr ""
+msgstr "Säti default route"
 
 #: src/network/org.freedesktop.network1.policy:56
 #: src/resolve/org.freedesktop.resolve1.policy:67
 msgid "Authentication is required to set default route."
-msgstr ""
+msgstr "Autentimine on vajalik, et seadistada default route."
 
 #: src/network/org.freedesktop.network1.policy:66
 #: src/resolve/org.freedesktop.resolve1.policy:77
 msgid "Enable/disable LLMNR"
-msgstr ""
+msgstr "Lülita LLMNR sisse/välja"
 
 #: src/network/org.freedesktop.network1.policy:67
 #: src/resolve/org.freedesktop.resolve1.policy:78
 msgid "Authentication is required to enable or disable LLMNR."
-msgstr ""
+msgstr "Autentimine on vajalik, et LLMNR lülitada sisse või välja."
 
 #: src/network/org.freedesktop.network1.policy:77
 #: src/resolve/org.freedesktop.resolve1.policy:88
 msgid "Enable/disable multicast DNS"
-msgstr ""
+msgstr "Lülita multicast DNS sisse/välja"
 
 #: src/network/org.freedesktop.network1.policy:78
 #: src/resolve/org.freedesktop.resolve1.policy:89
 msgid "Authentication is required to enable or disable multicast DNS."
-msgstr ""
+msgstr "Autentimine on vajalik, et multicast DNS lülitada sisse või välja."
 
 #: src/network/org.freedesktop.network1.policy:88
 #: src/resolve/org.freedesktop.resolve1.policy:99
 msgid "Enable/disable DNS over TLS"
-msgstr ""
+msgstr "Lülita DNS üle TLS sisse/välja"
 
 #: src/network/org.freedesktop.network1.policy:89
 #: src/resolve/org.freedesktop.resolve1.policy:100
 msgid "Authentication is required to enable or disable DNS over TLS."
-msgstr ""
+msgstr "Autentimine on vajalik, et DNS üle TLS'i lülitada sisse või välja."
 
 #: src/network/org.freedesktop.network1.policy:99
 #: src/resolve/org.freedesktop.resolve1.policy:110
 msgid "Enable/disable DNSSEC"
-msgstr ""
+msgstr "Lülita DNSSEC sisse/välja"
 
 #: src/network/org.freedesktop.network1.policy:100
 #: src/resolve/org.freedesktop.resolve1.policy:111
 msgid "Authentication is required to enable or disable DNSSEC."
-msgstr ""
+msgstr "Autentimine on vajalik, et DNSSEC lülitada sisse või välja."
 
 #: src/network/org.freedesktop.network1.policy:110
 #: src/resolve/org.freedesktop.resolve1.policy:121
 msgid "Set DNSSEC Negative Trust Anchors"
-msgstr ""
+msgstr "Säti DNSSEC negatiivsed usaldusankrud"
 
 #: src/network/org.freedesktop.network1.policy:111
 #: src/resolve/org.freedesktop.resolve1.policy:122
 msgid "Authentication is required to set DNSSEC Negative Trust Anchors."
-msgstr ""
+msgstr "Autentimine on vajalik, et seadistada DNSSEC negatiivsed usaldusankrud."
 
 #: src/network/org.freedesktop.network1.policy:121
 msgid "Revert NTP settings"
-msgstr ""
+msgstr "Taasta NTP sätted"
 
 #: src/network/org.freedesktop.network1.policy:122
 msgid "Authentication is required to reset NTP settings."
-msgstr ""
+msgstr "Autentimine on vajalik, et taastada NTP sätted."
 
 #: src/network/org.freedesktop.network1.policy:132
 msgid "Revert DNS settings"
-msgstr ""
+msgstr "Taasta DNS sätted"
 
 #: src/network/org.freedesktop.network1.policy:133
 msgid "Authentication is required to reset DNS settings."
-msgstr ""
+msgstr "Autentimine on vajalik, et lähtestada DNS sätted."
 
 #: src/network/org.freedesktop.network1.policy:143
 msgid "DHCP server sends force renew message"
-msgstr ""
+msgstr "DHCP server saadab sunduuendamise sõnumi"
 
 #: src/network/org.freedesktop.network1.policy:144
 msgid "Authentication is required to send force renew message."
-msgstr ""
+msgstr "Autentimine on vajalik, et saata sunduuendamis sõnumi."
 
 #: src/network/org.freedesktop.network1.policy:154
 msgid "Renew dynamic addresses"
-msgstr ""
+msgstr "Uuenda dünaamilist aadressit"
 
 #: src/network/org.freedesktop.network1.policy:155
 msgid "Authentication is required to renew dynamic addresses."
-msgstr ""
+msgstr "Autentimine on vajalik, et uuendada dünaamilist aadressit."
 
 #: src/network/org.freedesktop.network1.policy:165
 msgid "Reload network settings"
-msgstr ""
+msgstr "Lae võrgu seaded uuesti"
 
 #: src/network/org.freedesktop.network1.policy:166
 msgid "Authentication is required to reload network settings."
-msgstr ""
+msgstr "Autentimine on vajalik, et laadida võrgu seaded uuesti."
 
 #: src/network/org.freedesktop.network1.policy:176
 msgid "Reconfigure network interface"
-msgstr ""
+msgstr "Määra võrguliides"
 
 #: src/network/org.freedesktop.network1.policy:177
 msgid "Authentication is required to reconfigure network interface."
@@ -771,15 +776,15 @@ msgstr ""
 
 #: src/timedate/org.freedesktop.timedate1.policy:22
 msgid "Set system time"
-msgstr ""
+msgstr "Säti süsteemi aeg"
 
 #: src/timedate/org.freedesktop.timedate1.policy:23
 msgid "Authentication is required to set the system time."
-msgstr ""
+msgstr "Autentimine on vajalik, et seadistada süsteemi aeg."
 
 #: src/timedate/org.freedesktop.timedate1.policy:33
 msgid "Set system timezone"
-msgstr ""
+msgstr "Säti süsteemi ajavöönd"
 
 #: src/timedate/org.freedesktop.timedate1.policy:34
 msgid "Authentication is required to set the system timezone."
index 71f1227923120ca84e8ee2f643a148962d87b478..3833ae9461c6960c4244bf98d8ac6c66b9da9a49 100644 (file)
@@ -318,7 +318,7 @@ static BOOLEAN line_edit(
                 case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0): /* EZpad Mini 4s firmware sends malformed events */
                 case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
                         if (!streq16(line, *line_in)) {
-                                FreePool(*line_in);
+                                free(*line_in);
                                 *line_in = TAKE_PTR(line);
                         }
                         return TRUE;
@@ -741,7 +741,7 @@ static BOOLEAN menu_run(
                 }
 
                 if (timeout_remain > 0) {
-                        FreePool(status);
+                        free(status);
                         status = xpool_print(L"Boot in %u s.", timeout_remain);
                 }
 
@@ -872,7 +872,7 @@ static BOOLEAN menu_run(
                 case KEYPRESS(0, 0, 'd'):
                 case KEYPRESS(0, 0, 'D'):
                         if (config->idx_default_efivar != idx_highlight) {
-                                FreePool(config->entry_default_efivar);
+                                free(config->entry_default_efivar);
                                 config->entry_default_efivar = xstrdup16(config->entries[idx_highlight]->id);
                                 config->idx_default_efivar = idx_highlight;
                                 status = xstrdup16(u"Default boot entry selected.");
@@ -1037,11 +1037,10 @@ static void config_add_entry(Config *config, ConfigEntry *entry) {
         assert(config->entry_count < IDX_MAX);
 
         if ((config->entry_count & 15) == 0) {
-                UINTN i = config->entry_count + 16;
-                config->entries = xreallocate_pool(
+                config->entries = xrealloc(
                                 config->entries,
                                 sizeof(void *) * config->entry_count,
-                                sizeof(void *) * i);
+                                sizeof(void *) * (config->entry_count + 16));
         }
         config->entries[config->entry_count++] = entry;
 }
@@ -1050,20 +1049,20 @@ static void config_entry_free(ConfigEntry *entry) {
         if (!entry)
                 return;
 
-        FreePool(entry->id);
-        FreePool(entry->title_show);
-        FreePool(entry->title);
-        FreePool(entry->sort_key);
-        FreePool(entry->version);
-        FreePool(entry->machine_id);
-        FreePool(entry->loader);
-        FreePool(entry->devicetree);
-        FreePool(entry->options);
+        free(entry->id);
+        free(entry->title_show);
+        free(entry->title);
+        free(entry->sort_key);
+        free(entry->version);
+        free(entry->machine_id);
+        free(entry->loader);
+        free(entry->devicetree);
+        free(entry->options);
         strv_free(entry->initrd);
-        FreePool(entry->path);
-        FreePool(entry->current_name);
-        FreePool(entry->next_name);
-        FreePool(entry);
+        free(entry->path);
+        free(entry->current_name);
+        free(entry->next_name);
+        free(entry);
 }
 
 static inline void config_entry_freep(ConfigEntry **entry) {
@@ -1170,11 +1169,11 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) {
                 }
 
                 if (streq8((char *) key, "default")) {
-                        if (value[0] == '@' && !streq8((char *) value, "@saved")) {
+                        if (value[0] == '@' && !strcaseeq8((char *) value, "@saved")) {
                                 log_error_stall(L"Unsupported special entry identifier: %a", value);
                                 continue;
                         }
-                        FreePool(config->entry_default_config);
+                        free(config->entry_default_config);
                         config->entry_default_config = xstra_to_str(value);
                         continue;
                 }
@@ -1416,7 +1415,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) {
 
         /* If the file we just renamed is the loader path, then let's update that. */
         if (streq16(entry->loader, old_path)) {
-                FreePool(entry->loader);
+                free(entry->loader);
                 entry->loader = TAKE_PTR(new_path);
         }
 }
@@ -1451,31 +1450,31 @@ static void config_entry_add_type1(
 
         while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) {
                 if (streq8((char *) key, "title")) {
-                        FreePool(entry->title);
+                        free(entry->title);
                         entry->title = xstra_to_str(value);
                         continue;
                 }
 
                 if (streq8((char *) key, "sort-key")) {
-                        FreePool(entry->sort_key);
+                        free(entry->sort_key);
                         entry->sort_key = xstra_to_str(value);
                         continue;
                 }
 
                 if (streq8((char *) key, "version")) {
-                        FreePool(entry->version);
+                        free(entry->version);
                         entry->version = xstra_to_str(value);
                         continue;
                 }
 
                 if (streq8((char *) key, "machine-id")) {
-                        FreePool(entry->machine_id);
+                        free(entry->machine_id);
                         entry->machine_id = xstra_to_str(value);
                         continue;
                 }
 
                 if (streq8((char *) key, "linux")) {
-                        FreePool(entry->loader);
+                        free(entry->loader);
                         entry->type = LOADER_LINUX;
                         entry->loader = xstra_to_path(value);
                         entry->key = 'l';
@@ -1484,7 +1483,7 @@ static void config_entry_add_type1(
 
                 if (streq8((char *) key, "efi")) {
                         entry->type = LOADER_EFI;
-                        FreePool(entry->loader);
+                        free(entry->loader);
                         entry->loader = xstra_to_path(value);
 
                         /* do not add an entry for ourselves */
@@ -1505,13 +1504,13 @@ static void config_entry_add_type1(
                 }
 
                 if (streq8((char *) key, "devicetree")) {
-                        FreePool(entry->devicetree);
+                        free(entry->devicetree);
                         entry->devicetree = xstra_to_path(value);
                         continue;
                 }
 
                 if (streq8((char *) key, "initrd")) {
-                        entry->initrd = xreallocate_pool(
+                        entry->initrd = xrealloc(
                                 entry->initrd,
                                 n_initrd == 0 ? 0 : (n_initrd + 1) * sizeof(UINT16 *),
                                 (n_initrd + 2) * sizeof(UINT16 *));
@@ -1528,7 +1527,7 @@ static void config_entry_add_type1(
                                 CHAR16 *s;
 
                                 s = xpool_print(L"%s %s", entry->options, new);
-                                FreePool(entry->options);
+                                free(entry->options);
                                 entry->options = s;
                         } else
                                 entry->options = TAKE_PTR(new);
@@ -1606,6 +1605,11 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
 
         (void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &config->entry_default_efivar);
 
+        strtolower16(config->entry_default_config);
+        strtolower16(config->entry_default_efivar);
+        strtolower16(config->entry_oneshot);
+        strtolower16(config->entry_saved);
+
         config->use_saved_entry = streq16(config->entry_default_config, L"@saved");
         config->use_saved_entry_efivar = streq16(config->entry_default_efivar, L"@saved");
         if (config->use_saved_entry || config->use_saved_entry_efivar)
@@ -1710,14 +1714,16 @@ static int config_entry_compare(const ConfigEntry *a, const ConfigEntry *b) {
         return CMP(a->tries_done, b->tries_done);
 }
 
-static UINTN config_entry_find(Config *config, const CHAR16 *needle) {
+static UINTN config_entry_find(Config *config, const CHAR16 *pattern) {
         assert(config);
 
-        if (!needle)
+        /* We expect pattern and entry IDs to be already case folded. */
+
+        if (!pattern)
                 return IDX_INVALID;
 
         for (UINTN i = 0; i < config->entry_count; i++)
-                if (MetaiMatch(config->entries[i]->id, (CHAR16*) needle))
+                if (efi_fnmatch(pattern, config->entries[i]->id))
                         return i;
 
         return IDX_INVALID;
@@ -1935,13 +1941,14 @@ static void config_entry_add_osx(Config *config) {
         if (!config->auto_entries)
                 return;
 
-        err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &n_handles, &handles);
-        if (EFI_ERROR(err))
+        err = BS->LocateHandleBuffer(ByProtocol, &FileSystemProtocol, NULL, &n_handles, &handles);
+        if (err != EFI_SUCCESS)
                 return;
 
         for (UINTN i = 0; i < n_handles; i++) {
-                _cleanup_(file_closep) EFI_FILE *root = LibOpenRoot(handles[i]);
-                if (!root)
+                _cleanup_(file_closep) EFI_FILE *root = NULL;
+
+                if (open_volume(handles[i], &root) != EFI_SUCCESS)
                         continue;
 
                 if (config_entry_add_loader_auto(
@@ -2133,49 +2140,49 @@ static void config_entry_add_unified(
                 /* read properties from the embedded os-release file */
                 while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
                         if (streq8((char *) key, "PRETTY_NAME")) {
-                                FreePool(os_pretty_name);
+                                free(os_pretty_name);
                                 os_pretty_name = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "IMAGE_ID")) {
-                                FreePool(os_image_id);
+                                free(os_image_id);
                                 os_image_id = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "NAME")) {
-                                FreePool(os_name);
+                                free(os_name);
                                 os_name = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "ID")) {
-                                FreePool(os_id);
+                                free(os_id);
                                 os_id = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "IMAGE_VERSION")) {
-                                FreePool(os_image_version);
+                                free(os_image_version);
                                 os_image_version = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "VERSION")) {
-                                FreePool(os_version);
+                                free(os_version);
                                 os_version = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "VERSION_ID")) {
-                                FreePool(os_version_id);
+                                free(os_version_id);
                                 os_version_id = xstra_to_str(value);
                                 continue;
                         }
 
                         if (streq8((char *) key, "BUILD_ID")) {
-                                FreePool(os_build_id);
+                                free(os_build_id);
                                 os_build_id = xstra_to_str(value);
                                 continue;
                         }
@@ -2242,7 +2249,7 @@ static void config_load_xbootldr(
         assert(device);
 
         err = xbootldr_open(device, &new_device, &root_dir);
-        if (EFI_ERROR(err))
+        if (err != EFI_SUCCESS)
                 return;
 
         config_entry_add_unified(config, new_device, root_dir);
@@ -2300,7 +2307,7 @@ static EFI_STATUS initrd_prepare(
                 UINTN new_size, read_size = info->FileSize;
                 if (__builtin_add_overflow(size, read_size, &new_size))
                         return EFI_OUT_OF_RESOURCES;
-                initrd = xreallocate_pool(initrd, size, new_size);
+                initrd = xrealloc(initrd, size, new_size);
 
                 err = handle->Read(handle, &read_size, initrd + size);
                 if (EFI_ERROR(err))
@@ -2337,13 +2344,14 @@ static EFI_STATUS image_start(
         if (entry->call)
                 (void) entry->call();
 
-        _cleanup_(file_closep) EFI_FILE *image_root = LibOpenRoot(entry->device);
-        if (!image_root)
-                return log_error_status_stall(EFI_DEVICE_ERROR, L"Error opening root path.");
+        _cleanup_(file_closep) EFI_FILE *image_root = NULL;
+        err = open_volume(entry->device, &image_root);
+        if (err != EFI_SUCCESS)
+                return log_error_status_stall(err, L"Error opening root path: %r", err);
 
-        path = FileDevicePath(entry->device, entry->loader);
-        if (!path)
-                return log_error_status_stall(EFI_INVALID_PARAMETER, L"Error getting device path.");
+        err = make_file_device_path(entry->device, entry->loader, &path);
+        if (err != EFI_SUCCESS)
+                return log_error_status_stall(err, L"Error making file device path: %r", err);
 
         UINTN initrd_size = 0;
         _cleanup_freepool_ void *initrd = NULL;
@@ -2413,9 +2421,9 @@ static void config_free(Config *config) {
         assert(config);
         for (UINTN i = 0; i < config->entry_count; i++)
                 config_entry_free(config->entries[i]);
-        FreePool(config->entries);
-        FreePool(config->entry_default_config);
-        FreePool(config->entry_oneshot);
+        free(config->entries);
+        free(config->entry_default_config);
+        free(config->entry_oneshot);
 }
 
 static void config_write_entries_to_variable(Config *config) {
@@ -2428,7 +2436,7 @@ static void config_write_entries_to_variable(Config *config) {
         for (UINTN i = 0; i < config->entry_count; i++)
                 sz += strsize16(config->entries[i]->id);
 
-        p = buffer = xallocate_pool(sz);
+        p = buffer = xmalloc(sz);
 
         for (UINTN i = 0; i < config->entry_count; i++) {
                 UINTN l;
@@ -2595,9 +2603,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
 
         export_variables(loaded_image, loaded_image_path, init_usec);
 
-        root_dir = LibOpenRoot(loaded_image->DeviceHandle);
-        if (!root_dir)
-                return log_error_status_stall(EFI_LOAD_ERROR, L"Unable to open root directory.", EFI_LOAD_ERROR);
+        err = open_volume(loaded_image->DeviceHandle, &root_dir);
+        if (err != EFI_SUCCESS)
+                return log_error_status_stall(err, L"Unable to open root directory: %r", err);
 
         if (secure_boot_enabled() && shim_loaded()) {
                 err = security_policy_install();
index 937ad7ddfd052aee0103b1e263c51aa76c3e6602..009d3672b8944948dabbcd45bc0596554ea662c0 100644 (file)
@@ -48,7 +48,7 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
 
         if (!checked) {
                 /* Get the *first* TextInputEx device.*/
-                err = LibLocateProtocol(&SimpleTextInputExProtocol, (void **) &extraInEx);
+                err = BS->LocateProtocol(&SimpleTextInputExProtocol, NULL, (void **) &extraInEx);
                 if (EFI_ERROR(err) || BS->CheckEvent(extraInEx->WaitForKeyEx) == EFI_INVALID_PARAMETER)
                         /* If WaitForKeyEx fails here, the firmware pretends it talks this
                          * protocol, but it really doesn't. */
@@ -185,7 +185,7 @@ EFI_STATUS query_screen_resolution(UINT32 *ret_w, UINT32 *ret_h) {
         EFI_STATUS err;
         EFI_GRAPHICS_OUTPUT_PROTOCOL *go;
 
-        err = LibLocateProtocol(&GraphicsOutputProtocol, (void **) &go);
+        err = BS->LocateProtocol(&GraphicsOutputProtocol, NULL, (void **) &go);
         if (EFI_ERROR(err))
                 return err;
 
index aebffb51b7c317fbb1539bf7d6b7e7757145e7b9..454d79e11808cc5066139edf8078ec90ec22bff1 100644 (file)
@@ -111,7 +111,7 @@ static EFI_STATUS pack_cpio_one(
 
         if (*cpio_buffer_size > UINTN_MAX - l) /* overflow check */
                 return EFI_OUT_OF_RESOURCES;
-        a = xreallocate_pool(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + l);
+        a = xrealloc(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + l);
 
         *cpio_buffer = a;
         a = (CHAR8*) *cpio_buffer + *cpio_buffer_size;
@@ -195,7 +195,7 @@ static EFI_STATUS pack_cpio_dir(
         if (*cpio_buffer_size > UINTN_MAX - l) /* overflow check */
                 return EFI_OUT_OF_RESOURCES;
 
-        *cpio_buffer = a = xreallocate_pool(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + l);
+        *cpio_buffer = a = xrealloc(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + l);
         a = (CHAR8*) *cpio_buffer + *cpio_buffer_size;
 
         memcpy(a, "070701", 6); /* magic ID */
@@ -297,7 +297,7 @@ static EFI_STATUS pack_cpio_trailer(
         assert(cpio_buffer_size);
         assert_cc(sizeof(trailer) % 4 == 0);
 
-        *cpio_buffer = xreallocate_pool(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + sizeof(trailer));
+        *cpio_buffer = xrealloc(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + sizeof(trailer));
         memcpy((UINT8*) *cpio_buffer + *cpio_buffer_size, trailer, sizeof(trailer));
         *cpio_buffer_size += sizeof(trailer);
 
@@ -401,7 +401,7 @@ EFI_STATUS pack_cpio(
                                 return log_oom();
 
                         m = n_items + 16;
-                        items = xreallocate_pool(items, n_allocated * sizeof(UINT16*), m * sizeof(UINT16*));
+                        items = xrealloc(items, n_allocated * sizeof(UINT16*), m * sizeof(UINT16*));
                         n_allocated = m;
                 }
 
index 81c6e60ca66818eac61d41a87fb47eba03e62ae7..15513a98e6f4f755c02373e2de089d3fad9b0326 100644 (file)
@@ -8,6 +8,13 @@
 
 #define FDT_V1_SIZE (7*4)
 
+static void *get_dtb_table(void) {
+        for (UINTN i = 0; i < ST->NumberOfTableEntries; i++)
+                if (memcmp(&EfiDtbTableGuid, &ST->ConfigurationTable[i].VendorGuid, sizeof(EfiDtbTableGuid)) == 0)
+                        return ST->ConfigurationTable[i].VendorTable;
+        return NULL;
+}
+
 static EFI_STATUS devicetree_allocate(struct devicetree_state *state, UINTN size) {
         UINTN pages = DIV_ROUND_UP(size, EFI_PAGE_SIZE);
         EFI_STATUS err;
@@ -34,7 +41,7 @@ static EFI_STATUS devicetree_fixup(struct devicetree_state *state, UINTN len) {
 
         assert(state);
 
-        err = LibLocateProtocol(&EfiDtFixupProtocol, (void **)&fixup);
+        err = BS->LocateProtocol(&EfiDtFixupProtocol, NULL, (void **) &fixup);
         if (EFI_ERROR(err))
                 return log_error_status_stall(EFI_SUCCESS,
                                               L"Could not locate device tree fixup protocol, skipping.");
@@ -74,8 +81,8 @@ EFI_STATUS devicetree_install(struct devicetree_state *state, EFI_FILE *root_dir
         assert(root_dir);
         assert(name);
 
-        err = LibGetSystemConfigurationTable(&EfiDtbTableGuid, &state->orig);
-        if (EFI_ERROR(err))
+        state->orig = get_dtb_table();
+        if (!state->orig)
                 return EFI_UNSUPPORTED;
 
         err = root_dir->Open(root_dir, &handle, name, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY);
@@ -114,8 +121,8 @@ EFI_STATUS devicetree_install_from_memory(struct devicetree_state *state,
         assert(state);
         assert(dtb_buffer && dtb_length > 0);
 
-        err = LibGetSystemConfigurationTable(&EfiDtbTableGuid, &state->orig);
-        if (EFI_ERROR(err))
+        state->orig = get_dtb_table();
+        if (!state->orig)
                 return EFI_UNSUPPORTED;
 
         err = devicetree_allocate(state, dtb_length);
index b7beac3d08b9683b2b230c3bdbbc748c7c7b8f6b..bf2984ed1fa5919f36c63f26090aa603a61aed50 100644 (file)
@@ -7,30 +7,33 @@
 #include "util.h"
 
 EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) {
-        EFI_DEVICE_PATH *device_path;
-        _cleanup_freepool_ EFI_DEVICE_PATH *paths = NULL;
-
-        if (!handle)
-                return EFI_NOT_FOUND;
+        EFI_STATUS err;
+        EFI_DEVICE_PATH *dp;
 
         /* export the device path this image is started from */
-        device_path = DevicePathFromHandle(handle);
-        if (!device_path)
+
+        if (!handle)
                 return EFI_NOT_FOUND;
 
-        paths = UnpackDevicePath(device_path);
-        for (EFI_DEVICE_PATH *path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
-                HARDDRIVE_DEVICE_PATH *drive;
+        err = BS->HandleProtocol(handle, &DevicePathProtocol, (void **) &dp);
+        if (err != EFI_SUCCESS)
+                return err;
 
-                if (DevicePathType(path) != MEDIA_DEVICE_PATH)
+        for (; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
+                if (DevicePathType(dp) != MEDIA_DEVICE_PATH)
                         continue;
-                if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP)
+                if (DevicePathSubType(dp) != MEDIA_HARDDRIVE_DP)
                         continue;
-                drive = (HARDDRIVE_DEVICE_PATH *)path;
-                if (drive->SignatureType != SIGNATURE_TYPE_GUID)
+
+                HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *) dp;
+                if (hd->SignatureType != SIGNATURE_TYPE_GUID)
                         continue;
 
-                GuidToString(uuid, (EFI_GUID *)&drive->Signature);
+                /* Use memcpy in case the device path node is misaligned. */
+                EFI_GUID sig;
+                memcpy(&sig, hd->Signature, sizeof(hd->Signature));
+
+                GuidToString(uuid, &sig);
                 return EFI_SUCCESS;
         }
 
index 65c74c461d52c8c454f2a271e1c08b7e9004cf9a..615c4ca1f3b8cae43a93b506c798f73b7eab4e80 100644 (file)
@@ -21,9 +21,9 @@ static EFI_STATUS load_one_driver(
         assert(fname);
 
         spath = xpool_print(L"\\EFI\\systemd\\drivers\\%s", fname);
-        path = FileDevicePath(loaded_image->DeviceHandle, spath);
-        if (!path)
-                return log_oom();
+        err = make_file_device_path(loaded_image->DeviceHandle, spath, &path);
+        if (err != EFI_SUCCESS)
+                return log_error_status_stall(err, L"Error making file device path: %r", err);
 
         err = BS->LoadImage(FALSE, parent_image, path, NULL, 0, &image);
         if (EFI_ERROR(err))
index 4b405155a03975097bc8425925dfa27c8f88da04..b9ef1548ca24494fe21ab6b1c460905a60aebc97 100644 (file)
@@ -7,7 +7,6 @@
 
 #ifdef SD_BOOT
 #  include "util.h"
-#  define xmalloc(n) xallocate_pool(n)
 #else
 #  include <stdlib.h>
 #  include "macro.h"
@@ -139,6 +138,107 @@ DEFINE_STRCHR(char16_t, strchr16);
 DEFINE_STRNDUP(char, xstrndup8, strnlen8);
 DEFINE_STRNDUP(char16_t, xstrndup16, strnlen16);
 
+/* Patterns are fnmatch-compatible (with reduced feature support). */
+static bool efi_fnmatch_internal(const char16_t *p, const char16_t *h, int max_depth) {
+        assert(p);
+        assert(h);
+
+        if (max_depth == 0)
+                return false;
+
+        for (;; p++, h++)
+                switch (*p) {
+                case '\0':
+                        /* End of pattern. Check that haystack is now empty. */
+                        return *h == '\0';
+
+                case '\\':
+                        p++;
+                        if (*p == '\0' || *p != *h)
+                                /* Trailing escape or no match. */
+                                return false;
+                        break;
+
+                case '?':
+                        if (*h == '\0')
+                                /* Early end of haystack. */
+                                return false;
+                        break;
+
+                case '*':
+                        /* No need to recurse for consecutive '*'. */
+                        while (*p == '*')
+                                p++;
+
+                        for (; *h != '\0'; h++)
+                                /* Try matching haystack with remaining pattern. */
+                                if (efi_fnmatch_internal(p, h, max_depth - 1))
+                                        return true;
+
+                        /* End of haystack. Pattern needs to be empty too for a match. */
+                        return *p == '\0';
+
+                case '[':
+                        if (*h == '\0')
+                                /* Early end of haystack. */
+                                return false;
+
+                        bool first = true, can_range = true, match = false;
+                        for (;; first = false) {
+                                p++;
+                                if (*p == '\0')
+                                        return false;
+
+                                if (*p == '\\') {
+                                        p++;
+                                        if (*p == '\0')
+                                                return false;
+                                        match |= *p == *h;
+                                        can_range = true;
+                                        continue;
+                                }
+
+                                /* End of set unless it's the first char. */
+                                if (*p == ']' && !first)
+                                        break;
+
+                                /* Range pattern if '-' is not first or last in set. */
+                                if (*p == '-' && can_range && !first && *(p + 1) != ']') {
+                                        char16_t low = *(p - 1);
+                                        p++;
+                                        if (*p == '\\')
+                                                p++;
+                                        if (*p == '\0')
+                                                return false;
+
+                                        if (low <= *h && *h <= *p)
+                                                match = true;
+
+                                        /* Ranges cannot be chained: [a-c-f] == [-abcf] */
+                                        can_range = false;
+                                        continue;
+                                }
+
+                                if (*p == *h)
+                                        match = true;
+                                can_range = true;
+                        }
+
+                        if (!match)
+                                return false;
+                        break;
+
+                default:
+                        if (*p != *h)
+                                /* Single char mismatch. */
+                                return false;
+                }
+}
+
+bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack) {
+        return efi_fnmatch_internal(pattern, haystack, 32);
+}
+
 int efi_memcmp(const void *p1, const void *p2, size_t n) {
         const uint8_t *up1 = p1, *up2 = p2;
         int r;
index b4870975bcba1a2888cd596ef5c20129cff7bf95..55c9c6e47ad7224b2e2abee91ae6da956641511f 100644 (file)
@@ -99,6 +99,8 @@ static inline char16_t *xstrdup16(const char16_t *s) {
         return xstrndup16(s, SIZE_MAX);
 }
 
+bool efi_fnmatch(const char16_t *pattern, const char16_t *haystack);
+
 #ifdef SD_BOOT
 /* The compiler normally has knowledge about standard functions such as memcmp, but this is not the case when
  * compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do
index 62a3512fa38b26ded1f8c33b97cac27e395263dd..9e69c2703da172bb52c154787deef1ece984f859 100644 (file)
@@ -19,7 +19,7 @@ EFI_STATUS graphics_mode(BOOLEAN on) {
         BOOLEAN stdin_locked;
         EFI_STATUS err;
 
-        err = LibLocateProtocol((EFI_GUID*) EFI_CONSOLE_CONTROL_GUID, (void **)&ConsoleControl);
+        err = BS->LocateProtocol((EFI_GUID *) EFI_CONSOLE_CONTROL_GUID, NULL, (void **) &ConsoleControl);
         if (EFI_ERROR(err))
                 /* console control protocol is nonstandard and might not exist. */
                 return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
index 2d0984990bf8abc686bb20a91f8434335df59a6a..1b4e746483001886a1b74315aa89730188bb24a2 100644 (file)
@@ -103,7 +103,7 @@ EFI_STATUS initrd_register(
                         &EfiLoadFile2Protocol, loader,
                         NULL);
         if (EFI_ERROR(err))
-                FreePool(loader);
+                free(loader);
 
         return err;
 }
@@ -135,6 +135,6 @@ EFI_STATUS initrd_unregister(EFI_HANDLE initrd_handle) {
                 return err;
 
         initrd_handle = NULL;
-        FreePool(loader);
+        free(loader);
         return EFI_SUCCESS;
 }
index c9ce8f19e0fbf0f7d03714bcb368e6201d399f7b..def42fece4f179de5298a57a91c28d51cae6510a 100644 (file)
@@ -26,7 +26,8 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(
         assert(description);
 
         desc_len = strsize16(description);
-        tcg_event = xallocate_zero_pool(offsetof(TCG_PCR_EVENT, Event) + desc_len);
+        tcg_event = xmalloc(offsetof(TCG_PCR_EVENT, Event) + desc_len);
+        memset(tcg_event, 0, offsetof(TCG_PCR_EVENT, Event) + desc_len);
         *tcg_event = (TCG_PCR_EVENT) {
                 .EventSize = desc_len,
                 .PCRIndex = pcrindex,
@@ -57,7 +58,8 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log(
         assert(description);
 
         desc_len = strsize16(description);
-        tcg_event = xallocate_zero_pool(offsetof(EFI_TCG2_EVENT, Event) + desc_len);
+        tcg_event = xmalloc(offsetof(EFI_TCG2_EVENT, Event) + desc_len);
+        memset(tcg_event, 0, offsetof(EFI_TCG2_EVENT, Event) + desc_len);
         *tcg_event = (EFI_TCG2_EVENT) {
                 .Size = offsetof(EFI_TCG2_EVENT, Event) + desc_len,
                 .Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER),
@@ -84,7 +86,7 @@ static EFI_TCG *tcg1_interface_check(void) {
         UINT32 features;
         EFI_TCG *tcg;
 
-        status = LibLocateProtocol((EFI_GUID*) EFI_TCG_GUID, (void **) &tcg);
+        status = BS->LocateProtocol((EFI_GUID *) EFI_TCG_GUID, NULL, (void **) &tcg);
         if (EFI_ERROR(status))
                 return NULL;
 
@@ -113,7 +115,7 @@ static EFI_TCG2 * tcg2_interface_check(void) {
         EFI_STATUS status;
         EFI_TCG2 *tcg;
 
-        status = LibLocateProtocol((EFI_GUID*) EFI_TCG2_GUID, (void **) &tcg);
+        status = BS->LocateProtocol((EFI_GUID *) EFI_TCG2_GUID, NULL, (void **) &tcg);
         if (EFI_ERROR(status))
                 return NULL;
 
index f9bd57f0ce5e658cddffb3a79700938e1390daaf..c1a4064896196f1eb1cd52f09a87ad75be7b91ed 100644 (file)
@@ -318,7 +318,7 @@ EFI_STATUS pe_file_locate_sections(
                 return EFI_LOAD_ERROR;
 
         section_table_len = pe.FileHeader.NumberOfSections * sizeof(struct PeSectionHeader);
-        section_table = xallocate_pool(section_table_len);
+        section_table = xmalloc(section_table_len);
         if (!section_table)
                 return EFI_OUT_OF_RESOURCES;
 
index a9ee2736736ff1a4c452b57854bd81cf8bb0afdf..116ccfe515b53ea10a21d8b2c0cb96d73275c3e2 100644 (file)
@@ -26,13 +26,13 @@ static EFI_STATUS acquire_rng(UINTN size, void **ret) {
 
         /* Try to acquire the specified number of bytes from the UEFI RNG */
 
-        err = LibLocateProtocol((EFI_GUID*) EFI_RNG_GUID, (void**) &rng);
+        err = BS->LocateProtocol((EFI_GUID *) EFI_RNG_GUID, NULL, (void **) &rng);
         if (EFI_ERROR(err))
                 return err;
         if (!rng)
                 return EFI_UNSUPPORTED;
 
-        data = xallocate_pool(size);
+        data = xmalloc(size);
 
         err = rng->GetRNG(rng, NULL, size, data);
         if (EFI_ERROR(err))
@@ -99,7 +99,7 @@ static EFI_STATUS hash_many(
         /* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the
          * range counter_start…counter_start+n-1. */
 
-        output = xallocate_pool(n * HASH_VALUE_SIZE);
+        output = xmalloc_multiply(HASH_VALUE_SIZE, n);
 
         for (UINTN i = 0; i < n; i++)
                 hash_once(old_seed, rng, size,
@@ -274,7 +274,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
         if (size > RANDOM_MAX_SIZE_MAX)
                 return log_error_status_stall(EFI_INVALID_PARAMETER, L"Random seed file is too large.");
 
-        seed = xallocate_pool(size);
+        seed = xmalloc(size);
 
         rsize = size;
         err = handle->Read(handle, &rsize, seed);
index fb4aecaee0217ada87254dc279fa4bf14770ca4b..20db89817a88e7e1c51dcb8ea076e0c5faee9fbe 100644 (file)
@@ -102,7 +102,6 @@ static EFIAPI EFI_STATUS security2_policy_authentication (const EFI_SECURITY2_PR
 static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROTOCOL *this, UINT32 authentication_status,
                                                          const EFI_DEVICE_PATH_PROTOCOL *device_path_const) {
         EFI_STATUS status;
-        _cleanup_freepool_ EFI_DEVICE_PATH *dev_path = NULL;
         _cleanup_freepool_ CHAR16 *dev_path_str = NULL;
         EFI_HANDLE h;
         _cleanup_freepool_ CHAR8 *file_buffer = NULL;
@@ -113,18 +112,15 @@ static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROT
         if (!device_path_const)
                 return EFI_INVALID_PARAMETER;
 
-        dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const);
-        if (!dev_path)
-                return EFI_OUT_OF_RESOURCES;
-
-        EFI_DEVICE_PATH *dp = dev_path;
+        EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) device_path_const;
         status = BS->LocateDevicePath(&FileSystemProtocol, &dp, &h);
         if (EFI_ERROR(status))
                 return status;
 
-        _cleanup_(file_closep) EFI_FILE *root = LibOpenRoot(h);
-        if (!root)
-                return EFI_NOT_FOUND;
+        _cleanup_(file_closep) EFI_FILE *root = NULL;
+        status = open_volume(h, &root);
+        if (status != EFI_SUCCESS)
+                return status;
 
         dev_path_str = DevicePathToStr(dp);
         if (!dev_path_str)
index e0d075c911f8afa5f5a3592a4487318d64330f56..2fd2db6ba0b1ca66d10ccc7afa54c310aeb2017f 100644 (file)
@@ -279,7 +279,7 @@ EFI_STATUS graphics_splash(const UINT8 *content, UINTN len, const EFI_GRAPHICS_O
                 background = &pixel;
         }
 
-        err = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&GraphicsOutput);
+        err = BS->LocateProtocol(&GraphicsOutputProtocol, NULL, (void **) &GraphicsOutput);
         if (EFI_ERROR(err))
                 return err;
 
index f335d3782d58b4accde45233807107dff2064bf5..9fe521efd40508c7e5c8360cc8561cc42ad56c42 100644 (file)
@@ -214,7 +214,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 &&
             *(CHAR16 *) loaded_image->LoadOptions > 0x1F) {
                 cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
-                cmdline = cmdline_owned = xallocate_pool(cmdline_len);
+                cmdline = cmdline_owned = xmalloc(cmdline_len);
 
                 for (UINTN i = 0; i < cmdline_len; i++)
                         cmdline[i] = ((CHAR16 *) loaded_image->LoadOptions)[i];
index b688c6ae4101168f54ddf728ca6db7c53eaa8cc0..178ad766cb460675aff6ceb065351fc89cc77ebb 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <fnmatch.h>
+
 #include "efi-string.h"
 #include "tests.h"
 
@@ -322,6 +324,53 @@ TEST(xstrdup16) {
         free(s);
 }
 
+#define TEST_FNMATCH_ONE(pattern, haystack, expect)                                     \
+        ({                                                                              \
+                assert_se(fnmatch(pattern, haystack, 0) == (expect ? 0 : FNM_NOMATCH)); \
+                assert_se(efi_fnmatch(u##pattern, u##haystack) == expect);              \
+        })
+
+TEST(efi_fnmatch) {
+        TEST_FNMATCH_ONE("", "", true);
+        TEST_FNMATCH_ONE("abc", "abc", true);
+        TEST_FNMATCH_ONE("aBc", "abc", false);
+        TEST_FNMATCH_ONE("b", "a", false);
+        TEST_FNMATCH_ONE("b", "", false);
+        TEST_FNMATCH_ONE("abc", "a", false);
+        TEST_FNMATCH_ONE("a?c", "azc", true);
+        TEST_FNMATCH_ONE("???", "?.9", true);
+        TEST_FNMATCH_ONE("1?", "1", false);
+        TEST_FNMATCH_ONE("***", "", true);
+        TEST_FNMATCH_ONE("*", "123", true);
+        TEST_FNMATCH_ONE("**", "abcd", true);
+        TEST_FNMATCH_ONE("*b*", "abcd", true);
+        TEST_FNMATCH_ONE("abc*d", "abc", false);
+        TEST_FNMATCH_ONE("*.conf", "arch.conf", true);
+        TEST_FNMATCH_ONE("debian-*.conf", "debian-wheezy.conf", true);
+        TEST_FNMATCH_ONE("debian-*.*", "debian-wheezy.efi", true);
+        TEST_FNMATCH_ONE("ab*cde", "abzcd", false);
+        TEST_FNMATCH_ONE("\\*\\a\\[", "*a[", true);
+        TEST_FNMATCH_ONE("[abc] [abc] [abc]", "a b c", true);
+        TEST_FNMATCH_ONE("abc]", "abc]", true);
+        TEST_FNMATCH_ONE("[abc]", "z", false);
+        TEST_FNMATCH_ONE("[abc", "a", false);
+        TEST_FNMATCH_ONE("[][!] [][!] [][!]", "[ ] !", true);
+        TEST_FNMATCH_ONE("[]-] []-]", "] -", true);
+        TEST_FNMATCH_ONE("[1\\]] [1\\]]", "1 ]", true);
+        TEST_FNMATCH_ONE("[$-\\+]", "&", true);
+        TEST_FNMATCH_ONE("[1-3A-C] [1-3A-C]", "2 B", true);
+        TEST_FNMATCH_ONE("[3-5] [3-5] [3-5]", "3 4 5", true);
+        TEST_FNMATCH_ONE("[f-h] [f-h] [f-h]", "f g h", true);
+        TEST_FNMATCH_ONE("[a-c-f] [a-c-f] [a-c-f] [a-c-f] [a-c-f]", "a b c - f", true);
+        TEST_FNMATCH_ONE("[a-c-f]", "e", false);
+        TEST_FNMATCH_ONE("[--0] [--0] [--0]", "- . 0", true);
+        TEST_FNMATCH_ONE("[+--] [+--] [+--]", "+ , -", true);
+        TEST_FNMATCH_ONE("[f-l]", "m", false);
+        TEST_FNMATCH_ONE("[b]", "z-a", false);
+        TEST_FNMATCH_ONE("[a\\-z]", "b", false);
+        TEST_FNMATCH_ONE("?a*b[.-0]c", "/a/b/c", true);
+}
+
 TEST(efi_memcmp) {
         assert_se(efi_memcmp(NULL, NULL, 0) == 0);
         assert_se(efi_memcmp(NULL, NULL, 1) == 0);
index 06859d2f3a3a22f987071b7ee80f8eec46fa6f19..c6324035ad59d7e1161329f7eeeaf815c848a31b 100644 (file)
@@ -115,7 +115,7 @@ EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value
         }
 
         /* Make sure a terminating NUL is available at the end */
-        val = xallocate_pool(size + sizeof(CHAR16));
+        val = xmalloc(size + sizeof(CHAR16));
 
         memcpy(val, buf, size);
         val[size / sizeof(CHAR16) - 1] = 0; /* NUL terminate */
@@ -189,7 +189,7 @@ EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **bu
         assert(name);
 
         l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
-        buf = xallocate_pool(l);
+        buf = xmalloc(l);
 
         err = RT->GetVariable((CHAR16 *) name, (EFI_GUID *) vendor, NULL, &l, buf);
         if (!EFI_ERROR(err)) {
@@ -391,7 +391,7 @@ EFI_STATUS file_read(EFI_FILE *dir, const CHAR16 *name, UINTN off, UINTN size, C
         /* Allocate some extra bytes to guarantee the result is NUL-terminated for CHAR8 and CHAR16 strings. */
         UINTN extra = size % sizeof(CHAR16) + sizeof(CHAR16);
 
-        buf = xallocate_pool(size + extra);
+        buf = xmalloc(size + extra);
         err = handle->Read(handle, &size, buf);
         if (EFI_ERROR(err))
                 return err;
@@ -486,11 +486,11 @@ EFI_STATUS get_file_info_harder(
 
         /* A lot like LibFileInfo() but with useful error propagation */
 
-        fi = xallocate_pool(size);
+        fi = xmalloc(size);
         err = handle->GetInfo(handle, &GenericFileInfo, &size, fi);
         if (err == EFI_BUFFER_TOO_SMALL) {
-                FreePool(fi);
-                fi = xallocate_pool(size);  /* GetInfo tells us the required size, let's use that now */
+                free(fi);
+                fi = xmalloc(size);  /* GetInfo tells us the required size, let's use that now */
                 err = handle->GetInfo(handle, &GenericFileInfo, &size, fi);
         }
 
@@ -527,15 +527,15 @@ EFI_STATUS readdir_harder(
                  * file name length.
                  * As a side effect, most readdir_harder() calls will now be slightly faster. */
                 sz = sizeof(EFI_FILE_INFO) + 256 * sizeof(CHAR16);
-                *buffer = xallocate_pool(sz);
+                *buffer = xmalloc(sz);
                 *buffer_size = sz;
         } else
                 sz = *buffer_size;
 
         err = handle->Read(handle, &sz, *buffer);
         if (err == EFI_BUFFER_TOO_SMALL) {
-                FreePool(*buffer);
-                *buffer = xallocate_pool(sz);
+                free(*buffer);
+                *buffer = xmalloc(sz);
                 *buffer_size = sz;
                 err = handle->Read(handle, &sz, *buffer);
         }
@@ -544,7 +544,7 @@ EFI_STATUS readdir_harder(
 
         if (sz == 0) {
                 /* End of directory */
-                FreePool(*buffer);
+                free(*buffer);
                 *buffer = NULL;
                 *buffer_size = 0;
         }
@@ -568,9 +568,9 @@ CHAR16 **strv_free(CHAR16 **v) {
                 return NULL;
 
         for (CHAR16 **i = v; *i; i++)
-                FreePool(*i);
+                free(*i);
 
-        FreePool(v);
+        free(v);
         return NULL;
 }
 
@@ -682,3 +682,59 @@ void beep(UINTN beep_count) {
         }
 }
 #endif
+
+EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file) {
+        EFI_STATUS err;
+        EFI_FILE *file;
+        EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *volume;
+
+        assert(ret_file);
+
+        err = BS->HandleProtocol(device, &FileSystemProtocol, (void **) &volume);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        err = volume->OpenVolume(volume, &file);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        *ret_file = file;
+        return EFI_SUCCESS;
+}
+
+EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp) {
+        EFI_STATUS err;
+        EFI_DEVICE_PATH *dp;
+
+        assert(file);
+        assert(ret_dp);
+
+        err = BS->HandleProtocol(device, &DevicePathProtocol, (void **) &dp);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        EFI_DEVICE_PATH *end_node = dp;
+        while (!IsDevicePathEnd(end_node))
+                end_node = NextDevicePathNode(end_node);
+
+        size_t file_size = strsize16(file);
+        size_t dp_size = ((uint8_t *) end_node - (uint8_t *) dp) + END_DEVICE_PATH_LENGTH;
+
+        /* Make a copy that can also hold a file media device path. */
+        *ret_dp = xmalloc(dp_size + file_size + SIZE_OF_FILEPATH_DEVICE_PATH);
+        memcpy(*ret_dp, dp, dp_size);
+
+        /* Point dp to the end node of the copied device path. */
+        dp = (EFI_DEVICE_PATH *) ((uint8_t *) *ret_dp + dp_size - END_DEVICE_PATH_LENGTH);
+
+        /* Replace end node with file media device path. */
+        FILEPATH_DEVICE_PATH *file_dp = (FILEPATH_DEVICE_PATH *) dp;
+        file_dp->Header.Type = MEDIA_DEVICE_PATH;
+        file_dp->Header.SubType = MEDIA_FILEPATH_DP;
+        memcpy(&file_dp->PathName, file, file_size);
+        SetDevicePathNodeLength(&file_dp->Header, SIZE_OF_FILEPATH_DEVICE_PATH + file_size);
+
+        dp = NextDevicePathNode(dp);
+        SetDevicePathEndNode(dp);
+        return EFI_SUCCESS;
+}
index 06c298d776df354fa0af65c3da9b58bf92d579ea..e191fe58664ebd7a695bd57640f8ace958aa1e2f 100644 (file)
@@ -30,19 +30,50 @@ assert_cc(sizeof(int) == sizeof(UINT32));
 #  error "Unexpected pointer size"
 #endif
 
-#define xnew_alloc(type, n, alloc)                                           \
-        ({                                                                   \
-                UINTN _alloc_size;                                           \
-                assert_se(!__builtin_mul_overflow(sizeof(type), (n), &_alloc_size)); \
-                (type *) alloc(_alloc_size);                                 \
-        })
+static inline void free(void *p) {
+        if (!p)
+                return;
+
+        /* Debugging an invalid free requires trace logging to find the call site or a debugger attached. For
+         * release builds it is not worth the bother to even warn when we cannot even print a call stack. */
+#ifdef EFI_DEBUG
+        assert_se(BS->FreePool(p) == EFI_SUCCESS);
+#else
+        (void) BS->FreePool(p);
+#endif
+}
+
+static inline void freep(void *p) {
+        free(*(void **) p);
+}
+
+#define _cleanup_freepool_ _cleanup_free_
+#define _cleanup_free_ _cleanup_(freep)
+
+_malloc_ _alloc_(1) _returns_nonnull_ _warn_unused_result_
+static inline void *xmalloc(size_t size) {
+        void *p;
+        assert_se(BS->AllocatePool(EfiBootServicesData, size, &p) == EFI_SUCCESS);
+        return p;
+}
+
+_malloc_ _alloc_(1, 2) _returns_nonnull_ _warn_unused_result_
+static inline void *xmalloc_multiply(size_t size, size_t n) {
+        assert_se(!__builtin_mul_overflow(size, n, &size));
+        return xmalloc(size);
+}
+
+/* Use malloc attribute as this never returns p like userspace realloc. */
+_malloc_ _alloc_(3) _returns_nonnull_ _warn_unused_result_
+static inline void *xrealloc(void *p, size_t old_size, size_t new_size) {
+        void *r = xmalloc(new_size);
+        memcpy(r, p, MIN(old_size, new_size));
+        free(p);
+        return r;
+}
 
-#define xallocate_pool(size) ASSERT_SE_PTR(AllocatePool(size))
-#define xallocate_zero_pool(size) ASSERT_SE_PTR(AllocateZeroPool(size))
-#define xreallocate_pool(p, old_size, new_size) ASSERT_SE_PTR(ReallocatePool((p), (old_size), (new_size)))
 #define xpool_print(fmt, ...) ((CHAR16 *) ASSERT_SE_PTR(PoolPrint((fmt), ##__VA_ARGS__)))
-#define xnew(type, n) xnew_alloc(type, (n), xallocate_pool)
-#define xnew0(type, n) xnew_alloc(type, (n), xallocate_zero_pool)
+#define xnew(type, n) ((type *) xmalloc_multiply(sizeof(type), (n)))
 
 EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b);
 
@@ -65,17 +96,6 @@ CHAR16 *xstra_to_str(const CHAR8 *stra);
 
 EFI_STATUS file_read(EFI_FILE *dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
 
-static inline void free_poolp(void *p) {
-        void *q = *(void**) p;
-
-        if (!q)
-                return;
-
-        (void) BS->FreePool(q);
-}
-
-#define _cleanup_freepool_ _cleanup_(free_poolp)
-
 static inline void file_closep(EFI_FILE **handle) {
         if (!*handle)
                 return;
@@ -165,3 +185,6 @@ void beep(UINTN beep_count);
 #else
 static inline void beep(UINTN beep_count) {}
 #endif
+
+EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file);
+EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp);
index bc82768715f6de4c1240546814aa2bd75c3b3ea5..6e60e4b45df33b60f55d15032b3fe65a68c46d87 100644 (file)
@@ -17,7 +17,7 @@ static EFI_DEVICE_PATH *path_chop(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node)
         assert(node);
 
         UINTN len = (UINT8 *) node - (UINT8 *) path;
-        EFI_DEVICE_PATH *chopped = xallocate_pool(len + END_DEVICE_PATH_LENGTH);
+        EFI_DEVICE_PATH *chopped = xmalloc(len + END_DEVICE_PATH_LENGTH);
 
         memcpy(chopped, path, len);
         SetDevicePathEndNode((EFI_DEVICE_PATH *) ((UINT8 *) chopped + len));
@@ -25,6 +25,22 @@ static EFI_DEVICE_PATH *path_chop(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node)
         return chopped;
 }
 
+static EFI_DEVICE_PATH *path_dup(const EFI_DEVICE_PATH *dp) {
+        assert(dp);
+
+        const EFI_DEVICE_PATH *node = dp;
+        size_t size = 0;
+        while (!IsDevicePathEnd(node)) {
+                size += DevicePathNodeLength(node);
+                node = NextDevicePathNode(node);
+        }
+        size += DevicePathNodeLength(node);
+
+        EFI_DEVICE_PATH *dup = xmalloc(size);
+        memcpy(dup, dp, size);
+        return dup;
+}
+
 static BOOLEAN verify_gpt(union GptHeaderBuffer *gpt_header_buffer, EFI_LBA lba_expected) {
         EFI_PARTITION_TABLE_HEADER *h;
         UINT32 crc32, crc32_saved;
@@ -101,7 +117,7 @@ static EFI_STATUS try_gpt(
 
         /* Now load the GPT entry table */
         size = ALIGN_TO((UINTN) gpt.gpt_header.SizeOfPartitionEntry * (UINTN) gpt.gpt_header.NumberOfPartitionEntries, 512);
-        entries = xallocate_pool(size);
+        entries = xmalloc(size);
 
         err = block_io->ReadBlocks(
                         block_io,
@@ -154,9 +170,10 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p
         assert(device);
         assert(ret_device_path);
 
-        EFI_DEVICE_PATH *partition_path = DevicePathFromHandle(device);
-        if (!partition_path)
-                return EFI_NOT_FOUND;
+        EFI_DEVICE_PATH *partition_path;
+        err = BS->HandleProtocol(device, &DevicePathProtocol, (void **) &partition_path);
+        if (err != EFI_SUCCESS)
+                return err;
 
         /* Find the (last) partition node itself. */
         EFI_DEVICE_PATH *part_node = NULL;
@@ -226,7 +243,7 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p
                 }
 
                 /* Patch in the data we found */
-                EFI_DEVICE_PATH *xboot_path = ASSERT_SE_PTR(DuplicateDevicePath(partition_path));
+                EFI_DEVICE_PATH *xboot_path = path_dup(partition_path);
                 memcpy((UINT8 *) xboot_path + ((UINT8 *) part_node - (UINT8 *) partition_path), &hd, sizeof(hd));
                 *ret_device_path = xboot_path;
                 return EFI_SUCCESS;
@@ -247,17 +264,17 @@ EFI_STATUS xbootldr_open(EFI_HANDLE *device, EFI_HANDLE *ret_device, EFI_FILE **
         assert(ret_root_dir);
 
         err = find_device(device, &partition_path);
-        if (EFI_ERROR(err))
+        if (err != EFI_SUCCESS)
                 return err;
 
         EFI_DEVICE_PATH *dp = partition_path;
         err = BS->LocateDevicePath(&BlockIoProtocol, &dp, &new_device);
-        if (EFI_ERROR(err))
+        if (err != EFI_SUCCESS)
                 return err;
 
-        root_dir = LibOpenRoot(new_device);
-        if (!root_dir)
-                return EFI_NOT_FOUND;
+        err = open_volume(new_device, &root_dir);
+        if (err != EFI_SUCCESS)
+                return err;
 
         *ret_device = new_device;
         *ret_root_dir = root_dir;
index c88e45771695d7e04699596f3e7df1214ce415f0..c2f9b5ac4286a8f79486e91b53e16f10354e62af 100644 (file)
@@ -4,7 +4,7 @@ if conf.get('BPF_FRAMEWORK') != 1
         subdir_done()
 endif
 
-clang_flags = [
+bpf_clang_flags = [
         '-Wno-compare-distinct-pointer-types',
         '-O2',
         '-target',
@@ -13,6 +13,14 @@ clang_flags = [
         '-c',
 ]
 
+bpf_gcc_flags = [
+        '-O2',
+        '-mkernel=5.2',
+        '-mcpu=v3',
+        '-mco-re',
+        '-gbtf',
+]
+
 # Generate defines that are appropriate to tell the compiler what architecture
 # we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
 # This dictionary contains the exceptions where this doesn't work.
@@ -30,19 +38,32 @@ cpu_arch_defines = {
         'arm'     : ['-D__arm__', '-D__ARM_PCS_VFP'],
 }
 
-clang_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
-                                        ['-D__@0@__'.format(host_machine.cpu_family())])
+bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
+                                      ['-D__@0@__'.format(host_machine.cpu_family())])
+if bpf_compiler == 'gcc'
+        bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
+endif
 
 libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
 
-bpf_o_unstripped_cmd = [
-        clang,
-        clang_flags,
-        clang_arch_flags,
-        '-I.'
-]
+bpf_o_unstripped_cmd = []
+if bpf_compiler == 'clang'
+        bpf_o_unstripped_cmd += [
+                clang,
+                bpf_clang_flags,
+                bpf_arch_flags,
+        ]
+elif bpf_compiler == 'gcc'
+        bpf_o_unstripped_cmd += [
+                bpf_gcc,
+                bpf_gcc_flags,
+                bpf_arch_flags,
+        ]
+endif
+
+bpf_o_unstripped_cmd += ['-I.']
 
-if not meson.is_cross_build()
+if not meson.is_cross_build() and bpf_compiler == 'clang'
         target_triplet_cmd = run_command('gcc', '-dumpmachine', check: false)
         if target_triplet_cmd.returncode() == 0
                 target_triplet = target_triplet_cmd.stdout().strip()
@@ -69,7 +90,7 @@ if bpftool_strip
                 '@OUTPUT@',
                 '@INPUT@'
         ]
-else
+elif bpf_compiler == 'clang'
         bpf_o_cmd = [
                 llvm_strip,
                 '-g',
index 347a3a8d21519a15abaea3d08217af65411c4266..32cde5c8e020fc8f4e20470dcaa395a1c4f5bb5f 100644 (file)
@@ -20,7 +20,7 @@ struct {
 #define DROP 0
 #define PASS 1
 
-static inline int restrict_network_interfaces_impl(const struct __sk_buff *sk) {
+static __always_inline int restrict_network_interfaces_impl(const struct __sk_buff *sk) {
         __u32 zero = 0, ifindex;
         __u8 *lookup_result;
 
index 04d8e7c5e39d837634ba33f8f5552ad4c9679dd6..18b36e74bfa7a91502b6f6c00749364fc9c7b049 100644 (file)
@@ -328,8 +328,8 @@ static int dynamic_user_pop(DynamicUser *d, uid_t *ret_uid, int *ret_lock_fd) {
         assert(ret_uid);
         assert(ret_lock_fd);
 
-        /* Read the UID and lock fd that is stored in the storage AF_UNIX socket. This should be called with the lock
-         * on the socket taken. */
+        /* Read the UID and lock fd that is stored in the storage AF_UNIX socket. This should be called with
+         * the lock on the socket taken. */
 
         k = receive_one_fd_iov(d->storage_socket[0], &iov, 1, MSG_DONTWAIT, &lock_fd);
         if (k < 0)
@@ -531,7 +531,8 @@ int dynamic_user_current(DynamicUser *d, uid_t *ret) {
 
         assert(d);
 
-        /* Get the currently assigned UID for the user, if there's any. This simply pops the data from the storage socket, and pushes it back in right-away. */
+        /* Get the currently assigned UID for the user, if there's any. This simply pops the data from the
+         * storage socket, and pushes it back in right-away. */
 
         r = lockfp(d->storage_socket[0], &storage_socket0_lock);
         if (r < 0)
@@ -555,9 +556,9 @@ static DynamicUser* dynamic_user_unref(DynamicUser *d) {
         if (!d)
                 return NULL;
 
-        /* Note that this doesn't actually release any resources itself. If a dynamic user should be fully destroyed
-         * and its UID released, use dynamic_user_destroy() instead. NB: the dynamic user table may contain entries
-         * with no references, which is commonly the case right before a daemon reload. */
+        /* Note that this doesn't actually release any resources itself. If a dynamic user should be fully
+         * destroyed and its UID released, use dynamic_user_destroy() instead. NB: the dynamic user table may
+         * contain entries with no references, which is commonly the case right before a daemon reload. */
 
         assert(d->n_ref > 0);
         d->n_ref--;
@@ -571,8 +572,8 @@ static int dynamic_user_close(DynamicUser *d) {
         uid_t uid;
         int r;
 
-        /* Release the user ID, by releasing the lock on it, and emptying the storage socket. After this the user is
-         * unrealized again, much like it was after it the DynamicUser object was first allocated. */
+        /* Release the user ID, by releasing the lock on it, and emptying the storage socket. After this the
+         * user is unrealized again, much like it was after it the DynamicUser object was first allocated. */
 
         r = lockfp(d->storage_socket[0], &storage_socket0_lock);
         if (r < 0)
index f78c62ef250b3c2b5f097c7a60b303ef88d71e51..18370ac46a7cc926818f25c6af1823370bfcbfeb 100644 (file)
@@ -25,6 +25,7 @@
 #define _public_ __attribute__((__visibility__("default")))
 #define _pure_ __attribute__((__pure__))
 #define _retain_ __attribute__((__retain__))
+#define _returns_nonnull_ __attribute__((__returns_nonnull__))
 #define _section_(x) __attribute__((__section__(x)))
 #define _sentinel_ __attribute__((__sentinel__))
 #define _unlikely_(x) (__builtin_expect(!!(x), 0))
@@ -76,8 +77,6 @@
         #endif
         #define static_assert _Static_assert
         #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); })
-
-        #define free(a) FreePool(a)
 #endif
 
 /* This passes the argument through after (if asserts are enabled) checking that it is not null. */
index b81cd6ca8b4f88f2f6a5783e6434775b153d0f64..183d34054dc5a8073ef5c40dc3a30b5ede94f586 100644 (file)
@@ -256,7 +256,10 @@ _public_ int sd_id128_get_invocation(sd_id128_t *ret) {
                 /* We first check the environment. The environment variable is primarily relevant for user
                  * services, and sufficiently safe as long as no privilege boundary is involved. */
                 r = get_invocation_from_environment(&saved_invocation_id);
-                if (r < 0 && r != -ENXIO)
+                if (r >= 0) {
+                        *ret = saved_invocation_id;
+                        return 0;
+                } else if (r != -ENXIO)
                         return r;
 
                 /* The kernel keyring is relevant for system services (as for user services we don't store
index a907b67a70cc54aabb201a9f0f907139781582ef..e12f95d4b13e5941fdd201fadc5438a427c37be8 100644 (file)
@@ -197,14 +197,14 @@ int bus_check_peercred(sd_bus *c) {
         return 1;
 }
 
-int bus_connect_system_systemd(sd_bus **_bus) {
+int bus_connect_system_systemd(sd_bus **ret_bus) {
         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
         int r;
 
-        assert(_bus);
+        assert(ret_bus);
 
         if (geteuid() != 0)
-                return sd_bus_default_system(_bus);
+                return sd_bus_default_system(ret_bus);
 
         /* If we are root then let's talk directly to the system
          * instance, instead of going via the bus */
@@ -219,28 +219,27 @@ int bus_connect_system_systemd(sd_bus **_bus) {
 
         r = sd_bus_start(bus);
         if (r < 0)
-                return sd_bus_default_system(_bus);
+                return sd_bus_default_system(ret_bus);
 
         r = bus_check_peercred(bus);
         if (r < 0)
                 return r;
 
-        *_bus = TAKE_PTR(bus);
-
+        *ret_bus = TAKE_PTR(bus);
         return 0;
 }
 
-int bus_connect_user_systemd(sd_bus **_bus) {
+int bus_connect_user_systemd(sd_bus **ret_bus) {
         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *ee = NULL;
         const char *e;
         int r;
 
-        assert(_bus);
+        assert(ret_bus);
 
         e = secure_getenv("XDG_RUNTIME_DIR");
         if (!e)
-                return sd_bus_default_user(_bus);
+                return sd_bus_default_user(ret_bus);
 
         ee = bus_address_escape(e);
         if (!ee)
@@ -256,14 +255,13 @@ int bus_connect_user_systemd(sd_bus **_bus) {
 
         r = sd_bus_start(bus);
         if (r < 0)
-                return sd_bus_default_user(_bus);
+                return sd_bus_default_user(ret_bus);
 
         r = bus_check_peercred(bus);
         if (r < 0)
                 return r;
 
-        *_bus = TAKE_PTR(bus);
-
+        *ret_bus = TAKE_PTR(bus);
         return 0;
 }
 
@@ -323,8 +321,6 @@ int bus_connect_transport(
 }
 
 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
-        int r;
-
         assert(transport >= 0);
         assert(transport < _BUS_TRANSPORT_MAX);
         assert(bus);
@@ -336,29 +332,23 @@ int bus_connect_transport_systemd(BusTransport transport, const char *host, bool
 
         case BUS_TRANSPORT_LOCAL:
                 if (user)
-                        r = bus_connect_user_systemd(bus);
-                else {
-                        if (sd_booted() <= 0)
-                                /* Print a friendly message when the local system is actually not running systemd as PID 1. */
-                                return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
-                                                       "System has not been booted with systemd as init system (PID 1). Can't operate.");
-                        r = bus_connect_system_systemd(bus);
-                }
-                break;
+                        return bus_connect_user_systemd(bus);
+
+                if (sd_booted() <= 0)
+                        /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+                        return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
+                                               "System has not been booted with systemd as init system (PID 1). Can't operate.");
+                return bus_connect_system_systemd(bus);
 
         case BUS_TRANSPORT_REMOTE:
-                r = sd_bus_open_system_remote(bus, host);
-                break;
+                return sd_bus_open_system_remote(bus, host);
 
         case BUS_TRANSPORT_MACHINE:
-                r = sd_bus_open_system_machine(bus, host);
-                break;
+                return sd_bus_open_system_machine(bus, host);
 
         default:
                 assert_not_reached();
         }
-
-        return r;
 }
 
 /**
index 00514e359f85611be024209f57514b209e36d7a8..955cdcb57c8344a6166347324be6a24ba2b0b4e1 100644 (file)
@@ -33,8 +33,8 @@ bool bus_error_is_unknown_service(const sd_bus_error *error);
 
 int bus_check_peercred(sd_bus *c);
 
-int bus_connect_system_systemd(sd_bus **_bus);
-int bus_connect_user_systemd(sd_bus **_bus);
+int bus_connect_system_systemd(sd_bus **ret_bus);
+int bus_connect_user_systemd(sd_bus **ret_bus);
 
 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
index 2604dbd15ecd49f1dd008408d68b0a426258dae4..331aaf3f0b48f057e6217d250826f6d00989528d 100644 (file)
@@ -928,7 +928,7 @@ static int nft_set_element_op_in_addr_open(
         r = nft_set_element_op_in_addr(nfnl, table, set,
                                        add, nfproto, af, address, prefixlen);
 
-        log_debug("%s NFT family %s table %s set %s IP addresss %s",
+        log_debug("%s NFT family %s table %s set %s IP address %s",
                   add ? "Added" : "Deleted",
                   nfproto_to_string(nfproto), table, set,
                   IN_ADDR_PREFIX_TO_STRING(af, address, prefixlen));
index 796dc4079e54aaef4dfb03c7a22d475ae5ac86c3..525849ee19e77f4e6057644d75c2c3de79e0eccd 100644 (file)
@@ -133,9 +133,8 @@ static int verify_features(
         assert(path);
 
         if (!sym_fido_dev_is_fido2(d))
-                return log_full_errno(log_level,
-                                      SYNTHETIC_ERRNO(ENODEV),
-                                       "Specified device %s is not a FIDO2 device.", path);
+                return log_full_errno(log_level, SYNTHETIC_ERRNO(ENODEV),
+                                      "Specified device %s is not a FIDO2 device.", path);
 
         di = sym_fido_cbor_info_new();
         if (!di)
index 2c3cbec02c840c1253d7751491f7a3bfdd2eb8b2..eee956d496317757a9d24712cc0a9fcc446702e4 100644 (file)
@@ -331,10 +331,9 @@ static void init_watchdog(void) {
 }
 
 int main(int argc, char *argv[]) {
-        bool need_umount, need_swapoff, need_loop_detach, need_dm_detach, need_md_detach, in_container, can_initrd;
         _cleanup_free_ char *cgroup = NULL;
         char *arguments[3];
-        int cmd, r, umount_log_level = LOG_INFO;
+        int cmd, r;
         static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL};
 
         /* The log target defaults to console, but the original systemd process will pass its log target in through a
@@ -379,7 +378,7 @@ int main(int argc, char *argv[]) {
         }
 
         (void) cg_get_root_path(&cgroup);
-        in_container = detect_container() > 0;
+        bool in_container = detect_container() > 0;
 
         /* If the logging messages are going to KMSG, and if we are not running from a container, then try to
          * update the sysctl kernel.printk current value in order to see "info" messages; This current log
@@ -414,11 +413,8 @@ int main(int argc, char *argv[]) {
         log_info("Sending SIGKILL to remaining processes...");
         broadcast_signal(SIGKILL, true, false, arg_timeout);
 
-        need_umount = !in_container;
-        need_swapoff = !in_container;
-        need_loop_detach = !in_container;
-        need_dm_detach = !in_container;
-        need_md_detach = !in_container;
+        bool need_umount = !in_container, need_swapoff = !in_container, need_loop_detach = !in_container,
+             need_dm_detach = !in_container, need_md_detach = !in_container, can_initrd, last_try = false;
         can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0;
 
         /* Unmount all mountpoints, swaps, and loopback devices */
@@ -436,7 +432,7 @@ int main(int argc, char *argv[]) {
 
                 if (need_umount) {
                         log_info("Unmounting file systems.");
-                        r = umount_all(&changed, umount_log_level);
+                        r = umount_all(&changed, last_try);
                         if (r == 0) {
                                 need_umount = false;
                                 log_info("All filesystems unmounted.");
@@ -460,7 +456,7 @@ int main(int argc, char *argv[]) {
 
                 if (need_loop_detach) {
                         log_info("Detaching loop devices.");
-                        r = loopback_detach_all(&changed, umount_log_level);
+                        r = loopback_detach_all(&changed, last_try);
                         if (r == 0) {
                                 need_loop_detach = false;
                                 log_info("All loop devices detached.");
@@ -472,7 +468,7 @@ int main(int argc, char *argv[]) {
 
                 if (need_md_detach) {
                         log_info("Stopping MD devices.");
-                        r = md_detach_all(&changed, umount_log_level);
+                        r = md_detach_all(&changed, last_try);
                         if (r == 0) {
                                 need_md_detach = false;
                                 log_info("All MD devices stopped.");
@@ -484,7 +480,7 @@ int main(int argc, char *argv[]) {
 
                 if (need_dm_detach) {
                         log_info("Detaching DM devices.");
-                        r = dm_detach_all(&changed, umount_log_level);
+                        r = dm_detach_all(&changed, last_try);
                         if (r == 0) {
                                 need_dm_detach = false;
                                 log_info("All DM devices detached.");
@@ -501,13 +497,12 @@ int main(int argc, char *argv[]) {
                         break;
                 }
 
-                if (!changed && umount_log_level == LOG_INFO && !can_initrd) {
-                        /* There are things we cannot get rid of. Loop one more time
-                         * with LOG_ERR to inform the user. Note that we don't need
-                         * to do this if there is an initrd to switch to, because that
-                         * one is likely to get rid of the remaining mounts. If not,
-                         * it will log about them. */
-                        umount_log_level = LOG_ERR;
+                if (!changed && last_try && !can_initrd) {
+                        /* There are things we cannot get rid of. Loop one more time in which we will log
+                         * with higher priority to inform the user. Note that we don't need to do this if
+                         * there is an initrd to switch to, because that one is likely to get rid of the
+                         * remaining mounts. If not, it will log about them. */
+                        last_try = true;
                         continue;
                 }
 
index 820aa8e286858988b2c9c2d3a1363a54324fd397..1e691379a45aaad81e1e7acb3f91728fd79def6c 100644 (file)
 #include "blockdev-util.h"
 #include "def.h"
 #include "device-util.h"
+#include "dirent-util.h"
 #include "escape.h"
 #include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
 #include "fstab-util.h"
 #include "libmount-util.h"
 #include "mount-setup.h"
 #include "mount-util.h"
 #include "mountpoint-util.h"
+#include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "signal-util.h"
@@ -524,7 +528,59 @@ static bool nonunmountable_path(const char *path) {
                 || path_startswith(path, "/run/initramfs");
 }
 
-static int remount_with_timeout(MountPoint *m, int umount_log_level) {
+static void log_umount_blockers(const char *mnt) {
+        _cleanup_closedir_ DIR *dir = opendir("/proc");
+        if (!dir)
+                return (void) log_warning_errno(errno, "opendir(/proc) failed: %m");
+
+        _cleanup_free_ char *blockers = NULL;
+
+        FOREACH_DIRENT_ALL(de, dir, break) {
+                if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
+                        continue;
+
+                pid_t pid;
+                if (parse_pid(de->d_name, &pid) < 0)
+                        continue;
+
+                _cleanup_closedir_ DIR *pid_dir = xopendirat(dirfd(dir), de->d_name, 0);
+                if (!pid_dir)
+                        continue;
+
+                _cleanup_closedir_ DIR *fd_dir = xopendirat(dirfd(pid_dir), "fd", 0);
+                if (!fd_dir)
+                        continue;
+
+                FOREACH_DIRENT(fd_de, fd_dir, break) {
+                        _cleanup_free_ char *open_file = NULL, *comm = NULL;
+
+                        if (readlinkat_malloc(dirfd(fd_dir), fd_de->d_name, &open_file) < 0)
+                                continue;
+
+                        if (!path_startswith(open_file, mnt))
+                                continue;
+
+                        if (PATH_STARTSWITH_SET(open_file, "/dev", "/sys", "/proc"))
+                                continue;
+
+                        if (get_process_comm(pid, &comm) < 0)
+                                continue;
+
+                        if (!strextend_with_separator(&blockers, ", ", comm))
+                                return (void) log_oom();
+
+                        if (!strextend(&blockers, "(", de->d_name, ")"))
+                                return (void) log_oom();
+
+                        break;
+                }
+        }
+
+        if (blockers)
+                log_warning("Unmounting '%s' blocked by: %s", mnt, blockers);
+}
+
+static int remount_with_timeout(MountPoint *m, bool last_try) {
         pid_t pid;
         int r;
 
@@ -543,7 +599,10 @@ static int remount_with_timeout(MountPoint *m, int umount_log_level) {
                 /* Start the mount operation here in the child */
                 r = mount(NULL, m->path, NULL, m->remount_flags, m->remount_options);
                 if (r < 0)
-                        log_full_errno(umount_log_level, errno, "Failed to remount '%s' read-only: %m", m->path);
+                        log_full_errno(last_try ? LOG_ERR : LOG_INFO,
+                                       errno,
+                                       "Failed to remount '%s' read-only: %m",
+                                       m->path);
 
                 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
         }
@@ -560,7 +619,7 @@ static int remount_with_timeout(MountPoint *m, int umount_log_level) {
         return r;
 }
 
-static int umount_with_timeout(MountPoint *m, int umount_log_level) {
+static int umount_with_timeout(MountPoint *m, bool last_try) {
         pid_t pid;
         int r;
 
@@ -583,9 +642,24 @@ static int umount_with_timeout(MountPoint *m, int umount_log_level) {
                  * "busy", this may allow processes to die, thus making the
                  * filesystem less busy so the unmount might succeed (rather
                  * than return EBUSY). */
-                r = umount2(m->path, MNT_FORCE);
-                if (r < 0)
-                        log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path);
+                r = RET_NERRNO(umount2(m->path, MNT_FORCE));
+                if (r < 0) {
+                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Failed to unmount %s: %m", m->path);
+
+                        if (r == -EBUSY && last_try)
+                                log_umount_blockers(m->path);
+
+                        /* If API filesystems under /oldroot cannot be unmounted we can still lazily unmount
+                         * them to unblock /oldroot. They serve no function to us anymore and should be
+                         * memory-only and hence safe to unmount like this. */
+                        if (in_initrd() &&
+                            PATH_STARTSWITH_SET(m->path, "/oldroot/dev", "/oldroot/proc", "/oldroot/sys")) {
+                                log_info("Lazily unmounting '%s' instead.", m->path);
+                                r = umount2(m->path, MNT_FORCE | MNT_DETACH);
+                                if (r < 0)
+                                        log_error_errno(errno, "Failed to lazily unmount %s: %m", m->path);
+                        }
+                }
 
                 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
         }
@@ -604,7 +678,7 @@ static int umount_with_timeout(MountPoint *m, int umount_log_level) {
 
 /* This includes remounting readonly, which changes the kernel mount options.  Therefore the list passed to
  * this function is invalidated, and should not be reused. */
-static int mount_points_list_umount(MountPoint **head, bool *changed, int umount_log_level) {
+static int mount_points_list_umount(MountPoint **head, bool *changed, bool last_try) {
         int n_failed = 0;
 
         assert(head);
@@ -624,7 +698,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, int umount
                          *
                          * Since the remount can hang in the instance of remote filesystems, we remount
                          * asynchronously and skip the subsequent umount if it fails. */
-                        if (remount_with_timeout(m, umount_log_level) < 0) {
+                        if (remount_with_timeout(m, last_try) < 0) {
                                 /* Remount failed, but try unmounting anyway,
                                  * unless this is a mount point we want to skip. */
                                 if (nonunmountable_path(m->path)) {
@@ -640,7 +714,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, int umount
                         continue;
 
                 /* Trying to umount */
-                if (umount_with_timeout(m, umount_log_level) < 0)
+                if (umount_with_timeout(m, last_try) < 0)
                         n_failed++;
                 else
                         *changed = true;
@@ -670,7 +744,7 @@ static int swap_points_list_off(MountPoint **head, bool *changed) {
         return n_failed;
 }
 
-static int loopback_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
+static int loopback_points_list_detach(MountPoint **head, bool *changed, bool last_try) {
         int n_failed = 0, r;
         dev_t rootdev = 0;
 
@@ -688,7 +762,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed, int umo
                 log_info("Detaching loopback %s.", m->path);
                 r = delete_loopback(m->path);
                 if (r < 0) {
-                        log_full_errno(umount_log_level, r, "Could not detach loopback %s: %m", m->path);
+                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Could not detach loopback %s: %m", m->path);
                         n_failed++;
                         continue;
                 }
@@ -701,7 +775,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed, int umo
         return n_failed;
 }
 
-static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
+static int dm_points_list_detach(MountPoint **head, bool *changed, bool last_try) {
         int n_failed = 0, r;
         dev_t rootdev = 0;
 
@@ -719,7 +793,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_lo
                 log_info("Detaching DM %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum));
                 r = delete_dm(m);
                 if (r < 0) {
-                        log_full_errno(umount_log_level, r, "Could not detach DM %s: %m", m->path);
+                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Could not detach DM %s: %m", m->path);
                         n_failed++;
                         continue;
                 }
@@ -731,7 +805,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_lo
         return n_failed;
 }
 
-static int md_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
+static int md_points_list_detach(MountPoint **head, bool *changed, bool last_try) {
         int n_failed = 0, r;
         dev_t rootdev = 0;
 
@@ -749,7 +823,7 @@ static int md_points_list_detach(MountPoint **head, bool *changed, int umount_lo
                 log_info("Stopping MD %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum));
                 r = delete_md(m);
                 if (r < 0) {
-                        log_full_errno(umount_log_level, r, "Could not stop MD %s: %m", m->path);
+                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Could not stop MD %s: %m", m->path);
                         n_failed++;
                         continue;
                 }
@@ -761,7 +835,7 @@ static int md_points_list_detach(MountPoint **head, bool *changed, int umount_lo
         return n_failed;
 }
 
-static int umount_all_once(bool *changed, int umount_log_level) {
+static int umount_all_once(bool *changed, bool last_try) {
         _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
         int r;
 
@@ -772,10 +846,10 @@ static int umount_all_once(bool *changed, int umount_log_level) {
         if (r < 0)
                 return r;
 
-        return mount_points_list_umount(&mp_list_head, changed, umount_log_level);
+        return mount_points_list_umount(&mp_list_head, changed, last_try);
 }
 
-int umount_all(bool *changed, int umount_log_level) {
+int umount_all(bool *changed, bool last_try) {
         bool umount_changed;
         int r;
 
@@ -787,7 +861,7 @@ int umount_all(bool *changed, int umount_log_level) {
         do {
                 umount_changed = false;
 
-                r = umount_all_once(&umount_changed, umount_log_level);
+                r = umount_all_once(&umount_changed, last_try);
                 if (umount_changed)
                         *changed = true;
         } while (umount_changed);
@@ -810,7 +884,7 @@ int swapoff_all(bool *changed) {
         return swap_points_list_off(&swap_list_head, changed);
 }
 
-int loopback_detach_all(bool *changed, int umount_log_level) {
+int loopback_detach_all(bool *changed, bool last_try) {
         _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, loopback_list_head);
         int r;
 
@@ -822,10 +896,10 @@ int loopback_detach_all(bool *changed, int umount_log_level) {
         if (r < 0)
                 return r;
 
-        return loopback_points_list_detach(&loopback_list_head, changed, umount_log_level);
+        return loopback_points_list_detach(&loopback_list_head, changed, last_try);
 }
 
-int dm_detach_all(bool *changed, int umount_log_level) {
+int dm_detach_all(bool *changed, bool last_try) {
         _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, dm_list_head);
         int r;
 
@@ -837,10 +911,10 @@ int dm_detach_all(bool *changed, int umount_log_level) {
         if (r < 0)
                 return r;
 
-        return dm_points_list_detach(&dm_list_head, changed, umount_log_level);
+        return dm_points_list_detach(&dm_list_head, changed, last_try);
 }
 
-int md_detach_all(bool *changed, int umount_log_level) {
+int md_detach_all(bool *changed, bool last_try) {
         _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, md_list_head);
         int r;
 
@@ -852,5 +926,5 @@ int md_detach_all(bool *changed, int umount_log_level) {
         if (r < 0)
                 return r;
 
-        return md_points_list_detach(&md_list_head, changed, umount_log_level);
+        return md_points_list_detach(&md_list_head, changed, last_try);
 }
index fac1a12406a79591fc603bb3e9a8d7ff63ca8ec2..618b754011445f4caa4dd49db5f8c5272b1b1c57 100644 (file)
@@ -7,15 +7,11 @@
 
 #include "list.h"
 
-int umount_all(bool *changed, int umount_log_level);
-
+int umount_all(bool *changed, bool last_try);
 int swapoff_all(bool *changed);
-
-int loopback_detach_all(bool *changed, int umount_log_level);
-
-int dm_detach_all(bool *changed, int umount_log_level);
-
-int md_detach_all(bool *changed, int umount_log_level);
+int loopback_detach_all(bool *changed, bool last_try);
+int dm_detach_all(bool *changed, bool last_try);
+int md_detach_all(bool *changed, bool last_try);
 
 /* This is exported just for testing */
 typedef struct MountPoint {
index 6a71bce5fb267a85d5ad541f1e592080fe8743ee..13a039cdfb6ee206f8cdb94e703ece709aad2ac1 100644 (file)
@@ -291,8 +291,6 @@ int check_triggering_units(sd_bus *bus, const char *unit) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *n = NULL, *dbus_path = NULL, *load_state = NULL;
         _cleanup_strv_free_ char **triggered_by = NULL;
-        bool print_warning_label = true;
-        UnitActiveState active_state;
         int r;
 
         r = unit_name_mangle(unit, 0, &n);
@@ -321,7 +319,10 @@ int check_triggering_units(sd_bus *bus, const char *unit) {
         if (r < 0)
                 return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
 
+        bool first = true;
         STRV_FOREACH(i, triggered_by) {
+                UnitActiveState active_state;
+
                 r = get_state_one_unit(bus, *i, &active_state);
                 if (r < 0)
                         return r;
@@ -329,9 +330,9 @@ int check_triggering_units(sd_bus *bus, const char *unit) {
                 if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
                         continue;
 
-                if (print_warning_label) {
+                if (first) {
                         log_warning("Warning: Stopping %s, but it can still be activated by:", n);
-                        print_warning_label = false;
+                        first = false;
                 }
 
                 log_warning("  %s", *i);
index a6e0c8501e86ba4e92500cfd4930ef74d690fa11..3a26ecaa70efd4ee396a7c052a5e1f57f6ed1a7c 100644 (file)
@@ -61,15 +61,15 @@ static void test_dns_name_to_wire_format_one(const char *what, const char *expec
         uint8_t buffer[buffer_sz];
         int r;
 
-        log_info("%s, %s, %zu, →%d", what, expect, buffer_sz, ret);
+        log_info("%s, %s, %zu, →%d", what, strnull(expect), buffer_sz, ret);
 
         r = dns_name_to_wire_format(what, buffer, buffer_sz, false);
         assert_se(r == ret);
 
-        if (r < 0)
-                return;
-
-        assert_se(!memcmp(buffer, expect, r));
+        if (r >= 0) {
+                assert(expect);  /* for gcc */
+                assert_se(memcmp(buffer, expect, r) == 0);
+        }
 }
 
 TEST(dns_name_to_wire_format) {
@@ -165,7 +165,7 @@ static void test_dns_label_escape_one(const char *what, size_t l, const char *ex
         _cleanup_free_ char *t = NULL;
         int r;
 
-        log_info("%s, %zu, %s, →%d", what, l, expect, ret);
+        log_info("%s, %zu, %s, →%d", what, l, strnull(expect), ret);
 
         r = dns_label_escape_new(what, l, &t);
         assert_se(r == ret);
@@ -483,7 +483,7 @@ TEST(dnssd_srv_type_is_valid) {
 static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) {
         _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
 
-        log_info("%s, %s, %s, →%d, %s", a, b, c, r, d);
+        log_info("%s, %s, %s, →%d, %s", strnull(a), strnull(b), strnull(c), r, strnull(d));
 
         assert_se(dns_service_join(a, b, c, &t) == r);
         assert_se(streq_ptr(t, d));
@@ -515,7 +515,7 @@ TEST(dns_service_join) {
 static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) {
         _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL;
 
-        log_info("%s, %s, %s, %s, →%d", joined, a, b, c, r);
+        log_info("%s, %s, %s, %s, →%d", joined, strnull(a), strnull(b), strnull(c), r);
 
         assert_se(dns_service_split(joined, &x, &y, &z) == r);
         assert_se(streq_ptr(x, a));
@@ -545,7 +545,7 @@ TEST(dns_service_split) {
 static void test_dns_name_change_suffix_one(const char *name, const char *old_suffix, const char *new_suffix, int r, const char *result) {
         _cleanup_free_ char *s = NULL;
 
-        log_info("%s, %s, %s, →%s", name, old_suffix, new_suffix, result);
+        log_info("%s, %s, %s, →%s", name, old_suffix, new_suffix, strnull(result));
 
         assert_se(dns_name_change_suffix(name, old_suffix, new_suffix, &s) == r);
         assert_se(streq_ptr(s, result));
@@ -566,7 +566,7 @@ TEST(dns_name_change_suffix) {
 static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) {
         const char *p = NULL;
 
-        log_info("%s, %d, →%s, %d", name, n_labels, result, ret);
+        log_info("%s, %d, →%s, %d", name, n_labels, strnull(result), ret);
 
         assert_se(ret == dns_name_suffix(name, n_labels, &p));
         assert_se(streq_ptr(p, result));
index 2ce4e18643777d993494154d2777decccd253639..89365b0bc5abe5cf854c302c7468ef5ca4c24987 100644 (file)
@@ -37,7 +37,7 @@ static void do_fstab_filter_options(const char *opts,
         r = fstab_filter_options(opts, remove, &name, &value, NULL, &filtered);
         log_info("1: \"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"",
                  opts, r, strnull(name), value, filtered,
-                 r_expected, name_expected, value_expected, filtered_expected ?: opts);
+                 r_expected, strnull(name_expected), strnull(value_expected), filtered_expected ?: opts);
         assert_se(r == r_expected);
         assert_se(streq_ptr(name, name_expected));
         assert_se(streq_ptr(value, value_expected));
@@ -49,7 +49,7 @@ static void do_fstab_filter_options(const char *opts,
         assert_se(joined = strv_join(values, ":"));
         log_info("2: \"%s\" → %d, \"%s\", \"%s\", expected %d, \"%s\", \"%s\"",
                  opts, r, strnull(name), joined,
-                 r_values_expected, name_expected, values_expected);
+                 r_values_expected, strnull(name_expected), strnull(values_expected));
         assert_se(r == r_values_expected);
         assert_se(streq_ptr(name, r_values_expected > 0 ? name_expected : NULL));
         assert_se(streq_ptr(joined, values_expected));
@@ -58,7 +58,7 @@ static void do_fstab_filter_options(const char *opts,
         r = fstab_filter_options(opts, remove, &name, NULL, NULL, NULL);
         log_info("3: \"%s\" → %d, \"%s\", expected %d, \"%s\"\n-",
                  opts, r, strnull(name),
-                 r_expected, name_expected);
+                 r_expected, strnull(name_expected));
         assert_se(r == r_expected);
         assert_se(streq_ptr(name, name_expected));
 }
index 7a8adad50c8a0a4165fa6b1aa4ffd48a85c71439..990eb1e2b674be23be4ee74a9a2a6422dd441f2f 100644 (file)
@@ -528,7 +528,7 @@ static void test_rename_process_now(const char *p, int ret) {
         _cleanup_free_ char *comm = NULL, *cmdline = NULL;
         int r;
 
-        log_info("/* %s */", __func__);
+        log_info("/* %s(%s) */", __func__, p);
 
         r = rename_process(p);
         assert_se(r == ret ||
@@ -574,7 +574,7 @@ static void test_rename_process_one(const char *p, int ret) {
         siginfo_t si;
         pid_t pid;
 
-        log_info("/* %s */", __func__);
+        log_info("/* %s(%s) */", __func__, p);
 
         pid = fork();
         assert_se(pid >= 0);
@@ -590,6 +590,11 @@ static void test_rename_process_one(const char *p, int ret) {
         assert_se(si.si_status == EXIT_SUCCESS);
 }
 
+TEST(rename_process_invalid) {
+        assert_se(rename_process(NULL) == -EINVAL);
+        assert_se(rename_process("") == -EINVAL);
+}
+
 TEST(rename_process_multi) {
         pid_t pid;
 
@@ -612,14 +617,10 @@ TEST(rename_process_multi) {
         (void) setresuid(99, 99, 99); /* change uid when running privileged */
         test_rename_process_now("time!", 0);
         test_rename_process_now("0", 1); /* shorter than "one", should fit */
-        test_rename_process_one("", -EINVAL);
-        test_rename_process_one(NULL, -EINVAL);
         _exit(EXIT_SUCCESS);
 }
 
 TEST(rename_process) {
-        test_rename_process_one(NULL, -EINVAL);
-        test_rename_process_one("", -EINVAL);
         test_rename_process_one("foo", 1); /* should always fit */
         test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
         test_rename_process_one("1234567", 1); /* should always fit */
index 45fe8f7c59999986a4fb480eadcb36687363a895..db7c2175210942e2f3c956b52ef0d20e1666950d 100644 (file)
@@ -934,8 +934,15 @@ TEST(lock_personality) {
         }
 
         assert_se(opinionated_personality(&current) >= 0);
+        /* On ppc64le sanitizers disable ASLR (i.e. by setting ADDR_NO_RANDOMIZE),
+         * which opinionated_personality() doesn't return. Let's tweak the current
+         * personality ourselves in such cases.
+         * See: https://github.com/llvm/llvm-project/commit/78f7a6eaa601bfdd6ae70ffd3da2254c21ff77f9
+         */
+        if (FLAGS_SET(safe_personality(PERSONALITY_INVALID), ADDR_NO_RANDOMIZE))
+                current |= ADDR_NO_RANDOMIZE;
 
-        log_info("current personality=%lu", current);
+        log_info("current personality=0x%lX", current);
 
         pid = fork();
         assert_se(pid >= 0);
@@ -945,13 +952,14 @@ TEST(lock_personality) {
 
                 assert_se((unsigned long) safe_personality(current) == current);
 
-                /* Note, we also test that safe_personality() works correctly, by checkig whether errno is properly
+                /* Note, we also test that safe_personality() works correctly, by checking whether errno is properly
                  * set, in addition to the return value */
                 errno = 0;
-                assert_se(safe_personality(PER_LINUX | ADDR_NO_RANDOMIZE) == -EPERM);
+                assert_se(safe_personality(PER_LINUX | MMAP_PAGE_ZERO) == -EPERM);
                 assert_se(errno == EPERM);
 
-                assert_se(safe_personality(PER_LINUX | MMAP_PAGE_ZERO) == -EPERM);
+                if (!FLAGS_SET(current, ADDR_NO_RANDOMIZE))
+                        assert_se(safe_personality(PER_LINUX | ADDR_NO_RANDOMIZE) == -EPERM);
                 assert_se(safe_personality(PER_LINUX | ADDR_COMPAT_LAYOUT) == -EPERM);
                 assert_se(safe_personality(PER_LINUX | READ_IMPLIES_EXEC) == -EPERM);
                 assert_se(safe_personality(PER_LINUX_32BIT) == -EPERM);
index d41399718958891864fa4c911b5563ac58cde9fe..35b20dc172d12ecfbdf1ddf524f64ce21be0fd28 100644 (file)
@@ -13,7 +13,7 @@ static void test_udev_rule_parse_value_one(const char *in, const char *expected_
         char *value = UINT_TO_PTR(0x12345678U);
         char *endpos = UINT_TO_PTR(0x87654321U);
 
-        log_info("/* %s (%s, %s, %d) */", __func__, in, expected_value, expected_retval);
+        log_info("/* %s (%s, %s, %d) */", __func__, in, strnull(expected_value), expected_retval);
 
         assert_se(str = strdup(in));
         assert_se(udev_rule_parse_value(str, &value, &endpos) == expected_retval);
@@ -36,9 +36,9 @@ TEST(udev_rule_parse_value) {
         /* input: "va'l\'id\"op\"erand"
          * parsed: va'l\'id"op"erand */
         test_udev_rule_parse_value_one("\"va'l\\'id\\\"op\\\"erand\"", "va'l\\'id\"op\"erand", 0);
-        test_udev_rule_parse_value_one("no quotes", 0, -EINVAL);
+        test_udev_rule_parse_value_one("no quotes", NULL, -EINVAL);
         test_udev_rule_parse_value_one("\"\\\\a\\b\\x\\y\"", "\\\\a\\b\\x\\y", 0);
-        test_udev_rule_parse_value_one("\"reject\0nul\"", 0, -EINVAL);
+        test_udev_rule_parse_value_one("\"reject\0nul\"", NULL, -EINVAL);
         /* input: e"" */
         test_udev_rule_parse_value_one("e\"\"", "", 0);
         /* input: e"1234" */
@@ -46,13 +46,13 @@ TEST(udev_rule_parse_value) {
         /* input: e"\"" */
         test_udev_rule_parse_value_one("e\"\\\"\"", "\"", 0);
         /* input: e"\ */
-        test_udev_rule_parse_value_one("e\"\\", 0, -EINVAL);
+        test_udev_rule_parse_value_one("e\"\\", NULL, -EINVAL);
         /* input: e"\" */
-        test_udev_rule_parse_value_one("e\"\\\"", 0, -EINVAL);
+        test_udev_rule_parse_value_one("e\"\\\"", NULL, -EINVAL);
         /* input: e"\\" */
         test_udev_rule_parse_value_one("e\"\\\\\"", "\\", 0);
         /* input: e"\\\" */
-        test_udev_rule_parse_value_one("e\"\\\\\\\"", 0, -EINVAL);
+        test_udev_rule_parse_value_one("e\"\\\\\\\"", NULL, -EINVAL);
         /* input: e"\\\"" */
         test_udev_rule_parse_value_one("e\"\\\\\\\"\"", "\\\"", 0);
         /* input: e"\\\\" */
@@ -63,9 +63,9 @@ TEST(udev_rule_parse_value) {
         test_udev_rule_parse_value_one(
                 "e\"single\\rcharacter\\t\\aescape\\bsequence\"", "single\rcharacter\t\aescape\bsequence", 0);
         /* input: e"reject\invalid escape sequence" */
-        test_udev_rule_parse_value_one("e\"reject\\invalid escape sequence", 0, -EINVAL);
+        test_udev_rule_parse_value_one("e\"reject\\invalid escape sequence", NULL, -EINVAL);
         /* input: e"\ */
-        test_udev_rule_parse_value_one("e\"\\", 0, -EINVAL);
+        test_udev_rule_parse_value_one("e\"\\", NULL, -EINVAL);
         /* input: "s\u1d1c\u1d04\u029c \u1d1c\u0274\u026a\u1d04\u1d0f\u1d05\u1d07 \U0001d568\U0001d560\U0001d568" */
         test_udev_rule_parse_value_one(
                 "e\"s\\u1d1c\\u1d04\\u029c \\u1d1c\\u0274\\u026a\\u1d04\\u1d0f\\u1d05\\u1d07 \\U0001d568\\U0001d560\\U0001d568\"",
index f827f90865b6978a81ba687e0aa45855082fb7f2..6a8d3a8a11ec97cf6f7007a3631676b1e042d5d2 100755 (executable)
@@ -4,7 +4,6 @@ set -e
 
 TEST_DESCRIPTION="Job-related tests"
 TEST_NO_QEMU=1
-IMAGE_NAME="default"
 
 # shellcheck source=test/test-functions
 . "${TEST_BASE_DIR:?}/test-functions"
index 079ecfd62947cfbf8cf38a9132c6e3357dcd9862..9d91eee2041ca4afdd3295bf23221e39386dbc7e 100755 (executable)
@@ -3,7 +3,6 @@
 set -e
 
 TEST_DESCRIPTION="UDEV"
-IMAGE_NAME="default"
 TEST_NO_NSPAWN=1
 
 # shellcheck source=test/test-functions
diff --git a/test/TEST-45-TIMEDATE/Makefile b/test/TEST-45-TIMEDATE/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-45-TIMEDATE/test.sh b/test/TEST-45-TIMEDATE/test.sh
new file mode 100755 (executable)
index 0000000..27edf4a
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -e
+
+TEST_DESCRIPTION="test timedated"
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
index e273d211bc2d784068355ce0ddd6488e55f5514e..fe8043430933ab9d150f5e0c55cb975f7871d07e 100755 (executable)
@@ -9,7 +9,6 @@
 set -e
 
 TEST_DESCRIPTION="systemd-udev storage tests"
-IMAGE_NAME="default"
 TEST_NO_NSPAWN=1
 # Save only journals of failing test cases by default (to conserve space)
 TEST_SAVE_JOURNAL="${TEST_SAVE_JOURNAL:-fail}"
diff --git a/test/units/assert.sh b/test/units/assert.sh
new file mode 100644 (file)
index 0000000..db67dad
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+# utility functions for shell tests
+
+assert_true() {
+    local rc
+
+    set +e
+    "$@"
+    rc=$?
+    set -e
+    if [[ "$rc" != "0" ]]; then
+        echo "FAIL: command '$*' failed with exit code $rc" >&2
+        exit 1
+    fi
+}
+
+
+assert_eq() {
+    if [[ "$1" != "$2" ]]; then
+        echo "FAIL: expected: '$2' actual: '$1'" >&2
+        exit 1
+    fi
+}
+
+assert_in() {
+    if ! echo "$2" | grep -q "$1"; then
+        echo "FAIL: '$1' not found in:" >&2
+        echo "$2" >&2
+        exit 1
+    fi
+}
+
+assert_rc() {
+    local exp=$1
+    local rc
+    shift
+    set +e
+    "$@"
+    rc=$?
+    set -e
+    assert_eq "$rc" "$exp"
+}
diff --git a/test/units/testsuite-45.service b/test/units/testsuite-45.service
new file mode 100644 (file)
index 0000000..79c0a6f
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Unit]
+Description=TEST-45-TIMEDATE
+
+[Service]
+ExecStartPre=rm -f /failed /testok
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+StandardOutput=journal+console
+StandardError=journal+console
+Type=oneshot
diff --git a/test/units/testsuite-45.sh b/test/units/testsuite-45.sh
new file mode 100755 (executable)
index 0000000..ac7860d
--- /dev/null
@@ -0,0 +1,246 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/assert.sh
+. "$(dirname "$0")"/assert.sh
+
+test_timezone() {
+    local ORIG_TZ=
+
+    if [[ -L /etc/localtime ]]; then
+        ORIG_TZ=$(readlink /etc/localtime | sed 's#^.*zoneinfo/##')
+        echo "original tz: $ORIG_TZ"
+    fi
+
+    echo 'timedatectl works'
+    assert_in "Local time:" "$(timedatectl --no-pager)"
+
+    echo 'change timezone'
+    assert_eq "$(timedatectl --no-pager set-timezone Europe/Kiev 2>&1)" ""
+    assert_eq "$(readlink /etc/localtime | sed 's#^.*zoneinfo/##')" "Europe/Kiev"
+    assert_in "Time.*zone: Europe/Kiev (EEST, +" "$(timedatectl --no-pager)"
+
+    if [[ -n "$ORIG_TZ" ]]; then
+        echo 'reset timezone to original'
+        assert_eq "$(timedatectl --no-pager set-timezone "$ORIG_TZ" 2>&1)" ""
+        assert_eq "$(readlink /etc/localtime | sed 's#^.*zoneinfo/##')" "$ORIG_TZ"
+    fi
+}
+
+restore_adjtime() {
+    if [[ -e /etc/adjtime.bak ]]; then
+        mv /etc/adjtime.bak /etc/adjtime
+    else
+        rm /etc/adjtime
+    fi
+}
+
+check_adjtime_not_exist() {
+    if [[ -e /etc/adjtime ]]; then
+        echo "/etc/adjtime unexpectedly exists." >&2
+        exit 1
+    fi
+}
+
+test_adjtime() {
+    # test setting UTC vs. LOCAL in /etc/adjtime
+    if [[ -e /etc/adjtime ]]; then
+        mv /etc/adjtime /etc/adjtime.bak
+    fi
+
+    trap restore_adjtime EXIT
+
+    echo 'no adjtime file'
+    rm -f /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+
+    echo 'UTC set in adjtime file'
+    printf '0.0 0 0\n0\nUTC\n' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+UTC"
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    echo 'non-zero values in adjtime file'
+    printf '0.1 123 0\n0\nLOCAL\n' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    assert_eq "$(cat /etc/adjtime)" "0.1 123 0
+0
+UTC"
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.1 123 0
+0
+LOCAL"
+
+    echo 'fourth line adjtime file'
+    printf '0.0 0 0\n0\nLOCAL\nsomethingelse\n' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+UTC
+somethingelse"
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL
+somethingelse"
+
+    echo 'no final newline in adjtime file'
+    printf '0.0 0 0\n0\nUTC' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    printf '0.0 0 0\n0\nUTC' > /etc/adjtime
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    echo 'only one line in adjtime file'
+    printf '0.0 0 0\n' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    printf '0.0 0 0\n' > /etc/adjtime
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    echo 'only one line in adjtime file, no final newline'
+    printf '0.0 0 0' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    printf '0.0 0 0' > /etc/adjtime
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    echo 'only two lines in adjtime file'
+    printf '0.0 0 0\n0\n' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    printf '0.0 0 0\n0\n' > /etc/adjtime
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    echo 'only two lines in adjtime file, no final newline'
+    printf '0.0 0 0\n0' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    printf '0.0 0 0\n0' > /etc/adjtime
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    echo 'unknown value in 3rd line of adjtime file'
+    printf '0.0 0 0\n0\nFOO\n' > /etc/adjtime
+    timedatectl set-local-rtc 0
+    check_adjtime_not_exist
+    printf '0.0 0 0\n0\nFOO\n' > /etc/adjtime
+    timedatectl set-local-rtc 1
+    assert_eq "$(cat /etc/adjtime)" "0.0 0 0
+0
+LOCAL"
+
+    restore_adjtime
+    trap - EXIT
+}
+
+assert_ntp() {
+    assert_eq "$(busctl get-property org.freedesktop.timedate1 /org/freedesktop/timedate1 org.freedesktop.timedate1 NTP)" "b $1"
+}
+
+start_mon() {
+    busctl monitor --match="type='signal',sender=org.freedesktop.timedate1,member='PropertiesChanged',path=/org/freedesktop/timedate1" >"$mon" &
+    MONPID=$!
+}
+
+wait_mon() {
+    for ((i=0;i<10;i++)); do
+        if (( i != 0 )); then sleep 1; fi
+        if grep -q "$1" "$mon"; then break; fi
+    done
+    assert_in "$2" "$(cat "$mon")"
+    kill "$MONPID"
+    wait "$MONPID" 2>/dev/null || true
+}
+
+test_ntp() {
+    # timesyncd has ConditionVirtualization=!container by default; drop/mock that for testing
+    if systemd-detect-virt --container --quiet; then
+        systemctl disable --quiet --now systemd-timesyncd
+        mkdir -p /run/systemd/system/systemd-timesyncd.service.d
+        cat >/run/systemd/system/systemd-timesyncd.service.d/container.conf <<EOF
+[Unit]
+ConditionVirtualization=
+
+[Service]
+Type=simple
+AmbientCapabilities=
+ExecStart=
+ExecStart=/bin/sleep infinity
+EOF
+        systemctl daemon-reload
+    fi
+
+    mon=$(mktemp -t dbusmon.XXXXXX)
+
+    echo 'disable NTP'
+    timedatectl set-ntp false
+    for ((i=0;i<10;i++)); do
+        if (( i != 0 )); then sleep 1; fi
+        if [[ "$(systemctl --no-pager show systemd-timesyncd --property ActiveState)" == "ActiveState=inactive" ]]; then
+            break;
+        fi
+    done
+    assert_eq "$(systemctl --no-pager show systemd-timesyncd --property ActiveState)" "ActiveState=inactive"
+    assert_ntp "false"
+    assert_rc 3 systemctl is-active --quiet systemd-timesyncd
+
+    echo 'enable NTP'
+    start_mon
+    timedatectl set-ntp true
+    wait_mon "NTP" "BOOLEAN true"
+    assert_ntp "true"
+    for ((i=0;i<10;i++)); do
+        if (( i != 0 )); then sleep 1; fi
+        if [[ "$(systemctl --no-pager show systemd-timesyncd --property ActiveState)" == "ActiveState=active" ]]; then
+            break;
+        fi
+    done
+    assert_eq "$(systemctl --no-pager show systemd-timesyncd --property ActiveState)" "ActiveState=active"
+    assert_rc 0 systemctl is-active --quiet systemd-timesyncd
+
+    echo 're-disable NTP'
+    start_mon
+    timedatectl set-ntp false
+    wait_mon "NTP" "BOOLEAN false"
+    assert_ntp "false"
+    assert_rc 3 systemctl is-active --quiet systemd-timesyncd
+}
+
+: >/failed
+
+test_timezone
+test_adjtime
+test_ntp
+
+touch /testok
+rm /failed