From 201df28d9019c82e49beba85403a9fab27491332 Mon Sep 17 00:00:00 2001 From: Roman Marchenko Date: Thu, 29 Dec 2016 09:53:19 +0200 Subject: [PATCH] Fixing invalid reads in find_elf_note due to setenv invocation Resolves issue on mailing list and Red Hat Bugzilla 1163404. Change-Id: I7d162bb30ad45e907203fb5192f18d54bab17818 Signed-off-by: Roman Marchenko --- proc/sysinfo.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/proc/sysinfo.c b/proc/sysinfo.c index f318376..85a9cb9 100644 --- a/proc/sysinfo.c +++ b/proc/sysinfo.c @@ -36,6 +36,9 @@ #include /* htons */ #endif +#include +#include + long smp_num_cpus; /* number of CPUs */ #define BAD_OPEN_MESSAGE \ @@ -242,15 +245,67 @@ static void old_Hertz_hack(void){ extern char** environ; -/* for ELF executables, notes are pushed before environment and args */ -static unsigned long find_elf_note(unsigned long findme){ +static unsigned long find_elf_note(unsigned long type) +{ + ElfW(auxv_t) auxv_struct; + ElfW(auxv_t) *auxv_temp; + FILE *fd; + int i; + static ElfW(auxv_t) *auxv = NULL; unsigned long *ep = (unsigned long *)environ; - while(*ep++); - while(*ep){ - if(ep[0]==findme) return ep[1]; - ep+=2; + unsigned long ret_val = NOTE_NOT_FOUND; + + + if(!auxv) { + + fd = fopen("/proc/self/auxv", "rb"); + + if(!fd) { // can't open auxv? that could be caused by euid change + // ... and we need to fall back to the old and unsafe + // ... method that doesn't work when calling library + // ... functions with dlopen -> FIXME :( + + while(*ep++); // for ELF executables, notes are pushed + while(*ep){ // ... before environment and args + if(ep[0]==type) return ep[1]; + ep+=2; + } + return NOTE_NOT_FOUND; + } + + auxv = (ElfW(auxv_t) *) malloc(getpagesize()); + if (!auxv) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + i = 0; + do { + fread(&auxv_struct, sizeof(ElfW(auxv_t)), 1, fd); + auxv[i] = auxv_struct; + i++; + } while (auxv_struct.a_type != AT_NULL); + + fclose(fd); + + } + + auxv_temp = auxv; + i = 0; + do { + if(auxv_temp[i].a_type == type) { + ret_val = (unsigned long)auxv_temp[i].a_un.a_val; + break; + } + i++; + } while (auxv_temp[i].a_type != AT_NULL); + + if (auxv){ + auxv_temp = NULL; + free(auxv); + auxv = NULL; } - return NOTE_NOT_FOUND; + return ret_val; } int have_privs; -- 2.7.4