diff options
| author | Eric Andersen <andersen@codepoet.org> | 2004-10-27 09:44:00 +0000 | 
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2004-10-27 09:44:00 +0000 | 
| commit | 5853eed77b485b3f47d6239bc0262c7b0a055a6b (patch) | |
| tree | d81a8339468436c78d65c6ede5a32f6208148990 /libc/misc/internals/__uClibc_main.c | |
| parent | b33b788f8978551f4232328d76c3ddc6e5a5c582 (diff) | |
| download | uClibc-alpine-5853eed77b485b3f47d6239bc0262c7b0a055a6b.tar.bz2 uClibc-alpine-5853eed77b485b3f47d6239bc0262c7b0a055a6b.tar.xz  | |
Fix up __uClibc_init() for so that we prevent starting SUID
binaries where the standard file descriptors are not opened.
 -Erik
Diffstat (limited to 'libc/misc/internals/__uClibc_main.c')
| -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;  | 
