]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
log: add upper bound to journal iovec accounting
authorLuca Boccassi <luca.boccassi@gmail.com>
Thu, 9 Jul 2026 10:30:02 +0000 (11:30 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 14 Jul 2026 15:43:28 +0000 (16:43 +0100)
Use checked arithmetic before clamping the journal iovec length.
Stop copying input iovecs once the fixed journal vector is full.

Follow-up for e69cc9eb36fd6e76710b4d5f4bb7013980fb5174

src/basic/log.c
src/test/test-log.c

index 29702abd44e40126c4cc3e224e8b3aee1ecfefce..17ea26d8a410ee2bdf145253a920ce9273ae8b41 100644 (file)
@@ -726,7 +726,11 @@ static int write_to_journal(
         if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_JOURNAL])
                 return 0;
 
-        iovec_len = MIN(6 + log_context_num_fields() * 3, IOVEC_MAX);
+        if (!MUL_SAFE(&iovec_len, log_context_num_fields(), 3) ||
+            !ADD_SAFE(&iovec_len, iovec_len, 6))
+                iovec_len = IOVEC_MAX;
+        else
+                iovec_len = MIN(iovec_len, IOVEC_MAX);
         iovec = newa(struct iovec, iovec_len);
 
         log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
@@ -1024,7 +1028,11 @@ int log_struct_internal(
                         int r;
                         bool fallback = false;
 
-                        iovec_len = MIN(17 + log_context_num_fields() * 3, IOVEC_MAX);
+                        if (!MUL_SAFE(&iovec_len, log_context_num_fields(), 3) ||
+                            !ADD_SAFE(&iovec_len, iovec_len, 17))
+                                iovec_len = IOVEC_MAX;
+                        else
+                                iovec_len = MIN(iovec_len, IOVEC_MAX);
                         iovec = newa(struct iovec, iovec_len);
 
                         /* If the journal is available do structured logging.
@@ -1123,15 +1131,21 @@ int log_struct_iovec_internal(
 
                 char header[LINE_MAX];
                 struct iovec *iovec;
-                size_t n = 0, iovec_len;
+                size_t n = 0, iovec_len, n_context_iovec, n_input_iovec_expanded;
 
-                iovec_len = MIN(1 + n_input_iovec * 2 + log_context_num_fields() * 3, IOVEC_MAX);
+                if (!MUL_SAFE(&n_input_iovec_expanded, n_input_iovec, 2) ||
+                    !MUL_SAFE(&n_context_iovec, log_context_num_fields(), 3) ||
+                    !ADD_SAFE(&iovec_len, 1, n_input_iovec_expanded) ||
+                    !ADD_SAFE(&iovec_len, iovec_len, n_context_iovec))
+                        iovec_len = IOVEC_MAX;
+                else
+                        iovec_len = MIN(iovec_len, IOVEC_MAX);
                 iovec = newa(struct iovec, iovec_len);
 
                 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
 
                 iovec[n++] = IOVEC_MAKE_STRING(header);
-                for (size_t i = 0; i < n_input_iovec; i++) {
+                for (size_t i = 0; i < n_input_iovec && n + 2 <= iovec_len; i++) {
                         iovec[n++] = input_iovec[i];
                         iovec[n++] = IOVEC_MAKE_STRING("\n");
                 }
index fb23776b211d240d99a91e92dfc79298f0277e6b..61468a3229ce54a15d726ebd725cc8126a66b837 100644 (file)
@@ -145,6 +145,28 @@ TEST(log_format_iovec) {
                                   LOG_ITEM("FOOFOO=%hu-%llu", (unsigned short) 4, (long long unsigned) 3));
 }
 
+TEST(log_struct_iovec_many_fields) {
+        LogTarget old_target = log_get_target();
+        struct iovec iovec[1024];
+
+        log_set_target(LOG_TARGET_JOURNAL);
+        log_open();
+        if (log_on_console()) {
+                log_set_target(old_target);
+                log_open();
+                return (void) log_tests_skipped("journal socket is not available");
+        }
+
+        iovec[0] = IOVEC_MAKE_STRING("MESSAGE=many fields");
+        for (size_t i = 1; i < ELEMENTSOF(iovec); i++)
+                iovec[i] = IOVEC_MAKE_STRING("FIELD=value");
+
+        ASSERT_OK(log_struct_iovec(LOG_INFO, iovec, ELEMENTSOF(iovec)));
+
+        log_set_target(old_target);
+        log_open();
+}
+
 static void test_log_struct(void) {
         log_struct(LOG_INFO,
                    "MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(),