Blame src/mapping.c

Packit 3feee0
/*
Packit 3feee0
 * Class and permission mappings.
Packit 3feee0
 */
Packit 3feee0
Packit 3feee0
#include <errno.h>
Packit 3feee0
#include <stdio.h>
Packit 3feee0
#include <stdlib.h>
Packit 3feee0
#include <stdarg.h>
Packit 3feee0
#include <stdbool.h>
Packit 3feee0
#include <selinux/selinux.h>
Packit 3feee0
#include <selinux/avc.h>
Packit 3feee0
#include "callbacks.h"
Packit 3feee0
#include "mapping.h"
Packit 3feee0
#include "selinux_internal.h"
Packit 3feee0
Packit 3feee0
/*
Packit 3feee0
 * Class and permission mappings
Packit 3feee0
 */
Packit 3feee0
Packit 3feee0
struct selinux_mapping {
Packit 3feee0
	security_class_t value; /* real, kernel value */
Packit 3feee0
	unsigned num_perms;
Packit 3feee0
	access_vector_t perms[sizeof(access_vector_t) * 8];
Packit 3feee0
};
Packit 3feee0
Packit 3feee0
static struct selinux_mapping *current_mapping = NULL;
Packit 3feee0
static security_class_t current_mapping_size = 0;
Packit 3feee0
Packit 3feee0
/*
Packit 3feee0
 * Mapping setting function
Packit 3feee0
 */
Packit 3feee0
Packit 3feee0
int
Packit 3feee0
selinux_set_mapping(struct security_class_mapping *map)
Packit 3feee0
{
Packit 3feee0
	size_t size = sizeof(struct selinux_mapping);
Packit 3feee0
	security_class_t i, j;
Packit 3feee0
	unsigned k;
Packit 3feee0
	bool print_unknown_handle = false;
Packit 3feee0
	bool reject = (security_reject_unknown() == 1);
Packit 3feee0
	bool deny = (security_deny_unknown() == 1);
Packit 3feee0
Packit 3feee0
	free(current_mapping);
Packit 3feee0
	current_mapping = NULL;
Packit 3feee0
	current_mapping_size = 0;
Packit 3feee0
Packit 3feee0
	if (avc_reset() < 0)
Packit 3feee0
		goto err;
Packit 3feee0
Packit 3feee0
	/* Find number of classes in the input mapping */
Packit 3feee0
	if (!map) {
Packit 3feee0
		errno = EINVAL;
Packit 3feee0
		goto err;
Packit 3feee0
	}
Packit 3feee0
	i = 0;
Packit 3feee0
	while (map[i].name)
Packit 3feee0
		i++;
Packit 3feee0
Packit 3feee0
	/* Allocate space for the class records, plus one for class zero */
Packit 3feee0
	current_mapping = (struct selinux_mapping *)calloc(++i, size);
Packit 3feee0
	if (!current_mapping)
Packit 3feee0
		goto err;
Packit 3feee0
Packit 3feee0
	/* Store the raw class and permission values */
Packit 3feee0
	j = 0;
Packit 3feee0
	while (map[j].name) {
Packit 3feee0
		struct security_class_mapping *p_in = map + (j++);
Packit 3feee0
		struct selinux_mapping *p_out = current_mapping + j;
Packit 3feee0
Packit 3feee0
		p_out->value = string_to_security_class(p_in->name);
Packit 3feee0
		if (!p_out->value) {
Packit 3feee0
			selinux_log(SELINUX_INFO,
Packit 3feee0
				    "SELinux: Class %s not defined in policy.\n",
Packit 3feee0
				    p_in->name);
Packit 3feee0
			if (reject)
Packit 3feee0
				goto err2;
Packit 3feee0
			p_out->num_perms = 0;
Packit 3feee0
			print_unknown_handle = true;
Packit 3feee0
			continue;
Packit 3feee0
		}
Packit 3feee0
Packit 3feee0
		k = 0;
Packit 3feee0
		while (p_in->perms[k]) {
Packit 3feee0
			/* An empty permission string skips ahead */
Packit 3feee0
			if (!*p_in->perms[k]) {
Packit 3feee0
				k++;
Packit 3feee0
				continue;
Packit 3feee0
			}
Packit 3feee0
			p_out->perms[k] = string_to_av_perm(p_out->value,
Packit 3feee0
							    p_in->perms[k]);
Packit 3feee0
			if (!p_out->perms[k]) {
Packit 3feee0
				selinux_log(SELINUX_INFO,
Packit 3feee0
					    "SELinux:  Permission %s in class %s not defined in policy.\n",
Packit 3feee0
					    p_in->perms[k], p_in->name);
Packit 3feee0
				if (reject)
Packit 3feee0
					goto err2;
Packit 3feee0
				print_unknown_handle = true;
Packit 3feee0
			}
Packit 3feee0
			k++;
Packit 3feee0
		}
Packit 3feee0
		p_out->num_perms = k;
Packit 3feee0
	}
Packit 3feee0
Packit 3feee0
	if (print_unknown_handle)
Packit 3feee0
		selinux_log(SELINUX_INFO,
Packit 3feee0
			    "SELinux: the above unknown classes and permissions will be %s\n",
Packit 3feee0
			    deny ? "denied" : "allowed");
Packit 3feee0
Packit 3feee0
	/* Set the mapping size here so the above lookups are "raw" */
Packit 3feee0
	current_mapping_size = i;
Packit 3feee0
	return 0;
Packit 3feee0
err2:
Packit 3feee0
	free(current_mapping);
Packit 3feee0
	current_mapping = NULL;
Packit 3feee0
	current_mapping_size = 0;
Packit 3feee0
err:
Packit 3feee0
	return -1;
Packit 3feee0
}
Packit 3feee0
Packit 3feee0
/*
Packit 3feee0
 * Get real, kernel values from mapped values
Packit 3feee0
 */
Packit 3feee0
Packit 3feee0
security_class_t
Packit 3feee0
unmap_class(security_class_t tclass)
Packit 3feee0
{
Packit 3feee0
	if (tclass < current_mapping_size)
Packit 3feee0
		return current_mapping[tclass].value;
Packit 3feee0
Packit 3feee0
	/* If here no mapping set or the class requested is not valid. */
Packit 3feee0
	if (current_mapping_size != 0) {
Packit 3feee0
		errno = EINVAL;
Packit 3feee0
		return 0;
Packit 3feee0
	}
Packit 3feee0
	else
Packit 3feee0
		return tclass;
Packit 3feee0
}
Packit 3feee0
Packit 3feee0
access_vector_t
Packit 3feee0
unmap_perm(security_class_t tclass, access_vector_t tperm)
Packit 3feee0
{
Packit 3feee0
	if (tclass < current_mapping_size) {
Packit 3feee0
		unsigned i;
Packit 3feee0
		access_vector_t kperm = 0;
Packit 3feee0
Packit 3feee0
		for (i=0; i
Packit 3feee0
			if (tperm & (1<
Packit 3feee0
				kperm |= current_mapping[tclass].perms[i];
Packit 3feee0
				tperm &= ~(1<
Packit 3feee0
			}
Packit 3feee0
		return kperm;
Packit 3feee0
	}
Packit 3feee0
Packit 3feee0
	/* If here no mapping set or the perm requested is not valid. */
Packit 3feee0
	if (current_mapping_size != 0) {
Packit 3feee0
		errno = EINVAL;
Packit 3feee0
		return 0;
Packit 3feee0
	}
Packit 3feee0
	else
Packit 3feee0
		return tperm;
Packit 3feee0
}
Packit 3feee0
Packit 3feee0
/*
Packit 3feee0
 * Get mapped values from real, kernel values
Packit 3feee0
 */
Packit 3feee0
Packit 3feee0
security_class_t
Packit 3feee0
map_class(security_class_t kclass)
Packit 3feee0
{
Packit 3feee0
	security_class_t i;
Packit 3feee0
Packit 3feee0
	for (i=0; i
Packit 3feee0
		if (current_mapping[i].value == kclass)
Packit 3feee0
			return i;
Packit 3feee0
Packit 3feee0
/* If here no mapping set or the class requested is not valid. */
Packit 3feee0
	if (current_mapping_size != 0) {
Packit 3feee0
		errno = EINVAL;
Packit 3feee0
		return 0;
Packit 3feee0
	}
Packit 3feee0
	else
Packit 3feee0
		return kclass;
Packit 3feee0
}
Packit 3feee0
Packit 3feee0
access_vector_t
Packit 3feee0
map_perm(security_class_t tclass, access_vector_t kperm)
Packit 3feee0
{
Packit 3feee0
	if (tclass < current_mapping_size) {
Packit 3feee0
		unsigned i;
Packit 3feee0
		access_vector_t tperm = 0;
Packit 3feee0
Packit 3feee0
		for (i=0; i
Packit 3feee0
			if (kperm & current_mapping[tclass].perms[i]) {
Packit 3feee0
				tperm |= 1<
Packit 3feee0
				kperm &= ~current_mapping[tclass].perms[i];
Packit 3feee0
			}
Packit 3feee0
Packit 3feee0
		if (tperm == 0) {
Packit 3feee0
			errno = EINVAL;
Packit 3feee0
			return 0;
Packit 3feee0
		}
Packit 3feee0
		else
Packit 3feee0
			return tperm;
Packit 3feee0
	}
Packit 3feee0
	return kperm;
Packit 3feee0
}
Packit 3feee0
Packit 3feee0
void
Packit 3feee0
map_decision(security_class_t tclass, struct av_decision *avd)
Packit 3feee0
{
Packit 3feee0
	if (tclass < current_mapping_size) {
Packit 3feee0
		bool allow_unknown = (security_deny_unknown() == 0);
Packit 3feee0
		struct selinux_mapping *mapping = &current_mapping[tclass];
Packit 3feee0
		unsigned int i, n = mapping->num_perms;
Packit 3feee0
		access_vector_t result;
Packit 3feee0
Packit 3feee0
		for (i = 0, result = 0; i < n; i++) {
Packit 3feee0
			if (avd->allowed & mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
			else if (allow_unknown && !mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
		}
Packit 3feee0
		avd->allowed = result;
Packit 3feee0
Packit 3feee0
		for (i = 0, result = 0; i < n; i++) {
Packit 3feee0
			if (avd->decided & mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
			else if (allow_unknown && !mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
		}
Packit 3feee0
		avd->decided = result;
Packit 3feee0
Packit 3feee0
		for (i = 0, result = 0; i < n; i++)
Packit 3feee0
			if (avd->auditallow & mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
		avd->auditallow = result;
Packit 3feee0
Packit 3feee0
		for (i = 0, result = 0; i < n; i++) {
Packit 3feee0
			if (avd->auditdeny & mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
			else if (!allow_unknown && !mapping->perms[i])
Packit 3feee0
				result |= 1<
Packit 3feee0
		}
Packit 3feee0
Packit 3feee0
		/*
Packit 3feee0
		 * Make sure we audit denials for any permission check
Packit 3feee0
		 * beyond the mapping->num_perms since this indicates
Packit 3feee0
		 * a bug in the object manager.
Packit 3feee0
		 */
Packit 3feee0
		for (; i < (sizeof(result)*8); i++)
Packit 3feee0
			result |= 1<
Packit 3feee0
		avd->auditdeny = result;
Packit 3feee0
	}
Packit 3feee0
}