diff options
| author | Ron Yorston <rmy@pobox.com> | 2024-10-08 08:46:53 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2024-10-08 08:47:44 +0100 |
| commit | 2fe27c6dbf3c752edbfddfd48c15bab55b3ab8de (patch) | |
| tree | 3d907c63f92be35ef96dde01fedf6cf6b7a8e14c /shell | |
| parent | 5b30de8fba414f75cb25faebf5cd8f391e1deb75 (diff) | |
| parent | 0929a129fc75c556de67877491281e0bc3ef3edd (diff) | |
| download | busybox-w32-2fe27c6dbf3c752edbfddfd48c15bab55b3ab8de.tar.gz busybox-w32-2fe27c6dbf3c752edbfddfd48c15bab55b3ab8de.tar.bz2 busybox-w32-2fe27c6dbf3c752edbfddfd48c15bab55b3ab8de.zip | |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/shell/ash.c b/shell/ash.c index 679846574..b37446233 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -671,6 +671,10 @@ struct globals_misc { | |||
| 671 | char **trap_ptr; /* used only by "trap hack" */ | 671 | char **trap_ptr; /* used only by "trap hack" */ |
| 672 | 672 | ||
| 673 | /* Rarely referenced stuff */ | 673 | /* Rarely referenced stuff */ |
| 674 | |||
| 675 | /* Cached supplementary group array (for testing executable'ity of files) */ | ||
| 676 | struct cached_groupinfo groupinfo; | ||
| 677 | |||
| 674 | #if ENABLE_ASH_RANDOM_SUPPORT | 678 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 675 | random_t random_gen; | 679 | random_t random_gen; |
| 676 | #endif | 680 | #endif |
| @@ -714,6 +718,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
| 714 | #define may_have_traps (G_misc.may_have_traps ) | 718 | #define may_have_traps (G_misc.may_have_traps ) |
| 715 | #define trap (G_misc.trap ) | 719 | #define trap (G_misc.trap ) |
| 716 | #define trap_ptr (G_misc.trap_ptr ) | 720 | #define trap_ptr (G_misc.trap_ptr ) |
| 721 | #define groupinfo (G_misc.groupinfo ) | ||
| 717 | #define random_gen (G_misc.random_gen ) | 722 | #define random_gen (G_misc.random_gen ) |
| 718 | #define backgndpid (G_misc.backgndpid ) | 723 | #define backgndpid (G_misc.backgndpid ) |
| 719 | 724 | ||
| @@ -729,6 +734,8 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
| 729 | curdir = nullstr; \ | 734 | curdir = nullstr; \ |
| 730 | physdir = nullstr; \ | 735 | physdir = nullstr; \ |
| 731 | trap_ptr = trap; \ | 736 | trap_ptr = trap; \ |
| 737 | groupinfo.euid = -1; \ | ||
| 738 | groupinfo.egid = -1; \ | ||
| 732 | } while (0) | 739 | } while (0) |
| 733 | 740 | ||
| 734 | 741 | ||
| @@ -2579,7 +2586,7 @@ initvar(void) | |||
| 2579 | #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT | 2586 | #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT |
| 2580 | vps1.var_text = "PS1=\\w \\$ "; | 2587 | vps1.var_text = "PS1=\\w \\$ "; |
| 2581 | #else | 2588 | #else |
| 2582 | if (!geteuid()) | 2589 | if (!get_cached_euid(&groupinfo.euid)); |
| 2583 | vps1.var_text = "PS1=# "; | 2590 | vps1.var_text = "PS1=# "; |
| 2584 | #endif | 2591 | #endif |
| 2585 | vp = varinit; | 2592 | vp = varinit; |
| @@ -11342,7 +11349,7 @@ static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, a | |||
| 11342 | static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } | 11349 | static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } |
| 11343 | #endif | 11350 | #endif |
| 11344 | #if ENABLE_ASH_TEST || BASH_TEST2 | 11351 | #if ENABLE_ASH_TEST || BASH_TEST2 |
| 11345 | static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } | 11352 | static int FAST_FUNC testcmd(int argc, char **argv) { return test_main2(&groupinfo, argc, argv); } |
| 11346 | #endif | 11353 | #endif |
| 11347 | #if ENABLE_ASH_SLEEP | 11354 | #if ENABLE_ASH_SLEEP |
| 11348 | static int FAST_FUNC sleepcmd(int argc, char **argv) { return sleep_main(argc, argv); } | 11355 | static int FAST_FUNC sleepcmd(int argc, char **argv) { return sleep_main(argc, argv); } |
| @@ -15101,6 +15108,42 @@ readcmdfile(char *name) | |||
| 15101 | 15108 | ||
| 15102 | /* ============ find_command inplementation */ | 15109 | /* ============ find_command inplementation */ |
| 15103 | 15110 | ||
| 15111 | static int test_exec(/*const char *fullname,*/ struct stat *statb) | ||
| 15112 | { | ||
| 15113 | /* | ||
| 15114 | * TODO: use faccessat(AT_FDCWD, fullname, X_OK, AT_EACCESS) | ||
| 15115 | * instead: executability may depend on ACLs, capabilities | ||
| 15116 | * and who knows what else, not just mode bits. | ||
| 15117 | * (faccessat2 syscall was added to Linux in May 14 2020) | ||
| 15118 | */ | ||
| 15119 | mode_t stmode; | ||
| 15120 | uid_t euid; | ||
| 15121 | enum { ANY_IX = S_IXUSR | S_IXGRP | S_IXOTH }; | ||
| 15122 | |||
| 15123 | /* Do we already know with no extra syscalls? */ | ||
| 15124 | if (!S_ISREG(statb->st_mode)) | ||
| 15125 | return 0; /* not a regular file */ | ||
| 15126 | if ((statb->st_mode & ANY_IX) == 0) | ||
| 15127 | return 0; /* no one can execute */ | ||
| 15128 | if ((statb->st_mode & ANY_IX) == ANY_IX) | ||
| 15129 | return 1; /* anyone can execute */ | ||
| 15130 | |||
| 15131 | /* Executability depends on our euid/egid/supplementary groups */ | ||
| 15132 | stmode = S_IXOTH; | ||
| 15133 | euid = get_cached_euid(&groupinfo.euid); | ||
| 15134 | if (euid == 0) | ||
| 15135 | /* for root user, any X bit is good enough */ | ||
| 15136 | stmode = ANY_IX; | ||
| 15137 | else if (statb->st_uid == euid) | ||
| 15138 | stmode = S_IXUSR; | ||
| 15139 | else if (statb->st_gid == get_cached_egid(&groupinfo.egid)) | ||
| 15140 | stmode = S_IXGRP; | ||
| 15141 | else if (is_in_supplementary_groups(&groupinfo, statb->st_gid)) | ||
| 15142 | stmode = S_IXGRP; | ||
| 15143 | |||
| 15144 | return statb->st_mode & stmode; | ||
| 15145 | } | ||
| 15146 | |||
| 15104 | /* | 15147 | /* |
| 15105 | * Resolve a command name. If you change this routine, you may have to | 15148 | * Resolve a command name. If you change this routine, you may have to |
| 15106 | * change the shellexec routine as well. | 15149 | * change the shellexec routine as well. |
| @@ -15128,9 +15171,12 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
| 15128 | if (errno == EINTR) | 15171 | if (errno == EINTR) |
| 15129 | continue; | 15172 | continue; |
| 15130 | #endif | 15173 | #endif |
| 15174 | absfail: | ||
| 15131 | entry->cmdtype = CMDUNKNOWN; | 15175 | entry->cmdtype = CMDUNKNOWN; |
| 15132 | return; | 15176 | return; |
| 15133 | } | 15177 | } |
| 15178 | if (!test_exec(/*name,*/ &statb)) | ||
| 15179 | goto absfail; | ||
| 15134 | } | 15180 | } |
| 15135 | entry->cmdtype = CMDNORMAL; | 15181 | entry->cmdtype = CMDNORMAL; |
| 15136 | return; | 15182 | return; |
| @@ -15275,9 +15321,6 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
| 15275 | e = errno; | 15321 | e = errno; |
| 15276 | goto loop; | 15322 | goto loop; |
| 15277 | } | 15323 | } |
| 15278 | e = EACCES; /* if we fail, this will be the error */ | ||
| 15279 | if (!S_ISREG(statb.st_mode)) | ||
| 15280 | continue; | ||
| 15281 | if (lpathopt) { /* this is a %func directory */ | 15324 | if (lpathopt) { /* this is a %func directory */ |
| 15282 | stalloc(len); | 15325 | stalloc(len); |
| 15283 | /* NB: stalloc will return space pointed by fullname | 15326 | /* NB: stalloc will return space pointed by fullname |
| @@ -15290,6 +15333,9 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
| 15290 | stunalloc(fullname); | 15333 | stunalloc(fullname); |
| 15291 | goto success; | 15334 | goto success; |
| 15292 | } | 15335 | } |
| 15336 | e = EACCES; /* if we fail, this will be the error */ | ||
| 15337 | if (!test_exec(/*fullname,*/ &statb)) | ||
| 15338 | continue; | ||
| 15293 | TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); | 15339 | TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); |
| 15294 | if (!updatetbl) { | 15340 | if (!updatetbl) { |
| 15295 | entry->cmdtype = CMDNORMAL; | 15341 | entry->cmdtype = CMDNORMAL; |
