From: Simon Wilkinson Date: Sat, 19 Dec 2009 23:58:54 +0000 (+0000) Subject: Linux: Rework PAG to group conversions X-Git-Tag: openafs-devel-1_5_69~26 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=6e65ffbb6c520bf1c28356206410363d8eb36d78;p=packages%2Fo%2Fopenafs.git Linux: Rework PAG to group conversions The change to using a single group for PAGs on Linux led to a load of special cases throughout the code. This patch moves the OS dependent parts of this into the LINUX/ platform directory, and rearranges that file so that there is a clear distinction between the one and two group sections of the code. Change-Id: Ib6e6f081519b23494dcf731b4be689c006180c68 Reviewed-on: http://gerrit.openafs.org/1007 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c index e37e8c959..11bd17a8e 100644 --- a/src/afs/LINUX/osi_groups.c +++ b/src/afs/LINUX/osi_groups.c @@ -29,11 +29,92 @@ #include #ifdef AFS_LINUX26_ONEGROUP_ENV -#define NUMPAGGROUPS 1 +# define NUMPAGGROUPS 1 + +static afs_uint32 +afs_linux_pag_from_groups(struct group_info *group_info) { + afs_uint32 g0 = 0; + afs_uint32 i; + + if (group_info->ngroups < NUMPAGGROUPS) + return NOPAG; + + for (i = 0; (i < group_info->ngroups && + (g0 = GROUP_AT(group_info, i)) != (gid_t) NOGROUP); i++) { + if (((g0 >> 24) & 0xff) == 'A') + return g0; + } + return NOPAG; +} + +static inline void +afs_linux_pag_to_groups(afs_uint32 newpag, + struct group_info *old, struct group_info **new) { + int need_space = 0; + int i; + int j; + + if (afs_linux_pag_from_groups(old) == NOPAG) + need_space = NUMPAGGROUPS; + + *new = groups_alloc(old->ngroups + need_space); + + for (i = 0, j = 0; i < old->ngroups; ++i) { + int ths = GROUP_AT(old, i); + int last = i > 0 ? GROUP_AT(old, i-1) : 0; + if ((ths >> 24) == 'A') + continue; + if (last <= newpag && ths > newpag) { + GROUP_AT(*new, j) = newpag; + j++; + } + GROUP_AT(*new, j) = ths; + j++; + } + if (j != i + need_space) + GROUP_AT(*new, j) = newpag; +} + #else -#define NUMPAGGROUPS 2 +# define NUMPAGGROUPS 2 + +static inline afs_uint32 +afs_linux_pag_from_groups(struct group_info *group_info) { + + if (group_info->ngroups < NUMPAGGROUPS) + return NOPAG; + + return afs_get_pag_from_groups(GROUP_AT(group_info, 0), GROUP_AT(group_info, 1)); +} + +static inline void +afs_linux_pag_to_groups(afs_uint32 newpag, + struct group_info *old, struct group_info *new) { + int need_space = 0; + int i; + gid_t g0; + gid_t g1; + + if (afs_linux_pag_from_groups(old) == NOPAG) + need_space = NUMPAGGGROUPS; + + *new = groups_alloc(old->ngroups + need_space); + + for (i = 0; i < old->ngroups; ++i) + GROUP_AT(new, i + need_space) = GROUP_AT(old, i); + + afs_get_groups_from_pag(newpag, &g0, g1); + GROUP_AT(new, 0) = g0; + GROUP_AT(new, 1) = g1; +} #endif +afs_int32 +osi_get_group_pag(afs_ucred_t *cred) { + return afs_linux_pag_from_groups(afs_cr_group_info(cred)); +} + + static int afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent) { @@ -59,76 +140,23 @@ afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent) return (0); } -/* Returns number of groups. And we trust groups to be large enough to - * hold all the groups. - */ -static struct group_info * -afs_getgroups(cred_t * cr) -{ - AFS_STATCNT(afs_getgroups); - - get_group_info(afs_cr_group_info(cr)); - return afs_cr_group_info(cr); -} int __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag, int change_parent) { struct group_info *group_info; -#ifndef AFS_LINUX26_ONEGROUP_ENV - gid_t g0, g1; -#endif struct group_info *tmp; - int i; -#ifdef AFS_LINUX26_ONEGROUP_ENV - int j; -#endif - int need_space = 0; - group_info = afs_getgroups(*cr); - if (group_info->ngroups < NUMPAGGROUPS - || afs_get_pag_from_groups( -#ifdef AFS_LINUX26_ONEGROUP_ENV - group_info -#else - GROUP_AT(group_info, 0) ,GROUP_AT(group_info, 1) -#endif - ) == NOPAG) - /* We will have to make sure group_info is big enough for pag */ - need_space = NUMPAGGROUPS; + get_group_info(afs_cr_group_info(*cr)); + group_info = afs_cr_group_info(*cr); - tmp = groups_alloc(group_info->ngroups + need_space); - *newpag = (pagvalue == -1 ? genpag() : pagvalue); -#ifdef AFS_LINUX26_ONEGROUP_ENV - for (i = 0, j = 0; i < group_info->ngroups; ++i) { - int ths = GROUP_AT(group_info, i); - int last = i > 0 ? GROUP_AT(group_info, i-1) : 0; - if ((ths >> 24) == 'A') - continue; - if (last <= *newpag && ths > *newpag) { - GROUP_AT(tmp, j) = *newpag; - j++; - } - GROUP_AT(tmp, j) = ths; - j++; - } - if (j != i + need_space) - GROUP_AT(tmp, j) = *newpag; -#else - for (i = 0; i < group_info->ngroups; ++i) - GROUP_AT(tmp, i + need_space) = GROUP_AT(group_info, i); -#endif + afs_linux_pag_to_groups(*newpag, group_info, &tmp); + put_group_info(group_info); group_info = tmp; -#ifndef AFS_LINUX26_ONEGROUP_ENV - afs_get_groups_from_pag(*newpag, &g0, &g1); - GROUP_AT(group_info, 0) = g0; - GROUP_AT(group_info, 1) = g1; -#endif - afs_setgroups(cr, group_info, change_parent); put_group_info(group_info); @@ -406,9 +434,6 @@ static int afs_pag_instantiate(struct key *key, const void *data, size_t datalen { int code; afs_uint32 *userpag, pag = NOPAG; -#ifndef AFS_LINUX26_ONEGROUP_ENV - int g0, g1; -#endif if (key->uid != 0 || key->gid != 0) return -EPERM; @@ -419,18 +444,9 @@ static int afs_pag_instantiate(struct key *key, const void *data, size_t datalen if (datalen != sizeof(afs_uint32) || !data) goto error; - if (current_group_info()->ngroups < NUMPAGGROUPS) - goto error; - /* ensure key being set matches current pag */ -#ifdef AFS_LINUX26_ONEGROUP_ENV - pag = afs_get_pag_from_groups(current_group_info()); -#else - g0 = GROUP_AT(current_group_info(), 0); - g1 = GROUP_AT(current_group_info(), 1); + pag = afs_linux_pag_from_groups(current_group_info()); - pag = afs_get_pag_from_groups(g0, g1); -#endif if (pag == NOPAG) goto error; @@ -552,7 +568,7 @@ osi_get_keyring_pag(afs_ucred_t *cred) * and the creds are from the current process */ if (afs_linux_cred_is_current(cred) && ((keyring_pag >> 24) & 0xff) == 'A' && - keyring_pag != afs_get_pag_from_groups(current_group_info())) { + keyring_pag != afs_linux_pag_from_groups(current_group_info())) { __setpag(&cred, keyring_pag, &newpag, 0); } } diff --git a/src/afs/afs_osi_pag.c b/src/afs/afs_osi_pag.c index 4db10a83a..f6356dbb7 100644 --- a/src/afs/afs_osi_pag.c +++ b/src/afs/afs_osi_pag.c @@ -465,23 +465,7 @@ afs_InitReq(register struct vrequest *av, afs_ucred_t *acred) return 0; } - -#ifdef AFS_LINUX26_ONEGROUP_ENV -afs_uint32 -afs_get_pag_from_groups(struct group_info *group_info) -{ - afs_uint32 g0 = 0; - afs_uint32 i; - - AFS_STATCNT(afs_get_pag_from_groups); - for (i = 0; (i < group_info->ngroups && - (g0 = GROUP_AT(group_info, i)) != (gid_t) NOGROUP); i++) { - if (((g0 >> 24) & 0xff) == 'A') - return g0; - } - return NOPAG; -} -#else +#ifndef AFS_LINUX26_ONEGROUP_ENV afs_uint32 afs_get_pag_from_groups(gid_t g0a, gid_t g1a) { @@ -498,51 +482,50 @@ afs_get_pag_from_groups(gid_t g0a, gid_t g1a) h = (g0 >> 14); h = (g1 >> 14) + h + h + h; ret = ((h << 28) | l); -#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) +# if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) return ret; -#else +# else /* Additional testing */ if (((ret >> 24) & 0xff) == 'A') return ret; -#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */ +# endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */ } return NOPAG; } -#endif void afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p) { -#ifndef AFS_LINUX26_ONEGROUP_ENV unsigned short g0, g1; -#endif - AFS_STATCNT(afs_get_groups_from_pag); -#ifdef AFS_LINUX26_ONEGROUP_ENV *g0p = pag; *g1p = 0; -#else -#if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS) +# if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS) pag &= 0x7fffffff; -#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */ +# endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */ g0 = 0x3fff & (pag >> 14); g1 = 0x3fff & pag; g0 |= ((pag >> 28) / 3) << 14; g1 |= ((pag >> 28) % 3) << 14; *g0p = g0 + 0x3f00; *g1p = g1 + 0x3f00; -#endif } +#else +void afs_get_groups_from_pag(afs_uint32 pag, gid_t *g0p, gid_t *g1p) +{ + AFS_STATCNT(afs_get_groups_from_pag); + *g0p = pag; + *g1p = 0; +} +#endif - -afs_int32 -afs_get_group_pag(afs_ucred_t *cred) +#ifndef AFS_LINUX26_ENV +static afs_int32 +osi_get_group_pag(afs_ucred_t *cred) { afs_int32 pag = NOPAG; -#if !defined(AFS_LINUX26_ONEGROUP_ENV) gid_t g0, g1; -#endif #if defined(AFS_SUN510_ENV) const gid_t *gids; int ngroups; @@ -561,28 +544,24 @@ afs_get_group_pag(afs_ucred_t *cred) g0 = cred->cr_groups[1]; g1 = cred->cr_groups[2]; #else -#if defined(AFS_AIX_ENV) +# if defined(AFS_AIX_ENV) if (cred->cr_ngrps < 2) return NOPAG; -#elif defined(AFS_LINUX26_ENV) +# elif defined(AFS_LINUX26_ENV) if (afs_cr_group_info(cred)->ngroups < NUMPAGGROUPS) return NOPAG; -#elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV) -#if defined(AFS_SUN510_ENV) +# elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV) +# if defined(AFS_SUN510_ENV) if (ngroups < 2) { -#else +# else if (cred->cr_ngroups < 2) { -#endif +# endif return NOPAG; } -#endif -#if defined(AFS_AIX51_ENV) +# endif +# if defined(AFS_AIX51_ENV) g0 = cred->cr_groupset.gs_union.un_groups[0]; g1 = cred->cr_groupset.gs_union.un_groups[1]; -#elif defined(AFS_LINUX26_ONEGROUP_ENV) -#elif defined(AFS_LINUX26_ENV) - g0 = GROUP_AT(afs_cr_group_info(cred), 0); - g1 = GROUP_AT(afs_cr_group_info(cred), 1); #elif defined(AFS_SUN510_ENV) g0 = gids[0]; g1 = gids[1]; @@ -591,13 +570,10 @@ afs_get_group_pag(afs_ucred_t *cred) g1 = cred->cr_groups[1]; #endif #endif -#if defined(AFS_LINUX26_ONEGROUP_ENV) - pag = (afs_int32) afs_get_pag_from_groups(afs_cr_group_info(cred)); -#else pag = (afs_int32) afs_get_pag_from_groups(g0, g1); -#endif return pag; } +#endif afs_int32 @@ -619,12 +595,12 @@ PagInCred(afs_ucred_t *cred) * to looking at the keyrings. */ # if !defined(STRUCT_TASK_HAS_CRED) - pag = afs_get_group_pag(cred); + pag = osi_get_group_pag(cred); # endif if (pag == NOPAG) pag = osi_get_keyring_pag(cred); #else - pag = afs_get_group_pag(cred); + pag = osi_get_group_pag(cred); #endif return pag; } diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h index 6fed26653..725ff06b5 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -581,13 +581,7 @@ extern int AddPag(afs_proc_t *p, afs_int32 aval, afs_ucred_t **credpp); extern int AddPag(afs_int32 aval, afs_ucred_t **credpp); #endif extern int afs_InitReq(register struct vrequest *av, afs_ucred_t *acred); -#if defined(UKERNEL) extern afs_uint32 afs_get_pag_from_groups(gid_t g0a, gid_t g1a); -#else -#ifdef AFS_LINUX26_ONEGROUP_ENV -extern afs_uint32 afs_get_pag_from_groups(struct group_info *gi); -#endif -#endif extern void afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p); extern afs_int32 PagInCred(afs_ucred_t *cred);