Assorted basic/shared/home/import hardening fixes flagged by kres (#42950)

This commit is contained in:
Lennart Poettering
2026-07-14 23:31:53 +02:00
committed by GitHub
9 changed files with 240 additions and 40 deletions
+19 -5
View 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");
}
+49 -10
View File
@@ -357,6 +357,33 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le
return t;
}
/* Walk backwards from 'end' (exclusive) to the start of the last complete UTF-8 character, without
* descending below 'start', validate it and return a pointer to its first byte, optionally decoding it
* into *ret_c. Returns NULL on a truncated or otherwise malformed sequence. */
static const char* find_previous_unichar(const char *start, const char *end, char32_t *ret_c) {
const char *p;
int r;
assert(start);
assert(end);
assert(end > start);
for (p = end; p > start; ) {
p--;
if (((uint8_t) *p & 0xc0) != 0x80) /* Found a non-continuation byte, i.e. a character start. */
break;
}
r = utf8_encoded_valid_unichar(p, end - p);
if (r < 0 || p + r != end)
return NULL;
if (ret_c)
assert_se(utf8_encoded_to_unichar(p, ret_c) == r);
return p;
}
char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
size_t x, k, len, len2;
const char *i, *j;
@@ -400,11 +427,13 @@ char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
continue; /* ANSI sequences don't take up any space in output */
}
char32_t c;
r = utf8_encoded_to_unichar(i, &c);
r = utf8_encoded_valid_unichar(i, s + old_length - i);
if (r < 0)
return NULL;
char32_t c;
assert_se(utf8_encoded_to_unichar(i, &c) == r);
int w = unichar_iswide(c) ? 2 : 1;
if (k + w > x)
break;
@@ -431,9 +460,9 @@ char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
continue;
}
tt = utf8_prev_char(t);
r = utf8_encoded_to_unichar(tt, &c);
if (r < 0)
/* Find the previous complete UTF-8 character inside the retained suffix. */
tt = find_previous_unichar(i, t, &c);
if (!tt)
return NULL;
w = unichar_iswide(c) ? 2 : 1;
@@ -451,11 +480,21 @@ char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
if (k >= new_length) {
/* Make space for ellipsis, if required and possible. We know that the edge character is not
* part of an ANSI sequence (because then we'd skip it). If the last character we looked at
* was wide, we don't need to make space. */
if (j < s + old_length)
j = utf8_next_char(j);
else if (i > s)
i = utf8_prev_char(i);
* was wide, we don't need to make space.
* Move the edge by one complete UTF-8 character within the input slice. */
if (j < s + old_length) {
r = utf8_encoded_valid_unichar(j, s + old_length - j);
if (r < 0)
return NULL;
j += r;
} else if (i > s) {
const char *tt = find_previous_unichar(s, i, NULL);
if (!tt)
return NULL;
i = tt;
}
}
len = i - s;