Blame SOURCES/procps-ng-3.3.10-find_elf_note-memory-error-fix.patch

6ec062
diff --git a/proc/sysinfo.c b/proc/sysinfo.c
6ec062
index 1435de1..1d2b8e2 100644
6ec062
--- a/proc/sysinfo.c
6ec062
+++ b/proc/sysinfo.c
6ec062
@@ -36,6 +36,9 @@
6ec062
 #include <netinet/in.h>  /* htons */
6ec062
 #endif
6ec062
 
6ec062
+#include <link.h>
6ec062
+#include <elf.h>
6ec062
+
6ec062
 long smp_num_cpus;     /* number of CPUs */
6ec062
 long page_bytes;       /* this architecture's page size */
6ec062
 
6ec062
@@ -249,15 +252,67 @@ static void old_Hertz_hack(void){
6ec062
 
6ec062
 extern char** environ;
6ec062
 
6ec062
-/* for ELF executables, notes are pushed before environment and args */
6ec062
-static unsigned long find_elf_note(unsigned long findme){
6ec062
+static unsigned long find_elf_note(unsigned long type)
6ec062
+{
6ec062
+  ElfW(auxv_t) auxv_struct;
6ec062
+  ElfW(auxv_t) *auxv_temp;
6ec062
+  FILE *fd;
6ec062
+  int i;
6ec062
+  static ElfW(auxv_t) *auxv = NULL;
6ec062
   unsigned long *ep = (unsigned long *)environ;
6ec062
-  while(*ep++);
6ec062
-  while(*ep){
6ec062
-    if(ep[0]==findme) return ep[1];
6ec062
-    ep+=2;
6ec062
+  unsigned long ret_val = NOTE_NOT_FOUND;
6ec062
+
6ec062
+
6ec062
+  if(!auxv) {
6ec062
+
6ec062
+    fd = fopen("/proc/self/auxv", "rb");
6ec062
+
6ec062
+    if(!fd) {  // can't open auxv? that could be caused by euid change
6ec062
+               // ... and we need to fall back to the old and unsafe
6ec062
+               // ... method that doesn't work when calling library
6ec062
+               // ... functions with dlopen -> FIXME :(
6ec062
+
6ec062
+      while(*ep++);  // for ELF executables, notes are pushed
6ec062
+      while(*ep){    // ... before environment and args
6ec062
+        if(ep[0]==type) return ep[1];
6ec062
+        ep+=2;
6ec062
+      }
6ec062
+      return NOTE_NOT_FOUND;
6ec062
+    }
6ec062
+
6ec062
+    auxv = (ElfW(auxv_t) *) malloc(getpagesize());
6ec062
+    if (!auxv) {
6ec062
+      perror("malloc");
6ec062
+      exit(EXIT_FAILURE);
6ec062
+    }
6ec062
+
6ec062
+    i = 0;
6ec062
+    do {
6ec062
+      fread(&auxv_struct, sizeof(ElfW(auxv_t)), 1, fd);
6ec062
+      auxv[i] = auxv_struct;
6ec062
+      i++;
6ec062
+    } while (auxv_struct.a_type != AT_NULL);
6ec062
+
6ec062
+    fclose(fd);
6ec062
+
6ec062
+  }
6ec062
+
6ec062
+  auxv_temp = auxv;
6ec062
+  i = 0;
6ec062
+  do {
6ec062
+    if(auxv_temp[i].a_type == type) {
6ec062
+      ret_val = (unsigned long)auxv_temp[i].a_un.a_val;
6ec062
+      break;
6ec062
+    }
6ec062
+    i++;
6ec062
+  } while (auxv_temp[i].a_type != AT_NULL);
6ec062
+
6ec062
+  if (auxv){
6ec062
+	  auxv_temp = NULL;
6ec062
+	  free(auxv);
6ec062
+	  auxv = NULL;
6ec062
   }
6ec062
-  return NOTE_NOT_FOUND;
6ec062
+  return ret_val;
6ec062
 }
6ec062
 
6ec062
 int have_privs;