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:
parent
b3f3c23f78
commit
2f0c0d0b88
10
Config.in
10
Config.in
@ -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.
|
||||||
|
29
init/init.c
29
init/init.c
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -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)
|
||||||
;
|
;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user