Files
Arquivotheca.AIX-4.1.3/bos/kernel/s/auth/cred.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

428 lines
7.6 KiB
C

static char sccsid[] = "@(#)25 1.13.1.7 src/bos/kernel/s/auth/cred.c, syssauth, bos411, 9428A410j 7/6/94 15:28:27";
/*
* COMPONENT_NAME: TCBAUTH
*
* FUNCTIONS: crget(), crfree(), crcopy(), crdup(), crset(),
* crlock(), crunlock(), credlock(), credunlock(), crref(),
* _crget(), _crfree(), _crcopy(), _crdup()
*
* ORIGINS: 27 83
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1988, 1993
* All Rights Reserved
* Licensed Materials - Property of IBM
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/*
* LEVEL 1, 5 Years Bull Confidential Information
*/
/*
* Kernel service routines to manipulate credentials
*/
#include "sys/param.h"
#include "sys/systm.h"
#include "grp.h"
#include "sys/user.h"
#include "sys/intr.h"
#include "sys/malloc.h"
#include "sys/limits.h"
#include "sys/syspest.h"
#include "sys/lockl.h"
#include "sys/lock_alloc.h"
#include "sys/lockname.h"
#include "sys/cred.h"
#include "crlock.h"
extern Simple_lock cred_lock;
/*
* Routines to allocate and free credentials structures
*/
static void credalloc();
volatile int crtotal = 0;
#define CL_MAGIC (0x9357fdb1)
struct credlist {
int cl_magic;
struct credlist *cl_next;
};
static struct credlist *crfreelist = NULL;
Simple_lock cred_lock;
/*
* Allocate a zeroed cred structure and increment its reference count.
*
*/
/* _crget() : crget() wthout lock (internal function) */
struct ucred *
_crget()
{
register struct ucred *cr;
/*
* Get the cred lock, get the next cred off of the freelist,
* update the freelist, and unlock the cred list.
*/
if (! crfreelist)
(void)credalloc(); /* get a page of creds */
/*
* I have a valid value in crfreelist and the cred list is
* locked - no one else can steal my cred before I get
* to it.
*/
cr = (struct ucred *) crfreelist;
crfreelist = crfreelist->cl_next;
/*
* We are assured that "cr" is non-NULL, so I will
* initialize it to all zeros and mark it as held.
* I also keep a count of total creds as a sanity check
* against the cred list being corrupted.
*/
assert(cr != 0);
assert(((struct credlist *) cr)->cl_magic == CL_MAGIC);
bzero((caddr_t)cr, sizeof(*cr));
/*
* Don't do crhold here as it leads to dead lock
*/
cr->cr_ref = 1;
/*
* I have gotten the cred structure off the free list
* and pointed to the next free element - now I can
* unlock the cred list.
*/
return(cr);
}
struct ucred *
crget()
{
register struct ucred *cr;
/*
* Get the cred lock, get the next cred off of the freelist,
* update the freelist, and unlock the cred list.
*/
CRED_LOCK();
if (! crfreelist)
(void)credalloc(); /* get a page of creds */
/*
* I have a valid value in crfreelist and the cred list is
* locked - no one else can steal my cred before I get
* to it.
*/
cr = (struct ucred *) crfreelist;
crfreelist = crfreelist->cl_next;
CRED_UNLOCK();
/*
* We are assured that "cr" is non-NULL, so I will
* initialize it to all zeros and mark it as held.
* I also keep a count of total creds as a sanity check
* against the cred list being corrupted.
*/
assert(cr != 0);
assert(((struct credlist *) cr)->cl_magic == CL_MAGIC);
bzero((caddr_t)cr, sizeof(*cr));
/*
* Don't do crhold here as it leads to dead lock
*/
cr->cr_ref = 1;
/*
* I have gotten the cred structure off the free list
* and pointed to the next free element - now I can
* unlock the cred list.
*/
return(cr);
}
/*
* Free a cred structure.
* Throws away space when ref count gets to 0.
*/
void
_crfree(cr)
struct ucred *cr;
{
assert(((struct credlist *)cr)->cl_magic != CL_MAGIC);
if (--cr->cr_ref > 0)
{
/*
* This cred structure is still being used. Simply return
*/
return;
}
/*
* Stick the cred structure back on the freelist.
*/
((struct credlist *)cr)->cl_next = crfreelist;
((struct credlist *)cr)->cl_magic = CL_MAGIC;
crfreelist = (struct credlist *)cr;
}
void
crfree(cr)
struct ucred *cr;
{
/*
* Serialize access to the free list by holding the cred lock
*/
CRED_LOCK();
_crfree (cr);
CRED_UNLOCK();
}
/*
* Copy cred structure to a new one and free the old one.
*/
struct ucred *
_crcopy(cr)
struct ucred *cr;
{
struct ucred *newcr, *_crdup();
ASSERT(cr != 0);
/*
* No need to duplicate and copy if this is the only process
* having the cred
*/
if (cr->cr_ref == 1)
return(cr);
newcr = _crdup(cr);
ASSERT(newcr != 0);
_crfree(cr);
return(newcr);
}
struct ucred *
crcopy(cr)
struct ucred *cr;
{
struct ucred *newcr, *crdup();
ASSERT(cr != 0);
/*
* No need to duplicate and copy if this is the only process
* having the cred
*/
if (cr->cr_ref == 1)
return(cr);
newcr = crdup(cr);
ASSERT(newcr != 0);
crfree(cr);
return(newcr);
}
/*
* Dup cred struct to a new held one.
*/
struct ucred *
_crdup(cr)
struct ucred *cr;
{
struct ucred *newcr;
struct ucred *_crget();
ASSERT(cr != 0);
newcr = _crget();
ASSERT(newcr != 0);
*newcr = *cr;
newcr->cr_ref = 1;
return(newcr);
}
struct ucred *
crdup(cr)
struct ucred *cr;
{
struct ucred *newcr;
struct ucred *crget();
ASSERT(cr != 0);
newcr = crget();
ASSERT(newcr != 0);
*newcr = *cr;
newcr->cr_ref = 1;
return(newcr);
}
/*
* Initialize cred freelist and initial struct user's cred.
*/
void
credinit()
{
/*
* Alloctate cred_lock and initialize
*/
lock_alloc(&cred_lock,LOCK_ALLOC_PAGED,CRED_LOCK_CLASS,-1);
simple_lock_init(&cred_lock);
/*
* Lock cred_lock before calling cred_alloc
*/
CRED_LOCK();
(void)credalloc(); /* get a page of creds */
CRED_UNLOCK();
/*
* No need to take CRED_LOCK as the boot process is
* single threaded
*/
U.U_cred = crget(); /* get one for initial u. */
}
/*
* do a per page allocation for cred structs.
* NOTE that it is used by crget() and credinit().
* NOTE: should we keep track of how many pages of creds are gotten???
* NOTE: should we print warning msgs if > about 4 pages gotten???
* MP : The free list must be locked prior to calling credalloc()
*/
void
credalloc()
{
struct ucred *cr;
caddr_t page;
int i;
assert((page = (caddr_t)xmalloc(PAGESIZE, 12, kernel_heap)) != NULL);
bzero(page, PAGESIZE);
i = PAGESIZE / sizeof(struct ucred); /* how many per page */
cr = (struct ucred *)page;
/*
* Step through the entire page of cred structures putting each
* one onto the free list
*/
while (i--)
{
((struct credlist *)cr)->cl_next = crfreelist;
((struct credlist *)cr)->cl_magic = CL_MAGIC;
crfreelist = (struct credlist *)cr;
crtotal++;
cr++;
}
}
/*
* Lock the cred lock in the u structure
*/
void crlock()
{
CR_LOCK();
}
/*
* Unlock the cred lock in the u structure
*/
void crunlock()
{
CR_UNLOCK();
}
/*
* Lock the cred_lock lock
*/
void credlock()
{
CRED_LOCK();
}
/*
* Unlock the cred_lock lock
*/
void credunlock()
{
CRED_UNLOCK();
}
/*
* Return a pointer to the cred structure. Inc ref count
*/
struct ucred *
crref(void)
{
struct ucred *temp;
CRED_LOCK();
temp = U.U_cred;
assert(((struct credlist *)temp)->cl_magic != CL_MAGIC);
temp->cr_ref++;
CRED_UNLOCK();
return(temp);
}
/*
* set the process credentials
*/
void
crset(struct ucred *ucp)
{
CRED_LOCK();
if (U.U_cred)
_crfree(U.U_cred);
U.U_cred = ucp;
CRED_UNLOCK();
}
void
crhold(struct ucred *ucp)
{
CRED_LOCK();
assert(((struct credlist *)ucp)->cl_magic != CL_MAGIC);
ucp->cr_ref++;
CRED_UNLOCK();
}