147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Class and permission mappings. 347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <errno.h> 647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdio.h> 747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdlib.h> 847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdarg.h> 947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <assert.h> 1047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <selinux/selinux.h> 1147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <selinux/avc.h> 1247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "mapping.h" 1347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 1447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 1547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Class and permission mappings 1647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 1747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 1847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstruct selinux_mapping { 1947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner security_class_t value; /* real, kernel value */ 2047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned num_perms; 2147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner access_vector_t perms[sizeof(access_vector_t) * 8]; 2247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}; 2347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 2447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic struct selinux_mapping *current_mapping = NULL; 2547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic security_class_t current_mapping_size = 0; 2647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 2747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 2847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Mapping setting function 2947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 3047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 3147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerint 3247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerselinux_set_mapping(struct security_class_mapping *map) 3347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 3447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t size = sizeof(struct selinux_mapping); 3547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner security_class_t i, j; 3647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned k; 3747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 3847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(current_mapping); 3947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner current_mapping = NULL; 4047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner current_mapping_size = 0; 4147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 4247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (avc_reset() < 0) 4347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto err; 4447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 4547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Find number of classes in the input mapping */ 4647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!map) { 4747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = EINVAL; 4847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto err; 4947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 5047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner i = 0; 5147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (map[i].name) 5247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner i++; 5347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 5447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Allocate space for the class records, plus one for class zero */ 5547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner current_mapping = (struct selinux_mapping *)calloc(++i, size); 5647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!current_mapping) 5747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto err; 5847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 5947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Store the raw class and permission values */ 6047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner j = 0; 6147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (map[j].name) { 6247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct security_class_mapping *p_in = map + (j++); 6347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct selinux_mapping *p_out = current_mapping + j; 6447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 6547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner p_out->value = string_to_security_class(p_in->name); 6647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!p_out->value) 6747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto err2; 6847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 6947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner k = 0; 7047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (p_in->perms && p_in->perms[k]) { 7147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* An empty permission string skips ahead */ 7247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!*p_in->perms[k]) { 7347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner k++; 7447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner continue; 7547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 7647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner p_out->perms[k] = string_to_av_perm(p_out->value, 7747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner p_in->perms[k]); 7847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!p_out->perms[k]) 7947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto err2; 8047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner k++; 8147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 8247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner p_out->num_perms = k; 8347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 8447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 8547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Set the mapping size here so the above lookups are "raw" */ 8647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner current_mapping_size = i; 8747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 8847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnererr2: 8947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(current_mapping); 9047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner current_mapping = NULL; 9147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner current_mapping_size = 0; 9247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnererr: 9347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 9447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 9547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 9647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 9747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Get real, kernel values from mapped values 9847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 9947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 10047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnersecurity_class_t 10147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerunmap_class(security_class_t tclass) 10247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 10347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (tclass < current_mapping_size) 10447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return current_mapping[tclass].value; 10547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 10647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(current_mapping_size == 0); 10747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return tclass; 10847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 10947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 11047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turneraccess_vector_t 11147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerunmap_perm(security_class_t tclass, access_vector_t tperm) 11247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 11347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (tclass < current_mapping_size) { 11447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned i; 11547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner access_vector_t kperm = 0; 11647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 11747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0; i<current_mapping[tclass].num_perms; i++) 11847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (tperm & (1<<i)) { 11947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(current_mapping[tclass].perms[i]); 12047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner kperm |= current_mapping[tclass].perms[i]; 12147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner tperm &= ~(1<<i); 12247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 12347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(tperm == 0); 12447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return kperm; 12547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 12647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 12747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(current_mapping_size == 0); 12847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return tperm; 12947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 13047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 13147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 13247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Get mapped values from real, kernel values 13347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 13447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 13547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnersecurity_class_t 13647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnermap_class(security_class_t kclass) 13747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 13847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner security_class_t i; 13947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 14047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0; i<current_mapping_size; i++) 14147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (current_mapping[i].value == kclass) 14247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return i; 14347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 14447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(current_mapping_size == 0); 14547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return kclass; 14647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 14747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 14847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turneraccess_vector_t 14947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnermap_perm(security_class_t tclass, access_vector_t kperm) 15047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 15147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (tclass < current_mapping_size) { 15247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned i; 15347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner access_vector_t tperm = 0; 15447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 15547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0; i<current_mapping[tclass].num_perms; i++) 15647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (kperm & current_mapping[tclass].perms[i]) { 15747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner tperm |= 1<<i; 15847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner kperm &= ~current_mapping[tclass].perms[i]; 15947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 16047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(kperm == 0); 16147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return tperm; 16247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 16347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 16447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner assert(current_mapping_size == 0); 16547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return kperm; 16647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 16747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 16847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnervoid 16947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnermap_decision(security_class_t tclass, struct av_decision *avd) 17047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 17147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (tclass < current_mapping_size) { 17247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned i; 17347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner access_vector_t result; 17447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 17547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 17647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (avd->allowed & current_mapping[tclass].perms[i]) 17747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner result |= 1<<i; 17847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner avd->allowed = result; 17947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 18047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 18147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (avd->decided & current_mapping[tclass].perms[i]) 18247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner result |= 1<<i; 18347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner avd->decided = result; 18447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 18547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 18647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (avd->auditallow & current_mapping[tclass].perms[i]) 18747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner result |= 1<<i; 18847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner avd->auditallow = result; 18947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) 19147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (avd->auditdeny & current_mapping[tclass].perms[i]) 19247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner result |= 1<<i; 19347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner avd->auditdeny = result; 19447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 19547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 196