wrongly auxvt in __uClibc_main

Filippo ARCIDIACONO filippo.arcidiacono at st.com
Mon Nov 26 15:45:18 UTC 2012


Folks,
we have seen some issues recently in uClibc related to the way the aux 
vect is managed inside __uClibc_main.

Running a set-[user,group]-ID ELF binaries with some 'unsecure' 
environment variable set (i.e LD_LIBRARY_PATH or LD_PRELOAD), auxvt is 
wrongly set in __uClibc_main.

The problem is caused by the call to _dl_unsetenv function in ldso.c 
that pops the specific env variables
from the stack adding a corresponding number of NULL entries at the end 
of the environments stack.
To be clearer, at the beginning the stack looks like as expected 
(assuming M env variables and N aux_vect entries)

argc
argv[0]
...
argv[argc-1]
NULL /* separator */
envp[0]
...
LD_LIBRARY_PATH
...
envp[M-1]
NULL /* separator */
aux_vect[0]
.......
aux_vect[N-1]
NULL /* separator */

After the LD_LIBRARY_PATH has been removed by _dl_unsetenv, the stack 
will look like to libc

argc
argv[0]
...
argv[argc-1]
NULL /* separator */
envp[0]
...
envp[M-2]
NULL /* filled by ld.so */
NULL /* separator */
auxvect[0]
.......
aux_vect[N-1]
NULL /* separator */

Currently, __uClibc_main assumes that there is just one NULL separator 
between environments and aux_vect entries, as from the extract below:

     aux_dat = (unsigned long*)__environ;
     while (*aux_dat) {
         aux_dat++;
     }
     aux_dat++; <-- This move the aux_dat of just 1 position to skip the 
NULL separator

Due to this, the local auxvt array (initialised by memset) won't be 
filled with proper values.
All the following code that use the auxvt variable is wrong.

For example, the check for the SUID binaries will be affected, as it 
needs to verify AT_UID, AT_GID, AT-EUID and AT_EGID entries (all NULL)

A potential dirty fix or work-around would be to replace "aux_dat++" 
statement with "while (!(*aux_dat++))" to skip all the NULL entries, but 
doing so there is no way to detect the case where aux_vect is not present.

So, the proper fix we have in mind is to completely remove the aux vect 
handling from libc and keep it solely into the dynamic linker (as 
actually glibc is doing). If libc needs to check some values from aux 
vect, it can refer to globals exported by the ld.so.

Feedback are really welcome,
Regards,
Filippo


More information about the uClibc mailing list