1
2 /* Call mask ACL management. */
3
4 #include <minix/drivers.h>
5
6 #include "proto.h"
7 #include "glo.h"
8 #include "util.h"
9
10 #define NO_ACL -1
11 #define USER_ACL 0
12 #define FIRST_SYS_ACL 1
13
14 static bitchunk_t acl_mask[NR_SYS_PROCS][VM_CALL_MASK_SIZE];
15 static bitchunk_t acl_inuse[BITMAP_CHUNKS(NR_SYS_PROCS)];
16
17 /*
18 * Initialize ACL data structures.
19 */
20 void
acl_init(void)21 acl_init(void)
22 {
23 int i;
24
25 for (i = 0; i < ELEMENTS(vmproc); i++)
26 vmproc[i].vm_acl = NO_ACL;
27
28 memset(acl_mask, 0, sizeof(acl_mask));
29 memset(acl_inuse, 0, sizeof(acl_inuse));
30 }
31
32 /*
33 * Check whether a process is allowed to make a certain (zero-based) call.
34 * Return OK or an error.
35 */
36 int
acl_check(struct vmproc * vmp,int call)37 acl_check(struct vmproc *vmp, int call)
38 {
39
40 /* VM makes asynchronous calls to itself. Always allow those. */
41 if (vmp->vm_endpoint == VM_PROC_NR)
42 return OK;
43
44 /* If the process has no ACL, all calls are allowed.. for now. */
45 if (vmp->vm_acl == NO_ACL) {
46 /* RS instrumented with ASR may call VM_BRK at startup. */
47 if (vmp->vm_endpoint == RS_PROC_NR)
48 return OK;
49
50 printf("VM: calling process %u has no ACL!\n",
51 vmp->vm_endpoint);
52
53 return OK;
54 }
55
56 /* See if the call is allowed. */
57 if (!GET_BIT(acl_mask[vmp->vm_acl], call))
58 return EPERM;
59
60 return OK;
61 }
62
63 /*
64 * Assign a call mask to a process. User processes share the first ACL entry.
65 * System processes are assigned to any of the other slots. For user
66 * processes, no call mask need to be provided: it will simply be inherited in
67 * that case.
68 */
69 void
acl_set(struct vmproc * vmp,bitchunk_t * mask,int sys_proc)70 acl_set(struct vmproc *vmp, bitchunk_t *mask, int sys_proc)
71 {
72 int i;
73
74 acl_clear(vmp);
75
76 if (sys_proc) {
77 for (i = FIRST_SYS_ACL; i < NR_SYS_PROCS; i++)
78 if (!GET_BIT(acl_inuse, i))
79 break;
80
81 /*
82 * This should never happen. If it does, then different user
83 * processes have been assigned call masks separately. It is
84 * RS's responsibility to prevent that.
85 */
86 if (i == NR_SYS_PROCS) {
87 printf("VM: no ACL entries available!\n");
88 return;
89 }
90 } else
91 i = USER_ACL;
92
93 if (!GET_BIT(acl_inuse, i) && mask == NULL)
94 printf("VM: WARNING: inheriting uninitialized ACL mask\n");
95
96 SET_BIT(acl_inuse, i);
97 vmp->vm_acl = i;
98
99 if (mask != NULL)
100 memcpy(&acl_mask[vmp->vm_acl], mask, sizeof(acl_mask[0]));
101 }
102
103 /*
104 * A process has forked. User processes inherit their parent's ACL by default,
105 * although they may be turned into system processes later. System processes
106 * do not inherit an ACL, and will have to be assigned one before getting to
107 * run.
108 */
109 void
acl_fork(struct vmproc * vmp)110 acl_fork(struct vmproc *vmp)
111 {
112 if (vmp->vm_acl != USER_ACL)
113 vmp->vm_acl = NO_ACL;
114 }
115
116 /*
117 * A process has exited. Decrease the reference count on its ACL entry, and
118 * mark the process as having no ACL.
119 */
120 void
acl_clear(struct vmproc * vmp)121 acl_clear(struct vmproc *vmp)
122 {
123 if (vmp->vm_acl != NO_ACL) {
124 if (vmp->vm_acl != USER_ACL)
125 UNSET_BIT(acl_inuse, vmp->vm_acl);
126
127 vmp->vm_acl = NO_ACL;
128 }
129 }
130