#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)
{
#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
}
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());
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;
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
}
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);
{
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
#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)
#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;
#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)
afs_set_cr_rgid(afs_ucred_t *cred, gid_t gid) {
cred->cr_rgid = gid;
}
+#endif
#endif /* _AFS_H_ */
#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 */
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;
}
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];
#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