aboutsummaryrefslogtreecommitdiff
path: root/tools/sepolicy-analyze/neverallow.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/sepolicy-analyze/neverallow.c')
-rw-r--r--tools/sepolicy-analyze/neverallow.c515
1 files changed, 0 insertions, 515 deletions
diff --git a/tools/sepolicy-analyze/neverallow.c b/tools/sepolicy-analyze/neverallow.c
deleted file mode 100644
index b288ea7..0000000
--- a/tools/sepolicy-analyze/neverallow.c
+++ /dev/null
@@ -1,515 +0,0 @@
-#include <ctype.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "neverallow.h"
-
-static int debug;
-static int warn;
-
-void neverallow_usage() {
- fprintf(stderr, "\tneverallow [-w|--warn] [-d|--debug] [-n|--neverallows <neverallow-rules>] | [-f|--file <neverallow-file>]\n");
-}
-
-static int read_typeset(policydb_t *policydb, char **ptr, char *end,
- type_set_t *typeset, uint32_t *flags)
-{
- const char *keyword = "self";
- size_t keyword_size = strlen(keyword), len;
- char *p = *ptr;
- unsigned openparens = 0;
- char *start, *id;
- type_datum_t *type;
- struct ebitmap_node *n;
- unsigned int bit;
- bool negate = false;
- int rc;
-
- do {
- while (p < end && isspace(*p))
- p++;
-
- if (p == end)
- goto err;
-
- if (*p == '~') {
- if (debug)
- printf(" ~");
- typeset->flags = TYPE_COMP;
- p++;
- while (p < end && isspace(*p))
- p++;
- if (p == end)
- goto err;
- }
-
- if (*p == '{') {
- if (debug && !openparens)
- printf(" {");
- openparens++;
- p++;
- continue;
- }
-
- if (*p == '}') {
- if (debug && openparens == 1)
- printf(" }");
- if (openparens == 0)
- goto err;
- openparens--;
- p++;
- continue;
- }
-
- if (*p == '*') {
- if (debug)
- printf(" *");
- typeset->flags = TYPE_STAR;
- p++;
- continue;
- }
-
- if (*p == '-') {
- if (debug)
- printf(" -");
- negate = true;
- p++;
- continue;
- }
-
- if (*p == '#') {
- while (p < end && *p != '\n')
- p++;
- continue;
- }
-
- start = p;
- while (p < end && !isspace(*p) && *p != ':' && *p != ';' && *p != '{' && *p != '}' && *p != '#')
- p++;
-
- if (p == start)
- goto err;
-
- len = p - start;
- if (len == keyword_size && !strncmp(start, keyword, keyword_size)) {
- if (debug)
- printf(" self");
- *flags |= RULE_SELF;
- continue;
- }
-
- id = calloc(1, len + 1);
- if (!id)
- goto err;
- memcpy(id, start, len);
- if (debug)
- printf(" %s", id);
- type = hashtab_search(policydb->p_types.table, id);
- if (!type) {
- if (warn)
- fprintf(stderr, "Warning! Type or attribute %s used in neverallow undefined in policy being checked.\n", id);
- negate = false;
- continue;
- }
- free(id);
-
- if (type->flavor == TYPE_ATTRIB) {
- if (negate)
- rc = ebitmap_union(&typeset->negset, &policydb->attr_type_map[type->s.value - 1]);
- else
- rc = ebitmap_union(&typeset->types, &policydb->attr_type_map[type->s.value - 1]);
- } else if (negate) {
- rc = ebitmap_set_bit(&typeset->negset, type->s.value - 1, 1);
- } else {
- rc = ebitmap_set_bit(&typeset->types, type->s.value - 1, 1);
- }
-
- negate = false;
-
- if (rc)
- goto err;
-
- } while (p < end && openparens);
-
- if (p == end)
- goto err;
-
- if (typeset->flags & TYPE_STAR) {
- for (bit = 0; bit < policydb->p_types.nprim; bit++) {
- if (ebitmap_get_bit(&typeset->negset, bit))
- continue;
- if (policydb->type_val_to_struct[bit] &&
- policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB)
- continue;
- if (ebitmap_set_bit(&typeset->types, bit, 1))
- goto err;
- }
- }
-
- ebitmap_for_each_bit(&typeset->negset, n, bit) {
- if (!ebitmap_node_get_bit(n, bit))
- continue;
- if (ebitmap_set_bit(&typeset->types, bit, 0))
- goto err;
- }
-
- if (typeset->flags & TYPE_COMP) {
- for (bit = 0; bit < policydb->p_types.nprim; bit++) {
- if (policydb->type_val_to_struct[bit] &&
- policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB)
- continue;
- if (ebitmap_get_bit(&typeset->types, bit))
- ebitmap_set_bit(&typeset->types, bit, 0);
- else {
- if (ebitmap_set_bit(&typeset->types, bit, 1))
- goto err;
- }
- }
- }
-
- if (warn && ebitmap_length(&typeset->types) == 0 && !(*flags))
- fprintf(stderr, "Warning! Empty type set\n");
-
- *ptr = p;
- return 0;
-err:
- return -1;
-}
-
-static int read_classperms(policydb_t *policydb, char **ptr, char *end,
- class_perm_node_t **perms)
-{
- char *p = *ptr;
- unsigned openparens = 0;
- char *id, *start;
- class_datum_t *cls = NULL;
- perm_datum_t *perm = NULL;
- class_perm_node_t *classperms = NULL, *node = NULL;
- bool complement = false;
-
- while (p < end && isspace(*p))
- p++;
-
- if (p == end || *p != ':')
- goto err;
- p++;
-
- if (debug)
- printf(" :");
-
- do {
- while (p < end && isspace(*p))
- p++;
-
- if (p == end)
- goto err;
-
- if (*p == '{') {
- if (debug && !openparens)
- printf(" {");
- openparens++;
- p++;
- continue;
- }
-
- if (*p == '}') {
- if (debug && openparens == 1)
- printf(" }");
- if (openparens == 0)
- goto err;
- openparens--;
- p++;
- continue;
- }
-
- if (*p == '#') {
- while (p < end && *p != '\n')
- p++;
- continue;
- }
-
- start = p;
- while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#')
- p++;
-
- if (p == start)
- goto err;
-
- id = calloc(1, p - start + 1);
- if (!id)
- goto err;
- memcpy(id, start, p - start);
- if (debug)
- printf(" %s", id);
- cls = hashtab_search(policydb->p_classes.table, id);
- if (!cls) {
- if (warn)
- fprintf(stderr, "Warning! Class %s used in neverallow undefined in policy being checked.\n", id);
- continue;
- }
-
- node = calloc(1, sizeof *node);
- if (!node)
- goto err;
- node->tclass = cls->s.value;
- node->next = classperms;
- classperms = node;
- free(id);
- } while (p < end && openparens);
-
- if (p == end)
- goto err;
-
- if (warn && !classperms)
- fprintf(stderr, "Warning! Empty class set\n");
-
- do {
- while (p < end && isspace(*p))
- p++;
-
- if (p == end)
- goto err;
-
- if (*p == '~') {
- if (debug)
- printf(" ~");
- complement = true;
- p++;
- while (p < end && isspace(*p))
- p++;
- if (p == end)
- goto err;
- }
-
- if (*p == '{') {
- if (debug && !openparens)
- printf(" {");
- openparens++;
- p++;
- continue;
- }
-
- if (*p == '}') {
- if (debug && openparens == 1)
- printf(" }");
- if (openparens == 0)
- goto err;
- openparens--;
- p++;
- continue;
- }
-
- if (*p == '#') {
- while (p < end && *p != '\n')
- p++;
- continue;
- }
-
- start = p;
- while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#')
- p++;
-
- if (p == start)
- goto err;
-
- id = calloc(1, p - start + 1);
- if (!id)
- goto err;
- memcpy(id, start, p - start);
- if (debug)
- printf(" %s", id);
-
- if (!strcmp(id, "*")) {
- for (node = classperms; node; node = node->next)
- node->data = ~0;
- continue;
- }
-
- for (node = classperms; node; node = node->next) {
- cls = policydb->class_val_to_struct[node->tclass-1];
- perm = hashtab_search(cls->permissions.table, id);
- if (cls->comdatum && !perm)
- perm = hashtab_search(cls->comdatum->permissions.table, id);
- if (!perm) {
- if (warn)
- fprintf(stderr, "Warning! Permission %s used in neverallow undefined in class %s in policy being checked.\n", id, policydb->p_class_val_to_name[node->tclass-1]);
- continue;
- }
- node->data |= 1U << (perm->s.value - 1);
- }
- free(id);
- } while (p < end && openparens);
-
- if (p == end)
- goto err;
-
- if (complement) {
- for (node = classperms; node; node = node->next)
- node->data = ~node->data;
- }
-
- if (warn) {
- for (node = classperms; node; node = node->next)
- if (!node->data)
- fprintf(stderr, "Warning! Empty permission set\n");
- }
-
- *perms = classperms;
- *ptr = p;
- return 0;
-err:
- return -1;
-}
-
-static int check_neverallows(policydb_t *policydb, char *text, char *end)
-{
- const char *keyword = "neverallow";
- size_t keyword_size = strlen(keyword), len;
- struct avrule *neverallows = NULL, *avrule;
- char *p, *start;
-
- p = text;
- while (p < end) {
- while (p < end && isspace(*p))
- p++;
-
- if (*p == '#') {
- while (p < end && *p != '\n')
- p++;
- continue;
- }
-
- start = p;
- while (p < end && !isspace(*p))
- p++;
-
- len = p - start;
- if (len != keyword_size || strncmp(start, keyword, keyword_size))
- continue;
-
- if (debug)
- printf("neverallow");
-
- avrule = calloc(1, sizeof *avrule);
- if (!avrule)
- goto err;
-
- avrule->specified = AVRULE_NEVERALLOW;
-
- if (read_typeset(policydb, &p, end, &avrule->stypes, &avrule->flags))
- goto err;
-
- if (read_typeset(policydb, &p, end, &avrule->ttypes, &avrule->flags))
- goto err;
-
- if (read_classperms(policydb, &p, end, &avrule->perms))
- goto err;
-
- while (p < end && *p != ';')
- p++;
-
- if (p == end || *p != ';')
- goto err;
-
- if (debug)
- printf(";\n");
-
- avrule->next = neverallows;
- neverallows = avrule;
- }
-
- if (!neverallows)
- goto err;
-
- return check_assertions(NULL, policydb, neverallows);
-err:
- if (errno == ENOMEM) {
- fprintf(stderr, "Out of memory while parsing neverallow rules\n");
- } else
- fprintf(stderr, "Error while parsing neverallow rules\n");
- return -1;
-}
-
-static int check_neverallows_file(policydb_t *policydb, const char *filename)
-{
- int fd;
- struct stat sb;
- char *text, *end;
-
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
- return -1;
- }
- if (fstat(fd, &sb) < 0) {
- fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno));
- close(fd);
- return -1;
- }
- text = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- end = text + sb.st_size;
- if (text == MAP_FAILED) {
- fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno));
- close(fd);
- return -1;
- }
- close(fd);
- return check_neverallows(policydb, text, end);
-}
-
-static int check_neverallows_string(policydb_t *policydb, char *string, size_t len)
-{
- char *text, *end;
- text = string;
- end = text + len;
- return check_neverallows(policydb, text, end);
-}
-
-int neverallow_func (int argc, char **argv, policydb_t *policydb) {
- char *rules = 0, *file = 0;
- char ch;
-
- struct option neverallow_options[] = {
- {"debug", no_argument, NULL, 'd'},
- {"file_input", required_argument, NULL, 'f'},
- {"neverallow", required_argument, NULL, 'n'},
- {"warn", no_argument, NULL, 'w'},
- {NULL, 0, NULL, 0}
- };
-
- while ((ch = getopt_long(argc, argv, "df:n:w", neverallow_options, NULL)) != -1) {
- switch (ch) {
- case 'd':
- debug = 1;
- break;
- case 'f':
- file = optarg;
- break;
- case 'n':
- rules = optarg;
- break;
- case 'w':
- warn = 1;
- break;
- default:
- USAGE_ERROR = true;
- return -1;
- }
- }
-
- if (!(rules || file) || (rules && file)){
- USAGE_ERROR = true;
- return -1;
- }
- if (file) {
- return check_neverallows_file(policydb, file);
- } else {
- return check_neverallows_string(policydb, rules, strlen(rules));
- }
-}