Skip to content

Commit

Permalink
libkmod: Use correct data types for ELF arithmetic
Browse files Browse the repository at this point in the history
Make sure that no input files could overflow internal variables
used for calculations.

This prevents wrong output and out of boundary writes.

Signed-off-by: Tobias Stoeckmann <[email protected]>
Link: #272
Signed-off-by: Lucas De Marchi <[email protected]>
  • Loading branch information
stoeckmann authored and lucasdemarchi committed Jan 2, 2025
1 parent ad689ac commit bcff223
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions libkmod/libkmod-elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,10 +541,9 @@ static inline void elf_get_modversion_lengths(const struct kmod_elf *elf, size_t
/* array will be allocated with strings in a single malloc, just free *array */
int kmod_elf_get_modversions(const struct kmod_elf *elf, struct kmod_modversion **array)
{
size_t off, crclen, namlen, verlen;
uint64_t sec_off, size;
size_t i, count, crclen, namlen, verlen;
uint64_t off, sec_off, size;
struct kmod_modversion *a;
int i, count;

elf_get_modversion_lengths(elf, &verlen, &crclen, &namlen);

Expand All @@ -562,6 +561,10 @@ int kmod_elf_get_modversions(const struct kmod_elf *elf, struct kmod_modversion
return -EINVAL;

count = size / verlen;
if (count > INT_MAX) {
ELFDBG(elf, "too many modversions: %zu\n", count);
return -EINVAL;
}

*array = a = malloc(sizeof(struct kmod_modversion) * count);
if (*array == NULL)
Expand All @@ -573,7 +576,7 @@ int kmod_elf_get_modversions(const struct kmod_elf *elf, struct kmod_modversion
size_t nlen = strnlen(symbol, namlen);

if (nlen == namlen) {
ELFDBG(elf, "symbol name at index %d too long\n", i);
ELFDBG(elf, "symbol name at index %zu too long\n", i);
return -EINVAL;
}

Expand Down Expand Up @@ -704,8 +707,7 @@ static int kmod_elf_get_symbols_symtab(const struct kmod_elf *elf,
uint64_t i, last, off, size;
const char *strings;
struct kmod_modversion *a;
int count;
size_t total_size;
size_t count, total_size;

*array = NULL;

Expand Down Expand Up @@ -740,6 +742,11 @@ static int kmod_elf_get_symbols_symtab(const struct kmod_elf *elf,
}
}

if (count > INT_MAX) {
ELFDBG(elf, "too many symbols: %zu\n", count);
return -EINVAL;
}

/* sizeof(struct kmod_modversion) * count */
if (umulsz_overflow(sizeof(struct kmod_modversion), count, &total_size)) {
return -ENOMEM;
Expand Down Expand Up @@ -973,8 +980,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
uint64_t versionslen, strtablen, symtablen, str_off, sym_off, ver_off;
uint64_t str_sec_off, sym_sec_off;
struct kmod_modversion *a;
size_t namlen, verlen, symlen, crclen;
int i, count, symcount, vercount;
size_t i, count, namlen, vercount, verlen, symcount, symlen, crclen;
bool handle_register_symbols;
uint8_t *visited_versions;
uint64_t *symcrcs;
Expand Down Expand Up @@ -1095,7 +1101,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
if (name_off >= strtablen) {
ELFDBG(elf,
".strtab is %" PRIu64
" bytes, but .symtab entry %d wants to access offset %" PRIu32
" bytes, but .symtab entry %zu wants to access offset %" PRIu32
".\n",
strtablen, i, name_off);
free(visited_versions);
Expand All @@ -1105,7 +1111,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,

name = elf_get_mem(elf, str_off + name_off);
if (name[0] == '\0') {
ELFDBG(elf, "empty symbol name at index %d\n", i);
ELFDBG(elf, "empty symbol name at index %zu\n", i);
continue;
}

Expand All @@ -1128,7 +1134,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
nlen = strnlen(name, namlen);

if (nlen == namlen) {
ELFDBG(elf, "symbol name at index %d too long\n",
ELFDBG(elf, "symbol name at index %zu too long\n",
i);
free(visited_versions);
free(symcrcs);
Expand All @@ -1140,6 +1146,14 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
}
}

if (count > INT_MAX) {
ELFDBG(elf, "too many symbols: %zu\n", count);
free(visited_versions);
free(symcrcs);
*array = NULL;
return -EINVAL;
}

if (count == 0) {
free(visited_versions);
free(symcrcs);
Expand Down Expand Up @@ -1201,7 +1215,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,

name = elf_get_mem(elf, str_off + name_off);
if (name[0] == '\0') {
ELFDBG(elf, "empty symbol name at index %d\n", i);
ELFDBG(elf, "empty symbol name at index %zu\n", i);
continue;
}

Expand Down

0 comments on commit bcff223

Please sign in to comment.