From: Jérémie Galarneau Date: Tue, 8 Oct 2019 21:34:51 +0000 (-0400) Subject: Fix: sessiond: unbounded elf section data size allocation X-Git-Tag: v2.11.0~11 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=a1243fdc865a6d3320d8a74a9e92efa459e68ca4;p=lttng-tools.git Fix: sessiond: unbounded elf section data size allocation The size of ELF sections is read from a user-provided file descriptor to an ELF file which could be malformed. In theory it would not really be a problem as the run-as process is automatically restarted after a crash (e.g. SIGBUS). The alloctions are now bounded to the smallest of 512MB or the file's size. The limit is kept high to accomodate very large binaries and not impose an artificial limitation. In time, this should be replaced by an mmap() of the section's data rather than copying to a private set of pages. 1405558 Untrusted value as argument The argument could be controlled by an attacker, who could invoke the function with arbitrary values (for example, a very high or negative buffer size). In lttng_elf_get_sdt_probe_offsets: An unscrutinized value from an untrusted source used as argument to a function (for example, a buffer size) (CWE-20) Reported-by: Coverity Scan Signed-off-by: Jérémie Galarneau --- diff --git a/src/common/lttng-elf.c b/src/common/lttng-elf.c index 5d4b93bbb..91afcfdea 100644 --- a/src/common/lttng-elf.c +++ b/src/common/lttng-elf.c @@ -43,6 +43,7 @@ #define NOTE_STAPSDT_SECTION_NAME ".note.stapsdt" #define NOTE_STAPSDT_NAME "stapsdt" #define NOTE_STAPSDT_TYPE 3 +#define MAX_SECTION_DATA_SIZE 512 * 1024 * 1024 #if BYTE_ORDER == LITTLE_ENDIAN #define NATIVE_ELF_ENDIANNESS ELFDATA2LSB @@ -191,6 +192,7 @@ struct lttng_elf_sym { struct lttng_elf { int fd; + size_t file_size; uint8_t bitness; uint8_t endianness; /* Offset in bytes to start of section names string table. */ @@ -531,16 +533,28 @@ struct lttng_elf *lttng_elf_create(int fd) struct lttng_elf_shdr section_names_shdr; struct lttng_elf *elf = NULL; int ret; + struct stat stat_buf; if (fd < 0) { goto error; } + ret = fstat(fd, &stat_buf); + if (ret) { + PERROR("Failed to determine size of elf file"); + goto error; + } + if (!S_ISREG(stat_buf.st_mode)) { + ERR("Refusing to initialize lttng_elf from non-regular file"); + goto error; + } + elf = zmalloc(sizeof(struct lttng_elf)); if (!elf) { PERROR("Error allocating struct lttng_elf"); goto error; } + elf->file_size = (size_t) stat_buf.st_size; elf->fd = dup(fd); if (elf->fd < 0) { @@ -632,6 +646,8 @@ char *lttng_elf_get_section_data(struct lttng_elf *elf, int ret; off_t section_offset; char *data; + const size_t max_alloc_size = min_t(size_t, MAX_SECTION_DATA_SIZE, + elf->file_size); if (!elf || !shdr) { goto error; @@ -643,6 +659,11 @@ char *lttng_elf_get_section_data(struct lttng_elf *elf, goto error; } + if (shdr->sh_size > max_alloc_size) { + ERR("ELF section size exceeds maximal allowed size of %zu bytes", + max_alloc_size); + goto error; + } data = zmalloc(shdr->sh_size); if (!data) { PERROR("Error allocating buffer for ELF section data");