#include <afsconfig.h>
#include "afs/param.h"
-RCSID
- ("$Header$");
#include "afs/sysincludes.h"
#include "afsincludes.h"
-/* Setup a pool for creds. Allocate several at a time. */
-#define CRED_ALLOC_STEP 29 /* at 140 bytes/cred = 4060 bytes. */
-
-
-static cred_t *cred_pool = NULL;
-int cred_allocs = 0;
-int ncreds_inuse = 0;
-
-/* Cred locking assumes current single threaded non-preemptive kernel.
- * Also assuming a fast path through both down and up if no waiters. Otherwise,
- * test if no creds in pool before grabbing lock in crfree().
- */
-#if defined(AFS_LINUX24_ENV)
-static DECLARE_MUTEX(linux_cred_pool_lock);
-#else
-static struct semaphore linux_cred_pool_lock = MUTEX;
-#endif
-#define CRED_LOCK() down(&linux_cred_pool_lock)
-#define CRED_UNLOCK() up(&linux_cred_pool_lock)
-
cred_t *
crget(void)
{
cred_t *tmp;
- int i;
-
- CRED_LOCK();
- if (!cred_pool) {
- cred_allocs++;
- cred_pool = (cred_t *) osi_Alloc(CRED_ALLOC_STEP * sizeof(cred_t));
- if (!cred_pool)
- osi_Panic("crget: No more memory for creds!\n");
-
- for (i = 0; i < CRED_ALLOC_STEP - 1; i++)
- cred_pool[i].cr_next = (cred_t *) &cred_pool[i + 1];
- cred_pool[i].cr_next = NULL;
- }
- tmp = cred_pool;
- cred_pool = (cred_t *) tmp->cr_next;
- ncreds_inuse++;
- CRED_UNLOCK();
-
- memset(tmp, 0, sizeof(cred_t));
+
+#if !defined(GFP_NOFS)
+#define GFP_NOFS GFP_KERNEL
+#endif
+ tmp = kmalloc(sizeof(cred_t), GFP_NOFS);
+ if (!tmp)
+ osi_Panic("crget: No more memory for creds!\n");
+
tmp->cr_ref = 1;
return tmp;
}
return;
}
-#if defined(AFS_LINUX26_ENV)
put_group_info(cr->cr_group_info);
-#endif
- CRED_LOCK();
- cr->cr_next = (cred_t *) cred_pool;
- cred_pool = cr;
- CRED_UNLOCK();
- ncreds_inuse--;
+
+ kfree(cr);
}
tmp->cr_uid = cr->cr_uid;
tmp->cr_ruid = cr->cr_ruid;
tmp->cr_gid = cr->cr_gid;
+ tmp->cr_rgid = cr->cr_rgid;
-#if defined(AFS_LINUX26_ENV)
get_group_info(cr->cr_group_info);
tmp->cr_group_info = cr->cr_group_info;
-#else
- memcpy(tmp->cr_groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
- tmp->cr_ngroups = cr->cr_ngroups;
-#endif
- tmp->cr_ref = 1;
return tmp;
}
{
cred_t *cr = crget();
- cr->cr_uid = current->fsuid;
- cr->cr_ruid = current->uid;
- cr->cr_gid = current->fsgid;
- cr->cr_rgid = current->gid;
+ cr->cr_uid = current_fsuid();
+ cr->cr_ruid = current_uid();
+ cr->cr_gid = current_fsgid();
+ cr->cr_rgid = current_gid();
-#if defined(AFS_LINUX26_ENV)
task_lock(current);
- get_group_info(current->group_info);
- cr->cr_group_info = current->group_info;
+ get_group_info(current_group_info());
+ cr->cr_group_info = current_group_info();
task_unlock(current);
-#else
- memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
- cr->cr_ngroups = current->ngroups;
-#endif
+
return cr;
}
-
/* 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 our current task doesn't have identical real and effective
+ * credentials, commit_cred won't let us change them, so we just
+ * bail here.
+ */
+ if (current->cred != current->real_cred)
+ return;
+ new_creds = prepare_creds();
+ new_creds->fsuid = cr->cr_uid;
+ new_creds->uid = cr->cr_ruid;
+ new_creds->fsgid = cr->cr_gid;
+ new_creds->gid = cr->cr_rgid;
+#else
current->fsuid = cr->cr_uid;
current->uid = cr->cr_ruid;
current->fsgid = cr->cr_gid;
current->gid = cr->cr_rgid;
-#if defined(AFS_LINUX26_ENV)
-{
- struct group_info *old_info;
+#endif
/* using set_current_groups() will sort the groups */
get_group_info(cr->cr_group_info);
task_lock(current);
+#if defined(STRUCT_TASK_HAS_CRED)
+ old_info = current->cred->group_info;
+ new_creds->group_info = cr->cr_group_info;
+ commit_creds(new_creds);
+#else
old_info = current->group_info;
current->group_info = cr->cr_group_info;
+#endif
task_unlock(current);
put_group_info(old_info);
}
-#else
- memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
- current->ngroups = cr->cr_ngroups;
-#endif
-}