selinux/python/audit2allow/sepolgen-ifgen-attr-helper.c
Christian Göttsche c14a86af9a python/audit2allow: close file stream on error
sepolgen-ifgen-attr-helper.c: In function ‘load_policy’:
    sepolgen-ifgen-attr-helper.c:196:17: warning: leak of FILE ‘fp’ [CWE-775] [-Wanalyzer-file-leak]
      196 |                 fprintf(stderr, "Out of memory!\n");
          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
2022-06-15 08:58:54 -04:00

267 lines
5.8 KiB
C

/* Authors: Frank Mayer <mayerf@tresys.com>
* and Karl MacMillan <kmacmillan@tresys.com>
*
* 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;
}