[uClibc-cvs] CVS uClibc/libc/misc/internals

CVS User andersen andersen at codepoet.org
Wed Oct 27 09:44:01 UTC 2004


Update of /var/cvs/uClibc/libc/misc/internals
In directory nail:/tmp/cvs-serv21410/libc/misc/internals

Modified Files:
	__uClibc_main.c 
Log Message:
Fix up __uClibc_init() for so that we prevent starting SUID
binaries where the standard file descriptors are not opened.
 -Erik


--- /var/cvs/uClibc/libc/misc/internals/__uClibc_main.c	2004/08/16 22:16:45	1.42
+++ /var/cvs/uClibc/libc/misc/internals/__uClibc_main.c	2004/10/27 09:44:00	1.43
@@ -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 @@
  * 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 @@
 	__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 @@
 	}
 	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;



More information about the uClibc-cvs mailing list