1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-02 10:51:20 +03:00

journal: avoid buffer overread when locale name is too long

We could potentially create an unterminated string and then call normal string
operations on it. Let's be more careful: first remove the suffix we ignore anyway,
then find if the string is of acceptable length, and possibly ignore it if it
is too long. The code rejects lengths above 31 bytes. Language names that are
actually used are much shorter, so this doesn't matter much.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-01-27 09:37:26 +01:00
parent cd8c98d7a7
commit 00e1adf8b1

View File

@ -46,7 +46,8 @@ typedef struct CatalogHeader {
typedef struct CatalogItem {
sd_id128_t id;
char language[32];
char language[32]; /* One byte is used for termination, so the maximum allowed
* length of the string is actually 31 bytes. */
le64_t offset;
} CatalogItem;
@ -556,25 +557,44 @@ static const char *find_id(void *p, sd_id128_t id) {
const char *loc;
loc = setlocale(LC_MESSAGES, NULL);
if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) {
strncpy(key.language, loc, sizeof(key.language));
key.language[strcspn(key.language, ".@")] = 0;
if (!isempty(loc) && !STR_IN_SET(loc, "C", "POSIX")) {
size_t len;
f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func);
if (!f) {
char *e;
len = strcspn(loc, ".@");
if (len > sizeof(key.language) - 1)
log_debug("LC_MESSAGES value too long, ignoring: \"%.*s\"", (int) len, loc);
else {
strncpy(key.language, loc, len);
key.language[len] = '\0';
e = strchr(key.language, '_');
if (e) {
*e = 0;
f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func);
f = bsearch(&key,
(const uint8_t*) p + le64toh(h->header_size),
le64toh(h->n_items),
le64toh(h->catalog_item_size),
(comparison_fn_t) catalog_compare_func);
if (!f) {
char *e;
e = strchr(key.language, '_');
if (e) {
*e = 0;
f = bsearch(&key,
(const uint8_t*) p + le64toh(h->header_size),
le64toh(h->n_items),
le64toh(h->catalog_item_size),
(comparison_fn_t) catalog_compare_func);
}
}
}
}
if (!f) {
zero(key.language);
f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func);
f = bsearch(&key,
(const uint8_t*) p + le64toh(h->header_size),
le64toh(h->n_items),
le64toh(h->catalog_item_size),
(comparison_fn_t) catalog_compare_func);
}
if (!f)