| /* Authors: Frank Mayer <[email protected]> |
| * and Karl MacMillan <[email protected]> |
| * |
| * Copyright (C) 2003,2010 Tresys Technology, LLC |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation, version 2. |
| * |
| * Adapted from dispol.c. |
| * |
| * This program is used by sepolgen-ifgen to get the access for all of |
| * the attributes in the policy so that it can resolve the |
| * typeattribute statements in the interfaces. |
| * |
| * It outputs the attribute access in a similar format to what sepolgen |
| * uses to store interface vectors: |
| * [Attribute sandbox_x_domain] |
| * sandbox_x_domain,samba_var_t,file,ioctl,read,getattr,lock,open |
| * sandbox_x_domain,samba_var_t,dir,getattr,search,open |
| * sandbox_x_domain,initrc_var_run_t,file,ioctl,read,getattr,lock,open |
| * |
| */ |
| |
| #include <sepol/policydb/policydb.h> |
| #include <sepol/policydb/avtab.h> |
| #include <sepol/policydb/util.h> |
| |
| #include <selinux/selinux.h> |
| |
| #include <limits.h> |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <sys/mman.h> |
| #include <unistd.h> |
| |
| struct val_to_name { |
| unsigned int val; |
| char *name; |
| }; |
| |
| static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data) |
| { |
| struct val_to_name *v = data; |
| perm_datum_t *perdatum; |
| |
| perdatum = (perm_datum_t *) datum; |
| |
| if (v->val == perdatum->s.value) { |
| v->name = key; |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| static int render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp, |
| FILE *fp) |
| { |
| struct val_to_name v; |
| class_datum_t *cladatum; |
| char *perm = NULL; |
| unsigned int i; |
| int rc; |
| uint32_t tclass = key->target_class; |
| |
| cladatum = policydbp->class_val_to_struct[tclass - 1]; |
| for (i = 0; i < cladatum->permissions.nprim; i++) { |
| if (av & (1 << i)) { |
| v.val = i + 1; |
| rc = hashtab_map(cladatum->permissions.table, |
| perm_name, &v); |
| if (!rc && cladatum->comdatum) { |
| rc = hashtab_map(cladatum->comdatum-> |
| permissions.table, perm_name, |
| &v); |
| } |
| if (rc) |
| perm = v.name; |
| if (perm) { |
| fprintf(fp, ",%s", perm); |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int render_key(avtab_key_t *key, policydb_t *p, FILE *fp) |
| { |
| char *stype, *ttype, *tclass; |
| stype = p->p_type_val_to_name[key->source_type - 1]; |
| ttype = p->p_type_val_to_name[key->target_type - 1]; |
| tclass = p->p_class_val_to_name[key->target_class - 1]; |
| if (stype && ttype) { |
| fprintf(fp, "%s,%s,%s", stype, ttype, tclass); |
| } else { |
| fprintf(stderr, "error rendering key\n"); |
| exit(1); |
| } |
| |
| return 0; |
| } |
| |
| struct callback_data |
| { |
| uint32_t attr; |
| policydb_t *policy; |
| FILE *fp; |
| }; |
| |
| static int output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args) |
| { |
| struct callback_data *cb_data = (struct callback_data *)args; |
| |
| if (key->source_type != cb_data->attr) |
| return 0; |
| |
| if (!(key->specified & AVTAB_AV && key->specified & AVTAB_ALLOWED)) |
| return 0; |
| |
| render_key(key, cb_data->policy, cb_data->fp); |
| render_access_mask(datum->data, key, cb_data->policy, cb_data->fp); |
| fprintf(cb_data->fp, "\n"); |
| |
| return 0; |
| } |
| |
| static int attribute_callback(hashtab_key_t key, hashtab_datum_t datum, void *datap) |
| { |
| struct callback_data *cb_data = (struct callback_data *)datap; |
| type_datum_t *t = (type_datum_t *)datum; |
| |
| if (t->flavor == TYPE_ATTRIB) { |
| fprintf(cb_data->fp, "[Attribute %s]\n", key); |
| cb_data->attr = t->s.value; |
| if (avtab_map(&cb_data->policy->te_avtab, output_avrule, cb_data) < 0) |
| return -1; |
| if (avtab_map(&cb_data->policy->te_cond_avtab, output_avrule, cb_data) < 0) |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| static policydb_t *load_policy(const char *filename) |
| { |
| policydb_t *policydb; |
| struct policy_file pf; |
| FILE *fp; |
| char pathname[PATH_MAX]; |
| int suffix_ver; |
| int ret; |
| |
| /* no explicit policy name given, try loaded policy on a SELinux enabled system */ |
| if (!filename) { |
| filename = selinux_current_policy_path(); |
| } |
| |
| /* |
| * Fallback to default store paths with version suffixes, |
| * starting from the maximum supported policy version. |
| */ |
| if (!filename) { |
| for (suffix_ver = sepol_policy_kern_vers_max(); suffix_ver > 0; suffix_ver--) { |
| snprintf(pathname, sizeof(pathname), "%s.%d", selinux_binary_policy_path(), suffix_ver); |
| |
| if (access(pathname, F_OK) == 0) { |
| filename = pathname; |
| break; |
| } |
| } |
| |
| if (!filename) { |
| fprintf(stderr, "Can't find any policy at '%s'\n", |
| selinux_binary_policy_path()); |
| return NULL; |
| } |
| } |
| |
| fp = fopen(filename, "r"); |
| if (fp == NULL) { |
| fprintf(stderr, "Can't open '%s': %s\n", |
| filename, strerror(errno)); |
| return NULL; |
| } |
| |
| policy_file_init(&pf); |
| pf.type = PF_USE_STDIO; |
| pf.fp = fp; |
| |
| policydb = malloc(sizeof(policydb_t)); |
| if (policydb == NULL) { |
| fprintf(stderr, "Out of memory!\n"); |
| fclose(fp); |
| return NULL; |
| } |
| |
| if (policydb_init(policydb)) { |
| fprintf(stderr, "Out of memory!\n"); |
| free(policydb); |
| fclose(fp); |
| return NULL; |
| } |
| |
| ret = policydb_read(policydb, &pf, 1); |
| if (ret) { |
| fprintf(stderr, |
| "error(s) encountered while parsing configuration\n"); |
| free(policydb); |
| fclose(fp); |
| return NULL; |
| } |
| |
| fclose(fp); |
| |
| return policydb; |
| |
| } |
| |
| static void usage(char *progname) |
| { |
| printf("usage: %s out_file [policy_file]\n", progname); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| policydb_t *p; |
| struct callback_data cb_data; |
| FILE *fp; |
| |
| if (argc != 2 && argc != 3) { |
| usage(argv[0]); |
| return -1; |
| } |
| |
| /* Open the policy. */ |
| p = load_policy(argv[2]); |
| if (p == NULL) |
| return -1; |
| |
| /* Open the output policy. */ |
| fp = fopen(argv[1], "w"); |
| if (fp == NULL) { |
| fprintf(stderr, "error opening output file\n"); |
| policydb_destroy(p); |
| free(p); |
| return -1; |
| } |
| |
| /* Find all of the attributes and output their access. */ |
| cb_data.policy = p; |
| cb_data.fp = fp; |
| |
| if (hashtab_map(p->p_types.table, attribute_callback, &cb_data)) { |
| printf("error finding attributes\n"); |
| } |
| |
| policydb_destroy(p); |
| free(p); |
| fclose(fp); |
| |
| return 0; |
| } |