ash: cache more of uid/gid syscalls
Testcase: setuidgid 1:1 strace ash -c 'test -x TODO; test -x TODO; echo $?' should show that second "test -x" does not query ids again. function old new delta ash_main 1236 1256 +20 get_cached_euid - 19 +19 get_cached_egid - 19 +19 test_main 56 72 +16 test_exec 119 135 +16 is_in_supplementary_groups 52 57 +5 nexpr 718 702 -16 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 4/1 up/down: 95/-16) Total: 79 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
d26e958725
commit
96b0607302
4 changed files with 30 additions and 10 deletions
|
@ -638,7 +638,7 @@ static int binop(void)
|
||||||
static int is_a_group_member(gid_t gid)
|
static int is_a_group_member(gid_t gid)
|
||||||
{
|
{
|
||||||
/* Short-circuit if possible, maybe saving a call to getgroups(). */
|
/* 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 1;
|
||||||
|
|
||||||
return is_in_supplementary_groups(groupinfo, gid);
|
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) {
|
//TODO if (mode == X_OK) {
|
||||||
// /* Do we already know with no extra syscalls? */
|
// /* Do we already know with no extra syscalls? */
|
||||||
// if (!S_ISREG(st->st_mode))
|
// //if (!S_ISREG(st->st_mode))
|
||||||
// return 0; /* not a regular file */
|
// // return 0; /* not a regular file */
|
||||||
|
// // ^^^ bash does not check this
|
||||||
// if ((st->st_mode & ANY_IX) == 0)
|
// if ((st->st_mode & ANY_IX) == 0)
|
||||||
// return 0; /* no one can execute */
|
// return 0; /* no one can execute */
|
||||||
// if ((st->st_mode & ANY_IX) == ANY_IX)
|
// if ((st->st_mode & ANY_IX) == ANY_IX)
|
||||||
// return 1; /* anyone can execute */
|
// return 1; /* anyone can execute */
|
||||||
// }
|
// }
|
||||||
|
|
||||||
euid = geteuid();
|
euid = get_cached_euid(&groupinfo->euid);
|
||||||
if (euid == 0) {
|
if (euid == 0) {
|
||||||
/* Root can read or write any file. */
|
/* Root can read or write any file. */
|
||||||
if (mode != X_OK)
|
if (mode != X_OK)
|
||||||
|
@ -1019,6 +1020,8 @@ int test_main(int argc, char **argv)
|
||||||
struct cached_groupinfo info;
|
struct cached_groupinfo info;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
info.euid = -1;
|
||||||
|
info.egid = -1;
|
||||||
info.ngroups = 0;
|
info.ngroups = 0;
|
||||||
info.supplementary_array = NULL;
|
info.supplementary_array = NULL;
|
||||||
r = test_main2(&info, argc, argv);
|
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.
|
* getgroups() is cached in supplementary_array[], to make successive calls faster.
|
||||||
*/
|
*/
|
||||||
struct cached_groupinfo {
|
struct cached_groupinfo {
|
||||||
//TODO? gid_t egid;
|
uid_t euid;
|
||||||
|
gid_t egid;
|
||||||
int ngroups;
|
int ngroups;
|
||||||
gid_t *supplementary_array;
|
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);
|
int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid);
|
||||||
|
|
||||||
#if ENABLE_FEATURE_UTMP
|
#if ENABLE_FEATURE_UTMP
|
||||||
|
|
|
@ -46,6 +46,20 @@ gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array)
|
||||||
return 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. */
|
/* 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)
|
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; \
|
curdir = nullstr; \
|
||||||
physdir = nullstr; \
|
physdir = nullstr; \
|
||||||
trap_ptr = trap; \
|
trap_ptr = trap; \
|
||||||
|
groupinfo.euid = -1; \
|
||||||
|
groupinfo.egid = -1; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2319,7 +2321,7 @@ initvar(void)
|
||||||
#if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
|
#if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
|
||||||
vps1.var_text = "PS1=\\w \\$ ";
|
vps1.var_text = "PS1=\\w \\$ ";
|
||||||
#else
|
#else
|
||||||
if (!geteuid())
|
if (!get_cached_euid(&groupinfo.euid));
|
||||||
vps1.var_text = "PS1=# ";
|
vps1.var_text = "PS1=# ";
|
||||||
#endif
|
#endif
|
||||||
vp = varinit;
|
vp = varinit;
|
||||||
|
@ -13809,14 +13811,13 @@ static int test_exec(/*const char *fullname,*/ struct stat *statb)
|
||||||
|
|
||||||
/* Executability depends on our euid/egid/supplementary groups */
|
/* Executability depends on our euid/egid/supplementary groups */
|
||||||
stmode = S_IXOTH;
|
stmode = S_IXOTH;
|
||||||
euid = geteuid();
|
euid = get_cached_euid(&groupinfo.euid);
|
||||||
//TODO: cache euid?
|
|
||||||
if (euid == 0)
|
if (euid == 0)
|
||||||
/* for root user, any X bit is good enough */
|
/* for root user, any X bit is good enough */
|
||||||
stmode = ANY_IX;
|
stmode = ANY_IX;
|
||||||
else if (statb->st_uid == euid)
|
else if (statb->st_uid == euid)
|
||||||
stmode = S_IXUSR;
|
stmode = S_IXUSR;
|
||||||
else if (statb->st_gid == getegid())
|
else if (statb->st_gid == get_cached_egid(&groupinfo.egid))
|
||||||
stmode = S_IXGRP;
|
stmode = S_IXGRP;
|
||||||
else if (is_in_supplementary_groups(&groupinfo, statb->st_gid))
|
else if (is_in_supplementary_groups(&groupinfo, statb->st_gid))
|
||||||
stmode = S_IXGRP;
|
stmode = S_IXGRP;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue