1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* 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)
{
/* VM makes asynchronous calls to itself. Always allow those. */
if (vmp->vm_endpoint == VM_PROC_NR)
return OK;
/* If the process has no ACL, all calls are allowed.. for now. */
if (vmp->vm_acl == NO_ACL) {
/* RS instrumented with ASR may call VM_BRK at startup. */
if (vmp->vm_endpoint == RS_PROC_NR)
return OK;
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;
}
}
|