changeset 1467:d1411369baa7

Two problems: 1) Sometimes toy_exec() needs to re-exec to gain dropped root permissions, 2) shouldn't recurse forever without exec, stack depth increases and we may leak other resources. Limit it to ~5 levels.
author Rob Landley <rob@landley.net>
date Tue, 09 Sep 2014 23:42:25 -0500
parents aa0ae038e275
children 6fd5e556f89d
files main.c toys.h
diffstat 2 files changed, 8 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/main.c	Tue Sep 09 20:13:03 2014 -0500
+++ b/main.c	Tue Sep 09 23:42:25 2014 -0500
@@ -119,12 +119,18 @@
 }
 
 // Like exec() but runs an internal toybox command instead of another file.
-// Only returns if it can't find the command, otherwise exit() when done.
+// Only returns if it can't run command internally, otherwise exit() when done.
 void toy_exec(char *argv[])
 {
   struct toy_list *which;
 
+  // Return if we can't find it, or need to re-exec to acquire root,
+  // or if stack depth is getting silly.
   if (!(which = toy_find(argv[0]))) return;
+  if (toys.recursion && (which->flags & TOYFLAG_ROOTONLY) && getuid()) return;
+  if (toys.recursion++ > 5) return;
+
+  // Run command
   toy_init(which, argv);
   if (toys.which) toys.which->toy_main();
   if (fflush(NULL) || ferror(stdout)) perror_exit("write");
--- a/toys.h	Tue Sep 09 20:13:03 2014 -0500
+++ b/toys.h	Tue Sep 09 23:42:25 2014 -0500
@@ -132,6 +132,7 @@
   int toycount;            // Total number of commands in this build
   int signal;              // generic_signal() records what signal it saw here
   int signalfd;            // and writes signal to this fd, if set
+  int recursion;           // How many nested calls to toy_exec()
 
   // This is at the end so toy_init() doesn't zero it.
   jmp_buf *rebound;        // longjmp here instead of exit when do_rebound set