Introduce FEATURE_EXEC_PREFER_APPLETS = "re-execute our own

executable if we asked to exec someting with argv[0] == known_applet"
Use it in init. Also respect PATH in init, remove explicit "/sbin" etc
from exec. Patch by Gabriel L. Somlo <somlo@cmu.edu>
This commit is contained in:
Denis Vlasenko 2007-01-21 00:41:04 +00:00
parent b3f3c23f78
commit 2f0c0d0b88
5 changed files with 39 additions and 12 deletions

View File

@ -231,6 +231,14 @@ config SELINUX
Most people will leave this set to 'N'. Most people will leave this set to 'N'.
config FEATURE_EXEC_PREFER_APPLETS
bool "exec prefers applets"
default n
help
This is an experimental option which directs applets about to
call 'exec' to try and find an applicable busybox applet before
searching the executable path for a binary or symlink to execute.
config BUSYBOX_EXEC_PATH config BUSYBOX_EXEC_PATH
string "Path to BusyBox executable" string "Path to BusyBox executable"
default "/proc/self/exe" default "/proc/self/exe"
@ -439,7 +447,7 @@ config INSTALL_APPLET_HARDLINKS
config INSTALL_APPLET_DONT config INSTALL_APPLET_DONT
bool bool
prompt "not installed" prompt "not installed"
depends on FEATURE_INSTALLER || FEATURE_SH_STANDALONE_SHELL depends on FEATURE_INSTALLER || FEATURE_SH_STANDALONE_SHELL || FEATURE_EXEC_PREFER_APPLETS
help help
Do not install applet links. Useful when using the -install feature Do not install applet links. Useful when using the -install feature
or a standalone shell for rescue pruposes. or a standalone shell for rescue pruposes.

View File

@ -389,6 +389,7 @@ static pid_t run(const struct init_action *a)
#include CUSTOMIZED_BANNER #include CUSTOMIZED_BANNER
#endif #endif
"\nPlease press Enter to activate this console. "; "\nPlease press Enter to activate this console. ";
char *prog;
/* Block sigchild while forking. */ /* Block sigchild while forking. */
sigemptyset(&nmask); sigemptyset(&nmask);
@ -560,7 +561,10 @@ static pid_t run(const struct init_action *a)
/* Now run it. The new program will take over this PID, /* Now run it. The new program will take over this PID,
* so nothing further in init.c should be run. */ * so nothing further in init.c should be run. */
execv(cmdpath, cmd); prog = cmdpath;
if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && find_applet_by_name(prog))
prog = CONFIG_BUSYBOX_EXEC_PATH;
execvp(prog, cmd);
/* We're still here? Some error happened. */ /* We're still here? Some error happened. */
message(LOG | CONSOLE, "Bummer, cannot run '%s': %m", cmdpath); message(LOG | CONSOLE, "Bummer, cannot run '%s': %m", cmdpath);
@ -678,6 +682,7 @@ static void exec_signal(int sig ATTRIBUTE_UNUSED)
{ {
struct init_action *a, *tmp; struct init_action *a, *tmp;
sigset_t unblock_signals; sigset_t unblock_signals;
char *prog;
for (a = init_action_list; a; a = tmp) { for (a = init_action_list; a; a = tmp) {
tmp = a->next; tmp = a->next;
@ -713,7 +718,10 @@ static void exec_signal(int sig ATTRIBUTE_UNUSED)
dup(0); dup(0);
messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command); messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command);
execl(a->command, a->command, NULL); prog = a->command;
if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && find_applet_by_name(prog))
prog = CONFIG_BUSYBOX_EXEC_PATH;
execlp(prog, a->command, NULL);
message(CONSOLE | LOG, "exec of '%s' failed: %m", message(CONSOLE | LOG, "exec of '%s' failed: %m",
a->command); a->command);
@ -852,13 +860,13 @@ static void parse_inittab(void)
/* No inittab file -- set up some default behavior */ /* No inittab file -- set up some default behavior */
#endif #endif
/* Reboot on Ctrl-Alt-Del */ /* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL, "/sbin/reboot", ""); new_init_action(CTRLALTDEL, "reboot", "");
/* Umount all filesystems on halt/reboot */ /* Umount all filesystems on halt/reboot */
new_init_action(SHUTDOWN, "/bin/umount -a -r", ""); new_init_action(SHUTDOWN, "umount -a -r", "");
/* Swapoff on halt/reboot */ /* Swapoff on halt/reboot */
if(ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "/sbin/swapoff -a", ""); if(ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
/* Prepare to restart init when a HUP is received */ /* Prepare to restart init when a HUP is received */
new_init_action(RESTART, "/sbin/init", ""); new_init_action(RESTART, "init", "");
/* Askfirst shell on tty1-4 */ /* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell, ""); new_init_action(ASKFIRST, bb_default_login_shell, "");
new_init_action(ASKFIRST, bb_default_login_shell, VC_2); new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
@ -1039,9 +1047,9 @@ int init_main(int argc, char **argv)
{ {
message(CONSOLE,"Low memory: forcing swapon."); message(CONSOLE,"Low memory: forcing swapon.");
/* swapon -a requires /proc typically */ /* swapon -a requires /proc typically */
new_init_action(SYSINIT, "/bin/mount -t proc proc /proc", ""); new_init_action(SYSINIT, "mount -t proc proc /proc", "");
/* Try to turn on swap */ /* Try to turn on swap */
new_init_action(SYSINIT, "/sbin/swapon -a", ""); new_init_action(SYSINIT, "swapon -a", "");
run_actions(SYSINIT); /* wait and removing */ run_actions(SYSINIT); /* wait and removing */
} }
} }
@ -1068,7 +1076,10 @@ int init_main(int argc, char **argv)
putenv("SELINUX_INIT=YES"); putenv("SELINUX_INIT=YES");
if (selinux_init_load_policy(&enforce) == 0) { if (selinux_init_load_policy(&enforce) == 0) {
execv(argv[0], argv); char *prog = argv[0];
if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && find_applet_by_name(prog))
prog = CONFIG_BUSYBOX_EXEC_PATH;
execvp(prog, argv);
} else if (enforce > 0) { } else if (enforce > 0) {
/* SELinux in enforcing mode but load_policy failed */ /* SELinux in enforcing mode but load_policy failed */
/* At this point, we probably can't open /dev/console, so log() won't work */ /* At this point, we probably can't open /dev/console, so log() won't work */

View File

@ -183,14 +183,17 @@ pid_t spawn(char **argv)
/* Why static? */ /* Why static? */
static int failed; static int failed;
pid_t pid; pid_t pid;
void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0; char *prog;
// Be nice to nommu machines. // Be nice to nommu machines.
failed = 0; failed = 0;
pid = vfork(); pid = vfork();
if (pid < 0) return pid; if (pid < 0) return pid;
if (!pid) { if (!pid) {
execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv); prog = argv[0];
if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && find_applet_by_name(prog))
prog = CONFIG_BUSYBOX_EXEC_PATH;
execvp(prog, argv);
// We're sharing a stack with blocked parent, let parent know we failed // We're sharing a stack with blocked parent, let parent know we failed
// and then exit to unblock parent (but don't run atexit() stuff, which // and then exit to unblock parent (but don't run atexit() stuff, which

View File

@ -27,6 +27,7 @@ CONFIG_FEATURE_SYSLOG=y
CONFIG_FEATURE_SUID_CONFIG=y CONFIG_FEATURE_SUID_CONFIG=y
CONFIG_FEATURE_SUID_CONFIG_QUIET=y CONFIG_FEATURE_SUID_CONFIG_QUIET=y
# CONFIG_SELINUX is not set # CONFIG_SELINUX is not set
#CONFIG_FEATURE_EXEC_PREFER_APPLETS is not set
CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
# #

View File

@ -6528,6 +6528,10 @@ setjobctl(int on)
int ofd; int ofd;
ofd = fd = open(_PATH_TTY, O_RDWR); ofd = fd = open(_PATH_TTY, O_RDWR);
if (fd < 0) { if (fd < 0) {
/* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
* That sometimes helps to acquire controlling tty.
* Obviously, a workaround for bugs when someone
* failed to provide a controlling tty to bash! :) */
fd += 3; fd += 3;
while (!isatty(fd) && --fd >= 0) while (!isatty(fd) && --fd >= 0)
; ;