@@ -759,10 +759,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */
#define POLICYDB_VERSION_GLBLUB 32
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
+#define POLICYDB_VERSION_COND_XPERMS 34 /* extended permissions in conditional policies */
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4
@@ -785,9 +786,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define MOD_POLICYDB_VERSION_INFINIBAND 19
#define MOD_POLICYDB_VERSION_GLBLUB 20
#define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21
+#define MOD_POLICYDB_VERSION_COND_XPERMS 22
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SELF_TYPETRANS
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_COND_XPERMS
#define POLICYDB_CONFIG_MLS 1
@@ -801,6 +803,12 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
((p)->policy_type != POLICY_KERN \
&& (p)->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY))
+#define policydb_has_cond_xperms_feature(p) \
+ (((p)->policy_type == POLICY_KERN \
+ && (p)->policyvers >= POLICYDB_VERSION_COND_XPERMS) || \
+ ((p)->policy_type != POLICY_KERN \
+ && (p)->policyvers >= MOD_POLICYDB_VERSION_COND_XPERMS))
+
/* the config flags related to unknown classes/perms are bits 2 and 3 */
#define DENY_UNKNOWN SEPOL_DENY_UNKNOWN
#define REJECT_UNKNOWN SEPOL_REJECT_UNKNOWN
@@ -33,8 +33,8 @@ struct avtab_match_args {
sepol_handle_t *handle;
policydb_t *p;
const avrule_t *narule;
- avtab_t *avtab;
unsigned long errors;
+ bool conditional;
};
static const char* policy_name(const policydb_t *p) {
@@ -152,12 +152,19 @@ static void extended_permissions_violated(avtab_extended_perms_t *result,
}
}
+static bool match_node_key(const struct avtab_node *node, const avtab_key_t *key)
+{
+ return node->key.source_type == key->source_type
+ && node->key.target_type == key->target_type
+ && node->key.target_class == key->target_class;
+}
+
/* Same scenarios of interest as check_assertion_extended_permissions */
static int report_assertion_extended_permissions(sepol_handle_t *handle,
policydb_t *p, const avrule_t *narule,
unsigned int stype, unsigned int ttype,
const class_perm_node_t *curperm, uint32_t perms,
- const avtab_key_t *k, avtab_t *avtab)
+ const avtab_key_t *k, bool conditional)
{
avtab_ptr_t node;
avtab_key_t tmp_key;
@@ -167,7 +174,7 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle,
const ebitmap_t *tattr = &p->type_attr_map[ttype];
ebitmap_node_t *snode, *tnode;
unsigned int i, j;
- bool found_xperm = false;
+ bool found_xperm = false, found_cond_conflict = false;
int errors = 0;
memcpy(&tmp_key, k, sizeof(avtab_key_t));
@@ -177,7 +184,7 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle,
tmp_key.source_type = i + 1;
ebitmap_for_each_positive_bit(tattr, tnode, j) {
tmp_key.target_type = j + 1;
- for (node = avtab_search_node(avtab, &tmp_key);
+ for (node = avtab_search_node(&p->te_avtab, &tmp_key);
node;
node = avtab_search_node_next(node, tmp_key.specified)) {
xperms = node->datum.xperms;
@@ -205,11 +212,105 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle,
errors++;
}
}
+
+ for (const cond_list_t *cl = p->cond_list; cl; cl = cl->next) {
+ bool found_true_base = false, found_true_xperm = false;
+ bool found_false_base = false, found_false_xperm = false;
+
+ for (const cond_av_list_t *cal = cl->true_list; cal; cal = cal->next) {
+ node = cal->node; /* node->next is not from the same condition */
+ if (!node)
+ continue;
+
+ if (!match_node_key(node, &tmp_key))
+ continue;
+
+ if (match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) {
+ found_true_base = true;
+ continue;
+ }
+
+ if (!(node->key.specified & AVTAB_XPERMS_ALLOWED))
+ continue;
+
+ xperms = node->datum.xperms;
+ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
+ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
+ && (xperms->specified != AVTAB_XPERMS_NLMSG))
+ continue;
+ found_true_xperm = true;
+ /* failure on the extended permission check_extended_permissions */
+ if (check_extended_permissions(narule->xperms, xperms)) {
+ char *permstring;
+
+ extended_permissions_violated(&error, narule->xperms, xperms);
+ permstring = sepol_extended_perms_to_string(&error);
+
+ ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
+ "allowxperm %s %s:%s %s;",
+ narule->source_line, narule->source_filename, narule->line, policy_name(p),
+ p->p_type_val_to_name[i],
+ p->p_type_val_to_name[j],
+ p->p_class_val_to_name[curperm->tclass - 1],
+ permstring ?: "<format-failure>");
+
+ free(permstring);
+ errors++;
+ }
+ }
+
+ for (const cond_av_list_t *cal = cl->false_list; cal; cal = cal->next) {
+ node = cal->node; /* node->next is not from the same condition */
+ if (!node)
+ continue;
+
+ if (!match_node_key(node, &tmp_key))
+ continue;
+
+ if (match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) {
+ found_false_base = true;
+ continue;
+ }
+
+ if (!(node->key.specified & AVTAB_XPERMS_ALLOWED))
+ continue;
+
+ xperms = node->datum.xperms;
+ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
+ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
+ && (xperms->specified != AVTAB_XPERMS_NLMSG))
+ continue;
+ found_false_xperm = true;
+ /* failure on the extended permission check_extended_permissions */
+ if (check_extended_permissions(narule->xperms, xperms)) {
+ char *permstring;
+
+ extended_permissions_violated(&error, narule->xperms, xperms);
+ permstring = sepol_extended_perms_to_string(&error);
+
+ ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
+ "allowxperm %s %s:%s %s;",
+ narule->source_line, narule->source_filename, narule->line, policy_name(p),
+ p->p_type_val_to_name[i],
+ p->p_type_val_to_name[j],
+ p->p_class_val_to_name[curperm->tclass - 1],
+ permstring ?: "<format-failure>");
+
+ free(permstring);
+ errors++;
+ }
+ }
+
+ if (found_true_xperm && found_false_xperm)
+ found_xperm = true;
+ else if (conditional && ((found_true_base && !found_true_xperm) || (found_false_base && !found_false_xperm)))
+ found_cond_conflict = true;
+ }
}
}
- /* failure on the regular permissions */
- if (!found_xperm) {
+ if ((!found_xperm && !conditional) || found_cond_conflict) {
+ /* failure on the regular permissions */
char *permstr = sepol_av_to_string(p, curperm->tclass, perms);
ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
@@ -222,7 +323,6 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle,
free(permstr);
errors++;
-
}
return errors;
@@ -234,7 +334,6 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void
struct avtab_match_args *a = (struct avtab_match_args *)args;
sepol_handle_t *handle = a->handle;
policydb_t *p = a->p;
- avtab_t *avtab = a->avtab;
const avrule_t *narule = a->narule;
const class_perm_node_t *cp;
uint32_t perms;
@@ -308,7 +407,8 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void
continue;
if (narule->specified == AVRULE_XPERMS_NEVERALLOW) {
a->errors += report_assertion_extended_permissions(handle,p, narule,
- i, j, cp, perms, k, avtab);
+ i, j, cp, perms, k,
+ a->conditional);
} else {
a->errors++;
report_failure(handle, p, narule, i, j, cp, perms);
@@ -335,12 +435,12 @@ static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, cons
.errors = 0,
};
- args.avtab = &p->te_avtab;
+ args.conditional = false;
rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
if (rc < 0)
goto oom;
- args.avtab = &p->te_cond_avtab;
+ args.conditional = true;
rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
if (rc < 0)
goto oom;
@@ -355,9 +455,10 @@ oom:
* Look up the extended permissions in avtab and verify that neverallowed
* permissions are not granted.
*/
-static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, avtab_t *avtab,
+static bool check_assertion_extended_permissions_avtab(const avrule_t *narule,
unsigned int stype, unsigned int ttype,
- const avtab_key_t *k, policydb_t *p)
+ const avtab_key_t *k, policydb_t *p,
+ bool conditional)
{
avtab_ptr_t node;
avtab_key_t tmp_key;
@@ -367,7 +468,7 @@ static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, a
const ebitmap_t *tattr = &p->type_attr_map[ttype];
ebitmap_node_t *snode, *tnode;
unsigned int i, j;
- bool ret = true;
+ bool found_xperm = false, found_cond_conflict = false;
memcpy(&tmp_key, k, sizeof(avtab_key_t));
tmp_key.specified = AVTAB_XPERMS_ALLOWED;
@@ -376,7 +477,7 @@ static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, a
tmp_key.source_type = i + 1;
ebitmap_for_each_positive_bit(tattr, tnode, j) {
tmp_key.target_type = j + 1;
- for (node = avtab_search_node(avtab, &tmp_key);
+ for (node = avtab_search_node(&p->te_avtab, &tmp_key);
node;
node = avtab_search_node_next(node, tmp_key.specified)) {
xperms = node->datum.xperms;
@@ -385,14 +486,78 @@ static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, a
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
&& (xperms->specified != AVTAB_XPERMS_NLMSG))
continue;
- ret = check_extended_permissions(neverallow_xperms, xperms);
- if (ret)
- return ret;
+ found_xperm = true;
+ if (check_extended_permissions(neverallow_xperms, xperms))
+ return true;
+ }
+
+ for (const cond_list_t *cl = p->cond_list; cl; cl = cl->next) {
+ bool found_true_base = false, found_true_xperm = false;
+ bool found_false_base = false, found_false_xperm = false;
+
+ for (const cond_av_list_t *cal = cl->true_list; cal; cal = cal->next) {
+ node = cal->node; /* node->next is not from the same condition */
+ if (!node)
+ continue;
+
+ if (!match_node_key(node, &tmp_key))
+ continue;
+
+ if ((node->key.specified & AVTAB_ALLOWED) && match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) {
+ found_true_base = true;
+ continue;
+ }
+
+ if (!(node->key.specified & AVTAB_XPERMS_ALLOWED))
+ continue;
+
+ xperms = node->datum.xperms;
+
+ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
+ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
+ && (xperms->specified != AVTAB_XPERMS_NLMSG))
+ continue;
+ found_true_xperm = true;
+ if (check_extended_permissions(neverallow_xperms, xperms))
+ return true;
+ }
+
+ for (const cond_av_list_t *cal = cl->false_list; cal; cal = cal->next) {
+ node = cal->node; /* node->next is not from the same condition */
+ if (!node)
+ continue;
+
+ if (!match_node_key(node, &tmp_key))
+ continue;
+
+ if ((node->key.specified & AVTAB_ALLOWED) && match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) {
+ found_false_base = true;
+ continue;
+ }
+
+ if (!(node->key.specified & AVTAB_XPERMS_ALLOWED))
+ continue;
+
+ xperms = node->datum.xperms;
+
+ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
+ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
+ && (xperms->specified != AVTAB_XPERMS_NLMSG))
+ continue;
+ found_false_xperm = true;
+ if (check_extended_permissions(neverallow_xperms, xperms))
+ return true;
+ }
+
+ if (found_true_xperm && found_false_xperm)
+ found_xperm = true;
+ else if (conditional && ((found_true_base && !found_true_xperm) || (found_false_base && !found_false_xperm)))
+ found_cond_conflict = true;
}
}
}
- return ret;
+ return (!conditional && !found_xperm) || found_cond_conflict;
}
/*
@@ -411,8 +576,9 @@ static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, a
* 4. FAIL - The ioctl permission is granted AND the extended permission is
* granted
*/
-static int check_assertion_extended_permissions(const avrule_t *narule, avtab_t *avtab,
- const avtab_key_t *k, policydb_t *p)
+static int check_assertion_extended_permissions(const avrule_t *narule,
+ const avtab_key_t *k, policydb_t *p,
+ bool conditional)
{
ebitmap_t src_matches, tgt_matches, self_matches;
unsigned int i, j;
@@ -474,7 +640,7 @@ static int check_assertion_extended_permissions(const avrule_t *narule, avtab_t
continue;
if (is_narule_notself && i == j)
continue;
- if (check_assertion_extended_permissions_avtab(narule, avtab, i, j, k, p)) {
+ if (check_assertion_extended_permissions_avtab(narule, i, j, k, p, conditional)) {
rc = 1;
goto exit;
}
@@ -578,7 +744,6 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a
struct avtab_match_args *a = (struct avtab_match_args *)args;
policydb_t *p = a->p;
const avrule_t *narule = a->narule;
- avtab_t *avtab = a->avtab;
if ((k->specified & AVTAB_ALLOWED) == 0)
goto nomatch;
@@ -611,7 +776,7 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a
}
if (narule->specified == AVRULE_XPERMS_NEVERALLOW) {
- rc = check_assertion_extended_permissions(narule, avtab, k, p);
+ rc = check_assertion_extended_permissions(narule, k, p, a->conditional);
if (rc < 0)
goto oom;
if (rc == 0)
@@ -636,11 +801,11 @@ int check_assertion(policydb_t *p, const avrule_t *narule)
.errors = 0,
};
- args.avtab = &p->te_avtab;
+ args.conditional = false;
rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
if (rc == 0) {
- args.avtab = &p->te_cond_avtab;
+ args.conditional = true;
rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args);
}
@@ -208,6 +208,13 @@ static const struct policydb_compat_info policydb_compat[] = {
.ocon_num = OCON_IBENDPORT + 1,
.target_platform = SEPOL_TARGET_SELINUX,
},
+ {
+ .type = POLICY_KERN,
+ .version = POLICYDB_VERSION_COND_XPERMS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_IBENDPORT + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
{
.type = POLICY_BASE,
.version = MOD_POLICYDB_VERSION_BASE,
@@ -334,6 +341,13 @@ static const struct policydb_compat_info policydb_compat[] = {
.ocon_num = OCON_IBENDPORT + 1,
.target_platform = SEPOL_TARGET_SELINUX,
},
+ {
+ .type = POLICY_BASE,
+ .version = MOD_POLICYDB_VERSION_COND_XPERMS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_IBENDPORT + 1,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
{
.type = POLICY_MOD,
.version = MOD_POLICYDB_VERSION_BASE,
@@ -460,6 +474,13 @@ static const struct policydb_compat_info policydb_compat[] = {
.ocon_num = 0,
.target_platform = SEPOL_TARGET_SELINUX,
},
+ {
+ .type = POLICY_MOD,
+ .version = MOD_POLICYDB_VERSION_COND_XPERMS,
+ .sym_num = SYM_NUM,
+ .ocon_num = 0,
+ .target_platform = SEPOL_TARGET_SELINUX,
+ },
};
#if 0
@@ -22,6 +22,7 @@ typedef struct map_arg {
validate_t *flavors;
sepol_handle_t *handle;
const policydb_t *policy;
+ int conditional;
} map_arg_t;
typedef struct perm_arg {
@@ -837,7 +838,7 @@ static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum
static int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
{
- map_arg_t margs = { flavors, handle, p };
+ map_arg_t margs = { flavors, handle, p, 0 };
if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs))
goto bad;
@@ -903,7 +904,7 @@ static int validate_avtab_key(const avtab_key_t *key, int conditional, const pol
case AVTAB_XPERMS_DONTAUDIT:
if (p->target_platform != SEPOL_TARGET_SELINUX)
goto bad;
- if (conditional)
+ if (conditional && !policydb_has_cond_xperms_feature(p))
goto bad;
break;
default:
@@ -956,7 +957,7 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *
{
map_arg_t *margs = args;
- if (validate_avtab_key(k, 0, margs->policy, margs->flavors))
+ if (validate_avtab_key(k, margs->conditional, margs->policy, margs->flavors))
return -1;
if (k->specified & AVTAB_AV) {
@@ -972,15 +973,23 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *
if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors))
return -1;
- if ((k->specified & AVTAB_XPERMS) && validate_xperms(d->xperms))
- return -1;
+ if (k->specified & AVTAB_XPERMS) {
+ uint32_t data = d->data;
+
+ /* checkpolicy does not touch data for xperms, CIL sets it. */
+ if (data != 0 && validate_access_vector(margs->handle, margs->policy, k->target_class, data))
+ return -1;
+
+ if (validate_xperms(d->xperms))
+ return -1;
+ }
return 0;
}
static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const policydb_t *p, validate_t flavors[])
{
- map_arg_t margs = { flavors, handle, p };
+ map_arg_t margs = { flavors, handle, p, 0 };
if (avtab_map(avtab, validate_avtab_key_and_datum, &margs)) {
ERR(handle, "Invalid avtab");
@@ -992,28 +1001,13 @@ static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const po
static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, const policydb_t *p, validate_t flavors[])
{
- const struct avtab_node *avtab_ptr;
-
- for (; cond_av; cond_av = cond_av->next) {
- for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) {
- const avtab_key_t *key = &avtab_ptr->key;
- const avtab_datum_t *datum = &avtab_ptr->datum;
+ struct avtab_node *avtab_ptr;
+ map_arg_t margs = { flavors, handle, p, 1 };
- if (validate_avtab_key(key, 1, p, flavors))
+ for (; cond_av; cond_av = cond_av->next)
+ for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next)
+ if (validate_avtab_key_and_datum(&avtab_ptr->key, &avtab_ptr->datum, &margs))
goto bad;
- if (key->specified & AVTAB_AV) {
- uint32_t data = datum->data;
-
- if ((0xFFF & key->specified) == AVTAB_AUDITDENY)
- data = ~data;
-
- if (validate_access_vector(handle, p, key->target_class, data))
- goto bad;
- }
- if ((key->specified & AVTAB_TYPE) && validate_simpletype(datum->data, p, flavors))
- goto bad;
- }
- }
return 0;
@@ -1046,7 +1040,7 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int
case AVRULE_XPERMS_AUDITALLOW:
case AVRULE_XPERMS_DONTAUDIT:
case AVRULE_XPERMS_NEVERALLOW:
- if (conditional)
+ if (conditional && !policydb_has_cond_xperms_feature(p))
goto bad;
break;
default:
@@ -1278,7 +1272,7 @@ bad:
static int validate_filename_trans_hashtab(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
{
- map_arg_t margs = { flavors, handle, p };
+ map_arg_t margs = { flavors, handle, p, 0 };
if (hashtab_map(p->filename_trans, validate_filename_trans, &margs)) {
ERR(handle, "Invalid filename trans");
@@ -1631,7 +1625,7 @@ bad:
static int validate_range_transitions(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
{
- map_arg_t margs = { flavors, handle, p };
+ map_arg_t margs = { flavors, handle, p, 0 };
if (hashtab_map(p->range_tr, validate_range_transition, &margs)) {
ERR(handle, "Invalid range transition");
@@ -56,7 +56,8 @@ struct policy_data {
};
static int avrule_write_list(policydb_t *p,
- avrule_t * avrules, struct policy_file *fp);
+ avrule_t * avrules, struct policy_file *fp,
+ unsigned conditional);
static int ebitmap_write(ebitmap_t * e, struct policy_file *fp)
{
@@ -104,7 +105,8 @@ static uint16_t spec_order[] = {
static int avtab_write_item(policydb_t * p,
avtab_ptr_t cur, struct policy_file *fp,
- unsigned merge, unsigned commit, uint32_t * nel)
+ unsigned merge, unsigned commit, unsigned conditional,
+ uint32_t * nel)
{
avtab_ptr_t node;
uint8_t buf8;
@@ -229,14 +231,20 @@ static int avtab_write_item(policydb_t * p,
return POLICYDB_ERROR;
if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) &&
(cur->key.specified & AVTAB_XPERMS)) {
- ERR(fp->handle, "policy version %u does not support ioctl extended"
+ ERR(fp->handle, "policy version %u does not support extended"
"permissions rules and one was specified", p->policyvers);
return POLICYDB_ERROR;
}
+ if (!policydb_has_cond_xperms_feature(p) && (cur->key.specified & AVTAB_XPERMS) && conditional) {
+ ERR(fp->handle, "policy version %u does not support extended"
+ "permissions rules in conditional policies and one was specified", p->policyvers);
+ return POLICYDB_ERROR;
+ }
+
if (p->target_platform != SEPOL_TARGET_SELINUX &&
(cur->key.specified & AVTAB_XPERMS)) {
- ERR(fp->handle, "Target platform %s does not support ioctl "
+ ERR(fp->handle, "Target platform %s does not support "
"extended permissions rules and one was specified",
policydb_target_strings[p->target_platform]);
return POLICYDB_ERROR;
@@ -313,7 +321,7 @@ static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp)
for (cur = a->htable[i]; cur; cur = cur->next) {
/* If old format, compute final nel.
If new format, write out the items. */
- if (avtab_write_item(p, cur, fp, 1, !oldvers, &nel)) {
+ if (avtab_write_item(p, cur, fp, 1, !oldvers, 0, &nel)) {
rc = -1;
goto out;
}
@@ -332,7 +340,7 @@ static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp)
avtab_reset_merged(a);
for (i = 0; i < a->nslot; i++) {
for (cur = a->htable[i]; cur; cur = cur->next) {
- if (avtab_write_item(p, cur, fp, 1, 1, NULL)) {
+ if (avtab_write_item(p, cur, fp, 1, 1, 0, NULL)) {
rc = -1;
goto out;
}
@@ -795,7 +803,7 @@ static int cond_write_av_list(policydb_t * p,
for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
if (cur_list->node->parse_context)
- if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL))
+ if (avtab_write_item(p, cur_list->node, fp, 0, 1, 1, NULL))
goto out;
}
@@ -846,9 +854,9 @@ static int cond_write_node(policydb_t * p,
if (cond_write_av_list(p, node->false_list, fp) != 0)
return POLICYDB_ERROR;
} else {
- if (avrule_write_list(p, node->avtrue_list, fp))
+ if (avrule_write_list(p, node->avtrue_list, fp, 1))
return POLICYDB_ERROR;
- if (avrule_write_list(p, node->avfalse_list, fp))
+ if (avrule_write_list(p, node->avfalse_list, fp, 1))
return POLICYDB_ERROR;
}
@@ -1743,7 +1751,7 @@ static int range_write(policydb_t * p, struct policy_file *fp)
/************** module writing functions below **************/
static int avrule_write(policydb_t *p, avrule_t * avrule,
- struct policy_file *fp)
+ struct policy_file *fp, unsigned conditional)
{
size_t items, items2;
uint32_t buf[32], len;
@@ -1801,15 +1809,23 @@ static int avrule_write(policydb_t *p, avrule_t * avrule,
if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
ERR(fp->handle,
- "module policy version %u does not support ioctl"
+ "module policy version %u does not support"
" extended permissions rules and one was specified",
p->policyvers);
return POLICYDB_ERROR;
}
+ if (conditional && !policydb_has_cond_xperms_feature(p)) {
+ ERR(fp->handle,
+ "module policy version %u does not support"
+ " extended permissions rules in conditional policies and one was specified",
+ p->policyvers);
+ return POLICYDB_ERROR;
+ }
+
if (p->target_platform != SEPOL_TARGET_SELINUX) {
ERR(fp->handle,
- "Target platform %s does not support ioctl"
+ "Target platform %s does not support"
" extended permissions rules and one was specified",
policydb_target_strings[p->target_platform]);
return POLICYDB_ERROR;
@@ -1834,7 +1850,7 @@ static int avrule_write(policydb_t *p, avrule_t * avrule,
}
static int avrule_write_list(policydb_t *p, avrule_t * avrules,
- struct policy_file *fp)
+ struct policy_file *fp, unsigned conditional)
{
uint32_t buf[32], len;
avrule_t *avrule;
@@ -1852,7 +1868,7 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules,
avrule = avrules;
while (avrule) {
- if (avrule_write(p, avrule, fp))
+ if (avrule_write(p, avrule, fp, conditional))
return POLICYDB_ERROR;
avrule = avrule->next;
}
@@ -2056,7 +2072,7 @@ static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
return POLICYDB_ERROR;
}
if (cond_write_list(p, decl->cond_list, fp) == -1 ||
- avrule_write_list(p, decl->avrules, fp) == -1 ||
+ avrule_write_list(p, decl->avrules, fp, 0) == -1 ||
role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
return POLICYDB_ERROR;