121 lines
2.5 KiB
C
121 lines
2.5 KiB
C
|
|
||
|
/* Call mask ACL management. */
|
||
|
|
||
|
#include <minix/drivers.h>
|
||
|
|
||
|
#include "proto.h"
|
||
|
#include "glo.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
#define NO_ACL -1
|
||
|
#define USER_ACL 0
|
||
|
#define FIRST_SYS_ACL 1
|
||
|
|
||
|
static bitchunk_t acl_mask[NR_SYS_PROCS][VM_CALL_MASK_SIZE];
|
||
|
static bitchunk_t acl_inuse[BITMAP_CHUNKS(NR_SYS_PROCS)];
|
||
|
|
||
|
/*
|
||
|
* Initialize ACL data structures.
|
||
|
*/
|
||
|
void
|
||
|
acl_init(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < ELEMENTS(vmproc); i++)
|
||
|
vmproc[i].vm_acl = NO_ACL;
|
||
|
|
||
|
memset(acl_mask, 0, sizeof(acl_mask));
|
||
|
memset(acl_inuse, 0, sizeof(acl_inuse));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check whether a process is allowed to make a certain (zero-based) call.
|
||
|
* Return OK or an error.
|
||
|
*/
|
||
|
int
|
||
|
acl_check(struct vmproc *vmp, int call)
|
||
|
{
|
||
|
/* If the process has no ACL, all calls are allowed.. for now. */
|
||
|
if (vmp->vm_acl == NO_ACL) {
|
||
|
printf("VM: calling process %u has no ACL!\n",
|
||
|
vmp->vm_endpoint);
|
||
|
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
/* See if the call is allowed. */
|
||
|
if (!GET_BIT(acl_mask[vmp->vm_acl], call))
|
||
|
return EPERM;
|
||
|
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Assign a call mask to a process. User processes share the first ACL entry.
|
||
|
* System processes are assigned to any of the other slots. For user
|
||
|
* processes, no call mask need to be provided: it will simply be inherited in
|
||
|
* that case.
|
||
|
*/
|
||
|
void
|
||
|
acl_set(struct vmproc *vmp, bitchunk_t *mask, int sys_proc)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
acl_clear(vmp);
|
||
|
|
||
|
if (sys_proc) {
|
||
|
for (i = FIRST_SYS_ACL; i < NR_SYS_PROCS; i++)
|
||
|
if (!GET_BIT(acl_inuse, i))
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
* This should never happen. If it does, then different user
|
||
|
* processes have been assigned call masks separately. It is
|
||
|
* RS's responsibility to prevent that.
|
||
|
*/
|
||
|
if (i == NR_SYS_PROCS) {
|
||
|
printf("VM: no ACL entries available!\n");
|
||
|
return;
|
||
|
}
|
||
|
} else
|
||
|
i = USER_ACL;
|
||
|
|
||
|
if (!GET_BIT(acl_inuse, i) && mask == NULL)
|
||
|
printf("VM: WARNING: inheriting uninitialized ACL mask\n");
|
||
|
|
||
|
SET_BIT(acl_inuse, i);
|
||
|
vmp->vm_acl = i;
|
||
|
|
||
|
if (mask != NULL)
|
||
|
memcpy(&acl_mask[vmp->vm_acl], mask, sizeof(acl_mask[0]));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* A process has forked. User processes inherit their parent's ACL by default,
|
||
|
* although they may be turned into system processes later. System processes
|
||
|
* do not inherit an ACL, and will have to be assigned one before getting to
|
||
|
* run.
|
||
|
*/
|
||
|
void
|
||
|
acl_fork(struct vmproc *vmp)
|
||
|
{
|
||
|
if (vmp->vm_acl != USER_ACL)
|
||
|
vmp->vm_acl = NO_ACL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* A process has exited. Decrease the reference count on its ACL entry, and
|
||
|
* mark the process as having no ACL.
|
||
|
*/
|
||
|
void
|
||
|
acl_clear(struct vmproc *vmp)
|
||
|
{
|
||
|
if (vmp->vm_acl != NO_ACL) {
|
||
|
if (vmp->vm_acl != USER_ACL)
|
||
|
UNSET_BIT(acl_inuse, vmp->vm_acl);
|
||
|
|
||
|
vmp->vm_acl = NO_ACL;
|
||
|
}
|
||
|
}
|