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

  • From: Jaromir Capik <jcapik@xxxxxxxxxx>
  • To: procps@xxxxxxxxxxxxx, Stig <thatsafunnyname@xxxxxxxxx>
  • Date: Mon, 2 Mar 2015 14:44:20 -0500 (EST)

----- Original Message -----
> From: "Stig" <thatsafunnyname@xxxxxxxxx>
> To: procps@xxxxxxxxxxxxx
> Sent: Wednesday, November 12, 2014 2:44:25 PM
> Subject: [procps] find_elf_note invalid read if setenv has been called before 
> libproc init
> 
> 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: