From c9da9188057efff853fe5780ca517cd3145977b8 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 7 Apr 2026 23:08:29 +0100 Subject: [PATCH 01/10] scsi_id: null-terminate serial after append_vendor_model append_vendor_model() uses memcpy() to write VENDOR_LENGTH + MODEL_LENGTH bytes without null-terminating. While the caller zeroes the buffer beforehand, Coverity cannot trace this. Add explicit null termination so the subsequent strlen() is provably safe. CID#1469706 Follow-up for 86fd0337c652b04755008cdca23e2d9c727fa9a9 --- src/udev/scsi_id/scsi_serial.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/udev/scsi_id/scsi_serial.c b/src/udev/scsi_id/scsi_serial.c index 82557e3b05..7de9999257 100644 --- a/src/udev/scsi_id/scsi_serial.c +++ b/src/udev/scsi_id/scsi_serial.c @@ -491,9 +491,14 @@ static int check_fill_0x83_id(struct scsi_id_device *dev_scsi, * this differs from SCSI_ID_T10_VENDOR, where the vendor is * included in the identifier. */ - if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) + if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) { if (append_vendor_model(dev_scsi, serial + 1) < 0) return 1; + /* append_vendor_model() uses memcpy() without null-terminating. + * The buffer was zeroed by the caller, but ensure the string is + * explicitly terminated for strlen() below. */ + serial[1 + VENDOR_LENGTH + MODEL_LENGTH] = '\0'; + } i = 4; /* offset to the start of the identifier */ s = j = strlen(serial); From 1934c65108505d0cd1888a889494467660a330c6 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 7 Apr 2026 23:45:30 +0100 Subject: [PATCH 02/10] uid-range: add assert to silence coverity Coverity flags range->n_entries - j - 1 and j-- as potential underflows. Add an assert that j > 0 before decrementing, since j starts at i + 1 >= 1 and is never decremented below its initial value. CID#1548015 Follow-up for 8dcc66cefc8ab489568c737adcba960756d76a3c --- src/basic/uid-range.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/basic/uid-range.c b/src/basic/uid-range.c index 628710a870..3d8f8445c4 100644 --- a/src/basic/uid-range.c +++ b/src/basic/uid-range.c @@ -76,6 +76,9 @@ static void uid_range_coalesce(UIDRange *range) { memmove(y, y + 1, sizeof(UIDRangeEntry) * (range->n_entries - j - 1)); range->n_entries--; + + /* Silence static analyzers, j cannot be 0 here since it starts at i + 1, i.e. >= 1 */ + assert(j > 0); j--; } } From 8fa088b8860c9ba6f67d962953cb8f11316f0505 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 7 Apr 2026 23:59:16 +0100 Subject: [PATCH 03/10] recurse-dir: add assert for MALLOC_SIZEOF_SAFE lower bound Coverity flags MALLOC_SIZEOF_SAFE(de) - offsetof(DirectoryEntries, buffer) as a potential underflow when MALLOC_SIZEOF_SAFE returns 0. After a successful malloc the return value is at least as large as the requested size, but Coverity cannot trace this. Add an assert to establish the lower bound. CID#1548020 Follow-up for 6393b847f459dba14d2b615ee93babb143168b57 --- src/basic/recurse-dir.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basic/recurse-dir.c b/src/basic/recurse-dir.c index 1bd8231966..8f691d9229 100644 --- a/src/basic/recurse-dir.c +++ b/src/basic/recurse-dir.c @@ -55,6 +55,8 @@ int readdir_all(int dir_fd, RecurseDirFlags flags, DirectoryEntries **ret) { size_t bs; ssize_t n; + /* Silence static analyzers, MALLOC_SIZEOF_SAFE is at least as large as the allocation */ + assert(MALLOC_SIZEOF_SAFE(de) >= offsetof(DirectoryEntries, buffer)); bs = MIN(MALLOC_SIZEOF_SAFE(de) - offsetof(DirectoryEntries, buffer), (size_t) SSIZE_MAX); assert(bs > de->buffer_size); From e60937b5853de50bbb0941fef49fe6faef213909 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:11:01 +0100 Subject: [PATCH 04/10] sd-bus: assert ALIGN8 result is not SIZE_MAX Coverity flags sizeof(BusMessageHeader) + ALIGN8(m->fields_size) as overflowing because ALIGN_TO can return SIZE_MAX as an overflow sentinel. Assert that the aligned value is not SIZE_MAX to prove the addition is safe. CID#1548023 CID#1548046 Follow-up for 2ac7c17f9d8eeb403b91ee5a389562edaf47fb87 --- src/libsystemd/sd-bus/bus-message.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h index fe9679393e..94eff878e5 100644 --- a/src/libsystemd/sd-bus/bus-message.h +++ b/src/libsystemd/sd-bus/bus-message.h @@ -153,7 +153,8 @@ static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) { } static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) { - /* Silence static analyzers */ + /* Silence static analyzers, fields_size is validated at message creation */ + assert(ALIGN8(m->fields_size) != SIZE_MAX); assert(ALIGN8(m->fields_size) <= SIZE_MAX - sizeof(BusMessageHeader)); assert(m->body_size <= SIZE_MAX - sizeof(BusMessageHeader) - ALIGN8(m->fields_size)); return @@ -163,7 +164,8 @@ static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) { } static inline size_t BUS_MESSAGE_BODY_BEGIN(sd_bus_message *m) { - /* Silence static analyzers */ + /* Silence static analyzers, fields_size is validated at message creation */ + assert(ALIGN8(m->fields_size) != SIZE_MAX); assert(ALIGN8(m->fields_size) <= SIZE_MAX - sizeof(BusMessageHeader)); return sizeof(BusMessageHeader) + From 0aaf7e697f068b2699b7c964a34711010cbb7fd8 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:15:18 +0100 Subject: [PATCH 05/10] test-path: use usec_add() for timeout calculation Coverity flags now() + 30 * USEC_PER_SEC as overflowing because now() can return USEC_INFINITY. Use usec_add() which saturates on overflow instead of wrapping. CID#1548025 Follow-up for 331461a5a2ffe323190c4ca6b7bcd35944e36f92 --- src/test/test-path.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/test-path.c b/src/test/test-path.c index 82b1f27ed7..8b02f5d0ff 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -78,9 +78,7 @@ static int _check_states(unsigned line, assert_se(m); assert_se(service); - /* Silence static analyzers */ - assert_cc(30 * USEC_PER_SEC <= USEC_INFINITY); - usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC; + usec_t end = usec_add(now(CLOCK_MONOTONIC), 30 * USEC_PER_SEC); while (path->state != path_state || service->state != service_state || path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS) { From aaab31d7a05563c5d44d4e6c7fae7a0bd802c45f Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:26:33 +0100 Subject: [PATCH 06/10] nss-myhostname: use INC_SAFE for buffer index accumulation Use overflow-safe INC_SAFE() instead of raw addition for idx accumulation, so that Coverity can see the addition is checked. CID#1548028 Follow-up for a05483a921a518fd283e7cb32dc8c8e816b2ab2c --- src/nss-myhostname/nss-myhostname.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index 6a016a1f5c..601a4198dd 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -238,14 +238,10 @@ static enum nss_status fill_in_hostent( if (additional) { ((char**) r_aliases)[0] = r_alias; ((char**) r_aliases)[1] = NULL; - /* Silence static analyzers */ - assert(idx <= buflen - 2 * sizeof(char*)); - idx += 2*sizeof(char*); + assert_se(INC_SAFE(&idx, 2 * sizeof(char*))); } else { ((char**) r_aliases)[0] = NULL; - /* Silence static analyzers */ - assert(idx <= buflen - sizeof(char*)); - idx += sizeof(char*); + assert_se(INC_SAFE(&idx, sizeof(char*))); } /* Third, add addresses */ From f0bb176ee1c3d9f1084af271359e0ae51eb03d91 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:34:56 +0100 Subject: [PATCH 07/10] sd-bus: use INC_SAFE and assert for message_from_header allocation Coverity flags ALIGN() as potentially returning SIZE_MAX and the subsequent a += label_sz + 1 as overflowing. Assert ALIGN result is not SIZE_MAX and use INC_SAFE for the addition. CID#1548030 Follow-up for 55354d5930fd0b7952d649d9ad5a850279fc73e1 --- src/libsystemd/sd-bus/bus-message.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 507c5d7ff4..f66b2fa3e2 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -359,12 +359,12 @@ static int message_from_header( /* Note that we are happy with unknown flags in the flags header! */ a = ALIGN(sizeof(sd_bus_message)); + /* Silence static analyzers, ALIGN cannot overflow for sizeof() */ + assert(a != SIZE_MAX); if (label) { label_sz = strlen(label); - /* Silence static analyzers */ - assert(label_sz <= SIZE_MAX - ALIGN(sizeof(sd_bus_message)) - 1); - a += label_sz + 1; + assert_se(INC_SAFE(&a, label_sz + 1)); } m = malloc0(a); From 79a9a9972870b99a045483f2b2126dceaf39f9df Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:40:01 +0100 Subject: [PATCH 08/10] sd-bus: assert ALIGN result in sd_bus_message_new Coverity flags ALIGN(sizeof(sd_bus_message)) as potentially returning SIZE_MAX, making the subsequent + sizeof(BusMessageHeader) overflow. Store the ALIGN result in a local and assert it is not SIZE_MAX. CID#1548031 Follow-up for 4f5b28b72c7ff78c7eabcce7ad4f0eaebfd5545d --- src/libsystemd/sd-bus/bus-message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index f66b2fa3e2..358fb3ca75 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -464,8 +464,8 @@ _public_ int sd_bus_message_new( /* Creation of messages with _SD_BUS_MESSAGE_TYPE_INVALID is allowed. */ assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL); - /* Silence static analyzers */ - assert_cc(sizeof(sd_bus_message) + sizeof(void*) + sizeof(BusMessageHeader) <= SIZE_MAX); + /* Silence static analyzers, ALIGN cannot overflow for sizeof() */ + assert(ALIGN(sizeof(sd_bus_message)) != SIZE_MAX); sd_bus_message *t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(BusMessageHeader)); if (!t) return -ENOMEM; From fda487ef30b83002bda2470af7eefc855191db78 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:53:07 +0100 Subject: [PATCH 09/10] sd-event: validate ssi_signo fits in signed int Coverity flags si.ssi_signo as tainted data from read(), and warns that casting it to signed could produce a negative value. Add an explicit range check against INT_MAX before the SIGNAL_VALID check to prove the cast is safe. CID#1548033 Follow-up for c8b53fcfd3463679e6475e9b57b61a97dac1a287 --- src/libsystemd/sd-event/sd-event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index ad82f308ba..19feff5668 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -3804,11 +3804,11 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, i if (_unlikely_(n != sizeof(si))) return -EIO; - if (_unlikely_(!SIGNAL_VALID(si.ssi_signo))) + if (_unlikely_(si.ssi_signo > INT_MAX)) /* Ensure value fits in int before casting */ return -EIO; - /* Silence static analyzers */ - assert(si.ssi_signo < _NSIG); + if (_unlikely_(!SIGNAL_VALID(si.ssi_signo))) + return -EIO; if (e->signal_sources) s = e->signal_sources[si.ssi_signo]; From 40eef914f35208ee3f34faf063e2e5bdb94cc034 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 8 Apr 2026 00:59:48 +0100 Subject: [PATCH 10/10] limits-util: use MUL_SAFE for physical memory calculation Coverity flags (uint64_t)sc * (uint64_t)ps as a potential overflow. Use MUL_SAFE which Coverity understands via __builtin_mul_overflow. Physical page count times page size cannot realistically overflow uint64_t, but this makes it provable to static analyzers. CID#1548042 Follow-up for 09bb6448ae221c09a00d1f4a9b45ce8535003319 --- src/basic/limits-util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/basic/limits-util.c b/src/basic/limits-util.c index 02fbe92cc7..732d0c6a6f 100644 --- a/src/basic/limits-util.c +++ b/src/basic/limits-util.c @@ -28,9 +28,9 @@ uint64_t physical_memory(void) { assert(sc > 0); ps = page_size(); - /* Silence static analyzers */ - assert((uint64_t) sc <= UINT64_MAX / (uint64_t) ps); - mem = (uint64_t) sc * (uint64_t) ps; + /* Physical page count times page size cannot realistically overflow uint64_t, + * but use MUL_SAFE to make this obvious to static analyzers. */ + assert_se(MUL_SAFE(&mem, (uint64_t) sc, (uint64_t) ps)); r = cg_get_root_path(&root); if (r < 0) {