[procps] find_elf_note invalid read if setenv has been called before libproc init

  • From: Stig <thatsafunnyname@xxxxxxxxx>
  • To: procps@xxxxxxxxxxxxx
  • Date: Wed, 12 Nov 2014 13:44:25 +0000

Hello and thank you for procps(-ng),

A valgrind test at work reported invalid reads from libproc (version 3.2.8
but I think the same code exists in the latest procps-ng).
A colleageue of mine found that when setenv is called before libproc is
initialized we will see the behaviour (invalid read), init_libproc in
proc/sysinfo.c calling find_elf_note which finds notes for ELF executables
based of environ, which at this point has changed.  The suggestion from my
colleageue was to use getauxval.
I have a reproducer below, a main executable must call setenv for a logical
that does not exist before libproc is initialized.

Cheers,
Peter (Stig) Edwards

mkdir /tmp/procps
cd /tmp/procps

> cat main.c
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>

void  *FunctionLib;
int   (*Function)();
const char *dlError;

int main(){

  printf("main()\n");

  setenv("TEST_DUMMY_ENV_MUST_NOT_EXIST","X",1);

  FunctionLib = dlopen("/tmp/libmyproc.so",RTLD_LAZY);
  dlError = dlerror();
  if( dlError ) {
    printf("dlopen return-%s- \n", dlError);
    exit(1);
  }

  Function    = dlsym( FunctionLib, "print_vsize");
  dlError = dlerror();
  if( dlError ) {
    printf("dlsym return-%s- \n", dlError);
    exit(1);
  }

  int rc = (*Function)( );
  dlError = dlerror();
  if( dlError ) {
    printf("function dlerror-%s-\n",dlError);
  }

  if(dlclose(FunctionLib)){
    dlError = dlerror();
    if( dlError ) {
      printf("dlclose return-%s-\n",dlError);
    }
  }

}

> cat myproc.h
void print_vsize();

> cat myproc.c
#include "myproc.h"
#include <stdio.h>
#include <proc/readproc.h>

void print_vsize() {
  printf("print_vsize()\n");
  struct proc_t usage;
  look_up_our_self(&usage);
  printf("vsize: %lu\n", usage.vsize);
}

rm -f libmyproc.so /tmp/libmyproc.so main.o ; gcc -fPIC -c myproc.c -lproc
&& gcc -fPIC -c main.c -ldl &&  gcc -shared myproc.o -o libmyproc.so -lproc
&& gcc main.o -Wl -o main -ldl && cp libmyproc.so /tmp/ &&
/usr/bin/valgrind --leak-check=yes ./main
==2849== Memcheck, a memory error detector
==2849== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==2849== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==2849== Command: ./main
==2849==
main()
==2849== Invalid read of size 8
==2849==    at 0x3CCAC09D8C: ??? (in /lib64/libproc-3.2.8.so)
==2849==    by 0x3CCAC0AD55: ??? (in /lib64/libproc-3.2.8.so)
==2849==    by 0x3CCAC03712: ??? (in /lib64/libproc-3.2.8.so)
==2849==  Address 0x4c22170 is 0 bytes after a block of size 304 alloc'd
==2849==    at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==2849==    by 0x4A06B62: realloc (vg_replace_malloc.c:662)
==2849==    by 0x3CCA83540C: __add_to_environ (in /lib64/libc-2.12.so)
==2849==    by 0x4A0A5D9: setenv (mc_replace_strmem.c:1755)
==2849==    by 0x4007FF: main (in /tmp/procps/main)
==2849==
==2849== Invalid read of size 8
==2849==    at 0x3CCAC09E34: ??? (in /lib64/libproc-3.2.8.so)
==2849==    by 0x3CCAC0AD55: ??? (in /lib64/libproc-3.2.8.so)
==2849==    by 0x3CCAC03712: ??? (in /lib64/libproc-3.2.8.so)
==2849==  Address 0x4c22170 is 0 bytes after a block of size 304 alloc'd
==2849==    at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==2849==    by 0x4A06B62: realloc (vg_replace_malloc.c:662)
==2849==    by 0x3CCA83540C: __add_to_environ (in /lib64/libc-2.12.so)
==2849==    by 0x4A0A5D9: setenv (mc_replace_strmem.c:1755)
==2849==    by 0x4007FF: main (in /tmp/procps/main)
==2849==
2.4+ kernel w/o ELF notes? -- report this
print_vsize()
vsize: 126840832
==2849==
==2849== HEAP SUMMARY:
==2849==     in use at exit: 0 bytes in 0 blocks
==2849==   total heap usage: 14 allocs, 14 frees, 3,185 bytes allocated
==2849==
==2849== All heap blocks were freed -- no leaks are possible
==2849==
==2849== For counts of detected and suppressed errors, rerun with: -v
==2849== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)

This was using kernel 2.6.32-431.29.2.el6.x86_64 on RHEL6.5 with
procps-3.2.8-25.el6 and gcc-4.4.7-4.el6.

Other related posts: