[CRIU] [RFC 1/4] compel: separate get_strings_section from __handle_elf
Dmitry Safonov
dsafonov at virtuozzo.com
Fri May 6 09:14:56 PDT 2016
I copied __ptr_oob* checks from util-vdso.c.
That will allow to check not only structure begin pointers,
but structure end also.
Before this patch code checked if strings section's header pointer is OOB,
but it did it after dereferencing this pointer, which is meaningless.
Now it checks:
- OOB of sections table,
- strings section's header should be inside sections table,
- check strings section with it's length for OOB.
In the very next patches I will add tests for this functions and
other compel-related changes.
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
compel/handle-elf.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 64 insertions(+), 9 deletions(-)
diff --git a/compel/handle-elf.c b/compel/handle-elf.c
index 9c6fb7e366de..2e8d33c0fbf7 100644
--- a/compel/handle-elf.c
+++ b/compel/handle-elf.c
@@ -16,16 +16,36 @@
#include "piegen.h"
#include "handle-elf.h"
-static bool __ptr_oob(const void *ptr, const void *start, const size_t size)
+/* TODO: merge with util-vdso.c part in criu header */
+/* Check if pointer is out-of-bound */
+static bool
+__ptr_oob(const uintptr_t ptr, const uintptr_t start, const size_t size)
{
- const void *end = (const void *)((const unsigned long)start + size);
- return ptr > end || ptr < start;
+ uintptr_t end = start + size;
+
+ return ptr >= end || ptr < start;
+}
+
+/* Check if pointed structure's end is out-of-bound */
+static bool __ptr_struct_end_oob(const uintptr_t ptr, const size_t struct_size,
+ const uintptr_t start, const size_t size)
+{
+ /* the last byte of the structure should be inside [begin, end) */
+ return __ptr_oob(ptr + struct_size - 1, start, size);
+}
+
+/* Check if pointed structure is out-of-bound */
+static bool __ptr_struct_oob(const uintptr_t ptr, const size_t struct_size,
+ const uintptr_t start, const size_t size)
+{
+ return __ptr_oob(ptr, start, size) ||
+ __ptr_struct_end_oob(ptr, struct_size, start, size);
}
static bool test_pointer(const void *ptr, const void *start, const size_t size,
const char *name, const char *file, const int line)
{
- if (__ptr_oob(ptr, start, size)) {
+ if (__ptr_oob((const uintptr_t)ptr, (const uintptr_t)start, size)) {
pr_err("Corrupted pointer %p (%s) at %s:%d\n",
ptr, name, file, line);
return true;
@@ -70,6 +90,43 @@ static bool is_header_supported(Ehdr_t *hdr)
return true;
}
+static const char *get_strings_section(Ehdr_t *hdr, uintptr_t mem, size_t size)
+{
+ size_t sec_table_size = hdr->e_shentsize * hdr->e_shnum;
+ uintptr_t sec_table = mem + hdr->e_shoff;
+ Shdr_t *secstrings_hdr;
+ uintptr_t addr;
+
+ if (__ptr_struct_oob(sec_table, sec_table_size, mem, size)) {
+ pr_err("Section table [%#zx, %#zx) is out of [%#zx, %#zx)\n",
+ sec_table, sec_table + sec_table_size, mem, mem + size);
+ return NULL;
+ }
+
+ /*
+ * strings section header's offset in section headers table is
+ * (size of section header * index of string section header)
+ */
+ addr = sec_table + hdr->e_shentsize * hdr->e_shstrndx;
+ if (__ptr_struct_oob(addr, sizeof(Shdr_t),
+ sec_table, sec_table + sec_table_size)) {
+ pr_err("String section header @%#zx is out of [%#zx, %#zx)\n",
+ addr, sec_table, sec_table + sec_table_size);
+ return NULL;
+ }
+ secstrings_hdr = (void*)addr;
+
+ addr = mem + secstrings_hdr->sh_offset;
+ if (__ptr_struct_oob(addr, secstrings_hdr->sh_size, mem, size)) {
+ pr_err("String section @%#zx size %#lx is out of [%#zx, %#zx)\n",
+ addr, (unsigned long)secstrings_hdr->sh_size,
+ mem, mem + size);
+ return NULL;
+ }
+
+ return (void*)addr;
+}
+
int __handle_elf(void *mem, size_t size)
{
const char *symstrings = NULL;
@@ -77,7 +134,6 @@ int __handle_elf(void *mem, size_t size)
Sym_t *symbols = NULL;
Ehdr_t *hdr = mem;
- Shdr_t *secstrings_hdr = NULL;
Shdr_t *strtab_hdr = NULL;
Shdr_t **sec_hdrs = NULL;
const char *secstrings;
@@ -103,10 +159,9 @@ int __handle_elf(void *mem, size_t size)
goto err;
}
- secstrings_hdr = mem + hdr->e_shoff + hdr->e_shentsize * hdr->e_shstrndx;
- secstrings = mem + secstrings_hdr->sh_offset;
- ptr_func_exit(secstrings_hdr);
- ptr_func_exit(secstrings);
+ secstrings = get_strings_section(hdr, (uintptr_t)mem, size);
+ if (!secstrings)
+ goto err;
pr_debug("Sections\n");
pr_debug("------------\n");
--
2.8.0
More information about the CRIU
mailing list