summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo ARCIDIACONO <filippo.arcidiacono@st.com>2012-12-14 11:40:05 +0100
committerCarmelo Amoroso <carmelo.amoroso@st.com>2013-05-13 10:08:11 +0200
commitf74663a2e6e3395d8f7e83efc28799c85842bed1 (patch)
tree987d3ec6777427e6408579d986664d358c09dbe3
parent458076d59ef9849f79d27e21b6094b0b3a85fbb4 (diff)
libc: deal with aux vect inside __uClibc_main only if !SHARED
It's not safe to use the aux vect inside __uClibc_main if we are running with shared libraries, because it could have been already modified. For example, if some constructor plays with environment variables by using unsetenv, the modifications done into the stack to unset an environment variable, have impacts on the aux vect due to the extra NULL entries added. Due to this, __uClibc_main is not able to detect where the aux vect starts, so all the entries that are used by __uClibc_main (AT_UID, AT_EUID, AT_GID, AT_EGID, AT_PAGESZ and possibly other arch specific) are impacted. Same side effect on the aux vect is caused by the ld.so when running a SUID program with some of the unsecure environment variables set, that will be unset by the ld.so itself. In order to fix this issue, it needs to handle aux vect entries into __uClibc_main only if SHARED is not defined. In SHARED case, libc refers to __dl_secure and _dl_pagesize as initialised by the ld.so where the aux vext is still untouched. Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com> Reviewed-by: Carmelo Amoroso <carmelo.amoroso@st.com> Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
-rw-r--r--ldso/ldso/ldso.c2
-rw-r--r--libc/misc/elf/dl-support.c4
-rw-r--r--libc/misc/internals/__uClibc_main.c22
3 files changed, 21 insertions, 7 deletions
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 70413d563..2d7a2349d 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -64,7 +64,7 @@ struct elf_resolve *_dl_trace_prelink_map = NULL; /* Library module for preli
bool _dl_verbose = true; /* On by default */
bool prelinked = false;
#endif
-static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
+int _dl_secure = 1; /* Are we dealing with setuid stuff? */
#ifdef __SUPPORT_LD_DEBUG__
char *_dl_debug = NULL;
diff --git a/libc/misc/elf/dl-support.c b/libc/misc/elf/dl-support.c
index f1946924c..ae77f5261 100644
--- a/libc/misc/elf/dl-support.c
+++ b/libc/misc/elf/dl-support.c
@@ -28,6 +28,7 @@ void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
ElfW(Phdr) *_dl_phdr;
size_t _dl_phnum;
+size_t _dl_pagesize;
void internal_function _dl_aux_init (ElfW(auxv_t) *av);
void internal_function _dl_aux_init (ElfW(auxv_t) *av)
@@ -37,6 +38,9 @@ void internal_function _dl_aux_init (ElfW(auxv_t) *av)
/* Get the number of program headers from the aux vect */
_dl_phnum = (size_t) av[AT_PHNUM].a_un.a_val;
+
+ /* Get the pagesize from the aux vect */
+ _dl_pagesize = (av[AT_PAGESZ].a_un.a_val) ? (size_t) av[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
}
#if defined(USE_TLS) && USE_TLS
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c
index 8a3646cde..a37751f2d 100644
--- a/libc/misc/internals/__uClibc_main.c
+++ b/libc/misc/internals/__uClibc_main.c
@@ -140,6 +140,11 @@ extern void (*__fini_array_end []) (void) attribute_hidden;
# endif
#endif
+#ifdef SHARED
+extern int _dl_secure;
+#endif
+extern size_t _dl_pagesize;
+
const char *__uclibc_progname = "";
#if !defined __UCLIBC_HAS___PROGNAME__ && defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__
# define __progname program_invocation_short_name
@@ -186,6 +191,7 @@ static void __check_one_fd(int fd, int mode)
}
}
+#ifndef SHARED
static int __check_suid(void)
{
uid_t uid, euid;
@@ -202,6 +208,7 @@ static int __check_suid(void)
return 0; /* we are not suid */
}
#endif
+#endif
/* __uClibc_init completely initialize uClibc so it is ready to use.
*
@@ -313,7 +320,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
char **argv, void (*app_init)(void), void (*app_fini)(void),
void (*rtld_fini)(void), void *stack_end attribute_unused)
{
-#ifndef __ARCH_HAS_NO_LDSO__
+#if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
unsigned long *aux_dat;
ElfW(auxv_t) auxvt[AT_EGID + 1];
#endif
@@ -339,7 +346,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
__environ = &argv[argc];
}
-#ifndef __ARCH_HAS_NO_LDSO__
+#if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED
/* Pull stuff from the ELF header when possible */
memset(auxvt, 0x00, sizeof(auxvt));
aux_dat = (unsigned long*)__environ;
@@ -354,13 +361,11 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
}
aux_dat += 2;
}
-#ifndef SHARED
/* Get the program headers (_dl_phdr) from the aux vector
It will be used into __libc_setup_tls. */
_dl_aux_init (auxvt);
#endif
-#endif
/* We need to initialize uClibc. If we are dynamically linked this
* may have already been completed by the shared lib loader. We call
@@ -368,15 +373,20 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,
__uClibc_init();
#ifndef __ARCH_HAS_NO_LDSO__
- /* Make certain getpagesize() gives the correct answer */
- __pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
+ /* Make certain getpagesize() gives the correct answer.
+ * _dl_pagesize is defined into ld.so if SHARED or into libc.a otherwise. */
+ __pagesize = _dl_pagesize;
+#ifndef SHARED
/* Prevent starting SUID binaries where the stdin. stdout, and
* stderr file descriptors are not already opened. */
if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) ||
(auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
(auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val ||
auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val)))
+#else
+ if (_dl_secure)
+#endif
{
__check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW);
__check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW);