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