Commit Graph
1863 Commits
Author SHA1 Message Date
Lennart Poettering 29c6d1c125 boot: measure select SMBIOS objects explicitly 2026-05-21 18:34:01 +02:00
Daan De Meyer 74d392ed1b tree-wide: standardize header names across src/fundamental, src/basic and src/shared
Drop the -fundamental suffix from src/fundamental/ headers in favor of names
that match their src/basic/ or src/shared/ counterparts (e.g.
macro-fundamental.h -> macro.h, assert-fundamental.h -> assert-util.h,
cleanup-fundamental.h -> cleanup-util.h). Rename src/basic/{btrfs,label}.{c,h}
to use the -util suffix to match the existing shared/btrfs-util and
shared/label-util siblings. Rename src/shared/mkdir-label.{c,h} to mkdir.{c,h}
and src/shared/tmpfile-util-label.{c,h} to tmpfile-util.{c,h} to match the
corresponding src/basic names.

This saves us from having to come up with separate names for files that do
the same thing across tiers, and it makes it easier to move stuff between
src/fundamental, src/basic and src/shared: consumers just #include "foo.h"
and pick up whichever tier their -I path resolves to first, so call sites
don't need to be updated when an API moves between layers.

Where a higher-tier wrapper exists (e.g. src/basic/macro.h wrapping
src/fundamental/macro.h), the wrapper uses an explicit "../fundamental/foo.h"
or "../basic/foo.h" relative include for the lower-tier header. We can't use
GCC's #include_next directive for this — when the wrapper is reachable both
via same-dir-as-source lookup and via -I (e.g. -Isrc/shared) for the
directory it lives in, #include_next advances by exactly one slot in libcpp's
internal directory chain and lands on the same physical directory it was
already in, never reaching the lower-tier sibling (see make_cpp_dir() in
gcc/libcpp/files.cc:1986).

To make sure the right headers are always picked up, the include directories
are reordered so that e.g. src/shared always takes priority over src/basic and
similar for the other directories.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 10:33:03 +09:00
Luca Boccassi 0096c83c5d boot: fix off-by-one truncation when reading efivars
'val' is allocated as 'size + 1', so the NUL terminator must be written
to 'size', rather than 'size - 1'.

Follow-up for fab8275646
2026-05-18 08:26:44 +02:00
Yu Watanabe c54decc406 ruff: use single quotes for multiline strings 2026-05-18 02:32:39 +09:00
Daan De Meyer 7b9d76cba7 boot,vconsole: Propagate UEFI HII keyboard layout to the OS
UEFI firmware can report the currently-active keyboard layout via
EFI_HII_DATABASE_PROTOCOL.GetKeyboardLayout(). The layout descriptor
includes an RFC 4646 / BCP 47 language tag (e.g. "en-US"). Query this
from sd-boot/sd-stub and write it to a new LoaderKeyboardLayout EFI
variable, advertised through a new EFI_LOADER_FEATURE_KEYBOARD_LAYOUT
feature bit.

On the OS side, systemd-vconsole-setup reads the variable as a
lowest-priority fallback for the console keymap. To map the BCP 47
tag to a vconsole keymap we extend /usr/share/systemd/kbd-model-map
with an optional sixth column listing the comma-separated BCP 47 tags
each row covers; a new find_vconsole_keymap_for_bcp47() helper walks
the file, preferring an exact tag match and otherwise falling back to
the row whose tag matches the input's primary subtag. Credentials,
/etc/vconsole.conf, and vconsole.keymap= on the kernel command line
continue to take precedence.

bootctl status surfaces the new variable, printing the language tag
or "n/a (not reported by firmware)" when sd-boot advertises the
feature but the firmware HII database didn't expose a layout (common
on QEMU without a USB keyboard, since EDK2's PS/2 driver does not
register an HII keyboard layout).
2026-05-11 21:10:11 +02:00
Sergei Trofimovich fc68ee6118 sd-boot: efi-log: fix __stack_chk_guard type
In https://gcc.gnu.org/PR121911 `gcc` started enforcing the type of
`__stack_chk_guard` to `uintptr_t` and broke `systemd` build as:

```
../src/boot/efi-log.c:136:17: error: conflicting types for '__stack_chk_guard'; have 'intptr_t' {aka 'long int'}
  136 | _used_ intptr_t __stack_chk_guard = (intptr_t) 0x70f6967de78acae3;
      |                 ^~~~~~~~~~~~~~~~~
cc1: note: previous declaration of '__stack_chk_guard' with type 'long unsigned int'
../src/boot/efi-log.c:136:17: error: declaration of '__stack_chk_guard' shadows a global declaration [-Werror=shadow]
  136 | _used_ intptr_t __stack_chk_guard = (intptr_t) 0x70f6967de78acae3;
      |                 ^~~~~~~~~~~~~~~~~
```

Let's match the declaration to unsigned type as suggested by upstream in
https://gcc.gnu.org/PR121911#c6.
2026-05-06 09:18:25 +02:00
Valentin David 5580db885c boot: Try to load UKI from simple filesystem before LoadImage
When the source buffer is NULL, the firmware is supposed to try to load the UKI
with simple filesystem protocol then load file 2 protocol. But it seems
on some versions of AMI, it does not use simple filesystem protocol,
and then fails to load if the ESP was loaded from an El Torito boot
catalog. Trying to load the source buffer from the simple filesystem protocol
protocols seems work around this limitation.

Shim for example, also loads the source buffer before calling LoadImage. So it
seems to be a safe thing to do. We could also maybe in the future use load file
2 protocol if simple filesystem failed in the first place.
2026-05-04 10:03:46 +02:00
Lennart Poettering 32a291abe9 sd-boot: minor tweaks as follow-up for #41863
This addresses some trivial points made by @keszybz in the PR review.
2026-04-29 15:53:21 +02:00
Lennart Poettering a3d0e761d4 boot: downgrade log level for an error we ignore 2026-04-29 13:36:56 +02:00
Lennart Poettering d5572aca2c boot: load extra files for UKIs into memory and register as initrds
This generates on-the-fly cpio initrds from 'extra' resources declared
in Type #1 entries and installs them via the Linux initrd protocol so
that they get passed to the Linux kernel.

Replaces: #39286
2026-04-29 13:36:56 +02:00
Lennart Poettering feba5dcc5f boot: parse 'extra' type 1 stanza too
This loads the new 'extra' stanza, but doesn't actually do anything with
it yet. That's added in a later commit.

Replaces: #39286

Implements: https://github.com/uapi-group/specifications/pull/212
2026-04-29 13:36:56 +02:00
Lennart Poettering c3ace5621b cpio: move TPM PCR info into CpioTarget
The PR to measure into is closely associated with where we place a
resource in the initrd cpios. Hence, let's also track it in CpioTarget,
thus simplifying our function parameter lists that way.

No change in behaviour.
2026-04-29 13:36:47 +02:00
Lennart Poettering 9d7fa23d38 boot: share combine_initrds() between stub/boot
We'd like to use combine_initrds() later in systemd-boot, hence move it
out of stub.c and into shared code.
2026-04-21 08:30:26 +02:00
Lennart Poettering f6b5fcc3cf boot: export more helpers from cpio.c
We want to reuse this later in systemd-boot, hence make these helpers
public.
2026-04-21 08:30:26 +02:00
Lennart Poettering 0e98e6ccd1 boot: introduce a common structure for cpio target dirs
There are only a few target dirs we place resources in when generating
on-the-fly initrd cpios. These dirs have very specific attributes.
Instead of repeating this everywhere, let's encapsulate them in a new
explicit structure, that we can reuse at various places.

This is preparation for placing extra resources of Type #1 entry also in
them without having to encode access modes at multiple places
redundantly.
2026-04-21 08:30:26 +02:00
Lennart Poettering 426134b0e7 stub: load previous initrd that is already configured, too
This changes the initrd combination logic to also include any initrd
already configured via the "LINUX_INITRD_MEDIA_GUID" device in the
initrd we pass to the linux kernel.

Or in other words: with this systemd-stub starts operating purely
incremental: it will extend any previously installed initrd with its own
stuff, so that both the previous initrd(s) and systemd-stub's are in
effect.
2026-04-21 08:30:26 +02:00
Lennart Poettering c363bb1869 boot: change initrd_register() so that it replaces any previously registered LINUX_INITRD_MEDIA device
So far, if an initrd is already registered we'd silently not register
one again. Let's make this more reliable and systematic, and register
ours, overriding what is previously set.

(Note, in a later commit we'll incorporate any previously set initrd,
which hence makes this all incremental instead of destructive as it
might appear now)
2026-04-21 08:30:25 +02:00
Lennart Poettering 9879a19222 boot: minor clean-ups in initrd_unregister() 2026-04-18 09:48:42 +02:00
Lennart Poettering 587064b3f3 boot: switch initrd_register() to use _cleanup_free_ and other tweaks 2026-04-18 08:40:58 +02:00
Lennart Poettering c40f254cca boot: gracefully handle LoadFile() implementations that return EFI_SUCCESS with a NULL buffer
LoadFile() with a NULL buffer is supposed to return the file size
without acquiring the data and return EFI_BUFFER_TOO_SMALL.

However it appears some firmware returns EFI_SUCCESS in case the file is
empty, i.e. the file size returned is zero. And I guess that's even
fine.

Let's handle this gracefully hence.
2026-04-17 18:23:51 +02:00
Lennart Poettering a93fa2c6b4 boot: never auto-boot a menu entry with the non-default profile
When figuring out which menu entry to pick by default, let's not
consider any with a profile number > 0. This reflects that fact that
additional profiles are generally used for
debug/recovery/factory-reset/storage target mode boots, and those should
never be auto-selected. Hence do a simple check: if profile != 0, simply
do not consider the entry as a default.

We might eventually want to beef this up, and add a property one can set
in the profile metadata that controls this behaviour, but for now let's
just do a this simple fix.
2026-04-17 17:54:47 +02:00
Milan Kyselica 2c664b9531 boot: fix loop bound and OOB in devicetree_get_compatible()
The loop used the byte offset end (struct_off + struct_size) as the
iteration limit, but cursor[i] indexes uint32_t words. This reads
past the struct block when end > size_words.

Use size_words (struct_size / sizeof(uint32_t)) which is the correct
number of words to iterate over.

Also fix a pre-existing OOB in the FDT_BEGIN_NODE handler: the guard
i >= size_words is always false inside the loop (since the loop
condition already ensures i < size_words), so cursor[++i] at the
boundary reads one word past the struct block. Use i + 1 >= size_words
to check before incrementing.

Fixes: https://github.com/systemd/systemd/issues/41590
2026-04-13 12:33:56 +02:00
Milan Kyselica c3c9cc7adb boot: fix integer overflow and division by zero in BMP splash parser
Bound image dimensions before computing row_size to prevent overflow
in the depth * x multiplication on 32-bit. Without this, crafted
dimensions like depth=32 x=0x10000001 wrap to a small row_size that
passes all subsequent checks.

Reject channel masks where all bits are set (popcount == 32), since
1U << 32 is undefined behavior and causes division by zero on
architectures where it evaluates to zero. Move the validation before
computing derived values for clarity. Use unsigned 1U in shifts to
avoid signed integer overflow UB for popcount == 31.

Also reject zero-width and zero-height images.

Fixes: https://github.com/systemd/systemd/issues/41589
2026-04-13 12:24:07 +02:00
Zbigniew Jędrzejewski-Szmek 5cd61c1330 Define array cleanup funcs through macros (#41559) 2026-04-10 21:45:14 +02:00
Zbigniew Jędrzejewski-Szmek 3b478198e9 stub: use DEFINE_ARRAY_FREE_FUNC 2026-04-10 15:08:02 +02:00
Daan De Meyer f08796065d compress: consolidate all compression into compress.c with dlopen
Move the push-based streaming compression API from import-compress.c
into compress.c and delete import-compress.c/h. This consolidates all
compression code in one place and makes all compression libraries
(liblzma, liblz4, libzstd, libz, libbz2) runtime-loaded via dlopen
instead of directly linked.

Introduce opaque Compressor/Decompressor types backed by a heap-
allocated struct defined only in compress.c, keeping all third-party
library headers out of compress.h.

Rewrite the per-codec fd-to-fd stream functions as thin wrappers around
the push API via generic compress_stream()/decompress_stream() taking a
Compression type parameter. Integrate LZ4 into this framework using the
LZ4 Frame API, eliminating all LZ4 special-casing.

Extend the Compression enum with COMPRESSION_GZIP and COMPRESSION_BZIP2
and add the corresponding blob, startswith, and stream functions for
both.

Rename the ImportCompress types and functions: ImportCompressType becomes
the existing Compression enum, ImportCompress becomes Compressor (with
Decompressor typedef), and all import_compress_*/import_uncompress_*
become compressor_*/decompressor_*. Rename dlopen_lzma() to dlopen_xz()
for consistency. Make compression_to_string() return lowercase by
default.

Add INT_MAX/UINT_MAX overflow checks for LZ4, zlib, and bzip2 blob
functions where the codec API uses narrower integer types than our
uint64_t parameters.

Migrate test-compress.c and test-compress-benchmark.c to the TEST()
macro framework, new assertion macros, and codec-generic loops instead
of per-codec duplication.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 22:39:11 +02:00
Daan De Meyer c82cf5662e boot: generalize CDROM terminology to El Torito
Per UEFI specification §13.3.2, El Torito partition discovery applies to
any block device, not just optical media. Rename
disk_get_part_uuid_cdrom() to disk_get_part_uuid_eltorito() and update
all log messages and comments to say "El Torito" instead of "CDROM" to
reflect this.
2026-04-05 08:19:49 +00:00
Daan De Meyer 05e1ca3144 boot: add El Torito CDROM partition UUID discovery
When booting from a CD-ROM via El Torito, the UEFI device path contains a
CDROM_DEVICE_PATH node instead of a HARDDRIVE_DEVICE_PATH node. Unlike the
hard drive variant, the CDROM node does not carry a partition UUID, so
systemd-boot previously could not determine the boot partition UUID in this
scenario.

Add disk_get_part_uuid_cdrom() which recovers the partition UUID by reading
the GPT from the underlying disk. Since ISO images are commonly mastered
with 512-byte GPT sectors on media with 2048-byte blocks, the function
probes for the GPT header at multiple sector sizes (512, 1024, 2048, 4096)
and matches the partition by comparing byte offsets between the CDROM node's
PartitionStart and each GPT entry's StartingLBA.

The function reuses read_gpt_entries() for GPT parsing and adds debug
logging for each failure path to aid diagnosis on real hardware.

Also adds the CDROM_DEVICE_PATH struct and MEDIA_CDROM_DP subtype constant
to device-path.h, and fixes disk_get_part_uuid() to preserve the original
device path pointer so it can be passed to the CDROM fallback.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 20:03:44 +02:00
Daan De Meyer 37b852c948 boot: Split out read_gpt_entries() 2026-04-04 20:03:44 +02:00
Daan De Meyer 4e5c605d4b boot: use EFI_DISK_IO_PROTOCOL instead of EFI_BLOCK_IO_PROTOCOL for disk reads
EFI_DISK_IO_PROTOCOL (UEFI spec section 13.7,
https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#disk-i-o-protocol)
supports reads at arbitrary byte offsets with no alignment requirements on the
buffer. The UEFI spec mandates that firmware produces this protocol on every
handle that also has EFI_BLOCK_IO_PROTOCOL, so it is always available.

This is a better fit than EFI_BLOCK_IO_PROTOCOL for our GPT parsing and
BitLocker detection because Block I/O requires that both the read offset (LBA)
and the buffer are aligned to the media's IoAlign value. Meeting that
constraint forces us to use xmalloc_aligned_pages() with
PHYSICAL_ADDRESS_TO_POINTER(), page-granularity allocations, and manual size
rounding (ALIGN_TO). Disk I/O handles all of that internally, so callers can
use plain xmalloc() or even stack buffers and read exactly the number of bytes
they need.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 20:03:44 +02:00
Daan De Meyer e306f4d123 stub: Determine the correct serial console from the ACPI device path
Instead of requiring exactly one serial device and assuming ttyS0,
extract the COM port index from the ACPI device path and use the
uart I/O port address format for the console= kernel argument.

On x86, the ACPI UID for PNP0501 (16550 UART) maps directly to the
COM port number: UID 0 = COM1 (0x3F8), UID 1 = COM2 (0x2F8), etc.
The I/O port addresses are fixed in the kernel (see
arch/x86/include/asm/serial.h). Using the console=uart,io,<addr>
format (see Documentation/admin-guide/kernel-parameters.txt) addresses
the UART by I/O port directly rather than relying on ttyS naming,
and also provides early console output before the full serial driver
loads.

Restrict the entire serial console auto-detection to x86. On non-x86
(e.g. ARM with PL011 UARTs), displays may be available without GOP
(e.g. simple-framebuffer via device tree), serial device indices are
assigned dynamically during probe rather than being fixed to I/O port
addresses, and the kernel has its own console auto-detection via DT
stdout-path.

When ConOut has no device path (ConSplitter), all text output handles
are enumerated. If multiple handles have PNP0501 UART nodes with
different UIDs, bail out rather than guessing.

Add ACPI_DP device path subtype, ACPI_HID_DEVICE_PATH struct, and
EISA_PNP_ID() macro to device-path.h for parsing ACPI device path
nodes. Remove MSG_UART_DP, device_path_has_uart(), count_serial_devices()
and proto/serial-io.h (no longer needed).

Move all the console logic to console.c as well.
2026-04-02 14:58:42 +02:00
Daan De Meyer 1653ac8db5 stub: Do a single PCI read to get the vendor and device ID 2026-04-02 14:58:42 +02:00
Daan De Meyer f9339b9087 stub: Drop needless enum value assignment
Follow up for 45e4df9a33
2026-04-02 14:58:42 +02:00
Zbigniew Jędrzejewski-Szmek e1342e063b test-efi-string: add more cases
This excercises the patterns used in
45e4df9a33.
2026-04-01 16:01:58 +02:00
Daan De Meyer 45e4df9a33 stub: auto-detect console device and append console= to kernel command line
The Linux kernel does not reliably auto-detect serial consoles on
headless systems. While the docs claim serial is used as a fallback
when no VGA card is found, in practice CONFIG_VT's dummy console
(dummycon) registers early and satisfies the kernel's console
requirement, preventing the serial fallback from ever triggering. The
ACPI SPCR table can help on ARM/RISC-V where QEMU generates it, but
x86 QEMU does not produce SPCR, and SPCR cannot describe virtio
consoles at all. This means UKIs booted via sd-stub in headless VMs
produce no visible console output unless console= is explicitly
passed on the kernel command line.

Fix this by having sd-stub auto-detect the console type and append an
appropriate console= argument when one isn't already present.

Detection priority:

1. VirtIO console PCI device (vendor 0x1AF4, device 0x1003): if
   exactly one is found, append console=hvc0. This takes highest
   priority since a VirtIO console is explicitly configured by the
   VMM (e.g. systemd-vmspawn's virtconsole device). If multiple
   VirtIO console devices exist, we cannot determine which hvc index
   is correct, so we skip this path entirely.

2. EFI Graphics Output Protocol (GOP): if present, don't add any
   console= argument. The kernel will use the framebuffer console by
   default, and adding a serial console= would redirect the primary
   console away from the display.

3. Serial console: first, we count the total number of serial devices
   via EFI_SERIAL_IO_PROTOCOL. If there are zero or more than one,
   we bail out — with multiple UARTs, the kernel assigns ttyS indices
   based on its own enumeration order and we cannot determine which
   index the console UART will receive. Only when exactly one serial
   device exists (guaranteeing it will be ttyS0) do we proceed to
   verify it's actually used as a console by checking for UART device
   path nodes (MESSAGING_DEVICE_PATH + MSG_UART_DP). The firmware's
   ConOut handle is checked first; if it has no device path (common
   with OVMF's ConSplitter virtual handle when using -nographic
   -nodefaults), we fall back to enumerating all
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL handles and checking each one's
   device path. The architecture-specific console argument is then
   appended:
   - x86:     console=ttyS0
   - ARM:     console=ttyAMA0
   - Others:  console=ttyS0 (RISC-V, LoongArch, MIPS all use ttyS0)

Note on OVMF's VirtioSerialDxe: it exposes virtio serial ports with
the same UART device path nodes as real serial ports (ACPI PNP 0x0501
+ MSG_UART_DP), making them indistinguishable from real UARTs via
device path inspection alone. This is why we check for the VirtIO
console PCI device via EFI_PCI_IO_PROTOCOL before falling back to
device path analysis.

Also add a minimal EFI_PCI_IO_PROTOCOL definition (proto/pci-io.h)
with just enough to call Pci.Read for vendor/device ID enumeration,
and add the MSG_UART_DP subtype to the device path header.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 15:32:13 +02:00
Luca Boccassi a770fb3e14 boot: clamp setup header copy size to sizeof(SetupHeader)
The setup_size field from the kernel image header is used as part
of the memcpy size. Clamp it to sizeof(SetupHeader) to ensure the
copy does not read beyond the struct bounds even if the kernel
image header contains an unexpected value.

CID#1549197

Follow-up for d62c177756
2026-03-30 10:55:33 +01:00
Luca Boccassi 85b20f5fa7 boot: add overflow check in GPT parser
ALIGN_TO() can overflow and return SIZE_MAX

CID#1644887

Follow-up for ccbd324a3a
2026-03-28 19:56:31 +00:00
Zbigniew Jędrzejewski-Szmek 5f2258affc many: more checks for pointer access without NULL check (#41370)
This is a followup for https://github.com/systemd/systemd/pull/41096
that makes more subsystems pass the new `check-pointer-deref` coccinelle
checks. See the individual commits.

My plan is to do a few more of these PRs until we have it all covered. I
could also do it in a single very big PR but I'm worried about a)
conflicts b) that its just too big/annoying to review. Only 7 dirs left
but some (like src/basic) are quite big (~50k loc) so those PRs will be
a bit bigger.
2026-03-27 14:58:27 +01:00
Luca Boccassi 79f8447f5f sd-boot: 4 smaller fixes (#41367) 2026-03-27 11:47:33 +00:00
Luca Boccassi 78ab70a46f boot: avoid division by zero in splash image handling
A malformed image can cause a division by zero, check that
the parameters are not zero.

Reported on yeswehackl.com as YWH-PGM9780-173

Follow-up for 0fa2cac4f0
2026-03-27 10:28:20 +00:00
Michael Vogt bf2d68433d coccinelle: generalize pidref_is_set() to =~ _is_set()
Our coccinelle/check-pointer-deref.cocci checker has a special
case for `assert(pidref_is_set(param))`. It turns out we can
generalize this and catch the following:
- iovec_is_set
- sd_dhcp_duid_is_set
- sd_dhcp_client_id_is_set
2026-03-27 11:14:49 +01:00
Lennart Poettering 6a4a4f0302 bootspec: honour profile number when sorting properly
This corrects sorting of menu entries regarding profile numbers:

1. If the profile number is unset, let's treat this identical to profile
   0, when ordering stuff, because an item with no profile is
   conceptually the same as an item with only a profile 0.

2. Let's take the profile number into account also if sort keys are
   used. This was makes profiles work sensibly in type 1 entries, via
   the recently added "profile" stanza.

Follow-up for: 5fb90fa319
2026-03-27 10:44:14 +01:00
Lennart Poettering 208cc69c50 boot: do no show pixel width/height in text mode
When running in pure text mode (i.e. serial terminal) the pixel
width/height is zero and makes no sense to report. Suppress it.
2026-03-27 10:44:14 +01:00
Lennart Poettering 3d4e3c1a5e boot: properly track internal menu entries
When showing the list of menu entries via "p", the "internal call:"
field was showing nonsense, since
fb6cf4bbb7.

Fix that by adding a proper entry type for "internal" menu items such as
reboot/firmware/poweroff, and then check for that.

With this in place all entries now have a loader type that makes sense
and describes precisely what an entry is about.
2026-03-27 10:44:14 +01:00
Lennart Poettering 6e2a452118 fundamental: move strv_isempty() into src/fundamental/ 2026-03-27 09:54:28 +01:00
Michael Vogt 777d9c10ad coccinelle: add checks for pointer access without NULL check
The fix in 8f1751a111 made me wonder if we could automatically detect
when pointers are accessed but when this might not be safe. Systemd
is already using a lot of `assert(dst)` and this change now forces
us to use them.

So this commit (ab)uses coccinelle to flag any pointer parameter
dereference not preceded by assert(param), ASSERT_PTR(param), or an
explicit NULL check. It adds integration into meson as a new "coccinelle"
test suite (just like clang-tidy) and is run in CI. The check is not
perfect but seems a reasonable heuristic.

For this RFC commit it is scoped to a subset, it excludes 25 dirs right
now and includes around 100. About 300 warnings left. Busywork that I am
happy to do if there is agreement that it is worth it.

With this in place we would have caught the bug from 8f1751a111 in CI:
```
FAIL: check-pointer-deref.cocci found issues in systemd/src/boot:
diff -u -p systemd/src/boot/measure.c /tmp/nothing/measure.c
--- systemd/src/boot/measure.c
+++ /tmp/nothing/measure.c
@@ -312,7 +312,6 @@ EFI_STATUS tpm_log_tagged_event(
         if (err != EFI_SUCCESS)
                 return err;

-        *ret_measured = true;
         return EFI_SUCCESS;
 }
```

This also adds a new POINTER_MAY_BE_NULL() for the cases when the
called function will do the NULL check (like `iovec_is_set()`).
2026-03-26 18:13:17 +01:00
Luca Boccassi 186032e1ed boot: add checks for invalid splash images in UKI
A malformed bmp with 8bits depth but smaller color
map would cause out of bounds reads. This is not a real
problem as the image is signed, but better to be safe.

Reported on yeswehack.com as:
YWH-PGM9780-135

Follow-up for 0fa2cac4f0
2026-03-26 11:52:23 +01:00
Luca Boccassi 82d96837db boot: fix typo in function name
Follow-up for dde03dd2a8
2026-03-26 11:52:23 +01:00
Mike Yuan aa71035a20 meson: detect availability of attributes using cc.has_function_attribute()
Alternative to fabc22f599

As suggested in https://github.com/systemd/systemd/pull/41174#discussion_r2966411375
2026-03-25 21:54:21 +01:00
Lennart Poettering dcad61c74d stub: introduce "boot secret" stored in an EFI variable inaccessible to the OS 2026-03-25 16:19:27 +01:00