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