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 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 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 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 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