ash: cache more of uid/gid syscalls
No binary (build failed)
—
(log yok)
| @@ -638,7 +638,7 @@ static int binop(void) | |
| static int is_a_group_member(gid_t gid) | |
| { | |
| /* Short-circuit if possible, maybe saving a call to getgroups(). */ | |
| - | if (gid == getgid() || gid == getegid()) |
| + | if (gid == get_cached_egid(&groupinfo->egid)) |
| return 1; | |
| return is_in_supplementary_groups(groupinfo, gid); | |
| @@ -656,15 +656,16 @@ static int test_st_mode(struct stat *st, int mode) | |
| //TODO if (mode == X_OK) { | |
| // /* Do we already know with no extra syscalls? */ | |
| - | // if (!S_ISREG(st->st_mode)) |
| - | // return 0; /* not a regular file */ |
| + | // //if (!S_ISREG(st->st_mode)) |
| + | // // return 0; /* not a regular file */ |
| + | // // ^^^ bash does not check this |
| // if ((st->st_mode & ANY_IX) == 0) | |
| // return 0; /* no one can execute */ | |
| // if ((st->st_mode & ANY_IX) == ANY_IX) | |
| // return 1; /* anyone can execute */ | |
| // } | |
| - | euid = geteuid(); |
| + | euid = get_cached_euid(&groupinfo->euid); |
| if (euid == 0) { | |
| /* Root can read or write any file. */ | |
| if (mode != X_OK) | |
| @@ -1019,6 +1020,8 @@ int test_main(int argc, char **argv) | |
| struct cached_groupinfo info; | |
| int r; | |
| + | info.euid = -1; |
| + | info.egid = -1; |
| info.ngroups = 0; | |
| info.supplementary_array = NULL; | |
| r = test_main2(&info, argc, argv); | |
| @@ -1206,11 +1206,13 @@ gid_t *bb_getgroups(int *ngroups, gid_t *group_array) FAST_FUNC; | |
| * getgroups() is cached in supplementary_array[], to make successive calls faster. | |
| */ | |
| struct cached_groupinfo { | |
| - | //TODO? gid_t egid; |
| + | uid_t euid; |
| + | gid_t egid; |
| int ngroups; | |
| gid_t *supplementary_array; | |
| }; | |
| - | //TODO? int FAST_FUNC get_cached_egid(gid_t *egid); |
| + | uid_t FAST_FUNC get_cached_euid(uid_t *euid); |
| + | gid_t FAST_FUNC get_cached_egid(gid_t *egid); |
| int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid); | |
| #if ENABLE_FEATURE_UTMP | |
| @@ -46,6 +46,20 @@ gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array) | |
| return group_array; | |
| } | |
| + | uid_t FAST_FUNC get_cached_euid(uid_t *euid) |
| + | { |
| + | if (*euid == (uid_t)-1) |
| + | *euid = geteuid(); |
| + | return *euid; |
| + | } |
| + | |
| + | gid_t FAST_FUNC get_cached_egid(gid_t *egid) |
| + | { |
| + | if (*egid == (gid_t)-1) |
| + | *egid = getegid(); |
| + | return *egid; |
| + | } |
| + | |
| /* Return non-zero if GID is in our supplementary group list. */ | |
| int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid) | |
| { | |
| @@ -536,6 +536,8 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; | |
| curdir = nullstr; \ | |
| physdir = nullstr; \ | |
| trap_ptr = trap; \ | |
| + | groupinfo.euid = -1; \ |
| + | groupinfo.egid = -1; \ |
| } while (0) | |
| @@ -2319,7 +2321,7 @@ initvar(void) | |
| #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT | |
| vps1.var_text = "PS1=\\w \\$ "; | |
| #else | |
| - | if (!geteuid()) |
| + | if (!get_cached_euid(&groupinfo.euid)); |
| vps1.var_text = "PS1=# "; | |
| #endif | |
| vp = varinit; | |
| @@ -13809,14 +13811,13 @@ static int test_exec(/*const char *fullname,*/ struct stat *statb) | |
| /* Executability depends on our euid/egid/supplementary groups */ | |
| stmode = S_IXOTH; | |
| - | euid = geteuid(); |
| - | //TODO: cache euid? |
| + | euid = get_cached_euid(&groupinfo.euid); |
| if (euid == 0) | |
| /* for root user, any X bit is good enough */ | |
| stmode = ANY_IX; | |
| else if (statb->st_uid == euid) | |
| stmode = S_IXUSR; | |
| - | else if (statb->st_gid == getegid()) |
| + | else if (statb->st_gid == get_cached_egid(&groupinfo.egid)) |
| stmode = S_IXGRP; | |
| else if (is_in_supplementary_groups(&groupinfo, statb->st_gid)) | |
| stmode = S_IXGRP; | |