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 <selinux/selinux.h> 10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <selinux/avc.h> 11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "mapping.h" 12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Class and permission mappings 15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 17f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct selinux_mapping { 18f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t value; /* real, kernel value */ 19f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned num_perms; 20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t perms[sizeof(access_vector_t) * 8]; 21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 23f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic struct selinux_mapping *current_mapping = NULL; 24f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic security_class_t current_mapping_size = 0; 25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Mapping setting function 28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 30f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint 31f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyselinux_set_mapping(struct security_class_mapping *map) 32f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 33f074036424618c130dacb3464465a8b40bffef5Stephen Smalley size_t size = sizeof(struct selinux_mapping); 34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t i, j; 35f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned k; 36f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 37f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(current_mapping); 38f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping = NULL; 39f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping_size = 0; 40f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 41f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avc_reset() < 0) 42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 43f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 44f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Find number of classes in the input mapping */ 45f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!map) { 46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = EINVAL; 47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley i = 0; 50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (map[i].name) 51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley i++; 52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Allocate space for the class records, plus one for class zero */ 54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping = (struct selinux_mapping *)calloc(++i, size); 55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!current_mapping) 56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err; 57f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Store the raw class and permission values */ 59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley j = 0; 60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (map[j].name) { 61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct security_class_mapping *p_in = map + (j++); 62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct selinux_mapping *p_out = current_mapping + j; 63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_out->value = string_to_security_class(p_in->name); 65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!p_out->value) 66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err2; 67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley k = 0; 69c01e95f737527e068edcacb1179affca9f62a52dEric Paris while (p_in->perms[k]) { 70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* An empty permission string skips ahead */ 71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!*p_in->perms[k]) { 72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley k++; 73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_out->perms[k] = string_to_av_perm(p_out->value, 76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_in->perms[k]); 77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!p_out->perms[k]) 78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto err2; 79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley k++; 80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley p_out->num_perms = k; 82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Set the mapping size here so the above lookups are "raw" */ 85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping_size = i; 86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 87f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr2: 88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(current_mapping); 89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping = NULL; 90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley current_mapping_size = 0; 91f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyerr: 92f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Get real, kernel values from mapped values 97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 99f074036424618c130dacb3464465a8b40bffef5Stephen Smalleysecurity_class_t 100f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyunmap_class(security_class_t tclass) 101f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) 103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return current_mapping[tclass].value; 104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 105574290e4d18567218176b3b839895b2500f7e128Richard Haines /* If here no mapping set or the class requested is not valid. */ 106574290e4d18567218176b3b839895b2500f7e128Richard Haines if (current_mapping_size != 0) { 107574290e4d18567218176b3b839895b2500f7e128Richard Haines errno = EINVAL; 108574290e4d18567218176b3b839895b2500f7e128Richard Haines return 0; 109574290e4d18567218176b3b839895b2500f7e128Richard Haines } 110574290e4d18567218176b3b839895b2500f7e128Richard Haines else 111574290e4d18567218176b3b839895b2500f7e128Richard Haines return tclass; 112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 114f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyaccess_vector_t 115f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyunmap_perm(security_class_t tclass, access_vector_t tperm) 116f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) { 118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned i; 119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t kperm = 0; 120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 121f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0; i<current_mapping[tclass].num_perms; i++) 122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tperm & (1<<i)) { 123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley kperm |= current_mapping[tclass].perms[i]; 124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tperm &= ~(1<<i); 125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return kperm; 127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 129574290e4d18567218176b3b839895b2500f7e128Richard Haines /* If here no mapping set or the perm requested is not valid. */ 130574290e4d18567218176b3b839895b2500f7e128Richard Haines if (current_mapping_size != 0) { 131574290e4d18567218176b3b839895b2500f7e128Richard Haines errno = EINVAL; 132574290e4d18567218176b3b839895b2500f7e128Richard Haines return 0; 133574290e4d18567218176b3b839895b2500f7e128Richard Haines } 134574290e4d18567218176b3b839895b2500f7e128Richard Haines else 135574290e4d18567218176b3b839895b2500f7e128Richard Haines return tperm; 136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Get mapped values from real, kernel values 140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 142f074036424618c130dacb3464465a8b40bffef5Stephen Smalleysecurity_class_t 143f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_class(security_class_t kclass) 144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley security_class_t i; 146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0; i<current_mapping_size; i++) 148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (current_mapping[i].value == kclass) 149f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return i; 150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 151574290e4d18567218176b3b839895b2500f7e128Richard Haines/* If here no mapping set or the class requested is not valid. */ 152574290e4d18567218176b3b839895b2500f7e128Richard Haines if (current_mapping_size != 0) { 153574290e4d18567218176b3b839895b2500f7e128Richard Haines errno = EINVAL; 154574290e4d18567218176b3b839895b2500f7e128Richard Haines return 0; 155574290e4d18567218176b3b839895b2500f7e128Richard Haines } 156574290e4d18567218176b3b839895b2500f7e128Richard Haines else 157574290e4d18567218176b3b839895b2500f7e128Richard Haines return kclass; 158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 160f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyaccess_vector_t 161f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_perm(security_class_t tclass, access_vector_t kperm) 162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) { 164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned i; 165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t tperm = 0; 166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0; i<current_mapping[tclass].num_perms; i++) 168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (kperm & current_mapping[tclass].perms[i]) { 169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley tperm |= 1<<i; 170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley kperm &= ~current_mapping[tclass].perms[i]; 171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 173574290e4d18567218176b3b839895b2500f7e128Richard Haines if (tperm == 0) { 174574290e4d18567218176b3b839895b2500f7e128Richard Haines errno = EINVAL; 175574290e4d18567218176b3b839895b2500f7e128Richard Haines return 0; 176574290e4d18567218176b3b839895b2500f7e128Richard Haines } 177574290e4d18567218176b3b839895b2500f7e128Richard Haines else 178574290e4d18567218176b3b839895b2500f7e128Richard Haines return tperm; 179574290e4d18567218176b3b839895b2500f7e128Richard Haines } 180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return kperm; 181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 183f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid 184f074036424618c130dacb3464465a8b40bffef5Stephen Smalleymap_decision(security_class_t tclass, struct av_decision *avd) 185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (tclass < current_mapping_size) { 187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned i; 188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley access_vector_t result; 189f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->allowed & current_mapping[tclass].perms[i]) 192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->allowed = result; 194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->decided & current_mapping[tclass].perms[i]) 197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->decided = result; 199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->auditallow & current_mapping[tclass].perms[i]) 202f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->auditallow = result; 204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (avd->auditdeny & current_mapping[tclass].perms[i]) 207f074036424618c130dacb3464465a8b40bffef5Stephen Smalley result |= 1<<i; 208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley avd->auditdeny = result; 209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 211