1
0
Files
irix-657m-src/irix/kern/io/ipc.c
2022-09-29 17:59:04 +03:00

201 lines
4.8 KiB
C

/* Copyright 1986, Silicon Graphics Inc., Mountain View, CA. */
/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/*#ident "@(#)kern-port:io/ipc.c 10.3"*/
#ident "$Revision: 3.29 $"
#include "sys/types.h"
#include "sys/param.h"
#include "sys/errno.h"
#include "sys/kipc.h"
#include "sys/ipc.h"
#include "sys/sat.h"
#include "sys/mac_label.h"
#include "sys/capability.h"
/*
** Common IPC routines.
*/
/*
** Check message, semaphore, or shared memory access permissions.
**
** This routine verifies the requested access permission for the current
** process. Super-user is always given permission. Otherwise, the
** appropriate bits are checked corresponding to owner, group, or
** everyone. Zero is returned on success. On failure, return EACCES.
** The arguments must be set up as follows:
** p - Pointer to permission structure to verify
** mode - Desired access permissions
*/
int
ipcaccess(struct ipc_perm *p,
struct cred *cred,
ushort mode)
{
ushort sat_mode = mode;
int error;
if (cred->cr_uid != p->uid && cred->cr_uid != p->cuid) {
mode >>= 3;
if (!groupmember(p->gid, cred) && !groupmember(p->cgid, cred))
mode >>= 3;
}
error = (mode & p->mode || _CAP_CRABLE(cred, CAP_DAC_OVERRIDE)) ?
0 : EACCES;
_SAT_SVIPC_ACCESS(NULL, sat_mode,
SAT_DAC | (error ? SAT_FAILURE : SAT_SUCCESS), error);
return(error);
}
/*
** Get message, semaphore, or shared memory structure.
**
** This routine searches for a matching key based on the given flags
** and returns a pointer to the appropriate entry. A structure is
** allocated if the key doesn't exist and the flags call for it.
** The arguments must be set up as follows:
** key - Key to be used
** flag - Creation flags and access modes
** ipcfcn - Function that returns ptrs to appropriate
** ipc id structure and associated semaphore
** size - sizeof(facility structure)
** status - Pointer to status word: set on successful completion
** only: 0 => existing entry found
** 1 => new entry created
** Ipcget returns the appropriate errno if it fails, or 0 if it succeeds.
*/
int
ipcget( key_t key,
register int flag,
register int (*ipcfcn)(int, struct ipc_perm **, mutex_t **),
register int *status,
struct cred *cred,
register int *indxp)
{
struct ipc_perm *base; /* ptr to perm array entry */
register struct ipc_perm *a; /* ptr to available entry */
mutex_t *lockp; /* ptr to perm mutex */
mutex_t *slockp;/* ptr to mutex for available entry */
register int i; /* loop control */
int indx;
int error;
if (key == IPC_PRIVATE) {
for (i = 0; (*ipcfcn)(i, &base, &lockp); i++) {
if (base->mode & IPC_ALLOC)
continue;
mutex_lock(lockp, PZERO);
if (base->mode & IPC_ALLOC) {
mutex_unlock(lockp);
continue;
}
indx = i;
goto init;
}
return ENOSPC;
}
tryagain:
for (i = 0, a = NULL; (*ipcfcn)(i, &base, &lockp); i++) {
if (base->mode & IPC_ALLOC) {
if (base->key == key) {
mutex_lock(lockp, PZERO);
if (base->key != key) {
mutex_unlock(lockp);
goto tryagain;
}
if ((flag & (IPC_CREAT | IPC_EXCL)) ==
(IPC_CREAT | IPC_EXCL)) {
error = EEXIST;
goto ipc_badget;
}
if ((flag & 0777) & ~base->mode) {
error = EACCES;
goto ipc_badget;
}
*status = 0;
*indxp = i;
return 0;
}
continue;
}
if (a == NULL) {
a = base;
slockp = lockp;
indx = i;
}
}
if (!(flag & IPC_CREAT))
return ENOENT;
if (a == NULL)
return ENOSPC;
base = a;
lockp = slockp;
mutex_lock(lockp, PZERO);
/* make sure two processors have not grabbed the same slot */
if (base->mode & IPC_ALLOC) {
mutex_unlock(lockp);
goto tryagain;
}
init:
*status = 1;
base->mode = IPC_ALLOC | (flag & 0777);
base->key = key;
base->cuid = base->uid = cred->cr_uid;
base->cgid = base->gid = cred->cr_gid;
*indxp = indx;
return 0;
ipc_badget:
mutex_unlock(lockp);
return error;
}
void
ipc_init(
struct ipc_perm *perm,
key_t key,
register int flag,
struct cred *cred)
{
perm->mode = IPC_ALLOC | (flag & 0777);
perm->key = key;
perm->cuid = perm->uid = cred->cr_uid;
perm->cgid = perm->gid = cred->cr_gid;
}
#if _MIPS_SIM == _ABI64
void
irix5_to_ipc_perm(
struct irix5_ipc_perm *i5_perm,
struct ipc_perm *perm)
{
perm->uid = i5_perm->uid;
perm->gid = i5_perm->gid;
perm->cuid = i5_perm->cuid;
perm->cgid = i5_perm->cgid;
perm->mode = i5_perm->mode;
perm->seq = i5_perm->seq;
perm->key = i5_perm->key;
}
void
ipc_perm_to_irix5(
struct ipc_perm *perm,
struct irix5_ipc_perm *i5_perm)
{
i5_perm->uid = perm->uid;
i5_perm->gid = perm->gid;
i5_perm->cuid = perm->cuid;
i5_perm->cgid = perm->cgid;
i5_perm->mode = perm->mode;
i5_perm->seq = perm->seq;
i5_perm->key = perm->key;
}
#endif /* _ABI64 */