mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-08-09 06:14:34 +02:00
In kallsyms__parse(), the loop reading symbol names iterates with i <
sizeof(symbol_name), which allows i to reach sizeof(symbol_name) upon
loop exit. The subsequent symbol_name[i] = '\0' then writes one byte
past the end of the stack-allocated symbol_name[] array.
Fix this by changing the loop bound to KSYM_NAME_LEN, so the null
terminator always lands within the array. The overflow is triggerable by
a kallsyms entry with a symbol name of KSYM_NAME_LEN+1 or more
characters (e.g., long Rust mangled names or a malicious
/proc/kallsyms).
Fixes: 53df2b9344 ("libsymbols kallsyms: Parse using io api")
Signed-off-by: Rui Qi <qirui.001@bytedance.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
82 lines
1.4 KiB
C
82 lines
1.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include "symbol/kallsyms.h"
|
|
#include "api/io.h"
|
|
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
u8 kallsyms2elf_type(char type)
|
|
{
|
|
type = tolower(type);
|
|
return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT;
|
|
}
|
|
|
|
bool kallsyms__is_function(char symbol_type)
|
|
{
|
|
symbol_type = toupper(symbol_type);
|
|
return symbol_type == 'T' || symbol_type == 'W';
|
|
}
|
|
|
|
static void read_to_eol(struct io *io)
|
|
{
|
|
int ch;
|
|
|
|
for (;;) {
|
|
ch = io__get_char(io);
|
|
if (ch < 0 || ch == '\n')
|
|
return;
|
|
}
|
|
}
|
|
|
|
int kallsyms__parse(const char *filename, void *arg,
|
|
int (*process_symbol)(void *arg, const char *name,
|
|
char type, u64 start))
|
|
{
|
|
struct io io;
|
|
char bf[BUFSIZ];
|
|
int err;
|
|
|
|
io.fd = open(filename, O_RDONLY, 0);
|
|
|
|
if (io.fd < 0)
|
|
return -1;
|
|
|
|
io__init(&io, io.fd, bf, sizeof(bf));
|
|
|
|
err = 0;
|
|
while (!io.eof) {
|
|
__u64 start;
|
|
int ch;
|
|
size_t i;
|
|
char symbol_type;
|
|
char symbol_name[KSYM_NAME_LEN + 1];
|
|
|
|
if (io__get_hex(&io, &start) != ' ') {
|
|
read_to_eol(&io);
|
|
continue;
|
|
}
|
|
symbol_type = io__get_char(&io);
|
|
if (io__get_char(&io) != ' ') {
|
|
read_to_eol(&io);
|
|
continue;
|
|
}
|
|
for (i = 0; i < KSYM_NAME_LEN; i++) {
|
|
ch = io__get_char(&io);
|
|
if (ch < 0 || ch == '\n')
|
|
break;
|
|
symbol_name[i] = ch;
|
|
}
|
|
symbol_name[i] = '\0';
|
|
|
|
if (i == KSYM_NAME_LEN)
|
|
read_to_eol(&io);
|
|
|
|
err = process_symbol(arg, symbol_name, symbol_type, start);
|
|
if (err)
|
|
break;
|
|
}
|
|
|
|
close(io.fd);
|
|
return err;
|
|
}
|