aboutsummaryrefslogtreecommitdiffstats
path: root/libselinux/src/mapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'libselinux/src/mapping.c')
-rw-r--r--libselinux/src/mapping.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/libselinux/src/mapping.c b/libselinux/src/mapping.c
index f205804b..33cea5ae 100644
--- a/libselinux/src/mapping.c
+++ b/libselinux/src/mapping.c
@@ -6,9 +6,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <selinux/selinux.h>
#include <selinux/avc.h>
+#include "callbacks.h"
#include "mapping.h"
+#include "selinux_internal.h"
/*
* Class and permission mappings
@@ -33,6 +36,9 @@ selinux_set_mapping(struct security_class_mapping *map)
size_t size = sizeof(struct selinux_mapping);
security_class_t i, j;
unsigned k;
+ bool print_unknown_handle = false;
+ bool reject = (security_reject_unknown() == 1);
+ bool deny = (security_deny_unknown() == 1);
free(current_mapping);
current_mapping = NULL;
@@ -62,8 +68,16 @@ selinux_set_mapping(struct security_class_mapping *map)
struct selinux_mapping *p_out = current_mapping + j;
p_out->value = string_to_security_class(p_in->name);
- if (!p_out->value)
- goto err2;
+ if (!p_out->value) {
+ selinux_log(SELINUX_INFO,
+ "SELinux: Class %s not defined in policy.\n",
+ p_in->name);
+ if (reject)
+ goto err2;
+ p_out->num_perms = 0;
+ print_unknown_handle = true;
+ continue;
+ }
k = 0;
while (p_in->perms[k]) {
@@ -74,13 +88,24 @@ selinux_set_mapping(struct security_class_mapping *map)
}
p_out->perms[k] = string_to_av_perm(p_out->value,
p_in->perms[k]);
- if (!p_out->perms[k])
- goto err2;
+ if (!p_out->perms[k]) {
+ selinux_log(SELINUX_INFO,
+ "SELinux: Permission %s in class %s not defined in policy.\n",
+ p_in->perms[k], p_in->name);
+ if (reject)
+ goto err2;
+ print_unknown_handle = true;
+ }
k++;
}
p_out->num_perms = k;
}
+ if (print_unknown_handle)
+ selinux_log(SELINUX_INFO,
+ "SELinux: the above unknown classes and permissions will be %s\n",
+ deny ? "denied" : "allowed");
+
/* Set the mapping size here so the above lookups are "raw" */
current_mapping_size = i;
return 0;
@@ -184,27 +209,46 @@ void
map_decision(security_class_t tclass, struct av_decision *avd)
{
if (tclass < current_mapping_size) {
- unsigned i;
+ bool allow_unknown = (security_deny_unknown() == 0);
+ struct selinux_mapping *mapping = &current_mapping[tclass];
+ unsigned int i, n = mapping->num_perms;
access_vector_t result;
- for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
- if (avd->allowed & current_mapping[tclass].perms[i])
+ for (i = 0, result = 0; i < n; i++) {
+ if (avd->allowed & mapping->perms[i])
+ result |= 1<<i;
+ else if (allow_unknown && !mapping->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])
+ for (i = 0, result = 0; i < n; i++) {
+ if (avd->decided & mapping->perms[i])
+ result |= 1<<i;
+ else if (allow_unknown && !mapping->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])
+ for (i = 0, result = 0; i < n; i++)
+ if (avd->auditallow & mapping->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])
+ for (i = 0, result = 0; i < n; i++) {
+ if (avd->auditdeny & mapping->perms[i])
result |= 1<<i;
+ else if (!allow_unknown && !mapping->perms[i])
+ result |= 1<<i;
+ }
+
+ /*
+ * Make sure we audit denials for any permission check
+ * beyond the mapping->num_perms since this indicates
+ * a bug in the object manager.
+ */
+ for (; i < (sizeof(result)*8); i++)
+ result |= 1<<i;
avd->auditdeny = result;
}
}