rendered paste body#include <sys/priv.h>
#include <sys/sysproto.h>
#include <sys/lock.h>
#include <sys/sx.h>
#include <sys/proc.h>
#include <sys/mutex.h>
#include <sys/kernel.h>
#include <sys/unistd.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/condvar.h>
#define MAXGLOBALMAILBOXES 50
#define MPERM_OWNER_READ 0x100
#define MPERM_OWNER_WRITE 0x080
#define MPERM_OWNER_ADMIN 0x040
#define MPERM_GROUP_READ 0x020
#define MPERM_GROUP_WRITE 0x010
#define MPERM_GROUP_ADMIN 0x008
#define MPERM_OTHER_READ 0x004
#define MPERM_OTHER_WRITE 0x002
#define MPERM_OTHER_ADMIN 0x001
#define MPERM_READ_ALLOWED 0x4
#define MPERM_WRITE_ALLOWED 0x2
#define MPERM_ADMIN_ALLOWED 0x1
MALLOC_DECLARE(M_MBOX);
MALLOC_DEFINE(M_MBOX, "mailbox_system", "Buffers to hold mboxgr and mbox structs and their associated data");
// Function Prototypes
//==========================
static void mboxinit(void *dummy);
struct mboxgr* find_gmboxgr(const char *name, const int flag);
struct mboxgr* find_umboxgr(const uid_t uid, const int flag);
int check_mperms(struct proc *p, int perms, uid_t owner, int numGroups, gid_t *groups);
// Global Data
//==========================
struct sx all_gmboxgr_lock;
struct sx all_umboxgr_lock;
LIST_HEAD(mboxgrlist, mboxgr);
struct mboxgrlist all_gmboxgr;
struct mboxgrlist all_umboxgr;
int numGlobalGroups;
// Data Structures
//============================
struct mboxgr
{
int type; // 0 for user, 1 for global
char name[9]; // name of GLOBAL mboxgr
int perms; // permissions
uid_t owner; // uid of owner
gid_t groups[NGROUPS+1]; // groups the owner belonged to when this mboxgr was created
int numGroups;
LIST_ENTRY(mboxgr) mlist;
struct mbox *boxes[8];
int numBoxes;
struct mtx m_mtx; // lock for this struct
};
struct mbox
{
char name[256]; // name of mbox
int perms; // permissions
uid_t owner; // uid of owner
gid_t groups[NGROUPS+1]; // groups the owner belonged to when this mboxgr was created
int numGroups;
char message[256]; // message in mbox
int hasMessage; // 0 if mbox is empty, 1 if there is a message
struct mtx m_mtx;
struct cv *readable; // lock for this struct
struct cv *writeable;
};
// SUPPORT FUNCTIONS:
//======================
static void
mboxinit(dummy)
void *dummy;
{
printf("mailbox: Initializing CSE422 Project0 mailbox subsystem.\n");
sx_init(&all_gmboxgr_lock, "allgmboxgr");
sx_init(&all_umboxgr_lock, "allumboxgr");
numGlobalGroups = 0;
LIST_INIT(&all_gmboxgr);
LIST_INIT(&all_umboxgr);
}
SYSINIT(mbox, SI_SUB_MBOX, SI_ORDER_ANY, mboxinit, NULL)
struct mboxgr*
find_gmboxgr(name, flag)
const char *name;
const int flag;
{
struct mboxgr *g;
sx_assert(&all_gmboxgr_lock, SA_LOCKED);
LIST_FOREACH(g, &all_gmboxgr, mlist)
{
if(strcmp(name, g->name) == 0)
{
if(flag)
mtx_lock(&g->m_mtx);
return g;
}
}
return NULL;
}
struct mboxgr*
find_umboxgr(uid, flag)
const uid_t uid;
const int flag;
{
struct mboxgr *g;
sx_assert(&all_umboxgr_lock, SA_LOCKED);
LIST_FOREACH(g, &all_umboxgr, mlist)
{
if(uid == g->owner)
{
if(flag)
mtx_lock(&g->m_mtx);
return g;
}
}
return NULL;
}
int
check_mperms(p,perms, owner, numGroups, groups)
struct proc *p;
int perms;
uid_t owner;
int numGroups;
gid_t *groups;
{
int auth = 0;
int haveCommonGroup = 0;
PROC_LOCK_ASSERT(p, MA_OWNED);
auth = perms & (MPERM_OTHER_READ | MPERM_OTHER_WRITE | MPERM_OTHER_ADMIN);
if(owner == p->p_ucred->cr_ruid)
auth = auth & ((perms & (MPERM_OWNER_READ | MPERM_OWNER_WRITE | MPERM_OWNER_ADMIN)) >> 6);
for(int i = 0; i < p->p_ucred->cr_ngroups;i++)
{
for(int j = 0; j < numGroups; j++)
{
if(p->p_ucred->cr_groups[i] == groups[j])
{
haveCommonGroup = 1;
i = p->p_ucred->cr_ngroups; // set this to break out of outer loop.
break;
}
}
}
if(haveCommonGroup)
auth = auth & ((perms & (MPERM_GROUP_READ | MPERM_GROUP_WRITE | MPERM_GROUP_ADMIN)) >> 3);
return auth;
}
// SYSTEM CALLS:
//=============================
//(int type, char *name, uid_t uid, int perms)
int
create_mboxgr(td, uap)
struct thread *td;
register struct create_mboxgr_args *uap;
{
struct mboxgr *g;
uid_t targetUID;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if((uap->type == 0 && uap->name != NULL) || (uap->type == 1 && uap->name == NULL))
return (EINVAL);
if((uap->type==1) && (uap->name[0]==0))
return (EINVAL);
targetUID = uap->uid;
if(uap->uid != 0)
{
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)!=0)
return (EACCES);
}
else
{
targetUID = td->td_ucred->cr_ruid;
}
if(uap->type == 0)
{
sx_xlock(&all_umboxgr_lock);
if((g = find_umboxgr(uap->uid, 0)) != NULL)
{
sx_xunlock(&all_umboxgr_lock);
return (EINVAL);
}
MALLOC(g, struct mboxgr *, sizeof(struct mboxgr), M_MBOX, M_WAITOK);
g->type = 0;
g->name[0] = 0;
g->perms = uap->perms;
g->owner = targetUID;
g->numBoxes = 0;
mtx_init(&g->m_mtx,"struct mboxgr mutex",NULL, MTX_DEF);
g->numGroups = td->td_ucred->cr_ngroups + 1;
g->groups[0] = td->td_ucred->cr_rgid;
for(int j =1; j<g->numGroups; j++)
{
g->groups[j] = td->td_ucred->cr_groups[j-1];
}
LIST_INSERT_HEAD(&all_umboxgr, g, mlist);
sx_xunlock(&all_umboxgr_lock);
}
else // (uap->type == 1)
{
sx_xlock(&all_gmboxgr_lock);
if(numGlobalGroups == MAXGLOBALMAILBOXES)
{
sx_xunlock(&all_gmboxgr_lock);
return (EPERM);
}
if((g = find_gmboxgr(uap->name, 0)) != NULL)
{
sx_xunlock(&all_gmboxgr_lock);
return (EINVAL);
}
MALLOC(g, struct mboxgr *, sizeof(struct mboxgr), M_MBOX, M_WAITOK);
g->type = 1;
strncpy(uap->name, g->name, 8);
g->name[8]=0;
g->perms = uap->perms; //FIXME
g->owner = targetUID;
g->numBoxes = 0;
mtx_init(&g->m_mtx,"struct mboxgr mutex",NULL, MTX_DEF);
g->numGroups = td->td_ucred->cr_ngroups + 1;
g->groups[0] = td->td_ucred->cr_rgid;
for(int j =1; j<g->numGroups; j++)
{
g->groups[j] = td->td_ucred->cr_groups[j-1];
}
LIST_INSERT_HEAD(&all_gmboxgr, g, mlist);
numGlobalGroups++;
sx_xunlock(&all_gmboxgr_lock);
}
return 0;
}
int
destroy_mboxgr(td, uap)
register struct thread *td;
struct destroy_mboxgr_args *uap;
//(int type, char *name, uid_t uid)
{
struct mboxgr *g;
int authorization;
int rootPrivs;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if((uap->type == 0 && uap->name != NULL) || (uap->type == 1 && uap->name == NULL))
return (EINVAL);
if((uap->type==1) && (uap->name[0]==0))
return (EINVAL);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
if(uap->type == 1)
{
sx_xlock(&all_gmboxgr_lock);
if((g = find_gmboxgr(uap->name, 1)) != NULL)
{
if(!rootPrivs) // root can destroy any mailbox group????
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,g->perms,g->owner,g->numGroups,g->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & MPERM_ADMIN_ALLOWED) == 0)
{
mtx_unlock(&g->m_mtx);
sx_xunlock(&all_gmboxgr_lock);
return (EACCES);
}
}
LIST_REMOVE(g, mlist);
numGlobalGroups--;
}
else
{
sx_xunlock(&all_gmboxgr_lock);
return 0; // No such group, so return success.
}
}
else // uap->type == 0
{
sx_xlock(&all_umboxgr_lock);
if((g = find_umboxgr(uap->uid,1)) != NULL)
{
if(!rootPrivs) // root can destroy any mailbox group????
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,g->perms,g->owner,g->numGroups,g->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & MPERM_ADMIN_ALLOWED) == 0)
{
mtx_unlock(&g->m_mtx);
sx_xunlock(&all_gmboxgr_lock);
return (EACCES);
}
}
LIST_REMOVE(g, mlist);
}
else
{
sx_xunlock(&all_umboxgr_lock);
return 0; // No such group, so return success.
}
}
// replace this with calls to mbox_destroy() if neccessary to check we have perm. to delete each mbox?...?
for(int i = 0; i < g->numBoxes; i++)
{
mtx_lock(&g->boxes[i]->m_mtx);
cv_broadcast(g->boxes[i]->readable);
cv_broadcast(g->boxes[i]->writeable);
cv_destroy(g->boxes[i]->readable);
cv_destroy(g->boxes[i]->writeable);
mtx_destroy(&g->boxes[i]->m_mtx);
FREE(g->boxes[i],M_MBOX);
}
mtx_destroy(&g->m_mtx);
FREE(g,M_MBOX);
if(uap->type == 0)
sx_xunlock(&all_umboxgr_lock);
else
sx_xunlock(&all_gmboxgr_lock);
return 0;
}
int
join_mboxgr(td, uap)
register struct thread *td;
struct join_mboxgr_args *uap;
//(char *name, pid_t pid)
{
struct mboxgr *g;
struct proc* p;
p = NULL;
int authorization;
int rootPrivs = 0;
//int i;
if(uap->name==NULL)
return (EINVAL);
if(uap->name[0]==0)
return (EINVAL);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
if(uap->pid == 0)
{
p = td->td_proc;
PROC_LOCK(p);
}
else //uap->pid != 0
{
if((p = pfind(uap->pid)) == NULL)
{
return (ESRCH);
}
}
sx_slock(&all_gmboxgr_lock);
if((g = find_gmboxgr(uap->name,1)) != NULL) // uap->name is a valid global mailbox group name
{
if(!rootPrivs) // root can destroy any mailbox group????
{
authorization = check_mperms(p,g->perms,g->owner,g->numGroups,g->groups);
mtx_unlock(&g->m_mtx);
if((authorization & (MPERM_READ_ALLOWED | MPERM_WRITE_ALLOWED)) == 0)
{
PROC_UNLOCK(p);
sx_sunlock(&all_gmboxgr_lock);
return (EACCES);
}
}
mtx_unlock(&g->m_mtx);
strncpy(uap->name, p->p_gmboxgr, 8);
p->p_gmboxgr[8] = 0;
PROC_UNLOCK(p);
sx_sunlock(&all_gmboxgr_lock);
}
else
{
if(uap->name == NULL && (rootPrivs || (p->p_ucred->cr_ruid == td->td_ucred->cr_ruid)))
{
p->p_gmboxgr[0] = 0;
PROC_UNLOCK(p);
sx_sunlock(&all_gmboxgr_lock);
}
else
{
PROC_UNLOCK(p);
sx_sunlock(&all_gmboxgr_lock);
return (EACCES);
}
}
return 0;
}
int
create_mbox(td, uap)
register struct thread *td;
struct create_mbox_args *uap;
//(int type, char *name, uid_t uid, int perms)
{
uid_t targetUID;
struct mboxgr *g;
struct mbox *b;
struct proc* p;
p = NULL;
int authorization;
int rootPrivs = 0;
int i;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if(uap->name == NULL)
return (EINVAL);
if((uap->name[0])==0)
return (EINVAL);
if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
return (EINVAL);
if(strlen(uap->name)>255)
return (E2BIG);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
if(uap->type == 1)
{
sx_slock(&all_gmboxgr_lock);
g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
sx_sunlock(&all_gmboxgr_lock);
}
else // uap->type == 0
{
targetUID = uap->uid;
if(targetUID == 0)
{
targetUID = td->td_ucred->cr_ruid;
}
sx_slock(&all_umboxgr_lock);
g = find_umboxgr(targetUID,1);
sx_sunlock(&all_umboxgr_lock);
}
if(g == NULL)
{
return (EINVAL); // mailbox group not found
}
if(!rootPrivs)
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,g->perms,g->owner,g->numGroups,g->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & MPERM_ADMIN_ALLOWED) == 0)
{
mtx_unlock(&g->m_mtx);
return (EACCES); // not allowed to create new mbox
}
}
if(g->numBoxes == 8)
{
mtx_unlock(&g->m_mtx);
return (EPERM); // not allowed to create any more mboxs
}
for(int i = 0; i < g->numBoxes; i++)
{
mtx_lock(&g->boxes[i]->m_mtx);
if(strcmp(g->boxes[i]->name, uap->name) == 0)
{
mtx_unlock(&g->boxes[i]->m_mtx);
mtx_unlock(&g->m_mtx);
return (EINVAL); // already a box with that name
}
mtx_unlock(&g->boxes[i]->m_mtx);
}
MALLOC(b, struct mbox *, sizeof(struct mbox), M_MBOX, M_WAITOK);
// dont use strncpy because it'd copy 255 bytes every time.
for(i = 0; i < 255 && uap->name[i] != 0; i++)
{
b->name[i] = uap->name[i];
}
b->name[i] = 0;
b->perms = uap->perms;
b->owner = td->td_ucred->cr_ruid;
mtx_init(&b->m_mtx,"struct mbox mutex",NULL, MTX_DEF);
cv_init(b->readable,"struct mbox readable condition variable");
cv_init(b->writeable,"struct mbox writable condition variable");
b->numGroups = td->td_ucred->cr_ngroups + 1;
b->groups[0] = td->td_ucred->cr_rgid;
for(int i =1; i<b->numGroups; i++)
{
b->groups[i] = td->td_ucred->cr_groups[i-1];
}
g->boxes[g->numBoxes++] = b;
mtx_unlock(&g->m_mtx);
return 0;
}
int
destroy_mbox(td, uap)
register struct thread *td;
struct destroy_mbox_args *uap;
//(int type, char *name, uid_t uid)
{
struct mboxgr *g;
struct mbox *b;
struct proc* p;
uid_t targetUID;
p = NULL;
int authorization;
int rootPrivs = 0;
int i;
int foundBox;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if(uap->name == NULL)
return (EINVAL);
if(uap->name[0]==0)
return (EINVAL);
if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
return (EINVAL);
if(strlen(uap->name)>255)
return (E2BIG);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
if(uap->type == 1)
{
sx_slock(&all_gmboxgr_lock);
g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
sx_sunlock(&all_gmboxgr_lock);
}
else // uap->type == 0
{
targetUID = uap->uid;
if(targetUID == 0)
{
targetUID = td->td_ucred->cr_ruid;
}
sx_slock(&all_umboxgr_lock);
g = find_umboxgr(targetUID,1);
sx_slock(&all_umboxgr_lock);
}
if(g == NULL)
{
return (EINVAL); // mailbox group not found
}
foundBox = 0;
for(i = 0; i < g->numBoxes; i++)
{
mtx_lock(&g->boxes[i]->m_mtx);
if(strcmp(g->boxes[i]->name, uap->name) == 0)
{
foundBox = 1;
b = g->boxes[i];
break;
}
mtx_unlock(&g->boxes[i]->m_mtx);
}
if(!foundBox)
{
mtx_unlock(&g->m_mtx);
return (EINVAL); // mailbox not found
}
if(!rootPrivs)
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & MPERM_ADMIN_ALLOWED) == 0)
{
mtx_unlock(&b->m_mtx);
mtx_unlock(&g->m_mtx);
return (EACCES); // not allowed to create new mbox
}
}
if(i != ((g->numBoxes)-1))
{
g->boxes[i] = g->boxes[(g->numBoxes)-1];
}
g->boxes[(g->numBoxes)-1] = NULL;
g->numBoxes--;
cv_broadcast(b->readable);
cv_broadcast(b->writeable);
cv_destroy(b->readable);
cv_destroy(b->writeable);
mtx_destroy(&b->m_mtx);
FREE(b,M_MBOX);
mtx_unlock(&g->m_mtx);
return 0;
}
int
write_mbox(td, uap)
register struct thread *td;
struct write_mbox_args *uap;
//(int type, char *name, uid_t uid, char *message, int flag)
{
struct mbox *b;
struct proc* p;
struct mboxgr *g;
uid_t targetUID;
p = NULL;
int authorization;
int rootPrivs = 0;
int i;
int foundBox;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if(uap->name == NULL)
return (EINVAL);
if(uap->name[0]==0)
return (EINVAL);
if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
return (EINVAL);
if(strlen(uap->name)>255)
return (E2BIG);
if(strlen(uap->message)>255)
return (E2BIG);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
do
{
if(uap->type == 1)
{
sx_slock(&all_gmboxgr_lock);
g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
sx_sunlock(&all_gmboxgr_lock);
}
else // uap->type == 0
{
targetUID = uap->uid;
if(targetUID == 0)
{
targetUID = td->td_ucred->cr_ruid;
}
sx_slock(&all_umboxgr_lock);
g = find_umboxgr(targetUID,1);
sx_sunlock(&all_umboxgr_lock);
}
if(g == NULL)
{
return (EINVAL); // mailbox group not found
}
foundBox = 0;
b=NULL;
for(i = 0; i < g->numBoxes; i++)
{
mtx_lock(&g->boxes[i]->m_mtx);
if(strcmp(g->boxes[i]->name, uap->name) == 0)
{
foundBox = 1;
b = g->boxes[i];
break;
}
mtx_unlock(&g->boxes[i]->m_mtx);
}
mtx_unlock(&g->m_mtx);
if(!foundBox)
{
return (EINVAL); // mailbox not found
}
if(!rootPrivs)
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & (MPERM_WRITE_ALLOWED)) == 0)
{
mtx_unlock(&b->m_mtx);
return (EACCES); // not allowed to create new mbox
}
}
if(b->hasMessage == 0)
{
//write message
b->hasMessage = 1;
cv_broadcast(b->readable);
mtx_unlock(&b->m_mtx);
return 0;
}
if(uap->flag)
{
mtx_unlock(&b->m_mtx);
return (EWOULDBLOCK);
}
cv_wait_unlock(b->writeable, &b->m_mtx);
} while(1);
return 0;//should never get here
}
int
read_mbox(td, uap)
register struct thread *td;
struct read_mbox_args *uap;
//(int type, char *name, uid_t uid, char *message, int len, int flag)
{
struct mbox *b;
struct proc* p;
struct mboxgr *g;
uid_t targetUID;
p = NULL;
int authorization;
int rootPrivs = 0;
int i;
int foundBox;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if(uap->name == NULL)
return (EINVAL);
if(uap->name[0]==0)
return (EINVAL);
if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
return (EINVAL);
if(strlen(uap->name)>255)
return (E2BIG);
if(strlen(uap->message)>255)
return (E2BIG);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
do
{
if(uap->type == 1)
{
sx_slock(&all_gmboxgr_lock);
g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
sx_sunlock(&all_gmboxgr_lock);
}
else // uap->type == 0
{
targetUID = uap->uid;
if(targetUID == 0)
{
targetUID = td->td_ucred->cr_ruid;
}
sx_slock(&all_umboxgr_lock);
g = find_umboxgr(targetUID,1);
sx_sunlock(&all_umboxgr_lock);
}
if(g == NULL)
{
return (EINVAL); // mailbox group not found
}
foundBox = 0;
b=NULL;
for(i = 0; i < g->numBoxes; i++)
{
mtx_lock(&g->boxes[i]->m_mtx);
if(strcmp(g->boxes[i]->name, uap->name) == 0)
{
foundBox = 1;
b = g->boxes[i];
break;
}
mtx_unlock(&g->boxes[i]->m_mtx);
}
mtx_unlock(&g->m_mtx);
if(!foundBox)
{
return (EINVAL); // mailbox not found
}
if(!rootPrivs)
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & (MPERM_READ_ALLOWED)) == 0)
{
mtx_unlock(&b->m_mtx);
return (EACCES); // not allowed to create new mbox
}
}
if(b->hasMessage == 1)
{
//read message
b->hasMessage = 0;
cv_broadcast(b->writeable);
mtx_unlock(&b->m_mtx);
return 0;
}
if(uap->flag)
{
mtx_unlock(&b->m_mtx);
return (EWOULDBLOCK);
}
mtx_unlock(&b->m_mtx);
cv_wait_unlock(b->readable, &b->m_mtx);
} while(1);
}
int
clear_mbox(td, uap)
register struct thread *td;
struct clear_mbox_args *uap;
//(int type, char *name, uid_t uid)
{
struct mboxgr *g;
struct mbox *b;
struct proc* p;
uid_t targetUID;
p = NULL;
int authorization;
int rootPrivs = 0;
int i;
int foundBox;
if(uap->type < 0 || uap->type > 1)
return (EINVAL);
if(uap->name == NULL)
return (EINVAL);
if(uap->name[0]==0)
return (EINVAL);
if((uap->type == 1) && (td->td_proc->p_gmboxgr[0]==0))
return (E2BIG);
if(strlen(uap->name)>255)
return (E2BIG);
if(priv_check_cred(td->td_ucred, PRIV_ROOT,0)==0)
rootPrivs = 1;
else
rootPrivs = 0;
if(uap->type == 1)
{
sx_slock(&all_gmboxgr_lock);
g = find_gmboxgr(td->td_proc->p_gmboxgr,1);
sx_sunlock(&all_gmboxgr_lock);
}
else // uap->type == 0
{
targetUID = uap->uid;
if(targetUID == 0)
{
targetUID = td->td_ucred->cr_ruid;
}
sx_slock(&all_umboxgr_lock);
g = find_umboxgr(targetUID,1);
sx_sunlock(&all_umboxgr_lock);
}
if(g == NULL)
{
return (EINVAL); // mailbox group not found
}
foundBox = 0;
b=NULL;
for(i = 0; i < g->numBoxes; i++)
{
mtx_lock(&g->boxes[i]->m_mtx);
if(strcmp(g->boxes[i]->name, uap->name) == 0)
{
foundBox = 1;
b = g->boxes[i];
break;
}
mtx_unlock(&g->boxes[i]->m_mtx);
}
mtx_unlock(&g->m_mtx);
if(!foundBox)
{
return (EINVAL); // mailbox not found
}
if(!rootPrivs)
{
PROC_LOCK(td->td_proc);
authorization = check_mperms(td->td_proc,b->perms,b->owner,b->numGroups,b->groups);
PROC_UNLOCK(td->td_proc);
if((authorization & (MPERM_ADMIN_ALLOWED|MPERM_READ_ALLOWED)) == 0)
{
mtx_unlock(&b->m_mtx);
return (EACCES); // not allowed to create new mbox
}
}
b->hasMessage = 0;
cv_broadcast(b->readable);
cv_broadcast(b->writeable);
mtx_unlock(&b->m_mtx);
return 0;
}