2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
|
|
|
|
*
|
|
|
|
* Copyright (C) 2003,2004,2005 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dismod.c
|
|
|
|
*
|
|
|
|
* Test program to the contents of a binary policy in text
|
|
|
|
* form.
|
|
|
|
*
|
|
|
|
* dismod binary_mod_file
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <sepol/policydb/policydb.h>
|
|
|
|
#include <sepol/policydb/services.h>
|
|
|
|
#include <sepol/policydb/conditional.h>
|
|
|
|
#include <sepol/policydb/link.h>
|
|
|
|
#include <sepol/policydb/module.h>
|
|
|
|
#include <sepol/policydb/util.h>
|
|
|
|
#include <sepol/policydb/polcaps.h>
|
|
|
|
|
|
|
|
#include <byteswap.h>
|
|
|
|
#include <endian.h>
|
|
|
|
|
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
|
#define le32_to_cpu(x) (x)
|
|
|
|
#else
|
|
|
|
#define le32_to_cpu(x) bswap_32(x)
|
|
|
|
#endif
|
|
|
|
|
2011-03-28 17:39:03 +00:00
|
|
|
#define DISPLAY_AVBLOCK_COND_AVTAB 0
|
|
|
|
#define DISPLAY_AVBLOCK_UNCOND_AVTAB 1
|
|
|
|
#define DISPLAY_AVBLOCK_ROLE_TYPE_NODE 2 /* unused? */
|
|
|
|
#define DISPLAY_AVBLOCK_ROLE_TRANS 3
|
|
|
|
#define DISPLAY_AVBLOCK_ROLE_ALLOW 4
|
|
|
|
#define DISPLAY_AVBLOCK_REQUIRES 5
|
|
|
|
#define DISPLAY_AVBLOCK_DECLARES 6
|
2011-03-28 18:00:19 +00:00
|
|
|
#define DISPLAY_AVBLOCK_FILENAME_TRANS 7
|
2011-03-28 17:39:03 +00:00
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
static policydb_t policydb;
|
|
|
|
extern unsigned int ss_initialized;
|
|
|
|
|
|
|
|
int policyvers = MOD_POLICYDB_VERSION_BASE;
|
|
|
|
|
|
|
|
static const char *symbol_labels[9] = {
|
|
|
|
"commons",
|
|
|
|
"classes", "roles ", "types ", "users ", "bools ",
|
|
|
|
"levels ", "cats ", "attribs"
|
|
|
|
};
|
|
|
|
|
2017-03-05 17:13:01 +00:00
|
|
|
static __attribute__((__noreturn__)) void usage(const char *progname)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
printf("usage: %s binary_pol_file\n\n", progname);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p,
|
|
|
|
FILE * fp)
|
|
|
|
{
|
|
|
|
char *perm;
|
|
|
|
fprintf(fp, "{");
|
|
|
|
perm = sepol_av_to_string(p, class, mask);
|
|
|
|
if (perm)
|
|
|
|
fprintf(fp, "%s ", perm);
|
|
|
|
fprintf(fp, "}");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void render_access_bitmap(ebitmap_t * map, uint32_t class,
|
|
|
|
policydb_t * p, FILE * fp)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
char *perm;
|
|
|
|
fprintf(fp, "{");
|
|
|
|
for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
|
|
|
|
if (ebitmap_get_bit(map, i)) {
|
2021-09-14 12:48:25 +00:00
|
|
|
perm = sepol_av_to_string(p, class, UINT32_C(1) << i);
|
2008-08-19 19:30:36 +00:00
|
|
|
if (perm)
|
|
|
|
fprintf(fp, " %s", perm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(fp, " }");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
|
2014-09-14 21:41:46 +00:00
|
|
|
uint32_t symbol_value, const char *prefix)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
char *id = p->sym_val_to_name[symbol_type][symbol_value];
|
|
|
|
scope_datum_t *scope =
|
|
|
|
(scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id);
|
|
|
|
assert(scope != NULL);
|
|
|
|
if (scope->scope == SCOPE_REQ) {
|
|
|
|
fprintf(fp, " [%s%s]", prefix, id);
|
|
|
|
} else {
|
|
|
|
fprintf(fp, " %s%s", prefix, id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
|
2008-08-19 19:30:36 +00:00
|
|
|
FILE * fp)
|
|
|
|
{
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i, num_types;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
if (set->flags & TYPE_STAR) {
|
|
|
|
fprintf(fp, " * ");
|
|
|
|
return 0;
|
|
|
|
} else if (set->flags & TYPE_COMP) {
|
|
|
|
fprintf(fp, " ~");
|
|
|
|
}
|
|
|
|
|
|
|
|
num_types = 0;
|
2022-11-25 15:49:49 +00:00
|
|
|
if (flags & (RULE_SELF | RULE_NOTSELF)) {
|
2008-08-19 19:30:36 +00:00
|
|
|
num_types++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
|
|
|
|
i++) {
|
|
|
|
if (!ebitmap_get_bit(&set->types, i))
|
|
|
|
continue;
|
|
|
|
num_types++;
|
|
|
|
if (num_types > 1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_types <= 1) {
|
|
|
|
for (i = ebitmap_startbit(&set->negset);
|
|
|
|
i < ebitmap_length(&set->negset); i++) {
|
|
|
|
if (!ebitmap_get_bit(&set->negset, i))
|
|
|
|
continue;
|
|
|
|
num_types++;
|
|
|
|
if (num_types > 1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_types > 1)
|
|
|
|
fprintf(fp, "{");
|
|
|
|
|
|
|
|
for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
|
|
|
|
i++) {
|
|
|
|
if (!ebitmap_get_bit(&set->types, i))
|
|
|
|
continue;
|
|
|
|
display_id(policy, fp, SYM_TYPES, i, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = ebitmap_startbit(&set->negset);
|
|
|
|
i < ebitmap_length(&set->negset); i++) {
|
|
|
|
if (!ebitmap_get_bit(&set->negset, i))
|
|
|
|
continue;
|
|
|
|
display_id(policy, fp, SYM_TYPES, i, "-");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & RULE_SELF) {
|
|
|
|
fprintf(fp, " self");
|
|
|
|
}
|
|
|
|
|
2022-11-25 15:49:49 +00:00
|
|
|
if (flags & RULE_NOTSELF) {
|
|
|
|
fprintf(fp, " -self");
|
|
|
|
}
|
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
if (num_types > 1)
|
|
|
|
fprintf(fp, " }");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i, num = 0;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
if (roles->flags & ROLE_STAR) {
|
|
|
|
fprintf(fp, " * ");
|
|
|
|
return 0;
|
|
|
|
} else if (roles->flags & ROLE_COMP) {
|
|
|
|
fprintf(fp, " ~");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = ebitmap_startbit(&roles->roles);
|
|
|
|
i < ebitmap_length(&roles->roles); i++) {
|
|
|
|
if (!ebitmap_get_bit(&roles->roles, i))
|
|
|
|
continue;
|
|
|
|
num++;
|
|
|
|
if (num > 1) {
|
|
|
|
fprintf(fp, "{");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = ebitmap_startbit(&roles->roles);
|
|
|
|
i < ebitmap_length(&roles->roles); i++) {
|
|
|
|
if (ebitmap_get_bit(&roles->roles, i))
|
|
|
|
display_id(p, fp, SYM_ROLES, i, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num > 1)
|
|
|
|
fprintf(fp, " }");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_avrule(avrule_t * avrule, policydb_t * policy,
|
2008-08-19 19:30:36 +00:00
|
|
|
FILE * fp)
|
|
|
|
{
|
|
|
|
class_perm_node_t *cur;
|
|
|
|
int num_classes;
|
|
|
|
|
|
|
|
if (avrule == NULL) {
|
|
|
|
fprintf(fp, " <empty>\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (avrule->specified & AVRULE_AV) {
|
|
|
|
if (avrule->specified & AVRULE_ALLOWED) {
|
|
|
|
fprintf(fp, " allow");
|
|
|
|
}
|
|
|
|
if (avrule->specified & AVRULE_AUDITALLOW) {
|
|
|
|
fprintf(fp, " auditallow ");
|
|
|
|
}
|
|
|
|
if (avrule->specified & AVRULE_DONTAUDIT) {
|
|
|
|
fprintf(fp, " dontaudit");
|
|
|
|
}
|
|
|
|
} else if (avrule->specified & AVRULE_TYPE) {
|
|
|
|
if (avrule->specified & AVRULE_TRANSITION) {
|
|
|
|
fprintf(fp, " type_transition");
|
|
|
|
}
|
|
|
|
if (avrule->specified & AVRULE_MEMBER) {
|
|
|
|
fprintf(fp, " type_member");
|
|
|
|
}
|
|
|
|
if (avrule->specified & AVRULE_CHANGE) {
|
|
|
|
fprintf(fp, " type_change");
|
|
|
|
}
|
|
|
|
} else if (avrule->specified & AVRULE_NEVERALLOW) {
|
|
|
|
fprintf(fp, " neverallow");
|
2017-05-15 16:21:45 +00:00
|
|
|
} else if (avrule->specified & AVRULE_XPERMS) {
|
|
|
|
if (avrule->specified & AVRULE_XPERMS_ALLOWED)
|
|
|
|
fprintf(fp, "allowxperm ");
|
|
|
|
else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW)
|
|
|
|
fprintf(fp, "auditallowxperm ");
|
|
|
|
else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT)
|
|
|
|
fprintf(fp, "dontauditxperm ");
|
2008-08-19 19:30:36 +00:00
|
|
|
} else {
|
|
|
|
fprintf(fp, " ERROR: no valid rule type specified\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (display_type_set(&avrule->stypes, 0, policy, fp))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
fprintf(fp, " :");
|
|
|
|
cur = avrule->perms;
|
|
|
|
num_classes = 0;
|
|
|
|
while (cur) {
|
|
|
|
num_classes++;
|
|
|
|
if (num_classes > 1)
|
|
|
|
break;
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_classes > 1)
|
|
|
|
fprintf(fp, " {");
|
|
|
|
|
|
|
|
cur = avrule->perms;
|
|
|
|
while (cur) {
|
2014-12-16 19:44:41 +00:00
|
|
|
display_id(policy, fp, SYM_CLASSES, cur->tclass - 1, "");
|
2008-08-19 19:30:36 +00:00
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_classes > 1)
|
|
|
|
fprintf(fp, " }");
|
|
|
|
fprintf(fp, " ");
|
|
|
|
|
|
|
|
if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
|
2014-12-16 19:44:41 +00:00
|
|
|
render_access_mask(avrule->perms->data, avrule->perms->tclass,
|
2008-08-19 19:30:36 +00:00
|
|
|
policy, fp);
|
|
|
|
} else if (avrule->specified & AVRULE_TYPE) {
|
|
|
|
display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
|
2017-05-15 16:21:45 +00:00
|
|
|
} else if (avrule->specified & AVRULE_XPERMS) {
|
|
|
|
avtab_extended_perms_t xperms;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION)
|
|
|
|
xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
|
|
|
|
else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER)
|
|
|
|
xperms.specified = AVTAB_XPERMS_IOCTLDRIVER;
|
|
|
|
else {
|
|
|
|
fprintf(fp, " ERROR: no valid xperms specified\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xperms.driver = avrule->xperms->driver;
|
|
|
|
for (i = 0; i < EXTENDED_PERMS_LEN; i++)
|
|
|
|
xperms.perms[i] = avrule->xperms->perms[i];
|
|
|
|
|
|
|
|
fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms));
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, ";\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
type_datum_t *type;
|
|
|
|
FILE *fp;
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i, first_attrib = 1;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
type = (type_datum_t *) datum;
|
|
|
|
fp = (FILE *) data;
|
|
|
|
|
|
|
|
if (type->primary) {
|
|
|
|
display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
|
|
|
|
fprintf(fp, " [%d]: ", type->s.value);
|
|
|
|
} else {
|
|
|
|
/* as that aliases have no value of their own and that
|
|
|
|
* they can never be required by a module, use this
|
|
|
|
* alternative way of displaying a name */
|
|
|
|
fprintf(fp, " %s [%d]: ", (char *)key, type->s.value);
|
|
|
|
}
|
|
|
|
if (type->flavor == TYPE_ATTRIB) {
|
|
|
|
fprintf(fp, "attribute for types");
|
|
|
|
for (i = ebitmap_startbit(&type->types);
|
|
|
|
i < ebitmap_length(&type->types); i++) {
|
|
|
|
if (!ebitmap_get_bit(&type->types, i))
|
|
|
|
continue;
|
|
|
|
if (first_attrib) {
|
|
|
|
first_attrib = 0;
|
|
|
|
} else {
|
|
|
|
fprintf(fp, ",");
|
|
|
|
}
|
|
|
|
display_id(&policydb, fp, SYM_TYPES, i, "");
|
|
|
|
}
|
|
|
|
} else if (type->primary) {
|
|
|
|
fprintf(fp, "type");
|
|
|
|
} else {
|
|
|
|
fprintf(fp, "alias for type");
|
|
|
|
display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
|
|
|
|
}
|
|
|
|
fprintf(fp, " flags:%x\n", type->flags);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_types(policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
if (hashtab_map(p->p_types.table, display_type_callback, fp))
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_users(policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i, j;
|
2008-08-19 19:30:36 +00:00
|
|
|
ebitmap_t *bitmap;
|
|
|
|
for (i = 0; i < p->p_users.nprim; i++) {
|
|
|
|
display_id(p, fp, SYM_USERS, i, "");
|
|
|
|
fprintf(fp, ":");
|
|
|
|
bitmap = &(p->user_val_to_struct[i]->roles.roles);
|
|
|
|
for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap);
|
|
|
|
j++) {
|
|
|
|
if (ebitmap_get_bit(bitmap, j)) {
|
|
|
|
display_id(p, fp, SYM_ROLES, j, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_bools(policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
for (i = 0; i < p->p_bools.nprim; i++) {
|
|
|
|
display_id(p, fp, SYM_BOOLS, i, "");
|
|
|
|
fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
cond_expr_t *cur;
|
|
|
|
for (cur = exp; cur != NULL; cur = cur->next) {
|
|
|
|
switch (cur->expr_type) {
|
|
|
|
case COND_BOOL:
|
|
|
|
fprintf(fp, "%s ",
|
2023-04-20 15:35:52 +00:00
|
|
|
p->p_bool_val_to_name[cur->boolean - 1]);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case COND_NOT:
|
|
|
|
fprintf(fp, "! ");
|
|
|
|
break;
|
|
|
|
case COND_OR:
|
|
|
|
fprintf(fp, "|| ");
|
|
|
|
break;
|
|
|
|
case COND_AND:
|
|
|
|
fprintf(fp, "&& ");
|
|
|
|
break;
|
|
|
|
case COND_XOR:
|
|
|
|
fprintf(fp, "^ ");
|
|
|
|
break;
|
|
|
|
case COND_EQ:
|
|
|
|
fprintf(fp, "== ");
|
|
|
|
break;
|
|
|
|
case COND_NEQ:
|
|
|
|
fprintf(fp, "!= ");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(fp, "error!");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static void display_policycon(FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
2011-11-03 20:54:25 +00:00
|
|
|
/* There was an attempt to implement this at one time. Look through
|
|
|
|
* git history to find it. */
|
|
|
|
fprintf(fp, "Sorry, not implemented\n");
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static void display_initial_sids(policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
ocontext_t *cur;
|
|
|
|
char *user, *role, *type;
|
|
|
|
|
|
|
|
fprintf(fp, "Initial SIDs:\n");
|
|
|
|
for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) {
|
|
|
|
user = p->p_user_val_to_name[cur->context[0].user - 1];
|
|
|
|
role = p->p_role_val_to_name[cur->context[0].role - 1];
|
|
|
|
type = p->p_type_val_to_name[cur->context[0].type - 1];
|
libsepol,checkpolicy: support omitting unused initial sid contexts
Remove restrictions in libsepol and checkpolicy that required all
declared initial SIDs to be assigned a context. With this patch,
it is possible to build and load a policy that drops the sid <sidname>
<context> declarations for the unused initial SIDs. It is still
required to retain the sid <sidname> declarations (in the flask
definitions) in order to preserve the initial SID ordering/values.
The unused initial SIDs can be renamed, e.g. to add an unused_
prefix or similar, if desired, since the names used in the policy
are not stored in the kernel binary policy.
In CIL policies, the (sid ...) and (sidorder (...)) statements
must be left intact for compatibility but the (sidcontext ...)
statements for the unused initial SIDs can be omitted after this change.
With current kernels, if one removes an unused initial SID context
from policy, builds policy with this change applied and loads the
policy into the kernel, cat /sys/fs/selinux/initial_contexts/<sidname>
will show the unlabeled context. With the kernel patch to remove unused
initial SIDs, the /sys/fs/selinux/initial_contexts/<sidname>
file will not be created for unused initial SIDs in the first place.
NB If an unused initial SID was assigned a context different from
the unlabeled context in existing policy, then it is not safe to
remove that initial SID context from policy and reload policy on
the running kernel that was booted with the original policy. This
is because that kernel may have assigned that SID to various kernel
objects already and those objects will then be treated as having
the unlabeled context after the removal. In refpolicy, examples
of such initial SIDs are the "fs" SID and the "sysctl" SID. Even
though these initial SIDs are not directly used (in code) by the current
kernel, their contexts are being applied to filesystems and sysctl files by
policy and therefore the SIDs are being assigned to objects.
NB The "sysctl" SID was in use by the kernel up until
commit 8e6c96935fcc1ed3dbebc96fddfef3f2f2395afc ("security/selinux:
fix /proc/sys/ labeling) circa v2.6.39. Removing its context from
policy will cause sysctl(2) or /proc/sys accesses to end up
performing permission checks against the unlabeled context and
likely encounter denials for kernels < 2.6.39.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
2020-01-28 14:47:41 +00:00
|
|
|
fprintf(fp, "\tsid %d, context %s:%s:%s\n",
|
|
|
|
cur->sid[0], user, role, type);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
fprintf(fp, "Policy Initial SIDs:\n");
|
|
|
|
for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) {
|
|
|
|
user = p->p_user_val_to_name[cur->context[0].user - 1];
|
|
|
|
role = p->p_role_val_to_name[cur->context[0].role - 1];
|
|
|
|
type = p->p_type_val_to_name[cur->context[0].type - 1];
|
|
|
|
fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
|
|
|
|
cur->u.name, cur->sid[0], user, role, type);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
|
2011-03-25 05:52:03 +00:00
|
|
|
{
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i, num = 0;
|
2011-03-25 05:52:03 +00:00
|
|
|
|
|
|
|
for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
|
|
|
|
if (!ebitmap_get_bit(classes, i))
|
|
|
|
continue;
|
|
|
|
num++;
|
|
|
|
if (num > 1) {
|
|
|
|
fprintf(fp, "{");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
|
|
|
|
if (ebitmap_get_bit(classes, i))
|
|
|
|
display_id(p, fp, SYM_CLASSES, i, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num > 1)
|
|
|
|
fprintf(fp, " }");
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
for (; tr; tr = tr->next) {
|
|
|
|
fprintf(fp, "role transition ");
|
|
|
|
display_mod_role_set(&tr->roles, p, fp);
|
|
|
|
display_type_set(&tr->types, 0, p, fp);
|
2011-03-25 05:52:03 +00:00
|
|
|
fprintf(fp, " :");
|
|
|
|
display_class_set(&tr->classes, p, fp);
|
|
|
|
display_id(p, fp, SYM_ROLES, tr->new_role - 1, "");
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(fp, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
for (; ra; ra = ra->next) {
|
|
|
|
fprintf(fp, "role allow ");
|
|
|
|
display_mod_role_set(&ra->roles, p, fp);
|
|
|
|
display_mod_role_set(&ra->new_roles, p, fp);
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-20 19:41:05 +00:00
|
|
|
static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
|
2011-03-28 18:00:19 +00:00
|
|
|
{
|
2011-04-20 19:41:05 +00:00
|
|
|
fprintf(fp, "filename transition");
|
2011-03-28 18:00:19 +00:00
|
|
|
for (; tr; tr = tr->next) {
|
|
|
|
display_type_set(&tr->stypes, 0, p, fp);
|
|
|
|
display_type_set(&tr->ttypes, 0, p, fp);
|
|
|
|
display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
|
|
|
|
display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
|
2011-04-20 19:41:05 +00:00
|
|
|
fprintf(fp, " %s\n", tr->name);
|
2011-03-28 18:00:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int role_display_callback(hashtab_key_t key __attribute__((unused)),
|
2011-11-03 20:54:25 +00:00
|
|
|
hashtab_datum_t datum, void *data)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
role_datum_t *role;
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
role = (role_datum_t *) datum;
|
|
|
|
fp = (FILE *) data;
|
|
|
|
|
|
|
|
fprintf(fp, "role:");
|
|
|
|
display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, "");
|
|
|
|
fprintf(fp, " types: ");
|
|
|
|
display_type_set(&role->types, 0, &policydb, fp);
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int display_scope_index(scope_index_t * indices, policydb_t * p,
|
|
|
|
FILE * out_fp)
|
|
|
|
{
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i;
|
2008-08-19 19:30:36 +00:00
|
|
|
for (i = 0; i < SYM_NUM; i++) {
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int any_found = 0, j;
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(out_fp, "%s:", symbol_labels[i]);
|
|
|
|
for (j = ebitmap_startbit(&indices->scope[i]);
|
|
|
|
j < ebitmap_length(&indices->scope[i]); j++) {
|
|
|
|
if (ebitmap_get_bit(&indices->scope[i], j)) {
|
|
|
|
any_found = 1;
|
|
|
|
fprintf(out_fp, " %s",
|
|
|
|
p->sym_val_to_name[i][j]);
|
|
|
|
if (i == SYM_CLASSES) {
|
|
|
|
if (j < indices->class_perms_len) {
|
|
|
|
render_access_bitmap(indices->
|
|
|
|
class_perms_map
|
|
|
|
+ j, j + 1,
|
|
|
|
p, out_fp);
|
|
|
|
} else {
|
|
|
|
fprintf(out_fp,
|
|
|
|
"<no perms known>");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!any_found) {
|
|
|
|
fprintf(out_fp, " <empty>");
|
|
|
|
}
|
|
|
|
fprintf(out_fp, "\n");
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
int display_cond_expressions(policydb_t * p, FILE * fp)
|
|
|
|
{
|
|
|
|
cond_node_t *cur;
|
|
|
|
cond_av_list_t *av_cur;
|
|
|
|
for (cur = p->cond_list; cur != NULL; cur = cur->next) {
|
|
|
|
fprintf(fp, "expression: ");
|
|
|
|
display_expr(p, cur->expr, fp);
|
|
|
|
fprintf(fp, "current state: %d\n", cur->cur_state);
|
|
|
|
fprintf(fp, "True list:\n");
|
|
|
|
for (av_cur = cur->true_list; av_cur != NULL;
|
|
|
|
av_cur = av_cur->next) {
|
|
|
|
fprintf(fp, "\t");
|
|
|
|
render_av_rule(&av_cur->node->key, &av_cur->node->datum,
|
|
|
|
RENDER_CONDITIONAL, p, fp);
|
|
|
|
}
|
|
|
|
fprintf(fp, "False list:\n");
|
|
|
|
for (av_cur = cur->false_list; av_cur != NULL;
|
|
|
|
av_cur = av_cur->next) {
|
|
|
|
fprintf(fp, "\t");
|
|
|
|
render_av_rule(&av_cur->node->key, &av_cur->node->datum,
|
|
|
|
RENDER_CONDITIONAL, p, fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int change_bool(char *name, int state, policydb_t * p, FILE * fp)
|
|
|
|
{
|
|
|
|
cond_bool_datum_t *bool;
|
|
|
|
|
|
|
|
bool = hashtab_search(p->p_bools.table, name);
|
|
|
|
if (bool == NULL) {
|
|
|
|
fprintf(fp, "Could not find bool %s\n", name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
bool->state = state;
|
|
|
|
evaluate_conds(p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_avdecl(avrule_decl_t * decl, int field,
|
2008-08-19 19:30:36 +00:00
|
|
|
policydb_t * policy, FILE * out_fp)
|
|
|
|
{
|
|
|
|
fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
|
|
|
|
(decl->enabled ? " [enabled]" : ""));
|
|
|
|
switch (field) {
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_COND_AVTAB:{
|
2008-08-19 19:30:36 +00:00
|
|
|
cond_list_t *cond = decl->cond_list;
|
|
|
|
avrule_t *avrule;
|
|
|
|
while (cond) {
|
|
|
|
fprintf(out_fp, "expression: ");
|
|
|
|
display_expr(&policydb, cond->expr, out_fp);
|
|
|
|
fprintf(out_fp, "current state: %d\n",
|
|
|
|
cond->cur_state);
|
|
|
|
fprintf(out_fp, "True list:\n");
|
|
|
|
avrule = cond->avtrue_list;
|
|
|
|
while (avrule) {
|
|
|
|
display_avrule(avrule,
|
|
|
|
&policydb, out_fp);
|
|
|
|
avrule = avrule->next;
|
|
|
|
}
|
|
|
|
fprintf(out_fp, "False list:\n");
|
|
|
|
avrule = cond->avfalse_list;
|
|
|
|
while (avrule) {
|
|
|
|
display_avrule(avrule,
|
|
|
|
&policydb, out_fp);
|
|
|
|
avrule = avrule->next;
|
|
|
|
}
|
|
|
|
cond = cond->next;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
|
2008-08-19 19:30:36 +00:00
|
|
|
avrule_t *avrule = decl->avrules;
|
|
|
|
if (avrule == NULL) {
|
|
|
|
fprintf(out_fp, " <empty>\n");
|
|
|
|
}
|
|
|
|
while (avrule != NULL) {
|
2011-11-03 20:54:25 +00:00
|
|
|
if (display_avrule(avrule, policy, out_fp))
|
2008-08-19 19:30:36 +00:00
|
|
|
return -1;
|
|
|
|
avrule = avrule->next;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{ /* role_type_node */
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_ROLE_TRANS:{
|
2008-08-19 19:30:36 +00:00
|
|
|
display_role_trans(decl->role_tr_rules, policy, out_fp);
|
|
|
|
break;
|
|
|
|
}
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_ROLE_ALLOW:{
|
2008-08-19 19:30:36 +00:00
|
|
|
display_role_allow(decl->role_allow_rules, policy,
|
|
|
|
out_fp);
|
|
|
|
break;
|
|
|
|
}
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_REQUIRES:{
|
2008-08-19 19:30:36 +00:00
|
|
|
if (display_scope_index
|
|
|
|
(&decl->required, policy, out_fp)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-03-28 17:39:03 +00:00
|
|
|
case DISPLAY_AVBLOCK_DECLARES:{
|
2008-08-19 19:30:36 +00:00
|
|
|
if (display_scope_index
|
|
|
|
(&decl->declared, policy, out_fp)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-03-28 18:00:19 +00:00
|
|
|
case DISPLAY_AVBLOCK_FILENAME_TRANS:
|
|
|
|
display_filename_trans(decl->filename_trans_rules, policy,
|
|
|
|
out_fp);
|
|
|
|
break;
|
2008-08-19 19:30:36 +00:00
|
|
|
default:{
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0; /* should never get here */
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_avblock(int field, policydb_t * policy,
|
2008-08-19 19:30:36 +00:00
|
|
|
FILE * out_fp)
|
|
|
|
{
|
|
|
|
avrule_block_t *block = policydb.global;
|
|
|
|
while (block != NULL) {
|
|
|
|
avrule_decl_t *decl = block->branch_list;
|
2021-07-06 17:54:26 +00:00
|
|
|
fprintf(out_fp, "--- begin avrule block ---\n");
|
2008-08-19 19:30:36 +00:00
|
|
|
while (decl != NULL) {
|
2011-11-03 20:54:25 +00:00
|
|
|
if (display_avdecl(decl, field, policy, out_fp)) {
|
2008-08-19 19:30:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
decl = decl->next;
|
|
|
|
}
|
|
|
|
block = block->next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int display_handle_unknown(policydb_t * p, FILE * out_fp)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
if (p->handle_unknown == ALLOW_UNKNOWN)
|
|
|
|
fprintf(out_fp, "Allow unknown classes and perms\n");
|
|
|
|
else if (p->handle_unknown == DENY_UNKNOWN)
|
|
|
|
fprintf(out_fp, "Deny unknown classes and perms\n");
|
|
|
|
else if (p->handle_unknown == REJECT_UNKNOWN)
|
|
|
|
fprintf(out_fp, "Reject unknown classes and perms\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int read_policy(char *filename, policydb_t * policy)
|
|
|
|
{
|
|
|
|
FILE *in_fp;
|
|
|
|
struct policy_file f;
|
|
|
|
int retval;
|
|
|
|
uint32_t buf[1];
|
|
|
|
|
|
|
|
if ((in_fp = fopen(filename, "rb")) == NULL) {
|
|
|
|
fprintf(stderr, "Can't open '%s': %s\n",
|
|
|
|
filename, strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
policy_file_init(&f);
|
|
|
|
f.type = PF_USE_STDIO;
|
|
|
|
f.fp = in_fp;
|
|
|
|
|
|
|
|
/* peek at the first byte. if they are indicative of a
|
|
|
|
package use the package reader, otherwise use the normal
|
|
|
|
policy reader */
|
|
|
|
if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
|
|
|
|
fprintf(stderr, "Could not read from policy.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
rewind(in_fp);
|
|
|
|
if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
|
|
|
|
sepol_module_package_t *package;
|
|
|
|
if (sepol_module_package_create(&package)) {
|
|
|
|
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
|
|
|
|
exit(1);
|
|
|
|
}
|
2021-09-15 13:11:30 +00:00
|
|
|
sepol_policydb_free(package->policy);
|
2008-08-19 19:30:36 +00:00
|
|
|
package->policy = (sepol_policydb_t *) policy;
|
|
|
|
package->file_contexts = NULL;
|
|
|
|
retval =
|
|
|
|
sepol_module_package_read(package,
|
|
|
|
(sepol_policy_file_t *) & f, 1);
|
2021-09-15 13:11:30 +00:00
|
|
|
package->policy = NULL;
|
|
|
|
sepol_module_package_free(package);
|
2008-08-19 19:30:36 +00:00
|
|
|
} else {
|
|
|
|
if (policydb_init(policy)) {
|
|
|
|
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
retval = policydb_read(policy, &f, 1);
|
|
|
|
}
|
|
|
|
fclose(in_fp);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void link_module(policydb_t * base, FILE * out_fp)
|
|
|
|
{
|
|
|
|
char module_name[80] = { 0 };
|
|
|
|
int ret;
|
|
|
|
policydb_t module, *mods = &module;
|
|
|
|
|
|
|
|
if (base->policy_type != POLICY_BASE) {
|
|
|
|
printf("Can only link if initial file was a base policy.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
printf("\nModule filename: ");
|
2015-02-26 08:22:48 +00:00
|
|
|
if (fgets(module_name, sizeof(module_name), stdin) == NULL) {
|
|
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
|
|
strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
module_name[strlen(module_name) - 1] = '\0'; /* remove LF */
|
|
|
|
if (module_name[0] == '\0') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read the binary policy */
|
|
|
|
fprintf(out_fp, "Reading module...\n");
|
|
|
|
if (read_policy(module_name, mods)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: error(s) encountered while loading policy\n",
|
|
|
|
module_name);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (module.policy_type != POLICY_MOD) {
|
|
|
|
fprintf(stderr, "This file is not a loadable policy module.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (policydb_index_classes(&module) ||
|
|
|
|
policydb_index_others(NULL, &module, 0)) {
|
|
|
|
fprintf(stderr, "Could not index module.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
ret = link_modules(NULL, base, &mods, 1, 0);
|
|
|
|
if (ret != 0) {
|
|
|
|
printf("Link failed (error %d)\n", ret);
|
|
|
|
printf("(You will probably need to restart dismod.)\n");
|
|
|
|
}
|
|
|
|
policydb_destroy(&module);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void display_policycaps(policydb_t * p, FILE * fp)
|
|
|
|
{
|
|
|
|
ebitmap_node_t *node;
|
|
|
|
const char *capname;
|
|
|
|
char buf[64];
|
2011-11-03 20:30:13 +00:00
|
|
|
unsigned int i;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
fprintf(fp, "policy capabilities:\n");
|
2019-05-14 08:14:16 +00:00
|
|
|
ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
|
|
|
|
capname = sepol_polcap_getname(i);
|
|
|
|
if (capname == NULL) {
|
2021-07-06 17:54:25 +00:00
|
|
|
snprintf(buf, sizeof(buf), "unknown (%u)", i);
|
2019-05-14 08:14:16 +00:00
|
|
|
capname = buf;
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
2019-05-14 08:14:16 +00:00
|
|
|
fprintf(fp, "\t%s\n", capname);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 17:54:32 +00:00
|
|
|
static int menu(void)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
printf("\nSelect a command:\n");
|
|
|
|
printf("1) display unconditional AVTAB\n");
|
|
|
|
printf("2) display conditional AVTAB\n");
|
|
|
|
printf("3) display users\n");
|
|
|
|
printf("4) display bools\n");
|
|
|
|
printf("5) display roles\n");
|
|
|
|
printf("6) display types, attributes, and aliases\n");
|
|
|
|
printf("7) display role transitions\n");
|
|
|
|
printf("8) display role allows\n");
|
|
|
|
printf("9) Display policycon\n");
|
|
|
|
printf("0) Display initial SIDs\n");
|
|
|
|
printf("\n");
|
|
|
|
printf("a) Display avrule requirements\n");
|
|
|
|
printf("b) Display avrule declarations\n");
|
|
|
|
printf("c) Display policy capabilities\n");
|
|
|
|
printf("l) Link in a module\n");
|
|
|
|
printf("u) Display the unknown handling setting\n");
|
2011-03-28 18:00:19 +00:00
|
|
|
printf("F) Display filename_trans rules\n");
|
2008-08-19 19:30:36 +00:00
|
|
|
printf("\n");
|
|
|
|
printf("f) set output file\n");
|
|
|
|
printf("m) display menu\n");
|
|
|
|
printf("q) quit\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
FILE *out_fp = stdout;
|
|
|
|
char ans[81], OutfileName[121];
|
|
|
|
|
|
|
|
if (argc != 2)
|
|
|
|
usage(argv[0]);
|
|
|
|
|
|
|
|
/* read the binary policy */
|
|
|
|
fprintf(out_fp, "Reading policy...\n");
|
2012-11-29 13:53:33 +00:00
|
|
|
if (policydb_init(&policydb)) {
|
|
|
|
fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__);
|
|
|
|
exit(1);
|
|
|
|
}
|
2008-08-19 19:30:36 +00:00
|
|
|
if (read_policy(argv[1], &policydb)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: error(s) encountered while loading policy\n",
|
|
|
|
argv[0]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (policydb.policy_type != POLICY_BASE &&
|
|
|
|
policydb.policy_type != POLICY_MOD) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"This file is neither a base nor loadable policy module.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (policydb_index_classes(&policydb)) {
|
|
|
|
fprintf(stderr, "Error indexing classes\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (policydb_index_others(NULL, &policydb, 1)) {
|
|
|
|
fprintf(stderr, "Error indexing others\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (policydb.policy_type == POLICY_BASE) {
|
2019-04-17 16:37:31 +00:00
|
|
|
printf("Binary base policy file loaded.\n");
|
2008-08-19 19:30:36 +00:00
|
|
|
} else {
|
|
|
|
printf("Binary policy module file loaded.\n");
|
|
|
|
printf("Module name: %s\n", policydb.name);
|
|
|
|
printf("Module version: %s\n", policydb.version);
|
|
|
|
}
|
|
|
|
|
2019-04-17 16:37:31 +00:00
|
|
|
printf("Policy version: %d\n\n", policydb.policyvers);
|
2008-08-19 19:30:36 +00:00
|
|
|
menu();
|
|
|
|
for (;;) {
|
|
|
|
printf("\nCommand (\'m\' for menu): ");
|
2015-02-26 08:22:48 +00:00
|
|
|
if (fgets(ans, sizeof(ans), stdin) == NULL) {
|
|
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
|
|
strerror(errno));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
switch (ans[0]) {
|
|
|
|
|
2011-03-28 17:39:03 +00:00
|
|
|
case '1':
|
|
|
|
fprintf(out_fp, "unconditional avtab:\n");
|
|
|
|
display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
|
2011-11-03 20:54:25 +00:00
|
|
|
&policydb, out_fp);
|
2011-03-28 17:39:03 +00:00
|
|
|
break;
|
2008-08-19 19:30:36 +00:00
|
|
|
case '2':
|
|
|
|
fprintf(out_fp, "conditional avtab:\n");
|
2011-03-28 17:39:03 +00:00
|
|
|
display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
|
2011-11-03 20:54:25 +00:00
|
|
|
&policydb, out_fp);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case '3':
|
|
|
|
display_users(&policydb, out_fp);
|
|
|
|
break;
|
|
|
|
case '4':
|
|
|
|
display_bools(&policydb, out_fp);
|
|
|
|
break;
|
|
|
|
case '5':
|
|
|
|
if (hashtab_map
|
|
|
|
(policydb.p_roles.table, role_display_callback,
|
|
|
|
out_fp))
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
case '6':
|
|
|
|
if (display_types(&policydb, out_fp)) {
|
|
|
|
fprintf(stderr, "Error displaying types\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '7':
|
|
|
|
fprintf(out_fp, "role transitions:\n");
|
2011-11-03 20:54:25 +00:00
|
|
|
display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS,
|
2011-03-28 17:39:03 +00:00
|
|
|
&policydb, out_fp);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
fprintf(out_fp, "role allows:\n");
|
2011-11-03 20:54:25 +00:00
|
|
|
display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW,
|
2011-03-28 17:39:03 +00:00
|
|
|
&policydb, out_fp);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case '9':
|
2011-11-03 20:54:25 +00:00
|
|
|
display_policycon(out_fp);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
display_initial_sids(&policydb, out_fp);
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
fprintf(out_fp, "avrule block requirements:\n");
|
2011-11-03 20:54:25 +00:00
|
|
|
display_avblock(DISPLAY_AVBLOCK_REQUIRES,
|
2011-03-28 17:39:03 +00:00
|
|
|
&policydb, out_fp);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
fprintf(out_fp, "avrule block declarations:\n");
|
2011-11-03 20:54:25 +00:00
|
|
|
display_avblock(DISPLAY_AVBLOCK_DECLARES,
|
2011-03-28 17:39:03 +00:00
|
|
|
&policydb, out_fp);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
display_policycaps(&policydb, out_fp);
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
case 'U':
|
|
|
|
display_handle_unknown(&policydb, out_fp);
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
printf
|
|
|
|
("\nFilename for output (<CR> for screen output): ");
|
2015-02-26 08:22:48 +00:00
|
|
|
if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
|
|
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
|
|
strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
2008-08-19 19:30:36 +00:00
|
|
|
OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */
|
|
|
|
if (strlen(OutfileName) == 0)
|
|
|
|
out_fp = stdout;
|
|
|
|
else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
|
|
|
|
fprintf(stderr, "Cannot open output file %s\n",
|
|
|
|
OutfileName);
|
|
|
|
out_fp = stdout;
|
|
|
|
}
|
|
|
|
if (out_fp != stdout)
|
|
|
|
printf("\nOutput to file: %s\n", OutfileName);
|
|
|
|
break;
|
2011-03-28 18:00:19 +00:00
|
|
|
case 'F':
|
|
|
|
fprintf(out_fp, "filename_trans rules:\n");
|
|
|
|
display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
|
2011-11-03 20:54:25 +00:00
|
|
|
&policydb, out_fp);
|
2011-03-28 18:00:19 +00:00
|
|
|
break;
|
2008-08-19 19:30:36 +00:00
|
|
|
case 'l':
|
|
|
|
link_module(&policydb, out_fp);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
policydb_destroy(&policydb);
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
menu();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("\nInvalid choice\n");
|
|
|
|
menu();
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|