diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-09 17:52:09 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-09 17:52:09 +0200 |
| commit | 81274d8b3085d59bf5c01a35c17bac3d6952b53d (patch) | |
| tree | 908a0ee3c9006f779c522b4c661b5c6ac43858ad /shell | |
| parent | 4ce8afe6b2a989a0360c09a81c6bf9d43d6ba24a (diff) | |
| download | busybox-w32-81274d8b3085d59bf5c01a35c17bac3d6952b53d.tar.gz busybox-w32-81274d8b3085d59bf5c01a35c17bac3d6952b53d.tar.bz2 busybox-w32-81274d8b3085d59bf5c01a35c17bac3d6952b53d.zip | |
ash: eval: Reset handler when entering a subshell
Upstream commit:
Date: Sun, 3 Mar 2019 21:57:50 +0800
eval: Reset handler when entering a subshell
As it is a subshell can execute code that is only meant for the
parent shell when it executes a longjmp that is caught by something
like evalcommand. This patch fixes it by resetting the handler
when entering a subshell.
function old new delta
evalsubshell 169 183 +14
evalpipe 342 356 +14
argstr 1406 1416 +10
ash_main 1236 1226 -10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/1 up/down: 65/-10) Total: 28 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/shell/ash.c b/shell/ash.c index a88fb804a..2c501993b 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -493,6 +493,8 @@ struct globals_misc { | |||
| 493 | 493 | ||
| 494 | /* Rarely referenced stuff */ | 494 | /* Rarely referenced stuff */ |
| 495 | 495 | ||
| 496 | struct jmploc main_handler; | ||
| 497 | |||
| 496 | /* Cached supplementary group array (for testing executable'ity of files) */ | 498 | /* Cached supplementary group array (for testing executable'ity of files) */ |
| 497 | struct cached_groupinfo groupinfo; | 499 | struct cached_groupinfo groupinfo; |
| 498 | 500 | ||
| @@ -529,6 +531,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
| 529 | #define may_have_traps (G_misc.may_have_traps ) | 531 | #define may_have_traps (G_misc.may_have_traps ) |
| 530 | #define trap (G_misc.trap ) | 532 | #define trap (G_misc.trap ) |
| 531 | #define trap_ptr (G_misc.trap_ptr ) | 533 | #define trap_ptr (G_misc.trap_ptr ) |
| 534 | #define main_handler (G_misc.main_handler ) | ||
| 532 | #define groupinfo (G_misc.groupinfo ) | 535 | #define groupinfo (G_misc.groupinfo ) |
| 533 | #define random_gen (G_misc.random_gen ) | 536 | #define random_gen (G_misc.random_gen ) |
| 534 | #define backgndpid (G_misc.backgndpid ) | 537 | #define backgndpid (G_misc.backgndpid ) |
| @@ -594,6 +597,14 @@ sigclearmask(void) | |||
| 594 | sigprocmask_allsigs(SIG_UNBLOCK); | 597 | sigprocmask_allsigs(SIG_UNBLOCK); |
| 595 | } | 598 | } |
| 596 | 599 | ||
| 600 | /* Reset handler when entering a subshell */ | ||
| 601 | static void | ||
| 602 | reset_exception_handler(void) | ||
| 603 | { | ||
| 604 | exception_handler = &main_handler; | ||
| 605 | } | ||
| 606 | |||
| 607 | |||
| 597 | /* ============ Parser data */ | 608 | /* ============ Parser data */ |
| 598 | 609 | ||
| 599 | /* | 610 | /* |
| @@ -6720,6 +6731,7 @@ evalbackcmd(union node *n, struct backcmd *result | |||
| 6720 | jp = (ctl == CTLBACKQ) ? makejob(1) : NULL; | 6731 | jp = (ctl == CTLBACKQ) ? makejob(1) : NULL; |
| 6721 | if (forkshell(jp, n, FORK_NOJOB) == 0) { | 6732 | if (forkshell(jp, n, FORK_NOJOB) == 0) { |
| 6722 | /* child */ | 6733 | /* child */ |
| 6734 | reset_exception_handler(); | ||
| 6723 | FORCEINTON; | 6735 | FORCEINTON; |
| 6724 | close(pip[ip]); | 6736 | close(pip[ip]); |
| 6725 | /* ic is index of child end of pipe *and* fd to connect it to */ | 6737 | /* ic is index of child end of pipe *and* fd to connect it to */ |
| @@ -9705,6 +9717,7 @@ evalsubshell(union node *n, int flags) | |||
| 9705 | if (backgnd) | 9717 | if (backgnd) |
| 9706 | flags &= ~EV_TESTED; | 9718 | flags &= ~EV_TESTED; |
| 9707 | nofork: | 9719 | nofork: |
| 9720 | reset_exception_handler(); | ||
| 9708 | redirect(n->nredir.redirect, 0); | 9721 | redirect(n->nredir.redirect, 0); |
| 9709 | evaltreenr(n->nredir.n, flags); | 9722 | evaltreenr(n->nredir.n, flags); |
| 9710 | /* never returns */ | 9723 | /* never returns */ |
| @@ -9817,6 +9830,7 @@ evalpipe(union node *n, int flags) | |||
| 9817 | } | 9830 | } |
| 9818 | if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { | 9831 | if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { |
| 9819 | /* child */ | 9832 | /* child */ |
| 9833 | reset_exception_handler(); | ||
| 9820 | INTON; | 9834 | INTON; |
| 9821 | if (pip[1] >= 0) { | 9835 | if (pip[1] >= 0) { |
| 9822 | close(pip[0]); | 9836 | close(pip[0]); |
| @@ -14851,7 +14865,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
| 14851 | /* note: 'argc' is used only if embedded scripts are enabled */ | 14865 | /* note: 'argc' is used only if embedded scripts are enabled */ |
| 14852 | { | 14866 | { |
| 14853 | volatile smallint state; | 14867 | volatile smallint state; |
| 14854 | struct jmploc jmploc; | ||
| 14855 | struct stackmark smark; | 14868 | struct stackmark smark; |
| 14856 | int login_sh; | 14869 | int login_sh; |
| 14857 | 14870 | ||
| @@ -14869,7 +14882,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
| 14869 | #endif | 14882 | #endif |
| 14870 | 14883 | ||
| 14871 | state = 0; | 14884 | state = 0; |
| 14872 | if (setjmp(jmploc.loc)) { | 14885 | if (setjmp(main_handler.loc)) { |
| 14873 | smallint e; | 14886 | smallint e; |
| 14874 | smallint s; | 14887 | smallint s; |
| 14875 | 14888 | ||
| @@ -14897,7 +14910,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
| 14897 | goto state3; | 14910 | goto state3; |
| 14898 | goto state4; | 14911 | goto state4; |
| 14899 | } | 14912 | } |
| 14900 | exception_handler = &jmploc; | 14913 | exception_handler = &main_handler; |
| 14901 | rootpid = getpid(); | 14914 | rootpid = getpid(); |
| 14902 | 14915 | ||
| 14903 | init(); | 14916 | init(); |
