xref: /minix3/minix/servers/vm/acl.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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