mirror of
https://git.openafs.org/openafs.git
synced 2025-01-22 08:50:17 +00:00
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:
parent
97d3fcfcd1
commit
dc85abcaa6
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user