diff options
| author | Ron Yorston <rmy@pobox.com> | 2024-10-07 12:50:51 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2024-10-07 12:50:51 +0100 |
| commit | 5b30de8fba414f75cb25faebf5cd8f391e1deb75 (patch) | |
| tree | dcb181f71a4ef80715976d5f5ef6554c019d53d7 /shell | |
| parent | 041f1d29671c58b839c8e63fced7aa901fbade45 (diff) | |
| download | busybox-w32-5b30de8fba414f75cb25faebf5cd8f391e1deb75.tar.gz busybox-w32-5b30de8fba414f75cb25faebf5cd8f391e1deb75.tar.bz2 busybox-w32-5b30de8fba414f75cb25faebf5cd8f391e1deb75.zip | |
ash: more changes to noexec applets
- Change the 'flags' argument to shellexec()/tryexec() so it only
indicates that it's permissible to run ash_main() directly. The
flag is only set TRUE in forkshell_shellexec().
- The check for a script with an interpreter which is an applet is
now performed for all calls to tryexec(), not just those that
originate from evalcommand().
Saves 64-80 bytes.
GitHub issue #461.
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 46 |
1 files changed, 16 insertions, 30 deletions
diff --git a/shell/ash.c b/shell/ash.c index 3865b72d4..679846574 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -9090,28 +9090,24 @@ static struct tblentry **cmdtable; | |||
| 9090 | static int builtinloc = -1; /* index in path of %builtin, or -1 */ | 9090 | static int builtinloc = -1; /* index in path of %builtin, or -1 */ |
| 9091 | 9091 | ||
| 9092 | 9092 | ||
| 9093 | #if ENABLE_PLATFORM_MINGW32 | ||
| 9094 | # define EXEC_FLAG 2 | ||
| 9095 | |||
| 9096 | static void | 9093 | static void |
| 9097 | tryexec(IF_FEATURE_SH_STANDALONE(int applet_no, const char *nfpath, int flags,) | 9094 | #if ENABLE_PLATFORM_MINGW32 |
| 9095 | tryexec(IF_FEATURE_SH_STANDALONE(int applet_no, const char *path, int noexec,) | ||
| 9098 | const char *cmd, char **argv, char **envp) | 9096 | const char *cmd, char **argv, char **envp) |
| 9099 | #else | 9097 | #else |
| 9100 | static void | ||
| 9101 | tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp) | 9098 | tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp) |
| 9102 | #endif | 9099 | #endif |
| 9103 | { | 9100 | { |
| 9104 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE | 9101 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE |
| 9105 | struct forkshell *fs = (struct forkshell *)sticky_mem_start; | ||
| 9106 | interp_t interp; | 9102 | interp_t interp; |
| 9107 | #endif | 9103 | #endif |
| 9108 | #if ENABLE_FEATURE_SH_STANDALONE | 9104 | #if ENABLE_FEATURE_SH_STANDALONE |
| 9109 | if (applet_no >= 0) { | 9105 | if (applet_no >= 0) { |
| 9110 | # if ENABLE_PLATFORM_MINGW32 | 9106 | # if ENABLE_PLATFORM_MINGW32 |
| 9111 | /* Treat all applets as NOEXEC, including the shell itself | 9107 | /* Treat all applets as NOEXEC, including the shell itself |
| 9112 | * unless it was invoked by the exec builtin. */ | 9108 | * if we were called from forkshell_shellexec(). */ |
| 9113 | if (applet_main[applet_no] != ash_main || !(flags & EXEC_FLAG)) { | ||
| 9114 | run_noexec: | 9109 | run_noexec: |
| 9110 | if (applet_main[applet_no] != ash_main || noexec) { | ||
| 9115 | /* mingw-w64's getopt() uses __argv[0] as the program name */ | 9111 | /* mingw-w64's getopt() uses __argv[0] as the program name */ |
| 9116 | __argv[0] = (char *)cmd; | 9112 | __argv[0] = (char *)cmd; |
| 9117 | /* 'which' wants to know if it was invoked from a standalone | 9113 | /* 'which' wants to know if it was invoked from a standalone |
| @@ -9154,17 +9150,10 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c | |||
| 9154 | add_win32_extension((char *)cmd); | 9150 | add_win32_extension((char *)cmd); |
| 9155 | 9151 | ||
| 9156 | # if ENABLE_FEATURE_SH_STANDALONE | 9152 | # if ENABLE_FEATURE_SH_STANDALONE |
| 9157 | /* If nfpath is non-NULL evalcommand() has determined this | 9153 | /* If the command is a script with an interpreter which is an |
| 9158 | * command doesn't need a fork(). Even it's NULL we can | 9154 | * applet, we can run it as if it were a noexec applet. */ |
| 9159 | * possibly avoid a fork if this is a FS_SHELLEXEC shell. */ | 9155 | if (parse_interpreter(cmd, &interp)) { |
| 9160 | if (nfpath == NULL && (fs && fs->fpid == FS_SHELLEXEC)) | 9156 | applet_no = find_applet_by_name_for_sh(interp.name, path); |
| 9161 | nfpath = pathval(); | ||
| 9162 | |||
| 9163 | /* If nfpath is non-NULL and the command is a script with an | ||
| 9164 | * interpreter which is an applet, we can run it as if it | ||
| 9165 | * were a noexec applet. */ | ||
| 9166 | if (nfpath && parse_interpreter(cmd, &interp)) { | ||
| 9167 | applet_no = find_applet_by_name_for_sh(interp.name, nfpath); | ||
| 9168 | if (applet_no >= 0) { | 9157 | if (applet_no >= 0) { |
| 9169 | argv[0] = (char *)cmd; | 9158 | argv[0] = (char *)cmd; |
| 9170 | /* evalcommand()/spawn_forkshell() add two elements before argv */ | 9159 | /* evalcommand()/spawn_forkshell() add two elements before argv */ |
| @@ -9233,18 +9222,15 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c | |||
| 9233 | */ | 9222 | */ |
| 9234 | static struct builtincmd *find_builtin(const char *name); | 9223 | static struct builtincmd *find_builtin(const char *name); |
| 9235 | static void shellexec(char *prog, char **argv, const char *path, int idx, | 9224 | static void shellexec(char *prog, char **argv, const char *path, int idx, |
| 9236 | int nofork) NORETURN; | 9225 | int noexec) NORETURN; |
| 9237 | static void shellexec(char *prog, char **argv, const char *path, int idx, | 9226 | static void shellexec(char *prog, char **argv, const char *path, int idx, |
| 9238 | int nofork) | 9227 | int noexec) |
| 9239 | { | 9228 | { |
| 9240 | char *cmdname; | 9229 | char *cmdname; |
| 9241 | int e; | 9230 | int e; |
| 9242 | char **envp; | 9231 | char **envp; |
| 9243 | int exerrno; | 9232 | int exerrno; |
| 9244 | int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ | 9233 | int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ |
| 9245 | #if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_SH_STANDALONE | ||
| 9246 | const char *nfpath = (nofork & ~EXEC_FLAG) ? path : NULL; | ||
| 9247 | #endif | ||
| 9248 | 9234 | ||
| 9249 | envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL); | 9235 | envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL); |
| 9250 | #if ENABLE_FEATURE_SH_STANDALONE && ENABLE_PLATFORM_MINGW32 && defined(_UCRT) | 9236 | #if ENABLE_FEATURE_SH_STANDALONE && ENABLE_PLATFORM_MINGW32 && defined(_UCRT) |
| @@ -9266,7 +9252,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx, | |||
| 9266 | ) { | 9252 | ) { |
| 9267 | #if ENABLE_PLATFORM_MINGW32 | 9253 | #if ENABLE_PLATFORM_MINGW32 |
| 9268 | char *progext = stack_add_ext_space(prog); | 9254 | char *progext = stack_add_ext_space(prog); |
| 9269 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no, nfpath, nofork,) | 9255 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no, path, noexec,) |
| 9270 | progext, argv, envp); | 9256 | progext, argv, envp); |
| 9271 | #else | 9257 | #else |
| 9272 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); | 9258 | tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); |
| @@ -9284,7 +9270,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx, | |||
| 9284 | const char *name = bb_basename(prog); | 9270 | const char *name = bb_basename(prog); |
| 9285 | # if ENABLE_FEATURE_SH_STANDALONE | 9271 | # if ENABLE_FEATURE_SH_STANDALONE |
| 9286 | if ((applet_no = find_applet_by_name_for_sh(name, path)) >= 0) { | 9272 | if ((applet_no = find_applet_by_name_for_sh(name, path)) >= 0) { |
| 9287 | tryexec(applet_no, nfpath, nofork, name, argv, envp); | 9273 | tryexec(applet_no, path, noexec, name, argv, envp); |
| 9288 | e = errno; | 9274 | e = errno; |
| 9289 | } | 9275 | } |
| 9290 | # endif | 9276 | # endif |
| @@ -9301,7 +9287,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx, | |||
| 9301 | cmdname = stackblock(); | 9287 | cmdname = stackblock(); |
| 9302 | if (--idx < 0 && pathopt == NULL) { | 9288 | if (--idx < 0 && pathopt == NULL) { |
| 9303 | #if ENABLE_PLATFORM_MINGW32 | 9289 | #if ENABLE_PLATFORM_MINGW32 |
| 9304 | tryexec(IF_FEATURE_SH_STANDALONE(-1, nfpath, nofork,) | 9290 | tryexec(IF_FEATURE_SH_STANDALONE(-1, path, noexec,) |
| 9305 | cmdname, argv, envp); | 9291 | cmdname, argv, envp); |
| 9306 | #else | 9292 | #else |
| 9307 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); | 9293 | tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); |
| @@ -11278,7 +11264,7 @@ execcmd(int argc UNUSED_PARAM, char **argv) | |||
| 11278 | prog = argv[0]; | 11264 | prog = argv[0]; |
| 11279 | if (optionarg) | 11265 | if (optionarg) |
| 11280 | argv[0] = optionarg; | 11266 | argv[0] = optionarg; |
| 11281 | shellexec(prog, argv, pathval(), 0, EXEC_FLAG); | 11267 | shellexec(prog, argv, pathval(), 0, FALSE); |
| 11282 | /* NOTREACHED */ | 11268 | /* NOTREACHED */ |
| 11283 | } | 11269 | } |
| 11284 | return 0; | 11270 | return 0; |
| @@ -11834,7 +11820,7 @@ evalcommand(union node *cmd, int flags) | |||
| 11834 | /* fall through to exec'ing external program */ | 11820 | /* fall through to exec'ing external program */ |
| 11835 | } | 11821 | } |
| 11836 | #endif | 11822 | #endif |
| 11837 | shellexec(argv[0], argv, path, cmdentry.u.index, TRUE); | 11823 | shellexec(argv[0], argv, path, cmdentry.u.index, FALSE); |
| 11838 | /* NOTREACHED */ | 11824 | /* NOTREACHED */ |
| 11839 | } /* default */ | 11825 | } /* default */ |
| 11840 | case CMDBUILTIN: | 11826 | case CMDBUILTIN: |
| @@ -16554,7 +16540,7 @@ forkshell_shellexec(struct forkshell *fs) | |||
| 16554 | char *path = fs->path; | 16540 | char *path = fs->path; |
| 16555 | 16541 | ||
| 16556 | FORCE_INT_ON; | 16542 | FORCE_INT_ON; |
| 16557 | shellexec(argv[0], argv, path, idx, FALSE); | 16543 | shellexec(argv[0], argv, path, idx, TRUE); |
| 16558 | } | 16544 | } |
| 16559 | 16545 | ||
| 16560 | static void | 16546 | static void |
