diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/misc/internals/__uClibc_main.c | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 937428a9e..c41f7ccf2 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -18,6 +18,12 @@ #include <string.h> #include <elf.h> #include <bits/uClibc_page.h> +#include <paths.h> +#include <unistd.h> +#include <asm/errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> #ifdef __UCLIBC_PROPOLICE__ extern void __guard_setup(void); #endif @@ -46,19 +52,58 @@ extern void weak_function __pthread_initialize_minimal(void); * Note: Apparently we must initialize __environ to ensure that the weak * environ symbol is also included. */ +char **__environ = 0; +weak_alias(__environ, environ); size_t __pagesize = 0; -char **__environ = 0; const char *__progname = 0; -weak_alias(__environ, environ); -/* FIXME */ -#if 0 -extern int _dl_secure; -int __secure = 0; -weak_alias(__secure, _dl_secure); + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 #endif +extern int __libc_fcntl(int fd, int cmd, ...); +extern int __libc_open(const char *file, int flags, ...); + +static void __check_one_fd(int fd, int mode) +{ + /* Check if the specified fd is already open */ + if (unlikely(__libc_fcntl(fd, F_GETFD)==-1 && *(__errno_location())==EBADF)) + { + /* The descriptor is probably not open, so try to use /dev/null */ + struct stat st; + int nullfd = __libc_open(_PATH_DEVNULL, mode); + /* /dev/null is major=1 minor=3. Make absolutely certain + * that is in fact the device that we have opened and not + * some other wierd file... */ + if ( (nullfd!=fd) || fstat(fd, &st) || !S_ISCHR(st.st_mode) || + (st.st_rdev != makedev(1, 3))) + { + /* Somebody is trying some trickery here... */ + while (1) { + abort(); + } + } + } +} + +static int __check_suid(void) +{ + uid_t uid, euid; + gid_t gid, egid; + + uid = getuid(); + euid = geteuid(); + gid = getgid(); + egid = getegid(); + + if(uid == euid && gid == egid) { + return 0; + } + return 1; +} + /* __uClibc_init completely initialize uClibc so it is ready to use. * @@ -94,16 +139,6 @@ void __uClibc_init(void) __pthread_initialize_minimal(); #endif - /* FIXME */ -#if 0 - /* Some security at this point. Prevent starting a SUID binary - * where the standard file descriptors are not opened. We have - * to do this only for statically linked applications since - * otherwise the dynamic loader did the work already. */ - if (unlikely (__secure!=NULL)) - __libc_check_standard_fds (); -#endif - #ifdef __UCLIBC_HAS_LOCALE__ /* Initialize the global locale structure. */ if (likely(_locale_init!=NULL)) @@ -161,7 +196,21 @@ __uClibc_start_main(int argc, char **argv, char **envp, } aux_dat += 2; } + + /* Make certain getpagesize() gives the correct answer */ __pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; + + /* Prevent starting SUID binaries where the stdin. stdout, and + * stderr file descriptors are not already opened. */ + if ((auxvt[AT_UID].a_un.a_val==-1 && __check_suid()) || + (auxvt[AT_UID].a_un.a_val != -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))) + { + __check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW); + __check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW); + __check_one_fd (STDERR_FILENO, O_RDWR | O_NOFOLLOW); + } #endif __progname = *argv; |