changeset 370:c7a26e26ad08

Add TOYBOX_SUID.
author Rob Landley <rob@landley.net>
date Tue, 05 Jan 2010 12:17:05 -0600
parents 5715eed39575
children 2cec41ee6eea
files Config.in lib/lib.c lib/lib.h main.c toys.h
diffstat 5 files changed, 39 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/Config.in	Tue Jan 05 10:48:32 2010 -0600
+++ b/Config.in	Tue Jan 05 12:17:05 2010 -0600
@@ -11,6 +11,14 @@
 	  With no arguments, shows available commands.  First argument is
 	  name of a command to run, followed by any arguments to that command.
 
+config TOYBOX_SUID
+	bool "SUID support"
+	default y
+	help
+	  Support for suid commands, which run as root.  This means toybox must
+	  be installed suid root, and drops permissions before running commands
+	  which do not require root access.
+
 config TOYBOX_FREE
 	bool "Free memory unnecessarily"
 	default n
--- a/lib/lib.c	Tue Jan 05 10:48:32 2010 -0600
+++ b/lib/lib.c	Tue Jan 05 12:17:05 2010 -0600
@@ -369,6 +369,16 @@
 		if (!*p) break;
 	}
 }
+
+// setuid() can fail (for example, too many processes belonging to that user),
+// which opens a security hole if the process continues as the original user.
+
+void xsetuid(uid_t uid)
+{
+	if (setuid(uid)) perror_exit("xsetuid");
+}
+
+
 // Find all file in a colon-separated path with access type "type" (generally
 // X_OK or R_OK).  Returns a list of absolute paths to each file found, in
 // order.
--- a/lib/lib.h	Tue Jan 05 10:48:32 2010 -0600
+++ b/lib/lib.h	Tue Jan 05 12:17:05 2010 -0600
@@ -81,6 +81,7 @@
 char *xabspath(char *path);
 void xchdir(char *path);
 void xmkpath(char *path, int mode);
+void xsetuid(uid_t uid);
 struct string_list *find_in_path(char *path, char *filename);
 void utoa_to_buf(unsigned n, char *buf, unsigned buflen);
 void itoa_to_buf(int n, char *buf, unsigned buflen);
--- a/main.c	Tue Jan 05 10:48:32 2010 -0600
+++ b/main.c	Tue Jan 05 12:17:05 2010 -0600
@@ -64,6 +64,21 @@
 
 void toy_init(struct toy_list *which, char *argv[])
 {
+	// Drop permissions for non-suid commands.
+
+	if (CFG_TOYBOX_SUID) {
+		uid_t uid = getuid(), euid = geteuid();
+
+		if (!(which->flags & TOYFLAG_STAYROOT)) {
+			if (uid != euid) xsetuid(euid=uid);
+		} else if (CFG_TOYBOX_DEBUG && uid)
+			error_exit("Not installed suid root");
+
+		if ((which->flags & TOYFLAG_NEEDROOT) && euid)
+			error_exit("Not root");
+
+	}
+
 	// Free old toys contents here?
 
 	toys.which = which;
--- a/toys.h	Tue Jan 05 10:48:32 2010 -0600
+++ b/toys.h	Tue Jan 05 12:17:05 2010 -0600
@@ -68,6 +68,11 @@
 // Start applet with a umask of 0 (saves old umask in this.old_umask)
 #define TOYFLAG_UMASK    (1<<5)
 
+// This applet runs as root.
+#define TOYFLAG_STAYROOT (1<<6)
+#define TOYFLAG_NEEDROOT (1<<7)
+#define TOYFLAG_ROOTONLY (TOYFLAG_STAYROOT|TOYFLAG_NEEDROOT)
+
 // Array of available applets
 
 extern struct toy_list {