Linux: Use the kernel's credentials structure

Recent kernels (2.6.29 and above) have a separate ref-counted
structure for holding credentials.  Use it directly instead of
keeping a separate afs specific structure that shadows the same
information.

Also adapt Linux for the change from cr_xxx to afs_cr_xxx wrappers.

Reference counting is done with the appropriate get/put calls.

Change-Id: I1135bb5a66cda51cee4fa9f3f3e63eaa9af28f61
Reviewed-on: http://gerrit.openafs.org/797
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Marc Dionne 2009-10-29 19:58:00 -04:00 committed by Derrick Brashear
parent 97d3fcfcd1
commit dc85abcaa6
6 changed files with 117 additions and 59 deletions

View File

@ -18,6 +18,17 @@
#include "afs/sysincludes.h"
#include "afsincludes.h"
/* Copy one credential structure to another, being careful about references */
static inline void
afs_copy_creds(cred_t *to_cred, const cred_t *from_cred) {
afs_set_cr_uid(to_cred, afs_cr_uid(from_cred));
afs_set_cr_gid(to_cred, afs_cr_gid(from_cred));
afs_set_cr_ruid(to_cred, afs_cr_ruid(from_cred));
afs_set_cr_rgid(to_cred, afs_cr_rgid(from_cred));
get_group_info(afs_cr_group_info(from_cred));
afs_set_cr_group_info(to_cred, afs_cr_group_info(from_cred));
}
cred_t *
crget(void)
{
@ -27,24 +38,31 @@ crget(void)
#define GFP_NOFS GFP_KERNEL
#endif
tmp = kmalloc(sizeof(cred_t), GFP_NOFS);
memset(tmp, 0, sizeof(cred_t));
if (!tmp)
osi_Panic("crget: No more memory for creds!\n");
osi_Panic("crget: No more memory for creds!\n");
#if defined(STRUCT_TASK_HAS_CRED)
get_cred(tmp);
#else
tmp->cr_ref = 1;
#endif
return tmp;
}
void
crfree(cred_t * cr)
{
#if defined(STRUCT_TASK_HAS_CRED)
put_cred(cr);
#else
if (cr->cr_ref > 1) {
cr->cr_ref--;
return;
}
put_group_info(cr_group_info(cr));
put_group_info(afs_cr_group_info(cr));
kfree(cr);
#endif
}
@ -53,21 +71,26 @@ cred_t *
crdup(cred_t * cr)
{
cred_t *tmp = crget();
#if defined(STRUCT_TASK_HAS_CRED)
afs_copy_creds(tmp, cr);
#else
afs_set_cr_uid(tmp, afs_cr_uid(cr));
afs_set_cr_ruid(tmp, afs_cr_ruid(cr));
afs_set_cr_gid(tmp, afs_cr_gid(cr));
afs_set_cr_rgid(tmp, afs_cr_rgid(cr));
get_group_info(cr_group_info(cr));
set_cr_group_info(tmp, cr_group_info(cr));
get_group_info(afs_cr_group_info(cr));
afs_set_cr_group_info(tmp, afs_cr_group_info(cr));
#endif
return tmp;
}
cred_t *
crref(void)
{
#if defined(STRUCT_TASK_HAS_CRED)
return (cred_t *)get_current_cred();
#else
cred_t *cr = crget();
afs_set_cr_uid(cr, current_fsuid());
@ -77,17 +100,17 @@ crref(void)
task_lock(current);
get_group_info(current_group_info());
set_cr_group_info(cr, current_group_info());
afs_set_cr_group_info(cr, current_group_info());
task_unlock(current);
return cr;
#endif
}
/* Set the cred info into the current task */
void
crset(cred_t * cr)
{
struct group_info *old_info;
#if defined(STRUCT_TASK_HAS_CRED)
struct cred *new_creds;
@ -98,30 +121,24 @@ crset(cred_t * cr)
if (current->cred != current->real_cred)
return;
new_creds = prepare_creds();
new_creds->fsuid = afs_cr_uid(cr);
new_creds->uid = afs_cr_ruid(cr);
new_creds->fsgid = afs_cr_gid(cr);
new_creds->gid = afs_cr_rgid(cr);
/* Drop the reference to group_info - we'll overwrite it in afs_copy_creds */
put_group_info(new_creds->group_info);
afs_copy_creds(new_creds, current_cred());
commit_creds(new_creds);
#else
struct group_info *old_info;
current->fsuid = afs_cr_uid(cr);
current->uid = afs_cr_ruid(cr);
current->fsgid = afs_cr_gid(cr);
current->gid = afs_cr_rgid(cr);
#endif
/* using set_current_groups() will sort the groups */
get_group_info(cr_group_info(cr));
get_group_info(afs_cr_group_info(cr));
task_lock(current);
#if defined(STRUCT_TASK_HAS_CRED)
old_info = current->cred->group_info;
new_creds->group_info = cr_group_info(cr);
commit_creds(new_creds);
#else
old_info = current->group_info;
current->group_info = cr_group_info(cr);
#endif
current->group_info = afs_cr_group_info(cr);
task_unlock(current);
put_group_info(old_info);
#endif
}

View File

@ -39,9 +39,9 @@ afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent)
AFS_STATCNT(afs_setgroups);
old_info = cr_group_info(*cr);
old_info = afs_cr_group_info(*cr);
get_group_info(group_info);
set_cr_group_info(*cr, group_info);
afs_set_cr_group_info(*cr, group_info);
put_group_info(old_info);
crset(*cr);
@ -65,8 +65,8 @@ afs_getgroups(cred_t * cr)
{
AFS_STATCNT(afs_getgroups);
get_group_info(cr_group_info(cr));
return cr_group_info(cr);
get_group_info(afs_cr_group_info(cr));
return afs_cr_group_info(cr);
}
int

View File

@ -153,38 +153,65 @@ static inline long copyinstr(char *from, char *to, int count, int *length) {
#define NGROUPS NGROUPS_SMALL
#endif
/* cred struct */
typedef struct afs_cred { /* maps to task field: */
int cr_ref;
uid_t cr_uid; /* euid */
uid_t cr_ruid; /* uid */
gid_t cr_gid; /* egid */
gid_t cr_rgid; /* gid */
struct group_info *cr_group_info;
} cred_t;
typedef struct afs_cred afs_ucred_t;
typedef struct task_struct afs_proc_t;
#define cr_group_info(cred) ((cred)->cr_group_info)
/* Credentials. For newer kernels we use the kernel structure directly. */
#if defined(STRUCT_TASK_HAS_CRED)
typedef struct cred afs_ucred_t;
typedef struct cred cred_t;
#define afs_cr_uid(cred) ((cred)->fsuid)
#define afs_cr_gid(cred) ((cred)->fsgid)
#define afs_cr_ruid(cred) ((cred)->uid)
#define afs_cr_rgid(cred) ((cred)->gid)
#define afs_cr_group_info(cred) ((cred)->group_info)
#define crhold(c) (get_cred(c))
static inline void
set_cr_group_info(afs_ucred_t *cred, struct group_info *group_info) {
cred->cr_group_info = group_info;
afs_set_cr_uid(cred_t *cred, uid_t uid) {
cred->fsuid = uid;
}
static inline void
afs_set_cr_gid(cred_t *cred, gid_t gid) {
cred->fsgid = gid;
}
static inline void
afs_set_cr_ruid(cred_t *cred, uid_t uid) {
cred->uid = uid;
}
static inline void
afs_set_cr_rgid(cred_t *cred, gid_t gid) {
cred->gid = gid;
}
static inline void
afs_set_cr_group_info(cred_t *cred, struct group_info *group_info) {
cred->group_info = group_info;
}
#if !defined(current_cred)
#define current_gid() (current->gid)
#define current_uid() (current->uid)
#define current_fsgid() (current->fsgid)
#define current_fsuid() (current->fsuid)
#endif
#if defined(STRUCT_TASK_HAS_CRED)
#define current_group_info() (current->cred->group_info)
#define task_gid(task) (task->cred->gid)
#define task_user(task) (task->cred->user)
#define task_session_keyring(task) (task->cred->tgcred->session_keyring)
#define current_session_keyring() (current->cred->tgcred->session_keyring)
#else
typedef struct afs_cred {
int cr_ref;
uid_t cr_uid;
uid_t cr_ruid;
gid_t cr_gid;
gid_t cr_rgid;
struct group_info *cr_group_info;
} cred_t;
typedef struct afs_cred afs_ucred_t;
#define afs_cr_group_info(cred) ((cred)->cr_group_info)
static inline void
afs_set_cr_group_info(cred_t *cred, struct group_info *group_info) {
cred->cr_group_info = group_info;
}
#define current_group_info() (current->group_info)
#if !defined(task_gid)
#define task_gid(task) (task->gid)
@ -195,9 +222,17 @@ set_cr_group_info(afs_ucred_t *cred, struct group_info *group_info) {
#define task_user(task) (task->user)
#define task_session_keyring(task) (task->signal->session_keyring)
#define current_session_keyring() (current->signal->session_keyring)
#endif
#define crhold(c) (c)->cr_ref++
#endif /* defined(STRUCT_TASK_HAS_CRED) */
#if !defined(current_cred)
#define current_gid() (current->gid)
#define current_uid() (current->uid)
#define current_fsgid() (current->fsgid)
#define current_fsuid() (current->fsuid)
#endif
/* UIO manipulation */
typedef enum { AFS_UIOSYS, AFS_UIOUSER } uio_seg_t;
typedef enum { UIO_READ, UIO_WRITE } uio_flag_t;

View File

@ -1399,7 +1399,12 @@ extern int afsd_dynamic_vcaches;
#define afsd_dynamic_vcaches 0
#endif
/* Wrappers for access to credentials structure members */
/*
* Wrappers for access to credentials structure members
* Linux uses the kernel cred structure if available, with the
* wrappers defined in LINUX/osi_machdep.h
*/
#if !(defined(AFS_LINUX26_ENV) && defined(STRUCT_TASK_HAS_CRED))
#define afs_cr_uid(cred) ((cred)->cr_uid)
#define afs_cr_gid(cred) ((cred)->cr_gid)
#define afs_cr_ruid(cred) ((cred)->cr_ruid)
@ -1421,4 +1426,5 @@ static_inline void
afs_set_cr_rgid(afs_ucred_t *cred, gid_t gid) {
cred->cr_rgid = gid;
}
#endif
#endif /* _AFS_H_ */

View File

@ -115,7 +115,7 @@ osi_Init(void)
#else
memset(&afs_osi_cred, 0, sizeof(afs_ucred_t));
#if defined(AFS_LINUX26_ENV)
set_cr_group_info(&afs_osi_cred, groups_alloc(0));
afs_set_cr_group_info(&afs_osi_cred, groups_alloc(0));
#endif
#if defined(AFS_DARWIN80_ENV)
afs_osi_cred.cr_ref = 1; /* kauth_cred_get_ref needs 1 existing ref */

View File

@ -571,7 +571,7 @@ PagInCred(afs_ucred_t *cred)
return NOPAG;
}
#elif defined(AFS_LINUX26_ENV)
if (cr_group_info(cred)->ngroups < NUMPAGGROUPS) {
if (afs_cr_group_info(cred)->ngroups < NUMPAGGROUPS) {
pag = NOPAG;
goto out;
}
@ -590,8 +590,8 @@ PagInCred(afs_ucred_t *cred)
g1 = cred->cr_groupset.gs_union.un_groups[1];
#elif defined(AFS_LINUX26_ONEGROUP_ENV)
#elif defined(AFS_LINUX26_ENV)
g0 = GROUP_AT(cr_group_info(cred), 0);
g1 = GROUP_AT(cr_group_info(cred), 1);
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];
@ -601,7 +601,7 @@ PagInCred(afs_ucred_t *cred)
#endif
#endif
#if defined(AFS_LINUX26_ONEGROUP_ENV)
pag = (afs_int32) afs_get_pag_from_groups(cr_group_info(cred));
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