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

  • From: Jaromir Capik <jcapik@xxxxxxxxxx>
  • To: procps@xxxxxxxxxxxxx
  • Date: Tue, 3 Mar 2015 07:44:59 -0500 (EST)

Hello Peter.

It seems the auxiliary vector values can be obtained
by parsing the /proc/self/auxv file.
I'm testing the solution right now and will let you know.

Regards,
Jaromir.


> > Hello and thank you for procps(-ng),
> 
> Hello Peter.
> 
>  
> > 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've already answered this in the RH Bugzilla.
> The getauxval is not a suitable replacement till glibc 2.19
> as it didn't support the errno=ENOENT check in the previous
> versions and that makes impossible to distinguish between
> zero values and non-existent types.
> Unfortunately the AT_SECURE type often contains zero
> and therefore there's no easy way around that.
> We would have to check the glibc version and switch between
> the calls accordingly, but that would make the solution
> a bit cumbersome. It's easier to document the limitation
> when using dlopen for accessing the libprocps functions.
> Users will have to initialize the library prior manipulating
> with the environment.
> 
> If you know about any suitable way how to resolve that,
> then tell me, please.
> 
> Thanks,
> Jaromir.
> 
> --
> Jaromir Capik
> Red Hat Czech, s.r.o.
> Software Engineer / Secondary Arch
> 
> Email: jcapik@xxxxxxxxxx
> Web: www.cz.redhat.com
> Red Hat Czech s.r.o., Purkynova 99/71, 612 45, Brno, Czech Republic
> IC: 27690016
> 
> 
> 
> > 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: