1433d6423SLionel Sambuc
2433d6423SLionel Sambuc /* Call mask ACL management. */
3433d6423SLionel Sambuc
4433d6423SLionel Sambuc #include <minix/drivers.h>
5433d6423SLionel Sambuc
6433d6423SLionel Sambuc #include "proto.h"
7433d6423SLionel Sambuc #include "glo.h"
8433d6423SLionel Sambuc #include "util.h"
9433d6423SLionel Sambuc
10433d6423SLionel Sambuc #define NO_ACL -1
11433d6423SLionel Sambuc #define USER_ACL 0
12433d6423SLionel Sambuc #define FIRST_SYS_ACL 1
13433d6423SLionel Sambuc
14433d6423SLionel Sambuc static bitchunk_t acl_mask[NR_SYS_PROCS][VM_CALL_MASK_SIZE];
15433d6423SLionel Sambuc static bitchunk_t acl_inuse[BITMAP_CHUNKS(NR_SYS_PROCS)];
16433d6423SLionel Sambuc
17433d6423SLionel Sambuc /*
18433d6423SLionel Sambuc * Initialize ACL data structures.
19433d6423SLionel Sambuc */
20433d6423SLionel Sambuc void
acl_init(void)21433d6423SLionel Sambuc acl_init(void)
22433d6423SLionel Sambuc {
23433d6423SLionel Sambuc int i;
24433d6423SLionel Sambuc
25433d6423SLionel Sambuc for (i = 0; i < ELEMENTS(vmproc); i++)
26433d6423SLionel Sambuc vmproc[i].vm_acl = NO_ACL;
27433d6423SLionel Sambuc
28433d6423SLionel Sambuc memset(acl_mask, 0, sizeof(acl_mask));
29433d6423SLionel Sambuc memset(acl_inuse, 0, sizeof(acl_inuse));
30433d6423SLionel Sambuc }
31433d6423SLionel Sambuc
32433d6423SLionel Sambuc /*
33433d6423SLionel Sambuc * Check whether a process is allowed to make a certain (zero-based) call.
34433d6423SLionel Sambuc * Return OK or an error.
35433d6423SLionel Sambuc */
36433d6423SLionel Sambuc int
acl_check(struct vmproc * vmp,int call)37433d6423SLionel Sambuc acl_check(struct vmproc *vmp, int call)
38433d6423SLionel Sambuc {
3965b4b952SCristiano Giuffrida
4065b4b952SCristiano Giuffrida /* VM makes asynchronous calls to itself. Always allow those. */
4165b4b952SCristiano Giuffrida if (vmp->vm_endpoint == VM_PROC_NR)
4265b4b952SCristiano Giuffrida return OK;
4365b4b952SCristiano Giuffrida
44433d6423SLionel Sambuc /* If the process has no ACL, all calls are allowed.. for now. */
45433d6423SLionel Sambuc if (vmp->vm_acl == NO_ACL) {
46*fbbf2570SDavid van Moolenbroek /* RS instrumented with ASR may call VM_BRK at startup. */
47*fbbf2570SDavid van Moolenbroek if (vmp->vm_endpoint == RS_PROC_NR)
48*fbbf2570SDavid van Moolenbroek return OK;
49*fbbf2570SDavid van Moolenbroek
50433d6423SLionel Sambuc printf("VM: calling process %u has no ACL!\n",
51433d6423SLionel Sambuc vmp->vm_endpoint);
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc return OK;
54433d6423SLionel Sambuc }
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc /* See if the call is allowed. */
57433d6423SLionel Sambuc if (!GET_BIT(acl_mask[vmp->vm_acl], call))
58433d6423SLionel Sambuc return EPERM;
59433d6423SLionel Sambuc
60433d6423SLionel Sambuc return OK;
61433d6423SLionel Sambuc }
62433d6423SLionel Sambuc
63433d6423SLionel Sambuc /*
64433d6423SLionel Sambuc * Assign a call mask to a process. User processes share the first ACL entry.
65433d6423SLionel Sambuc * System processes are assigned to any of the other slots. For user
66433d6423SLionel Sambuc * processes, no call mask need to be provided: it will simply be inherited in
67433d6423SLionel Sambuc * that case.
68433d6423SLionel Sambuc */
69433d6423SLionel Sambuc void
acl_set(struct vmproc * vmp,bitchunk_t * mask,int sys_proc)70433d6423SLionel Sambuc acl_set(struct vmproc *vmp, bitchunk_t *mask, int sys_proc)
71433d6423SLionel Sambuc {
72433d6423SLionel Sambuc int i;
73433d6423SLionel Sambuc
74433d6423SLionel Sambuc acl_clear(vmp);
75433d6423SLionel Sambuc
76433d6423SLionel Sambuc if (sys_proc) {
77433d6423SLionel Sambuc for (i = FIRST_SYS_ACL; i < NR_SYS_PROCS; i++)
78433d6423SLionel Sambuc if (!GET_BIT(acl_inuse, i))
79433d6423SLionel Sambuc break;
80433d6423SLionel Sambuc
81433d6423SLionel Sambuc /*
82433d6423SLionel Sambuc * This should never happen. If it does, then different user
83433d6423SLionel Sambuc * processes have been assigned call masks separately. It is
84433d6423SLionel Sambuc * RS's responsibility to prevent that.
85433d6423SLionel Sambuc */
86433d6423SLionel Sambuc if (i == NR_SYS_PROCS) {
87433d6423SLionel Sambuc printf("VM: no ACL entries available!\n");
88433d6423SLionel Sambuc return;
89433d6423SLionel Sambuc }
90433d6423SLionel Sambuc } else
91433d6423SLionel Sambuc i = USER_ACL;
92433d6423SLionel Sambuc
93433d6423SLionel Sambuc if (!GET_BIT(acl_inuse, i) && mask == NULL)
94433d6423SLionel Sambuc printf("VM: WARNING: inheriting uninitialized ACL mask\n");
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc SET_BIT(acl_inuse, i);
97433d6423SLionel Sambuc vmp->vm_acl = i;
98433d6423SLionel Sambuc
99433d6423SLionel Sambuc if (mask != NULL)
100433d6423SLionel Sambuc memcpy(&acl_mask[vmp->vm_acl], mask, sizeof(acl_mask[0]));
101433d6423SLionel Sambuc }
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc /*
104433d6423SLionel Sambuc * A process has forked. User processes inherit their parent's ACL by default,
105433d6423SLionel Sambuc * although they may be turned into system processes later. System processes
106433d6423SLionel Sambuc * do not inherit an ACL, and will have to be assigned one before getting to
107433d6423SLionel Sambuc * run.
108433d6423SLionel Sambuc */
109433d6423SLionel Sambuc void
acl_fork(struct vmproc * vmp)110433d6423SLionel Sambuc acl_fork(struct vmproc *vmp)
111433d6423SLionel Sambuc {
112433d6423SLionel Sambuc if (vmp->vm_acl != USER_ACL)
113433d6423SLionel Sambuc vmp->vm_acl = NO_ACL;
114433d6423SLionel Sambuc }
115433d6423SLionel Sambuc
116433d6423SLionel Sambuc /*
117433d6423SLionel Sambuc * A process has exited. Decrease the reference count on its ACL entry, and
118433d6423SLionel Sambuc * mark the process as having no ACL.
119433d6423SLionel Sambuc */
120433d6423SLionel Sambuc void
acl_clear(struct vmproc * vmp)121433d6423SLionel Sambuc acl_clear(struct vmproc *vmp)
122433d6423SLionel Sambuc {
123433d6423SLionel Sambuc if (vmp->vm_acl != NO_ACL) {
124433d6423SLionel Sambuc if (vmp->vm_acl != USER_ACL)
125433d6423SLionel Sambuc UNSET_BIT(acl_inuse, vmp->vm_acl);
126433d6423SLionel Sambuc
127433d6423SLionel Sambuc vmp->vm_acl = NO_ACL;
128433d6423SLionel Sambuc }
129433d6423SLionel Sambuc }
130