diff options
-rw-r--r-- | coreutils/test.c | 11 | ||||
-rw-r--r-- | include/libbb.h | 6 | ||||
-rw-r--r-- | libbb/bb_getgroups.c | 14 | ||||
-rw-r--r-- | shell/ash.c | 9 |
4 files changed, 30 insertions, 10 deletions
diff --git a/coreutils/test.c b/coreutils/test.c index ad777953f..6085d6663 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -638,7 +638,7 @@ static int binop(void) | |||
638 | static int is_a_group_member(gid_t gid) | 638 | static int is_a_group_member(gid_t gid) |
639 | { | 639 | { |
640 | /* Short-circuit if possible, maybe saving a call to getgroups(). */ | 640 | /* Short-circuit if possible, maybe saving a call to getgroups(). */ |
641 | if (gid == getgid() || gid == getegid()) | 641 | if (gid == get_cached_egid(&groupinfo->egid)) |
642 | return 1; | 642 | return 1; |
643 | 643 | ||
644 | return is_in_supplementary_groups(groupinfo, gid); | 644 | return is_in_supplementary_groups(groupinfo, gid); |
@@ -656,15 +656,16 @@ static int test_st_mode(struct stat *st, int mode) | |||
656 | 656 | ||
657 | //TODO if (mode == X_OK) { | 657 | //TODO if (mode == X_OK) { |
658 | // /* Do we already know with no extra syscalls? */ | 658 | // /* Do we already know with no extra syscalls? */ |
659 | // if (!S_ISREG(st->st_mode)) | 659 | // //if (!S_ISREG(st->st_mode)) |
660 | // return 0; /* not a regular file */ | 660 | // // return 0; /* not a regular file */ |
661 | // // ^^^ bash does not check this | ||
661 | // if ((st->st_mode & ANY_IX) == 0) | 662 | // if ((st->st_mode & ANY_IX) == 0) |
662 | // return 0; /* no one can execute */ | 663 | // return 0; /* no one can execute */ |
663 | // if ((st->st_mode & ANY_IX) == ANY_IX) | 664 | // if ((st->st_mode & ANY_IX) == ANY_IX) |
664 | // return 1; /* anyone can execute */ | 665 | // return 1; /* anyone can execute */ |
665 | // } | 666 | // } |
666 | 667 | ||
667 | euid = geteuid(); | 668 | euid = get_cached_euid(&groupinfo->euid); |
668 | if (euid == 0) { | 669 | if (euid == 0) { |
669 | /* Root can read or write any file. */ | 670 | /* Root can read or write any file. */ |
670 | if (mode != X_OK) | 671 | if (mode != X_OK) |
@@ -1019,6 +1020,8 @@ int test_main(int argc, char **argv) | |||
1019 | struct cached_groupinfo info; | 1020 | struct cached_groupinfo info; |
1020 | int r; | 1021 | int r; |
1021 | 1022 | ||
1023 | info.euid = -1; | ||
1024 | info.egid = -1; | ||
1022 | info.ngroups = 0; | 1025 | info.ngroups = 0; |
1023 | info.supplementary_array = NULL; | 1026 | info.supplementary_array = NULL; |
1024 | r = test_main2(&info, argc, argv); | 1027 | r = test_main2(&info, argc, argv); |
diff --git a/include/libbb.h b/include/libbb.h index 8748464ed..f5f8e1635 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1206,11 +1206,13 @@ gid_t *bb_getgroups(int *ngroups, gid_t *group_array) FAST_FUNC; | |||
1206 | * getgroups() is cached in supplementary_array[], to make successive calls faster. | 1206 | * getgroups() is cached in supplementary_array[], to make successive calls faster. |
1207 | */ | 1207 | */ |
1208 | struct cached_groupinfo { | 1208 | struct cached_groupinfo { |
1209 | //TODO? gid_t egid; | 1209 | uid_t euid; |
1210 | gid_t egid; | ||
1210 | int ngroups; | 1211 | int ngroups; |
1211 | gid_t *supplementary_array; | 1212 | gid_t *supplementary_array; |
1212 | }; | 1213 | }; |
1213 | //TODO? int FAST_FUNC get_cached_egid(gid_t *egid); | 1214 | uid_t FAST_FUNC get_cached_euid(uid_t *euid); |
1215 | gid_t FAST_FUNC get_cached_egid(gid_t *egid); | ||
1214 | int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid); | 1216 | int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid); |
1215 | 1217 | ||
1216 | #if ENABLE_FEATURE_UTMP | 1218 | #if ENABLE_FEATURE_UTMP |
diff --git a/libbb/bb_getgroups.c b/libbb/bb_getgroups.c index d9bbe95c3..31cff2b41 100644 --- a/libbb/bb_getgroups.c +++ b/libbb/bb_getgroups.c | |||
@@ -46,6 +46,20 @@ gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) | |||
46 | return group_array; | 46 | return group_array; |
47 | } | 47 | } |
48 | 48 | ||
49 | uid_t FAST_FUNC get_cached_euid(uid_t *euid) | ||
50 | { | ||
51 | if (*euid == (uid_t)-1) | ||
52 | *euid = geteuid(); | ||
53 | return *euid; | ||
54 | } | ||
55 | |||
56 | gid_t FAST_FUNC get_cached_egid(gid_t *egid) | ||
57 | { | ||
58 | if (*egid == (gid_t)-1) | ||
59 | *egid = getegid(); | ||
60 | return *egid; | ||
61 | } | ||
62 | |||
49 | /* Return non-zero if GID is in our supplementary group list. */ | 63 | /* Return non-zero if GID is in our supplementary group list. */ |
50 | int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid) | 64 | int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid) |
51 | { | 65 | { |
diff --git a/shell/ash.c b/shell/ash.c index a6bb9894c..9173b8608 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -536,6 +536,8 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |||
536 | curdir = nullstr; \ | 536 | curdir = nullstr; \ |
537 | physdir = nullstr; \ | 537 | physdir = nullstr; \ |
538 | trap_ptr = trap; \ | 538 | trap_ptr = trap; \ |
539 | groupinfo.euid = -1; \ | ||
540 | groupinfo.egid = -1; \ | ||
539 | } while (0) | 541 | } while (0) |
540 | 542 | ||
541 | 543 | ||
@@ -2319,7 +2321,7 @@ initvar(void) | |||
2319 | #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT | 2321 | #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT |
2320 | vps1.var_text = "PS1=\\w \\$ "; | 2322 | vps1.var_text = "PS1=\\w \\$ "; |
2321 | #else | 2323 | #else |
2322 | if (!geteuid()) | 2324 | if (!get_cached_euid(&groupinfo.euid)); |
2323 | vps1.var_text = "PS1=# "; | 2325 | vps1.var_text = "PS1=# "; |
2324 | #endif | 2326 | #endif |
2325 | vp = varinit; | 2327 | vp = varinit; |
@@ -13809,14 +13811,13 @@ static int test_exec(/*const char *fullname,*/ struct stat *statb) | |||
13809 | 13811 | ||
13810 | /* Executability depends on our euid/egid/supplementary groups */ | 13812 | /* Executability depends on our euid/egid/supplementary groups */ |
13811 | stmode = S_IXOTH; | 13813 | stmode = S_IXOTH; |
13812 | euid = geteuid(); | 13814 | euid = get_cached_euid(&groupinfo.euid); |
13813 | //TODO: cache euid? | ||
13814 | if (euid == 0) | 13815 | if (euid == 0) |
13815 | /* for root user, any X bit is good enough */ | 13816 | /* for root user, any X bit is good enough */ |
13816 | stmode = ANY_IX; | 13817 | stmode = ANY_IX; |
13817 | else if (statb->st_uid == euid) | 13818 | else if (statb->st_uid == euid) |
13818 | stmode = S_IXUSR; | 13819 | stmode = S_IXUSR; |
13819 | else if (statb->st_gid == getegid()) | 13820 | else if (statb->st_gid == get_cached_egid(&groupinfo.egid)) |
13820 | stmode = S_IXGRP; | 13821 | stmode = S_IXGRP; |
13821 | else if (is_in_supplementary_groups(&groupinfo, statb->st_gid)) | 13822 | else if (is_in_supplementary_groups(&groupinfo, statb->st_gid)) |
13822 | stmode = S_IXGRP; | 13823 | stmode = S_IXGRP; |