xref: /minix/minix/servers/vm/acl.c (revision 83133719)
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
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
37 acl_check(struct vmproc *vmp, int call)
38 {
39 	/* If the process has no ACL, all calls are allowed.. for now. */
40 	if (vmp->vm_acl == NO_ACL) {
41 		printf("VM: calling process %u has no ACL!\n",
42 		    vmp->vm_endpoint);
43 
44 		return OK;
45 	}
46 
47 	/* See if the call is allowed. */
48 	if (!GET_BIT(acl_mask[vmp->vm_acl], call))
49 		return EPERM;
50 
51 	return OK;
52 }
53 
54 /*
55  * Assign a call mask to a process.  User processes share the first ACL entry.
56  * System processes are assigned to any of the other slots.  For user
57  * processes, no call mask need to be provided: it will simply be inherited in
58  * that case.
59  */
60 void
61 acl_set(struct vmproc *vmp, bitchunk_t *mask, int sys_proc)
62 {
63 	int i;
64 
65 	acl_clear(vmp);
66 
67 	if (sys_proc) {
68 		for (i = FIRST_SYS_ACL; i < NR_SYS_PROCS; i++)
69 			if (!GET_BIT(acl_inuse, i))
70 				break;
71 
72 		/*
73 		 * This should never happen.  If it does, then different user
74 		 * processes have been assigned call masks separately.  It is
75 		 * RS's responsibility to prevent that.
76 		 */
77 		if (i == NR_SYS_PROCS) {
78 			printf("VM: no ACL entries available!\n");
79 			return;
80 		}
81 	} else
82 		i = USER_ACL;
83 
84 	if (!GET_BIT(acl_inuse, i) && mask == NULL)
85 		printf("VM: WARNING: inheriting uninitialized ACL mask\n");
86 
87 	SET_BIT(acl_inuse, i);
88 	vmp->vm_acl = i;
89 
90 	if (mask != NULL)
91 		memcpy(&acl_mask[vmp->vm_acl], mask, sizeof(acl_mask[0]));
92 }
93 
94 /*
95  * A process has forked.  User processes inherit their parent's ACL by default,
96  * although they may be turned into system processes later.  System processes
97  * do not inherit an ACL, and will have to be assigned one before getting to
98  * run.
99  */
100 void
101 acl_fork(struct vmproc *vmp)
102 {
103 	if (vmp->vm_acl != USER_ACL)
104 		vmp->vm_acl = NO_ACL;
105 }
106 
107 /*
108  * A process has exited.  Decrease the reference count on its ACL entry, and
109  * mark the process as having no ACL.
110  */
111 void
112 acl_clear(struct vmproc *vmp)
113 {
114 	if (vmp->vm_acl != NO_ACL) {
115 		if (vmp->vm_acl != USER_ACL)
116 			UNSET_BIT(acl_inuse, vmp->vm_acl);
117 
118 		vmp->vm_acl = NO_ACL;
119 	}
120 }
121