Skip to content

Commit

Permalink
libkmod: Fix overflow in kmod_module_hex_to_str
Browse files Browse the repository at this point in the history
If an overly long signature is found in a module file, it is possible to
trigger an out of boundary write in kmod_module_hex_to_str due to
integer and subsequent heap buffer overflow.

This approach replaces malloc + sprintf with a simple hex-lookup and a
strbuf approach, being slightly faster in real life scenarios while
adding around 100 bytes to library size. A much faster approach could be
done without strbuf and using our overflow check functions, but
readability should win here.

Signed-off-by: Tobias Stoeckmann <[email protected]>
Link: #236
Signed-off-by: Lucas De Marchi <[email protected]>
  • Loading branch information
stoeckmann authored and lucasdemarchi committed Nov 12, 2024
1 parent 7ff978b commit b6b27d3
Showing 1 changed file with 18 additions and 17 deletions.
35 changes: 18 additions & 17 deletions libkmod/libkmod-module.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <sys/types.h>
#include <sys/wait.h>

#include <shared/strbuf.h>
#include <shared/util.h>

#include "libkmod.h"
Expand Down Expand Up @@ -1798,29 +1799,29 @@ static struct kmod_list *kmod_module_info_append(struct kmod_list **list, const

static char *kmod_module_hex_to_str(const char *hex, size_t len)
{
char *str;
int i;
int j;
static const char digits[] = "0123456789ABCDEF";
struct strbuf sbuf;
const size_t line_limit = 20;
size_t str_len;

str_len = len * 3; /* XX: or XX\0 */
str_len += ((str_len + line_limit - 1) / line_limit - 1) * 3; /* \n\t\t */
strbuf_init(&sbuf);

str = malloc(str_len);
if (str == NULL)
return NULL;

for (i = 0, j = 0; i < (int)len; i++) {
j += sprintf(str + j, "%02X", (unsigned char)hex[i]);
if (i < (int)len - 1) {
str[j++] = ':';
for (size_t i = 0; i < len; i++) {
if (!strbuf_pushchar(&sbuf, digits[(hex[i] >> 4) & 0x0F]) ||
!strbuf_pushchar(&sbuf, digits[hex[i] & 0x0F]))
goto fail;
if (i < len - 1) {
if (!strbuf_pushchar(&sbuf, ':'))
goto fail;

if ((i + 1) % line_limit == 0)
j += sprintf(str + j, "\n\t\t");
if ((i + 1) % line_limit == 0 &&
!strbuf_pushchars(&sbuf, "\n\t\t"))
goto fail;
}
}
return str;
return strbuf_steal(&sbuf);
fail:
strbuf_release(&sbuf);
return NULL;
}

static struct kmod_list *kmod_module_info_append_hex(struct kmod_list **list,
Expand Down

0 comments on commit b6b27d3

Please sign in to comment.