From 4ff8fb899ba94e7b197f8c55a7797adb648791b4 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 20:59:35 +0000 Subject: [PATCH 01/21] journal: add assert for max_size overflow safety Coverity flags max_size*2 as a potential overflow. The value is bounded by MAX_SIZE_UPPER (128 MiB) or JOURNAL_COMPACT_SIZE_MAX (4 GiB), so doubling is safe within uint64_t. Add an assert to document this. CID#1548019 Follow-up for 8580d1f73db36e9383e674e388b4fb55828c0c66 --- src/libsystemd/sd-journal/journal-file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index de5d7075e0..b4efcc050e 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -4058,6 +4058,8 @@ static void journal_default_metrics(JournalMetrics *m, int fd, bool compact) { if (m->max_size < JOURNAL_FILE_SIZE_MIN) m->max_size = JOURNAL_FILE_SIZE_MIN; + /* Silence static analyzers */ + assert(m->max_size <= UINT64_MAX / 2); if (m->max_use != 0 && m->max_size*2 > m->max_use) m->max_use = m->max_size*2; } From a702b9b6ea9bde91f21f218ec18305f5b7c56f38 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:01:34 +0000 Subject: [PATCH 02/21] sd-json: silence false positive in sd_json_variant_filter Same pattern as the fix for sd_json_variant_unset_field in 9b3715d529e4eba79e19c87e85583f7be5ee2c95: cache the element count in a local variable and assert it is at least 2 before subtracting. CID#1548029 Follow-up for f2ff34ff2aaafd313a5c62b4b9f13ba6777731e5 --- src/libsystemd/sd-json/sd-json.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index b959fe1628..03557d3ac6 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -1940,7 +1940,7 @@ _public_ int sd_json_variant_filter(sd_json_variant **v, char **to_remove) { if (strv_isempty(to_remove)) return 0; - for (size_t i = 0; i < sd_json_variant_elements(*v); i += 2) { + for (size_t i = 0, m = sd_json_variant_elements(*v); i < m; i += 2) { sd_json_variant *p; p = sd_json_variant_by_index(*v, i); @@ -1949,7 +1949,9 @@ _public_ int sd_json_variant_filter(sd_json_variant **v, char **to_remove) { if (strv_contains(to_remove, sd_json_variant_string(p))) { if (!array) { - array = new(sd_json_variant*, sd_json_variant_elements(*v) - 2); + /* Silence static analyzers */ + assert(m >= 2); + array = new(sd_json_variant*, m - 2); if (!array) return -ENOMEM; From 56df6e5669a8c9a94ff1026f60db1b39033eb469 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:03:14 +0000 Subject: [PATCH 03/21] sd-daemon: add assert before CMSG_SPACE subtraction Coverity flags the subtraction from msg_controllen as a potential underflow. The CMSG_SPACE was added when send_ucred was set, and the subtraction only runs when send_ucred was true, so it is safe. Add an assert to document this invariant. CID#1548074 Follow-up for 64144440a5d2d94482f882b992fd2a4e0dca7a05 --- src/libsystemd/sd-daemon/sd-daemon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 2ab50287b4..2937ac569c 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -603,6 +603,8 @@ static int pid_notify_with_fds_internal( return log_debug_errno(errno, "Failed to send notify message to '%s': %m", e); /* If that failed, try with our own ucred instead */ + /* Silence static analyzers */ + assert(msghdr.msg_controllen >= CMSG_SPACE(sizeof(struct ucred))); msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred)); if (msghdr.msg_controllen == 0) msghdr.msg_control = NULL; From 55354d5930fd0b7952d649d9ad5a850279fc73e1 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:11:48 +0000 Subject: [PATCH 04/21] sd-bus: add asserts for message size overflow safety Coverity flags arithmetic in BUS_MESSAGE_SIZE(), BUS_MESSAGE_BODY_BEGIN() and message_from_header() as potential overflows. The values are validated at message creation time, but add asserts to make the invariants explicit for static analyzers. CID#1548023 CID#1548030 CID#1548046 Follow-up for 6629161f827c82889cf45cfcdce62dcb543eda23 --- src/libsystemd/sd-bus/bus-message.c | 2 ++ src/libsystemd/sd-bus/bus-message.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index c300d511ab..1f278db54e 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -362,6 +362,8 @@ static int message_from_header( if (label) { label_sz = strlen(label); + /* Silence static analyzers */ + assert(label_sz <= SIZE_MAX - ALIGN(sizeof(sd_bus_message)) - 1); a += label_sz + 1; } diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h index c15e947fbf..fe9679393e 100644 --- a/src/libsystemd/sd-bus/bus-message.h +++ b/src/libsystemd/sd-bus/bus-message.h @@ -153,6 +153,9 @@ 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 */ + assert(ALIGN8(m->fields_size) <= SIZE_MAX - sizeof(BusMessageHeader)); + assert(m->body_size <= SIZE_MAX - sizeof(BusMessageHeader) - ALIGN8(m->fields_size)); return sizeof(BusMessageHeader) + ALIGN8(m->fields_size) + @@ -160,6 +163,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 */ + assert(ALIGN8(m->fields_size) <= SIZE_MAX - sizeof(BusMessageHeader)); return sizeof(BusMessageHeader) + ALIGN8(m->fields_size); From 02f848b3752c9de4d00954e77b9069ae717d82fe Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:12:31 +0000 Subject: [PATCH 05/21] user-util: add asserts for buffer allocation overflow safety Coverity flags ALIGN(sizeof(struct passwd/group)) + bufsize as potential overflows in the getpw/getgr helpers. Add asserts to make the bounds explicit for static analyzers. CID#1548047 CID#1548049 CID#1548069 CID#1548070 Follow-up for 75673cd8aee5c6174538e71dd36c7a353c836973 --- src/basic/user-util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/basic/user-util.c b/src/basic/user-util.c index a4ae020c2c..93a3852879 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -1113,6 +1113,8 @@ int getpwnam_malloc(const char *name, struct passwd **ret) { for (;;) { _cleanup_free_ void *buf = NULL; + /* Silence static analyzers */ + assert(bufsize <= SIZE_MAX - ALIGN(sizeof(struct passwd))); buf = malloc0(ALIGN(sizeof(struct passwd)) + bufsize); if (!buf) return -ENOMEM; @@ -1154,6 +1156,8 @@ int getpwuid_malloc(uid_t uid, struct passwd **ret) { for (;;) { _cleanup_free_ void *buf = NULL; + /* Silence static analyzers */ + assert(bufsize <= SIZE_MAX - ALIGN(sizeof(struct passwd))); buf = malloc0(ALIGN(sizeof(struct passwd)) + bufsize); if (!buf) return -ENOMEM; @@ -1198,6 +1202,8 @@ int getgrnam_malloc(const char *name, struct group **ret) { for (;;) { _cleanup_free_ void *buf = NULL; + /* Silence static analyzers */ + assert(bufsize <= SIZE_MAX - ALIGN(sizeof(struct group))); buf = malloc0(ALIGN(sizeof(struct group)) + bufsize); if (!buf) return -ENOMEM; @@ -1237,6 +1243,8 @@ int getgrgid_malloc(gid_t gid, struct group **ret) { for (;;) { _cleanup_free_ void *buf = NULL; + /* Silence static analyzers */ + assert(bufsize <= SIZE_MAX - ALIGN(sizeof(struct group))); buf = malloc0(ALIGN(sizeof(struct group)) + bufsize); if (!buf) return -ENOMEM; From 09bb6448ae221c09a00d1f4a9b45ce8535003319 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:14:07 +0000 Subject: [PATCH 06/21] limits-util: add assert for physical memory calculation overflow Coverity flags (uint64_t) sc * (uint64_t) ps as a potential overflow. Add an assert to make the bounds explicit for static analyzers. CID#1548042 Follow-up for eefc66aa8f77c96a13a78d6c40c79ed7f3d6dc9d --- src/basic/limits-util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basic/limits-util.c b/src/basic/limits-util.c index d48d67dbf7..02fbe92cc7 100644 --- a/src/basic/limits-util.c +++ b/src/basic/limits-util.c @@ -28,6 +28,8 @@ 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; r = cg_get_root_path(&root); From 21cc3216a7c572c6689a7406e37ec0f6915ad3fc Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:14:35 +0000 Subject: [PATCH 07/21] dns-packet: add asserts for allocation overflow safety Coverity flags ALIGN(sizeof(DnsPacket)) + size calculations in dns_packet_new() and dns_packet_dup() as potential overflows. The sizes are bounded by DNS_PACKET_SIZE_MAX but add asserts to make this explicit for static analyzers. CID#1548058 CID#1548076 Follow-up for c73ce96b569e2f10dff64b7dc0bd271972674c2a --- src/shared/dns-packet.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shared/dns-packet.c b/src/shared/dns-packet.c index cdd56d513f..d333b255ee 100644 --- a/src/shared/dns-packet.c +++ b/src/shared/dns-packet.c @@ -120,6 +120,8 @@ int dns_packet_new( a = min_alloc_dsize; /* round up to next page size */ + /* Silence static analyzers */ + assert(a <= SIZE_MAX - ALIGN(sizeof(DnsPacket))); a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket)); /* make sure we never allocate more than useful */ @@ -226,6 +228,8 @@ int dns_packet_dup(DnsPacket **ret, DnsPacket *p) { if (r < 0) return r; + /* Silence static analyzers */ + assert(p->size <= SIZE_MAX - ALIGN(sizeof(DnsPacket))); c = malloc(ALIGN(sizeof(DnsPacket)) + p->size); if (!c) return -ENOMEM; From 3fd6774633d05850de78cc9c095f377e922609ac Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:19:14 +0000 Subject: [PATCH 08/21] networkd-ndisc: add assert for DNSSL allocation overflow safety Coverity flags ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1 as a potential overflow. Domain names are protocol-bounded but add an assert to make this explicit for static analyzers. CID#1548066 Follow-up for 1e7a0e21c97ac1bbc743009e5ec8c12bc6200e19 --- src/network/networkd-ndisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 93965f5253..e6b03c0826 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1909,6 +1909,8 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt, bool zero _cleanup_free_ NDiscDNSSL *s = NULL; NDiscDNSSL *dnssl; + /* Silence static analyzers */ + assert(strlen(*j) <= SIZE_MAX - ALIGN(sizeof(NDiscDNSSL)) - 1); s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*j) + 1); if (!s) return log_oom(); From 96b085c4beb48fe5e3fbed0e13462ca302d0a283 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:20:39 +0000 Subject: [PATCH 09/21] repart: add assert for offset + current_size overflow safety Coverity flags a->after->offset + a->after->current_size as a potential overflow. Both values are validated as not UINT64_MAX by existing asserts, add an explicit overflow check to document the invariant for static analyzers. CID#1548063 Follow-up for e594a3b154bd06c535a934a1cc7231b1ef76df73 --- src/repart/repart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/repart/repart.c b/src/repart/repart.c index d672db6d26..7a8bc00919 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -1247,6 +1247,8 @@ static uint64_t free_area_current_end(Context *context, const FreeArea *a) { assert(a->after->offset != UINT64_MAX); assert(a->after->current_size != UINT64_MAX); + /* Silence static analyzers */ + assert(a->after->current_size <= UINT64_MAX - a->after->offset); /* Calculate where the free area ends, based on the offset of the partition preceding it. */ return round_up_size(a->after->offset + a->after->current_size, context->grain_size) + free_area_available(a); From 331461a5a2ffe323190c4ca6b7bcd35944e36f92 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:28:56 +0000 Subject: [PATCH 10/21] tree-wide: add assert_cc for time constant multiplications Coverity flags compile-time constant multiplications of USEC_PER_SEC, USEC_PER_MSEC, and USEC_PER_HOUR as potential overflows. Add assert_cc() to prove they fit at build time. CID#1548025 CID#1548048 CID#1548055 CID#1548059 Follow-up for 500727c220354b81b68ed6667d9a6f0fafe3ba19 Follow-up for 27d340c772fb1b251085dba7bd5420484f7c5892 Follow-up for e537352b9bfffe6f6286483bff2c7601c78407e3 Follow-up for 1007ec60e664da03b7aea4803c643d991fcf6530 --- src/fsck/fsck.c | 1 + src/shared/utmp-wtmp.c | 2 ++ src/test/test-path.c | 2 ++ src/test/test-time-util.c | 2 ++ 4 files changed, 7 insertions(+) diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 9767568724..43cc208e59 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -218,6 +218,7 @@ static int process_progress(int fd, FILE* console) { /* Only update once every 50ms */ t = now(CLOCK_MONOTONIC); + assert_cc(50 * USEC_PER_MSEC <= USEC_INFINITY); if (last + 50 * USEC_PER_MSEC > t) continue; diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c index 6d150e7dcf..cfc6ae5a3d 100644 --- a/src/shared/utmp-wtmp.c +++ b/src/shared/utmp-wtmp.c @@ -17,6 +17,8 @@ static void init_timestamp(struct utmpx *store, usec_t t) { if (t <= 0) t = now(CLOCK_REALTIME); + /* Silence static analyzers */ + assert_cc(USEC_PER_SEC > 0); store->ut_tv.tv_sec = t / USEC_PER_SEC; store->ut_tv.tv_usec = t % USEC_PER_SEC; } diff --git a/src/test/test-path.c b/src/test/test-path.c index d282cfbf89..82b1f27ed7 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -78,6 +78,8 @@ 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; while (path->state != path_state || service->state != service_state || diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c index 04da9891cb..8250a03e29 100644 --- a/src/test/test-time-util.c +++ b/src/test/test-time-util.c @@ -1113,6 +1113,8 @@ TEST(usec_shift_clock) { assert_se(usec_shift_clock(USEC_INFINITY, CLOCK_REALTIME, CLOCK_MONOTONIC) == USEC_INFINITY); + /* Silence static analyzers */ + assert_cc(9 * USEC_PER_HOUR <= USEC_INFINITY); assert_similar(usec_shift_clock(rt + USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_MONOTONIC), mn + USEC_PER_HOUR); assert_similar(usec_shift_clock(rt + 2*USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_BOOTTIME), bt + 2*USEC_PER_HOUR); assert_se(usec_shift_clock(rt + 3*USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_REALTIME_ALARM) == rt + 3*USEC_PER_HOUR); From a05483a921a518fd283e7cb32dc8c8e816b2ab2c Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:29:58 +0000 Subject: [PATCH 11/21] nss-myhostname: add asserts for buffer index accumulation Coverity flags idx += 2*sizeof(char*) and idx += sizeof(char*) as potential overflows. The idx is bounded by the ms buffer size calculation, add asserts to document this. CID#1548028 Follow-up for e8a7a315391a6a07897122725cd707f4e9ce63d7 --- src/nss-myhostname/nss-myhostname.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index ed470ed298..6a016a1f5c 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -238,9 +238,13 @@ 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*); } else { ((char**) r_aliases)[0] = NULL; + /* Silence static analyzers */ + assert(idx <= buflen - sizeof(char*)); idx += sizeof(char*); } From aa2cc18c762af5c292fdd22357dbbc2c90c66db5 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:37:47 +0000 Subject: [PATCH 12/21] sd-bus: use usec_add() for auth timeout calculation Use the overflow-safe usec_add() instead of raw addition for computing the authentication timeout. CID#1548036 Follow-up for e3017af97310da024ffb378ed155bc1676922ce7 --- src/libsystemd/sd-bus/bus-socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 3c6a2b2747..fdbf557f13 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -788,7 +788,7 @@ int bus_socket_start_auth(sd_bus *b) { bus_get_peercred(b); bus_set_state(b, BUS_AUTHENTICATING); - b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT; + b->auth_timeout = usec_add(now(CLOCK_MONOTONIC), BUS_AUTH_TIMEOUT); if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0) b->accept_fd = false; From 4f5b28b72c7ff78c7eabcce7ad4f0eaebfd5545d Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:41:02 +0000 Subject: [PATCH 13/21] sd-bus: add assert_cc for message allocation size Use CONST_ALIGN_TO to express the compile-time overflow check for the ALIGN(sizeof(sd_bus_message)) + sizeof(BusMessageHeader) allocation, since ALIGN() is not constexpr. CID#1548031 Follow-up for de1c301ed165eb4d04a0c9d4babe97912b5233bb --- src/libsystemd/sd-bus/bus-message.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 1f278db54e..507c5d7ff4 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -464,6 +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); sd_bus_message *t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(BusMessageHeader)); if (!t) return -ENOMEM; From ded2e6e9761ef0838c6913f7acd21e6bf2f05075 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:47:08 +0000 Subject: [PATCH 14/21] test-strv: avoid unsigned wraparound in backwards iteration Use pre-decrement starting from 3 instead of post-decrement starting from 2, so that the unsigned counter does not wrap past zero on the final iteration. CID#1548035 Follow-up for 02f19706a9fd96e05c9ed16aa55ba3d03d008167 --- src/test/test-strv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/test-strv.c b/src/test/test-strv.c index b3468b1cfa..283ae5c865 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -799,14 +799,14 @@ TEST(strv_foreach) { TEST(strv_foreach_backwards) { _cleanup_strv_free_ char **a; - unsigned i = 2; + unsigned i = 3; a = strv_new("one", "two", "three"); assert_se(a); STRV_FOREACH_BACKWARDS(check, a) - ASSERT_STREQ(*check, input_table_multiple[i--]); + ASSERT_STREQ(*check, input_table_multiple[--i]); STRV_FOREACH_BACKWARDS(check, (char**) NULL) assert_not_reached(); From 1eb2bd5aaf14650a3433767fc44ffaef85407b21 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:52:57 +0000 Subject: [PATCH 15/21] repart: use INC_SAFE for partition min size accumulation Use overflow-safe INC_SAFE() instead of raw addition when accumulating partition minimum size components. CID#1548041 Follow-up for 170c98234530af6af487d37057b6e687569f8f91 --- src/repart/repart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/repart/repart.c b/src/repart/repart.c index 7a8bc00919..1cdc0a051f 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -1133,16 +1133,16 @@ static uint64_t partition_min_size(const Context *context, const Partition *p) { uint64_t d = 0; if (p->encrypt != ENCRYPT_OFF) - d += round_up_size(LUKS2_METADATA_KEEP_FREE, context->grain_size); + assert_se(INC_SAFE(&d, round_up_size(LUKS2_METADATA_KEEP_FREE, context->grain_size))); if (p->copy_blocks_size != UINT64_MAX) - d += round_up_size(p->copy_blocks_size, context->grain_size); + assert_se(INC_SAFE(&d, round_up_size(p->copy_blocks_size, context->grain_size))); else if (p->format || p->encrypt != ENCRYPT_OFF) { uint64_t f; /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */ f = partition_fstype_min_size(context, p); - d += f == UINT64_MAX ? context->grain_size : round_up_size(f, context->grain_size); + assert_se(INC_SAFE(&d, f == UINT64_MAX ? context->grain_size : round_up_size(f, context->grain_size))); } if (d > sz) From de2a7614f1703cbba6d978333900a6cdbc401a84 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 21:56:41 +0000 Subject: [PATCH 16/21] calendarspec: use ADD_SAFE for repeat offset calculation Use overflow-safe ADD_SAFE() instead of raw addition when computing the next matching calendar component with repeat. On overflow, skip the component instead of using a bogus value. CID#1548052 Follow-up for a2eb5ea79c53620cfcf616e83bfac0c431247f86 --- src/shared/calendarspec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c index dc13ae0f77..df371ac4f8 100644 --- a/src/shared/calendarspec.c +++ b/src/shared/calendarspec.c @@ -1149,9 +1149,8 @@ static int find_matching_component( } else if (c->repeat > 0) { int k; - k = start + ROUND_UP(*val - start, c->repeat); - - if ((!d_set || k < d) && (stop < 0 || k <= stop)) { + if (ADD_SAFE(&k, start, ROUND_UP(*val - start, c->repeat)) && + (!d_set || k < d) && (stop < 0 || k <= stop)) { d = k; d_set = true; } From 24bdc49c23be1b71f72ebf20586cce07147c9d3e Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 22:00:25 +0000 Subject: [PATCH 17/21] creds-util: add assert for output buffer size overflow safety Coverity flags the multi-term output.iov_len accumulation as a potential overflow. Add an assert after the calculation to verify the result is at least as large as the input, catching wraparound. CID#1548068 Follow-up for 21bc0b6fa1de44b520353b935bf14160f9f70591 --- src/shared/creds-util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index e7db1ff7ef..6fedc500dc 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1068,6 +1068,8 @@ int encrypt_credential_and_warn( ALIGN8(offsetof(struct metadata_credential_header, name) + strlen_ptr(name)) + input->iov_len + 2U * (size_t) bsz + tsz; + /* Silence static analyzers */ + assert(output.iov_len >= input->iov_len); output.iov_base = malloc0(output.iov_len); if (!output.iov_base) From a770fb3e14d434ef25f092c2f3293a43448c92cd Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 22:06:51 +0000 Subject: [PATCH 18/21] 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 d62c1777568ff69034fd5b5d582a2889229f7e20 --- src/boot/linux_x86.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/boot/linux_x86.c b/src/boot/linux_x86.c index cf9707a6cf..349e3fb26c 100644 --- a/src/boot/linux_x86.c +++ b/src/boot/linux_x86.c @@ -195,9 +195,14 @@ EFI_STATUS linux_exec_efi_handover( /* Setup size is determined by offset 0x0202 + byte value at offset 0x0201, which is the same as * offset of the header field and the target from the jump field (which we split for this reason). */ + size_t setup_hdr_len; + if (!ADD_SAFE(&setup_hdr_len, offsetof(SetupHeader, header), image_params->hdr.setup_size)) + setup_hdr_len = sizeof(SetupHeader); + else + setup_hdr_len = MIN(setup_hdr_len, sizeof(SetupHeader)); memcpy(&boot_params->hdr, &image_params->hdr, - offsetof(SetupHeader, header) + image_params->hdr.setup_size); + setup_hdr_len); boot_params->hdr.type_of_loader = 0xff; From 569c849be4ea60d9a83ea346bbb3af4634d7cf25 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 22:15:56 +0000 Subject: [PATCH 19/21] nspawn-oci: add asserts for UID/GID validity after dispatch Coverity flags UINT32_MAX - data.container_id as an underflow when container_id could be UID_INVALID (UINT32_MAX). After successful sd_json_dispatch_uid_gid(), the values are guaranteed valid, but Coverity cannot trace through the callback. Add asserts to document this invariant. CID#1548072 Follow-up for 91c4d1affdba02a323dc2c7caccabe240ccb8302 --- src/nspawn/nspawn-oci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c index 29091bd82c..1fde98a9d9 100644 --- a/src/nspawn/nspawn-oci.c +++ b/src/nspawn/nspawn-oci.c @@ -22,6 +22,7 @@ #include "string-util.h" #include "strv.h" #include "time-util.h" +#include "user-util.h" /* TODO: * OCI runtime tool implementation @@ -685,6 +686,10 @@ static int oci_uid_gid_mappings(const char *name, sd_json_variant *v, sd_json_di if (r < 0) return r; + /* Silence static analyzers, sd_json_dispatch_uid_gid() already validates */ + assert(uid_is_valid(data.host_id)); + assert(uid_is_valid(data.container_id)); + if (data.range > UINT32_MAX - data.host_id || data.range > UINT32_MAX - data.container_id) return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), From 7f133c996c8b1ea9219540ec8f966b64b58d30a6 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 22:32:06 +0000 Subject: [PATCH 20/21] test-json: avoid divide-by-zero coverity warning for index 9 Same fix as d0a066a1a4a391f629f7f52b5005103f8daf411f did for index 10: add iszero_safe() check before dividing by the json variant real value. CID#1587762 Follow-up for d0a066a1a4a391f629f7f52b5005103f8daf411f --- src/test/test-json.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/test-json.c b/src/test/test-json.c index d6308b23e7..016416dc4b 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -665,6 +665,7 @@ static void test_float_match(sd_json_variant *v) { sd_json_variant_integer(sd_json_variant_by_index(v, 8)) == -10); assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v, 9)) && !sd_json_variant_is_integer(sd_json_variant_by_index(v, 9))); + assert_se(!iszero_safe(sd_json_variant_real(sd_json_variant_by_index(v, 9)))); assert_se(fabs(1.0 - (DBL_MIN / 2 / sd_json_variant_real(sd_json_variant_by_index(v, 9)))) <= delta); assert_se(sd_json_variant_is_real(sd_json_variant_by_index(v, 10)) && !sd_json_variant_is_integer(sd_json_variant_by_index(v, 10))); From ea1e81e1179d0a50ff4348b40d64a15870ccdff8 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 28 Mar 2026 22:46:35 +0000 Subject: [PATCH 21/21] journald: add assert for allocated buffer size Coverity flags allocated - 1 as a potential underflow when allocated is 0. After GREEDY_REALLOC succeeds the buffer is guaranteed non-empty, but Coverity cannot trace through the conditional. Add an assert to document this. CID#1548053 Follow-up for ec20fe5ffb8a00469bab209fff6c069bb93c6db2 --- src/journal/journald-stream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 677fb93b75..ee903755cf 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -557,6 +557,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, * always leave room for a terminating NUL we might need to add. */ + /* Silence static analyzers, GREEDY_REALLOC above ensures allocated > 0 */ + assert(allocated > 0); limit = MIN(allocated - 1, MAX(s->manager->config.line_max, STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX)); assert(s->length <= limit); iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length);