diff options
author | Joshua Brindle <method@manicmethod.com> | 2008-08-19 15:30:36 -0400 |
---|---|---|
committer | Joshua Brindle <method@manicmethod.com> | 2008-08-19 15:30:36 -0400 |
commit | 13cd4c8960688af11ad23b4c946149015c80d549 (patch) | |
tree | 61e928c962bcf6981ef4dc02dfb0b46d1c16b818 /libselinux/src/mapping.c | |
download | android_external_selinux-13cd4c8960688af11ad23b4c946149015c80d549.tar.gz android_external_selinux-13cd4c8960688af11ad23b4c946149015c80d549.tar.bz2 android_external_selinux-13cd4c8960688af11ad23b4c946149015c80d549.zip |
initial import from svn trunk revision 2950
Diffstat (limited to 'libselinux/src/mapping.c')
-rw-r--r-- | libselinux/src/mapping.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/libselinux/src/mapping.c b/libselinux/src/mapping.c new file mode 100644 index 00000000..f9858ce1 --- /dev/null +++ b/libselinux/src/mapping.c @@ -0,0 +1,195 @@ +/* + * Class and permission mappings. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <assert.h> +#include <selinux/selinux.h> +#include <selinux/avc.h> +#include "mapping.h" + +/* + * Class and permission mappings + */ + +struct selinux_mapping { + security_class_t value; /* real, kernel value */ + unsigned num_perms; + access_vector_t perms[sizeof(access_vector_t) * 8]; +}; + +static struct selinux_mapping *current_mapping = NULL; +static security_class_t current_mapping_size = 0; + +/* + * Mapping setting function + */ + +int +selinux_set_mapping(struct security_class_mapping *map) +{ + size_t size = sizeof(struct selinux_mapping); + security_class_t i, j; + unsigned k; + + free(current_mapping); + current_mapping = NULL; + current_mapping_size = 0; + + if (avc_reset() < 0) + goto err; + + /* Find number of classes in the input mapping */ + if (!map) { + errno = EINVAL; + goto err; + } + i = 0; + while (map[i].name) + i++; + + /* Allocate space for the class records, plus one for class zero */ + current_mapping = (struct selinux_mapping *)calloc(++i, size); + if (!current_mapping) + goto err; + + /* Store the raw class and permission values */ + j = 0; + while (map[j].name) { + struct security_class_mapping *p_in = map + (j++); + struct selinux_mapping *p_out = current_mapping + j; + + p_out->value = string_to_security_class(p_in->name); + if (!p_out->value) + goto err2; + + k = 0; + while (p_in->perms && p_in->perms[k]) { + /* An empty permission string skips ahead */ + if (!*p_in->perms[k]) { + k++; + continue; + } + p_out->perms[k] = string_to_av_perm(p_out->value, + p_in->perms[k]); + if (!p_out->perms[k]) + goto err2; + k++; + } + p_out->num_perms = k; + } + + /* Set the mapping size here so the above lookups are "raw" */ + current_mapping_size = i; + return 0; +err2: + free(current_mapping); + current_mapping = NULL; + current_mapping_size = 0; +err: + return -1; +} + +/* + * Get real, kernel values from mapped values + */ + +security_class_t +unmap_class(security_class_t tclass) +{ + if (tclass < current_mapping_size) + return current_mapping[tclass].value; + + assert(current_mapping_size == 0); + return tclass; +} + +access_vector_t +unmap_perm(security_class_t tclass, access_vector_t tperm) +{ + if (tclass < current_mapping_size) { + unsigned i; + access_vector_t kperm = 0; + + for (i=0; i<current_mapping[tclass].num_perms; i++) + if (tperm & (1<<i)) { + assert(current_mapping[tclass].perms[i]); + kperm |= current_mapping[tclass].perms[i]; + tperm &= ~(1<<i); + } + assert(tperm == 0); + return kperm; + } + + assert(current_mapping_size == 0); + return tperm; +} + +/* + * Get mapped values from real, kernel values + */ + +security_class_t +map_class(security_class_t kclass) +{ + security_class_t i; + + for (i=0; i<current_mapping_size; i++) + if (current_mapping[i].value == kclass) + return i; + + assert(current_mapping_size == 0); + return kclass; +} + +access_vector_t +map_perm(security_class_t tclass, access_vector_t kperm) +{ + if (tclass < current_mapping_size) { + unsigned i; + access_vector_t tperm = 0; + + for (i=0; i<current_mapping[tclass].num_perms; i++) + if (kperm & current_mapping[tclass].perms[i]) { + tperm |= 1<<i; + kperm &= ~current_mapping[tclass].perms[i]; + } + assert(kperm == 0); + return tperm; + } + + assert(current_mapping_size == 0); + return kperm; +} + +void +map_decision(security_class_t tclass, struct av_decision *avd) +{ + if (tclass < current_mapping_size) { + unsigned i; + access_vector_t result; + + for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) + if (avd->allowed & current_mapping[tclass].perms[i]) + result |= 1<<i; + avd->allowed = result; + + for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) + if (avd->decided & current_mapping[tclass].perms[i]) + result |= 1<<i; + avd->decided = result; + + for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) + if (avd->auditallow & current_mapping[tclass].perms[i]) + result |= 1<<i; + avd->auditallow = result; + + for (i=0, result=0; i<current_mapping[tclass].num_perms; i++) + if (avd->auditdeny & current_mapping[tclass].perms[i]) + result |= 1<<i; + avd->auditdeny = result; + } +} |