1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Class and permission mappings. 3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <errno.h> 6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdio.h> 7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdlib.h> 8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdarg.h> 9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <assert.h> 10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/selinux.h> 11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/avc.h> 12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "mapping.h" 13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Class and permission mappings 16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 18f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct selinux_mapping { 19f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t value; /* real, kernel value */ 20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned num_perms; 21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms[sizeof(access_vector_t) * 8]; 22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 24f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct selinux_mapping *current_mapping = NULL; 25f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic security_class_t current_mapping_size = 0; 26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Mapping setting function 29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 30f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 31f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint 32f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyselinux_set_mapping(struct security_class_mapping *map) 33f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley size_t size = sizeof(struct selinux_mapping); 35f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t i, j; 36f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned k; 37f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 38f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(current_mapping); 39f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping = NULL; 40f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping_size = 0; 41f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_reset() < 0) 43f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 44f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 45f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Find number of classes in the input mapping */ 46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!map) { 47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = EINVAL; 48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley i = 0; 51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (map[i].name) 52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley i++; 53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Allocate space for the class records, plus one for class zero */ 55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping = (struct selinux_mapping *)calloc(++i, size); 56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!current_mapping) 57f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Store the raw class and permission values */ 60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley j = 0; 61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (map[j].name) { 62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct security_class_mapping *p_in = map + (j++); 63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct selinux_mapping *p_out = current_mapping + j; 64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_out->value = string_to_security_class(p_in->name); 66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!p_out->value) 67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err2; 68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 69f074036424618c130dacb3464465a8b40bffef5Stephen Smalley k = 0; 70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (p_in->perms && p_in->perms[k]) { 71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* An empty permission string skips ahead */ 72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!*p_in->perms[k]) { 73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley k++; 74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_out->perms[k] = string_to_av_perm(p_out->value, 77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_in->perms[k]); 78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!p_out->perms[k]) 79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err2; 80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley k++; 81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_out->num_perms = k; 83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Set the mapping size here so the above lookups are "raw" */ 86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping_size = i; 87f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 88f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr2: 89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(current_mapping); 90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping = NULL; 91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping_size = 0; 92f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr: 93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Get real, kernel values from mapped values 98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 99f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 100f074036424618c130dacb3464465a8b40bffef5Stephen Smalleysecurity_class_t 101f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyunmap_class(security_class_t tclass) 102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) 104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return current_mapping[tclass].value; 105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(current_mapping_size == 0); 107f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return tclass; 108f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 109f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 110f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyaccess_vector_t 111f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyunmap_perm(security_class_t tclass, access_vector_t tperm) 112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) { 114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned i; 115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t kperm = 0; 116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0; i<current_mapping[tclass].num_perms; i++) 118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tperm & (1<<i)) { 119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(current_mapping[tclass].perms[i]); 120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley kperm |= current_mapping[tclass].perms[i]; 121f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tperm &= ~(1<<i); 122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(tperm == 0); 124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return kperm; 125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(current_mapping_size == 0); 128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return tperm; 129f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Get mapped values from real, kernel values 133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 135f074036424618c130dacb3464465a8b40bffef5Stephen Smalleysecurity_class_t 136f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_class(security_class_t kclass) 137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t i; 139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0; i<current_mapping_size; i++) 141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (current_mapping[i].value == kclass) 142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return i; 143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(current_mapping_size == 0); 145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return kclass; 146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 148f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyaccess_vector_t 149f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_perm(security_class_t tclass, access_vector_t kperm) 150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) { 152f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned i; 153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t tperm = 0; 154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0; i<current_mapping[tclass].num_perms; i++) 156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (kperm & current_mapping[tclass].perms[i]) { 157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tperm |= 1<<i; 158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley kperm &= ~current_mapping[tclass].perms[i]; 159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(kperm == 0); 161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return tperm; 162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley assert(current_mapping_size == 0); 165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return kperm; 166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 168f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid 169f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_decision(security_class_t tclass, struct av_decision *avd) 170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) { 172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned i; 173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t result; 174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->allowed & current_mapping[tclass].perms[i]) 177f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->allowed = result; 179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->decided & current_mapping[tclass].perms[i]) 182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->decided = result; 184f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->auditallow & current_mapping[tclass].perms[i]) 187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->auditallow = result; 189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->auditdeny & current_mapping[tclass].perms[i]) 192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->auditdeny = result; 194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 196