diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml
index 3829313cf9..e319214bf0 100644
--- a/.github/workflows/claude-review.yml
+++ b/.github/workflows/claude-review.yml
@@ -285,6 +285,10 @@ jobs:
- Instructions to return ONLY a raw JSON array of findings. No markdown,
no explanation, no code fences — just the JSON array. If there are no
findings, return `[]`.
+ - Instructions that `severity` is a separate structured field — do NOT
+ repeat it inside `body` (no "must-fix:", "**suggestion**:", etc.
+ prefix). The posting step adds the severity label itself, so
+ including it in `body` produces duplicates.
## Phase 2: Collect, deduplicate, and summarize
@@ -488,7 +492,7 @@ jobs:
...(c.side != null && { side: c.side }),
...(c.start_line != null && { start_line: c.start_line }),
...(c.start_side != null && { start_side: c.start_side }),
- body: c.body,
+ body: `Claude: **${c.severity}**: ${c.body}`,
});
posted++;
} catch (e) {
diff --git a/README b/README
index ccb6f86bfe..ddcb863f4a 100644
--- a/README
+++ b/README
@@ -264,9 +264,9 @@ REQUIREMENTS:
During runtime, you need the following additional
dependencies:
- util-linux >= v2.41 required (including but not limited to: mount,
- umount, swapon, swapoff, sulogin,
- agetty, fsck)
+ util-linux >= v2.27.1 required (including but not limited to: mount,
+ umount, swapon, swapoff, sulogin,
+ agetty, fsck)
dbus >= 1.4.0 (strictly speaking optional, but recommended)
NOTE: If using dbus < 1.9.18, you should override the default
policy directory (--with-dbuspolicydir=/etc/dbus-1/system.d).
diff --git a/coccinelle/memcmp.cocci b/coccinelle/memcmp.cocci
new file mode 100644
index 0000000000..aa0effa4f8
--- /dev/null
+++ b/coccinelle/memcmp.cocci
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* Disable this transformation for iovec-util.h and the unit test */
+@ depends on !(file in "src/basic/iovec-util.h")
+ && !(file in "src/test/test-iovec-util.c") @
+expression a, b;
+@@
+(
+- iovec_memcmp(a, b) == 0
++ iovec_equal(a, b)
+|
+- iovec_memcmp(a, b) != 0
++ !iovec_equal(a, b)
+|
+- ASSERT_EQ(iovec_memcmp(a, b), 0)
++ ASSERT_TRUE(iovec_equal(a, b))
+|
+- ASSERT_NE(iovec_memcmp(a, b), 0)
++ ASSERT_FALSE(iovec_equal(a, b))
+)
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
index 5390754661..53f4a1a60c 100644
--- a/docs/ENVIRONMENT.md
+++ b/docs/ENVIRONMENT.md
@@ -679,6 +679,11 @@ SYSTEMD_HOME_DEBUG_SUFFIX=foo \
string format. Overrides the default maximum allowed size for a file-descriptor
based input record to be stored in the journal.
+* `$SYSTEMD_JOURNAL_REMOTE_CONFIG_FILE` – path to a configuration file for
+ `systemd-journal-remote`. When set, the specified file is used instead of the
+ default configuration file and drop-in directories. If set to the empty string
+ or `/dev/null`, configuration file parsing is skipped entirely.
+
* `$SYSTEMD_CATALOG` – path to the compiled catalog database file to use for
`journalctl -x`, `journalctl --update-catalog`, `journalctl --list-catalog`
and related calls.
diff --git a/hwdb.d/40-imds.hwdb b/hwdb.d/40-imds.hwdb
index 397a32b42f..21f58aac15 100644
--- a/hwdb.d/40-imds.hwdb
+++ b/hwdb.d/40-imds.hwdb
@@ -103,3 +103,29 @@ dmi:*:svnScaleway:*
IMDS_ADDRESS_IPV4=169.254.42.42
IMDS_ADDRESS_IPV6=fd00:42::42
IMDS_KEY_USERDATA=/user_data
+
+# https://www.tencentcloud.com/document/product/213/4934?lang=en
+dmi:*:svnTencentCloud:*
+ IMDS_VENDOR=tencent-cloud
+ IMDS_DATA_URL=http://metadata.tencentyun.com
+ IMDS_KEY_HOSTNAME=/meta-data/hostname
+ IMDS_KEY_REGION=/meta-data/placement/region
+ IMDS_KEY_ZONE=/meta-data/placement/zone
+ IMDS_KEY_IPV4_PUBLIC=/meta-data/public-ipv4
+ IMDS_KEY_SSH_KEY=/meta-data/public-keys/0/openssh-key
+ IMDS_KEY_USERDATA=/user-data
+
+# https://help.aliyun.com/zh/ecs/user-guide/view-instance-metadata
+dmi:*:svnAlibabaCloud:*
+ IMDS_VENDOR=alibaba-ecs
+ IMDS_TOKEN_URL=http://100.100.100.200/latest/api/token
+ IMDS_REFRESH_HEADER_NAME=X-aliyun-ecs-metadata-token-ttl-seconds
+ IMDS_DATA_URL=http://100.100.100.200/latest
+ IMDS_TOKEN_HEADER_NAME=X-aliyun-ecs-metadata-token
+ IMDS_ADDRESS_IPV4=100.100.100.200
+ IMDS_KEY_HOSTNAME=/meta-data/hostname
+ IMDS_KEY_REGION=/meta-data/region-id
+ IMDS_KEY_ZONE=/meta-data/zone-id
+ IMDS_KEY_IPV4_PUBLIC=/meta-data/eipv4
+ IMDS_KEY_SSH_KEY=/meta-data/public-keys/0/openssh-key
+ IMDS_KEY_USERDATA=/user-data
diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb
index a8e990de97..76f727573d 100644
--- a/hwdb.d/60-sensor.hwdb
+++ b/hwdb.d/60-sensor.hwdb
@@ -515,10 +515,6 @@ sensor:modalias:acpi:KIOX000A:*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd03/20/20
sensor:modalias:acpi:KIOX000A:*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/25/2017:*:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
ACCEL_LOCATION=base
-sensor:modalias:acpi:MXC6655:*:dmi:*:svnGPD:pnG1621-02:* # Pocket 3
-sensor:modalias:acpi:MXC6655:*:dmi:*:svnGPD:pnG1628-04:* # Pocket 4
- ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
-
sensor:modalias:acpi:BMI0160:*:dmi:*:svnGPD:pnG1619-04:* # Win Max 2
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
diff --git a/man/bootctl.xml b/man/bootctl.xml
index 5f53023c83..558891eaa1 100644
--- a/man/bootctl.xml
+++ b/man/bootctl.xml
@@ -406,6 +406,15 @@
+
+
+
+ Print the EFI architecture string of the local firmware. This is useful to
+ generically format filenames such as bootx64.efi that
+ include the local firmware architecture in the name.
+
+
+
Controls whether to touch the firmware's boot loader list stored in EFI variables,
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 0ad3c9c772..83544b3606 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -711,8 +711,8 @@
systemd.allow_userspace_verity=
Takes a boolean argument. Controls whether disk images that are Verity protected may
- be authenticated in userspace signature checks via /etc/verity.d/ (and related
- directories) public key drop-ins, or whether in-kernel signature checking only. Defaults to
+ be authenticated in userspace signature checks via /etc/verity.d/*.crt (and
+ related directories) public key drop-ins, or whether in-kernel signature checking only. Defaults to
on.
diff --git a/man/org.freedesktop.network1.xml b/man/org.freedesktop.network1.xml
index 0b7a6b5ed3..1c3abcad23 100644
--- a/man/org.freedesktop.network1.xml
+++ b/man/org.freedesktop.network1.xml
@@ -458,6 +458,10 @@ node /org/freedesktop/network1/link/_1 {
interface org.freedesktop.network1.DHCPServer {
properties:
readonly a(uayayayayt) Leases = [...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly u PoolSize = ...;
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+ readonly u PoolOffset = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
@@ -466,8 +470,6 @@ node /org/freedesktop/network1/link/_1 {
};
-
-
@@ -480,10 +482,23 @@ node /org/freedesktop/network1/link/_1 {
+
+
+
+
- Provides information about leases.
+ Provides information about the DHCP server. The Leases property contains
+ the currently active leases. The PoolSize property contains the total number
+ of addresses in the dynamic address pool. The PoolOffset property contains
+ the offset from the subnet base address where the pool starts. These correspond to the
+ PoolSize= and PoolOffset= settings in
+ systemd.network5.
+ UINT32_MAX is used as a sentinel value for PoolSize
+ and PoolOffset to indicate that the information is unavailable (i.e. no
+ DHCP server is configured or the link is in relay mode), rather than a valid pool size or
+ offset.
@@ -589,6 +604,10 @@ $ gdbus introspect --system \
History
+
+ DHCP Server Object
+ PoolSize and PoolOffset were added in version 261.
+
DHCPv4 Client Object
State was added in version 255.
diff --git a/man/systemd-journal-remote.service.xml b/man/systemd-journal-remote.service.xml
index d6258ce2fc..7beb96403d 100644
--- a/man/systemd-journal-remote.service.xml
+++ b/man/systemd-journal-remote.service.xml
@@ -333,6 +333,19 @@
+
+
+
+
+
+
+ These options override the corresponding settings from the configuration file
+ (see journal-remote.conf5).
+ See that page for the descriptions of these options.
+
+
+
+
diff --git a/man/systemd-mountfsd.service.xml b/man/systemd-mountfsd.service.xml
index 7cc607c4c5..2e623a2728 100644
--- a/man/systemd-mountfsd.service.xml
+++ b/man/systemd-mountfsd.service.xml
@@ -45,7 +45,7 @@
/usr/lib/ it is assumed to be trusted.
If the disk image contains a Verity enabled disk image, along with a signature
- partition with a key in the kernel keyring or in /etc/verity.d/ (and related
+ partition with a key in the kernel keyring or in /etc/verity.d/*.crt (and related
directories) the disk image is considered trusted.
diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 045aa60db8..54d6f83915 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -1590,6 +1590,36 @@ After=sys-subsystem-net-devices-ens1.device
+
+
+
+ Forward the container's journal to the host by starting
+ systemd-journal-remote8
+ listening on a Unix socket that is bind-mounted into the container. The container's
+ systemd-journald8
+ connects to the socket via the journal.forward_to_socket credential and streams
+ journal entries to the host in real-time. Takes a path to a journal file or directory where the received
+ entries will be stored. If the path ends in .journal, entries are written to a single
+ file; otherwise, entries are split per host into the specified directory.
+
+
+
+
+
+
+
+
+
+
+ These options configure the corresponding settings of
+ systemd-journal-remote8
+ when forwarding journal entries from the container. See
+ journal-remote.conf5
+ for the descriptions of these settings.
+
+
+
+
diff --git a/man/systemd-vmspawn.xml b/man/systemd-vmspawn.xml
index 5749136a5d..5c5ec4ccbc 100644
--- a/man/systemd-vmspawn.xml
+++ b/man/systemd-vmspawn.xml
@@ -668,6 +668,21 @@
+
+
+
+
+
+
+ These options configure the corresponding settings of
+ systemd-journal-remote8
+ when forwarding journal entries from the VM. See
+ journal-remote.conf5
+ for the descriptions of these settings.
+
+
+
+
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 4c777ef4e0..554d8da8ef 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1086,6 +1086,19 @@ DuplicateAddressDetection=none
+
+ IPv4SrcValidMark=
+
+ Takes a boolean. When enabled, the packet's firewall mark (fwmark) is included in the
+ reverse path filter route lookup for source address validation on this interface. This is
+ particularly useful for policy routing setups where packets may arrive with source addresses
+ that are only valid in routing tables selected by their fwmark. When unset, the kernel's
+ default will be used.
+
+
+
+
+
IPv4ProxyARP=
diff --git a/meson.build b/meson.build
index 0875390379..a902bc96aa 100644
--- a/meson.build
+++ b/meson.build
@@ -1067,86 +1067,6 @@ libbpf = dependency('libbpf',
libbpf_cflags = libbpf.partial_dependency(includes: true, compile_args: true)
conf.set10('HAVE_LIBBPF', libbpf.found())
-if not libbpf.found()
- conf.set10('BPF_FRAMEWORK', false)
-else
- clang_found = false
- clang_supports_bpf = false
- bpf_gcc_found = false
- bpftool_strip = 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,
- version : '>= 10.0.0')
- clang_found = r.found()
- if clang_found
- clang = r.full_path()
- endif
- else
- clang_found = true
- clang = cc.cmd_array()
- 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
- endif
- if bpf_framework.enabled() and not clang_supports_bpf
- error('bpf-framework was enabled but clang does not support bpf')
- endif
- elif bpf_compiler == 'gcc'
- bpf_gcc = find_program('bpf-gcc',
- 'bpf-none-gcc',
- 'bpf-unknown-none-gcc',
- required : true,
- version : '>= 13.1.0')
- bpf_gcc_found = bpf_gcc.found()
- endif
-
- 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.enabled() and bpf_compiler == 'gcc',
- version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
-
- if bpftool.found()
- bpftool_strip = true
- deps_found = true
- elif bpf_compiler == 'clang'
- # We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
- bpftool = find_program('bpftool',
- '/usr/sbin/bpftool',
- required : bpf_framework,
- version : '>= 5.6.0')
- endif
-
- # 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,
- 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)
-endif
-
libmount = dependency('mount',
version : fuzzer_build ? '>= 0' : '>= 2.30',
required : get_option('libmount'))
@@ -1156,8 +1076,8 @@ libmount_cflags = libmount.partial_dependency(includes: true, compile_args: true
libfdisk = dependency('fdisk',
version : '>= 2.32',
- disabler : true,
required : get_option('fdisk'))
+libfdisk_cflags = libfdisk.partial_dependency(includes: true, compile_args: true)
conf.set10('HAVE_LIBFDISK', libfdisk.found())
# This prefers pwquality if both are enabled or auto.
@@ -1261,6 +1181,7 @@ libmicrohttpd = dependency('libmicrohttpd',
version : '>= 0.9.33',
required : get_option('microhttpd'))
conf.set10('HAVE_MICROHTTPD', libmicrohttpd.found())
+libmicrohttpd_cflags = libmicrohttpd.partial_dependency(includes: true, compile_args: true)
libcryptsetup = get_option('libcryptsetup')
libcryptsetup_plugins = get_option('libcryptsetup-plugins')
@@ -1332,6 +1253,7 @@ libgnutls = dependency('gnutls',
version : '>= 3.1.4',
required : get_option('gnutls'))
conf.set10('HAVE_GNUTLS', libgnutls.found())
+libgnutls_cflags = libgnutls.partial_dependency(includes: true, compile_args: true)
libopenssl = dependency('openssl',
version : '>= 3.0.0',
@@ -1730,171 +1652,6 @@ endif
#####################################################################
-if conf.get('BPF_FRAMEWORK') == 1
- bpf_clang_flags = [
- '-std=gnu17',
- '-Wno-compare-distinct-pointer-types',
- '-Wno-microsoft-anon-tag',
- '-fms-extensions',
- '-fno-stack-protector',
- '-O2',
- '-target',
- 'bpf',
- '-g',
- '-c',
- ]
-
- bpf_gcc_flags = [
- '-std=gnu17',
- '-fms-extensions',
- '-fno-stack-protector',
- '-fno-ssa-phiopt',
- '-O2',
- '-mcpu=v3',
- '-mco-re',
- '-gbtf',
- '-c',
- ]
-
- # If c_args contains these flags copy them along with the values, in order to avoid breaking
- # reproducible builds and other functionality
- propagate_cflags = [
- '-ffile-prefix-map=',
- '-fdebug-prefix-map=',
- '-fmacro-prefix-map=',
- '--sysroot=',
- ]
-
- foreach opt : c_args
- foreach flag : propagate_cflags
- if opt.startswith(flag)
- bpf_clang_flags += [opt]
- bpf_gcc_flags += [opt]
- break
- endif
- endforeach
- endforeach
-
- # 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 ____.
- # This dictionary contains the exceptions where this doesn't work.
- #
- # C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
- # and src/basic/missing_syscall_def.h.
-
- # Start with older ABI. When define is missing, we're likely targeting that.
- ppc64_elf_version = '1'
-
- if host_machine.cpu_family() == 'ppc64'
- # cc doesn't have to be bpf_compiler, but they should be targeting the same ABI
- call_elf_value = cc.get_define('_CALL_ELF')
- if call_elf_value != ''
- ppc64_elf_version = call_elf_value
- endif
- endif
-
- cpu_arch_defines = {
- 'ppc' : ['-D__powerpc__', '-D__TARGET_ARCH_powerpc'],
- 'ppc64' : ['-D__powerpc64__', '-D__TARGET_ARCH_powerpc', '-D_CALL_ELF=' + ppc64_elf_version],
- 'riscv32' : ['-D__riscv', '-D__riscv_xlen=32', '-D__TARGET_ARCH_riscv'],
- 'riscv64' : ['-D__riscv', '-D__riscv_xlen=64', '-D__TARGET_ARCH_riscv'],
- 'x86' : ['-D__i386__', '-D__TARGET_ARCH_x86'],
- 's390x' : ['-D__s390__', '-D__s390x__', '-D__TARGET_ARCH_s390'],
-
- # For arm, assume hardware fp is available.
- 'arm' : ['-D__arm__', '-D__ARM_PCS_VFP', '-D__TARGET_ARCH_arm'],
- 'loongarch64' : ['-D__loongarch__', '-D__loongarch_grlen=64', '-D__TARGET_ARCH_loongarch']
- }
-
- 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 = []
- 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.', '-include', 'config.h']
-
- if cc.get_id() == 'gcc' or meson.is_cross_build()
- if cc.get_id() != 'gcc'
- warning('Cross compiler is not gcc. Guessing the target triplet for bpf likely fails.')
- endif
- target_triplet_cmd = run_command(cc.cmd_array(), '-print-multiarch', check: false)
- else
- # clang does not support -print-multiarch (D133170) and its -dump-machine
- # does not match multiarch. Query gcc instead.
- target_triplet_cmd = run_command('gcc', '-print-multiarch', check: false)
- endif
- if target_triplet_cmd.returncode() == 0
- sysroot = meson.get_external_property('sys_root', '/')
- target_triplet = target_triplet_cmd.stdout().strip()
- target_include_dir = sysroot / 'usr' / 'include'
- target_triple_include_dir = target_include_dir / target_triplet
- isystem_dir = ''
- if fs.is_dir(target_triple_include_dir)
- isystem_dir = target_triple_include_dir
- elif fs.is_dir(target_include_dir)
- isystem_dir = target_include_dir
- endif
- if isystem_dir != ''
- bpf_o_unstripped_cmd += [
- '-isystem', isystem_dir
- ]
- endif
- endif
-
- bpf_o_unstripped_cmd += [
- '-idirafter',
- libbpf_include_dir,
- '@INPUT@',
- '-o',
- '@OUTPUT@'
- ]
-
- if bpftool_strip
- bpf_o_cmd = [
- bpftool,
- 'gen',
- 'object',
- '@OUTPUT@',
- '@INPUT@'
- ]
- elif bpf_compiler == 'clang'
- bpf_o_cmd = [
- llvm_strip,
- '-g',
- '@INPUT@',
- '-o',
- '@OUTPUT@'
- ]
- endif
-
- skel_h_cmd = [
- bpftool,
- 'gen',
- 'skeleton',
- '@INPUT@'
- ]
-endif
-
-#####################################################################
-
efi_arch = {
'aarch64' : 'aa64',
'arm' : 'arm',
@@ -1932,77 +1689,6 @@ conf.set10('ENABLE_UKIFY', want_ukify)
#####################################################################
-use_provided_vmlinux_h = false
-use_generated_vmlinux_h = false
-provided_vmlinux_h_path = get_option('vmlinux-h-path')
-
-# For the more complex BPF programs we really want a vmlinux.h (which is arch
-# specific, but only somewhat bound to kernel version). Ideally the kernel
-# development headers would ship that, but right now they don't. Hence address
-# this in two ways:
-#
-# 1. Provide a vmlinux.h at build time
-# 2. Generate the file on the fly where possible (which requires /sys/ to be mounted)
-#
-# We generally prefer the former (to support reproducible builds), but will
-# fallback to the latter.
-
-if conf.get('BPF_FRAMEWORK') == 1
- enable_vmlinux_h = get_option('vmlinux-h')
-
- if enable_vmlinux_h == 'auto'
- if provided_vmlinux_h_path != ''
- use_provided_vmlinux_h = true
- elif fs.exists('/sys/kernel/btf/vmlinux') and \
- bpftool.found() and \
- (host_machine.cpu_family() == build_machine.cpu_family()) and \
- host_machine.cpu_family() in ['x86_64', 'aarch64']
-
- # We will only generate a vmlinux.h from the running
- # kernel if the host and build machine are of the same
- # family. Also for now we focus on x86_64 and aarch64,
- # since other archs don't seem to be ready yet.
-
- use_generated_vmlinux_h = true
- endif
- elif enable_vmlinux_h == 'provided'
- use_provided_vmlinux_h = true
- elif enable_vmlinux_h == 'generated'
- if not fs.exists('/sys/kernel/btf/vmlinux')
- error('BTF data from kernel not available (/sys/kernel/btf/vmlinux missing), cannot generate vmlinux.h, but was asked to.')
- endif
- if not bpftool.found()
- error('bpftool not available, cannot generate vmlinux.h, but was asked to.')
- endif
- use_generated_vmlinux_h = true
- endif
-endif
-
-vmlinux_h_dependency = []
-if use_provided_vmlinux_h
- if not fs.exists(provided_vmlinux_h_path)
- error('Path to provided vmlinux.h does not exist.')
- endif
- bpf_o_unstripped_cmd += ['-I' + fs.parent(provided_vmlinux_h_path)]
- message(f'Using provided @provided_vmlinux_h_path@')
-elif use_generated_vmlinux_h
- vmlinux_h_dependency = custom_target(
- output: 'vmlinux.h',
- command : [ bpftool, 'btf', 'dump', 'file', '/sys/kernel/btf/vmlinux', 'format', 'c' ],
- capture : true)
-
- bpf_o_unstripped_cmd += ['-I' + fs.parent(vmlinux_h_dependency.full_path())]
- message('Using generated @0@'.format(vmlinux_h_dependency.full_path()))
-else
- message('Using neither provided nor generated vmlinux.h, some features will not be available.')
-endif
-
-conf.set10('HAVE_VMLINUX_H', use_provided_vmlinux_h or use_generated_vmlinux_h)
-
-conf.set10('ENABLE_SYSCTL_BPF', conf.get('HAVE_VMLINUX_H') == 1 and libbpf.version().version_compare('>= 0.7'))
-
-#####################################################################
-
version_tag = get_option('version-tag')
if version_tag == ''
version_tag = meson.project_version()
@@ -2010,8 +1696,11 @@ endif
conf.set_quoted('VERSION_TAG', version_tag)
+generated_sources = []
+
subdir('tools')
subdir('src/version')
+subdir('src/bpf')
shared_lib_tag = get_option('shared-lib-tag')
if shared_lib_tag == ''
@@ -2051,7 +1740,6 @@ executables = []
executables_by_name = {}
objects_by_name = {}
fuzzer_exes = []
-generated_sources = [version_h, vmlinux_h_dependency]
sources = []
# binaries that have --help and are intended for use by humans,
@@ -2118,7 +1806,13 @@ libsystemd_includes = [basic_includes, include_directories(
'src/libsystemd/sd-resolve',
'src/libsystemd/sd-varlink')]
-includes = [libsystemd_includes, include_directories('src/shared')]
+includes = [
+ libsystemd_includes,
+ include_directories(
+ 'src/shared',
+ 'src/bpf',
+ ),
+]
subdir('po')
subdir('catalog')
@@ -2519,11 +2213,18 @@ foreach dict : executables
exe_sources = dict.get('sources', []) + dict.get('extract', [])
+ foreach bpf_name : dict.get('bpf_programs', [])
+ if bpf_name in bpf_programs_by_name
+ exe_sources += bpf_programs_by_name[bpf_name]
+ endif
+ endforeach
+
kwargs = {}
foreach key, val : dict
if key in ['name', 'dbus', 'public', 'conditions', 'type', 'suite',
'timeout', 'parallel', 'objects', 'sources', 'extract',
- 'include_directories', 'build_by_default', 'install']
+ 'include_directories', 'build_by_default', 'install',
+ 'bpf_programs']
continue
endif
@@ -2541,7 +2242,7 @@ foreach dict : executables
foreach val : dict.get('objects', [])
obj = objects_by_name[val]
- kwargs += { 'objects' : obj['objects'] }
+ kwargs += { 'objects' : kwargs.get('objects', []) + obj['objects'] }
include_directories += obj['include_directories']
endforeach
diff --git a/mkosi/mkosi.conf.d/centos-fedora/mkosi.conf b/mkosi/mkosi.conf.d/centos-fedora/mkosi.conf
index dd00fa737c..fc9ffd58c9 100644
--- a/mkosi/mkosi.conf.d/centos-fedora/mkosi.conf
+++ b/mkosi/mkosi.conf.d/centos-fedora/mkosi.conf
@@ -43,6 +43,7 @@ Packages=
kernel-core
knot
libcap-ng-utils
+ libmicrohttpd
libucontext
man-db
nmap-ncat
diff --git a/mkosi/mkosi.conf.d/opensuse/mkosi.conf b/mkosi/mkosi.conf.d/opensuse/mkosi.conf
index b0593e3f1a..5abebc04cf 100644
--- a/mkosi/mkosi.conf.d/opensuse/mkosi.conf
+++ b/mkosi/mkosi.conf.d/opensuse/mkosi.conf
@@ -57,6 +57,7 @@ Packages=
libcap-progs
libdw-devel
libdw1
+ libmicrohttpd12
libtss2-tcti-device0
libz1
man
@@ -84,6 +85,7 @@ Packages=
softhsm
squashfs
stress-ng
+ system-user-bin
tgt
timezone
tpm2.0-tools
diff --git a/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf b/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf
index 97607f9b59..f46a0a0372 100644
--- a/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf
+++ b/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf
@@ -9,5 +9,5 @@ Environment=
GIT_URL=https://salsa.debian.org/systemd-team/systemd.git
GIT_SUBDIR=debian
GIT_BRANCH=debian/master
- GIT_COMMIT=23ef56be0050f78be704f288ed1ce30ace47cbfe
+ GIT_COMMIT=94af257c72ac3e9bf20e324ff31c3bd5d8197f0e
PKG_SUBDIR=debian
diff --git a/mkosi/mkosi.postinst.chroot b/mkosi/mkosi.postinst.chroot
index eb6d917025..de67ddfdc8 100755
--- a/mkosi/mkosi.postinst.chroot
+++ b/mkosi/mkosi.postinst.chroot
@@ -27,8 +27,9 @@ mountpoint -q /etc/resolv.conf && umount /etc/resolv.conf
rm -f /etc/resolv.conf
for f in "$BUILDROOT"/usr/share/*.verity.sig; do
- jq --join-output '.rootHash' "$f" >"${f%.verity.sig}.roothash"
- jq --join-output '.signature' "$f" | base64 --decode >"${f%.verity.sig}.roothash.p7s"
+ # jq started refusing input with NUL bytes padding
+ strings "$f" | jq --join-output '.rootHash' >"${f%.verity.sig}.roothash"
+ strings "$f" | jq --join-output '.signature' | base64 --decode >"${f%.verity.sig}.roothash.p7s"
done
# We want /var/log/journal to be created on first boot so it can be created with the right chattr settings by
diff --git a/mkosi/mkosi.sanitizers/mkosi.postinst b/mkosi/mkosi.sanitizers/mkosi.postinst
index 1184331254..88ba2c2bc0 100755
--- a/mkosi/mkosi.sanitizers/mkosi.postinst
+++ b/mkosi/mkosi.sanitizers/mkosi.postinst
@@ -84,6 +84,7 @@ wrap=(
mdadm
mkfs.btrfs
mksquashfs
+ mount
multipath
multipathd
nvme
@@ -99,6 +100,7 @@ wrap=(
su
tar
tgtd
+ umount
unix_chkpwd
useradd
userdel
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 11efeb5f04..4fba725bb9 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -3,17 +3,18 @@
# Brazilian Portuguese translation for systemd.
# Enrico Nicoletto , 2014.
# Filipe Brandenburger , 2018.
-# Rafael Fontenelle , 2015-2020, 2025.
+# Rafael Fontenelle , 2015-2020, 2025, 2026.
# Gustavo Costa , 2021.
# Tiago Rocha Cunha , 2024.
# Gabriel Elyas , 2024.
# Fábio Rodrigues Ribeiro , 2024.
# "Geraldo S. Simião Kutz" , 2024.
+# Weblate Translation Memory , 2026.
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-06 03:46+0900\n"
-"PO-Revision-Date: 2025-10-29 18:54+0000\n"
+"PO-Revision-Date: 2026-04-22 10:58+0000\n"
"Last-Translator: Rafael Fontenelle \n"
"Language-Team: Portuguese (Brazil) \n"
@@ -22,7 +23,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 5.13.3\n"
+"X-Generator: Weblate 5.17\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
@@ -1051,12 +1052,12 @@ msgid "DHCP server sends force renew message"
msgstr "Servidor DHCP envia mensagem de renovação forçada"
#: src/network/org.freedesktop.network1.policy:144
-#, fuzzy
-#| msgid "Authentication is required to send force renew message."
msgid ""
"Authentication is required to send a force renew message from the DHCP "
"server."
-msgstr "É necessária autenticação para enviar mensagem de renovação forçada."
+msgstr ""
+"É necessária autenticação para enviar uma mensagem de renovação forçada a "
+"partir do servidor DHCP."
#: src/network/org.freedesktop.network1.policy:154
msgid "Renew dynamic addresses"
@@ -1098,11 +1099,11 @@ msgstr ""
#: src/network/org.freedesktop.network1.policy:198
msgid "Manage network links"
-msgstr ""
+msgstr "Gerenciar conexões de rede"
#: src/network/org.freedesktop.network1.policy:199
msgid "Authentication is required to manage network links."
-msgstr ""
+msgstr "A autenticação é necessária para gerenciar conexões de rede."
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
diff --git a/shell-completion/bash/bootctl b/shell-completion/bash/bootctl
index 31aaa1cace..d7714731c2 100644
--- a/shell-completion/bash/bootctl
+++ b/shell-completion/bash/bootctl
@@ -35,6 +35,7 @@ _bootctl() {
[STANDALONE]='-h --help --version
-p --print-esp-path -x --print-boot-path --print-loader-path
--print-stub-path -R --print-root-device -RR
+ --print-efi-architecture
--no-pager --graceful -q --quiet --all-architectures
--dry-run'
[ARG]='--esp-path --boot-path --root --image --image-policy --install-source
diff --git a/shell-completion/bash/systemd-nspawn b/shell-completion/bash/systemd-nspawn
index b39d3cbd6d..85f3023083 100644
--- a/shell-completion/bash/systemd-nspawn
+++ b/shell-completion/bash/systemd-nspawn
@@ -78,7 +78,9 @@ _systemd_nspawn() {
--network-ipvlan --network-veth-extra --network-zone -p --port --system-call-filter --overlay
--overlay-ro --settings --rlimit --hostname --no-new-privileges --oom-score-adjust --cpu-affinity
--resolv-conf --timezone --root-hash-sig --background --oci-bundle --verity-data
- --restrict-address-families'
+ --restrict-address-families
+ --forward-journal --forward-journal-max-use --forward-journal-keep-free
+ --forward-journal-max-file-size --forward-journal-max-files'
)
_init_completion || return
diff --git a/shell-completion/bash/systemd-vmspawn b/shell-completion/bash/systemd-vmspawn
index b2b3f4f5a8..efa0dae58d 100644
--- a/shell-completion/bash/systemd-vmspawn
+++ b/shell-completion/bash/systemd-vmspawn
@@ -38,7 +38,7 @@ _systemd_vmspawn() {
[BIND]='--bind --bind-ro'
[SSH_KEY]='--ssh-key'
[CONSOLE]='--console'
- [ARG]='--cpus --ram --vsock-cid -M --machine --uuid --private-users --background --set-credential --load-credential'
+ [ARG]='--cpus --ram --vsock-cid -M --machine --uuid --private-users --background --set-credential --load-credential --forward-journal-max-use --forward-journal-keep-free --forward-journal-max-file-size --forward-journal-max-files'
[IMAGE_FORMAT]='--image-format'
[IMAGE_DISK_TYPE]='--image-disk-type'
)
diff --git a/shell-completion/zsh/_bootctl b/shell-completion/zsh/_bootctl
index 4476128561..f7ed2a8e41 100644
--- a/shell-completion/zsh/_bootctl
+++ b/shell-completion/zsh/_bootctl
@@ -74,6 +74,7 @@ _arguments \
'--boot-path=[Path to the $BOOT partition]:path:_directories' \
'(-p --print-esp-path)'{-p,--print-esp-path}'[Print path to the EFI system partition]' \
'(-x --print-boot-path)'{-x,--print-boot-path}'[Print path to the $BOOT partition]' \
+ '--print-efi-architecture[Print the EFI architecture identifier]' \
'--make-machine-id-directory=[Control creation and deletion of the top-level machine ID directory.]:options:(yes no auto)' \
'--no-pager[Do not pipe output into a pager]' \
'--graceful[Do not fail when locating ESP or writing fails]' \
diff --git a/shell-completion/zsh/_systemd-nspawn b/shell-completion/zsh/_systemd-nspawn
index ee28fa7475..10dc527236 100644
--- a/shell-completion/zsh/_systemd-nspawn
+++ b/shell-completion/zsh/_systemd-nspawn
@@ -54,4 +54,9 @@ _arguments \
"--notify-ready=[Control when the ready notification is sent]:options:(yes no)" \
"--suppress-sync=[Control whether to suppress disk synchronization for the container payload]:options:(yes no)" \
'--restrict-address-families=[Restrict socket address families accessible in the container.]: : _message "address families"' \
+ '--forward-journal=[Forward the container journal to the host via systemd-journal-remote.]: : _files' \
+ '--forward-journal-max-use=[Maximum disk space used by forwarded journal files.]: : _message bytes' \
+ '--forward-journal-keep-free=[Disk space to keep free for forwarded journal files.]: : _message bytes' \
+ '--forward-journal-max-file-size=[Maximum size of individual forwarded journal files.]: : _message bytes' \
+ '--forward-journal-max-files=[Maximum number of forwarded journal files.]: : _message number' \
'*:: : _normal'
diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c
index c1b2948e6c..08bff2cf9e 100644
--- a/src/analyze/analyze-security.c
+++ b/src/analyze/analyze-security.c
@@ -605,7 +605,7 @@ static int assess_system_call_filter(
uint64_t b;
int r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0) {
*ret_badness = UINT64_MAX;
*ret_description = NULL;
@@ -2578,7 +2578,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
info->_umask = c->umask;
#if HAVE_SECCOMP
- if (dlopen_libseccomp() >= 0) {
+ if (dlopen_libseccomp(LOG_DEBUG) >= 0) {
SET_FOREACH(key, c->syscall_archs) {
const char *name;
diff --git a/src/basic/compress.c b/src/basic/compress.c
index 979e07ac80..8386bdb1b1 100644
--- a/src/basic/compress.c
+++ b/src/basic/compress.c
@@ -284,7 +284,7 @@ Compression compression_detect_from_magic(const uint8_t data[static COMPRESSION_
return _COMPRESSION_INVALID;
}
-int dlopen_xz(void) {
+int dlopen_xz(int log_level) {
#if HAVE_XZ
SD_ELF_NOTE_DLOPEN(
"lzma",
@@ -294,7 +294,7 @@ int dlopen_xz(void) {
return dlopen_many_sym_or_warn(
&lzma_dl,
- "liblzma.so.5", LOG_DEBUG,
+ "liblzma.so.5", log_level,
DLSYM_ARG(lzma_code),
DLSYM_ARG(lzma_easy_encoder),
DLSYM_ARG(lzma_end),
@@ -302,11 +302,12 @@ int dlopen_xz(void) {
DLSYM_ARG(lzma_lzma_preset),
DLSYM_ARG(lzma_stream_decoder));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "lzma support is not compiled in.");
#endif
}
-int dlopen_lz4(void) {
+int dlopen_lz4(int log_level) {
#if HAVE_LZ4
SD_ELF_NOTE_DLOPEN(
"lz4",
@@ -316,7 +317,7 @@ int dlopen_lz4(void) {
return dlopen_many_sym_or_warn(
&lz4_dl,
- "liblz4.so.1", LOG_DEBUG,
+ "liblz4.so.1", log_level,
DLSYM_ARG(LZ4F_compressBegin),
DLSYM_ARG(LZ4F_compressBound),
DLSYM_ARG(LZ4F_compressEnd),
@@ -333,11 +334,12 @@ int dlopen_lz4(void) {
DLSYM_ARG(LZ4_decompress_safe_partial),
DLSYM_ARG(LZ4_versionNumber));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "lz4 support is not compiled in.");
#endif
}
-int dlopen_zstd(void) {
+int dlopen_zstd(int log_level) {
#if HAVE_ZSTD
SD_ELF_NOTE_DLOPEN(
"zstd",
@@ -347,7 +349,7 @@ int dlopen_zstd(void) {
return dlopen_many_sym_or_warn(
&zstd_dl,
- "libzstd.so.1", LOG_DEBUG,
+ "libzstd.so.1", log_level,
DLSYM_ARG(ZSTD_getErrorCode),
DLSYM_ARG(ZSTD_compress),
DLSYM_ARG(ZSTD_getFrameContentSize),
@@ -365,11 +367,12 @@ int dlopen_zstd(void) {
DLSYM_ARG(ZSTD_createDCtx),
DLSYM_ARG(ZSTD_createCCtx));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "zstd support is not compiled in.");
#endif
}
-int dlopen_zlib(void) {
+int dlopen_zlib(int log_level) {
#if HAVE_ZLIB
SD_ELF_NOTE_DLOPEN(
"zlib",
@@ -379,7 +382,7 @@ int dlopen_zlib(void) {
return dlopen_many_sym_or_warn(
&zlib_dl,
- "libz.so.1", LOG_DEBUG,
+ "libz.so.1", log_level,
DLSYM_ARG(deflateInit2_),
DLSYM_ARG(deflate),
DLSYM_ARG(deflateEnd),
@@ -387,11 +390,12 @@ int dlopen_zlib(void) {
DLSYM_ARG(inflate),
DLSYM_ARG(inflateEnd));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "zlib support is not compiled in.");
#endif
}
-int dlopen_bzip2(void) {
+int dlopen_bzip2(int log_level) {
#if HAVE_BZIP2
SD_ELF_NOTE_DLOPEN(
"bzip2",
@@ -401,7 +405,7 @@ int dlopen_bzip2(void) {
return dlopen_many_sym_or_warn(
&bzip2_dl,
- "libbz2.so.1", LOG_DEBUG,
+ "libbz2.so.1", log_level,
DLSYM_ARG(BZ2_bzCompressInit),
DLSYM_ARG(BZ2_bzCompress),
DLSYM_ARG(BZ2_bzCompressEnd),
@@ -409,7 +413,8 @@ int dlopen_bzip2(void) {
DLSYM_ARG(BZ2_bzDecompress),
DLSYM_ARG(BZ2_bzDecompressEnd));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "bzip2 support is not compiled in.");
#endif
}
@@ -440,7 +445,7 @@ static int compress_blob_xz(
size_t out_pos = 0;
int r;
- r = dlopen_xz();
+ r = dlopen_xz(LOG_DEBUG);
if (r < 0)
return r;
@@ -485,7 +490,7 @@ static int compress_blob_lz4(
#if HAVE_LZ4
int r;
- r = dlopen_lz4();
+ r = dlopen_lz4(LOG_DEBUG);
if (r < 0)
return r;
/* Returns < 0 if we couldn't compress the data or the
@@ -533,7 +538,7 @@ static int compress_blob_zstd(
size_t k;
int r;
- r = dlopen_zstd();
+ r = dlopen_zstd(LOG_DEBUG);
if (r < 0)
return r;
@@ -560,7 +565,7 @@ static int compress_blob_gzip(const void *src, uint64_t src_size,
#if HAVE_ZLIB
int r;
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -609,7 +614,7 @@ static int compress_blob_bzip2(
#if HAVE_BZIP2
int r;
- r = dlopen_bzip2();
+ r = dlopen_bzip2(LOG_DEBUG);
if (r < 0)
return r;
@@ -677,7 +682,7 @@ static int decompress_blob_xz(
#if HAVE_XZ
int r;
- r = dlopen_xz();
+ r = dlopen_xz(LOG_DEBUG);
if (r < 0)
return r;
@@ -744,7 +749,7 @@ static int decompress_blob_lz4(
char* out;
int r, size; /* LZ4 uses int for size */
- r = dlopen_lz4();
+ r = dlopen_lz4(LOG_DEBUG);
if (r < 0)
return r;
@@ -790,7 +795,7 @@ static int decompress_blob_zstd(
uint64_t size;
int r;
- r = dlopen_zstd();
+ r = dlopen_zstd(LOG_DEBUG);
if (r < 0)
return r;
@@ -847,7 +852,7 @@ static int decompress_blob_gzip(
#if HAVE_ZLIB
int r;
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -914,7 +919,7 @@ static int decompress_blob_bzip2(
#if HAVE_BZIP2
int r;
- r = dlopen_bzip2();
+ r = dlopen_bzip2(LOG_DEBUG);
if (r < 0)
return r;
@@ -1010,7 +1015,7 @@ int decompress_zlib_raw(
#if HAVE_ZLIB
int r;
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -1061,7 +1066,7 @@ static int decompress_startswith_xz(
#if HAVE_XZ
int r;
- r = dlopen_xz();
+ r = dlopen_xz(LOG_DEBUG);
if (r < 0)
return r;
@@ -1128,7 +1133,7 @@ static int decompress_startswith_lz4(
size_t allocated;
int r;
- r = dlopen_lz4();
+ r = dlopen_lz4(LOG_DEBUG);
if (r < 0)
return r;
@@ -1200,7 +1205,7 @@ static int decompress_startswith_zstd(
#if HAVE_ZSTD
int r;
- r = dlopen_zstd();
+ r = dlopen_zstd(LOG_DEBUG);
if (r < 0)
return r;
@@ -1257,7 +1262,7 @@ static int decompress_startswith_gzip(
#if HAVE_ZLIB
int r;
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -1324,7 +1329,7 @@ static int decompress_startswith_bzip2(
#if HAVE_BZIP2
int r;
- r = dlopen_bzip2();
+ r = dlopen_bzip2(LOG_DEBUG);
if (r < 0)
return r;
@@ -1561,7 +1566,7 @@ static int decompressor_new(Decompressor **ret, Compression type) {
#if HAVE_XZ
case COMPRESSION_XZ:
- r = dlopen_xz();
+ r = dlopen_xz(LOG_DEBUG);
if (r < 0)
return r;
@@ -1572,7 +1577,7 @@ static int decompressor_new(Decompressor **ret, Compression type) {
#if HAVE_LZ4
case COMPRESSION_LZ4: {
- r = dlopen_lz4();
+ r = dlopen_lz4(LOG_DEBUG);
if (r < 0)
return r;
@@ -1586,7 +1591,7 @@ static int decompressor_new(Decompressor **ret, Compression type) {
#if HAVE_ZSTD
case COMPRESSION_ZSTD:
- r = dlopen_zstd();
+ r = dlopen_zstd(LOG_DEBUG);
if (r < 0)
return r;
@@ -1598,7 +1603,7 @@ static int decompressor_new(Decompressor **ret, Compression type) {
#if HAVE_ZLIB
case COMPRESSION_GZIP:
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -1610,7 +1615,7 @@ static int decompressor_new(Decompressor **ret, Compression type) {
#if HAVE_BZIP2
case COMPRESSION_BZIP2:
- r = dlopen_bzip2();
+ r = dlopen_bzip2(LOG_DEBUG);
if (r < 0)
return r;
@@ -1791,7 +1796,7 @@ int decompressor_detect(Decompressor **ret, const void *data, size_t size) {
#if HAVE_XZ
case COMPRESSION_XZ: {
- r = dlopen_xz();
+ r = dlopen_xz(LOG_DEBUG);
if (r < 0)
return r;
@@ -1805,7 +1810,7 @@ int decompressor_detect(Decompressor **ret, const void *data, size_t size) {
#if HAVE_LZ4
case COMPRESSION_LZ4: {
- r = dlopen_lz4();
+ r = dlopen_lz4(LOG_DEBUG);
if (r < 0)
return r;
@@ -1819,7 +1824,7 @@ int decompressor_detect(Decompressor **ret, const void *data, size_t size) {
#if HAVE_ZSTD
case COMPRESSION_ZSTD: {
- r = dlopen_zstd();
+ r = dlopen_zstd(LOG_DEBUG);
if (r < 0)
return r;
@@ -1833,7 +1838,7 @@ int decompressor_detect(Decompressor **ret, const void *data, size_t size) {
#if HAVE_ZLIB
case COMPRESSION_GZIP: {
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -1847,7 +1852,7 @@ int decompressor_detect(Decompressor **ret, const void *data, size_t size) {
#if HAVE_BZIP2
case COMPRESSION_BZIP2: {
- r = dlopen_bzip2();
+ r = dlopen_bzip2(LOG_DEBUG);
if (r < 0)
return r;
@@ -2092,7 +2097,7 @@ int compressor_new(Compressor **ret, Compression type) {
#if HAVE_XZ
case COMPRESSION_XZ: {
- r = dlopen_xz();
+ r = dlopen_xz(LOG_DEBUG);
if (r < 0)
return r;
@@ -2107,7 +2112,7 @@ int compressor_new(Compressor **ret, Compression type) {
#if HAVE_LZ4
case COMPRESSION_LZ4: {
- r = dlopen_lz4();
+ r = dlopen_lz4(LOG_DEBUG);
if (r < 0)
return r;
@@ -2133,7 +2138,7 @@ int compressor_new(Compressor **ret, Compression type) {
#if HAVE_ZSTD
case COMPRESSION_ZSTD:
- r = dlopen_zstd();
+ r = dlopen_zstd(LOG_DEBUG);
if (r < 0)
return r;
@@ -2156,7 +2161,7 @@ int compressor_new(Compressor **ret, Compression type) {
#if HAVE_ZLIB
case COMPRESSION_GZIP:
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0)
return r;
@@ -2176,7 +2181,7 @@ int compressor_new(Compressor **ret, Compression type) {
#if HAVE_BZIP2
case COMPRESSION_BZIP2:
- r = dlopen_bzip2();
+ r = dlopen_bzip2(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/basic/compress.h b/src/basic/compress.h
index 1c1e4f0e24..45584b7a6d 100644
--- a/src/basic/compress.h
+++ b/src/basic/compress.h
@@ -80,11 +80,11 @@ int compress_stream(Compression type, int fdf, int fdt, uint64_t max_bytes, uint
int decompress_stream(Compression type, int fdf, int fdt, uint64_t max_bytes);
int decompress_stream_by_filename(const char *filename, int fdf, int fdt, uint64_t max_bytes);
-int dlopen_xz(void);
-int dlopen_lz4(void);
-int dlopen_zstd(void);
-int dlopen_zlib(void);
-int dlopen_bzip2(void);
+int dlopen_xz(int log_level);
+int dlopen_lz4(int log_level);
+int dlopen_zstd(int log_level);
+int dlopen_zlib(int log_level);
+int dlopen_bzip2(int log_level);
static inline const char* default_compression_extension(void) {
return compression_extension_to_string(DEFAULT_COMPRESSION) ?: "";
diff --git a/src/basic/dlfcn-util.c b/src/basic/dlfcn-util.c
index 23bd1f666e..86ec2d28fd 100644
--- a/src/basic/dlfcn-util.c
+++ b/src/basic/dlfcn-util.c
@@ -47,7 +47,7 @@ int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) {
return r;
}
-int dlopen_verbose(void **dlp, const char *filename) {
+int dlopen_verbose(void **dlp, const char *filename, int log_level) {
int r;
assert(dlp);
@@ -58,10 +58,9 @@ int dlopen_verbose(void **dlp, const char *filename) {
_cleanup_(dlclosep) void *dl = NULL;
const char *dle = NULL;
r = dlopen_safe(filename, &dl, &dle);
- if (r < 0) {
- log_debug_errno(r, "Shared library '%s' is not available: %s", filename, dle ?: STRERROR(r));
- return -EOPNOTSUPP; /* Turn into recognizable error */
- }
+ if (r < 0)
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "Shared library '%s' is not available: %s", filename, dle ?: STRERROR(r));
log_debug("Loaded shared library '%s' via dlopen().", filename);
*dlp = TAKE_PTR(dl);
@@ -77,7 +76,7 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
return 0; /* Already loaded */
_cleanup_(dlclosep) void *dl = NULL;
- r = dlopen_verbose(&dl, filename);
+ r = dlopen_verbose(&dl, filename, log_level);
if (r < 0)
return r;
diff --git a/src/basic/dlfcn-util.h b/src/basic/dlfcn-util.h
index 40de137905..ccf0ec6be3 100644
--- a/src/basic/dlfcn-util.h
+++ b/src/basic/dlfcn-util.h
@@ -11,7 +11,7 @@ static inline void dlclosep(void **dlp) {
safe_dlclose(*dlp);
}
-int dlopen_verbose(void **dlp, const char *filename);
+int dlopen_verbose(void **dlp, const char *filename, int log_level);
int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) _sentinel_;
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) _sentinel_;
diff --git a/src/basic/gcrypt-util.c b/src/basic/gcrypt-util.c
index 79cab18822..34444811ad 100644
--- a/src/basic/gcrypt-util.c
+++ b/src/basic/gcrypt-util.c
@@ -5,6 +5,7 @@
#include "sd-dlopen.h"
#include "gcrypt-util.h"
+#include "log.h" /* IWYU pragma: keep */
#if HAVE_GCRYPT
@@ -44,7 +45,7 @@ DLSYM_PROTOTYPE(gcry_randomize) = NULL;
DLSYM_PROTOTYPE(gcry_strerror) = NULL;
#endif
-int dlopen_gcrypt(void) {
+int dlopen_gcrypt(int log_level) {
#if HAVE_GCRYPT
SD_ELF_NOTE_DLOPEN(
"gcrypt",
@@ -54,7 +55,7 @@ int dlopen_gcrypt(void) {
return dlopen_many_sym_or_warn(
&gcrypt_dl,
- "libgcrypt.so.20", LOG_DEBUG,
+ "libgcrypt.so.20", log_level,
DLSYM_ARG(gcry_control),
DLSYM_ARG(gcry_check_version),
DLSYM_ARG(gcry_md_close),
@@ -88,7 +89,8 @@ int dlopen_gcrypt(void) {
DLSYM_ARG(gcry_randomize),
DLSYM_ARG(gcry_strerror));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "gcrypt support is not compiled in.");
#endif
}
@@ -96,7 +98,7 @@ int initialize_libgcrypt(bool secmem) {
#if HAVE_GCRYPT
int r;
- r = dlopen_gcrypt();
+ r = dlopen_gcrypt(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/basic/gcrypt-util.h b/src/basic/gcrypt-util.h
index 147a174da0..0f45fad205 100644
--- a/src/basic/gcrypt-util.h
+++ b/src/basic/gcrypt-util.h
@@ -4,7 +4,7 @@
#include "basic-forward.h"
-int dlopen_gcrypt(void);
+int dlopen_gcrypt(int log_level);
int initialize_libgcrypt(bool secmem);
diff --git a/src/basic/iovec-util.c b/src/basic/iovec-util.c
index ec8af57e64..dab734b901 100644
--- a/src/basic/iovec-util.c
+++ b/src/basic/iovec-util.c
@@ -21,35 +21,39 @@ size_t iovec_total_size(const struct iovec *iovec, size_t n) {
assert(iovec || n == 0);
- FOREACH_ARRAY(j, iovec, n)
+ FOREACH_ARRAY(j, iovec, n) {
+ if (j->iov_len > SIZE_MAX - sum)
+ return SIZE_MAX; /* Indicate overflow. */
sum += j->iov_len;
+ }
return sum;
}
-bool iovec_increment(struct iovec *iovec, size_t n, size_t k) {
+bool iovec_inc_many(struct iovec *iovec, size_t n, size_t k) {
assert(iovec || n == 0);
/* Returns true if there is nothing else to send (bytes written cover all of the iovec),
* false if there's still work to do. */
+ bool have = false;
FOREACH_ARRAY(j, iovec, n) {
- size_t sub;
-
if (j->iov_len == 0)
continue;
if (k == 0)
return false;
- sub = MIN(j->iov_len, k);
- j->iov_len -= sub;
- j->iov_base = (uint8_t*) j->iov_base + sub;
+ size_t sub = MIN(j->iov_len, k);
+ iovec_inc(j, sub);
k -= sub;
+
+ have = have || iovec_is_set(j);
}
assert(k == 0); /* Anything else would mean that we wrote more bytes than available,
* or the kernel reported writing more bytes than sent. */
- return true;
+
+ return !have;
}
struct iovec* iovec_make_string(struct iovec *iovec, const char *s) {
diff --git a/src/basic/iovec-util.h b/src/basic/iovec-util.h
index 00cbb89a77..c8261861a0 100644
--- a/src/basic/iovec-util.h
+++ b/src/basic/iovec-util.h
@@ -11,7 +11,7 @@ extern const struct iovec iovec_empty; /* Points to an empty, but valid (i.e.
size_t iovec_total_size(const struct iovec *iovec, size_t n) _nonnull_if_nonzero_(1, 2);
-bool iovec_increment(struct iovec *iovec, size_t n, size_t k) _nonnull_if_nonzero_(1, 2);
+bool iovec_inc_many(struct iovec *iovec, size_t n, size_t k) _nonnull_if_nonzero_(1, 2);
struct iovec* iovec_make_string(struct iovec *iovec, const char *s);
@@ -38,6 +38,9 @@ char* set_iovec_string_field_free(struct iovec *iovec, size_t *n_iovec, const ch
void iovec_array_free(struct iovec *iovec, size_t n_iovec) _nonnull_if_nonzero_(1, 2);
int iovec_memcmp(const struct iovec *a, const struct iovec *b) _pure_;
+static inline bool iovec_equal(const struct iovec *a, const struct iovec *b) {
+ return iovec_memcmp(a, b) == 0;
+}
struct iovec* iovec_memdup(const struct iovec *source, struct iovec *ret);
diff --git a/src/basic/log.c b/src/basic/log.c
index 473d0bd70f..d8b441bfad 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -557,7 +557,7 @@ static int write_to_syslog(
if (!syslog_is_stream)
break;
- if (iovec_increment(iovec, ELEMENTSOF(iovec), n))
+ if (iovec_inc_many(iovec, ELEMENTSOF(iovec), n))
break;
}
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index a2bbaf1ea8..4d93083923 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -1099,25 +1099,40 @@ int strdup_to_full(char **ret, const char *src) {
}
};
-bool string_is_safe(const char *p) {
- if (!p)
+bool string_is_safe(const char *p, StringSafeFlags flags) {
+
+ /* Baseline checks are:
+ * • No control characters (i.e. 0…31 + 127)
+ * • UTF-8 valid (well, technically we skip this test if STRING_ASCII is set, since that is a tighter test)
+ */
+
+ if (FLAGS_SET(flags, STRING_ALLOW_EMPTY) ? !p : isempty(p))
return false;
- /* Checks if the specified string contains no quotes or control characters */
+ if (!FLAGS_SET(flags, STRING_ASCII) && !utf8_is_valid(p))
+ return false;
for (const char *t = p; *t; t++) {
- if (*t > 0 && *t < ' ') /* no control characters */
+ if ((*t > 0 && *t < ' ') || *t == 0x7f) /* never allow control characters */
return false;
- if (strchr(QUOTES "\\\x7f", *t))
+ if (!FLAGS_SET(flags, STRING_ALLOW_BACKSLASHES) && *t == '\\')
+ return false;
+
+ if (!FLAGS_SET(flags, STRING_ALLOW_QUOTES) && strchr(QUOTES, *t))
+ return false;
+
+ if (!FLAGS_SET(flags, STRING_ALLOW_GLOBS) && strchr(GLOB_CHARS, *t))
+ return false;
+
+ if (FLAGS_SET(flags, STRING_ASCII) && (uint8_t) *t >= 0x80)
return false;
}
- return true;
-}
+ if (FLAGS_SET(flags, STRING_FILENAME) && !filename_is_valid(p))
+ return false;
-bool string_is_safe_ascii(const char *p) {
- return ascii_is_valid(p) && string_is_safe(p);
+ return true;
}
char* str_realloc(char *p) {
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index 820b8688c2..17eaf5d9a6 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -220,8 +220,16 @@ static inline int strdup_to(char **ret, const char *src) {
return r < 0 ? r : 0; /* Suppress return value of 1. */
}
-bool string_is_safe(const char *p) _pure_;
-bool string_is_safe_ascii(const char *p) _pure_;
+typedef enum StringSafeFlags {
+ STRING_ASCII = 1 << 0, /* Verify string is 7-Bit ASCII (rather than just UTF-8) */
+ STRING_ALLOW_EMPTY = 1 << 1, /* Allow empty strings */
+ STRING_ALLOW_BACKSLASHES = 1 << 2, /* Allow backslashes (\) */
+ STRING_ALLOW_QUOTES = 1 << 3, /* Allow quotes (" or ') */
+ STRING_ALLOW_GLOBS = 1 << 4, /* Allow globs (?, * or [) */
+ STRING_FILENAME = 1 << 5, /* Verify the string is valid as regular filename */
+} StringSafeFlags;
+
+bool string_is_safe(const char *p, StringSafeFlags flags) _pure_;
DISABLE_WARNING_STRINGOP_TRUNCATION;
static inline void strncpy_exact(char *buf, const char *src, size_t buf_len) {
diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c
index fd910ca76d..bd1bb65282 100644
--- a/src/basic/syslog-util.c
+++ b/src/basic/syslog-util.c
@@ -4,9 +4,7 @@
#include "sd-id128.h"
-#include "glob-util.h"
#include "hexdecoct.h"
-#include "path-util.h"
#include "string-table.h"
#include "string-util.h"
#include "syslog-util.h"
@@ -111,7 +109,8 @@ bool log_namespace_name_valid(const char *s) {
* (so that /var/log/journal/. can be created based on it). Also make sure it
* is suitable as unit instance name, and does not contain fishy characters. */
- if (!filename_is_valid(s))
+ /* Let's avoid globbing for now */
+ if (!string_is_safe(s, STRING_FILENAME))
return false;
if (strlen(s) > LOG_NAMESPACE_MAX)
@@ -120,12 +119,5 @@ bool log_namespace_name_valid(const char *s) {
if (!unit_instance_is_valid(s))
return false;
- if (!string_is_safe(s))
- return false;
-
- /* Let's avoid globbing for now */
- if (string_is_glob(s))
- return false;
-
return true;
}
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c
index a89a81c703..57a67af163 100644
--- a/src/basic/unit-def.c
+++ b/src/basic/unit-def.c
@@ -72,6 +72,14 @@ const char* unit_dbus_interface_from_name(const char *name) {
return unit_dbus_interface_from_type(t);
}
+const char* unit_type_to_capitalized_string(UnitType t) {
+ const char *di = unit_dbus_interface_from_type(t);
+ if (!di)
+ return NULL;
+
+ return ASSERT_PTR(startswith(di, "org.freedesktop.systemd1."));
+}
+
static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = "service",
[UNIT_SOCKET] = "socket",
diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h
index 5fecd3ecec..8d05b5b5ed 100644
--- a/src/basic/unit-def.h
+++ b/src/basic/unit-def.h
@@ -321,6 +321,7 @@ void unit_types_list(void);
DECLARE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
DECLARE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
+const char* unit_type_to_capitalized_string(UnitType t);
DECLARE_STRING_TABLE_LOOKUP(freezer_state, FreezerState);
FreezerState freezer_state_finish(FreezerState state) _const_;
diff --git a/src/boot/cpio.c b/src/boot/cpio.c
index 7ad4b470fa..81792b00a8 100644
--- a/src/boot/cpio.c
+++ b/src/boot/cpio.c
@@ -52,12 +52,11 @@ static char *pad4(char *p, const char *start) {
return p;
}
-static EFI_STATUS pack_cpio_one(
+EFI_STATUS pack_cpio_one(
const char16_t *fname,
const void *contents,
size_t contents_size,
- const char *target_dir_prefix,
- uint32_t access_mode,
+ const CpioTarget *target,
uint32_t *inode_counter,
void **cpio_buffer,
size_t *cpio_buffer_size) {
@@ -67,7 +66,7 @@ static EFI_STATUS pack_cpio_one(
assert(fname);
assert(contents || contents_size == 0);
- assert(target_dir_prefix);
+ assert(target);
assert(inode_counter);
assert(cpio_buffer);
assert(cpio_buffer_size);
@@ -84,7 +83,7 @@ static EFI_STATUS pack_cpio_one(
l = 6 + 13*8 + 1 + 1; /* Fixed CPIO header size, slash separator, and NUL byte after the file name */
- target_dir_prefix_size = strlen8(target_dir_prefix);
+ target_dir_prefix_size = strlen8(target->directory);
if (l > SIZE_MAX - target_dir_prefix_size)
return EFI_OUT_OF_RESOURCES;
l += target_dir_prefix_size;
@@ -121,11 +120,11 @@ static EFI_STATUS pack_cpio_one(
a = mempcpy(a, "070701", 6); /* magic ID */
- a = write_cpio_word(a, (*inode_counter)++); /* inode */
- a = write_cpio_word(a, access_mode | 0100000 /* = S_IFREG */); /* mode */
- a = write_cpio_word(a, 0); /* uid */
- a = write_cpio_word(a, 0); /* gid */
- a = write_cpio_word(a, 1); /* nlink */
+ a = write_cpio_word(a, (*inode_counter)++); /* inode */
+ a = write_cpio_word(a, target->access_mode | 0100000 /* = S_IFREG */); /* mode */
+ a = write_cpio_word(a, 0); /* uid */
+ a = write_cpio_word(a, 0); /* gid */
+ a = write_cpio_word(a, 1); /* nlink */
/* Note: we don't make any attempt to propagate the mtime here, for two reasons: it's a mess given
* that FAT usually is assumed to operate with timezoned timestamps, while UNIX does not. More
@@ -141,7 +140,7 @@ static EFI_STATUS pack_cpio_one(
a = write_cpio_word(a, target_dir_prefix_size + fname_size + 2); /* fname size */
a = write_cpio_word(a, 0); /* "crc" */
- a = mempcpy(a, target_dir_prefix, target_dir_prefix_size);
+ a = mempcpy(a, target->directory, target_dir_prefix_size);
*(a++) = '/';
a = mangle_filename(a, fname);
@@ -225,16 +224,15 @@ static EFI_STATUS pack_cpio_dir(
return EFI_SUCCESS;
}
-static EFI_STATUS pack_cpio_prefix(
- const char *path,
- uint32_t dir_mode,
+EFI_STATUS pack_cpio_prefix(
+ const CpioTarget *target,
uint32_t *inode_counter,
void **cpio_buffer,
size_t *cpio_buffer_size) {
EFI_STATUS err;
- assert(path);
+ assert(target);
assert(inode_counter);
assert(cpio_buffer);
assert(cpio_buffer_size);
@@ -243,7 +241,7 @@ static EFI_STATUS pack_cpio_prefix(
* (similar to mkdir -p behaviour) all leading paths are created with 0555 access mode, only the
* final dir is created with the specified directory access mode. */
- for (const char *p = path;;) {
+ for (const char *p = target->directory;;) {
const char *e;
e = strchr8(p, '/');
@@ -253,7 +251,7 @@ static EFI_STATUS pack_cpio_prefix(
if (e > p) {
_cleanup_free_ char *t = NULL;
- t = xstrndup8(path, e - path);
+ t = xstrndup8(target->directory, e - target->directory);
if (!t)
return EFI_OUT_OF_RESOURCES;
@@ -265,10 +263,10 @@ static EFI_STATUS pack_cpio_prefix(
p = e + 1;
}
- return pack_cpio_dir(path, dir_mode, inode_counter, cpio_buffer, cpio_buffer_size);
+ return pack_cpio_dir(target->directory, target->dir_mode, inode_counter, cpio_buffer, cpio_buffer_size);
}
-static EFI_STATUS pack_cpio_trailer(
+EFI_STATUS pack_cpio_trailer(
void **cpio_buffer,
size_t *cpio_buffer_size) {
@@ -307,9 +305,7 @@ EFI_STATUS pack_cpio(
const char16_t *dropin_dir,
const char16_t *match_suffix,
const char16_t *exclude_suffix,
- const char *target_dir_prefix,
- uint32_t dir_mode,
- uint32_t access_mode,
+ const CpioTarget *target,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
@@ -325,7 +321,7 @@ EFI_STATUS pack_cpio(
EFI_STATUS err;
assert(loaded_image);
- assert(target_dir_prefix);
+ assert(target);
assert(ret_buffer);
if (!loaded_image->DeviceHandle)
@@ -400,7 +396,7 @@ EFI_STATUS pack_cpio(
/* Generate the leading directory inodes right before adding the first files, to the
* archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */
- err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
+ err = pack_cpio_prefix(target, &inode, &buffer, &buffer_size);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to pack cpio prefix: %m");
@@ -417,8 +413,7 @@ EFI_STATUS pack_cpio(
err = pack_cpio_one(
items[i],
content, contentsize,
- target_dir_prefix,
- access_mode,
+ target,
&inode,
&buffer, &buffer_size);
if (err != EFI_SUCCESS)
@@ -453,10 +448,8 @@ nothing:
EFI_STATUS pack_cpio_literal(
const void *data,
size_t data_size,
- const char *target_dir_prefix,
+ const CpioTarget *target,
const char16_t *target_filename,
- uint32_t dir_mode,
- uint32_t access_mode,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
@@ -468,22 +461,21 @@ EFI_STATUS pack_cpio_literal(
EFI_STATUS err;
assert(data || data_size == 0);
- assert(target_dir_prefix);
+ assert(target);
assert(target_filename);
assert(ret_buffer);
/* Generate the leading directory inodes right before adding the first files, to the
* archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */
- err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
+ err = pack_cpio_prefix(target, &inode, &buffer, &buffer_size);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to pack cpio prefix: %m");
err = pack_cpio_one(
target_filename,
data, data_size,
- target_dir_prefix,
- access_mode,
+ target,
&inode,
&buffer, &buffer_size);
if (err != EFI_SUCCESS)
@@ -505,3 +497,55 @@ EFI_STATUS pack_cpio_literal(
*ret_buffer = IOVEC_MAKE(TAKE_PTR(buffer), buffer_size);
return EFI_SUCCESS;
}
+
+/* The following are canonical definitions of the various cpio target directories we place resources in. We
+ * define them here in a single canonical list of targets because we need to reuse them at various places
+ * (well, some of them at least), and we don't want the access modes to deviate slightly on each use. */
+
+const CpioTarget cpio_target_credentials = {
+ .directory = ".extra/credentials",
+ .dir_mode = 0500,
+ .access_mode = 0400,
+};
+
+const CpioTarget cpio_target_global_credentials = {
+ .directory = ".extra/global_credentials",
+ .dir_mode = 0500,
+ .access_mode = 0400,
+};
+
+const CpioTarget cpio_target_sysext = {
+ .directory = ".extra/sysext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_global_sysext = {
+ .directory = ".extra/global_sysext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_confext = {
+ .directory = ".extra/confext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_global_confext = {
+ .directory = ".extra/global_confext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_meta = {
+ .directory = ".extra",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_meta_secret = {
+ .directory = ".extra",
+ .dir_mode = 0555,
+ .access_mode = 0400,
+};
diff --git a/src/boot/cpio.h b/src/boot/cpio.h
index bb741278fd..3c311bc714 100644
--- a/src/boot/cpio.h
+++ b/src/boot/cpio.h
@@ -4,14 +4,37 @@
#include "efi.h"
#include "proto/loaded-image.h"
+typedef struct CpioTarget {
+ const char *directory; /* Path to directory where to place resources */
+ uint32_t dir_mode; /* Access mode for the directory */
+ uint32_t access_mode; /* Access mode for the files in the directory */
+} CpioTarget;
+
+EFI_STATUS pack_cpio_one(
+ const char16_t *fname,
+ const void *contents,
+ size_t contents_size,
+ const CpioTarget *target,
+ uint32_t *inode_counter,
+ void **cpio_buffer,
+ size_t *cpio_buffer_size);
+
+EFI_STATUS pack_cpio_prefix(
+ const CpioTarget *target,
+ uint32_t *inode_counter,
+ void **cpio_buffer,
+ size_t *cpio_buffer_size);
+
+EFI_STATUS pack_cpio_trailer(
+ void **cpio_buffer,
+ size_t *cpio_buffer_size);
+
EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
const char16_t *dropin_dir,
const char16_t *match_suffix,
const char16_t *exclude_suffix,
- const char *target_dir_prefix,
- uint32_t dir_mode,
- uint32_t access_mode,
+ const CpioTarget *target,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
@@ -20,11 +43,18 @@ EFI_STATUS pack_cpio(
EFI_STATUS pack_cpio_literal(
const void *data,
size_t data_size,
- const char *target_dir_prefix,
+ const CpioTarget *target,
const char16_t *target_filename,
- uint32_t dir_mode,
- uint32_t access_mode,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
bool *ret_measured);
+
+extern const CpioTarget cpio_target_credentials;
+extern const CpioTarget cpio_target_global_credentials;
+extern const CpioTarget cpio_target_sysext;
+extern const CpioTarget cpio_target_global_sysext;
+extern const CpioTarget cpio_target_confext;
+extern const CpioTarget cpio_target_global_confext;
+extern const CpioTarget cpio_target_meta;
+extern const CpioTarget cpio_target_meta_secret;
diff --git a/src/boot/initrd.c b/src/boot/initrd.c
index 4babe1671d..044e011f60 100644
--- a/src/boot/initrd.c
+++ b/src/boot/initrd.c
@@ -71,8 +71,6 @@ EFI_STATUS initrd_register(
EFI_HANDLE *ret_initrd_handle) {
EFI_STATUS err;
- EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) &efi_initrd_device_path;
- EFI_HANDLE handle;
assert(ret_initrd_handle);
@@ -82,12 +80,43 @@ EFI_STATUS initrd_register(
if (!iovec_is_set(initrd))
return EFI_SUCCESS;
- /* Check if a LINUX_INITRD_MEDIA_GUID DevicePath is already registered. LocateDevicePath checks for
- * the "closest DevicePath" and returns its handle, whereas InstallMultipleProtocolInterfaces() only
- * matches identical DevicePaths. */
- err = BS->LocateDevicePath(MAKE_GUID_PTR(EFI_LOAD_FILE2_PROTOCOL), &dp, &handle);
- if (err != EFI_NOT_FOUND) /* InitrdMedia is already registered */
- return EFI_ALREADY_STARTED;
+ /* We want to override the LINUX_INITRD_MEDIA device, let's hence first unregister any existing
+ * one. We don't really expect multiple of these to be registered, but who knows? Let's kill all we
+ * can find. */
+ for (unsigned attempt = 0;; attempt++) {
+
+ if (attempt >= 16)
+ return log_debug_status(EFI_DEVICE_ERROR, "Unable to free LINUX_INITRD_MEDIA device path after %u attempts, giving up.", attempt);
+
+ EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) &efi_initrd_device_path;
+ EFI_HANDLE handle = NULL;
+ err = BS->LocateDevicePath(MAKE_GUID_PTR(EFI_LOAD_FILE2_PROTOCOL), &dp, &handle);
+ if (err == EFI_NOT_FOUND) /* Yay! All gone */
+ break;
+ if (err != EFI_SUCCESS)
+ return log_debug_status(err, "Failed to locate LINUX_INITRD_MEDIA device: %m");
+
+ /* Get the *actually* installed pointer for the device path */
+ err = BS->HandleProtocol(handle, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void**) &dp);
+ if (err != EFI_SUCCESS)
+ return log_debug_status(err, "Failed to acquire DevicePath protocol on LINUX_INITRD_MEDIA device: %m");
+
+ /* Take away the device path protocol */
+ err = BS->UninstallMultipleProtocolInterfaces(
+ handle,
+ MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), dp,
+ /* sentinel= */ NULL);
+ if (err != EFI_SUCCESS)
+ return log_debug_status(err, "Unable to release DevicePath protocol from old handle: %m");
+
+ /* NB: we leave the handle around (and thus leave the LoadFile2 protocol installed), because
+ * the owner might be unhappy if we destroy it for them. It will no longer have the device
+ * path we want to take possession of on it though. The assumption here is that whoever
+ * registered the device path is OK with the device path being taken away, even if it might
+ * not be OK with the handle being invalidated as a whole. */
+
+ log_debug("Successfully unregistered previous LINUX_INITRD_MEDIA device.");
+ }
_cleanup_free_ struct initrd_loader *loader = xnew(struct initrd_loader, 1);
*loader = (struct initrd_loader) {
@@ -122,15 +151,112 @@ EFI_STATUS initrd_unregister(EFI_HANDLE initrd_handle) {
if (err != EFI_SUCCESS)
return log_debug_status(err, "Failed to acquire LoadFile2 protocol on our own initrd handle: %m");
- /* uninstall all protocols thus destroying the handle */
+ /* We uninstall the DevicePath and the LoadFile2 protocol in separate steps. That's because we want
+ * to gracefully handle the former (because it's OK if something else takes over the device path),
+ * but be strict on the latter, because that's genuinely ours */
+
+ (void) BS->UninstallMultipleProtocolInterfaces(
+ initrd_handle,
+ MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), &efi_initrd_device_path,
+ /* sentinel= */ NULL);
+
+ /* This second call will also invalidate the handle, because it should be the last protocol on the handle */
err = BS->UninstallMultipleProtocolInterfaces(
- initrd_handle, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL),
- &efi_initrd_device_path, MAKE_GUID_PTR(EFI_LOAD_FILE2_PROTOCOL),
- loader,
- NULL);
+ initrd_handle,
+ MAKE_GUID_PTR(EFI_LOAD_FILE2_PROTOCOL), loader,
+ /* sentinel= */ NULL);
if (err != EFI_SUCCESS)
return log_debug_status(err, "Failed to uninstall LoadFile2 protocol from our own initrd handle: %m");
free(loader);
return EFI_SUCCESS;
}
+
+EFI_STATUS initrd_read_previous(struct iovec *ret_initrd) {
+ EFI_STATUS err;
+
+ /* If there's already an initrd registered, read it out, so that we can incorporate it in ours */
+
+ assert(ret_initrd);
+
+ /* Get from the device path to the handle */
+ EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) &efi_initrd_device_path;
+ EFI_HANDLE handle;
+ err = BS->LocateDevicePath(MAKE_GUID_PTR(EFI_LOAD_FILE2_PROTOCOL), &dp, &handle);
+ if (err != EFI_SUCCESS)
+ return err;
+
+ /* Get from the handle to the protocol */
+ EFI_LOAD_FILE2_PROTOCOL *protocol = NULL;
+ err = BS->HandleProtocol(handle, MAKE_GUID_PTR(EFI_LOAD_FILE2_PROTOCOL), (void**) &protocol);
+ if (err != EFI_SUCCESS)
+ return err;
+
+ size_t size = 0;
+ err = protocol->LoadFile(protocol, dp, /* bootPolicy= */ false, &size, /* Buffer= */ NULL);
+ if (err == EFI_SUCCESS) /* Success? Kinda unexpected given we set Buffer to NULL, but it probably
+ * means, that the file is zero-sized, let's treat it as such. */
+ size = 0;
+ else if (err != EFI_BUFFER_TOO_SMALL)
+ return err;
+
+ if (size == 0)
+ return EFI_NOT_FOUND; /* Treat empty initrds like missing ones */
+
+ _cleanup_free_ void *data = xmalloc(size);
+ err = protocol->LoadFile(protocol, dp, /* bootPolicy= */ false, &size, data);
+ if (err != EFI_SUCCESS)
+ return err;
+
+ *ret_initrd = (struct iovec) {
+ .iov_base = TAKE_PTR(data),
+ .iov_len = size,
+ };
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS combine_initrds(
+ const struct iovec initrds[], size_t n_initrds,
+ Pages *ret_initrd_pages, size_t *ret_initrd_size) {
+
+ size_t n = 0;
+
+ /* Combine initrds by concatenation in memory */
+
+ assert(initrds || n_initrds == 0);
+ assert(ret_initrd_pages);
+ assert(ret_initrd_size);
+
+ FOREACH_ARRAY(i, initrds, n_initrds) {
+ /* some initrds (the ones from UKI sections) need padding, pad all to be safe */
+ size_t initrd_size = ALIGN4(i->iov_len);
+ if (n > SIZE_MAX - initrd_size)
+ return EFI_OUT_OF_RESOURCES;
+
+ n += initrd_size;
+ }
+
+ _cleanup_pages_ Pages pages = xmalloc_initrd_pages(n);
+ uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr);
+
+ FOREACH_ARRAY(i, initrds, n_initrds) {
+ size_t pad;
+
+ p = mempcpy(p, i->iov_base, i->iov_len);
+
+ pad = ALIGN4(i->iov_len) - i->iov_len;
+ if (pad == 0)
+ continue;
+
+ memzero(p, pad);
+ p += pad;
+ }
+
+ assert(PHYSICAL_ADDRESS_TO_POINTER(pages.addr + n) == p);
+
+ *ret_initrd_pages = TAKE_STRUCT(pages);
+ *ret_initrd_size = n;
+
+ return EFI_SUCCESS;
+}
diff --git a/src/boot/initrd.h b/src/boot/initrd.h
index 50987c497d..cfcb8d1c6f 100644
--- a/src/boot/initrd.h
+++ b/src/boot/initrd.h
@@ -2,6 +2,8 @@
#pragma once
#include "efi.h"
+#include "iovec-util-fundamental.h"
+#include "util.h"
EFI_STATUS initrd_register(
const struct iovec *initrd,
@@ -13,3 +15,7 @@ static inline void cleanup_initrd(EFI_HANDLE *initrd_handle) {
(void) initrd_unregister(*initrd_handle);
*initrd_handle = NULL;
}
+
+EFI_STATUS initrd_read_previous(struct iovec *ret_initrd);
+
+EFI_STATUS combine_initrds(const struct iovec initrds[], size_t n_initrds, Pages *ret_initrd_pages, size_t *ret_initrd_size);
diff --git a/src/boot/stub.c b/src/boot/stub.c
index e2a8569cb3..8632a603a2 100644
--- a/src/boot/stub.c
+++ b/src/boot/stub.c
@@ -10,6 +10,7 @@
#include "efi-string.h"
#include "export-vars.h"
#include "graphics.h"
+#include "initrd.h"
#include "iovec-util-fundamental.h"
#include "linux.h"
#include "measure.h"
@@ -32,13 +33,10 @@
/* The list of initrds we combine into one, in the order we want to merge them */
enum {
- /* The first two are part of the PE binary */
- INITRD_UCODE,
- INITRD_BASE,
-
- /* The rest are dynamically generated, and hence in dynamic memory */
- _INITRD_DYNAMIC_FIRST,
- INITRD_CREDENTIAL = _INITRD_DYNAMIC_FIRST,
+ INITRD_UCODE, /* Part of the PE binary */
+ INITRD_PREVIOUS, /* initrd already configured via the EFI protocol before we were invoked */
+ INITRD_BASE, /* Part of the PE binary */
+ INITRD_CREDENTIAL,
INITRD_GLOBAL_CREDENTIAL,
INITRD_SYSEXT,
INITRD_GLOBAL_SYSEXT,
@@ -52,6 +50,8 @@ enum {
_INITRD_MAX,
};
+#define INITRD_IS_STATIC(idx) IN_SET(idx, INITRD_UCODE, INITRD_BASE)
+
/* magic string to find in the binary image */
DECLARE_NOALLOC_SECTION(".sdmagic", "#### LoaderInfo: systemd-stub " GIT_VERSION " ####");
@@ -102,50 +102,6 @@ static void combine_measured_flag(int *value, int measured) {
*value = *value < 0 ? measured : *value && measured;
}
-/* Combine initrds by concatenation in memory */
-static EFI_STATUS combine_initrds(
- const struct iovec initrds[], size_t n_initrds,
- Pages *ret_initrd_pages, size_t *ret_initrd_size) {
-
- size_t n = 0;
-
- assert(initrds || n_initrds == 0);
- assert(ret_initrd_pages);
- assert(ret_initrd_size);
-
- FOREACH_ARRAY(i, initrds, n_initrds) {
- /* some initrds (the ones from UKI sections) need padding, pad all to be safe */
- size_t initrd_size = ALIGN4(i->iov_len);
- if (n > SIZE_MAX - initrd_size)
- return EFI_OUT_OF_RESOURCES;
-
- n += initrd_size;
- }
-
- _cleanup_pages_ Pages pages = xmalloc_initrd_pages(n);
- uint8_t *p = PHYSICAL_ADDRESS_TO_POINTER(pages.addr);
-
- FOREACH_ARRAY(i, initrds, n_initrds) {
- size_t pad;
-
- p = mempcpy(p, i->iov_base, i->iov_len);
-
- pad = ALIGN4(i->iov_len) - i->iov_len;
- if (pad == 0)
- continue;
-
- memzero(p, pad);
- p += pad;
- }
-
- assert(PHYSICAL_ADDRESS_TO_POINTER(pages.addr + n) == p);
-
- *ret_initrd_pages = TAKE_STRUCT(pages);
- *ret_initrd_size = n;
-
- return EFI_SUCCESS;
-}
-
static void export_stub_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image, unsigned profile) {
static const uint64_t stub_features =
EFI_STUB_FEATURE_REPORT_BOOT_PARTITION | /* We set LoaderDevicePartUUID */
@@ -550,6 +506,21 @@ static void extend_initrds(
iovec_array_extend(all_initrds, n_all_initrds, *i);
}
+static void acquire_previous_initrd(struct iovec initrds[static _INITRD_MAX]) {
+ EFI_STATUS err;
+
+ /* NB: the assumption here is that any previously installed initrd are measured by whatever
+ * registered them, and we just pass them on here. */
+
+ err = initrd_read_previous(initrds + INITRD_PREVIOUS);
+ if (err == EFI_NOT_FOUND)
+ log_debug_status(err, "No previous initrd registered.");
+ else if (err != EFI_SUCCESS)
+ log_warning_status(err, "Failed to read previously registered initrd, ignoring.");
+ else
+ log_debug("Successfully loaded previously registered initrd (%zu bytes).", initrds[INITRD_PREVIOUS].iov_len);
+}
+
static EFI_STATUS load_addons(
EFI_HANDLE stub_image,
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
@@ -821,10 +792,11 @@ static void cmdline_append_and_measure_smbios(char16_t **cmdline, int *parameter
static void initrds_free(struct iovec (*initrds)[_INITRD_MAX]) {
assert(initrds);
- /* Free the dynamic initrds, but leave the non-dynamic ones around */
+ /* Free the non-static initrds, but leave the static (i.e. PE embedded) ones around */
- for (size_t i = _INITRD_DYNAMIC_FIRST; i < _INITRD_MAX; i++)
- iovec_done((*initrds) + i);
+ for (size_t i = 0; i < _INITRD_MAX; i++)
+ if (!INITRD_IS_STATIC(i))
+ iovec_done((*initrds) + i);
}
static void generate_sidecar_initrds(
@@ -846,9 +818,7 @@ static void generate_sidecar_initrds(
/* dropin_dir= */ NULL,
u".cred",
/* exclude_suffix= */ NULL,
- ".extra/credentials",
- /* dir_mode= */ 0500,
- /* access_mode= */ 0400,
+ &cpio_target_credentials,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Credentials initrd",
initrds + INITRD_CREDENTIAL,
@@ -859,9 +829,7 @@ static void generate_sidecar_initrds(
u"\\loader\\credentials",
u".cred",
/* exclude_suffix= */ NULL,
- ".extra/global_credentials",
- /* dir_mode= */ 0500,
- /* access_mode= */ 0400,
+ &cpio_target_global_credentials,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Global credentials initrd",
initrds + INITRD_GLOBAL_CREDENTIAL,
@@ -872,9 +840,7 @@ static void generate_sidecar_initrds(
/* dropin_dir= */ NULL,
u".raw", /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
u".confext.raw", /* … but then exclude *.confext.raw again */
- ".extra/sysext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_sysext,
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
u"System extension initrd",
initrds + INITRD_SYSEXT,
@@ -885,9 +851,7 @@ static void generate_sidecar_initrds(
u"\\loader\\extensions",
u".raw", /* as above */
u".confext.raw",
- ".extra/global_sysext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_global_sysext,
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
u"Global system extension initrd",
initrds + INITRD_GLOBAL_SYSEXT,
@@ -898,9 +862,7 @@ static void generate_sidecar_initrds(
/* dropin_dir= */ NULL,
u".confext.raw",
/* exclude_suffix= */ NULL,
- ".extra/confext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_confext,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Configuration extension initrd",
initrds + INITRD_CONFEXT,
@@ -911,9 +873,7 @@ static void generate_sidecar_initrds(
u"\\loader\\extensions",
u".confext.raw",
/* exclude_suffix= */ NULL,
- ".extra/global_confext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_global_confext,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Global configuration extension initrd",
initrds + INITRD_GLOBAL_CONFEXT,
@@ -964,10 +924,8 @@ static void generate_embedded_initrds(
(void) pack_cpio_literal(
(const uint8_t*) loaded_image->ImageBase + sections[t->section].memory_offset,
sections[t->section].memory_size,
- ".extra",
+ &cpio_target_meta,
t->filename,
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
/* tpm_pcr= */ UINT32_MAX,
/* tpm_description= */ NULL,
initrds + t->initrd_index,
@@ -988,10 +946,8 @@ static void generate_boot_secret_initrd(
(void) pack_cpio_literal(
boot_secret,
BOOT_SECRET_SIZE,
- ".extra",
+ &cpio_target_meta_secret,
u"boot-secret",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0400,
/* tpm_pcr= */ UINT32_MAX,
/* tpm_description= */ NULL,
initrds + INITRD_BOOT_SECRET,
@@ -1309,6 +1265,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
install_addon_devicetrees(&dt_state, dt_addons, n_dt_addons, ¶meters_measured);
/* Generate & find all initrds */
+ acquire_previous_initrd(initrds);
generate_sidecar_initrds(loaded_image, initrds, ¶meters_measured, &sysext_measured, &confext_measured);
generate_embedded_initrds(loaded_image, sections, initrds);
generate_boot_secret_initrd(boot_secret, initrds);
@@ -1319,9 +1276,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
* We want addons to take precedence over the base initrds, so the order is:
* 1. Ucode addons
* 2. UKI ucode
- * 3. UKI initrd
- * 4. Generated initrds
- * 5. initrd addons */
+ * 3. Previous initrds
+ * 4. UKI initrd
+ * 5. Generated initrds
+ * 6. initrd addons */
measure_and_append_ucode_addons(&all_initrds, &n_all_initrds, ucode_addons, n_ucode_addons, ¶meters_measured);
extend_initrds(initrds, &all_initrds, &n_all_initrds);
measure_and_append_initrd_addons(&all_initrds, &n_all_initrds, initrd_addons, n_initrd_addons, ¶meters_measured);
diff --git a/src/bootctl/bootctl.c b/src/bootctl/bootctl.c
index 239a0c9273..00ae512668 100644
--- a/src/bootctl/bootctl.c
+++ b/src/bootctl/bootctl.c
@@ -15,6 +15,7 @@
#include "bootctl-status.h"
#include "bootctl-uki.h"
#include "bootctl-unlink.h"
+#include "bootctl-util.h"
#include "build.h"
#include "devnum-util.h"
#include "dissect-image.h"
@@ -38,7 +39,6 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
-#include "utf8.h"
#include "varlink-io.systemd.BootControl.h"
#include "varlink-util.h"
#include "verbs.h"
@@ -52,6 +52,7 @@ bool arg_print_esp_path = false;
bool arg_print_dollar_boot_path = false;
bool arg_print_loader_path = false;
bool arg_print_stub_path = false;
+bool arg_print_efi_architecture = false;
unsigned arg_print_root_device = 0;
int arg_touch_variables = -1;
bool arg_install_random_seed = true;
@@ -450,6 +451,10 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
arg_print_root_device++;
break;
+ OPTION_LONG("print-efi-architecture", NULL, "Print the local EFI architecture string"):
+ arg_print_efi_architecture = true;
+ break;
+
OPTION_GROUP("Options"):
break;
@@ -567,7 +572,7 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
OPTION_LONG("efi-boot-option-description", "DESCRIPTION",
"Description of the entry in the boot option list"):
- if (isempty(arg) || !(string_is_safe(arg) && utf8_is_valid(arg))) {
+ if (!string_is_safe(arg, STRING_ALLOW_BACKSLASHES|STRING_ALLOW_QUOTES|STRING_ALLOW_GLOBS)) {
_cleanup_free_ char *escaped = cescape(arg);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid --efi-boot-option-description=: %s", strna(escaped));
@@ -639,9 +644,9 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
char **args = option_parser_get_args(&state);
- if (!!arg_print_esp_path + !!arg_print_dollar_boot_path + (arg_print_root_device > 0) + arg_print_loader_path + arg_print_stub_path > 1)
+ if (!!arg_print_esp_path + !!arg_print_dollar_boot_path + (arg_print_root_device > 0) + arg_print_loader_path + arg_print_stub_path + arg_print_efi_architecture > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--print-esp-path/-p, --print-boot-path/-x, --print-root-device=/-R, --print-loader-path, --print-stub-path cannot be combined.");
+ "--print-esp-path/-p, --print-boot-path/-x, --print-root-device=/-R, --print-loader-path, --print-stub-path, --print-efi-architecture cannot be combined.");
if ((arg_root || arg_image) && args[0] && !STR_IN_SET(args[0], "status", "list",
"install", "update", "remove", "is-installed", "random-seed", "unlink", "cleanup"))
@@ -761,6 +766,11 @@ static int run(int argc, char *argv[]) {
if (arg_print_loader_path || arg_print_stub_path)
return print_loader_or_stub_path();
+ if (arg_print_efi_architecture) {
+ printf("%s\n", get_efi_arch());
+ return 0;
+ }
+
/* Open up and mount the image */
if (arg_image) {
assert(!arg_root);
diff --git a/src/bootctl/bootctl.h b/src/bootctl/bootctl.h
index d3d6583c02..d0daab9dd1 100644
--- a/src/bootctl/bootctl.h
+++ b/src/bootctl/bootctl.h
@@ -24,6 +24,7 @@ extern bool arg_print_dollar_boot_path;
extern bool arg_print_loader_path;
extern bool arg_print_stub_path;
extern unsigned arg_print_root_device;
+extern bool arg_print_efi_architecture;
extern int arg_touch_variables;
extern bool arg_install_random_seed;
extern PagerFlags arg_pager_flags;
diff --git a/src/bpf/.clang-tidy b/src/bpf/.clang-tidy
new file mode 100644
index 0000000000..43b0c59f49
--- /dev/null
+++ b/src/bpf/.clang-tidy
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+---
+InheritParentConfig: true
+Checks: '-misc-use-internal-linkage'
+CheckOptions:
+ misc-include-cleaner.IgnoreHeaders: 'errno\.h'
+...
diff --git a/src/bpf/.clangd b/src/bpf/.clangd
new file mode 100644
index 0000000000..ec2f81817b
--- /dev/null
+++ b/src/bpf/.clangd
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+Diagnostics:
+ Includes:
+ IgnoreHeader: [errno\.h]
diff --git a/src/core/bpf/bind-iface/bind-iface.bpf.c b/src/bpf/bind-iface.bpf.c
similarity index 100%
rename from src/core/bpf/bind-iface/bind-iface.bpf.c
rename to src/bpf/bind-iface.bpf.c
diff --git a/src/nsresourced/bpf/userns-restrict/userns-restrict-skel.h b/src/bpf/bpf-skel-wrapper.h.in
similarity index 78%
rename from src/nsresourced/bpf/userns-restrict/userns-restrict-skel.h
rename to src/bpf/bpf-skel-wrapper.h.in
index 7ed12dea95..3dc3cede3e 100644
--- a/src/nsresourced/bpf/userns-restrict/userns-restrict-skel.h
+++ b/src/bpf/bpf-skel-wrapper.h.in
@@ -7,12 +7,13 @@
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
+#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__attach_skeleton sym_bpf_object__attach_skeleton
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
+#define bpf_object__detach_skeleton sym_bpf_object__detach_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
-#include "bpf/userns-restrict/userns-restrict.skel.h" /* IWYU pragma: export */
+#include "@NAME@.bpf.skel.h" /* IWYU pragma: export */
diff --git a/src/bpf/merge-bpf-compdb.py b/src/bpf/merge-bpf-compdb.py
new file mode 100755
index 0000000000..c93e685afd
--- /dev/null
+++ b/src/bpf/merge-bpf-compdb.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import json
+import os
+import sys
+
+
+def main() -> int:
+ build_root = os.environ['MESON_BUILD_ROOT']
+
+ sep = sys.argv.index('--')
+ sources = sys.argv[1:sep]
+ command = sys.argv[sep + 1:]
+
+ db_path = os.path.join(build_root, 'compile_commands.json')
+ try:
+ with open(db_path) as f:
+ db = json.load(f)
+ except FileNotFoundError:
+ db = []
+
+ sources_set = set(sources)
+ db = [entry for entry in db if entry['file'] not in sources_set]
+
+ for source in sources:
+ db.append({
+ 'directory': build_root,
+ 'file': source,
+ 'arguments': [source if a == '@INPUT@' else a for a in command],
+ })
+
+ with open(db_path, 'w') as f:
+ json.dump(db, f, indent=2)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/bpf/meson.build b/src/bpf/meson.build
new file mode 100644
index 0000000000..32ab32e93d
--- /dev/null
+++ b/src/bpf/meson.build
@@ -0,0 +1,397 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+if not libbpf.found()
+ conf.set10('BPF_FRAMEWORK', false)
+else
+ clang_found = false
+ clang_supports_bpf = false
+ bpf_gcc_found = false
+ bpftool_strip = 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,
+ version : '>= 10.0.0')
+ clang_found = r.found()
+ if clang_found
+ clang = r.full_path()
+ endif
+ else
+ clang_found = true
+ clang = cc.cmd_array()
+ 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
+ endif
+ if bpf_framework.enabled() and not clang_supports_bpf
+ error('bpf-framework was enabled but clang does not support bpf')
+ endif
+ elif bpf_compiler == 'gcc'
+ bpf_gcc = find_program('bpf-gcc',
+ 'bpf-none-gcc',
+ 'bpf-unknown-none-gcc',
+ required : true,
+ version : '>= 13.1.0')
+ bpf_gcc_found = bpf_gcc.found()
+ endif
+
+ 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.enabled() and bpf_compiler == 'gcc',
+ version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
+
+ if bpftool.found()
+ bpftool_strip = true
+ deps_found = true
+ elif bpf_compiler == 'clang'
+ # We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
+ bpftool = find_program('bpftool',
+ '/usr/sbin/bpftool',
+ required : bpf_framework,
+ version : '>= 5.6.0')
+ endif
+
+ # 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,
+ 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)
+endif
+
+if conf.get('BPF_FRAMEWORK') == 1
+ bpf_clang_flags = [
+ '-std=gnu17',
+ '-Wno-compare-distinct-pointer-types',
+ '-Wno-microsoft-anon-tag',
+ '-fms-extensions',
+ '-fno-stack-protector',
+ '-O2',
+ '-target',
+ 'bpf',
+ '-g',
+ '-c',
+ ]
+
+ bpf_gcc_flags = [
+ '-std=gnu17',
+ '-fms-extensions',
+ '-fno-stack-protector',
+ '-fno-ssa-phiopt',
+ '-O2',
+ '-mcpu=v3',
+ '-mco-re',
+ '-gbtf',
+ '-c',
+ ]
+
+ # If c_args contains these flags copy them along with the values, in order to avoid breaking
+ # reproducible builds and other functionality
+ propagate_cflags = [
+ '-ffile-prefix-map=',
+ '-fdebug-prefix-map=',
+ '-fmacro-prefix-map=',
+ '--sysroot=',
+ ]
+
+ foreach opt : c_args
+ foreach flag : propagate_cflags
+ if opt.startswith(flag)
+ bpf_clang_flags += [opt]
+ bpf_gcc_flags += [opt]
+ break
+ endif
+ endforeach
+ endforeach
+
+ # 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 ____.
+ # This dictionary contains the exceptions where this doesn't work.
+ #
+ # C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
+ # and src/basic/missing_syscall_def.h.
+
+ # Start with older ABI. When define is missing, we're likely targeting that.
+ ppc64_elf_version = '1'
+
+ if host_machine.cpu_family() == 'ppc64'
+ # cc doesn't have to be bpf_compiler, but they should be targeting the same ABI
+ call_elf_value = cc.get_define('_CALL_ELF')
+ if call_elf_value != ''
+ ppc64_elf_version = call_elf_value
+ endif
+ endif
+
+ cpu_arch_defines = {
+ 'ppc' : ['-D__powerpc__', '-D__TARGET_ARCH_powerpc'],
+ 'ppc64' : ['-D__powerpc64__', '-D__TARGET_ARCH_powerpc', '-D_CALL_ELF=' + ppc64_elf_version],
+ 'riscv32' : ['-D__riscv', '-D__riscv_xlen=32', '-D__TARGET_ARCH_riscv'],
+ 'riscv64' : ['-D__riscv', '-D__riscv_xlen=64', '-D__TARGET_ARCH_riscv'],
+ 'x86' : ['-D__i386__', '-D__TARGET_ARCH_x86'],
+ 's390x' : ['-D__s390__', '-D__s390x__', '-D__TARGET_ARCH_s390'],
+
+ # For arm, assume hardware fp is available.
+ 'arm' : ['-D__arm__', '-D__ARM_PCS_VFP', '-D__TARGET_ARCH_arm'],
+ 'loongarch64' : ['-D__loongarch__', '-D__loongarch_grlen=64', '-D__TARGET_ARCH_loongarch']
+ }
+
+ 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 = []
+ 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.', '-include', 'config.h']
+
+ if cc.get_id() == 'gcc' or meson.is_cross_build()
+ if cc.get_id() != 'gcc'
+ warning('Cross compiler is not gcc. Guessing the target triplet for bpf likely fails.')
+ endif
+ target_triplet_cmd = run_command(cc.cmd_array(), '-print-multiarch', check: false)
+ else
+ # clang does not support -print-multiarch (D133170) and its -dump-machine
+ # does not match multiarch. Query gcc instead.
+ target_triplet_cmd = run_command('gcc', '-print-multiarch', check: false)
+ endif
+ if target_triplet_cmd.returncode() == 0
+ sysroot = meson.get_external_property('sys_root', '/')
+ target_triplet = target_triplet_cmd.stdout().strip()
+ target_include_dir = sysroot / 'usr' / 'include'
+ target_triple_include_dir = target_include_dir / target_triplet
+ isystem_dir = ''
+ if fs.is_dir(target_triple_include_dir)
+ isystem_dir = target_triple_include_dir
+ elif fs.is_dir(target_include_dir)
+ isystem_dir = target_include_dir
+ endif
+ if isystem_dir != ''
+ bpf_o_unstripped_cmd += [
+ '-isystem', isystem_dir
+ ]
+ endif
+ endif
+
+ bpf_o_unstripped_cmd += [
+ '-idirafter',
+ libbpf_include_dir,
+ '@INPUT@',
+ '-o',
+ '@OUTPUT@'
+ ]
+
+ if bpftool_strip
+ bpf_o_cmd = [
+ bpftool,
+ 'gen',
+ 'object',
+ '@OUTPUT@',
+ '@INPUT@'
+ ]
+ elif bpf_compiler == 'clang'
+ bpf_o_cmd = [
+ llvm_strip,
+ '-g',
+ '@INPUT@',
+ '-o',
+ '@OUTPUT@'
+ ]
+ endif
+
+ skel_h_cmd = [
+ bpftool,
+ 'gen',
+ 'skeleton',
+ '@INPUT@'
+ ]
+endif
+
+use_provided_vmlinux_h = false
+use_generated_vmlinux_h = false
+provided_vmlinux_h_path = get_option('vmlinux-h-path')
+
+# For the more complex BPF programs we really want a vmlinux.h (which is arch
+# specific, but only somewhat bound to kernel version). Ideally the kernel
+# development headers would ship that, but right now they don't. Hence address
+# this in two ways:
+#
+# 1. Provide a vmlinux.h at build time
+# 2. Generate the file on the fly where possible (which requires /sys/ to be mounted)
+#
+# We generally prefer the former (to support reproducible builds), but will
+# fallback to the latter.
+
+if conf.get('BPF_FRAMEWORK') == 1
+ enable_vmlinux_h = get_option('vmlinux-h')
+
+ if enable_vmlinux_h == 'auto'
+ if provided_vmlinux_h_path != ''
+ use_provided_vmlinux_h = true
+ elif fs.exists('/sys/kernel/btf/vmlinux') and \
+ bpftool.found() and \
+ (host_machine.cpu_family() == build_machine.cpu_family()) and \
+ host_machine.cpu_family() in ['x86_64', 'aarch64']
+
+ # We will only generate a vmlinux.h from the running
+ # kernel if the host and build machine are of the same
+ # family. Also for now we focus on x86_64 and aarch64,
+ # since other archs don't seem to be ready yet.
+
+ use_generated_vmlinux_h = true
+ endif
+ elif enable_vmlinux_h == 'provided'
+ use_provided_vmlinux_h = true
+ elif enable_vmlinux_h == 'generated'
+ if not fs.exists('/sys/kernel/btf/vmlinux')
+ error('BTF data from kernel not available (/sys/kernel/btf/vmlinux missing), cannot generate vmlinux.h, but was asked to.')
+ endif
+ if not bpftool.found()
+ error('bpftool not available, cannot generate vmlinux.h, but was asked to.')
+ endif
+ use_generated_vmlinux_h = true
+ endif
+endif
+
+vmlinux_h_dependency = []
+if use_provided_vmlinux_h
+ if not fs.exists(provided_vmlinux_h_path)
+ error('Path to provided vmlinux.h does not exist.')
+ endif
+ bpf_o_unstripped_cmd += ['-I' + fs.parent(provided_vmlinux_h_path)]
+ message(f'Using provided @provided_vmlinux_h_path@')
+elif use_generated_vmlinux_h
+ vmlinux_h_dependency = custom_target(
+ output: 'vmlinux.h',
+ command : [ bpftool, 'btf', 'dump', 'file', '/sys/kernel/btf/vmlinux', 'format', 'c' ],
+ capture : true)
+
+ bpf_o_unstripped_cmd += ['-I' + fs.parent(vmlinux_h_dependency.full_path())]
+ generated_sources += vmlinux_h_dependency
+ message('Using generated @0@'.format(vmlinux_h_dependency.full_path()))
+else
+ message('Using neither provided nor generated vmlinux.h, some features will not be available.')
+endif
+
+conf.set10('HAVE_VMLINUX_H', use_provided_vmlinux_h or use_generated_vmlinux_h)
+
+conf.set10('ENABLE_SYSCTL_BPF', conf.get('HAVE_VMLINUX_H') == 1 and libbpf.version().version_compare('>= 0.7'))
+
+bpf_programs = [
+ {
+ 'source' : files('bind-iface.bpf.c'),
+ 'condition' : 'BPF_FRAMEWORK',
+ },
+ {
+ 'source' : files('restrict-fs.bpf.c'),
+ 'condition' : 'BPF_FRAMEWORK',
+ },
+ {
+ 'source' : files('restrict-ifaces.bpf.c'),
+ 'condition' : 'BPF_FRAMEWORK',
+ },
+ {
+ 'source' : files('socket-bind.bpf.c'),
+ 'condition' : 'BPF_FRAMEWORK',
+ },
+ {
+ 'source' : files('sysctl-monitor.bpf.c'),
+ 'condition' : 'ENABLE_SYSCTL_BPF',
+ 'depends' : vmlinux_h_dependency,
+ },
+ {
+ 'source' : files('userns-restrict.bpf.c'),
+ 'condition' : 'HAVE_VMLINUX_H',
+ 'depends' : vmlinux_h_dependency,
+ },
+]
+
+bpf_programs_by_name = {}
+bpf_sources = []
+
+foreach program : bpf_programs
+ if conf.get(program['condition']) != 1
+ continue
+ endif
+
+ source = program['source'][0]
+ # Strip .bpf.c extension
+ name = fs.stem(fs.stem(source))
+
+ bpf_o_unstripped = custom_target(
+ input : source,
+ output : name + '.bpf.unstripped.o',
+ command : bpf_o_unstripped_cmd,
+ depends : program.get('depends', []))
+
+ bpf_o = custom_target(
+ input : bpf_o_unstripped,
+ output : name + '.bpf.o',
+ command : bpf_o_cmd)
+
+ skel_h = custom_target(
+ input : bpf_o,
+ output : name + '.bpf.skel.h',
+ command : skel_h_cmd,
+ capture : true)
+
+ # The wrapper is written at meson setup time and found via the
+ # include path, so we don't need to list it as a build-time source.
+ # Keeping it out of bpf_programs_by_name also keeps it out of the
+ # clang-tidy per-source test loop, which would otherwise fall back
+ # to a BPF compile_commands.json entry (no -Isrc/shared) and fail
+ # to resolve bpf-dlopen.h.
+ configure_file(
+ input : 'bpf-skel-wrapper.h.in',
+ output : name + '-skel.h',
+ configuration : { 'NAME' : name })
+
+ bpf_programs_by_name += { name : skel_h }
+ generated_sources += skel_h
+ bpf_sources += source
+endforeach
+
+if bpf_sources.length() > 0
+ meson.add_postconf_script(
+ python,
+ files('merge-bpf-compdb.py'),
+ bpf_sources,
+ '--',
+ bpf_o_unstripped_cmd)
+endif
diff --git a/src/core/bpf/restrict-fs/restrict-fs.bpf.c b/src/bpf/restrict-fs.bpf.c
similarity index 100%
rename from src/core/bpf/restrict-fs/restrict-fs.bpf.c
rename to src/bpf/restrict-fs.bpf.c
diff --git a/src/core/bpf/restrict-ifaces/restrict-ifaces.bpf.c b/src/bpf/restrict-ifaces.bpf.c
similarity index 100%
rename from src/core/bpf/restrict-ifaces/restrict-ifaces.bpf.c
rename to src/bpf/restrict-ifaces.bpf.c
diff --git a/src/core/bpf/socket-bind/socket-bind-api.bpf.h b/src/bpf/socket-bind-api.bpf.h
similarity index 100%
rename from src/core/bpf/socket-bind/socket-bind-api.bpf.h
rename to src/bpf/socket-bind-api.bpf.h
diff --git a/src/core/bpf/socket-bind/socket-bind.bpf.c b/src/bpf/socket-bind.bpf.c
similarity index 100%
rename from src/core/bpf/socket-bind/socket-bind.bpf.c
rename to src/bpf/socket-bind.bpf.c
diff --git a/src/network/bpf/sysctl-monitor/sysctl-monitor.bpf.c b/src/bpf/sysctl-monitor.bpf.c
similarity index 100%
rename from src/network/bpf/sysctl-monitor/sysctl-monitor.bpf.c
rename to src/bpf/sysctl-monitor.bpf.c
diff --git a/src/network/bpf/sysctl-monitor/sysctl-write-event.h b/src/bpf/sysctl-write-event.h
similarity index 94%
rename from src/network/bpf/sysctl-monitor/sysctl-write-event.h
rename to src/bpf/sysctl-write-event.h
index 77b71fb4f9..c0603638d9 100644
--- a/src/network/bpf/sysctl-monitor/sysctl-write-event.h
+++ b/src/bpf/sysctl-write-event.h
@@ -2,6 +2,13 @@
#pragma once
+#ifdef __bpf__
+#include "vmlinux.h"
+#else
+#include
+#include
+#endif
+
#ifndef TASK_COMM_LEN
#define TASK_COMM_LEN 16
#endif
diff --git a/src/nsresourced/bpf/userns-restrict/userns-restrict.bpf.c b/src/bpf/userns-restrict.bpf.c
similarity index 99%
rename from src/nsresourced/bpf/userns-restrict/userns-restrict.bpf.c
rename to src/bpf/userns-restrict.bpf.c
index d70493fe7a..54473d7210 100644
--- a/src/nsresourced/bpf/userns-restrict/userns-restrict.bpf.c
+++ b/src/bpf/userns-restrict.bpf.c
@@ -15,7 +15,7 @@
#include "vmlinux.h"
-#include
+#include /* IWYU pragma: keep */
#include
#include
#include
diff --git a/src/core/bpf-bind-iface.c b/src/core/bpf-bind-iface.c
index fdd2e1d8e6..74cb2b3d52 100644
--- a/src/core/bpf-bind-iface.c
+++ b/src/core/bpf-bind-iface.c
@@ -14,7 +14,7 @@
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
-#include "bpf/bind-iface/bind-iface-skel.h"
+#include "bind-iface-skel.h"
static struct bind_iface_bpf *bind_iface_bpf_free(struct bind_iface_bpf *obj) {
bind_iface_bpf__destroy(obj);
@@ -31,7 +31,7 @@ int bpf_bind_network_interface_supported(void) {
if (supported >= 0)
return supported;
- if (dlopen_bpf_full(LOG_WARNING) < 0)
+ if (dlopen_bpf(LOG_WARNING) < 0)
return (supported = false);
obj = bind_iface_bpf__open();
diff --git a/src/core/bpf-restrict-fs.c b/src/core/bpf-restrict-fs.c
index 8df2f5235c..e60e6ca7ef 100644
--- a/src/core/bpf-restrict-fs.c
+++ b/src/core/bpf-restrict-fs.c
@@ -17,7 +17,7 @@
/* libbpf, clang and llc compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
-#include "bpf/restrict-fs/restrict-fs-skel.h"
+#include "restrict-fs-skel.h"
#define CGROUP_HASH_SIZE_MAX 2048
@@ -91,7 +91,7 @@ bool bpf_restrict_fs_supported(bool initialize) {
if (!initialize)
return false;
- if (dlopen_bpf_full(LOG_WARNING) < 0)
+ if (dlopen_bpf(LOG_WARNING) < 0)
return (supported = false);
r = lsm_supported("bpf");
diff --git a/src/core/bpf-restrict-ifaces.c b/src/core/bpf-restrict-ifaces.c
index a1bac8301b..3c73a682a3 100644
--- a/src/core/bpf-restrict-ifaces.c
+++ b/src/core/bpf-restrict-ifaces.c
@@ -16,7 +16,7 @@
#include "bpf-dlopen.h"
#include "bpf-link.h"
-#include "bpf/restrict-ifaces/restrict-ifaces-skel.h"
+#include "restrict-ifaces-skel.h"
static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) {
restrict_ifaces_bpf__destroy(obj);
@@ -86,7 +86,7 @@ int bpf_restrict_ifaces_supported(void) {
if (supported >= 0)
return supported;
- if (dlopen_bpf_full(LOG_WARNING) < 0)
+ if (dlopen_bpf(LOG_WARNING) < 0)
return (supported = false);
r = prepare_restrict_ifaces_bpf(NULL, true, NULL, &obj);
diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c
index b7158841fa..87e7d60c05 100644
--- a/src/core/bpf-socket-bind.c
+++ b/src/core/bpf-socket-bind.c
@@ -11,8 +11,8 @@
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
-#include "bpf/socket-bind/socket-bind-api.bpf.h"
-#include "bpf/socket-bind/socket-bind-skel.h"
+#include "socket-bind-api.bpf.h"
+#include "socket-bind-skel.h"
static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
/* socket_bind_bpf__destroy handles object == NULL case */
@@ -125,7 +125,7 @@ int bpf_socket_bind_supported(void) {
_cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL;
int r;
- if (dlopen_bpf_full(LOG_WARNING) < 0)
+ if (dlopen_bpf(LOG_WARNING) < 0)
return false;
r = prepare_socket_bind_bpf(/* unit= */ NULL, /* allow_rules= */ NULL, /* deny_rules= */ NULL, &obj);
diff --git a/src/core/bpf/bind-iface/bind-iface-skel.h b/src/core/bpf/bind-iface/bind-iface-skel.h
deleted file mode 100644
index 2ec63ca887..0000000000
--- a/src/core/bpf/bind-iface/bind-iface-skel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/* The SPDX header above is actually correct in claiming this was
- * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
- * compatible with GPL we will claim this to be GPL however, which should be
- * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
- */
-
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
-
-/* libbpf is used via dlopen(), so rename symbols */
-#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
-#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
-#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
-
-#include "bpf/bind-iface/bind-iface.skel.h" /* IWYU pragma: export */
diff --git a/src/core/bpf/bind-iface/meson.build b/src/core/bpf/bind-iface/meson.build
deleted file mode 100644
index 222cac16b0..0000000000
--- a/src/core/bpf/bind-iface/meson.build
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-if conf.get('BPF_FRAMEWORK') != 1
- subdir_done()
-endif
-
-bind_network_interface_bpf_o_unstripped = custom_target(
- input : 'bind-iface.bpf.c',
- output : 'bind-iface.bpf.unstripped.o',
- command : bpf_o_unstripped_cmd)
-
-bind_network_interface_bpf_o = custom_target(
- input : bind_network_interface_bpf_o_unstripped,
- output : 'bind-iface.bpf.o',
- command : bpf_o_cmd)
-
-bind_network_interface_skel_h = custom_target(
- input : bind_network_interface_bpf_o,
- output : 'bind-iface.skel.h',
- command : skel_h_cmd,
- capture : true)
-
-generated_sources += bind_network_interface_skel_h
diff --git a/src/core/bpf/restrict-fs/meson.build b/src/core/bpf/restrict-fs/meson.build
deleted file mode 100644
index 41fc130ace..0000000000
--- a/src/core/bpf/restrict-fs/meson.build
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-if conf.get('BPF_FRAMEWORK') != 1
- subdir_done()
-endif
-
-restrict_fs_bpf_o_unstripped = custom_target(
- input : 'restrict-fs.bpf.c',
- output : 'restrict-fs.bpf.unstripped.o',
- command : bpf_o_unstripped_cmd)
-
-restrict_fs_bpf_o = custom_target(
- input : restrict_fs_bpf_o_unstripped,
- output : 'restrict-fs.bpf.o',
- command : bpf_o_cmd)
-
-restrict_fs_skel_h = custom_target(
- input : restrict_fs_bpf_o,
- output : 'restrict-fs.skel.h',
- command : skel_h_cmd,
- capture : true)
-
-generated_sources += restrict_fs_skel_h
diff --git a/src/core/bpf/restrict-fs/restrict-fs-skel.h b/src/core/bpf/restrict-fs/restrict-fs-skel.h
deleted file mode 100644
index 06935f2cd8..0000000000
--- a/src/core/bpf/restrict-fs/restrict-fs-skel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/* The SPDX header above is actually correct in claiming this was
- * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
- * compatible with GPL we will claim this to be GPL however, which should be
- * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
- */
-
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
-
-/* libbpf is used via dlopen(), so rename symbols */
-#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
-#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
-#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
-
-#include "bpf/restrict-fs/restrict-fs.skel.h" /* IWYU pragma: export */
diff --git a/src/core/bpf/restrict-ifaces/meson.build b/src/core/bpf/restrict-ifaces/meson.build
deleted file mode 100644
index f9ef4c753e..0000000000
--- a/src/core/bpf/restrict-ifaces/meson.build
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-if conf.get('BPF_FRAMEWORK') != 1
- subdir_done()
-endif
-
-restrict_ifaces_bpf_o_unstripped = custom_target(
- input : 'restrict-ifaces.bpf.c',
- output : 'restrict-ifaces.bpf.unstripped.o',
- command : bpf_o_unstripped_cmd)
-
-restrict_ifaces_bpf_o = custom_target(
- input : restrict_ifaces_bpf_o_unstripped,
- output : 'restrict-ifaces.bpf.o',
- command : bpf_o_cmd)
-
-restrict_ifaces_skel_h = custom_target(
- input : restrict_ifaces_bpf_o,
- output : 'restrict-ifaces.skel.h',
- command : skel_h_cmd,
- capture : true)
-
-generated_sources += restrict_ifaces_skel_h
diff --git a/src/core/bpf/restrict-ifaces/restrict-ifaces-skel.h b/src/core/bpf/restrict-ifaces/restrict-ifaces-skel.h
deleted file mode 100644
index 53ba2e5b5a..0000000000
--- a/src/core/bpf/restrict-ifaces/restrict-ifaces-skel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/* The SPDX header above is actually correct in claiming this was
- * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
- * compatible with GPL we will claim this to be GPL however, which should be
- * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
- */
-
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
-
-/* libbpf is used via dlopen(), so rename symbols */
-#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
-#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
-#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
-
-#include "bpf/restrict-ifaces/restrict-ifaces.skel.h" /* IWYU pragma: export */
diff --git a/src/core/bpf/socket-bind/meson.build b/src/core/bpf/socket-bind/meson.build
deleted file mode 100644
index ec9d34637b..0000000000
--- a/src/core/bpf/socket-bind/meson.build
+++ /dev/null
@@ -1,23 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-if conf.get('BPF_FRAMEWORK') != 1
- subdir_done()
-endif
-
-socket_bind_bpf_o_unstripped = custom_target(
- input : 'socket-bind.bpf.c',
- output : 'socket-bind.bpf.unstripped.o',
- command : bpf_o_unstripped_cmd)
-
-socket_bind_bpf_o = custom_target(
- input : socket_bind_bpf_o_unstripped,
- output : 'socket-bind.bpf.o',
- command : bpf_o_cmd)
-
-socket_bind_skel_h = custom_target(
- input : socket_bind_bpf_o,
- output : 'socket-bind.skel.h',
- command : skel_h_cmd,
- capture : true)
-
-generated_sources += socket_bind_skel_h
diff --git a/src/core/bpf/socket-bind/socket-bind-skel.h b/src/core/bpf/socket-bind/socket-bind-skel.h
deleted file mode 100644
index d83dd89e52..0000000000
--- a/src/core/bpf/socket-bind/socket-bind-skel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/* The SPDX header above is actually correct in claiming this was
- * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
- * compatible with GPL we will claim this to be GPL however, which should be
- * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
- */
-
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
-
-/* libbpf is used via dlopen(), so rename symbols */
-#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
-#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
-#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
-
-#include "bpf/socket-bind/socket-bind.skel.h" /* IWYU pragma: export */
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 5a7f70d78b..1bc73e7b43 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -387,13 +387,16 @@ static int property_set_pretimeout_watchdog_governor(
sd_bus_error *reterr_error) {
Manager *m = ASSERT_PTR(userdata);
- char *governor;
+ const char *governor;
int r;
r = sd_bus_message_read(value, "s", &governor);
if (r < 0)
return r;
- if (!string_is_safe(governor))
+
+ if (isempty(governor))
+ governor = NULL;
+ else if (!string_is_safe(governor, /* flags= */ 0))
return -EINVAL;
return manager_override_watchdog_pretimeout_governor(m, governor);
diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c
index c663532e00..8c8502ffab 100644
--- a/src/core/exec-invoke.c
+++ b/src/core/exec-invoke.c
@@ -1359,9 +1359,9 @@ static int setup_pam(
* parent process will exec() the actual daemon. We do things this way to ensure that the main PID of
* the daemon is the one we initially fork()ed. */
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "PAM support not available: %m");
+ return r;
r = barrier_create(&barrier);
if (r < 0)
@@ -1625,7 +1625,7 @@ static bool seccomp_allows_drop_privileges(const ExecContext *c) {
assert(c);
/* No libseccomp, all is fine */
- if (dlopen_libseccomp() < 0)
+ if (dlopen_libseccomp(LOG_DEBUG) < 0)
return true;
/* No syscall filter, we are allowed to drop privileges */
@@ -1927,7 +1927,7 @@ static int apply_restrict_filesystems(const ExecContext *c, const ExecParameters
}
/* We are in a new binary, so dl-open again */
- r = dlopen_bpf();
+ r = dlopen_bpf(LOG_DEBUG);
if (r < 0)
return r;
@@ -6026,10 +6026,10 @@ int exec_invoke(
}
/* Load a bunch of libraries we'll possibly need later, before we turn off dlopen() */
- (void) dlopen_bpf();
- (void) dlopen_cryptsetup();
- (void) dlopen_libmount();
- (void) dlopen_libseccomp();
+ (void) dlopen_bpf(LOG_DEBUG);
+ (void) dlopen_cryptsetup(LOG_DEBUG);
+ (void) dlopen_libmount(LOG_DEBUG);
+ (void) dlopen_libseccomp(LOG_DEBUG);
/* Let's now disable further dlopen()ing of libraries, since we are about to do namespace
* shenanigans, and do not want to mix resources from host and namespace */
diff --git a/src/core/execute.c b/src/core/execute.c
index dea0699ba4..cfd63fe303 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1491,7 +1491,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
fputc('~', f);
#if HAVE_SECCOMP
- if (dlopen_libseccomp() >= 0) {
+ if (dlopen_libseccomp(LOG_DEBUG) >= 0) {
void *id, *val;
bool first = true;
HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) {
@@ -1910,7 +1910,7 @@ char** exec_context_get_syscall_filter(const ExecContext *c) {
assert(c);
#if HAVE_SECCOMP
- if (dlopen_libseccomp() < 0)
+ if (dlopen_libseccomp(LOG_DEBUG) < 0)
return strv_new(NULL);
void *id, *val;
@@ -1979,7 +1979,7 @@ char** exec_context_get_syscall_log(const ExecContext *c) {
assert(c);
#if HAVE_SECCOMP
- if (dlopen_libseccomp() < 0)
+ if (dlopen_libseccomp(LOG_DEBUG) < 0)
return strv_new(NULL);
void *id, *val;
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 52005c8c43..1fae521333 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -990,7 +990,7 @@ int config_parse_exec(
ignore ? ", ignoring" : "", rvalue);
return ignore ? 0 : -ENOEXEC;
}
- if (!string_is_safe(path)) {
+ if (!string_is_safe(path, /* flags= */ 0)) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0,
"Executable path contains special characters%s: %s",
ignore ? ", ignoring" : "", path);
diff --git a/src/core/main.c b/src/core/main.c
index b4022105e8..3bdce441a8 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -502,7 +502,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return 0;
}
- if (!string_is_safe(value)) {
+ if (!string_is_safe(value, /* flags= */ 0)) {
log_warning("Watchdog pretimeout governor '%s' is not valid, ignoring.", value);
return 0;
}
@@ -3378,7 +3378,7 @@ int main(int argc, char *argv[]) {
}
/* Building without libmount is allowed, but if it is compiled in, then we must be able to load it */
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0 && !ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
error_message = "Failed to load libmount.so";
goto finish;
diff --git a/src/core/manager.c b/src/core/manager.c
index 01841a97d6..56ee66e5bd 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -3576,12 +3576,14 @@ int manager_set_watchdog_pretimeout_governor(Manager *m, const char *governor) {
if (MANAGER_IS_USER(m))
return 0;
+ governor = empty_to_null(governor);
+
if (streq_ptr(m->watchdog_pretimeout_governor, governor))
return 0;
- p = strdup(governor);
- if (!p)
- return -ENOMEM;
+ r = strdup_to(&p, governor);
+ if (r < 0)
+ return r;
r = watchdog_setup_pretimeout_governor(governor);
if (r < 0)
@@ -3599,12 +3601,14 @@ int manager_override_watchdog_pretimeout_governor(Manager *m, const char *govern
if (MANAGER_IS_USER(m))
return 0;
+ governor = empty_to_null(governor);
+
if (streq_ptr(m->watchdog_pretimeout_governor_overridden, governor))
return 0;
- p = strdup(governor);
- if (!p)
- return -ENOMEM;
+ r = strdup_to(&p, governor);
+ if (r < 0)
+ return r;
r = watchdog_setup_pretimeout_governor(governor);
if (r < 0)
diff --git a/src/core/meson.build b/src/core/meson.build
index 391dc45a6b..d24fc3b6d3 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -64,26 +64,22 @@ libcore_sources = files(
'unit-serialize.c',
'unit.c',
'varlink.c',
+ 'varlink-automount.c',
'varlink-cgroup.c',
'varlink-common.c',
'varlink-dynamic-user.c',
'varlink-execute.c',
+ 'varlink-kill.c',
'varlink-manager.c',
'varlink-metrics.c',
+ 'varlink-mount.c',
'varlink-unit.c',
)
-subdir('bpf/socket-bind')
-subdir('bpf/restrict-fs')
-subdir('bpf/restrict-ifaces')
-subdir('bpf/bind-iface')
-
if conf.get('BPF_FRAMEWORK') == 1
- libcore_sources += [
- socket_bind_skel_h,
- restrict_fs_skel_h,
- restrict_ifaces_skel_h,
- bind_network_interface_skel_h]
+ foreach name : ['socket-bind', 'restrict-fs', 'restrict-ifaces', 'bind-iface']
+ libcore_sources += bpf_programs_by_name[name]
+ endforeach
endif
sources += libcore_sources
diff --git a/src/core/mount.c b/src/core/mount.c
index 46e157af20..967274b950 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -2408,7 +2408,7 @@ static int mount_test_startable(Unit *u) {
}
static bool mount_supported(void) {
- return dlopen_libmount() >= 0;
+ return dlopen_libmount(LOG_DEBUG) >= 0;
}
static int mount_subsystem_ratelimited(Manager *m) {
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 1412ccce8b..b07b1082ed 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1049,7 +1049,7 @@ static bool verity_has_later_duplicates(MountList *ml, const MountEntry *needle)
for (const MountEntry *m = needle + 1; m < ml->mounts + ml->n_mounts; m++) {
if (m->mode != MOUNT_EXTENSION_IMAGE)
continue;
- if (iovec_memcmp(&m->verity.root_hash, &needle->verity.root_hash) == 0)
+ if (iovec_equal(&m->verity.root_hash, &needle->verity.root_hash))
return true;
}
@@ -3984,7 +3984,7 @@ int refresh_extensions_in_namespace(
if (r > 0)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Target namespace is not separate, cannot reload extensions");
- (void) dlopen_cryptsetup();
+ (void) dlopen_cryptsetup(LOG_DEBUG);
extension_dir = path_join(p->private_namespace_dir, "unit-extensions");
if (!extension_dir)
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index 17905de2c7..d06c9f0293 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -17,11 +17,9 @@ int mac_selinux_setup(bool *loaded_policy) {
assert(loaded_policy);
- r = dlopen_libselinux();
- if (r < 0) {
- log_debug_errno(r, "No SELinux library available, skipping setup.");
+ r = dlopen_libselinux(LOG_DEBUG);
+ if (r < 0)
return 0;
- }
mac_selinux_disable_logging();
diff --git a/src/core/service.c b/src/core/service.c
index aa00413dc3..4e1d1d38d0 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -5210,7 +5210,7 @@ static void service_notify_message(
e = empty_to_null(e);
- if (e && !string_is_safe_ascii(e)) {
+ if (e && !string_is_safe(e, STRING_ASCII)) {
_cleanup_free_ char *escaped = cescape(e);
log_unit_warning(u, "Got invalid %s string, ignoring: %s", i->tag, strna(escaped));
} else if (free_and_strdup_warn(status_error, e) > 0)
diff --git a/src/core/varlink-automount.c b/src/core/varlink-automount.c
new file mode 100644
index 0000000000..2bb5fa397d
--- /dev/null
+++ b/src/core/varlink-automount.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-json.h"
+
+#include "automount.h"
+#include "json-util.h"
+#include "varlink-automount.h"
+
+int automount_context_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Automount *a = ASSERT_PTR(AUTOMOUNT(userdata));
+ return sd_json_buildo(
+ ASSERT_PTR(ret),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Where", a->where),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("ExtraOptions", a->extra_options),
+ SD_JSON_BUILD_PAIR_UNSIGNED("DirectoryMode", a->directory_mode),
+ JSON_BUILD_PAIR_FINITE_USEC("TimeoutIdleUSec", a->timeout_idle_usec));
+}
+
+int automount_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Automount *a = ASSERT_PTR(AUTOMOUNT(userdata));
+ return sd_json_buildo(ASSERT_PTR(ret), JSON_BUILD_PAIR_ENUM("Result", automount_result_to_string(a->result)));
+}
diff --git a/src/core/varlink-automount.h b/src/core/varlink-automount.h
new file mode 100644
index 0000000000..892f8ba65b
--- /dev/null
+++ b/src/core/varlink-automount.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "core-forward.h"
+
+int automount_context_build_json(sd_json_variant **ret, const char *name, void *userdata);
+int automount_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata);
diff --git a/src/core/varlink-common.c b/src/core/varlink-common.c
index e388b16339..bdef4d5a94 100644
--- a/src/core/varlink-common.c
+++ b/src/core/varlink-common.c
@@ -4,6 +4,7 @@
#include "bus-common-errors.h"
#include "cpu-set-util.h"
+#include "execute.h"
#include "json-util.h"
#include "rlimit-util.h"
#include "varlink-common.h"
@@ -104,3 +105,24 @@ empty:
*ret = NULL;
return 0;
}
+
+int exec_command_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ ExecCommand *cmd = ASSERT_PTR(userdata);
+
+ assert(ret);
+
+ if (isempty(cmd->path)) {
+ *ret = NULL;
+ return 0;
+ }
+
+ return sd_json_buildo(
+ ret,
+ SD_JSON_BUILD_PAIR_STRING("path", cmd->path),
+ JSON_BUILD_PAIR_STRV_NON_EMPTY("arguments", cmd->argv),
+ SD_JSON_BUILD_PAIR_BOOLEAN("ignoreFailure", FLAGS_SET(cmd->flags, EXEC_COMMAND_IGNORE_FAILURE)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("privileged", FLAGS_SET(cmd->flags, EXEC_COMMAND_FULLY_PRIVILEGED)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("noSetuid", FLAGS_SET(cmd->flags, EXEC_COMMAND_NO_SETUID)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("noEnvExpand", FLAGS_SET(cmd->flags, EXEC_COMMAND_NO_ENV_EXPAND)),
+ SD_JSON_BUILD_PAIR_BOOLEAN("viaShell", FLAGS_SET(cmd->flags, EXEC_COMMAND_VIA_SHELL)));
+}
diff --git a/src/core/varlink-common.h b/src/core/varlink-common.h
index 82d1458dd9..fc919dcf36 100644
--- a/src/core/varlink-common.h
+++ b/src/core/varlink-common.h
@@ -6,5 +6,5 @@
int rlimit_build_json(sd_json_variant **ret, const char *name, void *userdata);
int rlimit_table_build_json(sd_json_variant **ret, const char *name, void *userdata);
int cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata);
-
const char* varlink_error_id_from_bus_error(const sd_bus_error *e);
+int exec_command_build_json(sd_json_variant **ret, const char *name, void *userdata);
diff --git a/src/core/varlink-kill.c b/src/core/varlink-kill.c
new file mode 100644
index 0000000000..8b48da098a
--- /dev/null
+++ b/src/core/varlink-kill.c
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-json.h"
+
+#include "json-util.h"
+#include "kill.h"
+#include "signal-util.h"
+#include "varlink-kill.h"
+
+int unit_kill_context_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ KillContext *c = userdata;
+
+ assert(ret);
+
+ if (!c) {
+ *ret = NULL;
+ return 0;
+ }
+
+ return sd_json_buildo(
+ ret,
+ JSON_BUILD_PAIR_ENUM("KillMode", kill_mode_to_string(c->kill_mode)),
+ SD_JSON_BUILD_PAIR_STRING("KillSignal", signal_to_string(c->kill_signal)),
+ SD_JSON_BUILD_PAIR_STRING("RestartKillSignal", signal_to_string(restart_kill_signal(c))),
+ SD_JSON_BUILD_PAIR_BOOLEAN("SendSIGHUP", c->send_sighup),
+ SD_JSON_BUILD_PAIR_BOOLEAN("SendSIGKILL", c->send_sigkill),
+ SD_JSON_BUILD_PAIR_STRING("FinalKillSignal", signal_to_string(c->final_kill_signal)),
+ SD_JSON_BUILD_PAIR_STRING("WatchdogSignal", signal_to_string(c->watchdog_signal)));
+}
diff --git a/src/core/varlink-kill.h b/src/core/varlink-kill.h
new file mode 100644
index 0000000000..a894e89ad6
--- /dev/null
+++ b/src/core/varlink-kill.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "core-forward.h"
+
+int unit_kill_context_build_json(sd_json_variant **ret, const char *name, void *userdata);
diff --git a/src/core/varlink-mount.c b/src/core/varlink-mount.c
new file mode 100644
index 0000000000..f4148cafb3
--- /dev/null
+++ b/src/core/varlink-mount.c
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-json.h"
+
+#include "json-util.h"
+#include "mount.h"
+#include "user-util.h"
+#include "varlink-common.h"
+#include "varlink-mount.h"
+
+int mount_context_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Mount *m = ASSERT_PTR(MOUNT(userdata));
+ _cleanup_free_ char *what = NULL, *where = NULL, *options = NULL;
+
+ what = mount_get_what_escaped(m);
+ if (!what)
+ return -ENOMEM;
+
+ where = mount_get_where_escaped(m);
+ if (!where)
+ return -ENOMEM;
+
+ options = mount_get_options_escaped(m);
+ if (!options)
+ return -ENOMEM;
+
+ return sd_json_buildo(
+ ASSERT_PTR(ret),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("What", what),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Where", where),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Type", mount_get_fstype(m)),
+ JSON_BUILD_PAIR_STRING_NON_EMPTY("Options", options),
+ SD_JSON_BUILD_PAIR_BOOLEAN("SloppyOptions", m->sloppy_options),
+ SD_JSON_BUILD_PAIR_BOOLEAN("LazyUnmount", m->lazy_unmount),
+ SD_JSON_BUILD_PAIR_BOOLEAN("ReadWriteOnly", m->read_write_only),
+ SD_JSON_BUILD_PAIR_BOOLEAN("ForceUnmount", m->force_unmount),
+ SD_JSON_BUILD_PAIR_UNSIGNED("DirectoryMode", m->directory_mode),
+ JSON_BUILD_PAIR_FINITE_USEC("TimeoutUSec", m->timeout_usec),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("ExecMount", exec_command_build_json, &m->exec_command[MOUNT_EXEC_MOUNT]),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("ExecUnmount", exec_command_build_json, &m->exec_command[MOUNT_EXEC_UNMOUNT]),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("ExecRemount", exec_command_build_json, &m->exec_command[MOUNT_EXEC_REMOUNT]));
+}
+
+int mount_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) {
+ Unit *u = ASSERT_PTR(userdata);
+ Mount *m = ASSERT_PTR(MOUNT(u));
+ return sd_json_buildo(
+ ASSERT_PTR(ret),
+ SD_JSON_BUILD_PAIR_CONDITION(pidref_is_set(&m->control_pid), "ControlPID", JSON_BUILD_PIDREF(&m->control_pid)),
+ JSON_BUILD_PAIR_ENUM("Result", mount_result_to_string(m->result)),
+ JSON_BUILD_PAIR_ENUM("ReloadResult", mount_result_to_string(m->reload_result)),
+ JSON_BUILD_PAIR_ENUM("CleanResult", mount_result_to_string(m->clean_result)),
+ SD_JSON_BUILD_PAIR_CONDITION(uid_is_valid(u->ref_uid), "UID", SD_JSON_BUILD_UNSIGNED(u->ref_uid)),
+ SD_JSON_BUILD_PAIR_CONDITION(gid_is_valid(u->ref_gid), "GID", SD_JSON_BUILD_UNSIGNED(u->ref_gid)));
+}
diff --git a/src/core/varlink-mount.h b/src/core/varlink-mount.h
new file mode 100644
index 0000000000..30fd92781a
--- /dev/null
+++ b/src/core/varlink-mount.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "core-forward.h"
+
+int mount_context_build_json(sd_json_variant **ret, const char *name, void *userdata);
+int mount_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata);
diff --git a/src/core/varlink-unit.c b/src/core/varlink-unit.c
index e8b86845a2..789b21947c 100644
--- a/src/core/varlink-unit.c
+++ b/src/core/varlink-unit.c
@@ -18,8 +18,11 @@
#include "set.h"
#include "strv.h"
#include "unit.h"
+#include "varlink-automount.h"
#include "varlink-cgroup.h"
#include "varlink-execute.h"
+#include "varlink-kill.h"
+#include "varlink-mount.h"
#include "varlink-unit.h"
#include "varlink-util.h"
@@ -112,6 +115,12 @@ static int unit_context_build_json(sd_json_variant **ret, const char *name, void
* If it make sense to place a property into a config/unit file it belongs to Context.
* Otherwise it's a 'Runtime'. */
+ /* TODO missing callbacks */
+ static const sd_json_build_callback_t unit_type_callbacks[_UNIT_TYPE_MAX] = {
+ [UNIT_AUTOMOUNT] = automount_context_build_json,
+ [UNIT_MOUNT] = mount_context_build_json,
+ };
+
return sd_json_buildo(
ASSERT_PTR(ret),
SD_JSON_BUILD_PAIR_STRING("Type", unit_type_to_string(u->type)),
@@ -189,18 +198,9 @@ static int unit_context_build_json(sd_json_variant **ret, const char *name, void
SD_JSON_BUILD_PAIR_BOOLEAN("DebugInvocation", u->debug_invocation),
JSON_BUILD_PAIR_CALLBACK_NON_NULL("CGroup", unit_cgroup_context_build_json, u),
- JSON_BUILD_PAIR_CALLBACK_NON_NULL("Exec", unit_exec_context_build_json, u));
-
- // TODO follow up PRs:
- // JSON_BUILD_PAIR_CALLBACK_NON_NULL("Exec", exec_context_build_json, u)
- // JSON_BUILD_PAIR_CALLBACK_NON_NULL("Kill", kill_context_build_json, u)
- // Mount/Automount context
- // Path context
- // Scope context
- // Swap context
- // Timer context
- // Service context
- // Socket context
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("Exec", unit_exec_context_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("Kill", unit_kill_context_build_json, unit_get_kill_context(u)),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL(unit_type_to_capitalized_string(u->type), unit_type_callbacks[u->type], u));
}
static int can_clean_build_json(sd_json_variant **ret, const char *name, void *userdata) {
@@ -280,6 +280,12 @@ static int unit_runtime_build_json(sd_json_variant **ret, const char *name, void
Unit *u = ASSERT_PTR(userdata);
Unit *f = unit_following(u);
+ /* TODO missing callbacks */
+ static const sd_json_build_callback_t unit_type_callbacks[_UNIT_TYPE_MAX] = {
+ [UNIT_AUTOMOUNT] = automount_runtime_build_json,
+ [UNIT_MOUNT] = mount_runtime_build_json,
+ };
+
return sd_json_buildo(
ASSERT_PTR(ret),
JSON_BUILD_PAIR_STRING_NON_EMPTY("Following", f ? f->id : NULL),
@@ -309,7 +315,8 @@ static int unit_runtime_build_json(sd_json_variant **ret, const char *name, void
SD_JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(u->invocation_id), "InvocationID", SD_JSON_BUILD_UUID(u->invocation_id)),
JSON_BUILD_PAIR_CALLBACK_NON_NULL("Markers", markers_build_json, &u->markers),
JSON_BUILD_PAIR_CALLBACK_NON_NULL("ActivationDetails", activation_details_build_json, u->activation_details),
- JSON_BUILD_PAIR_CALLBACK_NON_NULL("CGroup", unit_cgroup_runtime_build_json, u));
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL("CGroup", unit_cgroup_runtime_build_json, u),
+ JSON_BUILD_PAIR_CALLBACK_NON_NULL(unit_type_to_capitalized_string(u->type), unit_type_callbacks[u->type], u));
}
static int list_unit_one(sd_varlink *link, Unit *unit) {
diff --git a/src/creds/creds.c b/src/creds/creds.c
index 6988d39ca4..a133a27dd2 100644
--- a/src/creds/creds.c
+++ b/src/creds/creds.c
@@ -188,7 +188,7 @@ static int is_tmpfs_with_noswap(dev_t devno) {
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
int r;
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/cryptenroll/cryptenroll-fido2.c b/src/cryptenroll/cryptenroll-fido2.c
index 822cf26c89..600207e947 100644
--- a/src/cryptenroll/cryptenroll-fido2.c
+++ b/src/cryptenroll/cryptenroll-fido2.c
@@ -54,7 +54,7 @@ int load_volume_key_fido2(
if (passphrase_size < 0)
return log_oom();
- r = crypt_volume_key_get(
+ r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -95,9 +95,9 @@ int enroll_fido2(
assert_se(iovec_is_set(volume_key));
assert_se(device);
- assert_se(node = crypt_get_device_name(cd));
+ assert_se(node = sym_crypt_get_device_name(cd));
- un = strempty(crypt_get_uuid(cd));
+ un = strempty(sym_crypt_get_uuid(cd));
if (salt_file)
r = fido2_read_salt_file(
@@ -140,7 +140,7 @@ int enroll_fido2(
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
- keyslot = crypt_keyslot_add_by_volume_key(
+ keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
diff --git a/src/cryptenroll/cryptenroll-list.c b/src/cryptenroll/cryptenroll-list.c
index bca9f74c3a..ab7637e616 100644
--- a/src/cryptenroll/cryptenroll-list.c
+++ b/src/cryptenroll/cryptenroll-list.c
@@ -26,11 +26,11 @@ int list_enrolled(struct crypt_device *cd) {
assert(cd);
/* First step, find out all currently used slots */
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
for (int slot = 0; slot < slot_max; slot++) {
crypt_keyslot_info status;
- status = crypt_keyslot_status(cd, slot);
+ status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
diff --git a/src/cryptenroll/cryptenroll-password.c b/src/cryptenroll/cryptenroll-password.c
index 2650318713..e189cce23a 100644
--- a/src/cryptenroll/cryptenroll-password.c
+++ b/src/cryptenroll/cryptenroll-password.c
@@ -31,7 +31,7 @@ int load_volume_key_password(
if (r < 0)
return log_error_errno(r, "Failed to acquire password from environment: %m");
if (r > 0) {
- r = crypt_volume_key_get(
+ r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -81,7 +81,7 @@ int load_volume_key_password(
r = -EPERM;
STRV_FOREACH(p, passwords) {
- r = crypt_volume_key_get(
+ r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -114,7 +114,7 @@ int enroll_password(
assert(cd);
assert(iovec_is_set(volume_key));
- assert_se(node = crypt_get_device_name(cd));
+ assert_se(node = sym_crypt_get_device_name(cd));
r = getenv_steal_erase("NEWPASSWORD", &new_password);
if (r < 0)
@@ -123,7 +123,7 @@ int enroll_password(
_cleanup_free_ char *disk_path = NULL, *id = NULL;
unsigned i = 5;
- assert_se(node = crypt_get_device_name(cd));
+ assert_se(node = sym_crypt_get_device_name(cd));
(void) suggest_passwords();
@@ -196,7 +196,7 @@ int enroll_password(
else if (r == 0)
log_warning("Specified password does not pass quality checks (%s), proceeding anyway.", error);
- keyslot = crypt_keyslot_add_by_volume_key(
+ keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
diff --git a/src/cryptenroll/cryptenroll-pkcs11.c b/src/cryptenroll/cryptenroll-pkcs11.c
index 7ddb9f871b..51c2a5fa77 100644
--- a/src/cryptenroll/cryptenroll-pkcs11.c
+++ b/src/cryptenroll/cryptenroll-pkcs11.c
@@ -53,7 +53,7 @@ int enroll_pkcs11(struct crypt_device *cd, const struct iovec *volume_key,const
assert_se(iovec_is_set(volume_key));
assert_se(uri);
- assert_se(node = crypt_get_device_name(cd));
+ assert_se(node = sym_crypt_get_device_name(cd));
r = pkcs11_acquire_public_key(
uri,
@@ -80,7 +80,7 @@ int enroll_pkcs11(struct crypt_device *cd, const struct iovec *volume_key,const
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
- int keyslot = crypt_keyslot_add_by_volume_key(
+ int keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
diff --git a/src/cryptenroll/cryptenroll-recovery.c b/src/cryptenroll/cryptenroll-recovery.c
index f9a588da26..85ec13f128 100644
--- a/src/cryptenroll/cryptenroll-recovery.c
+++ b/src/cryptenroll/cryptenroll-recovery.c
@@ -24,7 +24,7 @@ int enroll_recovery(
assert_se(cd);
assert_se(iovec_is_set(volume_key));
- assert_se(node = crypt_get_device_name(cd));
+ assert_se(node = sym_crypt_get_device_name(cd));
r = make_recovery_key(&password);
if (r < 0)
@@ -34,7 +34,7 @@ int enroll_recovery(
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
- keyslot = crypt_keyslot_add_by_volume_key(
+ keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
@@ -93,7 +93,7 @@ int enroll_recovery(
return keyslot;
rollback:
- q = crypt_keyslot_destroy(cd, keyslot);
+ q = sym_crypt_keyslot_destroy(cd, keyslot);
if (q < 0)
log_debug_errno(q, "Unable to remove key slot we just added again, can't rollback, sorry: %m");
diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c
index 50abca4363..2f6c7ecd72 100644
--- a/src/cryptenroll/cryptenroll-tpm2.c
+++ b/src/cryptenroll/cryptenroll-tpm2.c
@@ -72,7 +72,7 @@ static int search_policy_hash(
if (r < 0)
return log_error_errno(r, "Invalid hex data in 'tpm2-policy-hash' field item : %m");
- if (iovec_memcmp(policy_hash + j, &thash) != 0) {
+ if (!iovec_equal(policy_hash + j, &thash)) {
match = false;
break;
}
@@ -91,7 +91,7 @@ static int search_policy_hash(
if (r < 0)
return log_error_errno(r, "Invalid hex data in 'tpm2-policy-hash' field: %m");
- if (iovec_memcmp(policy_hash + 0, &thash) == 0)
+ if (iovec_equal(policy_hash + 0, &thash))
return keyslot; /* Found entry with same hash. */
}
}
@@ -272,7 +272,7 @@ int load_volume_key_tpm2(
if (passphrase_size < 0)
return log_oom();
- r = crypt_volume_key_get(
+ r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -329,7 +329,7 @@ int enroll_tpm2(struct crypt_device *cd,
assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
assert(ret_slot_to_wipe);
- assert_se(node = crypt_get_device_name(cd));
+ assert_se(node = sym_crypt_get_device_name(cd));
if (use_pin) {
r = get_pin(&pin_str, &flags);
@@ -566,7 +566,7 @@ int enroll_tpm2(struct crypt_device *cd,
if (r < 0)
return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
- if (iovec_memcmp(&secret, &secret2) != 0)
+ if (!iovec_equal(&secret, &secret2))
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 seal/unseal verification failed.");
}
@@ -579,7 +579,7 @@ int enroll_tpm2(struct crypt_device *cd,
if (r < 0)
return log_error_errno(r, "Failed to set minimal PBKDF: %m");
- keyslot = crypt_keyslot_add_by_volume_key(
+ keyslot = sym_crypt_keyslot_add_by_volume_key(
cd,
CRYPT_ANY_SLOT,
volume_key->iov_base,
diff --git a/src/cryptenroll/cryptenroll-wipe.c b/src/cryptenroll/cryptenroll-wipe.c
index 1ae92bf91b..a8638d2b3a 100644
--- a/src/cryptenroll/cryptenroll-wipe.c
+++ b/src/cryptenroll/cryptenroll-wipe.c
@@ -15,7 +15,7 @@ static int find_all_slots(struct crypt_device *cd, Set *wipe_slots, Set *keep_sl
assert(cd);
assert(wipe_slots);
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Finds all currently assigned slots, and adds them to 'wipe_slots', except if listed already in 'keep_slots' */
@@ -27,7 +27,7 @@ static int find_all_slots(struct crypt_device *cd, Set *wipe_slots, Set *keep_sl
set_contains(wipe_slots, INT_TO_PTR(slot)))
continue;
- status = crypt_keyslot_status(cd, slot);
+ status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
@@ -44,12 +44,12 @@ static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots,
assert(cd);
assert(wipe_slots);
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Finds all slots with an empty passphrase assigned (i.e. "") and adds them to 'wipe_slots', except
* if listed already in 'keep_slots' */
- r = crypt_get_volume_key_size(cd);
+ r = sym_crypt_get_volume_key_size(cd);
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
vks = (size_t) r;
@@ -63,7 +63,7 @@ static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots,
set_contains(wipe_slots, INT_TO_PTR(slot)))
continue;
- status = crypt_keyslot_status(cd, slot);
+ status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
@@ -71,7 +71,7 @@ static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots,
if (!vk)
return log_oom();
- r = crypt_volume_key_get(cd, slot, vk, &vks, "", 0);
+ r = sym_crypt_volume_key_get(cd, slot, vk, &vks, "", 0);
if (r < 0) {
log_debug_errno(r, "Failed to acquire volume key from slot %i with empty password, ignoring: %m", slot);
continue;
@@ -164,7 +164,7 @@ static int find_slots_by_mask(
if ((by_mask & (1U << ENROLL_PASSWORD)) != 0) {
int slot_max;
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
for (int slot = 0; slot < slot_max; slot++) {
crypt_keyslot_info status;
@@ -177,7 +177,7 @@ static int find_slots_by_mask(
if (set_contains(listed_slots, INT_TO_PTR(slot))) /* This has a token, hence is not a password. */
continue;
- status = crypt_keyslot_status(cd, slot);
+ status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST)) /* Not actually assigned? */
continue;
@@ -273,7 +273,7 @@ static bool slots_remain(struct crypt_device *cd, Set *wipe_slots, Set *keep_slo
int slot_max;
assert(cd);
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Checks if any slots remaining in the LUKS2 header if we remove all slots listed in 'wipe_slots'
* (keeping those listed in 'keep_slots') */
@@ -281,7 +281,7 @@ static bool slots_remain(struct crypt_device *cd, Set *wipe_slots, Set *keep_slo
for (int slot = 0; slot < slot_max; slot++) {
crypt_keyslot_info status;
- status = crypt_keyslot_status(cd, slot);
+ status = sym_crypt_keyslot_status(cd, slot);
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
continue;
@@ -338,7 +338,7 @@ int wipe_slots(struct crypt_device *cd,
if (set_put(keep_slots, INT_TO_PTR(except_slot)) < 0)
return log_oom();
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
/* Maintain another set of the slots we intend to wipe */
for (size_t i = 0; i < n_explicit_slots; i++) {
@@ -425,7 +425,7 @@ int wipe_slots(struct crypt_device *cd,
* first.) */
ret = 0;
for (size_t i = n_ordered_slots; i > 0; i--) {
- r = crypt_keyslot_destroy(cd, ordered_slots[i - 1]);
+ r = sym_crypt_keyslot_destroy(cd, ordered_slots[i - 1]);
if (r < 0) {
if (r == -ENOENT)
log_warning_errno(r, "Failed to wipe non-existent slot %i, continuing.", ordered_slots[i - 1]);
@@ -438,7 +438,7 @@ int wipe_slots(struct crypt_device *cd,
}
for (size_t i = n_ordered_tokens; i > 0; i--) {
- r = crypt_token_json_set(cd, ordered_tokens[i - 1], NULL);
+ r = sym_crypt_token_json_set(cd, ordered_tokens[i - 1], NULL);
if (r < 0) {
log_warning_errno(r, "Failed to wipe token %i, continuing: %m", ordered_tokens[i - 1]);
if (ret == 0)
diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c
index e9bb27c254..46b3a546c9 100644
--- a/src/cryptenroll/cryptenroll.c
+++ b/src/cryptenroll/cryptenroll.c
@@ -649,7 +649,7 @@ static int check_for_homed(struct crypt_device *cd) {
/* Politely refuse operating on homed volumes. The enrolled tokens for the user record and the LUKS2
* volume should not get out of sync. */
- for (int token = 0; token < crypt_token_max(CRYPT_LUKS2); token++) {
+ for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
r = cryptsetup_get_token_as_json(cd, token, "systemd-homed", NULL);
if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
continue;
@@ -688,7 +688,7 @@ static int load_volume_key_keyfile(
if (r < 0)
return log_error_errno(r, "Reading keyfile %s failed: %m", arg_unlock_keyfile);
- r = crypt_volume_key_get(
+ r = sym_crypt_volume_key_get(
cd,
CRYPT_ANY_SLOT,
ret_vk,
@@ -710,13 +710,13 @@ static int prepare_luks(
assert(ret_cd);
- r = crypt_init(&cd, arg_node);
+ r = sym_crypt_init(&cd, arg_node);
if (r < 0)
return log_error_errno(r, "Failed to allocate libcryptsetup context: %m");
cryptsetup_enable_logging(cd);
- r = crypt_load(cd, CRYPT_LUKS2, NULL);
+ r = sym_crypt_load(cd, CRYPT_LUKS2, NULL);
if (r < 0)
return log_error_errno(r, "Failed to load LUKS2 superblock of %s: %m", arg_node);
@@ -729,7 +729,7 @@ static int prepare_luks(
return 0;
}
- r = crypt_get_volume_key_size(cd);
+ r = sym_crypt_get_volume_key_size(cd);
if (r <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
@@ -783,11 +783,13 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
+ r = dlopen_cryptsetup(LOG_ERR);
+ if (r < 0)
+ return r;
+
/* A delicious drop of snake oil */
(void) safe_mlockall(MCL_CURRENT|MCL_FUTURE|MCL_ONFAULT);
- cryptsetup_enable_logging(NULL);
-
if (arg_enroll_type < 0)
r = prepare_luks(&cd, /* ret_volume_key= */ NULL); /* No need to unlock device if we don't need the volume key because we don't need to enroll anything */
else
diff --git a/src/cryptenroll/meson.build b/src/cryptenroll/meson.build
index 11265c8b41..2d882343d3 100644
--- a/src/cryptenroll/meson.build
+++ b/src/cryptenroll/meson.build
@@ -21,7 +21,7 @@ executables += [
'public' : true,
'sources' : systemd_cryptenroll_sources,
'dependencies' : [
- libcryptsetup,
+ libcryptsetup_cflags,
libdl,
libfido2_cflags,
libopenssl,
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index ff9449abd1..8e5161eba0 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -823,19 +823,19 @@ static PassphraseType check_registered_passwords(struct crypt_device *cd) {
assert(cd);
- if (!streq_ptr(crypt_get_type(cd), CRYPT_LUKS2)) {
- log_debug("%s: not a LUKS2 device, only passphrases are supported", crypt_get_device_name(cd));
+ if (!streq_ptr(sym_crypt_get_type(cd), CRYPT_LUKS2)) {
+ log_debug("%s: not a LUKS2 device, only passphrases are supported", sym_crypt_get_device_name(cd));
return PASSPHRASE_REGULAR;
}
/* Search all used slots */
- assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
+ assert_se((slot_max = sym_crypt_keyslot_max(CRYPT_LUKS2)) > 0);
slots = new(bool, slot_max);
if (!slots)
return log_oom();
for (int slot = 0; slot < slot_max; slot++)
- slots[slot] = IN_SET(crypt_keyslot_status(cd, slot), CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST);
+ slots[slot] = IN_SET(sym_crypt_keyslot_status(cd, slot), CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST);
/* Iterate all LUKS2 tokens and keep track of all their slots */
for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
@@ -1132,7 +1132,7 @@ static int measure_keyslot(
return log_oom();
_cleanup_free_ char *s = NULL;
- s = strjoin("cryptsetup-keyslot:", escaped, ":", strempty(crypt_get_uuid(cd)), ":", strempty(mechanism), ":", strempty(k));
+ s = strjoin("cryptsetup-keyslot:", escaped, ":", strempty(sym_crypt_get_uuid(cd)), ":", strempty(mechanism), ":", strempty(k));
if (!s)
return log_oom();
@@ -1207,7 +1207,7 @@ static int measured_crypt_activate_by_volume_key(
key_id, arg_fixate_volume_key);
}
- r = crypt_activate_by_volume_key(cd, name, volume_key, volume_key_size, flags);
+ r = sym_crypt_activate_by_volume_key(cd, name, volume_key, volume_key_size, flags);
if (r == -EEXIST) /* volume is already active */
return log_external_activation(r, name);
if (r < 0)
@@ -1250,7 +1250,7 @@ static int measured_crypt_activate_by_passphrase(
if (arg_tpm2_measure_pcr == UINT_MAX && !arg_fixate_volume_key)
goto shortcut;
- r = crypt_get_volume_key_size(cd);
+ r = sym_crypt_get_volume_key_size(cd);
if (r < 0)
return r;
if (r == 0) {
@@ -1262,14 +1262,14 @@ static int measured_crypt_activate_by_passphrase(
if (!vk)
return -ENOMEM;
- keyslot = crypt_volume_key_get(cd, keyslot, vk, &vks, passphrase, passphrase_size);
+ keyslot = sym_crypt_volume_key_get(cd, keyslot, vk, &vks, passphrase, passphrase_size);
if (keyslot < 0)
return keyslot;
return measured_crypt_activate_by_volume_key(cd, name, mechanism, keyslot, vk, vks, flags);
shortcut:
- keyslot = crypt_activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags);
+ keyslot = sym_crypt_activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags);
if (keyslot == -EEXIST) /* volume is already active */
return log_external_activation(keyslot, name);
if (keyslot < 0)
@@ -1320,7 +1320,7 @@ static int attach_tcrypt(
if (key_data) {
params.passphrase = key_data->iov_base;
params.passphrase_size = key_data->iov_len;
- r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
+ r = sym_crypt_load(cd, CRYPT_TCRYPT, ¶ms);
} else if (key_file) {
r = read_one_line_file(key_file, &passphrase);
if (r < 0) {
@@ -1329,13 +1329,13 @@ static int attach_tcrypt(
}
params.passphrase = passphrase;
params.passphrase_size = strlen(passphrase);
- r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
+ r = sym_crypt_load(cd, CRYPT_TCRYPT, ¶ms);
} else {
r = -EINVAL;
STRV_FOREACH(p, passwords){
params.passphrase = *p;
params.passphrase_size = strlen(*p);
- r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
+ r = sym_crypt_load(cd, CRYPT_TCRYPT, ¶ms);
if (r >= 0)
break;
}
@@ -1353,7 +1353,7 @@ static int attach_tcrypt(
return r;
}
- return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", crypt_get_device_name(cd));
+ return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", sym_crypt_get_device_name(cd));
}
r = measured_crypt_activate_by_volume_key(
@@ -1365,7 +1365,7 @@ static int attach_tcrypt(
/* volume_key_size= */ 0,
flags);
if (r < 0)
- return log_error_errno(r, "Failed to activate tcrypt device %s: %m", crypt_get_device_name(cd));
+ return log_error_errno(r, "Failed to activate tcrypt device %s: %m", sym_crypt_get_device_name(cd));
return 0;
}
@@ -1509,7 +1509,7 @@ static bool use_token_plugins(void) {
if (r == 0)
return false;
- return crypt_token_external_path();
+ return sym_crypt_token_external_path();
#else
return false;
#endif
@@ -1554,7 +1554,7 @@ static int crypt_activate_by_token_pin_ask_password(
_cleanup_strv_free_erase_ char **pins = NULL;
int r;
- r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, /* pin= */ NULL, /* pin_size= */ 0, userdata, activation_flags);
+ r = sym_crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, /* pin= */ NULL, /* pin_size= */ 0, userdata, activation_flags);
if (r > 0) /* returns unlocked keyslot id on success */
return 0;
if (r == -EEXIST) /* volume is already active */
@@ -1567,7 +1567,7 @@ static int crypt_activate_by_token_pin_ask_password(
return r;
STRV_FOREACH(p, pins) {
- r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags);
+ r = sym_crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags);
if (r > 0) /* returns unlocked keyslot id on success */
return 0;
if (r == -EEXIST) /* volume is already active */
@@ -1597,7 +1597,7 @@ static int crypt_activate_by_token_pin_ask_password(
return r;
STRV_FOREACH(p, pins) {
- r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags);
+ r = sym_crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags);
if (r > 0) /* returns unlocked keyslot id on success */
return 0;
if (r == -EEXIST) /* volume is already active */
@@ -1658,7 +1658,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
- friendly = friendly_disk_name(crypt_get_device_name(cd), name);
+ friendly = friendly_disk_name(sym_crypt_get_device_name(cd), name);
if (!friendly)
return log_oom();
@@ -1776,7 +1776,7 @@ static int attach_luks2_by_pkcs11_via_plugin(
#if HAVE_LIBCRYPTSETUP_PLUGINS
int r;
- if (!streq_ptr(crypt_get_type(cd), CRYPT_LUKS2))
+ if (!streq_ptr(sym_crypt_get_type(cd), CRYPT_LUKS2))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Automatic PKCS#11 metadata requires LUKS2 device.");
systemd_pkcs11_plugin_params params = {
@@ -1786,7 +1786,7 @@ static int attach_luks2_by_pkcs11_via_plugin(
.askpw_flags = arg_ask_password_flags,
};
- r = crypt_activate_by_token_pin(cd, name, "systemd-pkcs11", CRYPT_ANY_TOKEN, NULL, 0, ¶ms, flags);
+ r = sym_crypt_activate_by_token_pin(cd, name, "systemd-pkcs11", CRYPT_ANY_TOKEN, NULL, 0, ¶ms, flags);
if (r > 0) /* returns unlocked keyslot id on success */
r = 0;
if (r == -EEXIST) /* volume is already active */
@@ -1842,7 +1842,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
}
- friendly = friendly_disk_name(crypt_get_device_name(cd), name);
+ friendly = friendly_disk_name(sym_crypt_get_device_name(cd), name);
if (!friendly)
return log_oom();
@@ -2036,7 +2036,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
assert(name);
assert(arg_tpm2_device || arg_tpm2_device_auto);
- friendly = friendly_disk_name(crypt_get_device_name(cd), name);
+ friendly = friendly_disk_name(sym_crypt_get_device_name(cd), name);
if (!friendly)
return log_oom();
@@ -2382,7 +2382,7 @@ static int attach_luks_or_plain_or_bitlk(
assert(cd);
assert(name);
- if ((!arg_type && !crypt_get_type(cd)) || streq_ptr(arg_type, CRYPT_PLAIN)) {
+ if ((!arg_type && !sym_crypt_get_type(cd)) || streq_ptr(arg_type, CRYPT_PLAIN)) {
struct crypt_params_plain params = {
.offset = arg_offset,
.skip = arg_skip,
@@ -2421,7 +2421,7 @@ static int attach_luks_or_plain_or_bitlk(
/* In contrast to what the name crypt_format() might suggest this doesn't actually format
* anything, it just configures encryption parameters when used for plain mode. */
- r = crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, arg_keyfile_size, ¶ms);
+ r = sym_crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, arg_keyfile_size, ¶ms);
if (r < 0)
return log_error_errno(r, "Loading of cryptographic parameters failed: %m");
@@ -2430,10 +2430,10 @@ static int attach_luks_or_plain_or_bitlk(
}
log_info("Set cipher %s, mode %s, key size %i bits for device %s.",
- crypt_get_cipher(cd),
- crypt_get_cipher_mode(cd),
- crypt_get_volume_key_size(cd)*8,
- crypt_get_device_name(cd));
+ sym_crypt_get_cipher(cd),
+ sym_crypt_get_cipher_mode(cd),
+ sym_crypt_get_volume_key_size(cd)*8,
+ sym_crypt_get_device_name(cd));
if (token_type == TOKEN_TPM2)
return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key);
@@ -2643,19 +2643,19 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
if (arg_header) {
if (streq_ptr(arg_type, CRYPT_TCRYPT)){
log_debug("tcrypt header: %s", arg_header);
- r = crypt_init_data_device(&cd, arg_header, source);
+ r = sym_crypt_init_data_device(&cd, arg_header, source);
} else {
log_debug("LUKS header: %s", arg_header);
- r = crypt_init(&cd, arg_header);
+ r = sym_crypt_init(&cd, arg_header);
}
} else
- r = crypt_init(&cd, source);
+ r = sym_crypt_init(&cd, source);
if (r < 0)
return log_error_errno(r, "crypt_init() failed: %m");
cryptsetup_enable_logging(cd);
- status = crypt_status(cd, volume);
+ status = sym_crypt_status(cd, volume);
if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
log_info("Volume %s already active.", volume);
return 0;
@@ -2680,21 +2680,21 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
}
if (!arg_type || STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2)) {
- r = crypt_load(cd, !arg_type || streq(arg_type, ANY_LUKS) ? CRYPT_LUKS : arg_type, NULL);
+ r = sym_crypt_load(cd, !arg_type || streq(arg_type, ANY_LUKS) ? CRYPT_LUKS : arg_type, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", crypt_get_device_name(cd));
+ return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", sym_crypt_get_device_name(cd));
/* since cryptsetup 2.7.0 (Jan 2024) */
#if HAVE_CRYPT_SET_KEYRING_TO_LINK
if (arg_link_key_description) {
- r = crypt_set_keyring_to_link(cd, arg_link_key_description, NULL, arg_link_key_type, arg_link_keyring);
+ r = sym_crypt_set_keyring_to_link(cd, arg_link_key_description, NULL, arg_link_key_type, arg_link_keyring);
if (r < 0)
log_warning_errno(r, "Failed to set keyring or key description to link volume key in, ignoring: %m");
}
#endif
if (arg_header) {
- r = crypt_set_data_device(cd, source);
+ r = sym_crypt_set_data_device(cd, source);
if (r < 0)
return log_error_errno(r, "Failed to set LUKS data device %s: %m", source);
}
@@ -2716,14 +2716,14 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
return 0;
}
- log_debug_errno(r, "Token activation unsuccessful for device %s: %m", crypt_get_device_name(cd));
+ log_debug_errno(r, "Token activation unsuccessful for device %s: %m", sym_crypt_get_device_name(cd));
}
}
if (streq_ptr(arg_type, CRYPT_BITLK)) {
- r = crypt_load(cd, CRYPT_BITLK, NULL);
+ r = sym_crypt_load(cd, CRYPT_BITLK, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to load Bitlocker superblock on device %s: %m", crypt_get_device_name(cd));
+ return log_error_errno(r, "Failed to load Bitlocker superblock on device %s: %m", sym_crypt_get_device_name(cd));
}
bool use_cached_passphrase = true, try_discover_key = !key_file;
@@ -2850,7 +2850,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
- r = crypt_init_by_name(&cd, volume);
+ r = sym_crypt_init_by_name(&cd, volume);
if (r == -ENODEV) {
log_info("Volume %s already inactive.", volume);
return 0;
@@ -2860,7 +2860,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
cryptsetup_enable_logging(cd);
- r = crypt_deactivate(cd, volume);
+ r = sym_crypt_deactivate(cd, volume);
if (r < 0)
return log_error_errno(r, "Failed to deactivate '%s': %m", volume);
@@ -2879,7 +2879,9 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
- cryptsetup_enable_logging(NULL);
+ r = dlopen_cryptsetup(LOG_ERR);
+ if (r < 0)
+ return r;
return dispatch_verb_with_args(args, NULL);
}
diff --git a/src/cryptsetup/meson.build b/src/cryptsetup/meson.build
index b36354fb0a..9249f70177 100644
--- a/src/cryptsetup/meson.build
+++ b/src/cryptsetup/meson.build
@@ -18,7 +18,7 @@ executables += [
'public' : true,
'sources' : systemd_cryptsetup_sources,
'dependencies' : [
- libcryptsetup,
+ libcryptsetup_cflags,
libfido2_cflags,
libmount_cflags,
libopenssl,
diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c
index b3fe28e2cf..973a954acd 100644
--- a/src/dissect/dissect.c
+++ b/src/dissect/dissect.c
@@ -494,9 +494,9 @@ static int parse_argv(int argc, char *argv[]) {
break;
OPTION_LONG("make-archive", NULL, "Convert the DDI to an archive file"):
- r = dlopen_libarchive();
+ r = dlopen_libarchive(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Archive support not available (compiled without libarchive, or libarchive not installed?).");
+ return r;
arg_action = ACTION_MAKE_ARCHIVE;
break;
diff --git a/src/fuzz/fuzz-varlink.c b/src/fuzz/fuzz-varlink.c
index fb1584a2ea..7bd7e5ab92 100644
--- a/src/fuzz/fuzz-varlink.c
+++ b/src/fuzz/fuzz-varlink.c
@@ -41,7 +41,7 @@ static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userd
else
assert_se(errno == EAGAIN);
} else
- iovec_increment(iov, 1, n);
+ iovec_inc(iov, n);
}
if (revents & EPOLLIN) {
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 6716a8d1aa..abbb955e59 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -295,8 +295,8 @@ static int add_veritysetup(
return 0;
#else
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
- "Partition is Verity protected, but systemd-gpt-auto-generator was compiled without libcryptsetup support.");
+ log_warning("Compiled without libcryptsetup support, skipping verity setup for '%s'.", id);
+ return 0;
#endif
}
#endif
diff --git a/src/growfs/growfs.c b/src/growfs/growfs.c
index 8481257ab7..ff6a5909e7 100644
--- a/src/growfs/growfs.c
+++ b/src/growfs/growfs.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include
-#include
#include
#include "alloc-util.h"
@@ -13,10 +12,12 @@
#include "devnum-util.h"
#include "dissect-image.h"
#include "fd-util.h"
+#include "format-table.h"
#include "format-util.h"
#include "log.h"
#include "main-func.h"
#include "mountpoint-util.h"
+#include "options.h"
#include "pretty-print.h"
#include "resize-fs.h"
#include "string-util.h"
@@ -27,14 +28,14 @@ static bool arg_dry_run = false;
#if HAVE_LIBCRYPTSETUP
static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_devno) {
_cleanup_free_ char *devpath = NULL, *main_devpath = NULL;
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_close_ int main_devfd = -EBADF;
uint64_t size;
int r;
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Cannot resize LUKS device: %m");
+ return r;
main_devfd = r = device_open_from_devnum(S_IFBLK, main_devno, O_RDONLY|O_CLOEXEC, &main_devpath);
if (r < 0)
@@ -92,10 +93,6 @@ static int maybe_resize_underlying_device(
assert(mountfd >= 0);
assert(mountpath);
-#if HAVE_LIBCRYPTSETUP
- cryptsetup_enable_logging(NULL);
-#endif
-
r = get_block_device_harder_fd(mountfd, &devno);
if (r < 0)
return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m",
@@ -132,67 +129,60 @@ static int maybe_resize_underlying_device(
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("systemd-growfs@.service", "8", &link);
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...] /path/to/mountpoint\n\n"
- "Grow filesystem or encrypted payload to device size.\n\n"
- "Options:\n"
- " -h --help Show this help and exit\n"
- " --version Print version string and exit\n"
- " -n --dry-run Just print what would be done\n"
- "\nSee the %s for details.\n",
- program_invocation_short_name,
- link);
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+ printf("%s [OPTIONS...] /path/to/mountpoint\n\n"
+ "Grow filesystem or encrypted payload to device size.\n",
+ program_invocation_short_name);
+
+ printf("\n%sOptions:%s\n",
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- };
-
- int c;
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version" , no_argument, NULL, ARG_VERSION },
- { "dry-run", no_argument, NULL, 'n' },
- {}
- };
-
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hn", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case 'n':
+ OPTION('n', "dry-run", NULL, "Just print what would be done"):
arg_dry_run = true;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
- if (optind + 1 != argc)
+ if (option_parser_get_n_args(&state) != 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s expects exactly one argument (the mount point).",
program_invocation_short_name);
- arg_target = argv[optind];
+ arg_target = option_parser_get_args(&state)[0];
return 1;
}
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 2c6eed3248..cc48bf22fb 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -1,20 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include "alloc-util.h"
#include "build.h"
#include "devnum-util.h"
+#include "format-table.h"
#include "hibernate-resume-config.h"
#include "hibernate-util.h"
#include "initrd-util.h"
#include "log.h"
#include "main-func.h"
+#include "options.h"
#include "parse-util.h"
#include "pretty-print.h"
#include "stat-util.h"
#include "static-destruct.h"
+#include "strv.h"
static HibernateInfo arg_info = {};
static bool arg_clear = false;
@@ -23,70 +25,59 @@ STATIC_DESTRUCTOR_REGISTER(arg_info, hibernate_info_done);
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("systemd-hibernate-resume", "8", &link);
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...] [DEVICE [OFFSET]]\n"
- "\n%sInitiate resume from hibernation.%s\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --clear Clear hibernation storage information from EFI and exit\n"
- "\nSee the %s for details.\n",
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ printf("%s [OPTIONS...] [DEVICE [OFFSET]]\n\n"
+ "%sInitiate resume from hibernation.%s\n\n",
program_invocation_short_name,
ansi_highlight(),
- ansi_normal(),
- link);
+ ansi_normal());
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_CLEAR,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "clear", no_argument, NULL, ARG_CLEAR },
- {}
- };
-
- int c;
-
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_CLEAR:
+ OPTION_LONG("clear", NULL,
+ "Clear hibernation storage information from EFI and exit"):
arg_clear = true;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
- if (argc > optind && arg_clear)
+ if (option_parser_get_n_args(&state) > 0 && arg_clear)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Extraneous arguments specified with --clear, refusing.");
+ *ret_args = option_parser_get_args(&state);
return 1;
}
@@ -130,11 +121,14 @@ static int run(int argc, char *argv[]) {
log_setup();
- r = parse_argv(argc, argv);
+ char **args = NULL;
+ r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
- if (argc - optind > 2)
+ size_t n_args = strv_length(args);
+
+ if (n_args > 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program expects zero, one, or two arguments.");
umask(0022);
@@ -146,7 +140,7 @@ static int run(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
"Not running in initrd, refusing to initiate resume from hibernation.");
- if (argc <= optind) {
+ if (n_args == 0) {
r = setup_hibernate_info_and_warn();
if (r <= 0)
return r;
@@ -154,12 +148,12 @@ static int run(int argc, char *argv[]) {
if (arg_info.efi)
(void) clear_efi_hibernate_location_and_warn();
} else {
- arg_info.device = ASSERT_PTR(argv[optind]);
+ arg_info.device = ASSERT_PTR(args[0]);
- if (argc - optind == 2) {
- r = safe_atou64(argv[optind + 1], &arg_info.offset);
+ if (n_args == 2) {
+ r = safe_atou64(args[1], &arg_info.offset);
if (r < 0)
- return log_error_errno(r, "Failed to parse resume offset %s: %m", argv[optind + 1]);
+ return log_error_errno(r, "Failed to parse resume offset %s: %m", args[1]);
}
}
diff --git a/src/home/homectl.c b/src/home/homectl.c
index 194e73b491..4ebf47ca9e 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -4666,7 +4666,7 @@ static int parse_argv(int argc, char *argv[]) {
IN_SET(c, ARG_STORAGE, ARG_FS_TYPE) ?
&arg_identity_extra_this_machine : &arg_identity_extra;
- if (!isempty(optarg) && !string_is_safe(optarg))
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Parameter for field %s not valid: %s", field, optarg);
diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c
index 878ff5e905..96ac65a6fb 100644
--- a/src/home/homework-luks.c
+++ b/src/home/homework-luks.c
@@ -146,7 +146,7 @@ static int probe_file_system_by_fd(
assert(ret_fstype);
assert(ret_uuid);
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return r;
@@ -411,7 +411,7 @@ static int luks_setup(
key_serial_t *ret_key_serial) {
_cleanup_(keyring_unlinkp) key_serial_t key_serial = -1;
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(erase_and_freep) void *vk = NULL;
sd_id128_t p;
size_t vks;
@@ -522,14 +522,14 @@ static int acquire_open_luks_device(
HomeSetup *setup,
bool graceful) {
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
int r;
assert(h);
assert(setup);
assert(!setup->crypt_device);
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -684,7 +684,7 @@ static int luks_validate(
assert(ret_size);
assert(sector_size > 0);
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return r;
@@ -1289,7 +1289,7 @@ int home_setup_luks(
assert(setup);
assert(user_record_storage(h) == USER_LUKS);
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -1590,7 +1590,7 @@ int home_activate_luks(
assert(setup);
assert(ret_home);
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -1781,7 +1781,7 @@ static int luks_format(
struct crypt_device **ret) {
_cleanup_(user_record_unrefp) UserRecord *reduced = NULL;
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(erase_and_freep) void *volume_key = NULL;
struct crypt_pbkdf_type good_pbkdf, minimal_pbkdf;
_cleanup_free_ char *text = NULL;
@@ -1919,11 +1919,11 @@ static int make_partition_table(
assert(ret_size);
assert(ret_disk_uuid);
- t = fdisk_new_parttype();
+ t = sym_fdisk_new_parttype();
if (!t)
return log_oom();
- r = fdisk_parttype_set_typestr(t, SD_GPT_USER_HOME_STR);
+ r = sym_fdisk_parttype_set_typestr(t, SD_GPT_USER_HOME_STR);
if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m");
@@ -1931,27 +1931,27 @@ static int make_partition_table(
if (r < 0)
return log_error_errno(r, "Failed to open device: %m");
- r = fdisk_create_disklabel(c, "gpt");
+ r = sym_fdisk_create_disklabel(c, "gpt");
if (r < 0)
return log_error_errno(r, "Failed to create GPT disk label: %m");
- p = fdisk_new_partition();
+ p = sym_fdisk_new_partition();
if (!p)
return log_oom();
- r = fdisk_partition_set_type(p, t);
+ r = sym_fdisk_partition_set_type(p, t);
if (r < 0)
return log_error_errno(r, "Failed to set partition type: %m");
- r = fdisk_partition_partno_follow_default(p, 1);
+ r = sym_fdisk_partition_partno_follow_default(p, 1);
if (r < 0)
return log_error_errno(r, "Failed to place partition at first free partition index: %m");
/* Use same sector size as the fdisk context when converting to bytes */
- fdisk_sector_size = fdisk_get_sector_size(c);
+ fdisk_sector_size = sym_fdisk_get_sector_size(c);
assert(fdisk_sector_size > 0);
- first_lba = fdisk_get_first_lba(c); /* Boundary where usable space starts */
+ first_lba = sym_fdisk_get_first_lba(c); /* Boundary where usable space starts */
assert(first_lba <= UINT64_MAX / fdisk_sector_size);
start = DISK_SIZE_ROUND_UP(first_lba * fdisk_sector_size);
@@ -1960,38 +1960,38 @@ static int make_partition_table(
if (start == UINT64_MAX)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Overflow while rounding up start LBA.");
- last_lba = fdisk_get_last_lba(c); /* One sector before boundary where usable space ends */
+ last_lba = sym_fdisk_get_last_lba(c); /* One sector before boundary where usable space ends */
assert(last_lba < UINT64_MAX / fdisk_sector_size);
end = DISK_SIZE_ROUND_DOWN((last_lba + 1) * fdisk_sector_size);
if (end <= start)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Resulting partition size zero or negative.");
- r = fdisk_partition_set_start(p, start / fdisk_sector_size);
+ r = sym_fdisk_partition_set_start(p, start / fdisk_sector_size);
if (r < 0)
return log_error_errno(r, "Failed to place partition at offset %" PRIu64 ": %m", start);
- r = fdisk_partition_set_size(p, (end - start) / fdisk_sector_size);
+ r = sym_fdisk_partition_set_size(p, (end - start) / fdisk_sector_size);
if (r < 0)
return log_error_errno(r, "Failed to end partition at offset %" PRIu64 ": %m", end);
- r = fdisk_partition_set_name(p, label);
+ r = sym_fdisk_partition_set_name(p, label);
if (r < 0)
return log_error_errno(r, "Failed to set partition name: %m");
- r = fdisk_partition_set_uuid(p, SD_ID128_TO_UUID_STRING(uuid));
+ r = sym_fdisk_partition_set_uuid(p, SD_ID128_TO_UUID_STRING(uuid));
if (r < 0)
return log_error_errno(r, "Failed to set partition UUID: %m");
- r = fdisk_add_partition(c, p, NULL);
+ r = sym_fdisk_add_partition(c, p, NULL);
if (r < 0)
return log_error_errno(r, "Failed to add partition: %m");
- r = fdisk_write_disklabel(c);
+ r = sym_fdisk_write_disklabel(c);
if (r < 0)
return log_error_errno(r, "Failed to write disk label: %m");
- r = fdisk_get_disklabel_id(c, &disk_uuid_as_string);
+ r = sym_fdisk_get_disklabel_id(c, &disk_uuid_as_string);
if (r < 0)
return log_error_errno(r, "Failed to determine disk label UUID: %m");
@@ -1999,17 +1999,17 @@ static int make_partition_table(
if (r < 0)
return log_error_errno(r, "Failed to parse disk label UUID: %m");
- r = fdisk_get_partition(c, 0, &q);
+ r = sym_fdisk_get_partition(c, 0, &q);
if (r < 0)
return log_error_errno(r, "Failed to read created partition metadata: %m");
- assert(fdisk_partition_has_start(q));
- offset = fdisk_partition_get_start(q);
+ assert(sym_fdisk_partition_has_start(q));
+ offset = sym_fdisk_partition_get_start(q);
if (offset > UINT64_MAX / fdisk_sector_size)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Partition offset too large.");
- assert(fdisk_partition_has_size(q));
- size = fdisk_partition_get_size(q);
+ assert(sym_fdisk_partition_has_size(q));
+ size = sym_fdisk_partition_get_size(q);
if (size > UINT64_MAX / fdisk_sector_size)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Partition size too large.");
@@ -2207,7 +2207,11 @@ int home_create_luks(
assert(setup->image_fd < 0);
assert(ret_home);
- r = dlopen_cryptsetup();
+ r = dlopen_fdisk(LOG_DEBUG);
+ if (r < 0)
+ return r;
+
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -2806,10 +2810,10 @@ static int prepare_resize_partition(
if (r < 0)
return log_error_errno(r, "Failed to open device: %m");
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(ENOMEDIUM), "Disk has no GPT partition table.");
- r = fdisk_get_disklabel_id(c, &disk_uuid_as_string);
+ r = sym_fdisk_get_disklabel_id(c, &disk_uuid_as_string);
if (r < 0)
return log_error_errno(r, "Failed to acquire disk UUID: %m");
@@ -2817,34 +2821,36 @@ static int prepare_resize_partition(
if (r < 0)
return log_error_errno(r, "Failed to parse disk UUID: %m");
- r = fdisk_get_partitions(c, &t);
+ r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
- n_partitions = fdisk_table_get_nents(t);
+ n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
struct fdisk_partition *p;
uint64_t fdisk_sector_size;
- p = fdisk_table_get_partition(t, i);
+ p = sym_fdisk_table_get_partition(t, i);
if (!p)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
- if (fdisk_partition_is_used(p) <= 0)
+ if (sym_fdisk_partition_is_used(p) <= 0)
continue;
- if (fdisk_partition_has_start(p) <= 0 || fdisk_partition_has_size(p) <= 0 || fdisk_partition_has_end(p) <= 0)
+ if (sym_fdisk_partition_has_start(p) <= 0 ||
+ sym_fdisk_partition_has_size(p) <= 0 ||
+ sym_fdisk_partition_has_end(p) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found partition without a size.");
- fdisk_sector_size = fdisk_get_sector_size(c);
+ fdisk_sector_size = sym_fdisk_get_sector_size(c);
assert(fdisk_sector_size > 0);
- if (fdisk_partition_get_start(p) == partition_offset / fdisk_sector_size &&
- fdisk_partition_get_size(p) == old_partition_size / fdisk_sector_size) {
+ if (sym_fdisk_partition_get_start(p) == partition_offset / fdisk_sector_size &&
+ sym_fdisk_partition_get_size(p) == old_partition_size / fdisk_sector_size) {
if (found)
return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Partition found twice, refusing.");
found = p;
- } else if (fdisk_partition_get_end(p) > partition_offset / fdisk_sector_size)
+ } else if (sym_fdisk_partition_get_end(p) > partition_offset / fdisk_sector_size)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't extend, not last partition in image.");
}
@@ -2876,12 +2882,12 @@ static int get_maximum_partition_size(
return log_error_errno(r, "Failed to create fdisk context: %m");
/* Get the probed sector size by fdisk */
- fdisk_sector_size = fdisk_get_sector_size(c);
- start_lba = fdisk_partition_get_start(p);
+ fdisk_sector_size = sym_fdisk_get_sector_size(c);
+ start_lba = sym_fdisk_partition_get_start(p);
assert(start_lba <= UINT64_MAX / fdisk_sector_size);
start = start_lba * fdisk_sector_size;
- last_lba = fdisk_get_last_lba(c); /* One sector before boundary where usable space ends */
+ last_lba = sym_fdisk_get_last_lba(c); /* One sector before boundary where usable space ends */
assert(last_lba < UINT64_MAX / fdisk_sector_size);
end = DISK_SIZE_ROUND_DOWN((last_lba + 1) * fdisk_sector_size);
@@ -2898,14 +2904,14 @@ static int ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *userdata
assert(c);
- switch (fdisk_ask_get_type(ask)) {
+ switch (sym_fdisk_ask_get_type(ask)) {
case FDISK_ASKTYPE_STRING:
result = new(char, 37);
if (!result)
return log_oom();
- fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) userdata, result));
+ sym_fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) userdata, result));
break;
default:
@@ -2943,31 +2949,31 @@ static int apply_resize_partition(
return log_error_errno(r, "Failed to open device: %m");
/* Before writing our partition patch the final size in */
- r = fdisk_partition_size_explicit(p, 1);
+ r = sym_fdisk_partition_size_explicit(p, 1);
if (r < 0)
return log_error_errno(r, "Failed to enable explicit partition size: %m");
- r = fdisk_partition_set_size(p, new_partition_size / ssz);
+ r = sym_fdisk_partition_set_size(p, new_partition_size / ssz);
if (r < 0)
return log_error_errno(r, "Failed to change partition size: %m");
- r = fdisk_create_disklabel(c, "gpt");
+ r = sym_fdisk_create_disklabel(c, "gpt");
if (r < 0)
return log_error_errno(r, "Failed to create GPT disk label: %m");
- r = fdisk_apply_table(c, t);
+ r = sym_fdisk_apply_table(c, t);
if (r < 0)
return log_error_errno(r, "Failed to apply partition table: %m");
- r = fdisk_set_ask(c, ask_cb, &disk_uuids);
+ r = sym_fdisk_set_ask(c, ask_cb, &disk_uuids);
if (r < 0)
return log_error_errno(r, "Failed to set libfdisk query function: %m");
- r = fdisk_set_disklabel_id(c);
+ r = sym_fdisk_set_disklabel_id(c);
if (r < 0)
return log_error_errno(r, "Failed to change disklabel ID: %m");
- r = fdisk_write_disklabel(c);
+ r = sym_fdisk_write_disklabel(c);
if (r < 0)
return log_error_errno(r, "Failed to write disk label: %m");
@@ -3240,7 +3246,11 @@ int home_resize_luks(
assert(user_record_storage(h) == USER_LUKS);
assert(setup);
- r = dlopen_cryptsetup();
+ r = dlopen_fdisk(LOG_DEBUG);
+ if (r < 0)
+ return r;
+
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -3698,7 +3708,7 @@ int home_passwd_luks(
assert(user_record_storage(h) == USER_LUKS);
assert(setup);
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/home/homework.c b/src/home/homework.c
index a6e7d3751a..d63d481447 100644
--- a/src/home/homework.c
+++ b/src/home/homework.c
@@ -1331,7 +1331,7 @@ static int determine_default_storage(UserStorage *ret) {
if (r < 0)
log_warning_errno(r, "Failed to determine if %s is encrypted, ignoring: %m", get_home_root());
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
log_info("Not using '%s' storage, since libcryptsetup could not be loaded.", user_storage_to_string(USER_LUKS));
else {
@@ -2005,8 +2005,6 @@ static int run(int argc, char *argv[]) {
log_setup();
- cryptsetup_enable_logging(NULL);
-
umask(0022);
if (argc < 2 || argc > 3)
diff --git a/src/home/meson.build b/src/home/meson.build
index 1efee1619e..b051bf580c 100644
--- a/src/home/meson.build
+++ b/src/home/meson.build
@@ -73,13 +73,9 @@ executables += [
'name' : 'systemd-homework',
'sources' : systemd_homework_sources,
'objects' : ['systemd-homed'],
- 'link_with' : [
- libshared,
- libshared_fdisk
- ],
'dependencies' : [
libblkid_cflags,
- libfdisk,
+ libfdisk_cflags,
libopenssl,
libp11kit_cflags,
threads,
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index e8d7282cbf..1de66b4c03 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -789,7 +789,7 @@ _public_ PAM_EXTERN int pam_sm_authenticate(
bool debug = false;
int r;
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_DEBUG);
if (r < 0)
return PAM_SERVICE_ERR;
@@ -854,7 +854,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
bool debug = false;
int r;
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_DEBUG);
if (r < 0)
return PAM_SERVICE_ERR;
@@ -972,7 +972,7 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
usec_t t;
int r;
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_DEBUG);
if (r < 0)
return PAM_SERVICE_ERR;
@@ -1091,7 +1091,7 @@ _public_ PAM_EXTERN int pam_sm_chauthtok(
bool debug = false;
int r;
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_DEBUG);
if (r < 0)
return PAM_SERVICE_ERR;
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 3b407bb070..141387da4f 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
-
#include "alloc-util.h"
#include "build.h"
+#include "format-table.h"
#include "hwdb-util.h"
#include "label-util.h"
#include "log.h"
#include "main-func.h"
+#include "options.h"
#include "pretty-print.h"
#include "verbs.h"
@@ -15,10 +15,14 @@ static const char *arg_hwdb_bin_dir = NULL;
static const char *arg_root = NULL;
static bool arg_strict = false;
+VERB(verb_query, "query", "MODALIAS", 2, 2, 0,
+ "Query database and print result");
static int verb_query(int argc, char *argv[], uintptr_t _data, void *userdata) {
return hwdb_query(argv[1], arg_root);
}
+VERB_NOARG(verb_update, "update",
+ "Update the hwdb database");
static int verb_update(int argc, char *argv[], uintptr_t _data, void *userdata) {
if (hwdb_bypass())
return 0;
@@ -28,99 +32,93 @@ static int verb_update(int argc, char *argv[], uintptr_t _data, void *userdata)
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
int r;
r = terminal_urlify_man("systemd-hwdb", "8", &link);
if (r < 0)
return log_oom();
+ r = verbs_get_help_table(&verbs);
+ if (r < 0)
+ return r;
+
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ (void) table_sync_column_widths(0, verbs, options);
+
printf("%s [OPTIONS...] COMMAND ...\n\n"
"%sUpdate or query the hardware database.%s\n"
- "\nCommands:\n"
- " update Update the hwdb database\n"
- " query MODALIAS Query database and print result\n"
- "\nOptions:\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -s --strict When updating, return non-zero exit value on any parsing error\n"
- " --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
- " -r --root=PATH Alternative root path in the filesystem\n"
- "\nSee the %s for details.\n",
+ "\n%sCommands:%s\n",
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
- link);
+ ansi_underline(),
+ ansi_normal());
+ r = table_print_or_warn(verbs);
+ if (r < 0)
+ return r;
+
+ printf("\n%sOptions:%s\n",
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_USR,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "usr", no_argument, NULL, ARG_USR },
- { "strict", no_argument, NULL, 's' },
- { "root", required_argument, NULL, 'r' },
- {}
- };
-
- int c;
+VERB_COMMON_HELP_HIDDEN(help);
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
- while ((c = getopt_long(argc, argv, "sr:h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_USR:
- arg_hwdb_bin_dir = UDEVLIBEXECDIR;
- break;
-
- case 's':
+ OPTION('s', "strict", NULL,
+ "When updating, return non-zero exit value on any parsing error"):
arg_strict = true;
break;
- case 'r':
- arg_root = optarg;
+ OPTION('r', "root", "PATH", "Alternative root path in the filesystem"):
+ arg_root = arg;
break;
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
+ OPTION_LONG("usr", NULL,
+ "Generate in " UDEVLIBEXECDIR " instead of /etc/udev"):
+ arg_hwdb_bin_dir = UDEVLIBEXECDIR;
+ break;
}
+ *ret_args = option_parser_get_args(&state);
return 1;
}
-static int hwdb_main(int argc, char *argv[]) {
- static const Verb verbs[] = {
- { "update", 1, 1, 0, verb_update },
- { "query", 2, 2, 0, verb_query },
- {},
- };
-
- return dispatch_verb(argc, argv, verbs, NULL);
-}
-
static int run(int argc, char *argv[]) {
int r;
log_setup();
- r = parse_argv(argc, argv);
+ char **args = NULL;
+ r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
@@ -128,7 +126,7 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
- return hwdb_main(argc, argv);
+ return dispatch_verb_with_args(args, NULL);
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/imds/imdsd.c b/src/imds/imdsd.c
index 211565880c..8ab3498656 100644
--- a/src/imds/imdsd.c
+++ b/src/imds/imdsd.c
@@ -3070,7 +3070,7 @@ static int run(int argc, char* argv[]) {
if (r <= 0)
return r;
- r = dlopen_curl();
+ r = dlopen_curl(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/import/export.c b/src/import/export.c
index 389d5428bf..71f892feb0 100644
--- a/src/import/export.c
+++ b/src/import/export.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include
@@ -13,9 +12,11 @@
#include "export-raw.h"
#include "export-tar.h"
#include "fd-util.h"
+#include "format-table.h"
#include "import-common.h"
#include "log.h"
#include "main-func.h"
+#include "options.h"
#include "runtime-scope.h"
#include "signal-util.h"
#include "string-util.h"
@@ -44,6 +45,8 @@ static void on_tar_finished(TarExport *export, int error, void *userdata) {
sd_event_exit(event, ABS(error));
}
+VERB(verb_export_tar, "tar", "NAME [FILE]", 2, 3, 0,
+ "Export a TAR image");
static int verb_export_tar(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(tar_export_unrefp) TarExport *export = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
@@ -125,6 +128,8 @@ static void on_raw_finished(RawExport *export, int error, void *userdata) {
sd_event_exit(event, ABS(error));
}
+VERB(verb_export_raw, "raw", "NAME [FILE]", 2, 3, 0,
+ "Export a RAW image");
static int verb_export_raw(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(raw_export_unrefp) RawExport *export = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
@@ -189,126 +194,106 @@ static int verb_export_raw(int argc, char *argv[], uintptr_t _data, void *userda
}
static int help(void) {
- printf("%1$s [OPTIONS...] {COMMAND} ...\n"
- "\n%4$sExport disk images.%5$s\n"
- "\n%2$sCommands:%3$s\n"
- " tar NAME [FILE] Export a TAR image\n"
- " raw NAME [FILE] Export a RAW image\n"
- "\n%2$sOptions:%3$s\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --format=FORMAT Select format\n"
- " --class=CLASS Select image class (machine, sysext, confext,\n"
- " portable)\n"
- " --system Operate in per-system mode\n"
- " --user Operate in per-user mode\n",
+ _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
+ int r;
+
+ r = verbs_get_help_table(&verbs);
+ if (r < 0)
+ return r;
+
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ (void) table_sync_column_widths(0, verbs, options);
+
+ printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+ "%sExport disk images.%s\n"
+ "\n%sCommands:%s\n",
program_invocation_short_name,
- ansi_underline(),
- ansi_normal(),
ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
ansi_normal());
+ r = table_print_or_warn(verbs);
+ if (r < 0)
+ return r;
+
+ printf("\n%sOptions:%s\n",
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
return 0;
}
-static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) {
- return help();
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_FORMAT,
- ARG_CLASS,
- ARG_SYSTEM,
- ARG_USER,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "format", required_argument, NULL, ARG_FORMAT },
- { "class", required_argument, NULL, ARG_CLASS },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "user", no_argument, NULL, ARG_USER },
- {}
- };
-
- int c;
+VERB_COMMON_HELP_HIDDEN(help);
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_FORMAT:
- arg_compress = compression_from_string_harder(optarg);
+ OPTION_LONG("format", "FORMAT", "Select format"):
+ arg_compress = compression_from_string_harder(arg);
if (arg_compress < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Unknown format: %s", optarg);
+ "Unknown format: %s", arg);
break;
- case ARG_CLASS:
- arg_class = image_class_from_string(optarg);
+ OPTION_LONG("class", "CLASS",
+ "Select image class (machine, sysext, confext, portable)"):
+ arg_class = image_class_from_string(arg);
if (arg_class < 0)
- return log_error_errno(arg_class, "Failed to parse --class= argument: %s", optarg);
-
+ return log_error_errno(arg_class, "Failed to parse --class= argument: %s", arg);
break;
- case ARG_SYSTEM:
+ OPTION_LONG("system", NULL, "Operate in per-system mode"):
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
break;
- case ARG_USER:
+ OPTION_LONG("user", NULL, "Operate in per-user mode"):
arg_runtime_scope = RUNTIME_SCOPE_USER;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
if (arg_runtime_scope == RUNTIME_SCOPE_USER)
arg_import_flags |= IMPORT_FOREIGN_UID;
+ *ret_args = option_parser_get_args(&state);
return 1;
}
-static int export_main(int argc, char *argv[]) {
- static const Verb verbs[] = {
- { "help", VERB_ANY, VERB_ANY, 0, verb_help },
- { "tar", 2, 3, 0, verb_export_tar },
- { "raw", 2, 3, 0, verb_export_raw },
- {}
- };
-
- return dispatch_verb(argc, argv, verbs, NULL);
-}
-
static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
log_setup();
- r = parse_argv(argc, argv);
+ char **args = NULL;
+ r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
(void) ignore_signals(SIGPIPE);
- return export_main(argc, argv);
+ return dispatch_verb_with_args(args, NULL);
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/import/import-common.c b/src/import/import-common.c
index 948cd82988..5f17084f9f 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -32,7 +32,7 @@ int import_fork_tar_x(int tree_fd, int userns_fd, PidRef *ret_pid) {
assert(tree_fd >= 0);
assert(ret_pid);
- r = dlopen_libarchive();
+ r = dlopen_libarchive(LOG_DEBUG);
if (r < 0)
return r;
@@ -99,7 +99,7 @@ int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid) {
assert(tree_fd >= 0);
assert(ret_pid);
- r = dlopen_libarchive();
+ r = dlopen_libarchive(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/import/import-fs.c b/src/import/import-fs.c
index 4b2394d414..3605320300 100644
--- a/src/import/import-fs.c
+++ b/src/import/import-fs.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include
@@ -11,6 +10,7 @@
#include "copy.h"
#include "discover-image.h"
#include "fd-util.h"
+#include "format-table.h"
#include "format-util.h"
#include "import-common.h"
#include "import-util.h"
@@ -18,6 +18,7 @@
#include "log.h"
#include "main-func.h"
#include "mkdir-label.h"
+#include "options.h"
#include "parse-argument.h"
#include "path-util.h"
#include "ratelimit.h"
@@ -107,6 +108,8 @@ static int progress_bytes(uint64_t nbytes, uint64_t bps, void *userdata) {
return 0;
}
+VERB(verb_import_fs, "run", "DIRECTORY [NAME]", 2, 3, 0,
+ "Import a directory");
static int verb_import_fs(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(rm_rf_subvolume_and_freep) char *temp_path = NULL;
_cleanup_(progress_info_free) ProgressInfo progress = { .bps = UINT64_MAX };
@@ -266,145 +269,115 @@ static int verb_import_fs(int argc, char *argv[], uintptr_t _data, void *userdat
}
static int help(void) {
- printf("%1$s [OPTIONS...] {COMMAND} ...\n"
- "\n%4$sImport container images from a file system directories.%5$s\n"
- "\n%2$sCommands:%3$s\n"
- " run DIRECTORY [NAME] Import a directory\n"
- "\n%2$sOptions:%3$s\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --force Force creation of image\n"
- " --image-root=PATH Image root directory\n"
- " --read-only Create a read-only image\n"
- " --direct Import directly to specified directory\n"
- " --btrfs-subvol=BOOL Controls whether to create a btrfs subvolume\n"
- " instead of a directory\n"
- " --btrfs-quota=BOOL Controls whether to set up quota for btrfs\n"
- " subvolume\n"
- " --sync=BOOL Controls whether to sync() before completing\n"
- " --class=CLASS Select image class (machine, sysext, confext,\n"
- " portable)\n"
- " --system Operate in per-system mode\n"
- " --user Operate in per-user mode\n",
+ _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
+ int r;
+
+ r = verbs_get_help_table(&verbs);
+ if (r < 0)
+ return r;
+
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ (void) table_sync_column_widths(0, verbs, options);
+
+ printf("%s [OPTIONS...] {COMMAND} ...\n\n"
+ "%sImport container images from file system directories.%s\n"
+ "\n%sCommands:%s\n",
program_invocation_short_name,
- ansi_underline(),
- ansi_normal(),
ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
ansi_normal());
+ r = table_print_or_warn(verbs);
+ if (r < 0)
+ return r;
+
+ printf("\n%sOptions:%s\n",
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
return 0;
}
-static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) {
- return help();
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_FORCE,
- ARG_IMAGE_ROOT,
- ARG_READ_ONLY,
- ARG_DIRECT,
- ARG_BTRFS_SUBVOL,
- ARG_BTRFS_QUOTA,
- ARG_SYNC,
- ARG_CLASS,
- ARG_SYSTEM,
- ARG_USER,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "force", no_argument, NULL, ARG_FORCE },
- { "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
- { "read-only", no_argument, NULL, ARG_READ_ONLY },
- { "direct", no_argument, NULL, ARG_DIRECT },
- { "btrfs-subvol", required_argument, NULL, ARG_BTRFS_SUBVOL },
- { "btrfs-quota", required_argument, NULL, ARG_BTRFS_QUOTA },
- { "sync", required_argument, NULL, ARG_SYNC },
- { "class", required_argument, NULL, ARG_CLASS },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "user", no_argument, NULL, ARG_USER },
- {}
- };
-
- int c, r;
+VERB_COMMON_HELP_HIDDEN(help);
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+ int r;
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_FORCE:
+ OPTION_LONG("force", NULL, "Force creation of image"):
arg_force = true;
break;
- case ARG_IMAGE_ROOT:
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image_root);
+ OPTION_LONG("image-root", "PATH", "Image root directory"):
+ r = parse_path_argument(arg, /* suppress_root= */ false, &arg_image_root);
if (r < 0)
return r;
-
break;
- case ARG_READ_ONLY:
+ OPTION_LONG("read-only", NULL, "Create a read-only image"):
arg_read_only = true;
break;
- case ARG_DIRECT:
+ OPTION_LONG("direct", NULL, "Import directly to specified directory"):
arg_direct = true;
break;
- case ARG_BTRFS_SUBVOL:
- r = parse_boolean_argument("--btrfs-subvol=", optarg, &arg_btrfs_subvol);
+ OPTION_LONG("btrfs-subvol", "BOOL",
+ "Controls whether to create a btrfs subvolume instead of a directory"):
+ r = parse_boolean_argument("--btrfs-subvol=", arg, &arg_btrfs_subvol);
if (r < 0)
return r;
-
break;
- case ARG_BTRFS_QUOTA:
- r = parse_boolean_argument("--btrfs-quota=", optarg, &arg_btrfs_quota);
+ OPTION_LONG("btrfs-quota", "BOOL",
+ "Controls whether to set up quota for btrfs subvolume"):
+ r = parse_boolean_argument("--btrfs-quota=", arg, &arg_btrfs_quota);
if (r < 0)
return r;
-
break;
- case ARG_SYNC:
- r = parse_boolean_argument("--sync=", optarg, &arg_sync);
+ OPTION_LONG("sync", "BOOL", "Controls whether to sync() before completing"):
+ r = parse_boolean_argument("--sync=", arg, &arg_sync);
if (r < 0)
return r;
-
break;
- case ARG_CLASS:
- arg_class = image_class_from_string(optarg);
+ OPTION_LONG("class", "CLASS",
+ "Select image class (machine, sysext, confext, portable)"):
+ arg_class = image_class_from_string(arg);
if (arg_class < 0)
- return log_error_errno(arg_class, "Failed to parse --class= argument: %s", optarg);
-
+ return log_error_errno(arg_class, "Failed to parse --class= argument: %s", arg);
break;
- case ARG_SYSTEM:
+ OPTION_LONG("system", NULL, "Operate in per-system mode"):
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
break;
- case ARG_USER:
+ OPTION_LONG("user", NULL, "Operate in per-user mode"):
arg_runtime_scope = RUNTIME_SCOPE_USER;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
if (!arg_image_root) {
@@ -413,31 +386,22 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(r, "Failed to pick image root: %m");
}
+ *ret_args = option_parser_get_args(&state);
return 1;
}
-static int import_fs_main(int argc, char *argv[]) {
-
- static const Verb verbs[] = {
- { "help", VERB_ANY, VERB_ANY, 0, verb_help },
- { "run", 2, 3, 0, verb_import_fs },
- {}
- };
-
- return dispatch_verb(argc, argv, verbs, NULL);
-}
-
static int run(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
log_setup();
- r = parse_argv(argc, argv);
+ char **args = NULL;
+ r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
- return import_fs_main(argc, argv);
+ return dispatch_verb_with_args(args, NULL);
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index 3cc9c0d692..69346ff477 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -298,7 +298,7 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
}
if (iovec_is_set(&j->expected_checksum) &&
- iovec_memcmp(&j->checksum, &j->expected_checksum) != 0) {
+ !iovec_equal(&j->checksum, &j->expected_checksum)) {
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Checksum of downloaded resource does not match expected checksum, yikes.");
goto finish;
}
diff --git a/src/import/pull-oci.c b/src/import/pull-oci.c
index 4ae933928f..f4878e3c87 100644
--- a/src/import/pull-oci.c
+++ b/src/import/pull-oci.c
@@ -1195,7 +1195,7 @@ static int oci_pull_make_local(OciPull *i) {
return r;
if (!iovec_is_set(&i->config) ||
- iovec_memcmp(&i->config, &IOVEC_MAKE_STRING("{}")) == 0)
+ iovec_equal(&i->config, &IOVEC_MAKE_STRING("{}")))
log_info("Image has no configuration, not saving.");
else {
r = oci_pull_save_nspawn_settings(i);
diff --git a/src/import/test-tar.c b/src/import/test-tar.c
index c0e55c3597..b7cfed9bf3 100644
--- a/src/import/test-tar.c
+++ b/src/import/test-tar.c
@@ -26,7 +26,7 @@ static int run(int argc, char **argv) {
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown operation '%s'.", argv[1]);
- r = dlopen_libarchive();
+ r = dlopen_libarchive(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/integritysetup/integritysetup.c b/src/integritysetup/integritysetup.c
index 29581a0522..9a373e124b 100644
--- a/src/integritysetup/integritysetup.c
+++ b/src/integritysetup/integritysetup.c
@@ -126,19 +126,19 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
return r;
}
- r = crypt_init(&cd, device);
+ r = sym_crypt_init(&cd, device);
if (r < 0)
return log_error_errno(r, "Failed to open integrity device %s: %m", device);
cryptsetup_enable_logging(cd);
- status = crypt_status(cd, volume);
+ status = sym_crypt_status(cd, volume);
if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
log_info("Volume %s already active.", volume);
return 0;
}
- r = crypt_load(cd,
+ r = sym_crypt_load(cd,
CRYPT_INTEGRITY,
&(struct crypt_params_integrity) {
.journal_watermark = arg_percent,
@@ -149,12 +149,12 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
return log_error_errno(r, "Failed to load integrity superblock: %m");
if (!isempty(arg_existing_data_device)) {
- r = crypt_set_data_device(cd, arg_existing_data_device);
+ r = sym_crypt_set_data_device(cd, arg_existing_data_device);
if (r < 0)
return log_error_errno(r, "Failed to add separate data device: %m");
}
- r = crypt_activate_by_volume_key(cd, volume, key_buf, key_buf_size, arg_activate_flags);
+ r = sym_crypt_activate_by_volume_key(cd, volume, key_buf, key_buf_size, arg_activate_flags);
if (r < 0)
return log_error_errno(r, "Failed to set up integrity device: %m");
@@ -172,7 +172,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
- r = crypt_init_by_name(&cd, volume);
+ r = sym_crypt_init_by_name(&cd, volume);
if (r == -ENODEV) {
log_info("Volume %s already inactive.", volume);
return 0;
@@ -182,7 +182,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
cryptsetup_enable_logging(cd);
- r = crypt_deactivate(cd, volume);
+ r = sym_crypt_deactivate(cd, volume);
if (r < 0)
return log_error_errno(r, "Failed to deactivate: %m");
@@ -190,12 +190,16 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
}
static int run(int argc, char *argv[]) {
+ int r;
+
if (argv_looks_like_help(argc, argv))
return help();
log_setup();
- cryptsetup_enable_logging(NULL);
+ r = dlopen_cryptsetup(LOG_ERR);
+ if (r < 0)
+ return r;
umask(0022);
diff --git a/src/integritysetup/meson.build b/src/integritysetup/meson.build
index dd2eb60cf6..4f3601e681 100644
--- a/src/integritysetup/meson.build
+++ b/src/integritysetup/meson.build
@@ -9,7 +9,7 @@ executables += [
'name' : 'systemd-integritysetup',
'sources' : files('integritysetup.c'),
'extract' : files('integrity-util.c'),
- 'dependencies' : libcryptsetup,
+ 'dependencies' : libcryptsetup_cflags,
},
generator_template + {
'name' : 'systemd-integritysetup-generator',
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 7cb8846224..42e3f6df29 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -311,7 +311,7 @@ static int request_parse_accept(
assert(m);
assert(connection);
- header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
+ header = sym_MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
if (!header)
return 0;
@@ -459,7 +459,7 @@ static int request_parse_range(
assert(m);
assert(connection);
- range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
+ range = sym_MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range");
if (!range)
return 0;
@@ -566,7 +566,7 @@ static int request_parse_arguments(
assert(connection);
m->argument_parse_error = 0;
- MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m);
+ sym_MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m);
return m->argument_parse_error;
}
@@ -616,14 +616,14 @@ static int request_handler_entries(
if (r < 0)
return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.");
- response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL);
+ response = sym_MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL);
if (!response)
return respond_oom(connection);
- if (MHD_add_response_header(response, "Content-Type", mime_types[m->mode]) == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", mime_types[m->mode]) == MHD_NO)
return respond_oom(connection);
- return MHD_queue_response(connection, MHD_HTTP_OK, response);
+ return sym_MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int output_field(FILE *f, OutputMode m, const char *d, size_t l) {
@@ -744,14 +744,14 @@ static int request_handler_fields(
if (r < 0)
return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields.");
- response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL);
+ response = sym_MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL);
if (!response)
return respond_oom(connection);
- if (MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]) == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]) == MHD_NO)
return respond_oom(connection);
- return MHD_queue_response(connection, MHD_HTTP_OK, response);
+ return sym_MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int request_handler_redirect(
@@ -767,16 +767,16 @@ static int request_handler_redirect(
if (asprintf(&page, "Please continue to the journal browser.", target) < 0)
return respond_oom(connection);
- response = MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE);
+ response = sym_MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE);
if (!response)
return respond_oom(connection);
TAKE_PTR(page);
- if (MHD_add_response_header(response, "Content-Type", "text/html") == MHD_NO ||
- MHD_add_response_header(response, "Location", target) == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", "text/html") == MHD_NO ||
+ sym_MHD_add_response_header(response, "Location", target) == MHD_NO)
return respond_oom(connection);
- return MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response);
+ return sym_MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response);
}
static int request_handler_file(
@@ -799,15 +799,15 @@ static int request_handler_file(
if (fstat(fd, &st) < 0)
return mhd_respondf(connection, errno, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m");
- response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0);
+ response = sym_MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0);
if (!response)
return respond_oom(connection);
TAKE_FD(fd);
- if (MHD_add_response_header(response, "Content-Type", mime_type) == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", mime_type) == MHD_NO)
return respond_oom(connection);
- return MHD_queue_response(connection, MHD_HTTP_OK, response);
+ return sym_MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int get_virtualization(char **v) {
@@ -899,15 +899,15 @@ static int request_handler_machine(
if (r < 0)
return respond_oom(connection);
- response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE);
+ response = sym_MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE);
if (!response)
return respond_oom(connection);
TAKE_PTR(json);
- if (MHD_add_response_header(response, "Content-Type", "application/json") == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", "application/json") == MHD_NO)
return respond_oom(connection);
- return MHD_queue_response(connection, MHD_HTTP_OK, response);
+ return sym_MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static int output_boot(FILE *f, LogId boot, int boot_display_index) {
@@ -1026,14 +1026,14 @@ static int request_handler_boots(
if (r < 0)
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to seek in journal: %m");
- response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_boots, m, NULL);
+ response = sym_MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_boots, m, NULL);
if (!response)
return respond_oom(connection);
- if (MHD_add_response_header(response, "Content-Type", "application/json-seq") == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", "application/json-seq") == MHD_NO)
return respond_oom(connection);
- return MHD_queue_response(connection, MHD_HTTP_OK, response);
+ return sym_MHD_queue_response(connection, MHD_HTTP_OK, response);
}
static mhd_result request_handler(
@@ -1290,6 +1290,10 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
+ r = dlopen_microhttpd(LOG_ERR);
+ if (r < 0)
+ return r;
+
journal_browse_prepare();
assert_se(sigaction(SIGTERM, &sigterm, NULL) >= 0);
@@ -1323,11 +1327,16 @@ static int run(int argc, char *argv[]) {
{ MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem };
}
- d = MHD_start_daemon(flags, 19531,
- NULL, NULL,
- request_handler, NULL,
- MHD_OPTION_ARRAY, opts,
- MHD_OPTION_END);
+ d = sym_MHD_start_daemon(
+ flags,
+ /* port= */ 19531,
+ /* acp= */ NULL,
+ /* acp_cls= */ NULL,
+ request_handler,
+ /* dh_cls= */ NULL,
+ MHD_OPTION_ARRAY,
+ opts,
+ MHD_OPTION_END);
if (!d)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to start daemon!");
diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
index 9cb84bbe1e..1fbcc27815 100644
--- a/src/journal-remote/journal-remote-main.c
+++ b/src/journal-remote/journal-remote-main.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include "sd-daemon.h"
@@ -12,6 +11,7 @@
#include "daemon-util.h"
#include "extract-word.h"
#include "fd-util.h"
+#include "format-table.h"
#include "format-util.h"
#include "fileio.h"
#include "hashmap.h"
@@ -21,9 +21,11 @@
#include "logs-show.h"
#include "main-func.h"
#include "microhttpd-util.h"
+#include "options.h"
#include "parse-argument.h"
#include "parse-helpers.h"
#include "parse-util.h"
+#include "path-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "socket-netlink.h"
@@ -106,7 +108,7 @@ static MHDDaemonWrapper* MHDDaemonWrapper_free(MHDDaemonWrapper *d) {
d->timer_event = sd_event_source_unref(d->timer_event);
if (d->daemon)
- MHD_stop_daemon(d->daemon);
+ sym_MHD_stop_daemon(d->daemon);
return mfree(d);
}
@@ -359,7 +361,7 @@ static mhd_result request_handler(
if (*connection_cls) {
RemoteSource *source = *connection_cls;
- header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Encoding");
+ header = sym_MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Encoding");
if (header) {
Compression c = compression_from_string_harder(header);
if (c <= 0 || !compression_supported(c))
@@ -380,12 +382,12 @@ static mhd_result request_handler(
if (!streq(url, "/upload"))
return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.");
- header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type");
+ header = sym_MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type");
if (!header || !streq(header, "application/vnd.fdo.journal"))
return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE,
"Content-Type: application/vnd.fdo.journal is required.");
- header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Transfer-Encoding");
+ header = sym_MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Transfer-Encoding");
if (header) {
if (!strcaseeq(header, "chunked"))
return mhd_respondf(connection, 0, MHD_HTTP_BAD_REQUEST,
@@ -394,7 +396,7 @@ static mhd_result request_handler(
chunked = true;
}
- header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length");
+ header = sym_MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length");
if (header) {
size_t len;
@@ -418,8 +420,8 @@ static mhd_result request_handler(
{
const union MHD_ConnectionInfo *ci;
- ci = MHD_get_connection_info(connection,
- MHD_CONNECTION_INFO_CONNECTION_FD);
+ ci = sym_MHD_get_connection_info(connection,
+ MHD_CONNECTION_INFO_CONNECTION_FD);
if (!ci) {
log_error("MHD_get_connection_info failed: cannot get remote fd");
return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -462,6 +464,12 @@ static int setup_microhttpd_server(RemoteServer *s,
const char *trust) {
#if HAVE_MICROHTTPD
+ int r;
+
+ r = dlopen_microhttpd(LOG_ERR);
+ if (r < 0)
+ return r;
+
struct MHD_OptionItem opts[] = {
{ MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
{ MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
@@ -481,7 +489,7 @@ static int setup_microhttpd_server(RemoteServer *s,
_cleanup_(MHDDaemonWrapper_freep) MHDDaemonWrapper *d = NULL;
const union MHD_DaemonInfo *info;
- int r, epoll_fd;
+ int epoll_fd;
assert(fd >= 0);
@@ -524,18 +532,23 @@ static int setup_microhttpd_server(RemoteServer *s,
d->fd = (uint64_t) fd;
- d->daemon = MHD_start_daemon(flags, 0,
- NULL, NULL,
- request_handler, NULL,
- MHD_OPTION_ARRAY, opts,
- MHD_OPTION_END);
+ d->daemon = sym_MHD_start_daemon(
+ flags,
+ /* port= */ 0,
+ /* acp= */ NULL,
+ /* acp_cls= */ NULL,
+ request_handler,
+ /* dh_cls= */ NULL,
+ MHD_OPTION_ARRAY,
+ opts,
+ MHD_OPTION_END);
if (!d->daemon)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to start μhttp daemon");
log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)",
key ? "HTTPS" : "HTTP", fd, d);
- info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
+ info = sym_MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
if (!info)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "μhttp returned NULL daemon info");
@@ -607,12 +620,12 @@ static int dispatch_http_event(sd_event_source *event,
int r;
MHD_UNSIGNED_LONG_LONG timeout = ULLONG_MAX;
- r = MHD_run(d->daemon);
+ r = sym_MHD_run(d->daemon);
if (r == MHD_NO)
// FIXME: unregister daemon
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"MHD_run failed!");
- if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO)
+ if (sym_MHD_get_timeout(d->daemon, &timeout) == MHD_NO)
timeout = ULLONG_MAX;
r = sd_event_source_set_time(d->timer_event, timeout);
@@ -828,6 +841,22 @@ static int parse_config(void) {
{}
};
+ const char *config_file = secure_getenv("SYSTEMD_JOURNAL_REMOTE_CONFIG_FILE");
+ if (config_file) {
+ if (isempty(config_file) || path_equal(config_file, "/dev/null"))
+ return 0;
+
+ return config_parse(
+ /* unit= */ NULL,
+ config_file,
+ /* f= */ NULL,
+ "Remote\0",
+ config_item_table_lookup, items,
+ CONFIG_PARSE_WARN,
+ /* userdata= */ NULL,
+ /* ret_stat= */ NULL);
+ }
+
return config_parse_standard_file_with_dropins(
"systemd/journal-remote.conf",
"Remote\0",
@@ -838,155 +867,120 @@ static int parse_config(void) {
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("systemd-journal-remote.service", "8", &link);
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...] {FILE|-}...\n\n"
- "Write external journal events to journal file(s).\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --url=URL Read events from systemd-journal-gatewayd at URL\n"
- " --getter=COMMAND Read events from the output of COMMAND\n"
- " --listen-raw=ADDR Listen for connections at ADDR\n"
- " --listen-http=ADDR Listen for HTTP connections at ADDR\n"
- " --listen-https=ADDR Listen for HTTPS connections at ADDR\n"
- " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n"
- " --compress[=BOOL] Use compression in the output journal (default: yes)\n"
- " --seal[=BOOL] Use event sealing (default: no)\n"
- " --key=FILENAME SSL key in PEM format (default:\n"
- " \"" PRIV_KEY_FILE "\")\n"
- " --cert=FILENAME SSL certificate in PEM format (default:\n"
- " \"" CERT_FILE "\")\n"
- " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n"
- " \"" TRUST_FILE "\")\n"
- " --gnutls-log=CATEGORY...\n"
- " Specify a list of gnutls logging categories\n"
- " --split-mode=none|host How many output files to create\n"
- "\nNote: file descriptors from sd_listen_fds() will be consumed, too.\n"
- "\nSee the %s for details.\n",
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ printf("%s [OPTIONS...] {FILE|-}...\n"
+ "\n%sWrite external journal events to journal file(s).%s\n"
+ "\n%sOptions:%s\n",
program_invocation_short_name,
+ ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nNote: file descriptors from sd_listen_fds() will be consumed, too.\n"
+ "\nSee the %s for details.\n",
link);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_URL,
- ARG_LISTEN_RAW,
- ARG_LISTEN_HTTP,
- ARG_LISTEN_HTTPS,
- ARG_GETTER,
- ARG_SPLIT_MODE,
- ARG_COMPRESS,
- ARG_SEAL,
- ARG_KEY,
- ARG_CERT,
- ARG_TRUST,
- ARG_GNUTLS_LOG,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "url", required_argument, NULL, ARG_URL },
- { "getter", required_argument, NULL, ARG_GETTER },
- { "listen-raw", required_argument, NULL, ARG_LISTEN_RAW },
- { "listen-http", required_argument, NULL, ARG_LISTEN_HTTP },
- { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS },
- { "output", required_argument, NULL, 'o' },
- { "split-mode", required_argument, NULL, ARG_SPLIT_MODE },
- { "compress", optional_argument, NULL, ARG_COMPRESS },
- { "seal", optional_argument, NULL, ARG_SEAL },
- { "key", required_argument, NULL, ARG_KEY },
- { "cert", required_argument, NULL, ARG_CERT },
- { "trust", required_argument, NULL, ARG_TRUST },
- { "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG },
- {}
- };
-
- int c, r;
+ int r;
bool type_a, type_b;
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_URL:
- r = free_and_strdup_warn(&arg_url, optarg);
+ OPTION_LONG("url", "URL", "Read events from systemd-journal-gatewayd at URL"):
+ r = free_and_strdup_warn(&arg_url, arg);
if (r < 0)
return r;
break;
- case ARG_GETTER:
- r = free_and_strdup_warn(&arg_getter, optarg);
+ OPTION_LONG("getter", "COMMAND", "Read events from the output of COMMAND"):
+ r = free_and_strdup_warn(&arg_getter, arg);
if (r < 0)
return r;
break;
- case ARG_LISTEN_RAW:
- r = free_and_strdup_warn(&arg_listen_raw, optarg);
+ OPTION_LONG("listen-raw", "ADDR", "Listen for connections at ADDR"):
+ r = free_and_strdup_warn(&arg_listen_raw, arg);
if (r < 0)
return r;
break;
- case ARG_LISTEN_HTTP:
+ OPTION_LONG("listen-http", "ADDR", "Listen for HTTP connections at ADDR"):
if (arg_listen_http || http_socket >= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Cannot currently use --listen-http= more than once");
- r = negative_fd(optarg);
+ r = negative_fd(arg);
if (r >= 0)
http_socket = r;
else {
- r = free_and_strdup_warn(&arg_listen_http, optarg);
+ r = free_and_strdup_warn(&arg_listen_http, arg);
if (r < 0)
return r;
}
break;
- case ARG_LISTEN_HTTPS:
+ OPTION_LONG("listen-https", "ADDR", "Listen for HTTPS connections at ADDR"):
if (arg_listen_https || https_socket >= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Cannot currently use --listen-https= more than once");
- r = negative_fd(optarg);
+ r = negative_fd(arg);
if (r >= 0)
https_socket = r;
else {
- r = free_and_strdup_warn(&arg_listen_https, optarg);
+ r = free_and_strdup_warn(&arg_listen_https, arg);
if (r < 0)
return r;
}
break;
- case ARG_KEY:
- r = free_and_strdup_warn(&arg_key, optarg);
+ OPTION_LONG("key", "FILENAME", "SSL key in PEM format (default: \"" PRIV_KEY_FILE "\")"):
+ r = free_and_strdup_warn(&arg_key, arg);
if (r < 0)
return r;
break;
- case ARG_CERT:
- r = free_and_strdup_warn(&arg_cert, optarg);
+ OPTION_LONG("cert", "FILENAME", "SSL certificate in PEM format (default: \"" CERT_FILE "\")"):
+ r = free_and_strdup_warn(&arg_cert, arg);
if (r < 0)
return r;
break;
- case ARG_TRUST:
+ OPTION_LONG("trust", "FILENAME|all",
+ "SSL CA certificate or disable checking (default: \"" TRUST_FILE "\")"):
#if HAVE_GNUTLS
- r = free_and_strdup_warn(&arg_trust, optarg);
+ r = free_and_strdup_warn(&arg_trust, arg);
if (r < 0)
return r;
#else
@@ -994,33 +988,35 @@ static int parse_argv(int argc, char *argv[]) {
#endif
break;
- case 'o':
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_output);
+ OPTION('o', "output", "FILE|DIR", "Write output to FILE or DIR/external-*.journal"):
+ r = parse_path_argument(arg, /* suppress_root= */ false, &arg_output);
if (r < 0)
return r;
break;
- case ARG_SPLIT_MODE:
- arg_split_mode = journal_write_split_mode_from_string(optarg);
+ OPTION_LONG("split-mode", "none|host", "How many output files to create"):
+ arg_split_mode = journal_write_split_mode_from_string(arg);
if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID)
- return log_error_errno(arg_split_mode, "Invalid split mode: %s", optarg);
+ return log_error_errno(arg_split_mode, "Invalid split mode: %s", arg);
break;
- case ARG_COMPRESS:
- r = parse_boolean_argument("--compress", optarg, &arg_compress);
+ OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "compress", "BOOL",
+ "Use compression in the output journal (default: yes)"):
+ r = parse_boolean_argument("--compress", arg, &arg_compress);
if (r < 0)
return r;
break;
- case ARG_SEAL:
- r = parse_boolean_argument("--seal", optarg, &arg_seal);
+ OPTION_LONG_FLAGS(OPTION_OPTIONAL_ARG, "seal", "BOOL",
+ "Use event sealing (default: no)"):
+ r = parse_boolean_argument("--seal", arg, &arg_seal);
if (r < 0)
return r;
break;
- case ARG_GNUTLS_LOG:
+ OPTION_LONG("gnutls-log", "CATEGORY,...", "Specify a list of gnutls logging categories"):
#if HAVE_GNUTLS
- for (const char *p = optarg;;) {
+ for (const char *p = arg;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, ",", 0);
@@ -1037,14 +1033,32 @@ static int parse_argv(int argc, char *argv[]) {
#endif
break;
- case '?':
- return -EINVAL;
+ OPTION_LONG("max-use", "BYTES", "Maximum disk space to use"):
+ r = parse_size(arg, 1024, &arg_max_use);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --max-use= value: %s", arg);
+ break;
- default:
- assert_not_reached();
+ OPTION_LONG("keep-free", "BYTES", "Minimum disk space to keep free"):
+ r = parse_size(arg, 1024, &arg_keep_free);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --keep-free= value: %s", arg);
+ break;
+
+ OPTION_LONG("max-file-size", "BYTES", "Maximum size of individual journal files"):
+ r = parse_size(arg, 1024, &arg_max_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --max-file-size= value: %s", arg);
+ break;
+
+ OPTION_LONG("max-files", "N", "Maximum number of journal files to keep"):
+ r = safe_atou64(arg, &arg_n_max_files);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --max-files= value: %s", arg);
+ break;
}
- arg_files = strv_copy(strv_skip(argv, optind));
+ arg_files = strv_copy(option_parser_get_args(&state));
if (!arg_files)
return log_oom();
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index cd24dec34e..23bb48f687 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -924,7 +924,7 @@ static int run(int argc, char **argv) {
if (r <= 0)
return r;
- r = dlopen_curl();
+ r = dlopen_curl(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build
index c8d97526d3..f6aa71349c 100644
--- a/src/journal-remote/meson.build
+++ b/src/journal-remote/meson.build
@@ -3,9 +3,6 @@
systemd_journal_gatewayd_sources = files(
'journal-gatewayd.c',
)
-systemd_journal_gatewayd_extract_sources = files(
- 'microhttpd-util.c',
-)
systemd_journal_remote_sources = files('journal-remote-main.c')
systemd_journal_remote_extract_sources = files(
@@ -24,7 +21,7 @@ systemd_journal_upload_extract_sources = files(
)
common_deps = [
- libgnutls,
+ libgnutls_cflags,
liblz4_cflags,
libxz_cflags,
libzstd_cflags,
@@ -40,8 +37,7 @@ executables += [
'HAVE_MICROHTTPD',
],
'sources' : systemd_journal_gatewayd_sources,
- 'extract' : systemd_journal_gatewayd_extract_sources,
- 'dependencies' : common_deps + [libmicrohttpd],
+ 'dependencies' : common_deps + [libmicrohttpd_cflags],
},
libexec_template + {
'name' : 'systemd-journal-remote',
@@ -52,8 +48,7 @@ executables += [
'install' : conf.get('ENABLE_REMOTE') == 1,
'sources' : systemd_journal_remote_sources,
'extract' : systemd_journal_remote_extract_sources,
- 'objects' : conf.get('HAVE_MICROHTTPD') == 1 ? ['systemd-journal-gatewayd'] : [],
- 'dependencies' : common_deps + [libmicrohttpd],
+ 'dependencies' : common_deps + [libmicrohttpd_cflags],
},
libexec_template + {
'name' : 'systemd-journal-upload',
@@ -75,7 +70,7 @@ executables += [
fuzz_template + {
'sources' : files('fuzz-journal-remote.c'),
'objects' : ['systemd-journal-remote'],
- 'dependencies' : common_deps + [libmicrohttpd],
+ 'dependencies' : common_deps + [libmicrohttpd_cflags],
},
]
diff --git a/src/journal/meson.build b/src/journal/meson.build
index 5f64304219..142d2246c1 100644
--- a/src/journal/meson.build
+++ b/src/journal/meson.build
@@ -19,9 +19,6 @@ systemd_journald_extract_sources = files(
'journald-syslog.c',
'journald-varlink.c',
'journald-wall.c',
- # Build fuzz-journald.c as part of systemd-journald so we only compile it once instead of once per
- # fuzz test.
- 'fuzz-journald-util.c',
)
journald_gperf_c = custom_target(
@@ -58,7 +55,10 @@ journal_test_template = test_template + {
}
journal_fuzz_template = fuzz_template + {
- 'objects' : ['systemd-journald'],
+ 'objects' : [
+ 'fuzz-journald-audit',
+ 'systemd-journald',
+ ],
'dependencies' : libselinux_cflags,
}
@@ -133,8 +133,11 @@ executables += [
libselinux_cflags,
],
},
- journal_fuzz_template + {
+ fuzz_template + {
'sources' : files('fuzz-journald-audit.c'),
+ # fuzz-journald-util.c is shared with the other fuzzers below.
+ 'extract' : files('fuzz-journald-util.c'),
+ 'objects' : ['systemd-journald'],
},
journal_fuzz_template + {
'sources' : files('fuzz-journald-kmsg.c'),
diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c
index 516527aa2b..dcdd264226 100644
--- a/src/keyutil/keyutil.c
+++ b/src/keyutil/keyutil.c
@@ -1,16 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
-
#include "alloc-util.h"
#include "ask-password-api.h"
#include "build.h"
#include "fd-util.h"
#include "fileio.h"
+#include "format-table.h"
#include "fs-util.h"
#include "log.h"
#include "main-func.h"
#include "openssl-util.h"
+#include "options.h"
#include "parse-argument.h"
#include "pretty-print.h"
#include "string-util.h"
@@ -25,7 +25,7 @@ static char *arg_certificate_source = NULL;
static CertificateSourceType arg_certificate_source_type = OPENSSL_CERTIFICATE_SOURCE_FILE;
static char *arg_signature = NULL;
static char *arg_content = NULL;
-static char *arg_hash_algorithm = NULL;
+static const char *arg_hash_algorithm = NULL;
static char *arg_output = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_private_key, freep);
@@ -38,164 +38,137 @@ STATIC_DESTRUCTOR_REGISTER(arg_output, freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL, *verbs = NULL;
int r;
r = terminal_urlify_man("systemd-keyutil", "1", &link);
if (r < 0)
return log_oom();
- printf("%1$s [OPTIONS...] COMMAND ...\n"
- "\n%5$sPerform various operations on private keys and certificates.%6$s\n"
- "\n%3$sCommands:%4$s\n"
- " validate Load and validate the given certificate and private key\n"
- " extract-public Extract a public key\n"
- " extract-certificate Extract a certificate\n"
- " pkcs7 Generate a PKCS#7 signature\n"
- "\n%3$sOptions:%4$s\n"
- " -h --help Show this help\n"
- " --version Print version\n"
- " --private-key=KEY Private key in PEM format\n"
- " --private-key-source=file|provider:PROVIDER|engine:ENGINE\n"
- " Specify how to use KEY for --private-key=. Allows\n"
- " an OpenSSL engine/provider to be used for signing\n"
- " --certificate=PATH|URI\n"
- " PEM certificate to use for signing, or a provider\n"
- " specific designation if --certificate-source= is used\n"
- " --certificate-source=file|provider:PROVIDER\n"
- " Specify how to interpret the certificate from\n"
- " --certificate=. Allows the certificate to be loaded\n"
- " from an OpenSSL provider\n"
- " --content=PATH Raw data content to embed in PKCS#7 signature\n"
- " --signature=PATH PKCS#1 signature to embed in PKCS#7 signature\n"
- " --hash-algorithm=ALGORITHM\n"
- " Hash algorithm used to create the PKCS#1 signature\n"
- " --output=PATH Where to write the PKCS#7 signature\n"
- "\nSee the %2$s for details.\n",
+ r = verbs_get_help_table(&verbs);
+ if (r < 0)
+ return r;
+
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ (void) table_sync_column_widths(0, verbs, options);
+
+ printf("%s [OPTIONS...] COMMAND ...\n\n"
+ "%sPerform various operations on private keys and certificates.%s\n"
+ "\n%sCommands:%s\n",
program_invocation_short_name,
- link,
- ansi_underline(),
- ansi_normal(),
ansi_highlight(),
+ ansi_normal(),
+ ansi_underline(),
ansi_normal());
+ r = table_print_or_warn(verbs);
+ if (r < 0)
+ return r;
+
+ printf("\n%sOptions:%s\n",
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
-static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) {
- return help();
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_PRIVATE_KEY,
- ARG_PRIVATE_KEY_SOURCE,
- ARG_CERTIFICATE,
- ARG_CERTIFICATE_SOURCE,
- ARG_SIGNATURE,
- ARG_CONTENT,
- ARG_HASH_ALGORITHM,
- ARG_OUTPUT,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "private-key", required_argument, NULL, ARG_PRIVATE_KEY },
- { "private-key-source", required_argument, NULL, ARG_PRIVATE_KEY_SOURCE },
- { "certificate", required_argument, NULL, ARG_CERTIFICATE },
- { "certificate-source", required_argument, NULL, ARG_CERTIFICATE_SOURCE },
- { "signature", required_argument, NULL, ARG_SIGNATURE },
- { "content", required_argument, NULL, ARG_CONTENT },
- { "hash-algorithm", required_argument, NULL, ARG_HASH_ALGORITHM },
- { "output", required_argument, NULL, ARG_OUTPUT },
- {}
- };
-
- int c, r;
+VERB_COMMON_HELP_HIDDEN(help);
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+ int r;
+
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_PRIVATE_KEY:
- r = free_and_strdup_warn(&arg_private_key, optarg);
+ OPTION_LONG("private-key", "KEY", "Private key in PEM format"):
+ r = free_and_strdup_warn(&arg_private_key, arg);
if (r < 0)
return r;
-
break;
- case ARG_PRIVATE_KEY_SOURCE:
+ OPTION_LONG("private-key-source", "SOURCE",
+ "Specify how to use KEY for --private-key= "
+ "(file, provider:PROVIDER, engine:ENGINE)"):
r = parse_openssl_key_source_argument(
- optarg,
+ arg,
&arg_private_key_source,
&arg_private_key_source_type);
if (r < 0)
return r;
-
break;
- case ARG_CERTIFICATE:
- r = free_and_strdup_warn(&arg_certificate, optarg);
+ OPTION_LONG("certificate", "PATH|URI",
+ "PEM certificate to use for signing, "
+ "or a provider-specific designation if --certificate-source= is used"):
+ r = free_and_strdup_warn(&arg_certificate, arg);
if (r < 0)
return r;
break;
- case ARG_CERTIFICATE_SOURCE:
+ OPTION_LONG("certificate-source", "SOURCE",
+ "Specify how to interpret the certificate from --certificate= "
+ "(file, provider:PROVIDER)"):
r = parse_openssl_certificate_source_argument(
- optarg,
+ arg,
&arg_certificate_source,
&arg_certificate_source_type);
if (r < 0)
return r;
break;
- case ARG_SIGNATURE:
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_signature);
+ OPTION_LONG("signature", "PATH", "PKCS#1 signature to embed in PKCS#7 signature"):
+ r = parse_path_argument(arg, /* suppress_root= */ false, &arg_signature);
if (r < 0)
return r;
-
break;
- case ARG_CONTENT:
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_content);
+ OPTION_LONG("content", "PATH", "Raw data content to embed in PKCS#7 signature"):
+ r = parse_path_argument(arg, /* suppress_root= */ false, &arg_content);
if (r < 0)
return r;
-
break;
- case ARG_HASH_ALGORITHM:
- arg_hash_algorithm = optarg;
+ OPTION_LONG("hash-algorithm", "ALGORITHM",
+ "Hash algorithm used to create the PKCS#1 signature"):
+ arg_hash_algorithm = arg;
break;
- case ARG_OUTPUT:
- r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_output);
+ OPTION_LONG("output", "PATH", "Where to write the PKCS#7 signature"):
+ r = parse_path_argument(arg, /* suppress_root= */ false, &arg_output);
if (r < 0)
return r;
-
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
if (arg_private_key_source && !arg_certificate)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "When using --private-key-source=, --certificate= must be specified.");
+ *ret_args = option_parser_get_args(&state);
return 1;
}
+VERB_NOARG(verb_validate, "validate",
+ "Load and validate the given certificate and private key");
static int verb_validate(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(X509_freep) X509 *certificate = NULL;
_cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
@@ -251,6 +224,9 @@ static int verb_validate(int argc, char *argv[], uintptr_t _data, void *userdata
return 0;
}
+VERB_NOARG(verb_extract_public, "extract-public",
+ "Extract a public key");
+VERB(verb_extract_public, "public", NULL, VERB_ANY, 1, 0, NULL); /* Deprecated alias */
static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(EVP_PKEY_freep) EVP_PKEY *public_key = NULL;
int r;
@@ -318,6 +294,8 @@ static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *us
return 0;
}
+VERB_NOARG(verb_extract_certificate, "extract-certificate",
+ "Extract a certificate");
static int verb_extract_certificate(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(X509_freep) X509 *certificate = NULL;
int r;
@@ -345,6 +323,8 @@ static int verb_extract_certificate(int argc, char *argv[], uintptr_t _data, voi
return 0;
}
+VERB(verb_pkcs7, "pkcs7", NULL, VERB_ANY, VERB_ANY, 0,
+ "Generate a PKCS#7 signature");
static int verb_pkcs7(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(X509_freep) X509 *certificate = NULL;
_cleanup_free_ char *pkcs1 = NULL;
@@ -429,24 +409,16 @@ static int verb_pkcs7(int argc, char *argv[], uintptr_t _data, void *userdata) {
}
static int run(int argc, char *argv[]) {
- static const Verb verbs[] = {
- { "help", VERB_ANY, VERB_ANY, 0, verb_help },
- { "validate", VERB_ANY, 1, 0, verb_validate },
- { "extract-public", VERB_ANY, 1, 0, verb_extract_public },
- { "public", VERB_ANY, 1, 0, verb_extract_public }, /* Deprecated but kept for backwards compat. */
- { "extract-certificate", VERB_ANY, 1, 0, verb_extract_certificate },
- { "pkcs7", VERB_ANY, VERB_ANY, 0, verb_pkcs7 },
- {}
- };
int r;
log_setup();
- r = parse_argv(argc, argv);
+ char **args = NULL;
+ r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
- return dispatch_verb(argc, argv, verbs, NULL);
+ return dispatch_verb_with_args(args, NULL);
}
DEFINE_MAIN_FUNCTION(run);
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index c78e3cdad9..a195a4b098 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -427,7 +427,7 @@ int dhcp_option_parse_string(const uint8_t *option, size_t len, char **ret) {
if (r < 0)
return r;
- if (!string_is_safe(string) || !utf8_is_valid(string))
+ if (!string_is_safe(string, STRING_ALLOW_EMPTY|STRING_ALLOW_GLOBS))
return -EINVAL;
*ret = TAKE_PTR(string);
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 34ed3e10d3..fa0b830196 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -271,7 +271,9 @@ int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name
int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename) {
assert_return(server, -EINVAL);
- if (filename && !string_is_safe_ascii(filename))
+ if (isempty(filename))
+ filename = NULL;
+ else if (!string_is_safe(filename, STRING_ASCII|STRING_ALLOW_GLOBS))
return -EINVAL;
return free_and_strdup(&server->boot_filename, filename);
diff --git a/src/libsystemd-network/test-ndisc-send.c b/src/libsystemd-network/test-ndisc-send.c
index 247cc0ec16..e0bbcfe6c2 100644
--- a/src/libsystemd-network/test-ndisc-send.c
+++ b/src/libsystemd-network/test-ndisc-send.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include "sd-ndisc-protocol.h"
@@ -17,6 +16,7 @@
#include "ndisc-option.h"
#include "netlink-util.h"
#include "network-common.h"
+#include "options.h"
#include "parse-util.h"
#include "set.h"
#include "string-util.h"
@@ -72,197 +72,158 @@ static int parse_preference(const char *str) {
}
static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_RA_HOP_LIMIT,
- ARG_RA_MANAGED,
- ARG_RA_OTHER,
- ARG_RA_HOME_AGENT,
- ARG_RA_PREFERENCE,
- ARG_RA_LIFETIME,
- ARG_RA_REACHABLE,
- ARG_RA_RETRANSMIT,
- ARG_NA_ROUTER,
- ARG_NA_SOLICITED,
- ARG_NA_OVERRIDE,
- ARG_TARGET_ADDRESS,
- ARG_REDIRECT_DESTINATION,
- ARG_OPTION_SOURCE_LL,
- ARG_OPTION_TARGET_LL,
- ARG_OPTION_REDIRECTED_HEADER,
- ARG_OPTION_MTU,
- };
-
- static const struct option options[] = {
- { "version", no_argument, NULL, ARG_VERSION },
- { "interface", required_argument, NULL, 'i' },
- { "type", required_argument, NULL, 't' },
- { "dest", required_argument, NULL, 'd' },
- /* For Router Advertisement */
- { "hop-limit", required_argument, NULL, ARG_RA_HOP_LIMIT },
- { "managed", required_argument, NULL, ARG_RA_MANAGED },
- { "other", required_argument, NULL, ARG_RA_OTHER },
- { "home-agent", required_argument, NULL, ARG_RA_HOME_AGENT },
- { "preference", required_argument, NULL, ARG_RA_PREFERENCE },
- { "lifetime", required_argument, NULL, ARG_RA_LIFETIME },
- { "reachable-time", required_argument, NULL, ARG_RA_REACHABLE },
- { "retransmit-timer", required_argument, NULL, ARG_RA_RETRANSMIT },
- /* For Neighbor Advertisement */
- { "is-router", required_argument, NULL, ARG_NA_ROUTER },
- { "is-solicited", required_argument, NULL, ARG_NA_SOLICITED },
- { "is-override", required_argument, NULL, ARG_NA_OVERRIDE },
- /* For Neighbor Solicit, Neighbor Advertisement, and Redirect */
- { "target-address", required_argument, NULL, ARG_TARGET_ADDRESS },
- /* For Redirect */
- { "redirect-destination", required_argument, NULL, ARG_REDIRECT_DESTINATION },
- /* Options */
- { "source-ll-address", required_argument, NULL, ARG_OPTION_SOURCE_LL },
- { "target-ll-address", required_argument, NULL, ARG_OPTION_TARGET_LL },
- { "redirected-header", required_argument, NULL, ARG_OPTION_REDIRECTED_HEADER },
- { "mtu", required_argument, NULL, ARG_OPTION_MTU },
- {}
- };
-
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- int c, r;
+ int r;
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "i:t:d:", options, NULL)) >= 0) {
+ OptionParser state = { argc, argv };
+ const char *arg;
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case 'i':
- r = rtnl_resolve_interface_or_warn(&rtnl, optarg);
+ OPTION('i', "interface", "INTERFACE", "Network interface"):
+ r = rtnl_resolve_interface_or_warn(&rtnl, arg);
if (r < 0)
return r;
arg_ifindex = r;
break;
- case 't':
- r = parse_icmp6_type(optarg);
+ OPTION('t', "type", "TYPE", "ICMPv6 message type"):
+ r = parse_icmp6_type(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse message type: %m");
arg_icmp6_type = r;
break;
- case 'd':
- r = in_addr_from_string(AF_INET6, optarg, &arg_dest);
+ OPTION('d', "dest", "ADDRESS", "Destination address"):
+ r = in_addr_from_string(AF_INET6, arg, &arg_dest);
if (r < 0)
return log_error_errno(r, "Failed to parse destination address: %m");
if (!in6_addr_is_link_local(&arg_dest.in6))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "The destination address %s is not a link-local address.", optarg);
+ "The destination address %s is not a link-local address.", arg);
break;
- case ARG_RA_HOP_LIMIT:
- r = safe_atou8(optarg, &arg_hop_limit);
+ OPTION_GROUP("Router Advertisement"): {}
+
+ OPTION_LONG("hop-limit", "LIMIT", "Hop limit"):
+ r = safe_atou8(arg, &arg_hop_limit);
if (r < 0)
return log_error_errno(r, "Failed to parse hop limit: %m");
break;
- case ARG_RA_MANAGED:
- r = parse_boolean(optarg);
+ OPTION_LONG("managed", "BOOL", "Managed flag"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse managed flag: %m");
SET_FLAG(arg_ra_flags, ND_RA_FLAG_MANAGED, r);
break;
- case ARG_RA_OTHER:
- r = parse_boolean(optarg);
+ OPTION_LONG("other", "BOOL", "Other flag"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse other flag: %m");
SET_FLAG(arg_ra_flags, ND_RA_FLAG_OTHER, r);
break;
- case ARG_RA_HOME_AGENT:
- r = parse_boolean(optarg);
+ OPTION_LONG("home-agent", "BOOL", "Home-agent flag"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse home-agent flag: %m");
SET_FLAG(arg_ra_flags, ND_RA_FLAG_HOME_AGENT, r);
break;
- case ARG_RA_PREFERENCE:
- r = parse_preference(optarg);
+ OPTION_LONG("preference", "PREF", "Preference"):
+ r = parse_preference(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse preference: %m");
arg_preference = r;
break;
- case ARG_RA_LIFETIME:
- r = parse_sec(optarg, &arg_lifetime);
+ OPTION_LONG("lifetime", "SECS", "Lifetime"):
+ r = parse_sec(arg, &arg_lifetime);
if (r < 0)
return log_error_errno(r, "Failed to parse lifetime: %m");
break;
- case ARG_RA_REACHABLE:
- r = parse_sec(optarg, &arg_reachable);
+ OPTION_LONG("reachable-time", "SECS", "Reachable time"):
+ r = parse_sec(arg, &arg_reachable);
if (r < 0)
return log_error_errno(r, "Failed to parse reachable time: %m");
break;
- case ARG_RA_RETRANSMIT:
- r = parse_sec(optarg, &arg_retransmit);
+ OPTION_LONG("retransmit-timer", "SECS", "Retransmit timer"):
+ r = parse_sec(arg, &arg_retransmit);
if (r < 0)
return log_error_errno(r, "Failed to parse retransmit timer: %m");
break;
- case ARG_NA_ROUTER:
- r = parse_boolean(optarg);
+ OPTION_GROUP("Neighbor Advertisement"): {}
+
+ OPTION_LONG("is-router", "BOOL", "Router flag"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse is-router flag: %m");
SET_FLAG(arg_na_flags, ND_NA_FLAG_ROUTER, r);
break;
- case ARG_NA_SOLICITED:
- r = parse_boolean(optarg);
+ OPTION_LONG("is-solicited", "BOOL", "Solicited flag"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse is-solicited flag: %m");
SET_FLAG(arg_na_flags, ND_NA_FLAG_SOLICITED, r);
break;
- case ARG_NA_OVERRIDE:
- r = parse_boolean(optarg);
+ OPTION_LONG("is-override", "BOOL", "Override flag"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse is-override flag: %m");
SET_FLAG(arg_na_flags, ND_NA_FLAG_OVERRIDE, r);
break;
- case ARG_TARGET_ADDRESS:
- r = in_addr_from_string(AF_INET6, optarg, &arg_target_address);
+ OPTION_GROUP("Neighbor Solicit/Advertisement and Redirect"): {}
+
+ OPTION_LONG("target-address", "ADDRESS", "Target address"):
+ r = in_addr_from_string(AF_INET6, arg, &arg_target_address);
if (r < 0)
return log_error_errno(r, "Failed to parse target address: %m");
break;
- case ARG_REDIRECT_DESTINATION:
- r = in_addr_from_string(AF_INET6, optarg, &arg_redirect_destination);
+ OPTION_GROUP("Redirect"): {}
+
+ OPTION_LONG("redirect-destination", "ADDRESS", "Redirect destination address"):
+ r = in_addr_from_string(AF_INET6, arg, &arg_redirect_destination);
if (r < 0)
return log_error_errno(r, "Failed to parse destination address: %m");
break;
- case ARG_OPTION_SOURCE_LL:
- r = parse_boolean(optarg);
+ OPTION_GROUP("NDisc Options"): {}
+
+ OPTION_LONG("source-ll-address", "BOOL", "Include source link-layer address"):
+ r = parse_boolean(arg);
if (r < 0)
return log_error_errno(r, "Failed to parse source LL address option: %m");
arg_set_source_mac = r;
break;
- case ARG_OPTION_TARGET_LL:
- r = parse_ether_addr(optarg, &arg_target_mac);
+ OPTION_LONG("target-ll-address", "ADDRESS", "Target link-layer address"):
+ r = parse_ether_addr(arg, &arg_target_mac);
if (r < 0)
return log_error_errno(r, "Failed to parse target LL address option: %m");
arg_set_target_mac = true;
break;
- case ARG_OPTION_REDIRECTED_HEADER: {
+ OPTION_LONG("redirected-header", "BASE64", "Redirected header (base64)"): {
_cleanup_free_ void *p = NULL;
size_t len;
- r = unbase64mem(optarg, &p, &len);
+ r = unbase64mem(arg, &p, &len);
if (r < 0)
return log_error_errno(r, "Failed to parse redirected header: %m");
@@ -272,20 +233,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_redirected_header = TAKE_PTR(p);
break;
}
- case ARG_OPTION_MTU:
- r = safe_atou32(optarg, &arg_mtu);
+
+ OPTION_LONG("mtu", "MTU", "MTU"):
+ r = safe_atou32(arg, &arg_mtu);
if (r < 0)
return log_error_errno(r, "Failed to parse MTU: %m");
arg_set_mtu = true;
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
- }
if (arg_ifindex <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--interface/-i option is mandatory.");
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 041dc48216..94be969f7f 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -1498,9 +1498,6 @@ _public_ int sd_bus_message_append_string_iovec(
const struct iovec *iov,
unsigned n /* should be size_t, but is API now… 😞 */) {
- size_t size;
- unsigned i;
- char *p;
int r;
assert_return(m, -EINVAL);
@@ -1508,13 +1505,16 @@ _public_ int sd_bus_message_append_string_iovec(
assert_return(iov || n == 0, -EINVAL);
assert_return(!m->poisoned, -ESTALE);
- size = iovec_total_size(iov, n);
+ size_t size = iovec_total_size(iov, n);
+ if (size == SIZE_MAX)
+ return -ENOBUFS;
+ char *p;
r = sd_bus_message_append_string_space(m, size, &p);
if (r < 0)
return r;
- for (i = 0; i < n; i++) {
+ for (unsigned i = 0; i < n; i++) {
if (iov[i].iov_base)
memcpy(p, iov[i].iov_base, iov[i].iov_len);
@@ -2160,9 +2160,6 @@ _public_ int sd_bus_message_append_array_iovec(
const struct iovec *iov,
unsigned n /* should be size_t, but is API now… 😞 */) {
- size_t size;
- unsigned i;
- void *p;
int r;
assert_return(m, -EINVAL);
@@ -2171,13 +2168,16 @@ _public_ int sd_bus_message_append_array_iovec(
assert_return(iov || n == 0, -EINVAL);
assert_return(!m->poisoned, -ESTALE);
- size = iovec_total_size(iov, n);
+ size_t size = iovec_total_size(iov, n);
+ if (size == SIZE_MAX)
+ return -ENOBUFS;
+ void *p;
r = sd_bus_message_append_array_space(m, type, size, &p);
if (r < 0)
return r;
- for (i = 0; i < n; i++) {
+ for (unsigned i = 0; i < n; i++) {
if (iov[i].iov_base)
memcpy(p, iov[i].iov_base, iov[i].iov_len);
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 2937ac569c..da5242c3b7 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -621,7 +621,7 @@ static int pid_notify_with_fds_internal(
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
}
- } while (!iovec_increment(msghdr.msg_iov, msghdr.msg_iovlen, n));
+ } while (!iovec_inc_many(msghdr.msg_iov, msghdr.msg_iovlen, n));
if (address.sockaddr.sa.sa_family == AF_VSOCK && IN_SET(type, SOCK_STREAM, SOCK_SEQPACKET)) {
/* For AF_VSOCK, we need to close the socket to signal the end of the message. */
diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c
index df1a6bc600..bf62e9082b 100644
--- a/src/libsystemd/sd-device/test-sd-device.c
+++ b/src/libsystemd/sd-device/test-sd-device.c
@@ -898,7 +898,7 @@ static int intro(void) {
if (path_is_mount_point("/sys") <= 0)
return log_tests_skipped("/sys/ is not mounted");
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return log_tests_skipped("libmount not available.");
diff --git a/src/libsystemd/sd-journal/journal-send.c b/src/libsystemd/sd-journal/journal-send.c
index 5c7b007b13..931e669a08 100644
--- a/src/libsystemd/sd-journal/journal-send.c
+++ b/src/libsystemd/sd-journal/journal-send.c
@@ -273,13 +273,11 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
}
if (!have_syslog_identifier &&
- string_is_safe(program_invocation_short_name)) {
+ string_is_safe(program_invocation_short_name, /* flags= */ 0)) {
- /* Implicitly add program_invocation_short_name, if it
- * is not set explicitly. We only do this for
- * program_invocation_short_name, and nothing else
- * since everything else is much nicer to retrieve
- * from the outside. */
+ /* Implicitly add program_invocation_short_name, if it is not set explicitly. We only do this
+ * for program_invocation_short_name, and nothing else since everything else is much nicer to
+ * retrieve from the outside. */
w[j++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=");
w[j++] = IOVEC_MAKE_STRING(program_invocation_short_name);
diff --git a/src/libsystemd/sd-journal/test-journal-append.c b/src/libsystemd/sd-journal/test-journal-append.c
index 605839169c..a07634a249 100644
--- a/src/libsystemd/sd-journal/test-journal-append.c
+++ b/src/libsystemd/sd-journal/test-journal-append.c
@@ -1,15 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include
-#include
#include
#include
#include "chattr-util.h"
+#include "format-table.h"
#include "iovec-util.h"
#include "journal-file-util.h"
#include "log.h"
#include "mmap-cache.h"
+#include "options.h"
#include "parse-util.h"
#include "random-util.h"
#include "rm-rf.h"
@@ -146,98 +147,81 @@ int main(int argc, char *argv[]) {
uint64_t iteration_step = 1;
uint64_t corrupt_step = 31;
bool sequential = false, run_one = false;
- int c, r;
+ int r;
test_setup_logging(LOG_DEBUG);
- enum {
- ARG_START_OFFSET = 0x1000,
- ARG_ITERATIONS,
- ARG_ITERATION_STEP,
- ARG_CORRUPT_STEP,
- ARG_SEQUENTIAL,
- ARG_RUN_ONE,
- };
+ OptionParser state = { argc, argv };
+ const char *arg;
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "start-offset", required_argument, NULL, ARG_START_OFFSET },
- { "iterations", required_argument, NULL, ARG_ITERATIONS },
- { "iteration-step", required_argument, NULL, ARG_ITERATION_STEP },
- { "corrupt-step", required_argument, NULL, ARG_CORRUPT_STEP },
- { "sequential", no_argument, NULL, ARG_SEQUENTIAL },
- { "run-one", required_argument, NULL, ARG_RUN_ONE },
- {}
- };
-
- ASSERT_GE(argc, 0);
- ASSERT_NOT_NULL(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP: {
+ _cleanup_(table_unrefp) Table *options = NULL;
+
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
printf("Syntax:\n"
" %s [OPTION...]\n"
- "Options:\n"
- " --start-offset=OFFSET Offset at which to start corrupting the journal\n"
- " (default: random offset is picked, unless\n"
- " --sequential is used - in that case we use 0 + iteration)\n"
- " --iterations=ITER Number of iterations to perform before exiting\n"
- " (default: 100)\n"
- " --iteration-step=STEP Iteration step (default: 1)\n"
- " --corrupt-step=STEP Corrupt every n-th byte starting from OFFSET (default: 31)\n"
- " --sequential Go through offsets sequentially instead of picking\n"
- " a random one on each iteration. If set, we go through\n"
- " offsets <0; ITER), or 0) {
+ /* $RUNTIME_DIRECTORY was not set, so we got the fallback path and need to create and
+ * clean up the directory ourselves. */
+ destroy = strdup(dir);
+ if (!destroy)
+ return -ENOMEM;
+
+ r = mkdir_p(dir, 0755);
+ if (r < 0)
+ return r;
+ }
+
+ /* When $RUNTIME_DIRECTORY is set the service manager created the directory for us and
+ * will destroy it (or preserve it, per RuntimeDirectoryPreserve=) when the service stops. */
+
+ *ret_dir = TAKE_PTR(dir);
+ *ret_dir_destroy = TAKE_PTR(destroy);
+
+ return 0;
+}
+
static const char* const user_data_unit_paths[] = {
"/usr/local/lib/systemd/user",
"/usr/local/share/systemd/user",
diff --git a/src/libsystemd/sd-path/path-lookup.h b/src/libsystemd/sd-path/path-lookup.h
index 67a4f5d69c..8dcbf766e6 100644
--- a/src/libsystemd/sd-path/path-lookup.h
+++ b/src/libsystemd/sd-path/path-lookup.h
@@ -60,6 +60,7 @@ void lookup_paths_done(LookupPaths *p);
int config_directory_generic(RuntimeScope scope, const char *suffix, char **ret);
int runtime_directory_generic(RuntimeScope scope, const char *suffix, char **ret);
int runtime_directory(RuntimeScope scope, const char *fallback_suffix, char **ret);
+int runtime_directory_make(RuntimeScope scope, const char *subdir, char **ret_dir, char **ret_dir_destroy);
/* We don't treat /etc/xdg/systemd/ in these functions as the xdg base dir spec suggests because we assume
* that is a link to /etc/systemd/ anyway. */
diff --git a/src/locale/localed-util.c b/src/locale/localed-util.c
index 3fe039a053..4cddfc32d9 100644
--- a/src/locale/localed-util.c
+++ b/src/locale/localed-util.c
@@ -319,7 +319,7 @@ int vconsole_write_data(Context *c) {
return 0;
}
- r = write_vconsole_conf(AT_FDCWD, "/etc/vconsole.conf", l);
+ r = write_vconsole_conf(AT_FDCWD, etc_vconsole_conf(), l);
if (r < 0)
return r;
diff --git a/src/locale/xkbcommon-util.c b/src/locale/xkbcommon-util.c
index c0810331a9..a55316c73a 100644
--- a/src/locale/xkbcommon-util.c
+++ b/src/locale/xkbcommon-util.c
@@ -16,14 +16,14 @@ DLSYM_PROTOTYPE(xkb_context_set_log_fn) = NULL;
DLSYM_PROTOTYPE(xkb_keymap_new_from_names) = NULL;
DLSYM_PROTOTYPE(xkb_keymap_unref) = NULL;
-static int dlopen_xkbcommon(void) {
+static int dlopen_xkbcommon(int log_level) {
SD_ELF_NOTE_DLOPEN(
"xkbcommon",
"Support for keyboard locale descriptions",
SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, "libxkbcommon.so.0");
return dlopen_many_sym_or_warn(
- &xkbcommon_dl, "libxkbcommon.so.0", LOG_DEBUG,
+ &xkbcommon_dl, "libxkbcommon.so.0", log_level,
DLSYM_ARG(xkb_context_new),
DLSYM_ARG(xkb_context_unref),
DLSYM_ARG(xkb_context_set_log_fn),
@@ -57,7 +57,7 @@ int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant,
/* Compile keymap from RMLVO information to check out its validity */
- r = dlopen_xkbcommon();
+ r = dlopen_xkbcommon(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 9668bf0609..14208bc149 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1155,7 +1155,7 @@ static int manager_create_session_by_bus(
if (isempty(desktop))
desktop = NULL;
else {
- if (!string_is_safe(desktop))
+ if (!string_is_safe(desktop, STRING_ALLOW_GLOBS))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid desktop string %s", desktop);
}
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index 6c70b8b1af..4e571e7056 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -1750,7 +1750,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
assert(pamh);
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_DEBUG);
if (r < 0)
return PAM_SERVICE_ERR;
diff --git a/src/login/pam_systemd_loadkey.c b/src/login/pam_systemd_loadkey.c
index 3e0df8c86b..93ccddc25b 100644
--- a/src/login/pam_systemd_loadkey.c
+++ b/src/login/pam_systemd_loadkey.c
@@ -19,7 +19,7 @@ _public_ PAM_EXTERN int pam_sm_authenticate(
assert(pamh);
- r = dlopen_libpam();
+ r = dlopen_libpam(LOG_DEBUG);
if (r < 0)
return PAM_SERVICE_ERR;
diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c
index 70774dcdd1..4fb7082112 100644
--- a/src/machine-id-setup/machine-id-setup-main.c
+++ b/src/machine-id-setup/machine-id-setup-main.c
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include "alloc-util.h"
#include "build.h"
#include "dissect-image.h"
+#include "format-table.h"
#include "id128-util.h"
#include "image-policy.h"
#include "log.h"
@@ -13,6 +13,7 @@
#include "machine-id-setup.h"
#include "main-func.h"
#include "mount-util.h"
+#include "options.h"
#include "parse-argument.h"
#include "pretty-print.h"
@@ -28,104 +29,95 @@ STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *commands = NULL, *options = NULL;
int r;
r = terminal_urlify_man("systemd-machine-id-setup", "1", &link);
if (r < 0)
return log_oom();
- printf("%1$s [OPTIONS...]\n"
- "\n%2$sInitialize /etc/machine-id from a random source.%4$s\n"
- "\n%3$sCommands:%4$s\n"
- " --commit Commit transient ID\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- "\n%3$sOptions:%4$s\n"
- " --root=PATH Operate on an alternate filesystem root\n"
- " --image=PATH Operate on disk image as filesystem root\n"
- " --image-policy=POLICY Specify disk image dissection policy\n"
- " --print Print used machine ID\n"
- "\nSee the %5$s for details.\n",
+ r = option_parser_get_help_table(&commands);
+ if (r < 0)
+ return r;
+
+ r = option_parser_get_help_table_group("Options", &options);
+ if (r < 0)
+ return r;
+
+ (void) table_sync_column_widths(0, commands, options);
+
+ printf("%s [OPTIONS...]\n\n"
+ "%sInitialize /etc/machine-id from a random source.%s\n"
+ "\n%sCommands:%s\n",
program_invocation_short_name,
ansi_highlight(),
- ansi_underline(),
ansi_normal(),
- link);
+ ansi_underline(),
+ ansi_normal());
+ r = table_print_or_warn(commands);
+ if (r < 0)
+ return r;
+
+ printf("\n%sOptions:%s\n",
+ ansi_underline(),
+ ansi_normal());
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_ROOT,
- ARG_IMAGE,
- ARG_IMAGE_POLICY,
- ARG_COMMIT,
- ARG_PRINT,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
- { "image", required_argument, NULL, ARG_IMAGE },
- { "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
- { "commit", no_argument, NULL, ARG_COMMIT },
- { "print", no_argument, NULL, ARG_PRINT },
- {}
- };
-
- int c, r;
-
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+ const char *arg;
+ int r;
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_ROOT:
- r = parse_path_argument(optarg, true, &arg_root);
- if (r < 0)
- return r;
- break;
-
- case ARG_IMAGE:
- r = parse_path_argument(optarg, false, &arg_image);
- if (r < 0)
- return r;
- break;
-
- case ARG_IMAGE_POLICY:
- r = parse_image_policy_argument(optarg, &arg_image_policy);
- if (r < 0)
- return r;
- break;
-
- case ARG_COMMIT:
+ OPTION_LONG("commit", NULL, "Commit transient ID"):
arg_commit = true;
break;
- case ARG_PRINT:
- arg_print = true;
+ OPTION_GROUP("Options"): {}
+
+ OPTION_LONG("root", "PATH", "Operate on an alternate filesystem root"):
+ r = parse_path_argument(arg, true, &arg_root);
+ if (r < 0)
+ return r;
break;
- case '?':
- return -EINVAL;
+ OPTION_LONG("image", "PATH", "Operate on disk image as filesystem root"):
+ r = parse_path_argument(arg, false, &arg_image);
+ if (r < 0)
+ return r;
+ break;
- default:
- assert_not_reached();
+ OPTION_LONG("image-policy", "POLICY", "Specify disk image dissection policy"):
+ r = parse_image_policy_argument(arg, &arg_image_policy);
+ if (r < 0)
+ return r;
+ break;
+
+ OPTION_LONG("print", NULL, "Print used machine ID"):
+ arg_print = true;
+ break;
}
- if (optind < argc)
+ if (option_parser_get_n_args(&state) > 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Extraneous arguments");
diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c
index e8aeb67f1f..5435de4e2e 100644
--- a/src/modules-load/modules-load.c
+++ b/src/modules-load/modules-load.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include
#include
@@ -15,10 +14,12 @@
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "format-table.h"
#include "log.h"
#include "macro.h"
#include "main-func.h"
#include "module-util.h"
+#include "options.h"
#include "ordered-set.h"
#include "parse-util.h"
#include "pretty-print.h"
@@ -331,53 +332,46 @@ static unsigned determine_num_worker_threads(unsigned n_modules) {
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL;
+ int r;
if (terminal_urlify_man("systemd-modules-load.service", "8", &link) < 0)
return log_oom();
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Loads statically configured kernel modules.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- "\nSee the %s for details.\n",
- program_invocation_short_name,
- link);
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+ printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
+ "Loads statically configured kernel modules.\n\n",
+ program_invocation_short_name);
+
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- {}
- };
-
- int c;
-
+static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ OptionParser state = { argc, argv };
+
+ FOREACH_OPTION(&state, c, /* arg= */ NULL, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
+ *ret_args = option_parser_get_args(&state);
return 1;
}
@@ -395,7 +389,8 @@ static int run(int argc, char *argv[]) {
char *module;
int ret = 0, r;
- r = parse_argv(argc, argv);
+ char **args = NULL;
+ r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
@@ -407,9 +402,9 @@ static int run(int argc, char *argv[]) {
if (r < 0)
log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
- if (argc > optind) {
- for (int i = optind; i < argc; i++) {
- r = apply_file_from_path(argv[i], &module_set);
+ if (!strv_isempty(args)) {
+ STRV_FOREACH(i, args) {
+ r = apply_file_from_path(*i, &module_set);
if (r < 0)
RET_GATHER(ret, r);
}
diff --git a/src/mute-console/mute-console.c b/src/mute-console/mute-console.c
index b18e79d622..b40f86fafb 100644
--- a/src/mute-console/mute-console.c
+++ b/src/mute-console/mute-console.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
#include
#include "sd-bus.h"
@@ -15,8 +14,10 @@
#include "bus-util.h"
#include "daemon-util.h"
#include "errno-util.h"
+#include "format-table.h"
#include "log.h"
#include "main-func.h"
+#include "options.h"
#include "parse-argument.h"
#include "pretty-print.h"
#include "printk-util.h"
@@ -30,79 +31,60 @@ static bool arg_varlink = false;
static int help(void) {
_cleanup_free_ char *link = NULL;
+ _cleanup_(table_unrefp) Table *options = NULL;
int r;
r = terminal_urlify_man("systemd-mute-console", "1", &link);
if (r < 0)
return log_oom();
- printf("%s [OPTIONS...]\n"
- "\n%sMute status output to the console.%s\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --kernel=BOOL Mute kernel log output\n"
- " --pid1=BOOL Mute PID 1 status output\n"
- "\nSee the %s for details.\n",
+ r = option_parser_get_help_table(&options);
+ if (r < 0)
+ return r;
+
+ printf("%s [OPTIONS...]\n\n"
+ "%sMute status output to the console.%s\n\n",
program_invocation_short_name,
ansi_highlight(),
- ansi_normal(),
- link);
+ ansi_normal());
+ r = table_print_or_warn(options);
+ if (r < 0)
+ return r;
+
+ printf("\nSee the %s for details.\n", link);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_KERNEL,
- ARG_PID1,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "kernel", required_argument, NULL, ARG_KERNEL },
- { "pid1", required_argument, NULL, ARG_PID1 },
- {}
- };
-
- int c, r;
-
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
+ OptionParser state = { argc, argv };
+ const char *arg;
+ int r;
+ FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
- case 'h':
+ OPTION_COMMON_HELP:
return help();
- case ARG_VERSION:
+ OPTION_COMMON_VERSION:
return version();
- case ARG_PID1:
- r = parse_boolean_argument("--pid1=", optarg, &arg_mute_pid1);
+ OPTION_LONG("kernel", "BOOL", "Mute kernel log output"):
+ r = parse_boolean_argument("--kernel=", arg, &arg_mute_kernel);
if (r < 0)
return r;
-
break;
- case ARG_KERNEL:
- r = parse_boolean_argument("--kernel=", optarg, &arg_mute_kernel);
+ OPTION_LONG("pid1", "BOOL", "Mute PID 1 status output"):
+ r = parse_boolean_argument("--pid1=", arg, &arg_mute_pid1);
if (r < 0)
return r;
-
break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached();
}
- }
r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
if (r < 0)
diff --git a/src/network/bpf/sysctl-monitor/meson.build b/src/network/bpf/sysctl-monitor/meson.build
deleted file mode 100644
index 8b0de88674..0000000000
--- a/src/network/bpf/sysctl-monitor/meson.build
+++ /dev/null
@@ -1,24 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-if conf.get('ENABLE_SYSCTL_BPF') != 1
- subdir_done()
-endif
-
-sysctl_monitor_bpf_o_unstripped = custom_target(
- input : 'sysctl-monitor.bpf.c',
- output : 'sysctl-monitor.bpf.unstripped.o',
- command : bpf_o_unstripped_cmd,
- depends : vmlinux_h_dependency)
-
-sysctl_monitor_bpf_o = custom_target(
- input : sysctl_monitor_bpf_o_unstripped,
- output : 'sysctl-monitor.bpf.o',
- command : bpf_o_cmd)
-
-sysctl_monitor_skel_h = custom_target(
- input : sysctl_monitor_bpf_o,
- output : 'sysctl-monitor.skel.h',
- command : skel_h_cmd,
- capture : true)
-
-generated_sources += sysctl_monitor_skel_h
diff --git a/src/network/bpf/sysctl-monitor/sysctl-monitor-skel.h b/src/network/bpf/sysctl-monitor/sysctl-monitor-skel.h
deleted file mode 100644
index e1ebc3e509..0000000000
--- a/src/network/bpf/sysctl-monitor/sysctl-monitor-skel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/* The SPDX header above is actually correct in claiming this was
- * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
- * compatible with GPL we will claim this to be GPL however, which should be
- * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
- */
-
-#include "bpf-dlopen.h" /* IWYU pragma: keep */
-
-/* libbpf is used via dlopen(), so rename symbols */
-#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
-#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
-#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
-
-#include "bpf/sysctl-monitor/sysctl-monitor.skel.h" /* IWYU pragma: export */
diff --git a/src/network/meson.build b/src/network/meson.build
index 00361a0017..134416bcc8 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -1,7 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
-subdir('bpf/sysctl-monitor')
-
systemd_networkd_sources = files(
'networkd.c'
)
@@ -144,10 +142,6 @@ networkctl_sources = files(
networkd_network_gperf_gperf = files('networkd-network-gperf.gperf')
networkd_netdev_gperf_gperf = files('netdev/netdev-gperf.gperf')
-if conf.get('ENABLE_SYSCTL_BPF') == 1
- systemd_networkd_extract_sources += sysctl_monitor_skel_h
-endif
-
networkd_gperf_c = custom_target(
input : 'networkd-gperf.gperf',
output : 'networkd-gperf.c',
@@ -209,6 +203,9 @@ executables += [
networkd_link_with,
],
'dependencies' : threads,
+ 'bpf_programs': [
+ 'sysctl-monitor',
+ ]
},
libexec_template + {
'name' : 'systemd-networkd-wait-online',
diff --git a/src/network/networkd-dhcp-server-bus.c b/src/network/networkd-dhcp-server-bus.c
index db2ee37f34..e5ee6d3f6d 100644
--- a/src/network/networkd-dhcp-server-bus.c
+++ b/src/network/networkd-dhcp-server-bus.c
@@ -74,6 +74,46 @@ static int property_get_leases(
return sd_bus_message_close_container(reply);
}
+static int property_get_pool_size(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+ Link *l = ASSERT_PTR(userdata);
+ sd_dhcp_server *s;
+ uint32_t v;
+
+ assert(reply);
+
+ s = l->dhcp_server;
+ v = s && !sd_dhcp_server_is_in_relay_mode(s) ? s->pool_size : UINT32_MAX;
+
+ return sd_bus_message_append_basic(reply, 'u', &v);
+}
+
+static int property_get_pool_offset(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+ Link *l = ASSERT_PTR(userdata);
+ sd_dhcp_server *s;
+ uint32_t v;
+
+ assert(reply);
+
+ s = l->dhcp_server;
+ v = s && !sd_dhcp_server_is_in_relay_mode(s) ? s->pool_offset : UINT32_MAX;
+
+ return sd_bus_message_append_basic(reply, 'u', &v);
+}
+
static int dhcp_server_emit_changed_strv(Link *link, char **properties) {
_cleanup_free_ char *path = NULL;
@@ -104,6 +144,8 @@ static const sd_bus_vtable dhcp_server_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Leases", "a(uayayayayt)", property_get_leases, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("PoolSize", "u", property_get_pool_size, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("PoolOffset", "u", property_get_pool_offset, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
};
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index f1049cc7cc..aaf974e312 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -168,6 +168,7 @@ Network.IPv6ProxyNDP, config_parse_tristate,
Network.IPv6MTUBytes, config_parse_mtu, AF_INET6, offsetof(Network, ipv6_mtu)
Network.IPv4AcceptLocal, config_parse_tristate, 0, offsetof(Network, ipv4_accept_local)
Network.IPv4RouteLocalnet, config_parse_tristate, 0, offsetof(Network, ipv4_route_localnet)
+Network.IPv4SrcValidMark, config_parse_tristate, 0, offsetof(Network, ipv4_src_valid_mark)
Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave)
Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave)
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 1e159fa310..3ffe1640e7 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -479,6 +479,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.ip_forwarding = { -1, -1, },
.ipv4_accept_local = -1,
.ipv4_route_localnet = -1,
+ .ipv4_src_valid_mark = -1,
.ipv6_privacy_extensions = _IPV6_PRIVACY_EXTENSIONS_INVALID,
.ipv6_dad_transmits = -1,
.ipv6_proxy_ndp = -1,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 923828b2ea..9a36c312f8 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -332,6 +332,7 @@ typedef struct Network {
int ip_forwarding[2];
int ipv4_accept_local;
int ipv4_route_localnet;
+ int ipv4_src_valid_mark;
int ipv6_dad_transmits;
uint8_t ipv6_hop_limit;
usec_t ipv6_retransmission_time;
diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c
index 914fbccd09..0801ba977a 100644
--- a/src/network/networkd-sysctl.c
+++ b/src/network/networkd-sysctl.c
@@ -30,8 +30,8 @@
#if ENABLE_SYSCTL_BPF
#include "bpf-link.h"
-#include "bpf/sysctl-monitor/sysctl-monitor-skel.h"
-#include "bpf/sysctl-monitor/sysctl-write-event.h"
+#include "sysctl-monitor-skel.h"
+#include "sysctl-write-event.h"
static struct sysctl_monitor_bpf* sysctl_monitor_bpf_free(struct sysctl_monitor_bpf *obj) {
sysctl_monitor_bpf__destroy(obj);
@@ -108,7 +108,7 @@ int manager_install_sysctl_monitor(Manager *manager) {
assert(manager);
- r = dlopen_bpf();
+ r = dlopen_bpf(LOG_DEBUG);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return log_debug_errno(r, "sysctl monitor disabled, as BPF support is not available.");
if (r < 0)
@@ -662,6 +662,20 @@ static int link_set_ipv4_route_localnet(Link *link) {
return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "route_localnet", link->network->ipv4_route_localnet > 0, manager_get_sysctl_shadow(link->manager));
}
+static int link_set_ipv4_src_valid_mark(Link *link) {
+ assert(link);
+ assert(link->manager);
+ assert(link->network);
+
+ if (!link_is_configured_for_family(link, AF_INET))
+ return 0;
+
+ if (link->network->ipv4_src_valid_mark < 0)
+ return 0;
+
+ return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "src_valid_mark", link->network->ipv4_src_valid_mark > 0, manager_get_sysctl_shadow(link->manager));
+}
+
static int link_set_ipv4_promote_secondaries(Link *link) {
assert(link);
assert(link->manager);
@@ -750,6 +764,10 @@ int link_set_sysctl(Link *link) {
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv4 route_localnet flag for interface, ignoring: %m");
+ r = link_set_ipv4_src_valid_mark(link);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Cannot set IPv4 src_valid_mark flag for interface, ignoring: %m");
+
r = link_set_ipv4_rp_filter(link);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv4 reverse path filtering for interface, ignoring: %m");
diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c
index 5cbc58969f..bd28a67e6b 100644
--- a/src/nspawn/nspawn-oci.c
+++ b/src/nspawn/nspawn-oci.c
@@ -1826,7 +1826,7 @@ static int oci_seccomp(const char *name, sd_json_variant *v, sd_json_dispatch_fl
if (r < 0)
return json_log(def, flags, r, "Unknown default action: %s", sd_json_variant_string(def));
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return json_log(def, flags, r, "No support for libseccomp: %m");
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 438346a545..b1c8defb6c 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -49,6 +49,7 @@
#include "fd-util.h"
#include "fdset.h"
#include "fileio.h"
+#include "fork-notify.h"
#include "format-table.h"
#include "format-util.h"
#include "fs-util.h"
@@ -95,6 +96,7 @@
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
+#include "path-lookup.h"
#include "path-util.h"
#include "pidref.h"
#include "polkit-agent.h"
@@ -133,6 +135,7 @@
/* The notify socket inside the container it can use to talk to nspawn using the sd_notify(3) protocol */
#define NSPAWN_NOTIFY_SOCKET_PATH "/run/host/notify"
#define NSPAWN_MOUNT_TUNNEL "/run/host/incoming"
+#define NSPAWN_JOURNAL_SOCKET_PATH "/run/host/journal/socket"
#define EXIT_FORCE_RESTART 133
@@ -262,6 +265,11 @@ static char *arg_background = NULL;
static RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
static bool arg_cleanup = false;
static bool arg_ask_password = true;
+static char *arg_forward_journal = NULL;
+static uint64_t arg_forward_journal_max_use = UINT64_MAX;
+static uint64_t arg_forward_journal_keep_free = UINT64_MAX;
+static uint64_t arg_forward_journal_max_file_size = UINT64_MAX;
+static uint64_t arg_forward_journal_max_files = UINT64_MAX;
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
STATIC_DESTRUCTOR_REGISTER(arg_template, freep);
@@ -303,6 +311,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_restrict_address_families, set_freep);
STATIC_DESTRUCTOR_REGISTER(arg_settings_filename, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_forward_journal, freep);
static int parse_private_users(
const char *s,
@@ -1250,6 +1259,36 @@ static int parse_argv(int argc, char *argv[]) {
arg_settings_mask |= SETTING_LINK_JOURNAL;
break;
+ OPTION_LONG("forward-journal", "FILE|DIR", "Forward the container's journal to the host"):
+ r = parse_path_argument(arg, /* suppress_root= */ false, &arg_forward_journal);
+ if (r < 0)
+ return r;
+ break;
+
+ OPTION_LONG("forward-journal-max-use", "BYTES", "Maximum disk space for forwarded journal"):
+ r = parse_size(arg, 1024, &arg_forward_journal_max_use);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-max-use= value: %s", optarg);
+ break;
+
+ OPTION_LONG("forward-journal-keep-free", "BYTES", "Minimum disk space to keep free"):
+ r = parse_size(arg, 1024, &arg_forward_journal_keep_free);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-keep-free= value: %s", optarg);
+ break;
+
+ OPTION_LONG("forward-journal-max-file-size", "BYTES", "Maximum size of individual journal files"):
+ r = parse_size(arg, 1024, &arg_forward_journal_max_file_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-max-file-size= value: %s", optarg);
+ break;
+
+ OPTION_LONG("forward-journal-max-files", "N", "Maximum number of journal files to keep"):
+ r = safe_atou64(arg, &arg_forward_journal_max_files);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-max-files= value: %s", optarg);
+ break;
+
OPTION_GROUP("Mounts"): {}
OPTION_LONG("bind", "PATH[:PATH[:OPTIONS]]",
@@ -1446,6 +1485,12 @@ static int parse_argv(int argc, char *argv[]) {
arg_caps_retain |= arg_private_network ? UINT64_C(1) << CAP_NET_ADMIN : 0;
arg_caps_retain &= ~minus;
+ if ((arg_forward_journal_max_use != UINT64_MAX ||
+ arg_forward_journal_keep_free != UINT64_MAX ||
+ arg_forward_journal_max_file_size != UINT64_MAX ||
+ arg_forward_journal_max_files != UINT64_MAX) && !arg_forward_journal)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--forward-journal-max-use=/--forward-journal-keep-free=/--forward-journal-max-file-size=/--forward-journal-max-files= require --forward-journal=.");
+
/* Make sure to parse environment before we reset the settings mask below */
r = parse_environment();
if (r < 0)
@@ -3708,9 +3753,10 @@ static int setup_notify_child(const void *directory) {
return TAKE_FD(fd);
}
-static int setup_unix_export_dir_outside(char **ret) {
+static int setup_unix_export_dir_outside(const char *runtime_dir, char **ret) {
int r;
+ assert(runtime_dir);
assert(ret);
if (arg_userns_mode == USER_NAMESPACE_MANAGED) {
@@ -3719,7 +3765,7 @@ static int setup_unix_export_dir_outside(char **ret) {
}
_cleanup_free_ char *p = NULL;
- p = path_join("/run/systemd/nspawn/unix-export", arg_machine);
+ p = path_join(runtime_dir, "unix-export");
if (!p)
return log_oom();
@@ -5103,6 +5149,7 @@ static int load_oci_bundle(void) {
}
static int run_container(
+ const char *runtime_dir,
const char *directory,
int mount_fd,
DissectedImage *dissected_image,
@@ -5141,7 +5188,7 @@ static int run_container(
assert_se(sigaddset(&mask_chld, SIGCHLD) == 0);
/* Set up the unix export host directory on the host first */
- r = setup_unix_export_dir_outside(&unix_export_host_dir);
+ r = setup_unix_export_dir_outside(runtime_dir, &unix_export_host_dir);
if (r < 0)
return r;
@@ -5907,18 +5954,22 @@ static int cant_be_in_netns(void) {
return 0;
}
-static void cleanup_propagation_and_export_directories(void) {
- const char *p;
+static void cleanup_propagation_and_export_directories(const char *runtime_dir) {
+ _cleanup_free_ char *p = NULL;
- if (!arg_machine || arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
+ if (!runtime_dir || arg_userns_mode == USER_NAMESPACE_MANAGED)
return;
- p = strjoina("/run/systemd/nspawn/propagate/", arg_machine);
- (void) rm_rf(p, REMOVE_ROOT);
+ p = path_join("/run/systemd/nspawn/propagate", arg_machine);
+ if (p)
+ (void) rm_rf(p, REMOVE_ROOT);
- p = strjoina("/run/systemd/nspawn/unix-export/", arg_machine);
- (void) umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW);
- (void) rmdir(p);
+ free(p);
+ p = path_join(runtime_dir, "unix-export");
+ if (p) {
+ (void) umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW);
+ (void) rmdir(p);
+ }
}
static int do_cleanup(void) {
@@ -5931,7 +5982,16 @@ static int do_cleanup(void) {
if (r < 0)
return r;
- cleanup_propagation_and_export_directories();
+ _cleanup_free_ char *subdir = path_join("systemd/nspawn", arg_machine);
+ if (!subdir)
+ return log_oom();
+
+ _cleanup_free_ char *runtime_dir = NULL;
+ r = runtime_directory(arg_runtime_scope, subdir, &runtime_dir);
+ if (r < 0)
+ return r;
+
+ cleanup_propagation_and_export_directories(runtime_dir);
return 0;
}
@@ -5951,6 +6011,9 @@ static int run(int argc, char *argv[]) {
_cleanup_(sd_netlink_unrefp) sd_netlink *nfnl = NULL;
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *nsresource_link = NULL, *mountfsd_link = NULL;
+ _cleanup_free_ char *runtime_dir = NULL, *subdir = NULL;
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir_destroy = NULL;
+ _cleanup_(fork_notify_terminate) PidRef journal_remote_pidref = PIDREF_NULL;
log_setup();
@@ -5961,9 +6024,9 @@ static int run(int argc, char *argv[]) {
if (arg_cleanup)
return do_cleanup();
- (void) dlopen_libmount();
- (void) dlopen_libseccomp();
- (void) dlopen_libselinux();
+ (void) dlopen_libmount(LOG_DEBUG);
+ (void) dlopen_libseccomp(LOG_DEBUG);
+ (void) dlopen_libselinux(LOG_DEBUG);
r = cg_has_legacy();
if (r < 0)
@@ -6440,6 +6503,22 @@ static int run(int argc, char *argv[]) {
} else
assert_not_reached();
+ subdir = path_join("systemd/nspawn", arg_machine);
+ if (!subdir) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = runtime_directory_make(
+ arg_runtime_scope,
+ subdir,
+ &runtime_dir,
+ &runtime_dir_destroy);
+ if (r < 0) {
+ log_error_errno(r, "Failed to create runtime directory: %m");
+ goto finish;
+ }
+
/* Create a temporary place to mount stuff. */
r = mkdtemp_malloc("/tmp/nspawn-root-XXXXXX", &rootdir);
if (r < 0) {
@@ -6486,8 +6565,61 @@ static int run(int argc, char *argv[]) {
expose_args.nfnl = nfnl;
}
+ if (arg_forward_journal) {
+ _cleanup_free_ char *socket_path = path_join(runtime_dir, "journal-remote-socket");
+ if (!socket_path) {
+ r = log_oom();
+ goto finish;
+ }
+
+ union sockaddr_union sa;
+ r = sockaddr_un_set_path(&sa.un, socket_path);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set AF_UNIX path to '%s': %m", socket_path);
+ goto finish;
+ }
+
+ (void) sockaddr_un_unlink(&sa.un);
+
+ r = fork_journal_remote(
+ socket_path,
+ arg_forward_journal,
+ arg_forward_journal_max_use,
+ arg_forward_journal_keep_free,
+ arg_forward_journal_max_file_size,
+ arg_forward_journal_max_files,
+ &journal_remote_pidref);
+ if (r < 0)
+ goto finish;
+
+ CustomMount *cm = custom_mount_add(&arg_custom_mounts, &arg_n_custom_mounts, CUSTOM_MOUNT_BIND);
+ if (!cm) {
+ r = log_oom();
+ goto finish;
+ }
+
+ cm->source = TAKE_PTR(socket_path);
+ cm->read_only = true;
+ cm->destination = strdup(NSPAWN_JOURNAL_SOCKET_PATH);
+ if (!cm->destination) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = machine_credential_add(&arg_credentials, "journal.forward_to_socket", NSPAWN_JOURNAL_SOCKET_PATH, SIZE_MAX);
+ if (r == -EEXIST) {
+ log_error_errno(r, "Credential 'journal.forward_to_socket' already set via --set-credential=, refusing --forward-journal=.");
+ goto finish;
+ }
+ if (r < 0) {
+ log_error_errno(r, "Failed to add 'journal.forward_to_socket' credential: %m");
+ goto finish;
+ }
+ }
+
for (;;) {
r = run_container(
+ runtime_dir,
rootdir,
mount_fd,
dissected_image,
@@ -6528,18 +6660,7 @@ finish:
log_warning_errno(errno, "Can't remove image file '%s', ignoring: %m", arg_image);
}
- if (arg_machine && arg_userns_mode != USER_NAMESPACE_MANAGED) {
- const char *p;
-
- p = strjoina("/run/systemd/nspawn/propagate/", arg_machine);
- (void) rm_rf(p, REMOVE_ROOT);
-
- p = strjoina("/run/systemd/nspawn/unix-export/", arg_machine);
- (void) umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW);
- (void) rmdir(p);
- }
-
- cleanup_propagation_and_export_directories();
+ cleanup_propagation_and_export_directories(runtime_dir);
expose_port_flush(nfnl, arg_expose_ports, AF_INET, &expose_args.address4);
expose_port_flush(nfnl, arg_expose_ports, AF_INET6, &expose_args.address6);
diff --git a/src/nsresourced/bpf/userns-restrict/meson.build b/src/nsresourced/bpf/userns-restrict/meson.build
deleted file mode 100644
index e6bcc51add..0000000000
--- a/src/nsresourced/bpf/userns-restrict/meson.build
+++ /dev/null
@@ -1,24 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-if conf.get('HAVE_VMLINUX_H') != 1
- subdir_done()
-endif
-
-userns_restrict_bpf_o_unstripped = custom_target(
- input : 'userns-restrict.bpf.c',
- output : 'userns-restrict.bpf.unstripped.o',
- command : bpf_o_unstripped_cmd,
- depends : vmlinux_h_dependency)
-
-userns_restrict_bpf_o = custom_target(
- input : userns_restrict_bpf_o_unstripped,
- output : 'userns-restrict.bpf.o',
- command : bpf_o_cmd)
-
-userns_restrict_skel_h = custom_target(
- input : userns_restrict_bpf_o,
- output : 'userns-restrict.skel.h',
- command : skel_h_cmd,
- capture : true)
-
-generated_sources += userns_restrict_skel_h
diff --git a/src/nsresourced/meson.build b/src/nsresourced/meson.build
index 6b6ae1558c..881fd911e4 100644
--- a/src/nsresourced/meson.build
+++ b/src/nsresourced/meson.build
@@ -4,8 +4,6 @@ if conf.get('ENABLE_NSRESOURCED') != 1
subdir_done()
endif
-subdir('bpf/userns-restrict')
-
systemd_nsresourced_sources = files(
'nsresourced-manager.c',
'nsresourced.c',
@@ -21,29 +19,26 @@ test_userns_restrict_sources = files(
'test-userns-restrict.c'
)
-if conf.get('HAVE_VMLINUX_H') == 1
- systemd_nsresourced_sources += userns_restrict_skel_h
- systemd_nsresourcework_sources += userns_restrict_skel_h
- test_userns_restrict_sources += userns_restrict_skel_h
-endif
-
executables += [
libexec_template + {
'name' : 'systemd-nsresourced',
'sources' : systemd_nsresourced_sources,
'extract' : systemd_nsresourced_extract_sources,
'dependencies' : threads,
+ 'bpf_programs': ['userns-restrict'],
},
libexec_template + {
'name' : 'systemd-nsresourcework',
'sources' : systemd_nsresourcework_sources,
'dependencies' : threads,
'objects' : ['systemd-nsresourced'],
+ 'bpf_programs': ['userns-restrict'],
},
test_template + {
'sources' : test_userns_restrict_sources,
'conditions' : ['HAVE_VMLINUX_H'],
'objects' : ['systemd-nsresourced'],
+ 'bpf_programs': ['userns-restrict'],
},
]
diff --git a/src/nsresourced/nsresourced-manager.c b/src/nsresourced/nsresourced-manager.c
index 3102563617..cceaa9c378 100644
--- a/src/nsresourced/nsresourced-manager.c
+++ b/src/nsresourced/nsresourced-manager.c
@@ -8,7 +8,7 @@
#include "bpf-dlopen.h"
#if HAVE_VMLINUX_H
#include "bpf-link.h"
-#include "bpf/userns-restrict/userns-restrict-skel.h"
+#include "userns-restrict-skel.h"
#endif
#include "build-path.h"
#include "common-signal.h"
diff --git a/src/nsresourced/userns-restrict.c b/src/nsresourced/userns-restrict.c
index 5012276c82..11bb2e7d8f 100644
--- a/src/nsresourced/userns-restrict.c
+++ b/src/nsresourced/userns-restrict.c
@@ -3,7 +3,7 @@
#include
#if HAVE_VMLINUX_H
-#include "bpf/userns-restrict/userns-restrict-skel.h"
+#include "userns-restrict-skel.h"
#endif
#include "bpf-dlopen.h"
@@ -68,7 +68,7 @@ int userns_restrict_install(
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm not supported, can't lock down user namespace.");
- r = dlopen_bpf();
+ r = dlopen_bpf(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/oom/oomctl.c b/src/oom/oomctl.c
index 703b9c3f0e..51dfe1f1a4 100644
--- a/src/oom/oomctl.c
+++ b/src/oom/oomctl.c
@@ -89,6 +89,7 @@ static int verb_dump_state(int argc, char *argv[], uintptr_t _data, void *userda
static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
+ assert(ret_args);
OptionParser state = { argc, argv };
const char *arg;
diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c
index a6ec5c23d0..fd8b9e95a4 100644
--- a/src/pcrlock/pcrlock.c
+++ b/src/pcrlock/pcrlock.c
@@ -543,7 +543,7 @@ static int event_log_record_parse_variable_data(
if (!p)
return log_oom_debug();
- if (!string_is_safe(p))
+ if (!string_is_safe(p, STRING_ALLOW_GLOBS))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Unsafe EFI variable string in record.");
*ret_variable_uuid = efi_guid_to_id128(vdata->variableName);
@@ -627,7 +627,7 @@ static int event_log_record_extract_firmware_description(EventLogRecord *rec) {
if (r < 0)
return log_error_errno(r, "Failed to make C string from EFI action string: %m");
- if (!string_is_safe(d)) {
+ if (!string_is_safe(d, STRING_ALLOW_GLOBS|STRING_ALLOW_EMPTY|STRING_ALLOW_BACKSLASHES)) {
log_warning("Unsafe EFI action string in record, ignoring.");
goto invalid;
}
diff --git a/src/portable/portable.c b/src/portable/portable.c
index 8b2be8cead..3f3c0cda48 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -610,8 +610,8 @@ static int portable_extract_by_path(
* there, and extract the metadata we need. The metadata is sent from the child back to us. */
/* Load some libraries before we fork workers off that want to use them */
- (void) dlopen_cryptsetup();
- (void) dlopen_libmount();
+ (void) dlopen_cryptsetup(LOG_DEBUG);
+ (void) dlopen_libmount(LOG_DEBUG);
r = mkdtemp_malloc("/tmp/inspect-XXXXXX", &tmpdir);
if (r < 0)
diff --git a/src/repart/meson.build b/src/repart/meson.build
index 92c7d37da5..b7c70be068 100644
--- a/src/repart/meson.build
+++ b/src/repart/meson.build
@@ -12,13 +12,9 @@ executables += [
'repart.c',
'iso9660.c',
),
- 'link_with' : [
- libshared,
- libshared_fdisk,
- ],
'dependencies' : [
libblkid_cflags,
- libfdisk,
+ libfdisk_cflags,
libmount_cflags,
libopenssl,
threads,
@@ -31,13 +27,12 @@ executables += [
'link_with' : [
libc_wrapper_static,
libbasic_static,
- libshared_fdisk,
libshared_static,
libsystemd_static,
],
'dependencies' : [
libblkid_cflags,
- libfdisk,
+ libfdisk_cflags,
libmount_cflags,
libopenssl,
threads,
diff --git a/src/repart/repart.c b/src/repart/repart.c
index b8443fab19..821868b363 100644
--- a/src/repart/repart.c
+++ b/src/repart/repart.c
@@ -793,9 +793,9 @@ static Partition* partition_free(Partition *p) {
strv_free(p->drop_in_files);
if (p->current_partition)
- fdisk_unref_partition(p->current_partition);
+ sym_fdisk_unref_partition(p->current_partition);
if (p->new_partition)
- fdisk_unref_partition(p->new_partition);
+ sym_fdisk_unref_partition(p->new_partition);
if (p->copy_blocks_path_is_our_file)
unlink_and_free(p->copy_blocks_path);
@@ -976,7 +976,7 @@ static Context* context_free(Context *context) {
context_free_free_areas(context);
if (context->fdisk_context)
- fdisk_unref_context(context->fdisk_context);
+ sym_fdisk_unref_context(context->fdisk_context);
safe_close(context->backing_fd);
if (context->node_is_our_file)
@@ -3022,7 +3022,7 @@ static int partition_read_definition(
"Cannot format %s filesystem without source files, refusing.", p->format);
if (p->verity != VERITY_OFF || p->encrypt != ENCRYPT_OFF) {
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return log_syntax(NULL, LOG_ERR, path, 1, r,
"libcryptsetup not found, Verity=/Encrypt= are not supported: %m");
@@ -3198,31 +3198,31 @@ static int determine_current_padding(
assert(p);
assert(ret);
- if (!fdisk_partition_has_end(p))
+ if (!sym_fdisk_partition_has_end(p))
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition has no end.");
- offset = fdisk_partition_get_end(p);
+ offset = sym_fdisk_partition_get_end(p);
assert(offset < UINT64_MAX);
offset++; /* The end is one sector before the next partition or padding. */
assert(offset < UINT64_MAX / secsz);
offset *= secsz;
- n_partitions = fdisk_table_get_nents(t);
+ n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
struct fdisk_partition *q;
uint64_t start;
- q = fdisk_table_get_partition(t, i);
+ q = sym_fdisk_table_get_partition(t, i);
if (!q)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
- if (fdisk_partition_is_used(q) <= 0)
+ if (sym_fdisk_partition_is_used(q) <= 0)
continue;
- if (!fdisk_partition_has_start(q))
+ if (!sym_fdisk_partition_has_start(q))
continue;
- start = fdisk_partition_get_start(q);
+ start = sym_fdisk_partition_get_start(q);
assert(start < UINT64_MAX / secsz);
start *= secsz;
@@ -3232,7 +3232,7 @@ static int determine_current_padding(
if (next == UINT64_MAX) {
/* No later partition? In that case check the end of the usable area */
- next = fdisk_get_last_lba(c);
+ next = sym_fdisk_get_last_lba(c);
assert(next < UINT64_MAX);
next++; /* The last LBA is one sector before the end */
@@ -3274,21 +3274,21 @@ static int context_copy_from_one(Context *context, const char *src) {
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context: %m");
- secsz = fdisk_get_sector_size(c);
- grainsz = fdisk_get_grain_size(c);
+ secsz = sym_fdisk_get_sector_size(c);
+ grainsz = sym_fdisk_get_grain_size(c);
/* Insist on a power of two, and that it's a multiple of 512, i.e. the traditional sector size. */
if (secsz < 512 || !ISPOWEROF2(secsz))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size %lu is not a power of two larger than 512? Refusing.", secsz);
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Cannot copy from disk %s with no GPT disk label.", src);
- r = fdisk_get_partitions(c, &t);
+ r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
- n_partitions = fdisk_table_get_nents(t);
+ n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
_cleanup_(partition_freep) Partition *np = NULL;
_cleanup_free_ char *label_copy = NULL;
@@ -3298,16 +3298,16 @@ static int context_copy_from_one(Context *context, const char *src) {
sd_id128_t ptid, id;
GptPartitionType type;
- p = fdisk_table_get_partition(t, i);
+ p = sym_fdisk_table_get_partition(t, i);
if (!p)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
- if (fdisk_partition_is_used(p) <= 0)
+ if (sym_fdisk_partition_is_used(p) <= 0)
continue;
- if (fdisk_partition_has_start(p) <= 0 ||
- fdisk_partition_has_size(p) <= 0 ||
- fdisk_partition_has_partno(p) <= 0)
+ if (sym_fdisk_partition_has_start(p) <= 0 ||
+ sym_fdisk_partition_has_size(p) <= 0 ||
+ sym_fdisk_partition_has_partno(p) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
r = fdisk_partition_get_type_as_id128(p, &ptid);
@@ -3320,18 +3320,18 @@ static int context_copy_from_one(Context *context, const char *src) {
if (r < 0)
return log_error_errno(r, "Failed to query partition UUID: %m");
- label = fdisk_partition_get_name(p);
+ label = sym_fdisk_partition_get_name(p);
if (!isempty(label)) {
label_copy = strdup(label);
if (!label_copy)
return log_oom();
}
- sz = fdisk_partition_get_size(p);
+ sz = sym_fdisk_partition_get_size(p);
assert(sz <= UINT64_MAX/secsz);
sz *= secsz;
- start = fdisk_partition_get_start(p);
+ start = sym_fdisk_partition_get_start(p);
assert(start <= UINT64_MAX/secsz);
start *= secsz;
@@ -3606,14 +3606,14 @@ static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *da
_cleanup_free_ char *ids = NULL;
int r;
- if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
+ if (sym_fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
return -EINVAL;
ids = new(char, SD_ID128_UUID_STRING_MAX);
if (!ids)
return -ENOMEM;
- r = fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) data, ids));
+ r = sym_fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) data, ids));
if (r < 0)
return r;
@@ -3624,15 +3624,15 @@ static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *da
static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context *c, sd_id128_t id) {
int r;
- r = fdisk_set_ask(c, fdisk_ask_cb, &id);
+ r = sym_fdisk_set_ask(c, fdisk_ask_cb, &id);
if (r < 0)
return r;
- r = fdisk_set_disklabel_id(c);
+ r = sym_fdisk_set_disklabel_id(c);
if (r < 0)
return r;
- return fdisk_set_ask(c, NULL, NULL);
+ return sym_fdisk_set_ask(c, NULL, NULL);
}
static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) {
@@ -3693,13 +3693,13 @@ static int context_load_partition_table(Context *context) {
context_notify(context, PROGRESS_LOADING_TABLE, /* object= */ NULL, UINT_MAX);
- c = fdisk_new_context();
+ c = sym_fdisk_new_context();
if (!c)
return log_oom();
if (arg_sector_size > 0) {
fs_secsz = arg_sector_size;
- r = fdisk_save_user_sector_size(c, /* phy= */ 0, arg_sector_size);
+ r = sym_fdisk_save_user_sector_size(c, /* phy= */ 0, arg_sector_size);
} else {
uint32_t ssz;
struct stat st;
@@ -3732,14 +3732,14 @@ static int context_load_partition_table(Context *context) {
}
}
- r = fdisk_save_user_sector_size(c, /* phy= */ 0, ssz);
+ r = sym_fdisk_save_user_sector_size(c, /* phy= */ 0, ssz);
}
if (r < 0)
return log_error_errno(r, "Failed to set sector size: %m");
/* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the
* /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */
- r = fdisk_assign_device(
+ r = sym_fdisk_assign_device(
c,
context->backing_fd >= 0 ? FORMAT_PROC_FD_PATH(context->backing_fd) : context->node,
context->dry_run);
@@ -3758,7 +3758,7 @@ static int context_load_partition_table(Context *context) {
if (S_ISREG(st.st_mode) && st.st_size == 0) {
/* Use the fallback values if we have no better idea */
- context->sector_size = fdisk_get_sector_size(c);
+ context->sector_size = sym_fdisk_get_sector_size(c);
context->default_fs_sector_size = fs_secsz;
context->grain_size = determine_grain_size(context->sector_size);
return /* from_scratch= */ true;
@@ -3771,7 +3771,7 @@ static int context_load_partition_table(Context *context) {
if (context->backing_fd < 0) {
/* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
- r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(fdisk_get_devfd(c)),
+ r = context_open_and_lock_backing_fd(FORMAT_PROC_FD_PATH(sym_fdisk_get_devfd(c)),
context->dry_run ? LOCK_SH : LOCK_EX,
&context->backing_fd);
if (r < 0)
@@ -3783,7 +3783,7 @@ static int context_load_partition_table(Context *context) {
* it for all our needs. Note that the values we use ourselves always are in bytes though, thus mean
* the same thing universally. Also note that regardless what kind of sector size is in use we'll
* place partitions at multiples of 4K. */
- unsigned long secsz = fdisk_get_sector_size(c);
+ unsigned long secsz = sym_fdisk_get_sector_size(c);
/* Insist on a power of two, and that it's a multiple of 512, i.e. the traditional sector size. */
if (secsz < 512 || !ISPOWEROF2(secsz))
@@ -3799,14 +3799,14 @@ static int context_load_partition_table(Context *context) {
case EMPTY_REFUSE:
/* Refuse empty disks, insist on an existing GPT partition table */
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not repartitioning.", context->node);
break;
case EMPTY_REQUIRE:
/* Require an empty disk, refuse any existing partition table */
- r = fdisk_has_label(c);
+ r = sym_fdisk_has_label(c);
if (r < 0)
return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node);
if (r > 0)
@@ -3817,11 +3817,11 @@ static int context_load_partition_table(Context *context) {
case EMPTY_ALLOW:
/* Allow both an empty disk and an existing partition table, but only GPT */
- r = fdisk_has_label(c);
+ r = sym_fdisk_has_label(c);
if (r < 0)
return log_error_errno(r, "Failed to determine whether disk %s has a disk label: %m", context->node);
if (r > 0) {
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_notice_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has non-GPT disk label, not repartitioning.", context->node);
} else
from_scratch = true;
@@ -3839,7 +3839,7 @@ static int context_load_partition_table(Context *context) {
}
if (from_scratch) {
- r = fdisk_create_disklabel(c, "gpt");
+ r = sym_fdisk_create_disklabel(c, "gpt");
if (r < 0)
return log_error_errno(r, "Failed to create GPT disk label: %m");
@@ -3854,7 +3854,7 @@ static int context_load_partition_table(Context *context) {
goto add_initial_free_area;
}
- r = fdisk_get_disklabel_id(c, &disk_uuid_string);
+ r = sym_fdisk_get_disklabel_id(c, &disk_uuid_string);
if (r < 0)
return log_error_errno(r, "Failed to get current GPT disk label UUID: %m");
@@ -3864,17 +3864,17 @@ static int context_load_partition_table(Context *context) {
if (r < 0)
return log_error_errno(r, "Failed to acquire disk GPT uuid: %m");
- r = fdisk_set_disklabel_id(c);
+ r = sym_fdisk_set_disklabel_id(c);
if (r < 0)
return log_error_errno(r, "Failed to set GPT disk label: %m");
} else if (r < 0)
return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m");
- r = fdisk_get_partitions(c, &t);
+ r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
- n_partitions = fdisk_table_get_nents(t);
+ n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
_cleanup_free_ char *label_copy = NULL;
Partition *last = NULL;
@@ -3885,16 +3885,16 @@ static int context_load_partition_table(Context *context) {
sd_id128_t ptid, id;
size_t partno;
- p = fdisk_table_get_partition(t, i);
+ p = sym_fdisk_table_get_partition(t, i);
if (!p)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
- if (fdisk_partition_is_used(p) <= 0)
+ if (sym_fdisk_partition_is_used(p) <= 0)
continue;
- if (fdisk_partition_has_start(p) <= 0 ||
- fdisk_partition_has_size(p) <= 0 ||
- fdisk_partition_has_partno(p) <= 0)
+ if (sym_fdisk_partition_has_start(p) <= 0 ||
+ sym_fdisk_partition_has_size(p) <= 0 ||
+ sym_fdisk_partition_has_partno(p) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a position, size or number.");
r = fdisk_partition_get_type_as_id128(p, &ptid);
@@ -3905,22 +3905,22 @@ static int context_load_partition_table(Context *context) {
if (r < 0)
return log_error_errno(r, "Failed to query partition UUID: %m");
- label = fdisk_partition_get_name(p);
+ label = sym_fdisk_partition_get_name(p);
if (!isempty(label)) {
label_copy = strdup(label);
if (!label_copy)
return log_oom();
}
- sz = fdisk_partition_get_size(p);
+ sz = sym_fdisk_partition_get_size(p);
assert(sz <= UINT64_MAX/secsz);
sz *= secsz;
- start = fdisk_partition_get_start(p);
+ start = sym_fdisk_partition_get_start(p);
assert(start <= UINT64_MAX/secsz);
start *= secsz;
- partno = fdisk_partition_get_partno(p);
+ partno = sym_fdisk_partition_get_partno(p);
if (left_boundary == UINT64_MAX || left_boundary > start)
left_boundary = start;
@@ -3941,7 +3941,7 @@ static int context_load_partition_table(Context *context) {
pp->current_label = TAKE_PTR(label_copy);
pp->current_partition = p;
- fdisk_ref_partition(p);
+ sym_fdisk_ref_partition(p);
r = determine_current_padding(c, t, p, secsz, grainsz, &pp->current_padding);
if (r < 0)
@@ -3974,7 +3974,7 @@ static int context_load_partition_table(Context *context) {
np->current_label = TAKE_PTR(label_copy);
np->current_partition = p;
- fdisk_ref_partition(p);
+ sym_fdisk_ref_partition(p);
r = determine_current_padding(c, t, p, secsz, grainsz, &np->current_padding);
if (r < 0)
@@ -3996,15 +3996,15 @@ static int context_load_partition_table(Context *context) {
p->supplement_for->suppressing = NULL;
add_initial_free_area:
- nsectors = fdisk_get_nsectors(c);
+ nsectors = sym_fdisk_get_nsectors(c);
assert(nsectors <= UINT64_MAX/secsz);
nsectors *= secsz;
- first_lba = fdisk_get_first_lba(c);
+ first_lba = sym_fdisk_get_first_lba(c);
assert(first_lba <= UINT64_MAX/secsz);
first_lba *= secsz;
- last_lba = fdisk_get_last_lba(c);
+ last_lba = sym_fdisk_get_last_lba(c);
assert(last_lba < UINT64_MAX);
last_lba++;
assert(last_lba <= UINT64_MAX/secsz);
@@ -4072,12 +4072,12 @@ static void context_unload_partition_table(Context *context) {
p->offset = UINT64_MAX;
if (p->current_partition) {
- fdisk_unref_partition(p->current_partition);
+ sym_fdisk_unref_partition(p->current_partition);
p->current_partition = NULL;
}
if (p->new_partition) {
- fdisk_unref_partition(p->new_partition);
+ sym_fdisk_unref_partition(p->new_partition);
p->new_partition = NULL;
}
@@ -4098,7 +4098,7 @@ static void context_unload_partition_table(Context *context) {
context->total = UINT64_MAX;
if (context->fdisk_context) {
- fdisk_unref_context(context->fdisk_context);
+ sym_fdisk_unref_context(context->fdisk_context);
context->fdisk_context = NULL;
}
@@ -4235,7 +4235,7 @@ static int context_dump_partitions(Context *context) {
activity = "resize";
label = partition_label(p);
- partname = p->partno != UINT64_MAX ? fdisk_partname(context->node, p->partno+1) : NULL;
+ partname = p->partno != UINT64_MAX ? sym_fdisk_partname(context->node, p->partno+1) : NULL;
r = format_size_change(p->current_size, p->new_size, &size_change);
if (r < 0)
@@ -4402,7 +4402,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) {
}
if (p->partno != UINT64_MAX) {
- buf = fdisk_partname(node, p->partno+1);
+ buf = sym_fdisk_partname(node, p->partno+1);
goto done;
}
@@ -4614,16 +4614,16 @@ static int context_wipe_range(Context *context, uint64_t offset, uint64_t size)
assert(offset != UINT64_MAX);
assert(size != UINT64_MAX);
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Failed to load libblkid: %m");
+ return r;
probe = sym_blkid_new_probe();
if (!probe)
return log_oom();
errno = 0;
- r = sym_blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), offset, size);
+ r = sym_blkid_probe_set_device(probe, sym_fdisk_get_devfd(context->fdisk_context), offset, size);
if (r < 0)
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for wiping.");
@@ -4687,7 +4687,7 @@ static int context_discard_range(
if (size <= 0)
return 0;
- assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
+ assert_se((fd = sym_fdisk_get_devfd(context->fdisk_context)) >= 0);
if (fstat(fd, &st) < 0)
return -errno;
@@ -4784,7 +4784,7 @@ static int context_discard_gap_after(Context *context, Partition *p) {
* existing partitions may be before that so ensure the gap
* starts at the first actually usable lba
*/
- gap = fdisk_get_first_lba(context->fdisk_context) * context->sector_size;
+ gap = sym_fdisk_get_first_lba(context->fdisk_context) * context->sector_size;
LIST_FOREACH(partitions, q, context->partitions) {
if (q->dropped)
@@ -4801,7 +4801,7 @@ static int context_discard_gap_after(Context *context, Partition *p) {
}
if (next == UINT64_MAX) {
- next = (fdisk_get_last_lba(context->fdisk_context) + 1) * context->sector_size;
+ next = (sym_fdisk_get_last_lba(context->fdisk_context) + 1) * context->sector_size;
if (gap > next)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Partition end beyond disk end.");
}
@@ -4998,7 +4998,7 @@ static int prepare_temporary_file(Context *context, PartitionTarget *t, uint64_t
return log_error_errno(fd, "Failed to create temporary file: %m");
if (context->fdisk_context) {
- r = read_attr_fd(fdisk_get_devfd(context->fdisk_context), &attrs);
+ r = read_attr_fd(sym_fdisk_get_devfd(context->fdisk_context), &attrs);
if (r < 0 && !ERRNO_IS_NEG_NOT_SUPPORTED(r))
log_warning_errno(r, "Failed to read file attributes of %s, ignoring: %m", context->node);
@@ -5039,7 +5039,7 @@ static int partition_target_prepare(
assert(p);
assert(ret);
- assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
+ assert_se((whole_fd = sym_fdisk_get_devfd(context->fdisk_context)) >= 0);
t = new(PartitionTarget, 1);
if (!t)
@@ -5114,7 +5114,7 @@ static int partition_target_sync(Context *context, Partition *p, PartitionTarget
assert(p);
assert(t);
- assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
+ assert_se((whole_fd = sym_fdisk_get_devfd(context->fdisk_context)) >= 0);
log_info("Syncing future partition %"PRIu64" contents to disk.", p->partno);
@@ -5200,9 +5200,9 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
assert(p);
assert(p->encrypt != ENCRYPT_OFF);
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "libcryptsetup not found, cannot encrypt: %m");
+ return r;
log_info("Encrypting future partition %" PRIu64 "...", p->partno);
@@ -5253,7 +5253,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
return log_oom();
}
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
r = sym_crypt_init(&cd, offline ? hp : node);
if (r < 0)
return log_error_errno(r, "Failed to allocate libcryptsetup context for %s: %m", hp);
@@ -5709,7 +5709,7 @@ static int partition_format_verity_hash(
#if HAVE_LIBCRYPTSETUP
Partition *dp;
_cleanup_(partition_target_freep) PartitionTarget *t = NULL;
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_free_ char *hint = NULL;
int r;
@@ -5733,9 +5733,9 @@ static int partition_format_verity_hash(
(void) partition_hint(p, node, &hint);
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "libcryptsetup not found, cannot setup verity: %m");
+ return r;
if (!node) {
r = partition_target_prepare(context, p, p->new_size, /* need_path= */ true, &t);
@@ -5954,7 +5954,7 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
(void) partition_hint(p, context->node, &hint);
- assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
+ assert_se((whole_fd = sym_fdisk_get_devfd(context->fdisk_context)) >= 0);
_cleanup_(iovec_done) struct iovec sig_free = {};
const struct iovec *roothash, *sig;
@@ -6918,7 +6918,7 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
* appear in the host namespace. Hence we fork a child that has its own file system namespace and
* detached mount propagation. */
- (void) dlopen_libmount();
+ (void) dlopen_libmount(LOG_DEBUG);
r = pidref_safe_fork(
"(sd-copy)",
@@ -7424,7 +7424,7 @@ static int set_gpt_flags(struct fdisk_partition *q, uint64_t flags) {
return r;
}
- return fdisk_partition_set_attrs(q, strempty(a));
+ return sym_fdisk_partition_set_attrs(q, strempty(a));
}
static uint64_t partition_merge_flags(Partition *p) {
@@ -7497,11 +7497,11 @@ static int context_mangle_partitions(Context *context) {
assert(p->new_size >= p->current_size);
assert(p->new_size % context->sector_size == 0);
- r = fdisk_partition_size_explicit(p->current_partition, true);
+ r = sym_fdisk_partition_size_explicit(p->current_partition, true);
if (r < 0)
return log_error_errno(r, "Failed to enable explicit sizing: %m");
- r = fdisk_partition_set_size(p->current_partition, p->new_size / context->sector_size);
+ r = sym_fdisk_partition_set_size(p->current_partition, p->new_size / context->sector_size);
if (r < 0)
return log_error_errno(r, "Failed to grow partition: %m");
@@ -7510,7 +7510,7 @@ static int context_mangle_partitions(Context *context) {
}
if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
- r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
+ r = sym_fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
if (r < 0)
return log_error_errno(r, "Failed to set partition UUID: %m");
@@ -7519,7 +7519,7 @@ static int context_mangle_partitions(Context *context) {
}
if (!streq_ptr(p->new_label, p->current_label)) {
- r = fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
+ r = sym_fdisk_partition_set_name(p->current_partition, strempty(p->new_label));
if (r < 0)
return log_error_errno(r, "Failed to set partition label: %m");
@@ -7530,7 +7530,7 @@ static int context_mangle_partitions(Context *context) {
if (changed) {
assert(!PARTITION_IS_FOREIGN(p)); /* never touch foreign partitions */
- r = fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
+ r = sym_fdisk_set_partition(context->fdisk_context, p->partno, p->current_partition);
if (r < 0)
return log_error_errno(r, "Failed to update partition: %m");
}
@@ -7543,43 +7543,43 @@ static int context_mangle_partitions(Context *context) {
assert(p->new_size % context->sector_size == 0);
assert(p->new_label);
- t = fdisk_new_parttype();
+ t = sym_fdisk_new_parttype();
if (!t)
return log_oom();
- r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type.uuid));
+ r = sym_fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type.uuid));
if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m");
- q = fdisk_new_partition();
+ q = sym_fdisk_new_partition();
if (!q)
return log_oom();
- r = fdisk_partition_set_type(q, t);
+ r = sym_fdisk_partition_set_type(q, t);
if (r < 0)
return log_error_errno(r, "Failed to set partition type: %m");
- r = fdisk_partition_size_explicit(q, true);
+ r = sym_fdisk_partition_size_explicit(q, true);
if (r < 0)
return log_error_errno(r, "Failed to enable explicit sizing: %m");
- r = fdisk_partition_set_start(q, p->offset / context->sector_size);
+ r = sym_fdisk_partition_set_start(q, p->offset / context->sector_size);
if (r < 0)
return log_error_errno(r, "Failed to position partition: %m");
- r = fdisk_partition_set_size(q, p->new_size / context->sector_size);
+ r = sym_fdisk_partition_set_size(q, p->new_size / context->sector_size);
if (r < 0)
return log_error_errno(r, "Failed to grow partition: %m");
- r = fdisk_partition_set_partno(q, p->partno);
+ r = sym_fdisk_partition_set_partno(q, p->partno);
if (r < 0)
return log_error_errno(r, "Failed to set partition number: %m");
- r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
+ r = sym_fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
if (r < 0)
return log_error_errno(r, "Failed to set partition UUID: %m");
- r = fdisk_partition_set_name(q, strempty(p->new_label));
+ r = sym_fdisk_partition_set_name(q, strempty(p->new_label));
if (r < 0)
return log_error_errno(r, "Failed to set partition label: %m");
@@ -7590,7 +7590,7 @@ static int context_mangle_partitions(Context *context) {
log_info("Adding new partition %" PRIu64 " to partition table.", p->partno);
- r = fdisk_add_partition(context->fdisk_context, q, NULL);
+ r = sym_fdisk_add_partition(context->fdisk_context, q, NULL);
if (r < 0)
return log_error_errno(r, "Failed to add partition: %m");
@@ -7735,7 +7735,7 @@ static int context_split(Context *context) {
continue;
if (fd < 0) {
- assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
+ assert_se((fd = sym_fdisk_get_devfd(context->fdisk_context)) >= 0);
r = read_attr_fd(fd, &attrs);
if (r < 0 && !ERRNO_IS_NEG_NOT_SUPPORTED(r))
@@ -7754,9 +7754,30 @@ static int context_split(Context *context) {
if (lseek(fd, p->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to partition offset: %m");
- r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES|COPY_TRUNCATE);
- if (r < 0)
- return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path);
+ /* Verity signature partitions contain a JSON object NUL-padded out to the partition
+ * size. The on-disk partition must keep the padding, but the split-out file is a
+ * standalone artifact, so trim the trailing NUL bytes there to avoid tripping jq. */
+ if (partition_designator_is_verity_sig(p->type.designator)) {
+ _cleanup_free_ char *buf = malloc(p->new_size);
+ if (!buf)
+ return log_oom();
+
+ r = loop_read_exact(fd, buf, p->new_size, /* do_poll= */ false);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read verity signature partition: %m");
+
+ size_t len = strnlen(buf, p->new_size);
+ if (len == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Verity signature partition is empty");
+
+ r = loop_write(fdt, buf, len);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write to split partition %s: %m", p->split_path);
+ } else {
+ r = copy_bytes(fd, fdt, p->new_size, COPY_REFLINK|COPY_HOLES|COPY_TRUNCATE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to copy to split partition %s: %m", p->split_path);
+ }
}
return 0;
@@ -8058,7 +8079,7 @@ static int context_verify_eltorito_overlap(Context *context) {
return 0;
/* Check how many GPT partition entries can be stored. */
- size_t nents = fdisk_get_npartitions(context->fdisk_context);
+ size_t nents = sym_fdisk_get_npartitions(context->fdisk_context);
/* The GPT contains
* - 1 unused block (protective MBR)
* - GPT header
@@ -8073,7 +8094,7 @@ static int context_verify_eltorito_overlap(Context *context) {
* there, we should still not overlap with it since a partition could be added later.
* It is unexpected for tools to change the first lba in the GPT header. So this should be safe.
*/
- if (fdisk_get_first_lba(context->fdisk_context) * context->sector_size < (ISO9660_START+ISO9660_SIZE)*ISO9660_BLOCK_SIZE)
+ if (sym_fdisk_get_first_lba(context->fdisk_context) * context->sector_size < (ISO9660_START+ISO9660_SIZE)*ISO9660_BLOCK_SIZE)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "El Torito is overlapping with the first partition block.");
return 0;
@@ -8143,7 +8164,7 @@ static int context_write_partition_table(Context *context) {
}
}
- r = fdisk_get_partitions(context->fdisk_context, &original_table);
+ r = sym_fdisk_get_partitions(context->fdisk_context, &original_table);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
@@ -8169,11 +8190,11 @@ static int context_write_partition_table(Context *context) {
(void) context_notify(context, PROGRESS_WRITING_TABLE, /* object= */ NULL, UINT_MAX);
- r = fdisk_write_disklabel(context->fdisk_context);
+ r = sym_fdisk_write_disklabel(context->fdisk_context);
if (r < 0)
return log_error_errno(r, "Failed to write partition table: %m");
- capable = blockdev_partscan_enabled_fd(fdisk_get_devfd(context->fdisk_context));
+ capable = blockdev_partscan_enabled_fd(sym_fdisk_get_devfd(context->fdisk_context));
if (capable == -ENOTBLK)
log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
else if (capable < 0)
@@ -8182,7 +8203,7 @@ static int context_write_partition_table(Context *context) {
log_info("Informing kernel about changed partitions...");
(void) context_notify(context, PROGRESS_REREADING_TABLE, /* object= */ NULL, UINT_MAX);
- r = reread_partition_table_fd(fdisk_get_devfd(context->fdisk_context), /* flags= */ 0);
+ r = reread_partition_table_fd(sym_fdisk_get_devfd(context->fdisk_context), /* flags= */ 0);
if (r < 0)
return log_error_errno(r, "Failed to reread partition table: %m");
} else
@@ -8218,7 +8239,14 @@ static int context_write_eltorito(Context *context) {
log_info("Writing El Torito boot catalog.");
- r = write_eltorito(fdisk_get_devfd(context->fdisk_context), usec, utc, esp_offset / ISO9660_BLOCK_SIZE, arg_eltorito_system, arg_eltorito_volume, arg_eltorito_publisher);
+ r = write_eltorito(
+ sym_fdisk_get_devfd(context->fdisk_context),
+ usec,
+ utc,
+ esp_offset / ISO9660_BLOCK_SIZE,
+ arg_eltorito_system,
+ arg_eltorito_volume,
+ arg_eltorito_publisher);
if (r < 0)
return log_error_errno(r, "Failed to write El Torito boot catalog: %m");
@@ -8279,7 +8307,7 @@ static int context_factory_reset(Context *context) {
log_info("Removing partition %" PRIu64 " for factory reset.", p->partno);
- r = fdisk_delete_partition(context->fdisk_context, p->partno);
+ r = sym_fdisk_delete_partition(context->fdisk_context, p->partno);
if (r < 0)
return log_error_errno(r, "Failed to remove partition %" PRIu64 ": %m", p->partno);
@@ -8291,7 +8319,7 @@ static int context_factory_reset(Context *context) {
return 0;
}
- r = fdisk_write_disklabel(context->fdisk_context);
+ r = sym_fdisk_write_disklabel(context->fdisk_context);
if (r < 0)
return log_error_errno(r, "Failed to write disk label: %m");
@@ -8351,9 +8379,9 @@ static int resolve_copy_blocks_auto_candidate(
return log_error_errno(r, "Failed to open block device " DEVNUM_FORMAT_STR ": %m",
DEVNUM_FORMAT_VAL(whole_devno));
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Failed to find libblkid: %m");
+ return r;
b = sym_blkid_new_probe();
if (!b)
@@ -9220,7 +9248,7 @@ static int context_minimize(Context *context) {
attrs & FS_NOCOW_FL ? XO_NOCOW : 0,
0600);
if (fd < 0)
- return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
+ return log_error_errno(fd, "Failed to open temporary file %s: %m", temp);
if (fstype_is_ro(p->format) || is_btrfs)
/* Read-only filesystems and btrfs (with mkfs.btrfs --shrink) produce a minimal
@@ -9434,7 +9462,7 @@ static int context_minimize(Context *context) {
attrs & FS_NOCOW_FL ? XO_NOCOW : 0,
0600);
if (fd < 0)
- return log_error_errno(errno, "Failed to open temporary file %s: %m", temp);
+ return log_error_errno(fd, "Failed to open temporary file %s: %m", temp);
r = partition_format_verity_hash(context, p, temp, dp->copy_blocks_path);
if (r < 0)
@@ -10597,7 +10625,7 @@ static int find_root(Context *context) {
fd = xopenat_full(AT_FDCWD, arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, XO_NOCOW, 0666);
if (fd < 0)
- return log_error_errno(errno, "Failed to create '%s': %m", arg_node);
+ return log_error_errno(fd, "Failed to create '%s': %m", arg_node);
context->node = TAKE_PTR(s);
context->node_is_our_file = true;
@@ -10666,7 +10694,7 @@ static int resize_pt(int fd, uint64_t sector_size) {
if (r < 0)
return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd));
- r = fdisk_has_label(c);
+ r = sym_fdisk_has_label(c);
if (r < 0)
return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", FORMAT_PROC_FD_PATH(fd));
if (r == 0) {
@@ -10674,7 +10702,7 @@ static int resize_pt(int fd, uint64_t sector_size) {
return 0;
}
- r = fdisk_write_disklabel(c);
+ r = sym_fdisk_write_disklabel(c);
if (r < 0)
return log_error_errno(r, "Failed to write resized partition table: %m");
@@ -11211,9 +11239,9 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
-#if HAVE_LIBCRYPTSETUP
- cryptsetup_enable_logging(NULL);
-#endif
+ r = dlopen_fdisk(LOG_ERR);
+ if (r < 0)
+ return r;
if (arg_varlink)
return vl_server();
diff --git a/src/report/report-upload.c b/src/report/report-upload.c
index e70f8efa34..c64bf86e13 100644
--- a/src/report/report-upload.c
+++ b/src/report/report-upload.c
@@ -85,7 +85,7 @@ int upload_collected(Context *context) {
_cleanup_free_ char *json = NULL;
int r;
- r = dlopen_curl();
+ r = dlopen_curl(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/resolve/resolved-dns-delegate.c b/src/resolve/resolved-dns-delegate.c
index eee2daab94..db34916a29 100644
--- a/src/resolve/resolved-dns-delegate.c
+++ b/src/resolve/resolved-dns-delegate.c
@@ -172,8 +172,8 @@ static int dns_delegate_load(Manager *m, const char *path) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DNS delegate file name does not end in .dns-delegate, refusing: %s", fn);
_cleanup_free_ char *id = strndup(fn, e - fn);
- if (!string_is_safe(id))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DNS delegate file name contains weird characters, refusing: %s", fn);
+ if (!string_is_safe(id, /* flags= */ 0))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "DNS delegate file name is invalid, refusing: %s", fn);
_cleanup_free_ char *dropin_dirname = strjoin(id, ".dns-delegate.d");
if (!dropin_dirname)
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index e10605538a..b1d1b0069c 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -347,7 +347,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
IOVEC_MAKE(DNS_PACKET_DATA(s->write_packet), s->write_packet->size),
};
- iovec_increment(iov, ELEMENTSOF(iov), s->n_written);
+ iovec_inc_many(iov, ELEMENTSOF(iov), s->n_written);
ssize_t ss = dns_stream_writev(s, iov, ELEMENTSOF(iov), 0);
if (ss < 0) {
diff --git a/src/resolve/resolved-dnstls.c b/src/resolve/resolved-dnstls.c
index 09dda4508b..042077ab06 100644
--- a/src/resolve/resolved-dnstls.c
+++ b/src/resolve/resolved-dnstls.c
@@ -317,26 +317,30 @@ static ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t co
}
ssize_t dnstls_stream_writev(DnsStream *stream, const struct iovec *iov, size_t iovcnt) {
- _cleanup_free_ char *buf = NULL;
- size_t count;
-
assert(stream);
assert(stream->encrypted);
assert(stream->dnstls_data.ssl);
assert(iov);
- assert(iovec_total_size(iov, iovcnt) > 0);
+
+ size_t size = iovec_total_size(iov, iovcnt);
+ if (size == 0)
+ return -EINVAL;
+ if (size == SIZE_MAX)
+ return -ENOBUFS;
if (iovcnt == 1)
return dnstls_stream_write(stream, iov[0].iov_base, iov[0].iov_len);
/* As of now, OpenSSL cannot accumulate multiple writes, so join into a
single buffer. Suboptimal, but better than multiple SSL_write calls. */
- count = iovec_total_size(iov, iovcnt);
- buf = new(char, count);
+ _cleanup_free_ char *buf = new(char, size);
+ if (!buf)
+ return -ENOMEM;
+
for (size_t i = 0, pos = 0; i < iovcnt; pos += iov[i].iov_len, i++)
memcpy(buf + pos, iov[i].iov_base, iov[i].iov_len);
- return dnstls_stream_write(stream, buf, count);
+ return dnstls_stream_write(stream, buf, size);
}
ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c
index 5026b10ff4..fb20ba9cd0 100644
--- a/src/resolve/resolved-mdns.c
+++ b/src/resolve/resolved-mdns.c
@@ -413,6 +413,14 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
if (r <= 0)
return r;
+ /* Refuse traffic from the local host, to avoid query loops. However, allow legacy mDNS
+ * unicast queries through anyway (we never send those ourselves, hence no risk).
+ * i.e. check for the source port nr. */
+ if (p->sender_port == MDNS_PORT && manager_packet_from_local_address(m, p)) {
+ log_debug("Got mDNS UDP packet from local host, ignoring.");
+ return 0;
+ }
+
scope = manager_find_scope(m, p);
if (!scope) {
log_debug("Got mDNS UDP packet on unknown scope. Ignoring.");
@@ -529,14 +537,6 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
if (unsolicited_packet)
mdns_notify_browsers_unsolicited_updates(m, p->answer, p->family);
} else if (dns_packet_validate_query(p) > 0) {
- /* Refuse traffic from the local host, to avoid query loops. However, allow legacy mDNS
- * unicast queries through anyway (we never send those ourselves, hence no risk).
- * i.e. check for the source port nr. */
- if (p->sender_port == MDNS_PORT && manager_packet_from_local_address(m, p)) {
- log_debug("Got mDNS UDP packet from local host, ignoring.");
- return 0;
- }
-
log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));
r = mdns_scope_process_query(scope, p);
diff --git a/src/resolve/resolved-util.c b/src/resolve/resolved-util.c
index eec2819767..094ef00698 100644
--- a/src/resolve/resolved-util.c
+++ b/src/resolve/resolved-util.c
@@ -36,7 +36,7 @@ int resolve_system_hostname(char **full_hostname, char **first_label) {
#if HAVE_LIBIDN2
_cleanup_free_ char *utf8 = NULL;
- if (dlopen_idn() >= 0) {
+ if (dlopen_idn(LOG_DEBUG) >= 0) {
r = sym_idn2_to_unicode_8z8z(label, &utf8, 0);
if (r != IDN2_OK)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index 07206bdb5f..92d920e171 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -10,6 +10,7 @@
#include "errno-util.h"
#include "extract-word.h"
#include "fd-util.h"
+#include "log.h" /* IWYU pragma: keep */
#include "set.h"
#include "string-util.h"
#include "strv.h"
@@ -44,8 +45,10 @@ DLSYM_PROTOTYPE(acl_set_permset);
DLSYM_PROTOTYPE(acl_set_qualifier);
DLSYM_PROTOTYPE(acl_set_tag_type);
DLSYM_PROTOTYPE(acl_to_any_text);
+#endif
-int dlopen_libacl(void) {
+int dlopen_libacl(int log_level) {
+#if HAVE_ACL
SD_ELF_NOTE_DLOPEN(
"acl",
"Support for file Access Control Lists (ACLs)",
@@ -55,7 +58,7 @@ int dlopen_libacl(void) {
return dlopen_many_sym_or_warn(
&libacl_dl,
"libacl.so.1",
- LOG_DEBUG,
+ log_level,
DLSYM_ARG(acl_add_perm),
DLSYM_ARG(acl_calc_mask),
DLSYM_ARG(acl_copy_entry),
@@ -82,8 +85,13 @@ int dlopen_libacl(void) {
DLSYM_ARG(acl_set_qualifier),
DLSYM_ARG(acl_set_tag_type),
DLSYM_ARG(acl_to_any_text));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libacl support is not compiled in.");
+#endif
}
+#if HAVE_ACL
int devnode_acl(int fd, const Set *uids) {
_cleanup_set_free_ Set *found = NULL;
bool changed = false;
@@ -91,7 +99,7 @@ int devnode_acl(int fd, const Set *uids) {
assert(fd >= 0);
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
@@ -336,7 +344,7 @@ int acl_search_groups(const char *path, char ***ret_groups) {
assert(path);
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
@@ -413,7 +421,7 @@ int parse_acl(
if (!split)
return -ENOMEM;
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
@@ -591,7 +599,7 @@ int acls_for_file(const char *path, acl_type_t type, acl_t acl, acl_t *ret) {
assert(path);
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
@@ -650,7 +658,7 @@ int fd_add_uid_acl_permission(
assert(fd >= 0);
assert(uid_is_valid(uid));
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
@@ -716,7 +724,7 @@ int fd_acl_make_read_only(int fd) {
/* Safely drops all W bits from all relevant ACL entries of the file, without changing entries which
* are masked by the ACL mask */
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
goto maybe_fallback;
@@ -804,7 +812,7 @@ int fd_acl_make_writable(int fd) {
/* Safely adds the writable bit to the owner's ACL entry of this inode. (And only the owner's! – This
* not the obvious inverse of fd_acl_make_read_only() hence!) */
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
goto maybe_fallback;
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
index 1b74101ae4..5e2aeb94a9 100644
--- a/src/shared/acl-util.h
+++ b/src/shared/acl-util.h
@@ -36,8 +36,6 @@ extern DLSYM_PROTOTYPE(acl_set_qualifier);
extern DLSYM_PROTOTYPE(acl_set_tag_type);
extern DLSYM_PROTOTYPE(acl_to_any_text);
-int dlopen_libacl(void);
-
int devnode_acl(int fd, const Set *uids);
int calc_acl_mask_if_needed(acl_t *acl_p);
@@ -85,10 +83,6 @@ typedef unsigned acl_type_t;
#define ACL_TYPE_ACCESS (0x8000)
#define ACL_TYPE_DEFAULT (0x4000)
-static inline int dlopen_libacl(void) {
- return -EOPNOTSUPP;
-}
-
static inline int devnode_acl(int fd, const Set *uids) {
return -EOPNOTSUPP;
}
@@ -98,6 +92,8 @@ static inline int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask) {
}
#endif
+int dlopen_libacl(int log_level);
+
int fd_acl_make_read_only(int fd);
int fd_acl_make_writable(int fd);
diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c
index e24f4315a0..5f01bfae01 100644
--- a/src/shared/apparmor-util.c
+++ b/src/shared/apparmor-util.c
@@ -1,13 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "apparmor-util.h"
+#include "log.h"
+
+#if HAVE_APPARMOR
+
#include
#include "sd-dlopen.h"
#include "alloc-util.h"
-#include "apparmor-util.h"
#include "fileio.h"
-#include "log.h"
#include "parse-util.h"
static void *libapparmor_dl = NULL;
@@ -21,27 +24,6 @@ DLSYM_PROTOTYPE(aa_policy_cache_new) = NULL;
DLSYM_PROTOTYPE(aa_policy_cache_replace_all) = NULL;
DLSYM_PROTOTYPE(aa_policy_cache_unref) = NULL;
-int dlopen_libapparmor(void) {
- SD_ELF_NOTE_DLOPEN(
- "apparmor",
- "Support for AppArmor policies",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libapparmor.so.1");
-
- return dlopen_many_sym_or_warn(
- &libapparmor_dl,
- "libapparmor.so.1",
- LOG_DEBUG,
- DLSYM_ARG(aa_change_onexec),
- DLSYM_ARG(aa_change_profile),
- DLSYM_ARG(aa_features_new_from_kernel),
- DLSYM_ARG(aa_features_unref),
- DLSYM_ARG(aa_policy_cache_dir_path_preview),
- DLSYM_ARG(aa_policy_cache_new),
- DLSYM_ARG(aa_policy_cache_replace_all),
- DLSYM_ARG(aa_policy_cache_unref));
-}
-
bool mac_apparmor_use(void) {
static int cached_use = -1;
int r;
@@ -63,8 +45,36 @@ bool mac_apparmor_use(void) {
if (r <= 0)
return (cached_use = false);
- if (dlopen_libapparmor() < 0)
+ if (dlopen_libapparmor(LOG_DEBUG) < 0)
return (cached_use = false);
return (cached_use = true);
}
+
+#endif
+
+int dlopen_libapparmor(int log_level) {
+#if HAVE_APPARMOR
+ SD_ELF_NOTE_DLOPEN(
+ "apparmor",
+ "Support for AppArmor policies",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libapparmor.so.1");
+
+ return dlopen_many_sym_or_warn(
+ &libapparmor_dl,
+ "libapparmor.so.1",
+ log_level,
+ DLSYM_ARG(aa_change_onexec),
+ DLSYM_ARG(aa_change_profile),
+ DLSYM_ARG(aa_features_new_from_kernel),
+ DLSYM_ARG(aa_features_unref),
+ DLSYM_ARG(aa_policy_cache_dir_path_preview),
+ DLSYM_ARG(aa_policy_cache_new),
+ DLSYM_ARG(aa_policy_cache_replace_all),
+ DLSYM_ARG(aa_policy_cache_unref));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libapparmor support is not compiled in.");
+#endif
+}
diff --git a/src/shared/apparmor-util.h b/src/shared/apparmor-util.h
index 06d6bf30e2..e87ba84504 100644
--- a/src/shared/apparmor-util.h
+++ b/src/shared/apparmor-util.h
@@ -19,14 +19,11 @@ extern DLSYM_PROTOTYPE(aa_policy_cache_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(aa_features*, sym_aa_features_unref, aa_features_unrefp, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(aa_policy_cache*, sym_aa_policy_cache_unref, aa_policy_cache_unrefp, NULL);
-
-int dlopen_libapparmor(void);
bool mac_apparmor_use(void);
#else
-static inline int dlopen_libapparmor(void) {
- return -EOPNOTSUPP;
-}
static inline bool mac_apparmor_use(void) {
return false;
}
#endif
+
+int dlopen_libapparmor(int log_level);
diff --git a/src/shared/blkid-util.c b/src/shared/blkid-util.c
index f1b7ccdfeb..18bf100d06 100644
--- a/src/shared/blkid-util.c
+++ b/src/shared/blkid-util.c
@@ -1,11 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include
-
#include "sd-dlopen.h"
#include "sd-id128.h"
#include "blkid-util.h"
+#include "log.h" /* IWYU pragma: keep */
#include "parse-util.h"
#include "string-util.h"
@@ -49,55 +48,6 @@ DLSYM_PROTOTYPE(blkid_probe_set_sectorsize) = NULL;
DLSYM_PROTOTYPE(blkid_probe_set_superblocks_flags) = NULL;
DLSYM_PROTOTYPE(blkid_safe_string) = NULL;
-int dlopen_libblkid(void) {
- SD_ELF_NOTE_DLOPEN(
- "blkid",
- "Support for block device identification",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libblkid.so.1");
-
- return dlopen_many_sym_or_warn(
- &libblkid_dl,
- "libblkid.so.1",
- LOG_DEBUG,
- DLSYM_ARG(blkid_do_fullprobe),
- DLSYM_ARG(blkid_do_probe),
- DLSYM_ARG(blkid_do_safeprobe),
- DLSYM_ARG(blkid_do_wipe),
- DLSYM_ARG(blkid_encode_string),
- DLSYM_ARG(blkid_free_probe),
- DLSYM_ARG(blkid_new_probe),
- DLSYM_ARG(blkid_new_probe_from_filename),
- DLSYM_ARG(blkid_partition_get_flags),
- DLSYM_ARG(blkid_partition_get_name),
- DLSYM_ARG(blkid_partition_get_partno),
- DLSYM_ARG(blkid_partition_get_size),
- DLSYM_ARG(blkid_partition_get_start),
- DLSYM_ARG(blkid_partition_get_type),
- DLSYM_ARG(blkid_partition_get_type_string),
- DLSYM_ARG(blkid_partition_get_uuid),
- DLSYM_ARG(blkid_partlist_devno_to_partition),
- DLSYM_ARG(blkid_partlist_get_partition),
- DLSYM_ARG(blkid_partlist_numof_partitions),
- DLSYM_ARG(blkid_probe_enable_partitions),
- DLSYM_ARG(blkid_probe_enable_superblocks),
- DLSYM_ARG(blkid_probe_filter_superblocks_type),
- DLSYM_ARG(blkid_probe_filter_superblocks_usage),
- DLSYM_ARG(blkid_probe_get_fd),
- DLSYM_ARG(blkid_probe_get_partitions),
- DLSYM_ARG(blkid_probe_get_size),
- DLSYM_ARG(blkid_probe_get_value),
- DLSYM_ARG(blkid_probe_is_wholedisk),
- DLSYM_ARG(blkid_probe_lookup_value),
- DLSYM_ARG(blkid_probe_numof_values),
- DLSYM_ARG(blkid_probe_set_device),
- DLSYM_ARG(blkid_probe_set_hint),
- DLSYM_ARG(blkid_probe_set_partitions_flags),
- DLSYM_ARG(blkid_probe_set_sectorsize),
- DLSYM_ARG(blkid_probe_set_superblocks_flags),
- DLSYM_ARG(blkid_safe_string));
-}
-
int blkid_partition_get_uuid_id128(blkid_partition p, sd_id128_t *ret) {
const char *s;
@@ -146,3 +96,57 @@ int blkid_probe_lookup_value_u64(blkid_probe b, const char *field, uint64_t *ret
return safe_atou64(u, ret);
}
#endif
+
+int dlopen_libblkid(int log_level) {
+#if HAVE_BLKID
+ SD_ELF_NOTE_DLOPEN(
+ "blkid",
+ "Support for block device identification",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libblkid.so.1");
+
+ return dlopen_many_sym_or_warn(
+ &libblkid_dl,
+ "libblkid.so.1",
+ log_level,
+ DLSYM_ARG(blkid_do_fullprobe),
+ DLSYM_ARG(blkid_do_probe),
+ DLSYM_ARG(blkid_do_safeprobe),
+ DLSYM_ARG(blkid_do_wipe),
+ DLSYM_ARG(blkid_encode_string),
+ DLSYM_ARG(blkid_free_probe),
+ DLSYM_ARG(blkid_new_probe),
+ DLSYM_ARG(blkid_new_probe_from_filename),
+ DLSYM_ARG(blkid_partition_get_flags),
+ DLSYM_ARG(blkid_partition_get_name),
+ DLSYM_ARG(blkid_partition_get_partno),
+ DLSYM_ARG(blkid_partition_get_size),
+ DLSYM_ARG(blkid_partition_get_start),
+ DLSYM_ARG(blkid_partition_get_type),
+ DLSYM_ARG(blkid_partition_get_type_string),
+ DLSYM_ARG(blkid_partition_get_uuid),
+ DLSYM_ARG(blkid_partlist_devno_to_partition),
+ DLSYM_ARG(blkid_partlist_get_partition),
+ DLSYM_ARG(blkid_partlist_numof_partitions),
+ DLSYM_ARG(blkid_probe_enable_partitions),
+ DLSYM_ARG(blkid_probe_enable_superblocks),
+ DLSYM_ARG(blkid_probe_filter_superblocks_type),
+ DLSYM_ARG(blkid_probe_filter_superblocks_usage),
+ DLSYM_ARG(blkid_probe_get_fd),
+ DLSYM_ARG(blkid_probe_get_partitions),
+ DLSYM_ARG(blkid_probe_get_size),
+ DLSYM_ARG(blkid_probe_get_value),
+ DLSYM_ARG(blkid_probe_is_wholedisk),
+ DLSYM_ARG(blkid_probe_lookup_value),
+ DLSYM_ARG(blkid_probe_numof_values),
+ DLSYM_ARG(blkid_probe_set_device),
+ DLSYM_ARG(blkid_probe_set_hint),
+ DLSYM_ARG(blkid_probe_set_partitions_flags),
+ DLSYM_ARG(blkid_probe_set_sectorsize),
+ DLSYM_ARG(blkid_probe_set_superblocks_flags),
+ DLSYM_ARG(blkid_safe_string));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libblkid support is not compiled in.");
+#endif
+}
diff --git a/src/shared/blkid-util.h b/src/shared/blkid-util.h
index 09502eadc4..718a0f15a9 100644
--- a/src/shared/blkid-util.h
+++ b/src/shared/blkid-util.h
@@ -46,8 +46,6 @@ extern DLSYM_PROTOTYPE(blkid_probe_set_sectorsize);
extern DLSYM_PROTOTYPE(blkid_probe_set_superblocks_flags);
extern DLSYM_PROTOTYPE(blkid_safe_string);
-int dlopen_libblkid(void);
-
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(blkid_probe, sym_blkid_free_probe, blkid_free_probep, NULL);
int blkid_partition_get_uuid_id128(blkid_partition p, sd_id128_t *ret);
@@ -65,8 +63,6 @@ enum {
int blkid_probe_lookup_value_id128(blkid_probe b, const char *field, sd_id128_t *ret);
int blkid_probe_lookup_value_u64(blkid_probe b, const char *field, uint64_t *ret);
-#else
-static inline int dlopen_libblkid(void) {
- return -EOPNOTSUPP;
-}
#endif
+
+int dlopen_libblkid(int log_level);
diff --git a/src/shared/boot-entry.c b/src/shared/boot-entry.c
index ce75807491..b8665d7abb 100644
--- a/src/shared/boot-entry.c
+++ b/src/shared/boot-entry.c
@@ -11,10 +11,9 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
-#include "utf8.h"
bool boot_entry_token_valid(const char *p) {
- return utf8_is_valid(p) && string_is_safe(p) && filename_is_valid(p);
+ return string_is_safe(p, STRING_FILENAME);
}
static int entry_token_load_one(int rfd, const char *dir, BootEntryTokenType *type, char **token) {
diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c
index c8e2e7ce4d..1d2fdef781 100644
--- a/src/shared/bpf-dlopen.c
+++ b/src/shared/bpf-dlopen.c
@@ -76,7 +76,7 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis
return log_internalv(LOG_DEBUG, errno, NULL, 0, NULL, fmt, ap);
}
-int dlopen_bpf_full(int log_level) {
+int dlopen_bpf(int log_level) {
static int cached = 0;
int r;
@@ -210,7 +210,7 @@ int bpf_get_error_translated(const void *ptr) {
#else
-int dlopen_bpf_full(int log_level) {
+int dlopen_bpf(int log_level) {
return log_once_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
"libbpf support is not compiled in, cgroup BPF features disabled.");
}
diff --git a/src/shared/bpf-dlopen.h b/src/shared/bpf-dlopen.h
index ecae890035..b3d14f9b5f 100644
--- a/src/shared/bpf-dlopen.h
+++ b/src/shared/bpf-dlopen.h
@@ -51,7 +51,4 @@ int bpf_get_error_translated(const void *ptr);
#endif
-int dlopen_bpf_full(int log_level);
-static inline int dlopen_bpf(void) {
- return dlopen_bpf_full(LOG_DEBUG);
-}
+int dlopen_bpf(int log_level);
diff --git a/src/shared/bpf-link.c b/src/shared/bpf-link.c
index 72d374c235..95f7256a56 100644
--- a/src/shared/bpf-link.c
+++ b/src/shared/bpf-link.c
@@ -9,7 +9,7 @@ bool bpf_can_link_program(struct bpf_program *prog) {
assert(prog);
- if (dlopen_bpf() < 0)
+ if (dlopen_bpf(LOG_DEBUG) < 0)
return false;
/* Pass invalid cgroup fd intentionally. */
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index ba0bc4ad8c..bfba85564f 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -217,8 +217,8 @@ static int parse_line(
if (!n)
return log_oom();
- if (!string_is_safe(n))
- return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EBADMSG), "Bad characters in section header '%s'", l);
+ if (!string_is_safe(n, /* flags= */ 0))
+ return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EBADMSG), "Section header invalid '%s'", l);
if (sections && !nulstr_contains(sections, n)) {
bool ignore;
@@ -1244,7 +1244,7 @@ int config_parse_string(
return 1;
}
- if (FLAGS_SET(ltype, CONFIG_PARSE_STRING_SAFE) && !string_is_safe(rvalue)) {
+ if (FLAGS_SET(ltype, CONFIG_PARSE_STRING_SAFE) && !string_is_safe(rvalue, STRING_ALLOW_GLOBS)) {
_cleanup_free_ char *escaped = NULL;
escaped = cescape(rvalue);
diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c
index ba7910d864..47a148459d 100644
--- a/src/shared/cryptsetup-util.c
+++ b/src/shared/cryptsetup-util.c
@@ -21,7 +21,9 @@ static void *cryptsetup_dl = NULL;
DLSYM_PROTOTYPE(crypt_activate_by_passphrase) = NULL;
DLSYM_PROTOTYPE(crypt_activate_by_signed_key) = NULL;
+DLSYM_PROTOTYPE(crypt_activate_by_token_pin) = NULL;
DLSYM_PROTOTYPE(crypt_activate_by_volume_key) = NULL;
+DLSYM_PROTOTYPE(crypt_deactivate) = NULL;
DLSYM_PROTOTYPE(crypt_deactivate_by_name) = NULL;
DLSYM_PROTOTYPE(crypt_format) = NULL;
DLSYM_PROTOTYPE(crypt_free) = NULL;
@@ -37,9 +39,11 @@ DLSYM_PROTOTYPE(crypt_get_volume_key_size) = NULL;
DLSYM_PROTOTYPE(crypt_header_restore) = NULL;
DLSYM_PROTOTYPE(crypt_init) = NULL;
DLSYM_PROTOTYPE(crypt_init_by_name) = NULL;
+DLSYM_PROTOTYPE(crypt_init_data_device) = NULL;
DLSYM_PROTOTYPE(crypt_keyslot_add_by_volume_key) = NULL;
DLSYM_PROTOTYPE(crypt_keyslot_destroy) = NULL;
DLSYM_PROTOTYPE(crypt_keyslot_max) = NULL;
+DLSYM_PROTOTYPE(crypt_keyslot_status) = NULL;
DLSYM_PROTOTYPE(crypt_load) = NULL;
DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL;
DLSYM_PROTOTYPE(crypt_persistent_flags_get) = NULL;
@@ -51,10 +55,15 @@ DLSYM_PROTOTYPE(crypt_resume_by_volume_key) = NULL;
DLSYM_PROTOTYPE(crypt_set_data_device) = NULL;
DLSYM_PROTOTYPE(crypt_set_data_offset) = NULL;
DLSYM_PROTOTYPE(crypt_set_debug_level) = NULL;
+#if HAVE_CRYPT_SET_KEYRING_TO_LINK
+DLSYM_PROTOTYPE(crypt_set_keyring_to_link) = NULL;
+#endif
DLSYM_PROTOTYPE(crypt_set_log_callback) = NULL;
DLSYM_PROTOTYPE(crypt_set_metadata_size) = NULL;
DLSYM_PROTOTYPE(crypt_set_pbkdf_type) = NULL;
+DLSYM_PROTOTYPE(crypt_status) = NULL;
DLSYM_PROTOTYPE(crypt_suspend) = NULL;
+DLSYM_PROTOTYPE(crypt_token_external_path) = NULL;
DLSYM_PROTOTYPE(crypt_token_json_get) = NULL;
DLSYM_PROTOTYPE(crypt_token_json_set) = NULL;
DLSYM_PROTOTYPE(crypt_token_max) = NULL;
@@ -98,7 +107,7 @@ void cryptsetup_enable_logging(struct crypt_device *cd) {
* endless loop, but isn't because we break it via the check for 'cryptsetup_dl' early in
* dlopen_cryptsetup(). */
- if (dlopen_cryptsetup() < 0)
+ if (dlopen_cryptsetup(LOG_DEBUG) < 0)
return; /* If this fails, let's gracefully ignore the issue, this is just debug logging after
* all, and if this failed we already generated a debug log message that should help
* to track things down. */
@@ -124,10 +133,6 @@ int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd) {
/* Sets a minimal PKBDF in case we already have a high entropy key. */
- r = dlopen_cryptsetup();
- if (r < 0)
- return r;
-
r = sym_crypt_set_pbkdf_type(cd, &minimal_pbkdf);
if (r < 0)
return r;
@@ -155,10 +160,6 @@ int cryptsetup_get_token_as_json(
* -EMEDIUMTYPE → "verify_type" specified and doesn't match token's type
*/
- r = dlopen_cryptsetup();
- if (r < 0)
- return r;
-
r = sym_crypt_token_json_get(cd, idx, &text);
if (r < 0)
return r;
@@ -188,10 +189,6 @@ int cryptsetup_add_token_json(struct crypt_device *cd, sd_json_variant *v) {
_cleanup_free_ char *text = NULL;
int r;
- r = dlopen_cryptsetup();
- if (r < 0)
- return r;
-
r = sd_json_variant_format(v, 0, &text);
if (r < 0)
return log_debug_errno(r, "Failed to format token data for LUKS: %m");
@@ -268,7 +265,7 @@ int cryptsetup_get_volume_key_id(
}
#endif
-int dlopen_cryptsetup(void) {
+int dlopen_cryptsetup(int log_level) {
#if HAVE_LIBCRYPTSETUP
int r;
@@ -284,10 +281,12 @@ int dlopen_cryptsetup(void) {
"libcryptsetup.so.12");
r = dlopen_many_sym_or_warn(
- &cryptsetup_dl, "libcryptsetup.so.12", LOG_DEBUG,
+ &cryptsetup_dl, "libcryptsetup.so.12", log_level,
DLSYM_ARG(crypt_activate_by_passphrase),
DLSYM_ARG(crypt_activate_by_signed_key),
+ DLSYM_ARG(crypt_activate_by_token_pin),
DLSYM_ARG(crypt_activate_by_volume_key),
+ DLSYM_ARG(crypt_deactivate),
DLSYM_ARG(crypt_deactivate_by_name),
DLSYM_ARG(crypt_format),
DLSYM_ARG(crypt_free),
@@ -303,9 +302,11 @@ int dlopen_cryptsetup(void) {
DLSYM_ARG(crypt_header_restore),
DLSYM_ARG(crypt_init),
DLSYM_ARG(crypt_init_by_name),
+ DLSYM_ARG(crypt_init_data_device),
DLSYM_ARG(crypt_keyslot_add_by_volume_key),
DLSYM_ARG(crypt_keyslot_destroy),
DLSYM_ARG(crypt_keyslot_max),
+ DLSYM_ARG(crypt_keyslot_status),
DLSYM_ARG(crypt_load),
DLSYM_ARG(crypt_metadata_locking),
DLSYM_ARG(crypt_persistent_flags_get),
@@ -317,10 +318,15 @@ int dlopen_cryptsetup(void) {
DLSYM_ARG(crypt_set_data_device),
DLSYM_ARG(crypt_set_data_offset),
DLSYM_ARG(crypt_set_debug_level),
+#if HAVE_CRYPT_SET_KEYRING_TO_LINK
+ DLSYM_ARG(crypt_set_keyring_to_link),
+#endif
DLSYM_ARG(crypt_set_log_callback),
DLSYM_ARG(crypt_set_metadata_size),
DLSYM_ARG(crypt_set_pbkdf_type),
+ DLSYM_ARG(crypt_status),
DLSYM_ARG(crypt_suspend),
+ DLSYM_ARG(crypt_token_external_path),
DLSYM_ARG(crypt_token_json_get),
DLSYM_ARG(crypt_token_json_set),
DLSYM_ARG(crypt_token_max),
@@ -355,7 +361,8 @@ int dlopen_cryptsetup(void) {
return 1;
#else
- return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "cryptsetup support is not compiled in.");
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libcryptsetup support is not compiled in.");
#endif
}
diff --git a/src/shared/cryptsetup-util.h b/src/shared/cryptsetup-util.h
index 2e3ffe4c9e..4e994ce9f9 100644
--- a/src/shared/cryptsetup-util.h
+++ b/src/shared/cryptsetup-util.h
@@ -9,7 +9,9 @@
extern DLSYM_PROTOTYPE(crypt_activate_by_passphrase);
extern DLSYM_PROTOTYPE(crypt_activate_by_signed_key);
+extern DLSYM_PROTOTYPE(crypt_activate_by_token_pin);
extern DLSYM_PROTOTYPE(crypt_activate_by_volume_key);
+extern DLSYM_PROTOTYPE(crypt_deactivate);
extern DLSYM_PROTOTYPE(crypt_deactivate_by_name);
extern DLSYM_PROTOTYPE(crypt_format);
extern DLSYM_PROTOTYPE(crypt_free);
@@ -25,9 +27,11 @@ extern DLSYM_PROTOTYPE(crypt_get_volume_key_size);
extern DLSYM_PROTOTYPE(crypt_header_restore);
extern DLSYM_PROTOTYPE(crypt_init);
extern DLSYM_PROTOTYPE(crypt_init_by_name);
+extern DLSYM_PROTOTYPE(crypt_init_data_device);
extern DLSYM_PROTOTYPE(crypt_keyslot_add_by_volume_key);
extern DLSYM_PROTOTYPE(crypt_keyslot_destroy);
extern DLSYM_PROTOTYPE(crypt_keyslot_max);
+extern DLSYM_PROTOTYPE(crypt_keyslot_status);
extern DLSYM_PROTOTYPE(crypt_load);
extern DLSYM_PROTOTYPE(crypt_metadata_locking);
extern DLSYM_PROTOTYPE(crypt_persistent_flags_get);
@@ -39,10 +43,15 @@ extern DLSYM_PROTOTYPE(crypt_resume_by_volume_key);
extern DLSYM_PROTOTYPE(crypt_set_data_device);
extern DLSYM_PROTOTYPE(crypt_set_data_offset);
extern DLSYM_PROTOTYPE(crypt_set_debug_level);
+#if HAVE_CRYPT_SET_KEYRING_TO_LINK
+extern DLSYM_PROTOTYPE(crypt_set_keyring_to_link);
+#endif
extern DLSYM_PROTOTYPE(crypt_set_log_callback);
extern DLSYM_PROTOTYPE(crypt_set_metadata_size);
extern DLSYM_PROTOTYPE(crypt_set_pbkdf_type);
+extern DLSYM_PROTOTYPE(crypt_status);
extern DLSYM_PROTOTYPE(crypt_suspend);
+extern DLSYM_PROTOTYPE(crypt_token_external_path);
extern DLSYM_PROTOTYPE(crypt_token_json_get);
extern DLSYM_PROTOTYPE(crypt_token_json_set);
extern DLSYM_PROTOTYPE(crypt_token_max);
@@ -55,10 +64,9 @@ extern DLSYM_PROTOTYPE(crypt_volume_key_keyring);
extern DLSYM_PROTOTYPE(crypt_wipe);
extern DLSYM_PROTOTYPE(crypt_get_integrity_info);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct crypt_device *, crypt_free, NULL);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct crypt_device *, sym_crypt_free, NULL);
-
-/* Be careful, this works with dlopen_cryptsetup(), that is, it calls sym_crypt_free() instead of crypt_free(). */
+/* Be careful, these work with dlopen_cryptsetup(), that is, they call sym_crypt_free() instead of
+ * crypt_free() and hence depend on dlopen_cryptsetup() having been called. */
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct crypt_device *, sym_crypt_free, crypt_freep, NULL);
#define crypt_free_and_replace(a, b) \
free_and_replace_full(a, b, sym_crypt_free)
@@ -73,7 +81,7 @@ int cryptsetup_get_volume_key_id(struct crypt_device *cd, const char *volume_nam
size_t volume_key_size, char **ret);
#endif
-int dlopen_cryptsetup(void);
+int dlopen_cryptsetup(int log_level);
int cryptsetup_get_keyslot_from_token(sd_json_variant *v);
diff --git a/src/shared/curl-util.c b/src/shared/curl-util.c
index 59f9f16ae3..9254b83dd7 100644
--- a/src/shared/curl-util.c
+++ b/src/shared/curl-util.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "curl-util.h"
+#include "log.h"
#if HAVE_LIBCURL
@@ -11,7 +12,6 @@
#include "dlfcn-util.h"
#include "fd-util.h"
#include "hashmap.h"
-#include "log.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -40,39 +40,6 @@ DLSYM_PROTOTYPE(curl_multi_socket_action) = NULL;
DLSYM_PROTOTYPE(curl_slist_append) = NULL;
DLSYM_PROTOTYPE(curl_slist_free_all) = NULL;
-int dlopen_curl(void) {
- SD_ELF_NOTE_DLOPEN(
- "curl",
- "Support for downloading and uploading files over HTTP",
- SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
- "libcurl.so.4");
-
- return dlopen_many_sym_or_warn(
- &curl_dl,
- "libcurl.so.4",
- LOG_DEBUG,
- DLSYM_ARG(curl_easy_cleanup),
- DLSYM_ARG(curl_easy_getinfo),
- DLSYM_ARG(curl_easy_init),
- DLSYM_ARG(curl_easy_perform),
- DLSYM_ARG(curl_easy_setopt),
- DLSYM_ARG(curl_easy_strerror),
-#if LIBCURL_VERSION_NUM >= 0x075300
- DLSYM_ARG(curl_easy_header),
-#endif
- DLSYM_ARG(curl_getdate),
- DLSYM_ARG(curl_multi_add_handle),
- DLSYM_ARG(curl_multi_assign),
- DLSYM_ARG(curl_multi_cleanup),
- DLSYM_ARG(curl_multi_info_read),
- DLSYM_ARG(curl_multi_init),
- DLSYM_ARG(curl_multi_remove_handle),
- DLSYM_ARG(curl_multi_setopt),
- DLSYM_ARG(curl_multi_socket_action),
- DLSYM_ARG(curl_slist_append),
- DLSYM_ARG(curl_slist_free_all));
-}
-
static void curl_glue_check_finished(CurlGlue *g) {
int r;
@@ -271,7 +238,7 @@ int curl_glue_new(CurlGlue **glue, sd_event *event) {
assert(glue);
- r = dlopen_curl();
+ r = dlopen_curl(LOG_DEBUG);
if (r < 0)
return r;
@@ -327,7 +294,7 @@ int curl_glue_make(CURL **ret, const char *url, void *userdata) {
assert(ret);
assert(url);
- r = dlopen_curl();
+ r = dlopen_curl(LOG_DEBUG);
if (r < 0)
return r;
@@ -496,3 +463,41 @@ int curl_append_to_header(struct curl_slist **list, char **headers) {
}
#endif
+
+int dlopen_curl(int log_level) {
+#if HAVE_LIBCURL
+ SD_ELF_NOTE_DLOPEN(
+ "curl",
+ "Support for downloading and uploading files over HTTP",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
+ "libcurl.so.4");
+
+ return dlopen_many_sym_or_warn(
+ &curl_dl,
+ "libcurl.so.4",
+ log_level,
+ DLSYM_ARG(curl_easy_cleanup),
+ DLSYM_ARG(curl_easy_getinfo),
+ DLSYM_ARG(curl_easy_init),
+ DLSYM_ARG(curl_easy_perform),
+ DLSYM_ARG(curl_easy_setopt),
+ DLSYM_ARG(curl_easy_strerror),
+#if LIBCURL_VERSION_NUM >= 0x075300
+ DLSYM_ARG(curl_easy_header),
+#endif
+ DLSYM_ARG(curl_getdate),
+ DLSYM_ARG(curl_multi_add_handle),
+ DLSYM_ARG(curl_multi_assign),
+ DLSYM_ARG(curl_multi_cleanup),
+ DLSYM_ARG(curl_multi_info_read),
+ DLSYM_ARG(curl_multi_init),
+ DLSYM_ARG(curl_multi_remove_handle),
+ DLSYM_ARG(curl_multi_setopt),
+ DLSYM_ARG(curl_multi_socket_action),
+ DLSYM_ARG(curl_slist_append),
+ DLSYM_ARG(curl_slist_free_all));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libcurl support is not compiled in.");
+#endif
+}
diff --git a/src/shared/curl-util.h b/src/shared/curl-util.h
index 4ca3faf602..112649f371 100644
--- a/src/shared/curl-util.h
+++ b/src/shared/curl-util.h
@@ -29,8 +29,6 @@ extern DLSYM_PROTOTYPE(curl_multi_socket_action);
extern DLSYM_PROTOTYPE(curl_slist_append);
extern DLSYM_PROTOTYPE(curl_slist_free_all);
-int dlopen_curl(void);
-
#define easy_setopt(curl, log_level, opt, value) ({ \
CURLcode code = sym_curl_easy_setopt(ASSERT_PTR(curl), opt, value); \
if (code) \
@@ -71,10 +69,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(CURL*, sym_curl_easy_cleanup, curl_easy_
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(CURLM*, sym_curl_multi_cleanup, curl_multi_cleanupp, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct curl_slist*, sym_curl_slist_free_all, curl_slist_free_allp, NULL);
-#else
-
-static inline int dlopen_curl(void) {
- return -EOPNOTSUPP;
-}
-
#endif
+
+int dlopen_curl(int log_level);
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index e33e78d310..7252278768 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -239,7 +239,7 @@ int probe_filesystem_full(
assert(fd >= 0 || path);
assert(ret_fstype);
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return r;
@@ -1076,7 +1076,7 @@ static int dissect_image(
}
}
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return r;
@@ -1422,7 +1422,7 @@ static int dissect_image(
/* ret_root_hash_sig= */ NULL);
if (r < 0)
return r;
- if (iovec_memcmp(&verity->root_hash, &root_hash) != 0) {
+ if (!iovec_equal(&verity->root_hash, &root_hash)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *found = NULL, *expected = NULL;
@@ -2925,7 +2925,7 @@ static int decrypt_partition(
DecryptedImage *d) {
_cleanup_free_ char *node = NULL, *name = NULL;
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_close_ int fd = -EBADF;
int r;
@@ -2945,7 +2945,7 @@ static int decrypt_partition(
if (!FLAGS_SET(policy_flags, PARTITION_POLICY_ENCRYPTED))
return log_debug_errno(SYNTHETIC_ERRNO(ERFKILL), "Attempted to unlock partition via LUKS, but it's prohibited.");
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -2995,7 +2995,7 @@ static int verity_can_reuse(
struct crypt_device **ret_cd) {
/* If the same volume was already open, check that the root hashes match, and reuse it if they do */
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
struct crypt_params_verity crypt_params = {};
int r;
@@ -3023,7 +3023,7 @@ static int verity_can_reuse(
r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing.iov_base, &root_hash_existing.iov_len, NULL, 0);
if (r < 0)
return log_debug_errno(r, "Error opening verity device, crypt_volume_key_get failed: %m");
- if (iovec_memcmp(&verity->root_hash, &root_hash_existing) != 0)
+ if (!iovec_equal(&verity->root_hash, &root_hash_existing))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but root hashes are different.");
/* Ensure that, if signatures are supported, we only reuse the device if the previous mount used the
@@ -3072,7 +3072,7 @@ static int validate_signature_userspace(const VeritySettings *verity, const char
return 0;
}
if (!b) {
- log_debug("Userspace dm-verity signature authentication disabled via systemd.allow_userspace_verity= kernel command line variable.");
+ log_debug("Userspace dm-verity signature authentication disabled via systemd.allow_userspace_verity= kernel command line option.");
return 0;
}
@@ -3283,7 +3283,7 @@ static int verity_partition(
PartitionPolicyFlags policy_flags,
DecryptedImage *d) {
- _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_free_ char *node = NULL, *name = NULL;
_cleanup_close_ int mount_node_fd = -EBADF;
int r;
@@ -3313,7 +3313,7 @@ static int verity_partition(
return 0;
}
- r = dlopen_cryptsetup();
+ r = dlopen_cryptsetup(LOG_DEBUG);
if (r < 0)
return r;
@@ -3353,7 +3353,7 @@ static int verity_partition(
* retry a few times before giving up. */
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
_cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
- _cleanup_(sym_crypt_freep) struct crypt_device *existing_cd = NULL;
+ _cleanup_(crypt_freep) struct crypt_device *existing_cd = NULL;
_cleanup_close_ int fd = -EBADF;
/* First, check if the device already exists. */
@@ -3728,7 +3728,7 @@ static char *build_auxiliary_path(const char *image, const char *suffix) {
e = endswith(image, ".raw");
if (!e)
- return strjoin(e, suffix);
+ return strjoin(image, suffix);
n = new(char, e - image + strlen(suffix) + 1);
if (!n)
@@ -4048,7 +4048,7 @@ int dissected_image_load_verity_sig_partition(
/* Check if specified root hash matches if it is specified */
if (iovec_is_set(&verity->root_hash) &&
- iovec_memcmp(&verity->root_hash, &root_hash) != 0) {
+ !iovec_equal(&verity->root_hash, &root_hash)) {
_cleanup_free_ char *a = NULL, *b = NULL;
a = hexmem(root_hash.iov_base, root_hash.iov_len);
@@ -4176,7 +4176,7 @@ int dissected_image_acquire_metadata(
assert(m);
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 727e1d0625..c90da5fc46 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -1267,7 +1267,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
#if HAVE_LIBIDN2
int r;
- r = dlopen_idn();
+ r = dlopen_idn(LOG_DEBUG);
if (r == -EOPNOTSUPP) {
*ret = NULL;
return 0;
diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c
index be9e673a51..97188ca414 100644
--- a/src/shared/elf-util.c
+++ b/src/shared/elf-util.c
@@ -91,7 +91,7 @@ static DLSYM_PROTOTYPE(gelf_getnote) = NULL;
#endif
-int dlopen_dw(void) {
+int dlopen_dw(int log_level) {
#if HAVE_ELFUTILS
int r;
@@ -102,7 +102,7 @@ int dlopen_dw(void) {
"libdw.so.1");
r = dlopen_many_sym_or_warn(
- &dw_dl, "libdw.so.1", LOG_DEBUG,
+ &dw_dl, "libdw.so.1", log_level,
DLSYM_ARG(dwarf_getscopes),
DLSYM_ARG(dwarf_getscopes_die),
DLSYM_ARG(dwarf_tag),
@@ -141,11 +141,12 @@ int dlopen_dw(void) {
return 1;
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libdw support is not compiled in.");
#endif
}
-int dlopen_elf(void) {
+int dlopen_elf(int log_level) {
#if HAVE_ELFUTILS
int r;
@@ -156,7 +157,7 @@ int dlopen_elf(void) {
"libelf.so.1");
r = dlopen_many_sym_or_warn(
- &elf_dl, "libelf.so.1", LOG_DEBUG,
+ &elf_dl, "libelf.so.1", log_level,
DLSYM_ARG(elf_begin),
DLSYM_ARG(elf_end),
DLSYM_ARG(elf_getphdrnum),
@@ -173,7 +174,8 @@ int dlopen_elf(void) {
return 1;
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libelf support is not compiled in.");
#endif
}
@@ -824,11 +826,11 @@ int parse_elf_object(
assert(fd >= 0);
- r = dlopen_dw();
+ r = dlopen_dw(LOG_DEBUG);
if (r < 0)
return r;
- r = dlopen_elf();
+ r = dlopen_elf(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/elf-util.h b/src/shared/elf-util.h
index b5c3db80ee..e9d9e959da 100644
--- a/src/shared/elf-util.h
+++ b/src/shared/elf-util.h
@@ -3,8 +3,8 @@
#include "shared-forward.h"
-int dlopen_dw(void);
-int dlopen_elf(void);
+int dlopen_dw(int log_level);
+int dlopen_elf(int log_level);
/* Parse an ELF object in a forked process, so that errors while iterating over
* untrusted and potentially malicious data do not propagate to the main caller's process.
diff --git a/src/shared/fdisk-util.c b/src/shared/fdisk-util.c
index 2a0b7d765b..5eaa91160a 100644
--- a/src/shared/fdisk-util.c
+++ b/src/shared/fdisk-util.c
@@ -1,17 +1,164 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "fdisk-util.h"
+#include "log.h"
+
+#if HAVE_LIBFDISK
+
+#include "sd-dlopen.h"
+
#include "alloc-util.h"
#include "bitfield.h"
#include "dissect-image.h"
+#include "dlfcn-util.h"
#include "extract-word.h"
#include "fd-util.h"
-#include "fdisk-util.h"
-#include "log.h"
#include "parse-util.h"
#include "string-util.h"
-#if HAVE_LIBFDISK
+static void *fdisk_dl = NULL;
+DLSYM_PROTOTYPE(fdisk_add_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_apply_table) = NULL;
+DLSYM_PROTOTYPE(fdisk_ask_get_type) = NULL;
+DLSYM_PROTOTYPE(fdisk_ask_string_set_result) = NULL;
+DLSYM_PROTOTYPE(fdisk_assign_device) = NULL;
+DLSYM_PROTOTYPE(fdisk_create_disklabel) = NULL;
+DLSYM_PROTOTYPE(fdisk_delete_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_devfd) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_disklabel_id) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_first_lba) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_grain_size) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_last_lba) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_npartitions) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_nsectors) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_partitions) = NULL;
+DLSYM_PROTOTYPE(fdisk_get_sector_size) = NULL;
+DLSYM_PROTOTYPE(fdisk_has_label) = NULL;
+DLSYM_PROTOTYPE(fdisk_is_labeltype) = NULL;
+DLSYM_PROTOTYPE(fdisk_new_context) = NULL;
+DLSYM_PROTOTYPE(fdisk_new_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_new_parttype) = NULL;
+DLSYM_PROTOTYPE(fdisk_partname) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_attrs) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_end) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_name) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_partno) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_size) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_start) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_type) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_get_uuid) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_has_end) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_has_partno) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_has_size) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_has_start) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_is_used) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_partno_follow_default) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_attrs) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_name) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_partno) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_size) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_start) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_type) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_set_uuid) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_size_explicit) = NULL;
+DLSYM_PROTOTYPE(fdisk_partition_to_string) = NULL;
+DLSYM_PROTOTYPE(fdisk_parttype_get_string) = NULL;
+DLSYM_PROTOTYPE(fdisk_parttype_set_typestr) = NULL;
+DLSYM_PROTOTYPE(fdisk_ref_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_save_user_sector_size) = NULL;
+DLSYM_PROTOTYPE(fdisk_set_ask) = NULL;
+DLSYM_PROTOTYPE(fdisk_set_disklabel_id) = NULL;
+DLSYM_PROTOTYPE(fdisk_set_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_table_get_nents) = NULL;
+DLSYM_PROTOTYPE(fdisk_table_get_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_unref_context) = NULL;
+DLSYM_PROTOTYPE(fdisk_unref_partition) = NULL;
+DLSYM_PROTOTYPE(fdisk_unref_parttype) = NULL;
+DLSYM_PROTOTYPE(fdisk_unref_table) = NULL;
+DLSYM_PROTOTYPE(fdisk_write_disklabel) = NULL;
+#endif
+
+int dlopen_fdisk(int log_level) {
+#if HAVE_LIBFDISK
+ SD_ELF_NOTE_DLOPEN(
+ "fdisk",
+ "Support for reading and writing partition tables",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
+ "libfdisk.so.1");
+
+ return dlopen_many_sym_or_warn(
+ &fdisk_dl,
+ "libfdisk.so.1",
+ log_level,
+ DLSYM_ARG(fdisk_add_partition),
+ DLSYM_ARG(fdisk_apply_table),
+ DLSYM_ARG(fdisk_ask_get_type),
+ DLSYM_ARG(fdisk_ask_string_set_result),
+ DLSYM_ARG(fdisk_assign_device),
+ DLSYM_ARG(fdisk_create_disklabel),
+ DLSYM_ARG(fdisk_delete_partition),
+ DLSYM_ARG(fdisk_get_devfd),
+ DLSYM_ARG(fdisk_get_disklabel_id),
+ DLSYM_ARG(fdisk_get_first_lba),
+ DLSYM_ARG(fdisk_get_grain_size),
+ DLSYM_ARG(fdisk_get_last_lba),
+ DLSYM_ARG(fdisk_get_npartitions),
+ DLSYM_ARG(fdisk_get_nsectors),
+ DLSYM_ARG(fdisk_get_partition),
+ DLSYM_ARG(fdisk_get_partitions),
+ DLSYM_ARG(fdisk_get_sector_size),
+ DLSYM_ARG(fdisk_has_label),
+ DLSYM_ARG(fdisk_is_labeltype),
+ DLSYM_ARG(fdisk_new_context),
+ DLSYM_ARG(fdisk_new_partition),
+ DLSYM_ARG(fdisk_new_parttype),
+ DLSYM_ARG(fdisk_partname),
+ DLSYM_ARG(fdisk_partition_get_attrs),
+ DLSYM_ARG(fdisk_partition_get_end),
+ DLSYM_ARG(fdisk_partition_get_name),
+ DLSYM_ARG(fdisk_partition_get_partno),
+ DLSYM_ARG(fdisk_partition_get_size),
+ DLSYM_ARG(fdisk_partition_get_start),
+ DLSYM_ARG(fdisk_partition_get_type),
+ DLSYM_ARG(fdisk_partition_get_uuid),
+ DLSYM_ARG(fdisk_partition_has_end),
+ DLSYM_ARG(fdisk_partition_has_partno),
+ DLSYM_ARG(fdisk_partition_has_size),
+ DLSYM_ARG(fdisk_partition_has_start),
+ DLSYM_ARG(fdisk_partition_is_used),
+ DLSYM_ARG(fdisk_partition_partno_follow_default),
+ DLSYM_ARG(fdisk_partition_set_attrs),
+ DLSYM_ARG(fdisk_partition_set_name),
+ DLSYM_ARG(fdisk_partition_set_partno),
+ DLSYM_ARG(fdisk_partition_set_size),
+ DLSYM_ARG(fdisk_partition_set_start),
+ DLSYM_ARG(fdisk_partition_set_type),
+ DLSYM_ARG(fdisk_partition_set_uuid),
+ DLSYM_ARG(fdisk_partition_size_explicit),
+ DLSYM_ARG(fdisk_partition_to_string),
+ DLSYM_ARG(fdisk_parttype_get_string),
+ DLSYM_ARG(fdisk_parttype_set_typestr),
+ DLSYM_ARG(fdisk_ref_partition),
+ DLSYM_ARG(fdisk_save_user_sector_size),
+ DLSYM_ARG(fdisk_set_ask),
+ DLSYM_ARG(fdisk_set_disklabel_id),
+ DLSYM_ARG(fdisk_set_partition),
+ DLSYM_ARG(fdisk_table_get_nents),
+ DLSYM_ARG(fdisk_table_get_partition),
+ DLSYM_ARG(fdisk_unref_context),
+ DLSYM_ARG(fdisk_unref_partition),
+ DLSYM_ARG(fdisk_unref_parttype),
+ DLSYM_ARG(fdisk_unref_table),
+ DLSYM_ARG(fdisk_write_disklabel));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libfdisk support is not compiled in.");
+#endif
+}
+
+#if HAVE_LIBFDISK
int fdisk_new_context_at(
int dir_fd,
const char *path,
@@ -34,7 +181,7 @@ int fdisk_new_context_at(
dir_fd = fd;
}
- c = fdisk_new_context();
+ c = sym_fdisk_new_context();
if (!c)
return -ENOMEM;
@@ -45,12 +192,12 @@ int fdisk_new_context_at(
}
if (sector_size != 0) {
- r = fdisk_save_user_sector_size(c, /* phy= */ 0, sector_size);
+ r = sym_fdisk_save_user_sector_size(c, /* phy= */ 0, sector_size);
if (r < 0)
return r;
}
- r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(dir_fd), read_only);
+ r = sym_fdisk_assign_device(c, FORMAT_PROC_FD_PATH(dir_fd), read_only);
if (r < 0)
return r;
@@ -64,7 +211,7 @@ int fdisk_partition_get_uuid_as_id128(struct fdisk_partition *p, sd_id128_t *ret
assert(p);
assert(ret);
- ids = fdisk_partition_get_uuid(p);
+ ids = sym_fdisk_partition_get_uuid(p);
if (!ids)
return -ENXIO;
@@ -78,11 +225,11 @@ int fdisk_partition_get_type_as_id128(struct fdisk_partition *p, sd_id128_t *ret
assert(p);
assert(ret);
- pt = fdisk_partition_get_type(p);
+ pt = sym_fdisk_partition_get_type(p);
if (!pt)
return -ENXIO;
- pts = fdisk_parttype_get_string(pt);
+ pts = sym_fdisk_parttype_get_string(pt);
if (!pts)
return -ENXIO;
@@ -99,7 +246,7 @@ int fdisk_partition_get_attrs_as_uint64(struct fdisk_partition *pa, uint64_t *re
/* Retrieve current flags as uint64_t mask */
- a = fdisk_partition_get_attrs(pa);
+ a = sym_fdisk_partition_get_attrs(pa);
if (!a) {
*ret = 0;
return 0;
@@ -161,7 +308,7 @@ int fdisk_partition_set_attrs_as_uint64(struct fdisk_partition *pa, uint64_t fla
return r;
}
- return fdisk_partition_set_attrs(pa, strempty(attrs));
+ return sym_fdisk_partition_set_attrs(pa, strempty(attrs));
}
#endif
diff --git a/src/shared/fdisk-util.h b/src/shared/fdisk-util.h
index 98a2ed9948..bdac11c507 100644
--- a/src/shared/fdisk-util.h
+++ b/src/shared/fdisk-util.h
@@ -1,16 +1,79 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include "shared-forward.h"
+
#if HAVE_LIBFDISK
#include /* IWYU pragma: export */
-#include "shared-forward.h"
+#include "dlfcn-util.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
+extern DLSYM_PROTOTYPE(fdisk_add_partition);
+extern DLSYM_PROTOTYPE(fdisk_apply_table);
+extern DLSYM_PROTOTYPE(fdisk_ask_get_type);
+extern DLSYM_PROTOTYPE(fdisk_ask_string_set_result);
+extern DLSYM_PROTOTYPE(fdisk_assign_device);
+extern DLSYM_PROTOTYPE(fdisk_create_disklabel);
+extern DLSYM_PROTOTYPE(fdisk_delete_partition);
+extern DLSYM_PROTOTYPE(fdisk_get_devfd);
+extern DLSYM_PROTOTYPE(fdisk_get_disklabel_id);
+extern DLSYM_PROTOTYPE(fdisk_get_first_lba);
+extern DLSYM_PROTOTYPE(fdisk_get_grain_size);
+extern DLSYM_PROTOTYPE(fdisk_get_last_lba);
+extern DLSYM_PROTOTYPE(fdisk_get_npartitions);
+extern DLSYM_PROTOTYPE(fdisk_get_nsectors);
+extern DLSYM_PROTOTYPE(fdisk_get_partition);
+extern DLSYM_PROTOTYPE(fdisk_get_partitions);
+extern DLSYM_PROTOTYPE(fdisk_get_sector_size);
+extern DLSYM_PROTOTYPE(fdisk_has_label);
+extern DLSYM_PROTOTYPE(fdisk_is_labeltype);
+extern DLSYM_PROTOTYPE(fdisk_new_context);
+extern DLSYM_PROTOTYPE(fdisk_new_partition);
+extern DLSYM_PROTOTYPE(fdisk_new_parttype);
+extern DLSYM_PROTOTYPE(fdisk_partname);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_attrs);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_end);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_name);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_partno);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_size);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_start);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_type);
+extern DLSYM_PROTOTYPE(fdisk_partition_get_uuid);
+extern DLSYM_PROTOTYPE(fdisk_partition_has_end);
+extern DLSYM_PROTOTYPE(fdisk_partition_has_partno);
+extern DLSYM_PROTOTYPE(fdisk_partition_has_size);
+extern DLSYM_PROTOTYPE(fdisk_partition_has_start);
+extern DLSYM_PROTOTYPE(fdisk_partition_is_used);
+extern DLSYM_PROTOTYPE(fdisk_partition_partno_follow_default);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_attrs);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_name);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_partno);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_size);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_start);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_type);
+extern DLSYM_PROTOTYPE(fdisk_partition_set_uuid);
+extern DLSYM_PROTOTYPE(fdisk_partition_size_explicit);
+extern DLSYM_PROTOTYPE(fdisk_partition_to_string);
+extern DLSYM_PROTOTYPE(fdisk_parttype_get_string);
+extern DLSYM_PROTOTYPE(fdisk_parttype_set_typestr);
+extern DLSYM_PROTOTYPE(fdisk_ref_partition);
+extern DLSYM_PROTOTYPE(fdisk_save_user_sector_size);
+extern DLSYM_PROTOTYPE(fdisk_set_ask);
+extern DLSYM_PROTOTYPE(fdisk_set_disklabel_id);
+extern DLSYM_PROTOTYPE(fdisk_set_partition);
+extern DLSYM_PROTOTYPE(fdisk_table_get_nents);
+extern DLSYM_PROTOTYPE(fdisk_table_get_partition);
+extern DLSYM_PROTOTYPE(fdisk_unref_context);
+extern DLSYM_PROTOTYPE(fdisk_unref_partition);
+extern DLSYM_PROTOTYPE(fdisk_unref_parttype);
+extern DLSYM_PROTOTYPE(fdisk_unref_table);
+extern DLSYM_PROTOTYPE(fdisk_write_disklabel);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct fdisk_context*, sym_fdisk_unref_context, fdisk_unref_contextp, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct fdisk_partition*, sym_fdisk_unref_partition, fdisk_unref_partitionp, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct fdisk_parttype*, sym_fdisk_unref_parttype, fdisk_unref_parttypep, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct fdisk_table*, sym_fdisk_unref_table, fdisk_unref_tablep, NULL);
int fdisk_new_context_at(int dir_fd, const char *path, bool read_only, uint32_t sector_size, struct fdisk_context **ret);
@@ -21,3 +84,5 @@ int fdisk_partition_get_attrs_as_uint64(struct fdisk_partition *pa, uint64_t *re
int fdisk_partition_set_attrs_as_uint64(struct fdisk_partition *pa, uint64_t flags);
#endif
+
+int dlopen_fdisk(int log_level);
diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c
index 3497ca6da3..f04e3a14dc 100644
--- a/src/shared/find-esp.c
+++ b/src/shared/find-esp.c
@@ -75,9 +75,9 @@ static int verify_esp_blkid(
const char *v;
int r;
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "No libblkid support: %m");
+ return r;
r = devname_from_devnum(S_IFBLK, devid, &node);
if (r < 0)
@@ -572,9 +572,9 @@ static int verify_xbootldr_blkid(
const char *type, *v;
int r;
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "No libblkid support: %m");
+ return r;
r = devname_from_devnum(S_IFBLK, devid, &node);
if (r < 0)
diff --git a/src/shared/fork-notify.c b/src/shared/fork-notify.c
index 307197ac19..066ee29115 100644
--- a/src/shared/fork-notify.c
+++ b/src/shared/fork-notify.c
@@ -3,14 +3,19 @@
#include
#include
+#include "alloc-util.h"
#include "build-path.h"
+#include "chase.h"
+#include "chattr-util.h"
#include "escape.h"
#include "event-util.h"
#include "exit-status.h"
+#include "fd-util.h"
#include "fork-notify.h"
#include "log.h"
#include "notify-recv.h"
#include "parse-util.h"
+#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "runtime-scope.h"
@@ -90,7 +95,6 @@ static int on_child_notify(sd_event_source *s, int fd, uint32_t revents, void *u
int fork_notify(char * const *argv, PidRef *ret_pidref) {
int r;
- assert(!strv_isempty(argv));
assert(ret_pidref);
if (!is_main_thread())
@@ -119,7 +123,7 @@ int fork_notify(char * const *argv, PidRef *ret_pidref) {
if (r < 0)
return r;
- if (DEBUG_LOGGING) {
+ if (DEBUG_LOGGING && argv) {
_cleanup_free_ char *l = quote_command_line(argv, SHELL_ESCAPE_EMPTY);
log_debug("Invoking '%s' as child.", strnull(l));
}
@@ -141,6 +145,11 @@ int fork_notify(char * const *argv, PidRef *ret_pidref) {
_exit(EXIT_MEMORY);
}
+ if (!argv) {
+ *ret_pidref = TAKE_PIDREF(child);
+ return 0; /* Let the caller run custom code in the child */
+ }
+
r = invoke_callout_binary(argv[0], argv);
log_debug_errno(r, "Failed to invoke %s: %m", argv[0]);
_exit(EXIT_EXEC);
@@ -164,7 +173,7 @@ int fork_notify(char * const *argv, PidRef *ret_pidref) {
*ret_pidref = TAKE_PIDREF(child);
- return 0;
+ return 1; /* In the parent */
}
static void fork_notify_terminate_internal(PidRef *pidref) {
@@ -234,3 +243,92 @@ int journal_fork(RuntimeScope scope, char * const* units, OutputMode output, Pid
return fork_notify(argv, ret_pidref);
}
+
+int fork_journal_remote(
+ const char *listen_address,
+ const char *output,
+ uint64_t max_use,
+ uint64_t keep_free,
+ uint64_t max_file_size,
+ uint64_t max_files,
+ PidRef *ret_pidref) {
+
+ int r;
+
+ assert(listen_address);
+ assert(output);
+ assert(ret_pidref);
+
+ ChaseFlags chase_flags = CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY;
+ if (endswith(output, ".journal"))
+ chase_flags |= CHASE_PARENT;
+
+ _cleanup_close_ int fd = -EBADF;
+ r = chase(output, /* root= */ NULL, chase_flags, /* ret_path= */ NULL, &fd);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create journal directory for '%s': %m", output);
+
+ r = chattr_fd(fd, FS_NOCOW_FL, FS_NOCOW_FL);
+ if (r < 0)
+ log_debug_errno(r, "Failed to set NOCOW flag on journal directory for '%s', ignoring: %m", output);
+
+ _cleanup_free_ char *sd_socket_activate = NULL;
+ r = find_executable("systemd-socket-activate", &sd_socket_activate);
+ if (r < 0)
+ return log_error_errno(r, "Failed to find systemd-socket-activate binary: %m");
+
+ _cleanup_free_ char *sd_journal_remote = NULL;
+ r = find_executable_full(
+ "systemd-journal-remote",
+ /* root= */ NULL,
+ STRV_MAKE(LIBEXECDIR),
+ /* use_path_envvar= */ true,
+ &sd_journal_remote,
+ /* ret_fd= */ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to find systemd-journal-remote binary: %m");
+
+ _cleanup_strv_free_ char **argv = strv_new(
+ sd_socket_activate,
+ "--listen", listen_address,
+ sd_journal_remote,
+ "--output", output,
+ "--split-mode", endswith(output, ".journal") ? "none" : "host");
+ if (!argv)
+ return log_oom();
+
+ if (max_use != UINT64_MAX &&
+ strv_extendf(&argv, "--max-use=%" PRIu64, max_use) < 0)
+ return log_oom();
+
+ if (keep_free != UINT64_MAX &&
+ strv_extendf(&argv, "--keep-free=%" PRIu64, keep_free) < 0)
+ return log_oom();
+
+ if (max_file_size != UINT64_MAX &&
+ strv_extendf(&argv, "--max-file-size=%" PRIu64, max_file_size) < 0)
+ return log_oom();
+
+ if (max_files != UINT64_MAX &&
+ strv_extendf(&argv, "--max-files=%" PRIu64, max_files) < 0)
+ return log_oom();
+
+ r = fork_notify(/* argv= */ NULL, ret_pidref);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ /* In the child */
+ if (setenv("SYSTEMD_JOURNAL_REMOTE_CONFIG_FILE",
+ "/dev/null",
+ /* overwrite= */ true) < 0) {
+ log_debug_errno(errno, "Failed to set $SYSTEMD_JOURNAL_REMOTE_CONFIG_FILE: %m");
+ _exit(EXIT_MEMORY);
+ }
+
+ r = invoke_callout_binary(argv[0], argv);
+ log_debug_errno(r, "Failed to invoke %s: %m", argv[0]);
+ _exit(EXIT_EXEC);
+ }
+
+ return 0;
+}
diff --git a/src/shared/fork-notify.h b/src/shared/fork-notify.h
index 2dbfe368a4..cc241beff9 100644
--- a/src/shared/fork-notify.h
+++ b/src/shared/fork-notify.h
@@ -11,3 +11,12 @@ void fork_notify_terminate(PidRef *pidref);
void fork_notify_terminate_many(sd_event_source **array, size_t n);
int journal_fork(RuntimeScope scope, char * const *units, OutputMode output, PidRef *ret_pidref);
+
+int fork_journal_remote(
+ const char *listen_address,
+ const char *output,
+ uint64_t max_use,
+ uint64_t keep_free,
+ uint64_t max_file_size,
+ uint64_t max_files,
+ PidRef *ret_pidref);
diff --git a/src/shared/gnutls-util.c b/src/shared/gnutls-util.c
new file mode 100644
index 0000000000..1f17c4f5a1
--- /dev/null
+++ b/src/shared/gnutls-util.c
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-dlopen.h"
+
+#include "gnutls-util.h"
+#include "log.h" /* IWYU pragma: keep */
+
+#if HAVE_GNUTLS
+static void *gnutls_dl = NULL;
+
+DLSYM_PROTOTYPE(gnutls_certificate_get_peers) = NULL;
+DLSYM_PROTOTYPE(gnutls_certificate_type_get) = NULL;
+DLSYM_PROTOTYPE(gnutls_certificate_verification_status_print) = NULL;
+DLSYM_PROTOTYPE(gnutls_certificate_verify_peers2) = NULL;
+DLSYM_PROTOTYPE(gnutls_free) = NULL;
+DLSYM_PROTOTYPE(gnutls_global_set_log_function) = NULL;
+DLSYM_PROTOTYPE(gnutls_global_set_log_level) = NULL;
+DLSYM_PROTOTYPE(gnutls_x509_crt_deinit) = NULL;
+DLSYM_PROTOTYPE(gnutls_x509_crt_get_dn) = NULL;
+DLSYM_PROTOTYPE(gnutls_x509_crt_import) = NULL;
+DLSYM_PROTOTYPE(gnutls_x509_crt_init) = NULL;
+#endif
+
+int dlopen_gnutls(int log_level) {
+#if HAVE_GNUTLS
+ SD_ELF_NOTE_DLOPEN(
+ "gnutls",
+ "Support for TLS via GnuTLS",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
+ "libgnutls.so.30");
+
+ return dlopen_many_sym_or_warn(
+ &gnutls_dl,
+ "libgnutls.so.30",
+ log_level,
+ DLSYM_ARG(gnutls_certificate_get_peers),
+ DLSYM_ARG(gnutls_certificate_type_get),
+ DLSYM_ARG(gnutls_certificate_verification_status_print),
+ DLSYM_ARG(gnutls_certificate_verify_peers2),
+ DLSYM_ARG(gnutls_free),
+ DLSYM_ARG(gnutls_global_set_log_function),
+ DLSYM_ARG(gnutls_global_set_log_level),
+ DLSYM_ARG(gnutls_x509_crt_deinit),
+ DLSYM_ARG(gnutls_x509_crt_get_dn),
+ DLSYM_ARG(gnutls_x509_crt_import),
+ DLSYM_ARG(gnutls_x509_crt_init));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "gnutls support is not compiled in.");
+#endif
+}
diff --git a/src/shared/gnutls-util.h b/src/shared/gnutls-util.h
new file mode 100644
index 0000000000..a110b437c3
--- /dev/null
+++ b/src/shared/gnutls-util.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "shared-forward.h"
+
+int dlopen_gnutls(int log_level);
+
+#if HAVE_GNUTLS
+# include /* IWYU pragma: export */
+# include /* IWYU pragma: export */
+
+/* gnutls.h installs a function-like macro that wraps gnutls_free() and NULLs the passed pointer. We use
+ * dlsym to resolve the underlying function pointer variable, so undef the macro here to keep the variable
+ * name visible for DLSYM_PROTOTYPE/DLSYM_ARG. */
+# ifdef gnutls_free
+# undef gnutls_free
+# endif
+
+# include "dlfcn-util.h"
+
+extern DLSYM_PROTOTYPE(gnutls_certificate_get_peers);
+extern DLSYM_PROTOTYPE(gnutls_certificate_type_get);
+extern DLSYM_PROTOTYPE(gnutls_certificate_verification_status_print);
+extern DLSYM_PROTOTYPE(gnutls_certificate_verify_peers2);
+extern DLSYM_PROTOTYPE(gnutls_free);
+extern DLSYM_PROTOTYPE(gnutls_global_set_log_function);
+extern DLSYM_PROTOTYPE(gnutls_global_set_log_level);
+extern DLSYM_PROTOTYPE(gnutls_x509_crt_deinit);
+extern DLSYM_PROTOTYPE(gnutls_x509_crt_get_dn);
+extern DLSYM_PROTOTYPE(gnutls_x509_crt_import);
+extern DLSYM_PROTOTYPE(gnutls_x509_crt_init);
+#endif
diff --git a/src/shared/idn-util.c b/src/shared/idn-util.c
index a1b4a6c498..01512b95dd 100644
--- a/src/shared/idn-util.c
+++ b/src/shared/idn-util.c
@@ -1,17 +1,22 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include "sd-dlopen.h"
-
#include "idn-util.h"
#include "log.h" /* IWYU pragma: keep */
+#if HAVE_LIBIDN2
+
+#include "sd-dlopen.h"
+
static void* idn_dl = NULL;
DLSYM_PROTOTYPE(idn2_lookup_u8) = NULL;
const char *(*sym_idn2_strerror)(int rc) _const_ = NULL;
DLSYM_PROTOTYPE(idn2_to_unicode_8z8z) = NULL;
-int dlopen_idn(void) {
+#endif
+
+int dlopen_idn(int log_level) {
+#if HAVE_LIBIDN2
SD_ELF_NOTE_DLOPEN(
"idn",
"Support for internationalized domain names",
@@ -19,8 +24,12 @@ int dlopen_idn(void) {
"libidn2.so.0");
return dlopen_many_sym_or_warn(
- &idn_dl, "libidn2.so.0", LOG_DEBUG,
+ &idn_dl, "libidn2.so.0", log_level,
DLSYM_ARG(idn2_lookup_u8),
DLSYM_ARG(idn2_strerror),
DLSYM_ARG(idn2_to_unicode_8z8z));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libidn2 support is not compiled in.");
+#endif
}
diff --git a/src/shared/idn-util.h b/src/shared/idn-util.h
index c971be9aef..918f8c0a57 100644
--- a/src/shared/idn-util.h
+++ b/src/shared/idn-util.h
@@ -11,10 +11,6 @@
extern DLSYM_PROTOTYPE(idn2_lookup_u8);
extern const char *(*sym_idn2_strerror)(int rc) _const_;
extern DLSYM_PROTOTYPE(idn2_to_unicode_8z8z);
-
-int dlopen_idn(void);
-#else
-static inline int dlopen_idn(void) {
- return -EOPNOTSUPP;
-}
#endif
+
+int dlopen_idn(int log_level);
diff --git a/src/shared/kbd-util.c b/src/shared/kbd-util.c
index 84031df784..28ea2e8612 100644
--- a/src/shared/kbd-util.c
+++ b/src/shared/kbd-util.c
@@ -5,12 +5,10 @@
#include "errno-util.h"
#include "kbd-util.h"
#include "log.h"
-#include "path-util.h"
#include "recurse-dir.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
-#include "utf8.h"
#define KBD_KEYMAP_DIRS \
"/usr/share/keymaps/", \
@@ -129,21 +127,12 @@ int get_keymaps(char ***ret) {
}
bool keymap_is_valid(const char *name) {
- if (isempty(name))
+ if (!string_is_safe(name, STRING_FILENAME))
return false;
if (strlen(name) >= 128)
return false;
- if (!utf8_is_valid(name))
- return false;
-
- if (!filename_is_valid(name))
- return false;
-
- if (!string_is_safe(name))
- return false;
-
return true;
}
diff --git a/src/shared/libarchive-util.c b/src/shared/libarchive-util.c
index 02b6b36b3c..2ef0b37959 100644
--- a/src/shared/libarchive-util.c
+++ b/src/shared/libarchive-util.c
@@ -5,6 +5,7 @@
#include "sd-dlopen.h"
#include "libarchive-util.h"
+#include "log.h" /* IWYU pragma: keep */
#include "user-util.h" /* IWYU pragma: keep */
#if HAVE_LIBARCHIVE
@@ -79,8 +80,10 @@ DLSYM_PROTOTYPE(archive_write_open_FILE) = NULL;
DLSYM_PROTOTYPE(archive_write_open_fd) = NULL;
DLSYM_PROTOTYPE(archive_write_set_format_filter_by_ext) = NULL;
DLSYM_PROTOTYPE(archive_write_set_format_pax) = NULL;
+#endif
-int dlopen_libarchive(void) {
+int dlopen_libarchive(int log_level) {
+#if HAVE_LIBARCHIVE
SD_ELF_NOTE_DLOPEN(
"archive",
"Support for decompressing archive files",
@@ -90,7 +93,7 @@ int dlopen_libarchive(void) {
return dlopen_many_sym_or_warn(
&libarchive_dl,
"libarchive.so.13",
- LOG_DEBUG,
+ log_level,
DLSYM_ARG(archive_entry_acl_add_entry),
DLSYM_ARG(archive_entry_acl_next),
DLSYM_ARG(archive_entry_acl_reset),
@@ -152,8 +155,13 @@ int dlopen_libarchive(void) {
DLSYM_ARG(archive_write_open_fd),
DLSYM_ARG(archive_write_set_format_filter_by_ext),
DLSYM_ARG(archive_write_set_format_pax));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libarchive support is not compiled in.");
+#endif
}
+#if HAVE_LIBARCHIVE
/* libarchive uses its own file type macros. They happen to be defined the same way as the Linux ones, and
* we'd like to rely on it. Let's verify this first though. */
assert_cc(S_IFDIR == AE_IFDIR);
diff --git a/src/shared/libarchive-util.h b/src/shared/libarchive-util.h
index db1c31d223..f1f78aad5d 100644
--- a/src/shared/libarchive-util.h
+++ b/src/shared/libarchive-util.h
@@ -79,16 +79,13 @@ extern DLSYM_PROTOTYPE(archive_write_open_fd);
extern DLSYM_PROTOTYPE(archive_write_set_format_filter_by_ext);
extern DLSYM_PROTOTYPE(archive_write_set_format_pax);
-int dlopen_libarchive(void);
-
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct archive_entry*, sym_archive_entry_free, archive_entry_freep, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct archive*, sym_archive_write_free, archive_write_freep, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct archive*, sym_archive_read_free, archive_read_freep, NULL);
#else
-static inline int dlopen_libarchive(void) {
- return -EOPNOTSUPP;
-}
#endif
+
+int dlopen_libarchive(int log_level);
diff --git a/src/shared/libaudit-util.c b/src/shared/libaudit-util.c
index bf5791955b..478d3d33b6 100644
--- a/src/shared/libaudit-util.c
+++ b/src/shared/libaudit-util.c
@@ -23,7 +23,7 @@ DLSYM_PROTOTYPE(audit_log_user_comm_message) = NULL;
static DLSYM_PROTOTYPE(audit_open) = NULL;
#endif
-int dlopen_libaudit(void) {
+int dlopen_libaudit(int log_level) {
#if HAVE_AUDIT
SD_ELF_NOTE_DLOPEN(
"audit",
@@ -34,14 +34,15 @@ int dlopen_libaudit(void) {
return dlopen_many_sym_or_warn(
&libaudit_dl,
"libaudit.so.1",
- LOG_DEBUG,
+ log_level,
DLSYM_ARG(audit_close),
DLSYM_ARG(audit_log_acct_message),
DLSYM_ARG(audit_log_user_avc_message),
DLSYM_ARG(audit_log_user_comm_message),
DLSYM_ARG(audit_open));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libaudit support is not compiled in.");
#endif
}
@@ -93,7 +94,7 @@ bool use_audit(void) {
if (cached_use >= 0)
return cached_use;
- if (dlopen_libaudit() < 0)
+ if (dlopen_libaudit(LOG_DEBUG) < 0)
return (cached_use = false);
_cleanup_close_ int fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
@@ -141,7 +142,7 @@ int open_audit_fd_or_warn(void) {
#if HAVE_AUDIT
int r;
- r = dlopen_libaudit();
+ r = dlopen_libaudit(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/libaudit-util.h b/src/shared/libaudit-util.h
index 759b1c7574..8bb05a2fbd 100644
--- a/src/shared/libaudit-util.h
+++ b/src/shared/libaudit-util.h
@@ -3,7 +3,7 @@
#include "shared-forward.h"
-int dlopen_libaudit(void);
+int dlopen_libaudit(int log_level);
#if HAVE_AUDIT
# include /* IWYU pragma: export */
diff --git a/src/shared/libcrypt-util.c b/src/shared/libcrypt-util.c
index df3ba146f9..531684d64e 100644
--- a/src/shared/libcrypt-util.c
+++ b/src/shared/libcrypt-util.c
@@ -21,58 +21,6 @@ static DLSYM_PROTOTYPE(crypt_gensalt_ra) = NULL;
static DLSYM_PROTOTYPE(crypt_preferred_method) = NULL;
static DLSYM_PROTOTYPE(crypt_ra) = NULL;
-int dlopen_libcrypt(void) {
-#ifdef __GLIBC__
- static int cached = 0;
- int r;
-
- if (libcrypt_dl)
- return 0; /* Already loaded */
-
- if (cached < 0)
- return cached; /* Already tried, and failed. */
-
- /* Several distributions like Debian/Ubuntu and OpenSUSE provide libxcrypt as libcrypt.so.1
- * (libcrypt.so.1.1 on some architectures), while others like Fedora/CentOS and Arch provide it as
- * libcrypt.so.2. */
- SD_ELF_NOTE_DLOPEN(
- "crypt",
- "Support for hashing passwords",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libcrypt.so.2", "libcrypt.so.1", "libcrypt.so.1.1");
-
- _cleanup_(dlclosep) void *dl = NULL;
- const char *dle = NULL;
- FOREACH_STRING(soname, "libcrypt.so.2", "libcrypt.so.1", "libcrypt.so.1.1") {
- r = dlopen_safe(soname, &dl, &dle);
- if (r >= 0) {
- log_debug("Loaded '%s' via dlopen().", soname);
- break;
- }
- }
- if (r < 0) {
- log_debug_errno(r, "Failed to load libcrypt: %s", dle ?: STRERROR(r));
- return (cached = -EOPNOTSUPP); /* turn into recognizable error */
- }
-
- r = dlsym_many_or_warn(
- dl, LOG_DEBUG,
- DLSYM_ARG(crypt_gensalt_ra),
- DLSYM_ARG(crypt_preferred_method),
- DLSYM_ARG(crypt_ra));
- if (r < 0)
- return (cached = r);
-
- libcrypt_dl = TAKE_PTR(dl);
-#else
- libcrypt_dl = NULL;
- sym_crypt_gensalt_ra = missing_crypt_gensalt_ra;
- sym_crypt_preferred_method = missing_crypt_preferred_method;
- sym_crypt_ra = missing_crypt_ra;
-#endif
- return 0;
-}
-
int make_salt(char **ret) {
const char *e;
char *salt;
@@ -80,7 +28,7 @@ int make_salt(char **ret) {
assert(ret);
- r = dlopen_libcrypt();
+ r = dlopen_libcrypt(LOG_DEBUG);
if (r < 0)
return r;
@@ -127,7 +75,7 @@ int test_password_one(const char *hashed_password, const char *password) {
assert(hashed_password);
assert(password);
- r = dlopen_libcrypt();
+ r = dlopen_libcrypt(LOG_DEBUG);
if (r < 0)
return r;
@@ -175,3 +123,60 @@ bool looks_like_hashed_password(const char *s) {
return !STR_IN_SET(s, "x", "*");
}
+
+int dlopen_libcrypt(int log_level) {
+#if HAVE_LIBCRYPT
+#ifdef __GLIBC__
+ static int cached = 0;
+ int r;
+
+ if (libcrypt_dl)
+ return 0; /* Already loaded */
+
+ if (cached < 0)
+ return cached; /* Already tried, and failed. */
+
+ /* Several distributions like Debian/Ubuntu and OpenSUSE provide libxcrypt as libcrypt.so.1
+ * (libcrypt.so.1.1 on some architectures), while others like Fedora/CentOS and Arch provide it as
+ * libcrypt.so.2. */
+ SD_ELF_NOTE_DLOPEN(
+ "crypt",
+ "Support for hashing passwords",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libcrypt.so.2", "libcrypt.so.1", "libcrypt.so.1.1");
+
+ _cleanup_(dlclosep) void *dl = NULL;
+ const char *dle = NULL;
+ FOREACH_STRING(soname, "libcrypt.so.2", "libcrypt.so.1", "libcrypt.so.1.1") {
+ r = dlopen_safe(soname, &dl, &dle);
+ if (r >= 0) {
+ log_debug("Loaded '%s' via dlopen().", soname);
+ break;
+ }
+ }
+ if (r < 0) {
+ log_full_errno(log_level, r, "Failed to load libcrypt: %s", dle ?: STRERROR(r));
+ return (cached = -EOPNOTSUPP); /* turn into recognizable error */
+ }
+
+ r = dlsym_many_or_warn(
+ dl, log_level,
+ DLSYM_ARG(crypt_gensalt_ra),
+ DLSYM_ARG(crypt_preferred_method),
+ DLSYM_ARG(crypt_ra));
+ if (r < 0)
+ return (cached = r);
+
+ libcrypt_dl = TAKE_PTR(dl);
+#else
+ libcrypt_dl = NULL;
+ sym_crypt_gensalt_ra = missing_crypt_gensalt_ra;
+ sym_crypt_preferred_method = missing_crypt_preferred_method;
+ sym_crypt_ra = missing_crypt_ra;
+#endif
+ return 0;
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libcrypt support is not compiled in.");
+#endif
+}
diff --git a/src/shared/libcrypt-util.h b/src/shared/libcrypt-util.h
index 3f79916cbc..5c469b662c 100644
--- a/src/shared/libcrypt-util.h
+++ b/src/shared/libcrypt-util.h
@@ -4,7 +4,6 @@
#include "shared-forward.h"
#if HAVE_LIBCRYPT
-int dlopen_libcrypt(void);
int make_salt(char **ret);
int hash_password(const char *password, char **ret);
int test_password_one(const char *hashed_password, const char *password);
@@ -12,12 +11,11 @@ int test_password_many(char **hashed_password, const char *password);
#else
-static inline int dlopen_libcrypt(void) {
- return -EOPNOTSUPP;
-}
static inline int hash_password(const char *password, char **ret) {
return -EOPNOTSUPP;
}
#endif
+int dlopen_libcrypt(int log_level);
+
bool looks_like_hashed_password(const char *s);
diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c
index 18d020d34c..cc00006af9 100644
--- a/src/shared/libfido2-util.c
+++ b/src/shared/libfido2-util.c
@@ -80,7 +80,7 @@ static void fido_log_propagate_handler(const char *s) {
#endif
-int dlopen_libfido2(void) {
+int dlopen_libfido2(int log_level) {
#if HAVE_LIBFIDO2
int r;
@@ -91,7 +91,7 @@ int dlopen_libfido2(void) {
"libfido2.so.1");
r = dlopen_many_sym_or_warn(
- &libfido2_dl, "libfido2.so.1", LOG_DEBUG,
+ &libfido2_dl, "libfido2.so.1", log_level,
DLSYM_ARG(fido_assert_allow_cred),
DLSYM_ARG(fido_assert_free),
DLSYM_ARG(fido_assert_hmac_secret_len),
@@ -148,7 +148,8 @@ int dlopen_libfido2(void) {
return 0;
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libfido2 support is not compiled in.");
#endif
}
@@ -658,9 +659,9 @@ int fido2_use_hmac_hash(
fido_dev_info_t *di = NULL;
int r;
- r = dlopen_libfido2();
+ r = dlopen_libfido2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "FIDO2 support is not installed.");
+ return r;
if (device) {
r = fido2_is_cred_in_specific_token(device, rp_id, cid, cid_size, required);
@@ -784,9 +785,9 @@ int fido2_generate_hmac_hash(
assert((lock_with & ~(FIDO2ENROLL_PIN|FIDO2ENROLL_UP|FIDO2ENROLL_UV)) == 0);
assert(iovec_is_set(salt));
- r = dlopen_libfido2();
+ r = dlopen_libfido2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "FIDO2 token support is not installed.");
+ return r;
d = sym_fido_dev_new();
if (!d)
@@ -1188,9 +1189,9 @@ int fido2_list_devices(void) {
fido_dev_info_t *di = NULL;
int r;
- r = dlopen_libfido2();
+ r = dlopen_libfido2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "FIDO2 token support is not installed.");
+ return r;
di = sym_fido_dev_info_new(allocated);
if (!di)
@@ -1282,9 +1283,9 @@ int fido2_find_device_auto(char **ret) {
const char *path;
int r;
- r = dlopen_libfido2();
+ r = dlopen_libfido2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "FIDO2 token support is not installed.");
+ return r;
di = sym_fido_dev_info_new(di_size);
if (!di)
@@ -1359,9 +1360,9 @@ int fido2_have_device(const char *device) {
/* Return == 0 if not devices are found, > 0 if at least one is found */
- r = dlopen_libfido2();
+ r = dlopen_libfido2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "FIDO2 support is not installed.");
+ return r;
if (device) {
if (access(device, F_OK) < 0) {
diff --git a/src/shared/libfido2-util.h b/src/shared/libfido2-util.h
index c5d3875a0d..4f88100be7 100644
--- a/src/shared/libfido2-util.h
+++ b/src/shared/libfido2-util.h
@@ -16,7 +16,7 @@ typedef enum Fido2EnrollFlags {
_FIDO2ENROLL_TYPE_INVALID = -EINVAL,
} Fido2EnrollFlags;
-int dlopen_libfido2(void);
+int dlopen_libfido2(int log_level);
#if HAVE_LIBFIDO2
#include
diff --git a/src/shared/libmount-util.c b/src/shared/libmount-util.c
index 0d63675667..27e98888d0 100644
--- a/src/shared/libmount-util.c
+++ b/src/shared/libmount-util.c
@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "libmount-util.h"
+#include "log.h"
+
+#if HAVE_LIBMOUNT
+
#include
#include "sd-dlopen.h"
#include "fstab-util.h"
-#include "libmount-util.h"
-#include "log.h"
static void *libmount_dl = NULL;
@@ -42,50 +45,6 @@ DLSYM_PROTOTYPE(mnt_table_parse_stream) = NULL;
DLSYM_PROTOTYPE(mnt_table_parse_swaps) = NULL;
DLSYM_PROTOTYPE(mnt_unref_monitor) = NULL;
-int dlopen_libmount(void) {
- SD_ELF_NOTE_DLOPEN(
- "mount",
- "Support for mount enumeration",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libmount.so.1");
-
- return dlopen_many_sym_or_warn(
- &libmount_dl,
- "libmount.so.1",
- LOG_DEBUG,
- DLSYM_ARG(mnt_free_iter),
- DLSYM_ARG(mnt_free_table),
- DLSYM_ARG(mnt_fs_get_fs_options),
- DLSYM_ARG(mnt_fs_get_fstype),
- DLSYM_ARG(mnt_fs_get_id),
- DLSYM_ARG(mnt_fs_get_option),
- DLSYM_ARG(mnt_fs_get_options),
- DLSYM_ARG(mnt_fs_get_passno),
- DLSYM_ARG(mnt_fs_get_propagation),
- DLSYM_ARG(mnt_fs_get_source),
- DLSYM_ARG(mnt_fs_get_target),
- DLSYM_ARG(mnt_fs_get_vfs_options),
- DLSYM_ARG(mnt_get_builtin_optmap),
- DLSYM_ARG(mnt_init_debug),
- DLSYM_ARG(mnt_monitor_enable_kernel),
- DLSYM_ARG(mnt_monitor_enable_userspace),
- DLSYM_ARG(mnt_monitor_get_fd),
- DLSYM_ARG(mnt_monitor_next_change),
- DLSYM_ARG(mnt_new_iter),
- DLSYM_ARG(mnt_new_monitor),
- DLSYM_ARG(mnt_new_table),
- DLSYM_ARG(mnt_optstr_get_flags),
- DLSYM_ARG(mnt_table_find_devno),
- DLSYM_ARG(mnt_table_find_target),
- DLSYM_ARG(mnt_table_next_child_fs),
- DLSYM_ARG(mnt_table_next_fs),
- DLSYM_ARG(mnt_table_parse_file),
- DLSYM_ARG(mnt_table_parse_mtab),
- DLSYM_ARG(mnt_table_parse_stream),
- DLSYM_ARG(mnt_table_parse_swaps),
- DLSYM_ARG(mnt_unref_monitor));
-}
-
int libmount_parse_full(
const char *path,
FILE *source,
@@ -103,7 +62,7 @@ int libmount_parse_full(
assert(ret_table);
assert(ret_iter);
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return r;
@@ -156,3 +115,54 @@ int libmount_is_leaf(
return r == 1;
}
+
+#endif
+
+int dlopen_libmount(int log_level) {
+#if HAVE_LIBMOUNT
+ SD_ELF_NOTE_DLOPEN(
+ "mount",
+ "Support for mount enumeration",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libmount.so.1");
+
+ return dlopen_many_sym_or_warn(
+ &libmount_dl,
+ "libmount.so.1",
+ log_level,
+ DLSYM_ARG(mnt_free_iter),
+ DLSYM_ARG(mnt_free_table),
+ DLSYM_ARG(mnt_fs_get_fs_options),
+ DLSYM_ARG(mnt_fs_get_fstype),
+ DLSYM_ARG(mnt_fs_get_id),
+ DLSYM_ARG(mnt_fs_get_option),
+ DLSYM_ARG(mnt_fs_get_options),
+ DLSYM_ARG(mnt_fs_get_passno),
+ DLSYM_ARG(mnt_fs_get_propagation),
+ DLSYM_ARG(mnt_fs_get_source),
+ DLSYM_ARG(mnt_fs_get_target),
+ DLSYM_ARG(mnt_fs_get_vfs_options),
+ DLSYM_ARG(mnt_get_builtin_optmap),
+ DLSYM_ARG(mnt_init_debug),
+ DLSYM_ARG(mnt_monitor_enable_kernel),
+ DLSYM_ARG(mnt_monitor_enable_userspace),
+ DLSYM_ARG(mnt_monitor_get_fd),
+ DLSYM_ARG(mnt_monitor_next_change),
+ DLSYM_ARG(mnt_new_iter),
+ DLSYM_ARG(mnt_new_monitor),
+ DLSYM_ARG(mnt_new_table),
+ DLSYM_ARG(mnt_optstr_get_flags),
+ DLSYM_ARG(mnt_table_find_devno),
+ DLSYM_ARG(mnt_table_find_target),
+ DLSYM_ARG(mnt_table_next_child_fs),
+ DLSYM_ARG(mnt_table_next_fs),
+ DLSYM_ARG(mnt_table_parse_file),
+ DLSYM_ARG(mnt_table_parse_mtab),
+ DLSYM_ARG(mnt_table_parse_stream),
+ DLSYM_ARG(mnt_table_parse_swaps),
+ DLSYM_ARG(mnt_unref_monitor));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libmount support is not compiled in.");
+#endif
+}
diff --git a/src/shared/libmount-util.h b/src/shared/libmount-util.h
index bfbb00cd4a..7eb7b230b2 100644
--- a/src/shared/libmount-util.h
+++ b/src/shared/libmount-util.h
@@ -42,8 +42,6 @@ extern DLSYM_PROTOTYPE(mnt_table_parse_stream);
extern DLSYM_PROTOTYPE(mnt_table_parse_swaps);
extern DLSYM_PROTOTYPE(mnt_unref_monitor);
-int dlopen_libmount(void);
-
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct libmnt_table*, sym_mnt_free_table, mnt_free_tablep, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct libmnt_iter*, sym_mnt_free_iter, mnt_free_iterp, NULL);
@@ -79,9 +77,6 @@ int libmount_is_leaf(
struct libmnt_monitor;
-static inline int dlopen_libmount(void) {
- return -EOPNOTSUPP;
-}
static inline void* sym_mnt_unref_monitor(struct libmnt_monitor *p) {
assert(p == NULL);
@@ -89,3 +84,5 @@ static inline void* sym_mnt_unref_monitor(struct libmnt_monitor *p) {
}
#endif
+
+int dlopen_libmount(int log_level);
diff --git a/src/shared/meson.build b/src/shared/meson.build
index 0e45584c6d..1ab14a5c92 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -3,6 +3,7 @@
shared_sources = files(
'acl-util.c',
'acpi-fpdt.c',
+ 'apparmor-util.c',
'ask-password-agent.c',
'ask-password-api.c',
'async.c',
@@ -79,6 +80,7 @@ shared_sources = files(
'extension-util.c',
'factory-reset.c',
'facts.c',
+ 'fdisk-util.c',
'fdset.c',
'fido2-util.c',
'find-esp.c',
@@ -88,12 +90,14 @@ shared_sources = files(
'fstab-util.c',
'generator.c',
'geneve-util.c',
+ 'gnutls-util.c',
'gpt.c',
'group-record.c',
'hibernate-util.c',
'hostname-setup.c',
'hwdb-util.c',
'id128-print.c',
+ 'idn-util.c',
'ima-util.c',
'image-policy.c',
'import-util.c',
@@ -116,6 +120,7 @@ shared_sources = files(
'libaudit-util.c',
'libcrypt-util.c',
'libfido2-util.c',
+ 'libmount-util.c',
'local-addresses.c',
'locale-setup.c',
'log-assert-critical.c',
@@ -130,6 +135,7 @@ shared_sources = files(
'macvlan-util.c',
'main-func.c',
'metrics.c',
+ 'microhttpd-util.c',
'mkdir-label.c',
'mkfs-util.c',
'module-util.c',
@@ -150,6 +156,7 @@ shared_sources = files(
'osc-context.c',
'output-mode.c',
'pager.c',
+ 'pam-util.c',
'parse-argument.c',
'parse-helpers.c',
'password-quality-util-passwdqc.c',
@@ -283,22 +290,6 @@ if conf.get('HAVE_LIBBPF') == 1
shared_sources += files('bpf-link.c')
endif
-if conf.get('HAVE_PAM') == 1
- shared_sources += files('pam-util.c')
-endif
-
-if conf.get('HAVE_LIBMOUNT') == 1
- shared_sources += files('libmount-util.c')
-endif
-
-if conf.get('HAVE_LIBIDN2') == 1
- shared_sources += files('idn-util.c')
-endif
-
-if conf.get('HAVE_APPARMOR') == 1
- shared_sources += files('apparmor-util.c')
-endif
-
generate_ip_protocol_list = files('generate-ip-protocol-list.sh')
ip_protocol_list_txt = custom_target(
input : [generate_ip_protocol_list, ipproto_sources],
@@ -401,10 +392,13 @@ libshared_deps = [threads,
libdl,
libdw_cflags,
libelf_cflags,
+ libfdisk_cflags,
libfido2_cflags,
libgcrypt_cflags,
+ libgnutls_cflags,
libidn2_cflags,
libkmod_cflags,
+ libmicrohttpd_cflags,
libmount_cflags,
libopenssl,
libp11kit_cflags,
@@ -449,15 +443,3 @@ libshared = shared_library(
userspace],
install : true,
install_dir : pkglibdir)
-
-shared_fdisk_sources = files('fdisk-util.c')
-
-libshared_fdisk = static_library(
- 'shared-fdisk',
- shared_fdisk_sources,
- include_directories : includes,
- implicit_include_directories : false,
- dependencies : [libfdisk,
- userspace],
- c_args : ['-fvisibility=default'],
- build_by_default : false)
diff --git a/src/journal-remote/microhttpd-util.c b/src/shared/microhttpd-util.c
similarity index 65%
rename from src/journal-remote/microhttpd-util.c
rename to src/shared/microhttpd-util.c
index 32751e85e1..6dd55d8a07 100644
--- a/src/journal-remote/microhttpd-util.c
+++ b/src/shared/microhttpd-util.c
@@ -2,17 +2,74 @@
#include
-#if HAVE_GNUTLS
-#include
-#include
-#endif
+#include "sd-dlopen.h"
#include "alloc-util.h"
+#include "gnutls-util.h"
#include "log.h"
#include "microhttpd-util.h"
#include "string-util.h"
#include "strv.h"
+#if HAVE_MICROHTTPD
+static void *microhttpd_dl = NULL;
+
+DLSYM_PROTOTYPE(MHD_add_response_header) = NULL;
+DLSYM_PROTOTYPE(MHD_create_response_from_buffer) = NULL;
+DLSYM_PROTOTYPE(MHD_create_response_from_callback) = NULL;
+#if MHD_VERSION < 0x00094203
+DLSYM_PROTOTYPE(MHD_create_response_from_fd_at_offset) = NULL;
+#else
+DLSYM_PROTOTYPE(MHD_create_response_from_fd_at_offset64) = NULL;
+#endif
+DLSYM_PROTOTYPE(MHD_destroy_response) = NULL;
+DLSYM_PROTOTYPE(MHD_get_connection_info) = NULL;
+DLSYM_PROTOTYPE(MHD_get_connection_values) = NULL;
+DLSYM_PROTOTYPE(MHD_get_daemon_info) = NULL;
+DLSYM_PROTOTYPE(MHD_get_timeout) = NULL;
+DLSYM_PROTOTYPE(MHD_lookup_connection_value) = NULL;
+DLSYM_PROTOTYPE(MHD_queue_response) = NULL;
+DLSYM_PROTOTYPE(MHD_run) = NULL;
+DLSYM_PROTOTYPE(MHD_start_daemon) = NULL;
+DLSYM_PROTOTYPE(MHD_stop_daemon) = NULL;
+#endif
+
+int dlopen_microhttpd(int log_level) {
+#if HAVE_MICROHTTPD
+ SD_ELF_NOTE_DLOPEN(
+ "microhttpd",
+ "Support for embedded HTTP server via libmicrohttpd",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
+ "libmicrohttpd.so.12");
+
+ return dlopen_many_sym_or_warn(
+ µhttpd_dl,
+ "libmicrohttpd.so.12",
+ log_level,
+ DLSYM_ARG(MHD_add_response_header),
+ DLSYM_ARG(MHD_create_response_from_buffer),
+ DLSYM_ARG(MHD_create_response_from_callback),
+#if MHD_VERSION < 0x00094203
+ DLSYM_ARG(MHD_create_response_from_fd_at_offset),
+#else
+ DLSYM_ARG(MHD_create_response_from_fd_at_offset64),
+#endif
+ DLSYM_ARG(MHD_destroy_response),
+ DLSYM_ARG(MHD_get_connection_info),
+ DLSYM_ARG(MHD_get_connection_values),
+ DLSYM_ARG(MHD_get_daemon_info),
+ DLSYM_ARG(MHD_get_timeout),
+ DLSYM_ARG(MHD_lookup_connection_value),
+ DLSYM_ARG(MHD_queue_response),
+ DLSYM_ARG(MHD_run),
+ DLSYM_ARG(MHD_start_daemon),
+ DLSYM_ARG(MHD_stop_daemon));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libmicrohttpd support is not compiled in.");
+#endif
+}
+
#if HAVE_MICROHTTPD
void microhttpd_logger(void *arg, const char *fmt, va_list ap) {
@@ -36,18 +93,18 @@ int mhd_respond_internal(
assert(connection);
_cleanup_(MHD_destroy_responsep) struct MHD_Response *response
- = MHD_create_response_from_buffer(size, (char*) buffer, mode);
+ = sym_MHD_create_response_from_buffer(size, (char*) buffer, mode);
if (!response)
return MHD_NO;
log_debug("Queueing response %u: %s", code, buffer);
if (encoding)
- if (MHD_add_response_header(response, "Accept-Encoding", encoding) == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Accept-Encoding", encoding) == MHD_NO)
return MHD_NO;
- if (MHD_add_response_header(response, "Content-Type", "text/plain") == MHD_NO)
+ if (sym_MHD_add_response_header(response, "Content-Type", "text/plain") == MHD_NO)
return MHD_NO;
- return MHD_queue_response(connection, code, response);
+ return sym_MHD_queue_response(connection, code, response);
}
int mhd_respond_oom(struct MHD_Connection *connection) {
@@ -116,7 +173,7 @@ static void log_reset_gnutls_level(void) {
for (i = ELEMENTSOF(gnutls_log_map) - 1; i >= 0; i--)
if (gnutls_log_map[i].enabled) {
log_debug("Setting gnutls log level to %d", i);
- gnutls_global_set_log_level(i);
+ sym_gnutls_global_set_log_level(i);
break;
}
}
@@ -140,7 +197,16 @@ static int log_enable_gnutls_category(const char *cat) {
int setup_gnutls_logger(char **categories) {
int r;
- gnutls_global_set_log_function(log_func_gnutls);
+ r = dlopen_gnutls(LOG_DEBUG);
+ if (r < 0) {
+ if (categories)
+ log_notice("Ignoring specified gnutls logging categories -- gnutls not available.");
+ else
+ log_debug("GnuTLS not available, skipping logger setup.");
+ return 0;
+ }
+
+ sym_gnutls_global_set_log_function(log_func_gnutls);
if (categories)
STRV_FOREACH(cat, categories) {
@@ -160,17 +226,19 @@ static int verify_cert_authorized(gnutls_session_t session) {
gnutls_datum_t out;
int r;
- r = gnutls_certificate_verify_peers2(session, &status);
+ r = sym_gnutls_certificate_verify_peers2(session, &status);
if (r < 0)
return log_error_errno(r, "gnutls_certificate_verify_peers2 failed: %m");
- type = gnutls_certificate_type_get(session);
- r = gnutls_certificate_verification_status_print(status, type, &out, 0);
+ type = sym_gnutls_certificate_type_get(session);
+ r = sym_gnutls_certificate_verification_status_print(status, type, &out, 0);
if (r < 0)
return log_error_errno(r, "gnutls_certificate_verification_status_print failed: %m");
log_debug("Certificate status: %s", out.data);
- gnutls_free(out.data);
+ /* gnutls_free is declared as a function pointer variable (not a function), so sym_gnutls_free
+ * ends up as a pointer-to-function-pointer and must be explicitly dereferenced to be called. */
+ (*sym_gnutls_free)(out.data);
return status == 0 ? 0 : -EPERM;
}
@@ -184,12 +252,12 @@ static int get_client_cert(gnutls_session_t session, gnutls_x509_crt_t *client_c
assert(session);
assert(client_cert);
- pcert = gnutls_certificate_get_peers(session, &listsize);
+ pcert = sym_gnutls_certificate_get_peers(session, &listsize);
if (!pcert || !listsize)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to retrieve certificate chain");
- r = gnutls_x509_crt_init(&cert);
+ r = sym_gnutls_x509_crt_init(&cert);
if (r < 0) {
log_error("Failed to initialize client certificate");
return r;
@@ -197,10 +265,10 @@ static int get_client_cert(gnutls_session_t session, gnutls_x509_crt_t *client_c
/* Note that by passing values between 0 and listsize here, you
can get access to the CA's certs */
- r = gnutls_x509_crt_import(cert, &pcert[0], GNUTLS_X509_FMT_DER);
+ r = sym_gnutls_x509_crt_import(cert, &pcert[0], GNUTLS_X509_FMT_DER);
if (r < 0) {
log_error("Failed to import client certificate");
- gnutls_x509_crt_deinit(cert);
+ sym_gnutls_x509_crt_deinit(cert);
return r;
}
@@ -215,7 +283,7 @@ static int get_auth_dn(gnutls_x509_crt_t client_cert, char **buf) {
assert(buf);
assert(*buf == NULL);
- r = gnutls_x509_crt_get_dn(client_cert, NULL, &len);
+ r = sym_gnutls_x509_crt_get_dn(client_cert, NULL, &len);
if (r != GNUTLS_E_SHORT_MEMORY_BUFFER) {
log_error("gnutls_x509_crt_get_dn failed");
return r;
@@ -225,14 +293,15 @@ static int get_auth_dn(gnutls_x509_crt_t client_cert, char **buf) {
if (!*buf)
return log_oom();
- gnutls_x509_crt_get_dn(client_cert, *buf, &len);
+ sym_gnutls_x509_crt_get_dn(client_cert, *buf, &len);
return 0;
}
static void gnutls_x509_crt_deinitp(gnutls_x509_crt_t *p) {
assert(p);
- gnutls_x509_crt_deinit(*p);
+ if (*p)
+ sym_gnutls_x509_crt_deinit(*p);
}
int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) {
@@ -247,8 +316,12 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
*code = 0;
- ci = MHD_get_connection_info(connection,
- MHD_CONNECTION_INFO_GNUTLS_SESSION);
+ r = dlopen_gnutls(LOG_ERR);
+ if (r < 0)
+ return r;
+
+ ci = sym_MHD_get_connection_info(connection,
+ MHD_CONNECTION_INFO_GNUTLS_SESSION);
if (!ci) {
log_error("MHD_get_connection_info failed: session is unencrypted");
*code = mhd_respond(connection, MHD_HTTP_FORBIDDEN,
diff --git a/src/journal-remote/microhttpd-util.h b/src/shared/microhttpd-util.h
similarity index 76%
rename from src/journal-remote/microhttpd-util.h
rename to src/shared/microhttpd-util.h
index 80142e24f5..488ba7ea6e 100644
--- a/src/journal-remote/microhttpd-util.h
+++ b/src/shared/microhttpd-util.h
@@ -1,11 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include "shared-forward.h"
+
+int dlopen_microhttpd(int log_level);
+
#if HAVE_MICROHTTPD
#include
-#include "shared-forward.h"
+#include "dlfcn-util.h"
/* Those defines are added when options are renamed. If the old names
* are not '#define'd, then they are not deprecated yet and there are
@@ -58,6 +62,26 @@
# define mhd_result int
#endif
+extern DLSYM_PROTOTYPE(MHD_add_response_header);
+extern DLSYM_PROTOTYPE(MHD_create_response_from_buffer);
+extern DLSYM_PROTOTYPE(MHD_create_response_from_callback);
+#if MHD_VERSION < 0x00094203
+extern DLSYM_PROTOTYPE(MHD_create_response_from_fd_at_offset);
+# define sym_MHD_create_response_from_fd_at_offset64 sym_MHD_create_response_from_fd_at_offset
+#else
+extern DLSYM_PROTOTYPE(MHD_create_response_from_fd_at_offset64);
+#endif
+extern DLSYM_PROTOTYPE(MHD_destroy_response);
+extern DLSYM_PROTOTYPE(MHD_get_connection_info);
+extern DLSYM_PROTOTYPE(MHD_get_connection_values);
+extern DLSYM_PROTOTYPE(MHD_get_daemon_info);
+extern DLSYM_PROTOTYPE(MHD_get_timeout);
+extern DLSYM_PROTOTYPE(MHD_lookup_connection_value);
+extern DLSYM_PROTOTYPE(MHD_queue_response);
+extern DLSYM_PROTOTYPE(MHD_run);
+extern DLSYM_PROTOTYPE(MHD_start_daemon);
+extern DLSYM_PROTOTYPE(MHD_stop_daemon);
+
void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0);
/* respond_oom() must be usable with return, hence this form. */
@@ -107,7 +131,7 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
*/
int setup_gnutls_logger(char **categories);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Daemon*, MHD_stop_daemon, NULL);
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Response*, MHD_destroy_response, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct MHD_Daemon*, sym_MHD_stop_daemon, MHD_stop_daemonp, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct MHD_Response*, sym_MHD_destroy_response, MHD_destroy_responsep, NULL);
#endif
diff --git a/src/shared/module-util.c b/src/shared/module-util.c
index 8ad7dab180..9bf1a827b0 100644
--- a/src/shared/module-util.c
+++ b/src/shared/module-util.c
@@ -27,32 +27,6 @@ DLSYM_PROTOTYPE(kmod_set_log_fn) = NULL;
DLSYM_PROTOTYPE(kmod_unref) = NULL;
DLSYM_PROTOTYPE(kmod_validate_resources) = NULL;
-int dlopen_libkmod(void) {
- SD_ELF_NOTE_DLOPEN(
- "kmod",
- "Support for loading kernel modules",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libkmod.so.2");
-
- return dlopen_many_sym_or_warn(
- &libkmod_dl,
- "libkmod.so.2",
- LOG_DEBUG,
- DLSYM_ARG(kmod_list_next),
- DLSYM_ARG(kmod_load_resources),
- DLSYM_ARG(kmod_module_get_initstate),
- DLSYM_ARG(kmod_module_get_module),
- DLSYM_ARG(kmod_module_get_name),
- DLSYM_ARG(kmod_module_new_from_lookup),
- DLSYM_ARG(kmod_module_probe_insert_module),
- DLSYM_ARG(kmod_module_unref),
- DLSYM_ARG(kmod_module_unref_list),
- DLSYM_ARG(kmod_new),
- DLSYM_ARG(kmod_set_log_fn),
- DLSYM_ARG(kmod_unref),
- DLSYM_ARG(kmod_validate_resources));
-}
-
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
char ***denylist = ASSERT_PTR(data);
int r;
@@ -180,7 +154,7 @@ int module_setup_context(struct kmod_ctx **ret) {
assert(ret);
- r = dlopen_libkmod();
+ r = dlopen_libkmod(LOG_DEBUG);
if (r < 0)
return r;
@@ -196,3 +170,34 @@ int module_setup_context(struct kmod_ctx **ret) {
}
#endif
+
+int dlopen_libkmod(int log_level) {
+#if HAVE_KMOD
+ SD_ELF_NOTE_DLOPEN(
+ "kmod",
+ "Support for loading kernel modules",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libkmod.so.2");
+
+ return dlopen_many_sym_or_warn(
+ &libkmod_dl,
+ "libkmod.so.2",
+ log_level,
+ DLSYM_ARG(kmod_list_next),
+ DLSYM_ARG(kmod_load_resources),
+ DLSYM_ARG(kmod_module_get_initstate),
+ DLSYM_ARG(kmod_module_get_module),
+ DLSYM_ARG(kmod_module_get_name),
+ DLSYM_ARG(kmod_module_new_from_lookup),
+ DLSYM_ARG(kmod_module_probe_insert_module),
+ DLSYM_ARG(kmod_module_unref),
+ DLSYM_ARG(kmod_module_unref_list),
+ DLSYM_ARG(kmod_new),
+ DLSYM_ARG(kmod_set_log_fn),
+ DLSYM_ARG(kmod_unref),
+ DLSYM_ARG(kmod_validate_resources));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libkmod support is not compiled in.");
+#endif
+}
diff --git a/src/shared/module-util.h b/src/shared/module-util.h
index f5eaf35c90..629979722c 100644
--- a/src/shared/module-util.h
+++ b/src/shared/module-util.h
@@ -23,8 +23,6 @@ extern DLSYM_PROTOTYPE(kmod_set_log_fn);
extern DLSYM_PROTOTYPE(kmod_unref);
extern DLSYM_PROTOTYPE(kmod_validate_resources);
-int dlopen_libkmod(void);
-
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct kmod_ctx*, sym_kmod_unref, kmod_unrefp, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct kmod_module*, sym_kmod_module_unref, kmod_module_unrefp, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(struct kmod_list*, sym_kmod_module_unref_list, kmod_module_unref_listp, NULL);
@@ -41,9 +39,6 @@ int module_setup_context(struct kmod_ctx **ret);
struct kmod_ctx;
-static inline int dlopen_libkmod(void) {
- return -EOPNOTSUPP;
-}
static inline int module_setup_context(struct kmod_ctx **ret) {
return -EOPNOTSUPP;
@@ -54,3 +49,5 @@ static inline int module_load_and_warn(struct kmod_ctx *ctx, const char *module,
}
#endif
+
+int dlopen_libkmod(int log_level);
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index 45ffd9113b..12d3da82e2 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -451,7 +451,7 @@ int bind_remount_one_with_mountinfo(
rewind(proc_self_mountinfo);
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return r;
@@ -900,7 +900,7 @@ int mount_option_mangle(
* The validity of options stored in '*ret_remaining_options' is not checked.
* If 'options' is NULL, this just copies 'mount_flags' to *ret_mount_flags. */
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/pam-util.c b/src/shared/pam-util.c
index 0f04e97377..9728c3e00d 100644
--- a/src/shared/pam-util.c
+++ b/src/shared/pam-util.c
@@ -1,5 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "log.h"
+#include "pam-util.h"
+
+#if HAVE_PAM
+
#include
#include
@@ -11,8 +16,6 @@
#include "errno-util.h"
#include "fd-util.h"
#include "format-util.h"
-#include "log.h"
-#include "pam-util.h"
#include "process-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -35,34 +38,6 @@ DLSYM_PROTOTYPE(pam_strerror) = NULL;
DLSYM_PROTOTYPE(pam_syslog) = NULL;
DLSYM_PROTOTYPE(pam_vsyslog) = NULL;
-int dlopen_libpam(void) {
- SD_ELF_NOTE_DLOPEN(
- "pam",
- "Support for LinuxPAM",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libpam.so.0");
-
- return dlopen_many_sym_or_warn(
- &libpam_dl,
- "libpam.so.0",
- LOG_DEBUG,
- DLSYM_ARG(pam_acct_mgmt),
- DLSYM_ARG(pam_close_session),
- DLSYM_ARG(pam_end),
- DLSYM_ARG(pam_get_data),
- DLSYM_ARG(pam_get_item),
- DLSYM_ARG(pam_getenvlist),
- DLSYM_ARG(pam_open_session),
- DLSYM_ARG(pam_putenv),
- DLSYM_ARG(pam_set_data),
- DLSYM_ARG(pam_set_item),
- DLSYM_ARG(pam_setcred),
- DLSYM_ARG(pam_start),
- DLSYM_ARG(pam_strerror),
- DLSYM_ARG(pam_syslog),
- DLSYM_ARG(pam_vsyslog));
-}
-
void pam_log_setup(void) {
/* Make sure we don't leak the syslog fd we open by opening/closing the fd each time. */
log_set_open_when_needed(true);
@@ -385,3 +360,38 @@ int pam_prompt_graceful(pam_handle_t *pamh, int style, char **ret_response, cons
return PAM_SUCCESS;
}
+
+#endif
+
+int dlopen_libpam(int log_level) {
+#if HAVE_PAM
+ SD_ELF_NOTE_DLOPEN(
+ "pam",
+ "Support for LinuxPAM",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libpam.so.0");
+
+ return dlopen_many_sym_or_warn(
+ &libpam_dl,
+ "libpam.so.0",
+ log_level,
+ DLSYM_ARG(pam_acct_mgmt),
+ DLSYM_ARG(pam_close_session),
+ DLSYM_ARG(pam_end),
+ DLSYM_ARG(pam_get_data),
+ DLSYM_ARG(pam_get_item),
+ DLSYM_ARG(pam_getenvlist),
+ DLSYM_ARG(pam_open_session),
+ DLSYM_ARG(pam_putenv),
+ DLSYM_ARG(pam_set_data),
+ DLSYM_ARG(pam_set_item),
+ DLSYM_ARG(pam_setcred),
+ DLSYM_ARG(pam_start),
+ DLSYM_ARG(pam_strerror),
+ DLSYM_ARG(pam_syslog),
+ DLSYM_ARG(pam_vsyslog));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libpam support is not compiled in.");
+#endif
+}
diff --git a/src/shared/pam-util.h b/src/shared/pam-util.h
index 2464e144fb..96d522d8f9 100644
--- a/src/shared/pam-util.h
+++ b/src/shared/pam-util.h
@@ -27,8 +27,6 @@ extern DLSYM_PROTOTYPE(pam_strerror);
extern DLSYM_PROTOTYPE(pam_syslog);
extern DLSYM_PROTOTYPE(pam_vsyslog);
-int dlopen_libpam(void);
-
void pam_log_setup(void);
int errno_to_pam_error(int error) _const_;
@@ -92,10 +90,6 @@ int pam_get_data_many_internal(pam_handle_t *pamh, ...) _sentinel_;
int pam_prompt_graceful(pam_handle_t *pamh, int style, char **ret_response, const char *fmt, ...) _printf_(4,5);
-#else
-
-static inline int dlopen_libpam(void) {
- return -EOPNOTSUPP;
-}
-
#endif
+
+int dlopen_libpam(int log_level);
diff --git a/src/shared/password-quality-util-passwdqc.c b/src/shared/password-quality-util-passwdqc.c
index 33c77b01a0..6ce858c744 100644
--- a/src/shared/password-quality-util-passwdqc.c
+++ b/src/shared/password-quality-util-passwdqc.c
@@ -2,6 +2,9 @@
#include "password-quality-util-passwdqc.h"
+#include "errno-util.h" /* IWYU pragma: keep */
+#include "log.h" /* IWYU pragma: keep */
+
#if HAVE_PASSWDQC
#include
@@ -10,8 +13,6 @@
#include "alloc-util.h"
#include "dlfcn-util.h"
-#include "errno-util.h"
-#include "log.h"
#include "memory-util.h"
#include "strv.h"
@@ -34,7 +35,7 @@ static int pwqc_allocate_context(passwdqc_params_t **ret) {
assert(ret);
- r = dlopen_passwdqc();
+ r = dlopen_passwdqc(LOG_DEBUG);
if (r < 0)
return r;
@@ -137,7 +138,7 @@ int check_password_quality(
#endif
-int dlopen_passwdqc(void) {
+int dlopen_passwdqc(int log_level) {
#if HAVE_PASSWDQC
SD_ELF_NOTE_DLOPEN(
"passwdqc",
@@ -146,7 +147,7 @@ int dlopen_passwdqc(void) {
"libpasswdqc.so.1");
return dlopen_many_sym_or_warn(
- &passwdqc_dl, "libpasswdqc.so.1", LOG_DEBUG,
+ &passwdqc_dl, "libpasswdqc.so.1", log_level,
DLSYM_ARG(passwdqc_params_reset),
DLSYM_ARG(passwdqc_params_load),
DLSYM_ARG(passwdqc_params_parse),
@@ -154,6 +155,7 @@ int dlopen_passwdqc(void) {
DLSYM_ARG(passwdqc_check),
DLSYM_ARG(passwdqc_random));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libpasswdqc support is not compiled in.");
#endif
}
diff --git a/src/shared/password-quality-util-passwdqc.h b/src/shared/password-quality-util-passwdqc.h
index e813829b63..2ae00aa620 100644
--- a/src/shared/password-quality-util-passwdqc.h
+++ b/src/shared/password-quality-util-passwdqc.h
@@ -8,4 +8,4 @@ int suggest_passwords(void);
int check_password_quality(const char *password, const char *old, const char *username, char **ret_error);
#endif
-int dlopen_passwdqc(void);
+int dlopen_passwdqc(int log_level);
diff --git a/src/shared/password-quality-util-pwquality.c b/src/shared/password-quality-util-pwquality.c
index 3eba9495b6..dd0cdcfa13 100644
--- a/src/shared/password-quality-util-pwquality.c
+++ b/src/shared/password-quality-util-pwquality.c
@@ -2,6 +2,9 @@
#include "password-quality-util-pwquality.h"
+#include "errno-util.h"
+#include "log.h"
+
#if HAVE_PWQUALITY
#include
@@ -12,8 +15,6 @@
#include "alloc-util.h"
#include "dlfcn-util.h"
-#include "errno-util.h"
-#include "log.h"
#include "password-quality-util.h"
#include "string-util.h"
#include "strv.h"
@@ -72,7 +73,7 @@ static int pwq_allocate_context(pwquality_settings_t **ret) {
assert(ret);
- r = dlopen_pwquality();
+ r = dlopen_pwquality(LOG_DEBUG);
if (r < 0)
return r;
@@ -153,7 +154,7 @@ int check_password_quality(const char *password, const char *old, const char *us
#endif
-int dlopen_pwquality(void) {
+int dlopen_pwquality(int log_level) {
#if HAVE_PWQUALITY
SD_ELF_NOTE_DLOPEN(
"pwquality",
@@ -162,7 +163,7 @@ int dlopen_pwquality(void) {
"libpwquality.so.1");
return dlopen_many_sym_or_warn(
- &pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
+ &pwquality_dl, "libpwquality.so.1", log_level,
DLSYM_ARG(pwquality_check),
DLSYM_ARG(pwquality_default_settings),
DLSYM_ARG(pwquality_free_settings),
@@ -172,6 +173,7 @@ int dlopen_pwquality(void) {
DLSYM_ARG(pwquality_set_int_value),
DLSYM_ARG(pwquality_strerror));
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libpwquality support is not compiled in.");
#endif
}
diff --git a/src/shared/password-quality-util-pwquality.h b/src/shared/password-quality-util-pwquality.h
index 829025a10d..468734f590 100644
--- a/src/shared/password-quality-util-pwquality.h
+++ b/src/shared/password-quality-util-pwquality.h
@@ -8,4 +8,4 @@ int suggest_passwords(void);
int check_password_quality(const char *password, const char *old, const char *username, char **ret_error);
#endif
-int dlopen_pwquality(void);
+int dlopen_pwquality(int log_level);
diff --git a/src/shared/pcre2-util.c b/src/shared/pcre2-util.c
index 22a7635170..3ac76c1f9c 100644
--- a/src/shared/pcre2-util.c
+++ b/src/shared/pcre2-util.c
@@ -28,7 +28,7 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
const struct hash_ops pcre2_code_hash_ops_free = {};
#endif
-int dlopen_pcre2(void) {
+int dlopen_pcre2(int log_level) {
#if HAVE_PCRE2
SD_ELF_NOTE_DLOPEN(
"pcre2",
@@ -45,7 +45,7 @@ int dlopen_pcre2(void) {
* manually anymore. C is weird. 🤯 */
return dlopen_many_sym_or_warn(
- &pcre2_dl, "libpcre2-8.so.0", LOG_ERR,
+ &pcre2_dl, "libpcre2-8.so.0", log_level,
DLSYM_ARG(pcre2_match_data_create),
DLSYM_ARG(pcre2_match_data_free),
DLSYM_ARG(pcre2_code_free),
@@ -54,7 +54,8 @@ int dlopen_pcre2(void) {
DLSYM_ARG(pcre2_match),
DLSYM_ARG(pcre2_get_ovector_pointer));
#else
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "PCRE2 support is not compiled in.");
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "PCRE2 support is not compiled in.");
#endif
}
@@ -67,7 +68,7 @@ int pattern_compile_and_log(const char *pattern, PatternCompileCase case_, pcre2
assert(pattern);
- r = dlopen_pcre2();
+ r = dlopen_pcre2(LOG_ERR);
if (r < 0)
return r;
diff --git a/src/shared/pcre2-util.h b/src/shared/pcre2-util.h
index 8c85c61994..ba8827fb07 100644
--- a/src/shared/pcre2-util.h
+++ b/src/shared/pcre2-util.h
@@ -44,4 +44,4 @@ typedef enum PatternCompileCase {
int pattern_compile_and_log(const char *pattern, PatternCompileCase case_, pcre2_code **ret);
int pattern_matches_and_log(pcre2_code *compiled_pattern, const char *message, size_t size, size_t *ret_ovec);
-int dlopen_pcre2(void);
+int dlopen_pcre2(int log_level);
diff --git a/src/shared/pcrextend-util.c b/src/shared/pcrextend-util.c
index 6598bf8214..79efdc4574 100644
--- a/src/shared/pcrextend-util.c
+++ b/src/shared/pcrextend-util.c
@@ -37,7 +37,7 @@ static int device_get_file_system_word(
assert(ret);
#if HAVE_BLKID
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c
index 96b25c4ac3..eea7fec893 100644
--- a/src/shared/pkcs11-util.c
+++ b/src/shared/pkcs11-util.c
@@ -65,7 +65,7 @@ int uri_from_string(const char *p, P11KitUri **ret) {
assert(p);
assert(ret);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -85,7 +85,7 @@ P11KitUri *uri_from_module_info(const CK_INFO *info) {
assert(info);
- if (dlopen_p11kit() < 0)
+ if (dlopen_p11kit(LOG_DEBUG) < 0)
return NULL;
uri = sym_p11_kit_uri_new();
@@ -101,7 +101,7 @@ P11KitUri *uri_from_slot_info(const CK_SLOT_INFO *slot_info) {
assert(slot_info);
- if (dlopen_p11kit() < 0)
+ if (dlopen_p11kit(LOG_DEBUG) < 0)
return NULL;
uri = sym_p11_kit_uri_new();
@@ -117,7 +117,7 @@ P11KitUri *uri_from_token_info(const CK_TOKEN_INFO *token_info) {
assert(token_info);
- if (dlopen_p11kit() < 0)
+ if (dlopen_p11kit(LOG_DEBUG) < 0)
return NULL;
uri = sym_p11_kit_uri_new();
@@ -221,7 +221,7 @@ int pkcs11_token_login_by_pin(
assert(m);
assert(token_info);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -283,7 +283,7 @@ int pkcs11_token_login(
assert(m);
assert(token_info);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -675,7 +675,7 @@ int pkcs11_token_read_x509_certificate(
assert(ret_cert);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -1248,7 +1248,7 @@ int pkcs11_token_acquire_rng(
assert(m);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -1334,7 +1334,7 @@ static int slot_process(
assert(m);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -1417,7 +1417,7 @@ static int module_process(
assert(m);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -1481,7 +1481,7 @@ int pkcs11_find_token(
_cleanup_(p11_kit_uri_freep) P11KitUri *search_uri = NULL;
int r;
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -1740,7 +1740,7 @@ static int list_callback(
assert(slot_info);
assert(token_info);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
@@ -1784,7 +1784,7 @@ static int list_callback(
}
#endif
-int dlopen_p11kit(void) {
+int dlopen_p11kit(int log_level) {
#if HAVE_P11KIT
SD_ELF_NOTE_DLOPEN(
"p11-kit",
@@ -1794,7 +1794,7 @@ int dlopen_p11kit(void) {
return dlopen_many_sym_or_warn(
&p11kit_dl,
- "libp11-kit.so.0", LOG_DEBUG,
+ "libp11-kit.so.0", log_level,
DLSYM_ARG(p11_kit_module_get_name),
DLSYM_ARG(p11_kit_modules_finalize_and_release),
DLSYM_ARG(p11_kit_modules_load_and_initialize),
@@ -1812,7 +1812,8 @@ int dlopen_p11kit(void) {
DLSYM_ARG(p11_kit_uri_new),
DLSYM_ARG(p11_kit_uri_parse));
#else
- return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "p11kit support is not compiled in.");
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libp11-kit support is not compiled in.");
#endif
}
@@ -1858,7 +1859,7 @@ static int auto_callback(
assert(slot_info);
assert(token_info);
- r = dlopen_p11kit();
+ r = dlopen_p11kit(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/pkcs11-util.h b/src/shared/pkcs11-util.h
index 51279eabc4..92d850b6e5 100644
--- a/src/shared/pkcs11-util.h
+++ b/src/shared/pkcs11-util.h
@@ -106,7 +106,7 @@ int pkcs11_crypt_device_callback(
#endif
-int dlopen_p11kit(void);
+int dlopen_p11kit(int log_level);
typedef struct {
const char *friendly_name;
diff --git a/src/shared/qrcode-util.c b/src/shared/qrcode-util.c
index ee6d3c40f9..d1c639e74c 100644
--- a/src/shared/qrcode-util.c
+++ b/src/shared/qrcode-util.c
@@ -28,7 +28,7 @@ static DLSYM_PROTOTYPE(QRcode_encodeString) = NULL;
static DLSYM_PROTOTYPE(QRcode_free) = NULL;
#endif
-int dlopen_qrencode(void) {
+int dlopen_qrencode(int log_level) {
#if HAVE_QRENCODE
int r;
@@ -40,7 +40,7 @@ int dlopen_qrencode(void) {
FOREACH_STRING(s, "libqrencode.so.4", "libqrencode.so.3") {
r = dlopen_many_sym_or_warn(
- &qrcode_dl, s, LOG_DEBUG,
+ &qrcode_dl, s, log_level,
DLSYM_ARG(QRcode_encodeString),
DLSYM_ARG(QRcode_free));
if (r >= 0)
@@ -49,7 +49,8 @@ int dlopen_qrencode(void) {
return r;
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libqrencode support is not compiled in.");
#endif
}
@@ -210,7 +211,7 @@ int print_qrcode_full(
if (check_tty && !colors_enabled())
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Colors are disabled, cannot print qrcode");
- r = dlopen_qrencode();
+ r = dlopen_qrencode(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/shared/qrcode-util.h b/src/shared/qrcode-util.h
index 9a624e29e1..667ff8e3ff 100644
--- a/src/shared/qrcode-util.h
+++ b/src/shared/qrcode-util.h
@@ -13,7 +13,7 @@ int print_qrcode_full(
unsigned tty_height,
bool check_tty);
-int dlopen_qrencode(void);
+int dlopen_qrencode(int log_level);
static inline int print_qrcode(FILE *out, const char *header, const char *string) {
return print_qrcode_full(out, header, string, UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX, true);
diff --git a/src/shared/reread-partition-table.c b/src/shared/reread-partition-table.c
index 8f99b67134..9d908ee948 100644
--- a/src/shared/reread-partition-table.c
+++ b/src/shared/reread-partition-table.c
@@ -287,7 +287,7 @@ static int reread_partition_table_full(sd_device *dev, int fd, RereadPartitionTa
}
#if HAVE_BLKID
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
log_device_debug(dev, "We don't have libblkid, falling back to BLKRRPART on '%s'.", p);
return fallback_ioctl(dev, fd, flags);
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 49328ccde2..167a0e40de 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -50,32 +50,6 @@ DLSYM_PROTOTYPE(seccomp_rule_add_exact) = NULL;
DLSYM_PROTOTYPE(seccomp_syscall_resolve_name) = NULL;
DLSYM_PROTOTYPE(seccomp_syscall_resolve_num_arch) = NULL;
-int dlopen_libseccomp(void) {
- SD_ELF_NOTE_DLOPEN(
- "seccomp",
- "Support for Seccomp Sandboxes",
- SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
- "libseccomp.so.2");
-
- return dlopen_many_sym_or_warn(
- &libseccomp_dl,
- "libseccomp.so.2",
- LOG_DEBUG,
- DLSYM_ARG(seccomp_api_get),
- DLSYM_ARG(seccomp_arch_add),
- DLSYM_ARG(seccomp_arch_exist),
- DLSYM_ARG(seccomp_arch_native),
- DLSYM_ARG(seccomp_arch_remove),
- DLSYM_ARG(seccomp_attr_set),
- DLSYM_ARG(seccomp_init),
- DLSYM_ARG(seccomp_load),
- DLSYM_ARG(seccomp_release),
- DLSYM_ARG(seccomp_rule_add_array),
- DLSYM_ARG(seccomp_rule_add_exact),
- DLSYM_ARG(seccomp_syscall_resolve_name),
- DLSYM_ARG(seccomp_syscall_resolve_num_arch));
-}
-
/* This array will be modified at runtime as seccomp_restrict_archs is called. */
uint32_t seccomp_local_archs[] = {
@@ -283,7 +257,7 @@ int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_
/* Much like seccomp_init(), but initializes the filter for one specific architecture only, without affecting
* any others. Also, turns off the NNP fiddling. */
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -343,7 +317,7 @@ bool is_seccomp_available(void) {
static int cached_enabled = -1;
if (cached_enabled < 0) {
- if (dlopen_libseccomp() < 0)
+ if (dlopen_libseccomp(LOG_DEBUG) < 0)
return (cached_enabled = false);
int b = secure_getenv_bool("SYSTEMD_SECCOMP");
@@ -1093,7 +1067,7 @@ int seccomp_add_syscall_filter_item(
} else {
int id, r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1173,7 +1147,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
/* The one-stop solution: allocate a seccomp object, add the specified filter to it, and apply it. Once for
* each local arch. */
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1239,7 +1213,7 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* filter
if (hashmap_isempty(filter) && default_action == SCMP_ACT_ALLOW)
return 0;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1362,7 +1336,7 @@ int seccomp_parse_syscall_filter(
} else {
int id;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0) {
if (!FLAGS_SET(flags, SECCOMP_PARSE_PERMISSIVE))
return r;
@@ -1420,7 +1394,7 @@ int seccomp_restrict_namespaces(unsigned long retain) {
if (FLAGS_SET(retain, NAMESPACE_FLAGS_ALL))
return 0;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1548,7 +1522,7 @@ int seccomp_protect_sysctl(void) {
uint32_t arch;
int r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1600,7 +1574,7 @@ int seccomp_protect_syslog(void) {
uint32_t arch;
int r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1637,7 +1611,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
uint32_t arch;
int r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1823,7 +1797,7 @@ int seccomp_restrict_realtime_full(int error_code) {
assert(error_code > 0);
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -1928,7 +1902,7 @@ int seccomp_memory_deny_write_execute(void) {
unsigned loaded = 0;
int r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2048,7 +2022,7 @@ int seccomp_restrict_archs(Set *archs) {
int r;
bool blocked_new = false;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2141,7 +2115,7 @@ int seccomp_filter_set_add_by_name(Hashmap *filter, bool add, const char *name)
assert(filter);
assert(name);
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2190,7 +2164,7 @@ int seccomp_lock_personality(unsigned long personality) {
if (personality >= PERSONALITY_INVALID)
return -EINVAL;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2228,7 +2202,7 @@ int seccomp_protect_hostname(void) {
uint32_t arch;
int r;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2444,7 +2418,7 @@ int seccomp_restrict_suid_sgid(void) {
uint32_t arch;
int r, k;
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2571,7 +2545,7 @@ int seccomp_suppress_sync(void) {
*
* Additionally, O_SYNC/O_DSYNC are masked. */
- r = dlopen_libseccomp();
+ r = dlopen_libseccomp(LOG_DEBUG);
if (r < 0)
return r;
@@ -2628,6 +2602,37 @@ int seccomp_suppress_sync(void) {
#endif
+int dlopen_libseccomp(int log_level) {
+#if HAVE_SECCOMP
+ SD_ELF_NOTE_DLOPEN(
+ "seccomp",
+ "Support for Seccomp Sandboxes",
+ SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
+ "libseccomp.so.2");
+
+ return dlopen_many_sym_or_warn(
+ &libseccomp_dl,
+ "libseccomp.so.2",
+ log_level,
+ DLSYM_ARG(seccomp_api_get),
+ DLSYM_ARG(seccomp_arch_add),
+ DLSYM_ARG(seccomp_arch_exist),
+ DLSYM_ARG(seccomp_arch_native),
+ DLSYM_ARG(seccomp_arch_remove),
+ DLSYM_ARG(seccomp_attr_set),
+ DLSYM_ARG(seccomp_init),
+ DLSYM_ARG(seccomp_load),
+ DLSYM_ARG(seccomp_release),
+ DLSYM_ARG(seccomp_rule_add_array),
+ DLSYM_ARG(seccomp_rule_add_exact),
+ DLSYM_ARG(seccomp_syscall_resolve_name),
+ DLSYM_ARG(seccomp_syscall_resolve_num_arch));
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libseccomp support is not compiled in.");
+#endif
+}
+
bool seccomp_errno_or_action_is_valid(int n) {
return n == SECCOMP_ERROR_NUMBER_KILL || errno_is_valid(n);
}
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index 51c2ba6505..7037ef52d1 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -23,8 +23,6 @@ extern DLSYM_PROTOTYPE(seccomp_rule_add_exact);
extern DLSYM_PROTOTYPE(seccomp_syscall_resolve_name);
extern DLSYM_PROTOTYPE(seccomp_syscall_resolve_num_arch);
-int dlopen_libseccomp(void);
-
DECLARE_STRING_TABLE_LOOKUP_TO_STRING(seccomp_arch, uint32_t);
int seccomp_arch_from_string(const char *n, uint32_t *ret);
@@ -163,12 +161,11 @@ static inline bool is_seccomp_available(void) {
return false;
}
-static inline int dlopen_libseccomp(void) {
- return -EOPNOTSUPP;
-}
#endif
+int dlopen_libseccomp(int log_level);
+
/* This is a special value to be used where syscall filters otherwise expect errno numbers, will be
replaced with real seccomp action. */
enum {
diff --git a/src/shared/selinux-util.c b/src/shared/selinux-util.c
index 6b8e318a4c..19e0d2b488 100644
--- a/src/shared/selinux-util.c
+++ b/src/shared/selinux-util.c
@@ -5,6 +5,8 @@
#include
#include
+#include "log.h"
+
#if HAVE_SELINUX
#include
#include
@@ -20,7 +22,6 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "label.h"
-#include "log.h"
#include "path-util.h"
#include "string-util.h"
#include "time-util.h"
@@ -90,8 +91,10 @@ DLSYM_PROTOTYPE(setfilecon_raw) = NULL;
DLSYM_PROTOTYPE(setfscreatecon_raw) = NULL;
DLSYM_PROTOTYPE(setsockcreatecon_raw) = NULL;
DLSYM_PROTOTYPE(string_to_security_class) = NULL;
+#endif
-int dlopen_libselinux(void) {
+int dlopen_libselinux(int log_level) {
+#if HAVE_SELINUX
SD_ELF_NOTE_DLOPEN(
"selinux",
"Support for SELinux",
@@ -101,7 +104,7 @@ int dlopen_libselinux(void) {
return dlopen_many_sym_or_warn(
&libselinux_dl,
"libselinux.so.1",
- LOG_DEBUG,
+ log_level,
DLSYM_ARG(avc_open),
DLSYM_ARG(context_free),
DLSYM_ARG(context_new),
@@ -136,13 +139,16 @@ int dlopen_libselinux(void) {
DLSYM_ARG(setfscreatecon_raw),
DLSYM_ARG(setsockcreatecon_raw),
DLSYM_ARG(string_to_security_class));
-}
+#else
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "libselinux support is not compiled in.");
#endif
+}
bool mac_selinux_use(void) {
#if HAVE_SELINUX
if (_unlikely_(cached_use < 0)) {
- if (dlopen_libselinux() < 0)
+ if (dlopen_libselinux(LOG_DEBUG) < 0)
return (cached_use = false);
cached_use = sym_is_selinux_enabled() > 0;
@@ -162,7 +168,7 @@ bool mac_selinux_enforcing(void) {
/* If the SELinux status page has been successfully opened, retrieve the enforcing
* status over it to avoid system calls in security_getenforce(). */
- if (dlopen_libselinux() < 0)
+ if (dlopen_libselinux(LOG_DEBUG) < 0)
return false;
if (have_status_page)
@@ -188,7 +194,7 @@ static int open_label_db(void) {
struct mallinfo2 before_mallinfo = {};
int r;
- r = dlopen_libselinux();
+ r = dlopen_libselinux(LOG_DEBUG);
if (r < 0)
return r;
@@ -302,7 +308,7 @@ void mac_selinux_maybe_reload(void) {
if (!initialized)
return;
- if (dlopen_libselinux() < 0)
+ if (dlopen_libselinux(LOG_DEBUG) < 0)
return;
/* Do not use selinux_status_updated(3), cause since libselinux 3.2 selinux_check_access(3),
@@ -352,7 +358,7 @@ static int selinux_log_glue(int type, const char *fmt, ...) {
void mac_selinux_disable_logging(void) {
#if HAVE_SELINUX
/* Turn off all of SELinux' own logging, we want to do that ourselves */
- if (dlopen_libselinux() < 0)
+ if (dlopen_libselinux(LOG_DEBUG) < 0)
return;
sym_selinux_set_callback(SELINUX_CB_LOG, (const union selinux_callback) { .func_log = selinux_log_glue });
diff --git a/src/shared/selinux-util.h b/src/shared/selinux-util.h
index ab499e8c4f..f73503bc4b 100644
--- a/src/shared/selinux-util.h
+++ b/src/shared/selinux-util.h
@@ -13,8 +13,6 @@
#include "dlfcn-util.h"
-int dlopen_libselinux(void);
-
extern DLSYM_PROTOTYPE(avc_open);
extern DLSYM_PROTOTYPE(context_free);
extern DLSYM_PROTOTYPE(context_new);
@@ -54,15 +52,14 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(char*, sym_freecon, freeconp, NULL);
#else
-static inline int dlopen_libselinux(void) {
- return -EOPNOTSUPP;
-}
static inline void freeconp(char **p) {
assert(*p == NULL);
}
#endif
+int dlopen_libselinux(int log_level);
+
#define _cleanup_freecon_ _cleanup_(freeconp)
/* This accepts 0 error, like _zerook(). */
diff --git a/src/shared/shift-uid.c b/src/shared/shift-uid.c
index 2dcd5f2359..e455306be9 100644
--- a/src/shared/shift-uid.c
+++ b/src/shared/shift-uid.c
@@ -165,7 +165,7 @@ static int patch_acls(int fd, const char *name, const struct stat *st, uid_t shi
if (!inode_type_can_acl(st->st_mode))
return 0;
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return 0;
if (r < 0)
diff --git a/src/shared/tar-util.c b/src/shared/tar-util.c
index dad6337b75..97c41adba9 100644
--- a/src/shared/tar-util.c
+++ b/src/shared/tar-util.c
@@ -511,11 +511,9 @@ static int archive_entry_read_acl(
assert(c > 0);
#if HAVE_ACL
- r = dlopen_libacl();
- if (r < 0) {
- log_debug_errno(r, "Not restoring ACL data on inode as libacl is not available: %m");
+ r = dlopen_libacl(LOG_DEBUG);
+ if (r < 0)
return 0;
- }
_cleanup_(acl_freep) acl_t a = NULL;
a = sym_acl_init(c);
@@ -1480,10 +1478,8 @@ static int archive_item(
#if HAVE_ACL
if (inode_type_can_acl(sx->stx_mode)) {
- r = dlopen_libacl();
- if (r < 0)
- log_debug_errno(r, "No trying to read ACL off inode, as libacl support is not available: %m");
- else {
+ r = dlopen_libacl(LOG_DEBUG);
+ if (r >= 0) {
r = sym_acl_extended_file(FORMAT_PROC_FD_PATH(inode_fd));
if (r < 0 && !ERRNO_IS_NOT_SUPPORTED(errno))
return log_error_errno(errno, "Failed check if '%s' has ACLs: %m", path);
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 02f89c02ba..d972d39d76 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -128,7 +128,7 @@ static DLSYM_PROTOTYPE(Tss2_MU_UINT32_Marshal) = NULL;
static DLSYM_PROTOTYPE(Tss2_RC_Decode) = NULL;
-static int dlopen_tpm2_esys(void) {
+static int dlopen_tpm2_esys(int log_level) {
int r;
SD_ELF_NOTE_DLOPEN(
@@ -138,7 +138,7 @@ static int dlopen_tpm2_esys(void) {
"libtss2-esys.so.0");
r = dlopen_many_sym_or_warn(
- &libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
+ &libtss2_esys_dl, "libtss2-esys.so.0", log_level,
DLSYM_ARG(Esys_Create),
DLSYM_ARG(Esys_CreateLoaded),
DLSYM_ARG(Esys_CreatePrimary),
@@ -194,7 +194,7 @@ static int dlopen_tpm2_esys(void) {
return 0;
}
-static int dlopen_tpm2_rc(void) {
+static int dlopen_tpm2_rc(int log_level) {
SD_ELF_NOTE_DLOPEN(
"tpm",
"Support for TPM",
@@ -202,11 +202,11 @@ static int dlopen_tpm2_rc(void) {
"libtss2-rc.so.0");
return dlopen_many_sym_or_warn(
- &libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
+ &libtss2_rc_dl, "libtss2-rc.so.0", log_level,
DLSYM_ARG(Tss2_RC_Decode));
}
-static int dlopen_tpm2_mu(void) {
+static int dlopen_tpm2_mu(int log_level) {
SD_ELF_NOTE_DLOPEN(
"tpm",
"Support for TPM",
@@ -214,7 +214,7 @@ static int dlopen_tpm2_mu(void) {
"libtss2-mu.so.0");
return dlopen_many_sym_or_warn(
- &libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
+ &libtss2_mu_dl, "libtss2-mu.so.0", log_level,
DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),
DLSYM_ARG(Tss2_MU_TPM2_HANDLE_Marshal),
DLSYM_ARG(Tss2_MU_TPM2B_DIGEST_Marshal),
@@ -236,7 +236,7 @@ static int dlopen_tpm2_mu(void) {
DLSYM_ARG(Tss2_MU_UINT32_Marshal));
}
-static int dlopen_tpm2_tcti_device(void) {
+static int dlopen_tpm2_tcti_device(int log_level) {
/* The "device" TCTI is the most relevant one, let's also load it explicitly on dlopen_tpm2(), even
* if we don't resolve any symbols here. */
@@ -248,34 +248,36 @@ static int dlopen_tpm2_tcti_device(void) {
return dlopen_verbose(
&libtss2_tcti_device_dl,
- "libtss2-tcti-device.so.0");
+ "libtss2-tcti-device.so.0",
+ log_level);
}
#endif
-int dlopen_tpm2(void) {
+int dlopen_tpm2(int log_level) {
#if HAVE_TPM2
int r;
- r = dlopen_tpm2_esys();
+ r = dlopen_tpm2_esys(log_level);
if (r < 0)
return r;
- r = dlopen_tpm2_rc();
+ r = dlopen_tpm2_rc(log_level);
if (r < 0)
return r;
- r = dlopen_tpm2_mu();
+ r = dlopen_tpm2_mu(log_level);
if (r < 0)
return r;
- r = dlopen_tpm2_tcti_device();
+ r = dlopen_tpm2_tcti_device(log_level);
if (r < 0)
return r;
return 0;
#else
- return -EOPNOTSUPP;
+ return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "TPM2 support is not compiled in.");
#endif
}
@@ -874,9 +876,9 @@ int tpm2_context_new(const char *device, Tpm2Context **ret_context) {
.n_ref = 1,
};
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
if (!device) {
device = secure_getenv("SYSTEMD_TPM2_DEVICE");
@@ -3524,9 +3526,9 @@ int tpm2_calculate_pubkey_name(const TPMT_PUBLIC *public, TPM2B_NAME *ret_name)
assert(public);
assert(ret_name);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
if (public->nameAlg != TPM2_ALG_SHA256)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
@@ -3608,9 +3610,9 @@ int tpm2_calculate_nv_index_name(const TPMS_NV_PUBLIC *nvpublic, TPM2B_NAME *ret
assert(nvpublic);
assert(ret_name);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
if (nvpublic->nameAlg != TPM2_ALG_SHA256)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
@@ -3664,9 +3666,9 @@ int tpm2_calculate_policy_auth_value(TPM2B_DIGEST *digest) {
assert(digest);
assert(digest->size == SHA256_DIGEST_SIZE);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
uint8_t buf[sizeof(command)];
size_t offset = 0;
@@ -3725,9 +3727,9 @@ int tpm2_calculate_policy_signed(TPM2B_DIGEST *digest, const TPM2B_NAME *name) {
assert(digest->size == SHA256_DIGEST_SIZE);
assert(name);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
uint8_t buf[sizeof(command)];
size_t offset = 0;
@@ -3870,9 +3872,9 @@ int tpm2_calculate_policy_authorize_nv(
assert(digest);
assert(digest->size == SHA256_DIGEST_SIZE);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
uint8_t buf[sizeof(command)];
size_t offset = 0;
@@ -4005,9 +4007,9 @@ int tpm2_calculate_policy_or(const TPM2B_DIGEST *branches, size_t n_branches, TP
if (n_branches > 8)
return -E2BIG;
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "TPM2 support not installed: %m");
+ return r;
uint8_t buf[sizeof(command)];
size_t offset = 0;
@@ -4060,9 +4062,9 @@ int tpm2_calculate_policy_pcr(
assert(digest);
assert(digest->size == SHA256_DIGEST_SIZE);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
TPML_PCR_SELECTION pcr_selection;
_cleanup_free_ TPM2B_DIGEST *values = NULL;
@@ -4152,9 +4154,9 @@ int tpm2_calculate_policy_authorize(
assert(digest);
assert(digest->size == SHA256_DIGEST_SIZE);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
uint8_t buf[sizeof(command)];
size_t offset = 0;
@@ -6528,9 +6530,9 @@ int tpm2_list_devices(bool legend, bool quiet) {
_cleanup_closedir_ DIR *d = NULL;
int r;
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "TPM2 support is not installed.");
+ return r;
t = table_new("path", "device", "driver");
if (!t)
@@ -6600,9 +6602,9 @@ int tpm2_find_device_auto(char **ret) {
_cleanup_closedir_ DIR *d = NULL;
int r;
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support is not installed.");
+ return r;
d = opendir("/sys/class/tpmrm");
if (!d) {
@@ -7176,7 +7178,7 @@ static int tpm2_nvpcr_write_anchor_secret(
if (r < 0) {
if (r != -ENOENT)
return log_error_errno(r, "Failed to read '%s' file: %m", joined);
- } else if (iovec_memcmp(&existing, credential) == 0) {
+ } else if (iovec_equal(&existing, credential)) {
log_debug("Anchor secret file '%s' already matches expectations, not updating.", joined);
return 0;
} else
@@ -8460,8 +8462,8 @@ int tpm2_pcrlock_policy_from_credentials(
continue;
}
- if ((!srk || iovec_memcmp(srk, &loaded_policy.srk_handle) == 0) &&
- (!nv || iovec_memcmp(nv, &loaded_policy.nv_handle) == 0)) {
+ if ((!srk || iovec_equal(srk, &loaded_policy.srk_handle)) &&
+ (!nv || iovec_equal(nv, &loaded_policy.nv_handle))) {
*ret = TAKE_STRUCT(loaded_policy);
return 1;
}
@@ -8482,9 +8484,9 @@ int tpm2_load_public_key_file(const char *path, TPM2B_PUBLIC *ret) {
assert(path);
assert(ret);
- r = dlopen_tpm2();
+ r = dlopen_tpm2(LOG_DEBUG);
if (r < 0)
- return log_debug_errno(r, "TPM2 support not installed: %m");
+ return r;
r = read_full_file(path, &device_key_buffer, &device_key_buffer_size);
if (r < 0)
@@ -9145,15 +9147,15 @@ Tpm2Support tpm2_support_full(Tpm2Support mask) {
support |= TPM2_SUPPORT_SYSTEM;
if ((mask & (TPM2_SUPPORT_LIBRARIES|TPM2_SUPPORT_LIBTSS2_ALL)) != 0) {
- r = dlopen_tpm2_esys();
+ r = dlopen_tpm2_esys(LOG_DEBUG);
if (r >= 0)
support |= TPM2_SUPPORT_LIBTSS2_ESYS;
- r = dlopen_tpm2_rc();
+ r = dlopen_tpm2_rc(LOG_DEBUG);
if (r >= 0)
support |= TPM2_SUPPORT_LIBTSS2_RC;
- r = dlopen_tpm2_mu();
+ r = dlopen_tpm2_mu(LOG_DEBUG);
if (r >= 0)
support |= TPM2_SUPPORT_LIBTSS2_MU;
@@ -9489,7 +9491,6 @@ DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_FALLBACK(tpm2_pcr_index, int, TPM2_P
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(tpm2_pcr_index, int);
bool tpm2_nvpcr_name_is_valid(const char *name) {
- return filename_is_valid(name) &&
- string_is_safe(name) &&
+ return string_is_safe(name, STRING_FILENAME) &&
tpm2_pcr_index_from_string(name) < 0; /* don't allow nvpcrs to be name like pcrs */
}
diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h
index 5ada96e8e1..8576f278cf 100644
--- a/src/shared/tpm2-util.h
+++ b/src/shared/tpm2-util.h
@@ -39,7 +39,7 @@ static inline bool TPM2_PCR_MASK_VALID(uint32_t pcr_mask) {
#define TPM2_N_HASH_ALGORITHMS 4U
-int dlopen_tpm2(void);
+int dlopen_tpm2(int log_level);
#if HAVE_TPM2
diff --git a/src/shared/varlink-idl-common.c b/src/shared/varlink-idl-common.c
index f8f37c480c..24eec3bfcf 100644
--- a/src/shared/varlink-idl-common.c
+++ b/src/shared/varlink-idl-common.c
@@ -54,6 +54,23 @@ SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_DEFINE_FIELD_BY_TYPE(RTPRIO, ResourceLimit, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(RTTIME, ResourceLimit, SD_VARLINK_NULLABLE));
+SD_VARLINK_DEFINE_STRUCT_TYPE(
+ ExecCommand,
+ SD_VARLINK_FIELD_COMMENT("Path"),
+ SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0),
+ SD_VARLINK_FIELD_COMMENT("Arguments"),
+ SD_VARLINK_DEFINE_FIELD(arguments, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Ignore failure of the command"),
+ SD_VARLINK_DEFINE_FIELD(ignoreFailure, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Run with full privileges"),
+ SD_VARLINK_DEFINE_FIELD(privileged, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Skip setuid handling"),
+ SD_VARLINK_DEFINE_FIELD(noSetuid, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Skip environment variable expansion"),
+ SD_VARLINK_DEFINE_FIELD(noEnvExpand, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Run via shell"),
+ SD_VARLINK_DEFINE_FIELD(viaShell, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
+
SD_VARLINK_DEFINE_ENUM_TYPE(
ExecOutputType,
SD_VARLINK_DEFINE_ENUM_VALUE(inherit),
diff --git a/src/shared/varlink-idl-common.h b/src/shared/varlink-idl-common.h
index 0385752276..fdfbfc7986 100644
--- a/src/shared/varlink-idl-common.h
+++ b/src/shared/varlink-idl-common.h
@@ -8,6 +8,7 @@ extern const sd_varlink_symbol vl_type_ProcessId;
extern const sd_varlink_symbol vl_type_RateLimit;
extern const sd_varlink_symbol vl_type_ResourceLimit;
extern const sd_varlink_symbol vl_type_ResourceLimitTable;
+extern const sd_varlink_symbol vl_type_ExecCommand;
extern const sd_varlink_symbol vl_type_ExecOutputType;
extern const sd_varlink_symbol vl_type_CGroupPressureWatch;
extern const sd_varlink_symbol vl_type_ManagedOOMMode;
diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c
index 394e7b819b..422aeb6952 100644
--- a/src/shared/varlink-io.systemd.Unit.c
+++ b/src/shared/varlink-io.systemd.Unit.c
@@ -902,6 +902,76 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#UtmpMode="),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(UtmpMode, ExecUtmpMode, 0));
+SD_VARLINK_DEFINE_ENUM_TYPE(
+ KillMode,
+ SD_VARLINK_DEFINE_ENUM_VALUE(control_group),
+ SD_VARLINK_DEFINE_ENUM_VALUE(process),
+ SD_VARLINK_DEFINE_ENUM_VALUE(mixed),
+ SD_VARLINK_DEFINE_ENUM_VALUE(none));
+
+/* KillContext
+ * https://www.freedesktop.org/software/systemd/man/latest/systemd.kill.html */
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ KillContext,
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#KillMode="),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(KillMode, KillMode, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#KillSignal="),
+ SD_VARLINK_DEFINE_FIELD(KillSignal, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#RestartKillSignal="),
+ SD_VARLINK_DEFINE_FIELD(RestartKillSignal, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#SendSIGHUP="),
+ SD_VARLINK_DEFINE_FIELD(SendSIGHUP, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#SendSIGKILL="),
+ SD_VARLINK_DEFINE_FIELD(SendSIGKILL, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#FinalKillSignal="),
+ SD_VARLINK_DEFINE_FIELD(FinalKillSignal, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.kill.html#WatchdogSignal="),
+ SD_VARLINK_DEFINE_FIELD(WatchdogSignal, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
+
+/* AutomountContext
+ * https://www.freedesktop.org/software/systemd/man/latest/systemd.automount.html */
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ AutomountContext,
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.automount.html#Where="),
+ SD_VARLINK_DEFINE_FIELD(Where, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.automount.html#ExtraOptions="),
+ SD_VARLINK_DEFINE_FIELD(ExtraOptions, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.automount.html#DirectoryMode="),
+ SD_VARLINK_DEFINE_FIELD(DirectoryMode, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.automount.html#TimeoutIdleSec="),
+ SD_VARLINK_DEFINE_FIELD(TimeoutIdleUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
+/* MountContext
+ * https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html */
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ MountContext,
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#What="),
+ SD_VARLINK_DEFINE_FIELD(What, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#Where="),
+ SD_VARLINK_DEFINE_FIELD(Where, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#Type="),
+ SD_VARLINK_DEFINE_FIELD(Type, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#Options="),
+ SD_VARLINK_DEFINE_FIELD(Options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#SloppyOptions="),
+ SD_VARLINK_DEFINE_FIELD(SloppyOptions, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#LazyUnmount="),
+ SD_VARLINK_DEFINE_FIELD(LazyUnmount, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#ReadWriteOnly="),
+ SD_VARLINK_DEFINE_FIELD(ReadWriteOnly, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#ForceUnmount="),
+ SD_VARLINK_DEFINE_FIELD(ForceUnmount, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#DirectoryMode="),
+ SD_VARLINK_DEFINE_FIELD(DirectoryMode, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.mount.html#TimeoutSec="),
+ SD_VARLINK_DEFINE_FIELD(TimeoutUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Mount command"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExecMount, ExecCommand, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Unmount command"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExecUnmount, ExecCommand, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Remount command"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExecRemount, ExecCommand, SD_VARLINK_NULLABLE));
+
/* UnitContext */
static SD_VARLINK_DEFINE_STRUCT_TYPE(
Condition,
@@ -1059,7 +1129,13 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("The cgroup context of the unit"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(CGroup, CGroupContext, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The exec context of the unit"),
- SD_VARLINK_DEFINE_FIELD_BY_TYPE(Exec, ExecContext, SD_VARLINK_NULLABLE));
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Exec, ExecContext, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The kill context of the unit"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Kill, KillContext, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The automount context of the unit"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Automount, AutomountContext, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The mount context of the unit"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Mount, MountContext, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_STRUCT_TYPE(
ActivationDetails,
@@ -1133,6 +1209,45 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("The number of processes of this unit killed by systemd-oomd"),
SD_VARLINK_DEFINE_FIELD(ManagedOOMKills, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+SD_VARLINK_DEFINE_ENUM_TYPE(
+ AutomountResult,
+ SD_VARLINK_DEFINE_ENUM_VALUE(success),
+ SD_VARLINK_DEFINE_ENUM_VALUE(resources),
+ SD_VARLINK_DEFINE_ENUM_VALUE(start_limit_hit),
+ SD_VARLINK_DEFINE_ENUM_VALUE(mount_start_limit_hit),
+ SD_VARLINK_DEFINE_ENUM_VALUE(unmounted));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ AutomountRuntime,
+ SD_VARLINK_FIELD_COMMENT("Result of automount operation"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Result, AutomountResult, 0));
+
+SD_VARLINK_DEFINE_ENUM_TYPE(
+ MountResult,
+ SD_VARLINK_DEFINE_ENUM_VALUE(success),
+ SD_VARLINK_DEFINE_ENUM_VALUE(resources),
+ SD_VARLINK_DEFINE_ENUM_VALUE(timeout),
+ SD_VARLINK_DEFINE_ENUM_VALUE(exit_code),
+ SD_VARLINK_DEFINE_ENUM_VALUE(signal),
+ SD_VARLINK_DEFINE_ENUM_VALUE(core_dump),
+ SD_VARLINK_DEFINE_ENUM_VALUE(start_limit_hit),
+ SD_VARLINK_DEFINE_ENUM_VALUE(protocol));
+
+static SD_VARLINK_DEFINE_STRUCT_TYPE(
+ MountRuntime,
+ SD_VARLINK_FIELD_COMMENT("PID of the current mount/remount/etc process running"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ControlPID, ProcessId, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Result of mount operation"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Result, MountResult, 0),
+ SD_VARLINK_FIELD_COMMENT("Result of remount operation"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(ReloadResult, MountResult, 0),
+ SD_VARLINK_FIELD_COMMENT("Result of cleaning operation"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(CleanResult, MountResult, 0),
+ SD_VARLINK_FIELD_COMMENT("Reference UID"),
+ SD_VARLINK_DEFINE_FIELD(UID, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Reference GID"),
+ SD_VARLINK_DEFINE_FIELD(GID, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
static SD_VARLINK_DEFINE_STRUCT_TYPE(
UnitRuntime,
SD_VARLINK_FIELD_COMMENT("If not empty, the field contains the name of another unit that this unit follows in state"),
@@ -1190,7 +1305,11 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("Provides details about why a unit was activated"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(ActivationDetails, ActivationDetails, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The cgroup runtime of the unit"),
- SD_VARLINK_DEFINE_FIELD_BY_TYPE(CGroup, CGroupRuntime, SD_VARLINK_NULLABLE));
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(CGroup, CGroupRuntime, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The automount runtime of the unit"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Automount, AutomountRuntime, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("The mount runtime of the unit"),
+ SD_VARLINK_DEFINE_FIELD_BY_TYPE(Mount, MountRuntime, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_METHOD_FULL(
List,
@@ -1318,6 +1437,17 @@ SD_VARLINK_DEFINE_INTERFACE(
SD_VARLINK_SYMBOL_COMMENT("Exec context of a unit"),
&vl_type_ExecContext,
+ /* other contexts */
+ &vl_type_KillMode,
+ &vl_type_KillContext,
+ &vl_type_AutomountContext,
+ &vl_type_AutomountResult,
+ &vl_type_AutomountRuntime,
+ &vl_type_ExecCommand,
+ &vl_type_MountContext,
+ &vl_type_MountResult,
+ &vl_type_MountRuntime,
+
/* UnitContext enums */
&vl_type_CollectMode,
&vl_type_EmergencyAction,
diff --git a/src/shared/varlink-io.systemd.Unit.h b/src/shared/varlink-io.systemd.Unit.h
index f227dc67d6..a394071338 100644
--- a/src/shared/varlink-io.systemd.Unit.h
+++ b/src/shared/varlink-io.systemd.Unit.h
@@ -27,5 +27,8 @@ extern const sd_varlink_symbol vl_type_CPUSchedulingPolicy;
extern const sd_varlink_symbol vl_type_IOSchedulingClass;
extern const sd_varlink_symbol vl_type_NUMAPolicy;
extern const sd_varlink_symbol vl_type_MountPropagationFlag;
+extern const sd_varlink_symbol vl_type_KillMode;
+extern const sd_varlink_symbol vl_type_AutomountResult;
+extern const sd_varlink_symbol vl_type_MountResult;
extern const sd_varlink_symbol vl_type_CollectMode;
extern const sd_varlink_symbol vl_type_JobMode;
diff --git a/src/shared/vconsole-util.c b/src/shared/vconsole-util.c
index cd623bebdb..6e8c17561e 100644
--- a/src/shared/vconsole-util.c
+++ b/src/shared/vconsole-util.c
@@ -87,10 +87,10 @@ bool x11_context_is_safe(const X11Context *xc) {
assert(xc);
return
- (!xc->layout || string_is_safe(xc->layout)) &&
- (!xc->model || string_is_safe(xc->model)) &&
- (!xc->variant || string_is_safe(xc->variant)) &&
- (!xc->options || string_is_safe(xc->options));
+ (!xc->layout || string_is_safe(xc->layout, /* flags= */ 0)) &&
+ (!xc->model || string_is_safe(xc->model, /* flags= */ 0)) &&
+ (!xc->variant || string_is_safe(xc->variant, /* flags= */ 0)) &&
+ (!xc->options || string_is_safe(xc->options, /* flags= */ 0));
}
bool x11_context_equal(const X11Context *a, const X11Context *b) {
diff --git a/src/shutdown/detach-swap.c b/src/shutdown/detach-swap.c
index f064473ef7..04efbfeb36 100644
--- a/src/shutdown/detach-swap.c
+++ b/src/shutdown/detach-swap.c
@@ -36,9 +36,9 @@ int swap_list_get(const char *swaps, SwapDevice **head) {
assert(head);
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Cannot enumerate swap partitions, no libmount support.");
+ return r;
t = sym_mnt_new_table();
i = sym_mnt_new_iter(MNT_ITER_FORWARD);
diff --git a/src/ssh-generator/ssh-generator.c b/src/ssh-generator/ssh-generator.c
index bc01250a55..ae062fc58d 100644
--- a/src/ssh-generator/ssh-generator.c
+++ b/src/ssh-generator/ssh-generator.c
@@ -338,7 +338,7 @@ static int add_export_unix_socket(
return r;
log_debug("Binding SSH to AF_UNIX socket /run/host/unix-export/ssh\n"
- "→ connect via 'ssh unix/run/systemd/nspawn/unix-export/\?\?\?/ssh' from host");
+ "→ connect via 'ssh unix/run/systemd/nspawn/\?\?\?/unix-export/ssh' from host");
return 0;
}
diff --git a/src/ssh-generator/ssh-proxy.c b/src/ssh-generator/ssh-proxy.c
index fa42c5bee8..79d8ee0565 100644
--- a/src/ssh-generator/ssh-proxy.c
+++ b/src/ssh-generator/ssh-proxy.c
@@ -349,11 +349,11 @@ static int process_machine(const char *machine, const char *port) {
if (!streq_ptr(p.service, "systemd-nspawn"))
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Don't know how to SSH into '%s' container %s.", p.service, machine);
- r = runtime_directory_generic(scope, "systemd/nspawn/unix-export", &path);
+ r = runtime_directory_generic(scope, "systemd/nspawn", &path);
if (r < 0)
return log_error_errno(r, "Failed to determine runtime directory: %m");
- if (!path_extend(&path, machine, "ssh"))
+ if (!path_extend(&path, machine, "unix-export", "ssh"))
return log_oom();
r = is_socket(path);
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index 0475de3e6e..5f97f43ffb 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -565,7 +565,7 @@ static int unmerge(
bool need_to_reload;
int r;
- (void) dlopen_libmount();
+ (void) dlopen_libmount(LOG_DEBUG);
r = need_reload(image_class, hierarchies, no_reload);
if (r < 0)
@@ -2373,9 +2373,9 @@ static int merge(ImageClass image_class,
int r;
- (void) dlopen_cryptsetup();
- (void) dlopen_libblkid();
- (void) dlopen_libmount();
+ (void) dlopen_cryptsetup(LOG_DEBUG);
+ (void) dlopen_libblkid(LOG_DEBUG);
+ (void) dlopen_libmount(LOG_DEBUG);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = pidref_safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pidref);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 5c9a24b119..e5e7b412f5 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -27,7 +27,6 @@
#include "systemctl-compat-shutdown.h"
#include "systemctl-logind.h"
#include "time-util.h"
-#include "utf8.h"
char **arg_types = NULL;
char **arg_states = NULL;
@@ -969,16 +968,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case ARG_KERNEL_CMDLINE:
- if (!utf8_is_valid(optarg))
+ if (isempty(optarg)) {
+ arg_kernel_cmdline = mfree(arg_kernel_cmdline);
+ break;
+ }
+
+ if (!string_is_safe(optarg, STRING_ALLOW_GLOBS|STRING_ALLOW_BACKSLASHES|STRING_ALLOW_QUOTES))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--kernel-cmdline= argument is not valid UTF-8: %s", optarg);
- if (string_has_cc(optarg, NULL))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "--kernel-cmdline= argument contains control characters: %s", optarg);
+ "--kernel-cmdline= argument contains invalid characters: %s", optarg);
r = free_and_strdup_warn(&arg_kernel_cmdline, optarg);
if (r < 0)
- return r;
+ return r;
break;
case ARG_TIMESTAMP_STYLE:
diff --git a/src/sysupdate/meson.build b/src/sysupdate/meson.build
index 6875834e0f..68ac0e14ee 100644
--- a/src/sysupdate/meson.build
+++ b/src/sysupdate/meson.build
@@ -27,12 +27,8 @@ executables += [
'conditions' : ['ENABLE_SYSUPDATE'],
'sources' : systemd_sysupdate_sources,
'extract' : systemd_sysupdate_extract_sources,
- 'link_with' : [
- libshared,
- libshared_fdisk,
- ],
'dependencies' : [
- libfdisk,
+ libfdisk_cflags,
libopenssl,
threads,
],
diff --git a/src/sysupdate/sysupdate-partition.c b/src/sysupdate/sysupdate-partition.c
index 62fd7470cf..0b346da62d 100644
--- a/src/sysupdate/sysupdate-partition.c
+++ b/src/sysupdate/sysupdate-partition.c
@@ -77,32 +77,32 @@ int read_partition_info(
assert(t);
assert(ret);
- p = fdisk_table_get_partition(t, i);
+ p = sym_fdisk_table_get_partition(t, i);
if (!p)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
- if (fdisk_partition_is_used(p) <= 0) {
+ if (sym_fdisk_partition_is_used(p) <= 0) {
*ret = (PartitionInfo) PARTITION_INFO_NULL;
return 0; /* not found! */
}
- if (fdisk_partition_has_partno(p) <= 0 ||
- fdisk_partition_has_start(p) <= 0 ||
- fdisk_partition_has_size(p) <= 0)
+ if (sym_fdisk_partition_has_partno(p) <= 0 ||
+ sym_fdisk_partition_has_start(p) <= 0 ||
+ sym_fdisk_partition_has_size(p) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a number, position or size.");
- partno = fdisk_partition_get_partno(p);
+ partno = sym_fdisk_partition_get_partno(p);
- start = fdisk_partition_get_start(p);
- ssz = fdisk_get_sector_size(c);
+ start = sym_fdisk_partition_get_start(p);
+ ssz = sym_fdisk_get_sector_size(c);
assert(start <= UINT64_MAX / ssz);
start *= ssz;
- size = fdisk_partition_get_size(p);
+ size = sym_fdisk_partition_get_size(p);
assert(size <= UINT64_MAX / ssz);
size *= ssz;
- label = fdisk_partition_get_name(p);
+ label = sym_fdisk_partition_get_name(p);
if (!label)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a label.");
@@ -118,7 +118,7 @@ int read_partition_info(
if (r < 0)
return log_error_errno(r, "Failed to get partition flags: %m");
- r = fdisk_partition_to_string(p, c, FDISK_FIELD_DEVICE, &device);
+ r = sym_fdisk_partition_to_string(p, c, FDISK_FIELD_DEVICE, &device);
if (r != 0)
return log_error_errno(r, "Failed to get partition device name: %m");
@@ -161,18 +161,22 @@ int find_suitable_partition(
POINTER_MAY_BE_NULL(partition_type);
assert(ret);
+ r = dlopen_fdisk(LOG_DEBUG);
+ if (r < 0)
+ return r;
+
r = fdisk_new_context_at(AT_FDCWD, device, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context from '%s': %m", device);
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", device);
- r = fdisk_get_partitions(c, &t);
+ r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
- n_partitions = fdisk_table_get_nents(t);
+ n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
_cleanup_(partition_info_destroy) PartitionInfo pinfo = PARTITION_INFO_NULL;
@@ -226,11 +230,15 @@ int patch_partition(
if (change == 0) /* Nothing to do */
return 0;
+ r = dlopen_fdisk(LOG_DEBUG);
+ if (r < 0)
+ return r;
+
r = fdisk_new_context_at(AT_FDCWD, device, /* read_only= */ false, /* sector_size= */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context from '%s': %m", device);
- assert_se((fd = fdisk_get_devfd(c)) >= 0);
+ assert_se((fd = sym_fdisk_get_devfd(c)) >= 0);
/* Make sure udev doesn't read the device while we make changes (this lock is released automatically
* by the kernel when the fd is closed, i.e. when the fdisk context is freed, hence no explicit
@@ -238,21 +246,21 @@ int patch_partition(
if (flock(fd, LOCK_EX) < 0)
return log_error_errno(errno, "Failed to lock block device '%s': %m", device);
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", device);
- r = fdisk_get_partition(c, info->partno, &pa);
+ r = sym_fdisk_get_partition(c, info->partno, &pa);
if (r < 0)
return log_error_errno(r, "Failed to read partition %zu of GPT label of '%s': %m", info->partno, device);
if (change & PARTITION_LABEL) {
- r = fdisk_partition_set_name(pa, info->label);
+ r = sym_fdisk_partition_set_name(pa, info->label);
if (r < 0)
return log_error_errno(r, "Failed to update partition label: %m");
}
if (change & PARTITION_UUID) {
- r = fdisk_partition_set_uuid(pa, SD_ID128_TO_UUID_STRING(info->uuid));
+ r = sym_fdisk_partition_set_uuid(pa, SD_ID128_TO_UUID_STRING(info->uuid));
if (r < 0)
return log_error_errno(r, "Failed to update partition UUID: %m");
}
@@ -260,15 +268,15 @@ int patch_partition(
if (change & PARTITION_TYPE) {
_cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *pt = NULL;
- pt = fdisk_new_parttype();
+ pt = sym_fdisk_new_parttype();
if (!pt)
return log_oom();
- r = fdisk_parttype_set_typestr(pt, SD_ID128_TO_UUID_STRING(info->type));
+ r = sym_fdisk_parttype_set_typestr(pt, SD_ID128_TO_UUID_STRING(info->type));
if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m");
- r = fdisk_partition_set_type(pa, pt);
+ r = sym_fdisk_partition_set_type(pa, pt);
if (r < 0)
return log_error_errno(r, "Failed to update partition type: %m");
}
@@ -328,11 +336,11 @@ int patch_partition(
}
}
- r = fdisk_set_partition(c, info->partno, pa);
+ r = sym_fdisk_set_partition(c, info->partno, pa);
if (r < 0)
return log_error_errno(r, "Failed to update partition: %m");
- r = fdisk_write_disklabel(c);
+ r = sym_fdisk_write_disklabel(c);
if (r < 0)
return log_error_errno(r, "Failed to write updated partition table: %m");
diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c
index 5865a39e2f..5cd3d0fbbb 100644
--- a/src/sysupdate/sysupdate-resource.c
+++ b/src/sysupdate/sysupdate-resource.c
@@ -229,18 +229,22 @@ static int resource_load_from_blockdev(Resource *rr) {
assert(rr);
+ r = dlopen_fdisk(LOG_DEBUG);
+ if (r < 0)
+ return r;
+
r = fdisk_new_context_at(AT_FDCWD, rr->path, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context from '%s': %m", rr->path);
- if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
+ if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", rr->path);
- r = fdisk_get_partitions(c, &t);
+ r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
- n_partitions = fdisk_table_get_nents(t);
+ n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
_cleanup_(instance_metadata_destroy) InstanceMetadata extracted_fields = INSTANCE_METADATA_NULL;
_cleanup_(partition_info_destroy) PartitionInfo pinfo = PARTITION_INFO_NULL;
@@ -430,7 +434,7 @@ static int process_magic_file(
/* Even if we ignore if people have non-empty files for this file, let's nonetheless warn about it,
* so that people fix it. After all we want to retain liberty to maybe one day place some useful data
* inside it */
- if (iovec_memcmp(&IOVEC_MAKE(expected_hash, sizeof(expected_hash)), hash) != 0)
+ if (!iovec_equal(&IOVEC_MAKE(expected_hash, sizeof(expected_hash)), hash))
log_warning("Hash of best before marker file '%s' has unexpected value, proceeding anyway.", fn);
usec_t best_before;
diff --git a/src/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c
index 9c469fbe85..76b6507f9a 100644
--- a/src/sysupdate/sysupdate.c
+++ b/src/sysupdate/sysupdate.c
@@ -1202,7 +1202,9 @@ static int context_install(
}
(void) sd_notifyf(/* unset_environment=*/ false,
- "STATUS=Installing '%s'.", us->version);
+ "READY=1\n"
+ "X_SYSUPDATE_VERSION=%s\n"
+ "STATUS=Installing '%s'.", us->version, us->version);
for (size_t i = 0; i < c->n_transfers; i++) {
Instance *inst = us->instances[i];
diff --git a/src/test/meson.build b/src/test/meson.build
index 99c32cc6db..9544c166a5 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -301,7 +301,10 @@ executables += [
'sources' : files('test-dlopen-so.c'),
'dependencies' : [
libblkid_cflags,
+ libfdisk_cflags,
+ libgnutls_cflags,
libkmod_cflags,
+ libmicrohttpd_cflags,
libmount_cflags,
libp11kit_cflags,
libseccomp_cflags,
diff --git a/src/test/test-creds.c b/src/test/test-creds.c
index 5cad608093..e380550a5a 100644
--- a/src/test/test-creds.c
+++ b/src/test/test-creds.c
@@ -177,7 +177,7 @@ static void test_encrypt_decrypt_with(sd_id128_t mode, uid_t uid) {
&decrypted);
ASSERT_OK(r);
- ASSERT_EQ(iovec_memcmp(&plaintext, &decrypted), 0);
+ ASSERT_TRUE(iovec_equal(&plaintext, &decrypted));
}
static bool try_tpm2(void) {
diff --git a/src/test/test-dlopen-so.c b/src/test/test-dlopen-so.c
index a1f9212e37..d3121981cf 100644
--- a/src/test/test-dlopen-so.c
+++ b/src/test/test-dlopen-so.c
@@ -8,7 +8,9 @@
#include "cryptsetup-util.h"
#include "curl-util.h"
#include "elf-util.h"
+#include "fdisk-util.h"
#include "gcrypt-util.h"
+#include "gnutls-util.h"
#include "idn-util.h"
#include "libarchive-util.h"
#include "libaudit-util.h"
@@ -16,6 +18,7 @@
#include "libfido2-util.h"
#include "libmount-util.h"
#include "main-func.h"
+#include "microhttpd-util.h"
#include "module-util.h"
#include "pam-util.h"
#include "password-quality-util-passwdqc.h"
@@ -28,12 +31,12 @@
#include "tests.h"
#include "tpm2-util.h"
-#define ASSERT_DLOPEN(func, cond) \
- do { \
- if (cond) \
- ASSERT_OK(func()); \
- else \
- ASSERT_ERROR(func(), EOPNOTSUPP); \
+#define ASSERT_DLOPEN(func, cond) \
+ do { \
+ if (cond) \
+ ASSERT_OK(func(LOG_DEBUG)); \
+ else \
+ ASSERT_ERROR(func(LOG_DEBUG), EOPNOTSUPP); \
} while (false)
static int run(int argc, char **argv) {
@@ -49,7 +52,9 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_curl, HAVE_LIBCURL);
ASSERT_DLOPEN(dlopen_dw, HAVE_ELFUTILS);
ASSERT_DLOPEN(dlopen_elf, HAVE_ELFUTILS);
+ ASSERT_DLOPEN(dlopen_fdisk, HAVE_LIBFDISK);
ASSERT_DLOPEN(dlopen_gcrypt, HAVE_GCRYPT);
+ ASSERT_DLOPEN(dlopen_gnutls, HAVE_GNUTLS);
ASSERT_DLOPEN(dlopen_idn, HAVE_LIBIDN2);
ASSERT_DLOPEN(dlopen_libacl, HAVE_ACL);
ASSERT_DLOPEN(dlopen_libapparmor, HAVE_APPARMOR);
@@ -65,6 +70,7 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_libselinux, HAVE_SELINUX);
ASSERT_DLOPEN(dlopen_xz, HAVE_XZ);
ASSERT_DLOPEN(dlopen_lz4, HAVE_LZ4);
+ ASSERT_DLOPEN(dlopen_microhttpd, HAVE_MICROHTTPD);
ASSERT_DLOPEN(dlopen_p11kit, HAVE_P11KIT);
ASSERT_DLOPEN(dlopen_passwdqc, HAVE_PASSWDQC);
ASSERT_DLOPEN(dlopen_pcre2, HAVE_PCRE2);
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index ebd0260892..e14205bdf8 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -1633,7 +1633,7 @@ static int intro(void) {
if (path_is_read_only_fs("/sys") > 0)
return log_tests_skipped("/sys is mounted read-only");
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (r < 0)
return log_tests_skipped("libmount not available.");
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 575e2c52ed..a752b1c7cd 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -702,13 +702,13 @@ TEST(write_data_file_atomic_at) {
_cleanup_(iovec_done) struct iovec ra = {};
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
- ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
+ ASSERT_TRUE(iovec_equal(&a, &ra));
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_OK(write_data_file_atomic_at(XAT_FDROOT, "tmp/wdfa", &a, /* flags= */ 0));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
- ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
+ ASSERT_TRUE(iovec_equal(&a, &ra));
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, NULL, &a, /* flags= */ 0), EINVAL);
@@ -724,13 +724,13 @@ TEST(write_data_file_atomic_at) {
ASSERT_OK(write_data_file_atomic_at(AT_FDCWD, "wdfa", &a, /* flags= */ 0));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
- ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
+ ASSERT_TRUE(iovec_equal(&a, &ra));
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_OK(write_data_file_atomic_at(XAT_FDROOT, "tmp/wdfa", &a, /* flags= */ 0));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
- ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
+ ASSERT_TRUE(iovec_equal(&a, &ra));
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_OK_ERRNO(chdir(cwd));
@@ -739,7 +739,7 @@ TEST(write_data_file_atomic_at) {
ASSERT_OK(write_data_file_atomic_at(XAT_FDROOT, "tmp/zzz/wdfa", &a, WRITE_DATA_FILE_MKDIR_0755));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/zzz/wdfa", (char**) &ra.iov_base, &ra.iov_len));
- ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
+ ASSERT_TRUE(iovec_equal(&a, &ra));
ASSERT_OK_ERRNO(unlink("/tmp/zzz/wdfa"));
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, "/tmp/zzz", &a, /* flags= */ 0), EEXIST);
diff --git a/src/test/test-iovec-util.c b/src/test/test-iovec-util.c
index 68255071e8..bd73be1ea7 100644
--- a/src/test/test-iovec-util.c
+++ b/src/test/test-iovec-util.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "iovec-util.h"
+#include "iovec-wrapper.h"
#include "memory-util.h"
#include "tests.h"
@@ -38,6 +39,59 @@ TEST(iovec_inc) {
ASSERT_FALSE(iovec_is_set(iovec_inc(&empty, 1)));
}
+TEST(iovec_inc_many) {
+ ASSERT_TRUE(iovec_inc_many(NULL, 0, 0));
+ ASSERT_TRUE(iovec_inc_many(&(struct iovec) {}, 0, 0));
+ ASSERT_TRUE(iovec_inc_many(&(struct iovec) {}, 1, 0));
+
+ _cleanup_(iovw_done) struct iovec_wrapper iovw = {};
+ ASSERT_OK(iovw_put_iov(&iovw, &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_OK(iovw_put_iov(&iovw, &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_OK(iovw_put_iov(&iovw, &IOVEC_MAKE_STRING("ccc")));
+
+ ASSERT_FALSE(iovec_inc_many(iovw.iovec, iovw.count, 0));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[0], &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")));
+
+ ASSERT_FALSE(iovec_inc_many(iovw.iovec, iovw.count, 1));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[0], &IOVEC_MAKE_STRING("aa")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")));
+
+ ASSERT_FALSE(iovec_inc_many(iovw.iovec, iovw.count, 3));
+ ASSERT_FALSE(iovec_is_set(&iovw.iovec[0]));
+ ASSERT_NULL(iovw.iovec[0].iov_base);
+ ASSERT_EQ(iovw.iovec[0].iov_len, 0u);
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[1], &IOVEC_MAKE_STRING("bb")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")));
+
+ ASSERT_FALSE(iovec_inc_many(iovw.iovec, iovw.count, 4));
+ ASSERT_NULL(iovw.iovec[0].iov_base);
+ ASSERT_EQ(iovw.iovec[0].iov_len, 0u);
+ ASSERT_NULL(iovw.iovec[1].iov_base);
+ ASSERT_EQ(iovw.iovec[1].iov_len, 0u);
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[2], &IOVEC_MAKE_STRING("c")));
+
+ ASSERT_TRUE(iovec_inc_many(iovw.iovec, iovw.count, 1));
+ ASSERT_NULL(iovw.iovec[0].iov_base);
+ ASSERT_EQ(iovw.iovec[0].iov_len, 0u);
+ ASSERT_NULL(iovw.iovec[1].iov_base);
+ ASSERT_EQ(iovw.iovec[1].iov_len, 0u);
+ ASSERT_NULL(iovw.iovec[2].iov_base);
+ ASSERT_EQ(iovw.iovec[2].iov_len, 0u);
+
+ ASSERT_TRUE(iovec_inc_many(iovw.iovec, iovw.count, 0));
+ ASSERT_NULL(iovw.iovec[0].iov_base);
+ ASSERT_EQ(iovw.iovec[0].iov_len, 0u);
+ ASSERT_NULL(iovw.iovec[1].iov_base);
+ ASSERT_EQ(iovw.iovec[1].iov_len, 0u);
+ ASSERT_NULL(iovw.iovec[2].iov_base);
+ ASSERT_EQ(iovw.iovec[2].iov_len, 0u);
+
+ ASSERT_SIGNAL(iovec_inc_many(iovw.iovec, iovw.count, 1), SIGABRT);
+}
+
TEST(iovec_memcmp) {
struct iovec iov1 = CONST_IOVEC_MAKE_STRING("abcdef"), iov2 = IOVEC_MAKE_STRING("bcdefg"), empty = {};
diff --git a/src/test/test-iovec-wrapper.c b/src/test/test-iovec-wrapper.c
index 6764d2e78e..791a041ab8 100644
--- a/src/test/test-iovec-wrapper.c
+++ b/src/test/test-iovec-wrapper.c
@@ -97,9 +97,9 @@ TEST(iovw_put_iov) {
ASSERT_OK(iovw_put_iov(&iovw, &IOVEC_MAKE_STRING("bbb")));
ASSERT_OK(iovw_put_iov(&iovw, &IOVEC_MAKE_STRING("ccc")));
ASSERT_EQ(iovw.count, 3U);
- ASSERT_EQ(iovec_memcmp(&iovw.iovec[0], &IOVEC_MAKE_STRING("aaa")), 0);
- ASSERT_EQ(iovec_memcmp(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")), 0);
- ASSERT_EQ(iovec_memcmp(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")), 0);
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[0], &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")));
}
TEST(iovw_put_iovw) {
@@ -123,12 +123,12 @@ TEST(iovw_put_iovw) {
ASSERT_OK(iovw_put_iovw(&target, &source));
ASSERT_EQ(target.count, 6U);
- ASSERT_EQ(iovec_memcmp(&target.iovec[0], &IOVEC_MAKE_STRING("xxx")), 0);
- ASSERT_EQ(iovec_memcmp(&target.iovec[1], &IOVEC_MAKE_STRING("yyy")), 0);
- ASSERT_EQ(iovec_memcmp(&target.iovec[2], &IOVEC_MAKE_STRING("zzz")), 0);
- ASSERT_EQ(iovec_memcmp(&target.iovec[3], &IOVEC_MAKE_STRING("aaa")), 0);
- ASSERT_EQ(iovec_memcmp(&target.iovec[4], &IOVEC_MAKE_STRING("bbb")), 0);
- ASSERT_EQ(iovec_memcmp(&target.iovec[5], &IOVEC_MAKE_STRING("ccc")), 0);
+ ASSERT_TRUE(iovec_equal(&target.iovec[0], &IOVEC_MAKE_STRING("xxx")));
+ ASSERT_TRUE(iovec_equal(&target.iovec[1], &IOVEC_MAKE_STRING("yyy")));
+ ASSERT_TRUE(iovec_equal(&target.iovec[2], &IOVEC_MAKE_STRING("zzz")));
+ ASSERT_TRUE(iovec_equal(&target.iovec[3], &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_TRUE(iovec_equal(&target.iovec[4], &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_TRUE(iovec_equal(&target.iovec[5], &IOVEC_MAKE_STRING("ccc")));
/* iovw_put_iovw() does not copy data, hence the pointers must be equal */
ASSERT_PTR_EQ(target.iovec[3].iov_base, source.iovec[0].iov_base);
@@ -137,9 +137,9 @@ TEST(iovw_put_iovw) {
/* Source is unchanged */
ASSERT_EQ(source.count, 3U);
- ASSERT_EQ(iovec_memcmp(&source.iovec[0], &IOVEC_MAKE_STRING("aaa")), 0);
- ASSERT_EQ(iovec_memcmp(&source.iovec[1], &IOVEC_MAKE_STRING("bbb")), 0);
- ASSERT_EQ(iovec_memcmp(&source.iovec[2], &IOVEC_MAKE_STRING("ccc")), 0);
+ ASSERT_TRUE(iovec_equal(&source.iovec[0], &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_TRUE(iovec_equal(&source.iovec[1], &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_TRUE(iovec_equal(&source.iovec[2], &IOVEC_MAKE_STRING("ccc")));
/* Cannot pass the same objects */
ASSERT_ERROR(iovw_put_iovw(&target, &target), EINVAL);
@@ -183,9 +183,9 @@ TEST(iovw_extend_iov) {
ASSERT_OK(iovw_extend_iov(&iovw, &IOVEC_MAKE_STRING("bbb")));
ASSERT_OK(iovw_extend_iov(&iovw, &IOVEC_MAKE_STRING("ccc")));
ASSERT_EQ(iovw.count, 3U);
- ASSERT_EQ(iovec_memcmp(&iovw.iovec[0], &IOVEC_MAKE_STRING("aaa")), 0);
- ASSERT_EQ(iovec_memcmp(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")), 0);
- ASSERT_EQ(iovec_memcmp(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")), 0);
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[0], &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_TRUE(iovec_equal(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")));
}
TEST(iovw_extend_iovw) {
@@ -410,7 +410,7 @@ TEST(iovw_concat) {
ASSERT_OK(iovw_put(&iovw, (char*) "bar", 4));
ASSERT_OK(iovw_concat(&iovw, &iov));
- ASSERT_EQ(iovec_memcmp(&iov, &IOVEC_MAKE("foo\0bar\0", 8)), 0);
+ ASSERT_TRUE(iovec_equal(&iov, &IOVEC_MAKE("foo\0bar\0", 8)));
}
TEST(iovw_to_cstring) {
diff --git a/src/test/test-json.c b/src/test/test-json.c
index 1bd5d94f98..1785ef416f 100644
--- a/src/test/test-json.c
+++ b/src/test/test-json.c
@@ -1206,8 +1206,8 @@ TEST(json_iovec) {
assert_se(json_variant_unbase64_iovec(sd_json_variant_by_key(j, "nr1"), &a) >= 0);
assert_se(json_variant_unhex_iovec(sd_json_variant_by_key(j, "nr2"), &b) >= 0);
- assert_se(iovec_memcmp(&iov1, &a) == 0);
- assert_se(iovec_memcmp(&iov2, &b) == 0);
+ assert_se(iovec_equal(&iov1, &a));
+ assert_se(iovec_equal(&iov2, &b));
assert_se(iovec_memcmp(&iov2, &a) < 0);
assert_se(iovec_memcmp(&iov1, &b) > 0);
}
diff --git a/src/test/test-kexec.c b/src/test/test-kexec.c
index 2a400f75d0..a8dd397acc 100644
--- a/src/test/test-kexec.c
+++ b/src/test/test-kexec.c
@@ -104,7 +104,7 @@ TEST(gzip_round_trip) {
gz_path[] = "/tmp/test-kexec-gz.XXXXXX";
int r;
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0) {
log_tests_skipped("zlib not available");
return;
@@ -144,7 +144,7 @@ TEST(zboot_synthetic) {
zboot_path[] = "/tmp/test-kexec-zboot.XXXXXX";
int r;
- r = dlopen_zlib();
+ r = dlopen_zlib(LOG_DEBUG);
if (r < 0) {
log_tests_skipped("zlib not available");
return;
diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c
index 69d2d05b76..3e318a36c9 100644
--- a/src/test/test-load-fragment.c
+++ b/src/test/test-load-fragment.c
@@ -972,7 +972,7 @@ TEST(config_parse_log_filter_patterns) {
TEST_PATTERN("~foobar", 0, 1),
};
- if (ERRNO_IS_NOT_SUPPORTED(dlopen_pcre2()))
+ if (ERRNO_IS_NOT_SUPPORTED(dlopen_pcre2(LOG_DEBUG)))
return (void) log_tests_skipped("PCRE2 support is not available");
FOREACH_ELEMENT(test, regex_tests) {
diff --git a/src/test/test-log.c b/src/test/test-log.c
index a62f54006e..fb23776b21 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -104,9 +104,9 @@ static void test_log_format_iovec_sentinel(
for (size_t i = 0; i < n; i++)
if (i < m)
- ASSERT_EQ(iovec_memcmp(&iovec[i], &IOVEC_MAKE_STRING(v[i])), 0);
+ ASSERT_TRUE(iovec_equal(&iovec[i], &IOVEC_MAKE_STRING(v[i])));
else {
- ASSERT_EQ(iovec_memcmp(&iovec[i], &IOVEC_MAKE_STRING(expected[i - m])), 0);
+ ASSERT_TRUE(iovec_equal(&iovec[i], &IOVEC_MAKE_STRING(expected[i - m])));
free(iovec[i].iov_base);
}
@@ -122,12 +122,12 @@ static void test_log_format_iovec_sentinel(
for (size_t i = 0; i < n; i++)
if (i < m)
- ASSERT_EQ(iovec_memcmp(&iovec[i], &IOVEC_MAKE_STRING(v[i])), 0);
+ ASSERT_TRUE(iovec_equal(&iovec[i], &IOVEC_MAKE_STRING(v[i])));
else if ((i - m) % 2 == 0) {
- ASSERT_EQ(iovec_memcmp(&iovec[i], &IOVEC_MAKE_STRING(expected[(i - m) / 2])), 0);
+ ASSERT_TRUE(iovec_equal(&iovec[i], &IOVEC_MAKE_STRING(expected[(i - m) / 2])));
free(iovec[i].iov_base);
} else
- ASSERT_EQ(iovec_memcmp(&iovec[i], &IOVEC_MAKE_STRING("\n")), 0);
+ ASSERT_TRUE(iovec_equal(&iovec[i], &IOVEC_MAKE_STRING("\n")));
}
#define test_log_format_iovec_one(...) \
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index 899f8f6351..7497596cc5 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -213,7 +213,7 @@ TEST(protect_kernel_logs) {
return;
}
- r = dlopen_libmount();
+ r = dlopen_libmount(LOG_DEBUG);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
(void) log_tests_skipped("libmount support not compiled in");
return;
diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c
index 7934aa879d..d6f140e0aa 100644
--- a/src/test/test-netlink-manual.c
+++ b/src/test/test-netlink-manual.c
@@ -15,9 +15,9 @@ static int load_module(const char *mod_name) {
struct kmod_list *l;
int r;
- r = dlopen_libkmod();
+ r = dlopen_libkmod(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Failed to load libkmod: %m");
+ return r;
ctx = sym_kmod_new(NULL, NULL);
if (!ctx)
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 5707569e7e..6e07d72763 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -1495,4 +1495,146 @@ TEST(str_common_prefix) {
ASSERT_EQ(str_common_prefix("systemd-networkd", ""), 0U);
}
+TEST(string_is_safe) {
+ /* NULL is always rejected, regardless of flags. */
+ ASSERT_FALSE(string_is_safe(NULL, 0));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_ALLOW_EMPTY));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_ASCII));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_ALLOW_BACKSLASHES));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_ALLOW_QUOTES));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_ALLOW_GLOBS));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_FILENAME));
+
+ /* Baseline (flags=0): rejects empty, backslashes, quotes, globs, control chars and invalid UTF-8.
+ * Plain alphanumerics/whitespace and valid UTF-8 accepted. */
+ ASSERT_TRUE(string_is_safe("hello", 0));
+ ASSERT_TRUE(string_is_safe("hello world", 0));
+ ASSERT_TRUE(string_is_safe("über", 0)); /* valid UTF-8 allowed */
+ ASSERT_TRUE(string_is_safe("ünïcödé", 0));
+
+ ASSERT_FALSE(string_is_safe("", 0)); /* empty rejected by default */
+ ASSERT_FALSE(string_is_safe("a\\b", 0)); /* backslash rejected by default */
+ ASSERT_FALSE(string_is_safe("\"", 0)); /* double quote rejected by default */
+ ASSERT_FALSE(string_is_safe("'", 0)); /* single quote rejected by default */
+ ASSERT_FALSE(string_is_safe("*", 0)); /* glob rejected by default */
+ ASSERT_FALSE(string_is_safe("?", 0)); /* glob rejected by default */
+ ASSERT_FALSE(string_is_safe("[", 0)); /* glob rejected by default */
+ ASSERT_FALSE(string_is_safe("abc\x01", 0)); /* control char */
+ ASSERT_FALSE(string_is_safe("\t", 0));
+ ASSERT_FALSE(string_is_safe("\n", 0));
+ ASSERT_FALSE(string_is_safe("abc\x1f", 0));
+ ASSERT_FALSE(string_is_safe("abc\x7f", 0)); /* DEL */
+ ASSERT_FALSE(string_is_safe("ab\xc3\x28", 0)); /* invalid UTF-8 continuation */
+ ASSERT_FALSE(string_is_safe("\xff", 0)); /* not valid UTF-8 */
+
+ /* STRING_ALLOW_EMPTY. */
+ ASSERT_TRUE(string_is_safe("", STRING_ALLOW_EMPTY));
+ ASSERT_TRUE(string_is_safe("x", STRING_ALLOW_EMPTY));
+ ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_EMPTY));
+ ASSERT_FALSE(string_is_safe(NULL, STRING_ALLOW_EMPTY));
+
+ /* STRING_ASCII: high bytes rejected, low ASCII accepted, control chars still rejected.
+ * Empty is still rejected by default; backslashes/quotes/globs still rejected by default. */
+ ASSERT_TRUE(string_is_safe("hello", STRING_ASCII));
+ ASSERT_TRUE(string_is_safe("hello world 123!@#$%^&()", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("über", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("\x80", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("\xff", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("abc\x01", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("abc\x7f", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("a\\b", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("a\"b", STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("a*b", STRING_ASCII));
+
+ /* STRING_ALLOW_BACKSLASHES: backslashes allowed, quotes/globs still rejected. */
+ ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_BACKSLASHES));
+ ASSERT_TRUE(string_is_safe("hello world", STRING_ALLOW_BACKSLASHES));
+ ASSERT_TRUE(string_is_safe("\\", STRING_ALLOW_BACKSLASHES));
+ ASSERT_TRUE(string_is_safe("a\\b", STRING_ALLOW_BACKSLASHES));
+ ASSERT_TRUE(string_is_safe("foo\\", STRING_ALLOW_BACKSLASHES));
+ ASSERT_TRUE(string_is_safe("\\foo", STRING_ALLOW_BACKSLASHES));
+ ASSERT_TRUE(string_is_safe("foo\\nbar", STRING_ALLOW_BACKSLASHES)); /* literal backslash, not newline */
+ ASSERT_FALSE(string_is_safe("\"", STRING_ALLOW_BACKSLASHES)); /* quotes still rejected */
+ ASSERT_FALSE(string_is_safe("*", STRING_ALLOW_BACKSLASHES)); /* globs still rejected */
+
+ /* STRING_ALLOW_QUOTES: quotes allowed, backslashes/globs still rejected. */
+ ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("hello world", STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("\"", STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("'", STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("hello\"world", STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("it's", STRING_ALLOW_QUOTES));
+ ASSERT_FALSE(string_is_safe("a\\b", STRING_ALLOW_QUOTES)); /* backslashes still rejected */
+ ASSERT_FALSE(string_is_safe("*", STRING_ALLOW_QUOTES)); /* globs still rejected */
+
+ /* STRING_ALLOW_GLOBS: globs allowed, backslashes/quotes still rejected. */
+ ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("ab]c", STRING_ALLOW_GLOBS)); /* ']' is not in GLOB_CHARS anyway */
+ ASSERT_TRUE(string_is_safe("*", STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("?", STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("[", STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("foo*bar", STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("foo?bar", STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("foo[bar", STRING_ALLOW_GLOBS));
+ ASSERT_FALSE(string_is_safe("\"", STRING_ALLOW_GLOBS)); /* quotes still rejected */
+ ASSERT_FALSE(string_is_safe("a\\b", STRING_ALLOW_GLOBS)); /* backslashes still rejected */
+
+ /* STRING_FILENAME: rejects empty, ".", "..", and strings with '/'. */
+ ASSERT_TRUE(string_is_safe("hello", STRING_FILENAME));
+ ASSERT_TRUE(string_is_safe("hello.txt", STRING_FILENAME));
+ ASSERT_TRUE(string_is_safe("...", STRING_FILENAME));
+ ASSERT_TRUE(string_is_safe(".hidden", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe(".", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("..", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("/", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("/foo", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("foo/bar", STRING_FILENAME));
+
+ /* Pairwise combinations. */
+ ASSERT_TRUE(string_is_safe("", STRING_ALLOW_EMPTY | STRING_ASCII));
+ ASSERT_FALSE(string_is_safe("über", STRING_ALLOW_EMPTY | STRING_ASCII));
+ ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_EMPTY | STRING_ASCII));
+
+ ASSERT_TRUE(string_is_safe("ab\"cd", STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("ab*cd", STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS));
+ ASSERT_TRUE(string_is_safe("ab'*cd", STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS));
+ ASSERT_FALSE(string_is_safe("ab\\cd", STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS)); /* backslash still rejected */
+
+ ASSERT_TRUE(string_is_safe("hello.txt", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("", STRING_FILENAME));
+ ASSERT_FALSE(string_is_safe("foo/bar", STRING_FILENAME));
+
+ ASSERT_TRUE(string_is_safe("foo?bar", STRING_ASCII | STRING_ALLOW_GLOBS));
+ ASSERT_FALSE(string_is_safe("foo\"bar", STRING_ASCII | STRING_ALLOW_GLOBS)); /* quotes still rejected */
+ ASSERT_FALSE(string_is_safe("über", STRING_ASCII | STRING_ALLOW_GLOBS));
+
+ ASSERT_TRUE(string_is_safe("foo\\bar", STRING_ALLOW_BACKSLASHES));
+ ASSERT_FALSE(string_is_safe("foo\"bar", STRING_ALLOW_BACKSLASHES)); /* quotes still rejected */
+ ASSERT_FALSE(string_is_safe("foo*bar", STRING_ALLOW_BACKSLASHES)); /* globs still rejected */
+ ASSERT_TRUE(string_is_safe("foo\\\"bar", STRING_ALLOW_BACKSLASHES | STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("foo\\bar", STRING_ALLOW_BACKSLASHES | STRING_ALLOW_QUOTES));
+ ASSERT_TRUE(string_is_safe("foo\"bar", STRING_ALLOW_BACKSLASHES | STRING_ALLOW_QUOTES));
+
+ /* All allow flags combined: only baseline (control chars, invalid UTF-8) and STRING_FILENAME apply. */
+ StringSafeFlags all = STRING_ALLOW_EMPTY | STRING_ASCII | STRING_ALLOW_BACKSLASHES | STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS | STRING_FILENAME;
+ ASSERT_TRUE(string_is_safe("hello.txt", all));
+ ASSERT_TRUE(string_is_safe("foo-bar_baz.conf", all));
+ ASSERT_TRUE(string_is_safe("a", all));
+ ASSERT_TRUE(string_is_safe("foo\\bar", all)); /* backslash allowed */
+ ASSERT_TRUE(string_is_safe("foo\"bar", all)); /* quote allowed */
+ ASSERT_TRUE(string_is_safe("foo'bar", all)); /* quote allowed */
+ ASSERT_TRUE(string_is_safe("foo*bar", all)); /* glob allowed */
+ ASSERT_TRUE(string_is_safe("foo?bar", all)); /* glob allowed */
+ ASSERT_TRUE(string_is_safe("foo[bar", all)); /* glob allowed */
+ ASSERT_FALSE(string_is_safe("", all)); /* fails STRING_FILENAME */
+ ASSERT_FALSE(string_is_safe("über", all)); /* fails STRING_ASCII */
+ ASSERT_FALSE(string_is_safe("foo/bar", all)); /* fails STRING_FILENAME */
+ ASSERT_FALSE(string_is_safe(".", all)); /* fails STRING_FILENAME */
+ ASSERT_FALSE(string_is_safe("..", all)); /* fails STRING_FILENAME */
+ ASSERT_FALSE(string_is_safe("foo\x01""bar", all)); /* fails baseline control-char check */
+ ASSERT_FALSE(string_is_safe(NULL, all));
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);
diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c
index a6164f2677..78e2d234ab 100644
--- a/src/test/test-tpm2.c
+++ b/src/test/test-tpm2.c
@@ -1271,7 +1271,7 @@ static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) {
&srk,
&unsealed_secret) >= 0);
- assert_se(iovec_memcmp(&secret, &unsealed_secret) == 0);
+ assert_se(iovec_equal(&secret, &unsealed_secret));
}
static void check_seal_unseal(Tpm2Context *c) {
diff --git a/src/test/test-varlink-idl-unit.c b/src/test/test-varlink-idl-unit.c
index f840ff89da..2f4bb1c9e9 100644
--- a/src/test/test-varlink-idl-unit.c
+++ b/src/test/test-varlink-idl-unit.c
@@ -1,7 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "automount.h"
#include "cgroup.h"
#include "ioprio-util.h"
+#include "kill.h"
+#include "mount.h"
#include "numa-util.h"
#include "process-util.h"
#include "tests.h"
@@ -40,6 +43,9 @@ TEST(unit_enums_idl) {
test_enum_to_string_name("slave", &vl_type_MountPropagationFlag);
test_enum_to_string_name("private", &vl_type_MountPropagationFlag);
+ /* KillContext enums */
+ TEST_IDL_ENUM(KillMode, kill_mode, vl_type_KillMode);
+
/* CGroupContext enums */
TEST_IDL_ENUM(CGroupDevicePolicy, cgroup_device_policy, vl_type_CGroupDevicePolicy);
TEST_IDL_ENUM(ManagedOOMMode, managed_oom_mode, vl_type_ManagedOOMMode);
@@ -47,6 +53,12 @@ TEST(unit_enums_idl) {
TEST_IDL_ENUM(CGroupPressureWatch, cgroup_pressure_watch, vl_type_CGroupPressureWatch);
TEST_IDL_ENUM(CGroupController, cgroup_controller, vl_type_CGroupController);
+ /* AutomountRuntime enums */
+ TEST_IDL_ENUM(AutomountResult, automount_result, vl_type_AutomountResult);
+
+ /* MountRuntime enums */
+ TEST_IDL_ENUM(MountResult, mount_result, vl_type_MountResult);
+
/* UnitContext enums */
TEST_IDL_ENUM(CollectMode, collect_mode, vl_type_CollectMode);
TEST_IDL_ENUM(EmergencyAction, emergency_action, vl_type_EmergencyAction);
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 7e41f69299..9975ffca39 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1247,7 +1247,7 @@ static int parse_acl_cond_exec(
assert(cond_exec);
assert(ret);
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
@@ -1366,7 +1366,7 @@ static int path_set_acl(
assert(c);
- r = dlopen_libacl();
+ r = dlopen_libacl(LOG_DEBUG);
if (r < 0)
return r;
diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c
index 6a31f9c4c8..ba7a7fe5f5 100644
--- a/src/udev/scsi_id/scsi_id.c
+++ b/src/udev/scsi_id/scsi_id.c
@@ -15,6 +15,7 @@
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
+#include "parse-util.h"
#include "scsi_id.h"
#include "string-util.h"
#include "strv.h"
@@ -234,7 +235,7 @@ static void help(void) {
static int set_options(int argc, char **argv,
char *maj_min_dev) {
- int option;
+ int option, r;
/*
* optind is a global extern used by getopt. Since we can call
@@ -279,7 +280,11 @@ static int set_options(int argc, char **argv,
break;
case 's':
- sg_version = atoi(optarg);
+ r = safe_atoi(optarg, &sg_version);
+ if (r < 0)
+ return log_error_errno(r,
+ "Invalid SG version '%s'",
+ optarg);
if (sg_version < 3 || sg_version > 4)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown SG version '%s'",
diff --git a/src/udev/test-udev-rule-runner.c b/src/udev/test-udev-rule-runner.c
index 34755b1f8b..1acbe2f090 100644
--- a/src/udev/test-udev-rule-runner.c
+++ b/src/udev/test-udev-rule-runner.c
@@ -103,7 +103,7 @@ static int run(int argc, char *argv[]) {
/* Let's make sure the test runs with selinux assumed disabled. */
#if HAVE_SELINUX
- if (dlopen_libselinux() >= 0)
+ if (dlopen_libselinux(LOG_DEBUG) >= 0)
sym_fini_selinuxmnt();
#endif
mac_selinux_retest();
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index edadb71c7a..ca40b62d78 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -513,7 +513,7 @@ static int builtin_blkid(UdevEvent *event, int argc, char *argv[]) {
{}
};
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_DEBUG);
if (r < 0)
return log_device_debug_errno(dev, r, "blkid not available: %m");
diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
index 61250b7072..cfbea9d981 100644
--- a/src/udev/udev-builtin-usb_id.c
+++ b/src/udev/udev-builtin-usb_id.c
@@ -22,6 +22,9 @@
static void set_usb_iftype(char *to, int if_class_num, size_t len) {
const char *type = "generic";
+ assert(to);
+ assert(len > 0);
+
switch (if_class_num) {
case 1:
type = "audio";
@@ -71,6 +74,8 @@ static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len
int type_num = 0;
const char *type = "generic";
+ assert(to);
+
if (safe_atoi(from, &type_num) >= 0)
switch (type_num) {
case 1: /* RBC devices */
@@ -98,6 +103,8 @@ static void set_scsi_type(char *to, const char *from, size_t len) {
unsigned type_num;
const char *type = "generic";
+ assert(to);
+
if (safe_atou(from, &type_num) >= 0)
switch (type_num) {
case 0:
@@ -143,6 +150,10 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
uint8_t iInterface;
} _packed_;
+ assert(dev);
+ assert(ifs_str);
+ assert(len >= 2);
+
r = sd_device_get_syspath(dev, &syspath);
if (r < 0)
return r;
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 840febbd42..593eee89b8 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -58,11 +58,11 @@ int run_udevd(int argc, char *argv[]) {
return log_error_errno(r, "Failed to create /run/udev: %m");
/* Load some shared libraries before we fork any workers */
- (void) dlopen_libacl();
- (void) dlopen_libblkid();
- (void) dlopen_libkmod();
- (void) dlopen_libmount();
- (void) dlopen_tpm2();
+ (void) dlopen_libacl(LOG_DEBUG);
+ (void) dlopen_libblkid(LOG_DEBUG);
+ (void) dlopen_libkmod(LOG_DEBUG);
+ (void) dlopen_libmount(LOG_DEBUG);
+ (void) dlopen_tpm2(LOG_DEBUG);
if (arg_daemonize) {
pid_t pid;
diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
index 6f492bc9ba..03d475e5e7 100755
--- a/src/ukify/ukify.py
+++ b/src/ukify/ukify.py
@@ -1401,7 +1401,7 @@ def make_uki(opts: UkifyConfig) -> None:
if opts.hwids is not None:
hwids = parse_hwid_dir(Path(opts.hwids))
else:
- hwids_dir = Path(f'/tmp/s/usr/lib/systemd/boot/hwids/{opts.efi_arch}')
+ hwids_dir = Path(f'/usr/lib/systemd/boot/hwids/{opts.efi_arch}')
if hwids_dir.is_dir():
print(f'Automatically building .hwids section from {hwids_dir}', file=sys.stderr)
hwids = parse_hwid_dir(hwids_dir)
diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c
index 8da35172c5..6b4371aa50 100644
--- a/src/userdb/userdbctl.c
+++ b/src/userdb/userdbctl.c
@@ -1072,13 +1072,9 @@ static int verb_display_services(int argc, char *argv[], uintptr_t _data, void *
(void) table_set_sort(t, (size_t) 0);
FOREACH_DIRENT(de, d, return -errno) {
- _cleanup_free_ char *j = NULL, *no = NULL;
+ _cleanup_free_ char *no = NULL;
_cleanup_close_ int fd = -EBADF;
- j = path_join("/run/systemd/userdb/", de->d_name);
- if (!j)
- return log_oom();
-
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0)
return log_error_errno(errno, "Failed to allocate AF_UNIX/SOCK_STREAM socket: %m");
diff --git a/src/validatefs/validatefs.c b/src/validatefs/validatefs.c
index 1106eaf1fe..44a58387f0 100644
--- a/src/validatefs/validatefs.c
+++ b/src/validatefs/validatefs.c
@@ -291,9 +291,9 @@ static int validate_gpt_metadata_one(sd_device *d, const char *path, const Valid
assert(d);
assert(f);
- r = dlopen_libblkid();
+ r = dlopen_libblkid(LOG_ERR);
if (r < 0)
- return log_error_errno(r, "Cannot validate GPT constraints, refusing.");
+ return r;
_cleanup_close_ int block_fd = sd_device_open(d, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (block_fd < 0)
diff --git a/src/veritysetup/meson.build b/src/veritysetup/meson.build
index cc9ac80a61..21432d41f1 100644
--- a/src/veritysetup/meson.build
+++ b/src/veritysetup/meson.build
@@ -8,7 +8,7 @@ executables += [
libexec_template + {
'name' : 'systemd-veritysetup',
'sources' : files('veritysetup.c'),
- 'dependencies' : libcryptsetup,
+ 'dependencies' : libcryptsetup_cflags,
},
generator_template + {
'name' : 'systemd-veritysetup-generator',
diff --git a/src/veritysetup/veritysetup.c b/src/veritysetup/veritysetup.c
index 4a244ae83d..b5d57fd1fe 100644
--- a/src/veritysetup/veritysetup.c
+++ b/src/veritysetup/veritysetup.c
@@ -221,9 +221,6 @@ static int parse_options(const char *options) {
arg_hash_offset = off;
} else if ((val = startswith(word, "salt="))) {
- if (!string_is_safe(val))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "salt= is not valid.");
-
if (isempty(val)) {
arg_salt = mfree(arg_salt);
arg_salt_size = 32;
@@ -379,13 +376,13 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
return log_error_errno(r, "Failed to decode root hash signature data from udev data device: %m");
}
- r = crypt_init(&cd, verity_device);
+ r = sym_crypt_init(&cd, verity_device);
if (r < 0)
return log_error_errno(r, "Failed to open verity device %s: %m", verity_device);
cryptsetup_enable_logging(cd);
- status = crypt_status(cd, volume);
+ status = sym_crypt_status(cd, volume);
if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
log_info("Volume %s already active.", volume);
return 0;
@@ -399,7 +396,7 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
.fec_roots = arg_fec_roots,
};
- r = crypt_load(cd, CRYPT_VERITY, &p);
+ r = sym_crypt_load(cd, CRYPT_VERITY, &p);
if (r < 0)
return log_error_errno(r, "Failed to load verity superblock: %m");
} else {
@@ -419,28 +416,28 @@ static int verb_attach(int argc, char *argv[], uintptr_t _data, void *userdata)
.flags = CRYPT_VERITY_NO_HEADER,
};
- r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, arg_uuid, NULL, 0, &p);
+ r = sym_crypt_format(cd, CRYPT_VERITY, NULL, NULL, arg_uuid, NULL, 0, &p);
if (r < 0)
return log_error_errno(r, "Failed to format verity superblock: %m");
}
- r = crypt_set_data_device(cd, data_device);
+ r = sym_crypt_set_data_device(cd, data_device);
if (r < 0)
return log_error_errno(r, "Failed to configure data device: %m");
if (arg_root_hash_signature_size > 0) {
- r = crypt_activate_by_signed_key(cd, volume, rh, rh_size, arg_root_hash_signature, arg_root_hash_signature_size, arg_activate_flags);
+ r = sym_crypt_activate_by_signed_key(cd, volume, rh, rh_size, arg_root_hash_signature, arg_root_hash_signature_size, arg_activate_flags);
if (r < 0) {
log_info_errno(r, "Unable to activate verity device '%s' with root hash signature (%m), retrying without.", volume);
- r = crypt_activate_by_volume_key(cd, volume, rh, rh_size, arg_activate_flags);
+ r = sym_crypt_activate_by_volume_key(cd, volume, rh, rh_size, arg_activate_flags);
if (r < 0)
return log_error_errno(r, "Failed to activate verity device '%s' both with and without root hash signature: %m", volume);
log_info("Activation of verity device '%s' succeeded without root hash signature.", volume);
}
} else
- r = crypt_activate_by_volume_key(cd, volume, rh, rh_size, arg_activate_flags);
+ r = sym_crypt_activate_by_volume_key(cd, volume, rh, rh_size, arg_activate_flags);
if (r < 0)
return log_error_errno(r, "Failed to set up verity device '%s': %m", volume);
@@ -463,7 +460,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
if (!filename_is_valid(volume))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
- r = crypt_init_by_name(&cd, volume);
+ r = sym_crypt_init_by_name(&cd, volume);
if (r == -ENODEV) {
log_info("Volume %s 'already' inactive.", volume);
return 0;
@@ -473,7 +470,7 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
cryptsetup_enable_logging(cd);
- r = crypt_deactivate(cd, volume);
+ r = sym_crypt_deactivate(cd, volume);
if (r < 0)
return log_error_errno(r, "Failed to deactivate volume '%s': %m", volume);
@@ -481,12 +478,16 @@ static int verb_detach(int argc, char *argv[], uintptr_t _data, void *userdata)
}
static int run(int argc, char *argv[]) {
+ int r;
+
if (argv_looks_like_help(argc, argv))
return help();
log_setup();
- cryptsetup_enable_logging(NULL);
+ r = dlopen_cryptsetup(LOG_ERR);
+ if (r < 0)
+ return r;
umask(0022);
diff --git a/src/version/meson.build b/src/version/meson.build
index 54db791ccf..a0b03f41a6 100644
--- a/src/version/meson.build
+++ b/src/version/meson.build
@@ -14,3 +14,4 @@ version_h = custom_target('version',
])
version_include = include_directories('.')
userspace_sources += [version_h]
+generated_sources += [version_h]
diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c
index 5c70809e47..8ccd631762 100644
--- a/src/vmspawn/vmspawn.c
+++ b/src/vmspawn/vmspawn.c
@@ -25,8 +25,6 @@
#include "bus-locator.h"
#include "bus-util.h"
#include "capability-util.h"
-#include "chase.h"
-#include "chattr-util.h"
#include "common-signal.h"
#include "copy.h"
#include "discover-image.h"
@@ -159,6 +157,10 @@ static bool arg_firmware_describe = false;
static Set *arg_firmware_features_include = NULL;
static Set *arg_firmware_features_exclude = NULL;
static char *arg_forward_journal = NULL;
+static uint64_t arg_forward_journal_max_use = UINT64_MAX;
+static uint64_t arg_forward_journal_keep_free = UINT64_MAX;
+static uint64_t arg_forward_journal_max_file_size = UINT64_MAX;
+static uint64_t arg_forward_journal_max_files = UINT64_MAX;
static int arg_register = -1;
static bool arg_keep_unit = false;
static sd_id128_t arg_uuid = {};
@@ -844,6 +846,30 @@ static int parse_argv(int argc, char *argv[]) {
return r;
break;
+ OPTION_LONG("forward-journal-max-use", "BYTES", "Maximum disk space for forwarded journal"):
+ r = parse_size(arg, 1024, &arg_forward_journal_max_use);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-max-use= value: %s", optarg);
+ break;
+
+ OPTION_LONG("forward-journal-keep-free", "BYTES", "Minimum disk space to keep free"):
+ r = parse_size(arg, 1024, &arg_forward_journal_keep_free);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-keep-free= value: %s", optarg);
+ break;
+
+ OPTION_LONG("forward-journal-max-file-size", "BYTES", "Maximum size of individual journal files"):
+ r = parse_size(arg, 1024, &arg_forward_journal_max_file_size);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-max-file-size= value: %s", optarg);
+ break;
+
+ OPTION_LONG("forward-journal-max-files", "N", "Maximum number of journal files to keep"):
+ r = safe_atou64(arg, &arg_forward_journal_max_files);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --forward-journal-max-files= value: %s", optarg);
+ break;
+
OPTION_LONG("pass-ssh-key", "BOOL", "Create an SSH key to access the VM"):
r = parse_boolean_argument("--pass-ssh-key=", arg, &arg_pass_ssh_key);
if (r < 0)
@@ -851,7 +877,12 @@ static int parse_argv(int argc, char *argv[]) {
break;
OPTION_LONG("ssh-key-type", "TYPE", "Choose what type of SSH key to pass"):
- if (!string_is_safe(arg))
+ if (isempty(arg)) {
+ arg_ssh_key_type = mfree(arg_ssh_key_type);
+ break;
+ }
+
+ if (!string_is_safe(arg, STRING_ALLOW_GLOBS))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid value for --ssh-key-type=: %s", arg);
r = free_and_strdup_warn(&arg_ssh_key_type, arg);
@@ -918,6 +949,12 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_ram_slots > 0 && arg_ram_max == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Memory hotplug slots require a maximum RAM size");
+ if ((arg_forward_journal_max_use != UINT64_MAX ||
+ arg_forward_journal_keep_free != UINT64_MAX ||
+ arg_forward_journal_max_file_size != UINT64_MAX ||
+ arg_forward_journal_max_files != UINT64_MAX) && !arg_forward_journal)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--forward-journal-max-use=/--forward-journal-keep-free=/--forward-journal-max-file-size=/--forward-journal-max-files= require --forward-journal=.");
+
if (arg_ephemeral && arg_extra_drives.n_drives > 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --ephemeral with --extra-drive=");
@@ -1581,58 +1618,6 @@ static int start_tpm(
return 0;
}
-static int start_systemd_journal_remote(
- const char *scope,
- unsigned port,
- const char *sd_socket_activate,
- char **ret_listen_address,
- PidRef *ret_pidref) {
-
- int r;
-
- assert(scope);
- assert(sd_socket_activate);
-
- _cleanup_free_ char *scope_prefix = NULL;
- r = unit_name_to_prefix(scope, &scope_prefix);
- if (r < 0)
- return log_error_errno(r, "Failed to strip .scope suffix from scope: %m");
-
- _cleanup_free_ char *listen_address = NULL;
- if (asprintf(&listen_address, "vsock:2:%u", port) < 0)
- return log_oom();
-
- _cleanup_free_ char *sd_journal_remote = NULL;
- r = find_executable_full(
- "systemd-journal-remote",
- /* root= */ NULL,
- STRV_MAKE(LIBEXECDIR),
- /* use_path_envvar= */ true, /* systemd-journal-remote should be installed in
- * LIBEXECDIR, but for supporting fancy setups. */
- &sd_journal_remote,
- /* ret_fd= */ NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to find systemd-journal-remote binary: %m");
-
- _cleanup_strv_free_ char **argv = strv_new(
- sd_socket_activate,
- "--listen", listen_address,
- sd_journal_remote,
- "--output", arg_forward_journal,
- "--split-mode", endswith(arg_forward_journal, ".journal") ? "none" : "host");
- if (!argv)
- return log_oom();
-
- r = fork_notify(argv, ret_pidref);
- if (r < 0)
- return r;
-
- if (ret_listen_address)
- *ret_listen_address = TAKE_PTR(listen_address);
-
- return 0;
-}
-
static int discover_root(char **ret) {
int r;
_cleanup_(dissected_image_unrefp) DissectedImage *image = NULL;
@@ -2656,13 +2641,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
return log_oom();
/* Create our runtime directory. We need this for the QMP varlink control socket, the QEMU
- * config file, TPM state, virtiofsd sockets, runtime mounts, and SSH key material.
- *
- * Use runtime_directory() (not _generic()) so that when vmspawn runs in a systemd service
- * with RuntimeDirectory= set, we pick up $RUNTIME_DIRECTORY and place our stuff into the
- * directory the service manager prepared for us. When the env var is unset, we fall back
- * to /run/systemd/vmspawn// (or the $XDG_RUNTIME_DIR equivalent in user scope)
- * and take care of creation and destruction ourselves. */
+ * config file, TPM state, virtiofsd sockets, runtime mounts, and SSH key material. */
_cleanup_free_ char *runtime_dir = NULL, *runtime_dir_suffix = NULL;
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir_destroy = NULL;
@@ -2670,27 +2649,14 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
if (!runtime_dir_suffix)
return log_oom();
- r = runtime_directory(arg_runtime_scope, runtime_dir_suffix, &runtime_dir);
+ r = runtime_directory_make(arg_runtime_scope, runtime_dir_suffix, &runtime_dir, &runtime_dir_destroy);
if (r < 0)
- return log_error_errno(r, "Failed to determine runtime directory: %m");
- if (r > 0) {
- /* $RUNTIME_DIRECTORY was not set, so we got the fallback path and need to create and
- * clean up the directory ourselves.
- *
- * If a previous vmspawn instance was killed without cleanup (e.g. SIGKILL), the directory may
- * already exist with stale contents. This is harmless: varlink's sockaddr_un_unlink() removes stale
- * sockets before bind(), and other files (QEMU config, SSH keys) are created fresh. This matches
- * nspawn's approach of not proactively cleaning stale runtime directories. */
- r = mkdir_p(runtime_dir, 0755);
- if (r < 0)
- return log_error_errno(r, "Failed to create runtime directory '%s': %m", runtime_dir);
+ return log_error_errno(r, "Failed to create runtime directory: %m");
- runtime_dir_destroy = strdup(runtime_dir);
- if (!runtime_dir_destroy)
- return log_oom();
- }
- /* When $RUNTIME_DIRECTORY is set the service manager created the directory for us and
- * will destroy it (or preserve it, per RuntimeDirectoryPreserve=) when the service stops. */
+ /* If a previous vmspawn instance was killed without cleanup (e.g. SIGKILL), the directory may
+ * already exist with stale contents. This is harmless: varlink's sockaddr_un_unlink() removes stale
+ * sockets before bind(), and other files (QEMU config, SSH keys) are created fresh. This matches
+ * nspawn's approach of not proactively cleaning stale runtime directories. */
log_debug("Using runtime directory: %s", runtime_dir);
@@ -3402,25 +3368,21 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
if (arg_forward_journal) {
_cleanup_free_ char *listen_address = NULL;
-
- ChaseFlags chase_flags = CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY;
- if (endswith(arg_forward_journal, ".journal"))
- chase_flags |= CHASE_PARENT;
-
- _cleanup_close_ int journal_fd = -EBADF;
- r = chase(arg_forward_journal, /* root= */ NULL, chase_flags, /* ret_path= */ NULL, &journal_fd);
- if (r < 0)
- return log_error_errno(r, "Failed to create journal directory for '%s': %m", arg_forward_journal);
-
- r = chattr_fd(journal_fd, FS_NOCOW_FL, FS_NOCOW_FL);
- if (r < 0)
- log_debug_errno(r, "Failed to set NOCOW flag on journal directory for '%s', ignoring: %m", arg_forward_journal);
+ if (asprintf(&listen_address, "vsock:2:%u", child_cid) < 0)
+ return log_oom();
if (!GREEDY_REALLOC(children, n_children + 1))
return log_oom();
_cleanup_(fork_notify_terminate) PidRef child = PIDREF_NULL;
- r = start_systemd_journal_remote(unit, child_cid, sd_socket_activate, &listen_address, &child);
+ r = fork_journal_remote(
+ listen_address,
+ arg_forward_journal,
+ arg_forward_journal_max_use,
+ arg_forward_journal_keep_free,
+ arg_forward_journal_max_file_size,
+ arg_forward_journal_max_files,
+ &child);
if (r < 0)
return r;
@@ -4001,6 +3963,10 @@ static int verify_arguments(void) {
log_warning("--grow-image has no effect with --image-disk-type=scsi-cd (CD-ROMs are read-only).");
}
+ if (arg_grow_image && arg_image_format == IMAGE_FORMAT_QCOW2)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--grow-image is not supported for qcow2 images, use 'qemu-img resize FILE SIZE'.");
+
return 0;
}
diff --git a/test/test-network/conf/25-sysctl.network b/test/test-network/conf/25-sysctl.network
index dcc4f0d293..c0c709c32c 100644
--- a/test/test-network/conf/25-sysctl.network
+++ b/test/test-network/conf/25-sysctl.network
@@ -12,5 +12,6 @@ IPv4ProxyARPPrivateVLAN=yes
IPv6ProxyNDP=yes
IPv6AcceptRA=no
IPv4AcceptLocal=yes
+IPv4SrcValidMark=yes
IPv4ReversePathFilter=no
MulticastIGMPVersion=v1
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 03404e6cbe..0db4830848 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -931,6 +931,13 @@ def get_dbus_link_path(link):
out = out.decode()
return out[:-1].split('"')[1]
+def get_dhcp_server_property(link, prop):
+ link_path = get_dbus_link_path(link)
+
+ out = subprocess.check_output(['busctl', 'get-property', 'org.freedesktop.network1',
+ link_path, 'org.freedesktop.network1.DHCPServer', prop])
+ return out.strip().decode()
+
def get_dhcp_client_state(link, family):
link_path = get_dbus_link_path(link)
@@ -4996,6 +5003,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '1')
self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp_pvlan', '1')
self.check_ipv4_sysctl_attr('dummy98', 'accept_local', '1')
+ self.check_ipv4_sysctl_attr('dummy98', 'src_valid_mark', '1')
self.check_ipv4_sysctl_attr('dummy98', 'rp_filter', '0')
self.check_ipv4_sysctl_attr('dummy98', 'force_igmp_version', '1')
@@ -7293,6 +7301,9 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, "Offered DHCP leases: 192.168.5.[0-9]*")
+ self.assertEqual(get_dhcp_server_property('veth-peer', 'PoolSize'), 'u 50')
+ self.assertEqual(get_dhcp_server_property('veth-peer', 'PoolOffset'), 'u 10')
+
if persist_leases == 'yes':
path = '/var/lib/systemd/network/dhcp-server-lease/veth-peer'
elif persist_leases == 'runtime':
diff --git a/test/units/TEST-13-NSPAWN.machined.sh b/test/units/TEST-13-NSPAWN.machined.sh
index 34307f3c8b..de51daa24c 100755
--- a/test/units/TEST-13-NSPAWN.machined.sh
+++ b/test/units/TEST-13-NSPAWN.machined.sh
@@ -44,21 +44,27 @@ set -x
PID=0
-trap 'touch /terminate; kill 0' RTMIN+3
-trap 'touch /poweroff' RTMIN+4
-trap 'touch /reboot' INT
-trap 'touch /trap' TRAP
+# Use only builtins in trap handlers to avoid forking. External commands
+# (like touch) cause bash to enter wait_for() for the child, and a nested
+# signal arriving during that wait triggers a bash bug where
+# run_interrupt_trap() clears catch_flag while other traps are still
+# pending, creating an orphaned pending_traps[] entry that makes 'wait'
+# busy-loop indefinitely.
+trap ': >/terminate; kill 0' RTMIN+3
+trap ': >/poweroff' RTMIN+4
+trap ': >/reboot' INT
+trap ': >/trap' TRAP
trap 'exit 0' TERM
trap 'kill $PID' EXIT
# We need to wait for the sleep process asynchronously in order to allow
# bash to process signals
sleep infinity &
+PID=$!
# notify that the process is ready
-touch /ready
+: >/ready
-PID=$!
while :; do
wait || :
done
@@ -332,11 +338,11 @@ trap 'kill $PID' EXIT
# We need to wait for the sleep process asynchronously in order to allow
# bash to process signals
sleep infinity &
+PID=$!
# notify that the process is ready
-touch /ready
+: >/ready
-PID=$!
while :; do
wait || :
done
diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh
index fb3dbcfad5..7b536fa092 100755
--- a/test/units/TEST-58-REPART.sh
+++ b/test/units/TEST-58-REPART.sh
@@ -941,6 +941,7 @@ EOF
--dry-run=no \
--empty=create \
--size=auto \
+ --split=yes \
--json=pretty \
--private-key="$defs/verity.key" \
--certificate="$defs/verity.crt" \
@@ -953,6 +954,13 @@ EOF
assert_eq "$drh" "$hrh"
assert_eq "$hrh" "$srh"
+ # The split-out verity signature file should be a valid JSON document (i.e. trailing NUL padding
+ # from the on-disk partition must be trimmed when writing the split file).
+ sig_split=$(jq -r ".[] | select(.type == \"root-${architecture}-verity-sig\") | .split_path" <<<"$output")
+ assert_neq "$sig_split" ""
+ assert_neq "$sig_split" "null"
+ jq . "$sig_split" >/dev/null
+
# Check that offline signing works and the resulting image is valid
output=$(systemd-repart --offline="$OFFLINE" \
diff --git a/test/units/TEST-72-SYSUPDATE.sh b/test/units/TEST-72-SYSUPDATE.sh
index b929485bd5..27268c250b 100755
--- a/test/units/TEST-72-SYSUPDATE.sh
+++ b/test/units/TEST-72-SYSUPDATE.sh
@@ -373,7 +373,9 @@ EOF
if $have_updatectl; then
systemctl start systemd-sysupdated
"$SYSUPDATE" --verify=no check-new
- updatectl update
+ updatectl update |& tee "$WORKDIR"/updatectl-update-6
+ grep "Done" "$WORKDIR"/updatectl-update-6
+ (! grep "Already up-to-date" "$WORKDIR"/updatectl-update-6)
else
# If no updatectl, gracefully fall back to systemd-sysupdate
update_now "$update_type"
diff --git a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh
index 782a6dc6e9..9a22757067 100755
--- a/test/units/TEST-74-AUX-UTILS.varlinkctl.sh
+++ b/test/units/TEST-74-AUX-UTILS.varlinkctl.sh
@@ -230,6 +230,18 @@ set -o pipefail
varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List '{"cgroup": "/init.scope"}'
invocation_id="$(systemctl show -P InvocationID systemd-journald.service)"
varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "{\"invocationID\": \"$invocation_id\"}"
+# test for KillContext
+varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List '{"pid": {"pid": 0}}' | jq -e '.context.Kill'
+# test for AutomountContext/Runtime
+automount_id=$(varlinkctl call --collect /run/systemd/io.systemd.Manager io.systemd.Unit.List '{}' | jq -r '.[] | select(.context.Type == "automount" and .runtime.LoadState == "loaded") .context.ID' | grep -v null | tail -n 1)
+test -n "$automount_id"
+varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "{\"name\": \"$automount_id\"}" | jq -e '.context.Automount'
+varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "{\"name\": \"$automount_id\"}" | jq -e '.runtime.Automount'
+# test for MountContext/Runtime
+mount_id=$(varlinkctl call --collect /run/systemd/io.systemd.Manager io.systemd.Unit.List '{}' | jq -r '.[] | select(.context.Type == "mount" and .runtime.LoadState == "loaded") .context.ID' | grep -v null | tail -n 1)
+test -n "$mount_id"
+varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "{\"name\": \"$mount_id\"}" | jq -e '.context.Mount'
+varlinkctl call /run/systemd/io.systemd.Manager io.systemd.Unit.List "{\"name\": \"$mount_id\"}" | jq -e '.runtime.Mount'
# test io.systemd.Metrics
varlinkctl info /run/systemd/report/io.systemd.Manager
diff --git a/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh b/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh
index 7d26541ffa..440c3e5edf 100755
--- a/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh
@@ -101,7 +101,14 @@ basic_tests() {
testcase_bootctl_basic() {
assert_in "$(bootctl --print-esp-path)" "^(/boot/|/efi)$"
assert_in "$(bootctl --print-boot-path)" "^(/boot/|/efi)$"
+
bootctl --print-root-device
+ bootctl --print-root-device --print-root-device
+ bootctl --print-esp-path
+ bootctl --print-boot-path
+ bootctl --print-loader-path
+ bootctl --print-stub-path
+ bootctl --print-efi-architecture
basic_tests
}