@@ -1859,6 +1859,8 @@ int define_bool_tunable(int is_tunable)
avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
{
+ avrule_t *last;
+
if (pass == 1) {
/* return something so we get through pass 1 */
return (avrule_t *) 1;
@@ -1869,8 +1871,12 @@ avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
return avlist;
}
- /* prepend the new avlist to the pre-existing one */
- sl->next = avlist;
+ /* Prepend the new avlist to the pre-existing one.
+ * An extended permission statement might consist of multiple av
+ * rules. */
+ for (last = sl; last->next; last = last->next)
+ ;
+ last->next = avlist;
return sl;
}
@@ -1972,7 +1978,7 @@ static int avrule_read_xperm_ranges(struct av_xperm_range_list **rangehead)
id = queue_remove(id_queue);
r->range.high = (uint16_t) strtoul(id,NULL,0);
if (r->range.high < r->range.low) {
- yyerror2("Ioctl range %d-%d must be in ascending order.",
+ yyerror2("extended permission range %#x-%#x must be in ascending order.",
r->range.low, r->range.high);
return -1;
}
@@ -2454,9 +2460,9 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src)
return 0;
}
-static int define_te_avtab_ioctl(const avrule_t *avrule_template)
+static int define_te_avtab_ioctl(const avrule_t *avrule_template, avrule_t **ret_avrules)
{
- avrule_t *avrule;
+ avrule_t *avrule, *ret = NULL, **last = &ret;
struct av_xperm_range_list *rangelist, *r;
av_extended_perms_t *complete_driver, *partial_driver, *xperms;
unsigned int i;
@@ -2478,7 +2484,13 @@ static int define_te_avtab_ioctl(const avrule_t *avrule_template)
if (avrule_cpy(avrule, avrule_template))
return -1;
avrule->xperms = complete_driver;
- append_avrule(avrule);
+
+ if (ret_avrules) {
+ *last = avrule;
+ last = &(avrule->next);
+ } else {
+ append_avrule(avrule);
+ }
}
/* flag ioctl driver codes that are partially enabled */
@@ -2507,7 +2519,13 @@ static int define_te_avtab_ioctl(const avrule_t *avrule_template)
if (avrule_cpy(avrule, avrule_template))
return -1;
avrule->xperms = xperms;
- append_avrule(avrule);
+
+ if (ret_avrules) {
+ *last = avrule;
+ last = &(avrule->next);
+ } else {
+ append_avrule(avrule);
+ }
}
}
@@ -2521,12 +2539,15 @@ done:
free(r);
}
+ if (ret_avrules)
+ *ret_avrules = ret;
+
return 0;
}
-static int define_te_avtab_netlink(const avrule_t *avrule_template)
+static int define_te_avtab_netlink(const avrule_t *avrule_template, avrule_t **ret_avrules)
{
- avrule_t *avrule;
+ avrule_t *avrule, *ret = NULL, **last = &ret;
struct av_xperm_range_list *rangelist, *r;
av_extended_perms_t *partial_driver, *xperms;
unsigned int i;
@@ -2561,7 +2582,13 @@ static int define_te_avtab_netlink(const avrule_t *avrule_template)
if (avrule_cpy(avrule, avrule_template))
return -1;
avrule->xperms = xperms;
- append_avrule(avrule);
+
+ if (ret_avrules) {
+ *last = avrule;
+ last = &(avrule->next);
+ } else {
+ append_avrule(avrule);
+ }
}
}
@@ -2575,9 +2602,64 @@ done:
free(r);
}
+ if (ret_avrules)
+ *ret_avrules = ret;
+
return 0;
}
+avrule_t *define_cond_te_avtab_extended_perms(int which)
+{
+ char *id;
+ unsigned int i;
+ avrule_t *avrule_template, *rules = NULL;
+ int rc = 0;
+
+ if (policydbp->policy_type == POLICY_KERN && policydbp->policyvers < POLICYDB_VERSION_COND_XPERMS) {
+ yyerror2("extended permissions in conditional policies are only supported since policy version %d, found policy version %d",
+ POLICYDB_VERSION_COND_XPERMS, policydbp->policyvers);
+ return COND_ERR;
+ }
+ if (policydbp->policy_type != POLICY_KERN && policydbp->policyvers < MOD_POLICYDB_VERSION_COND_XPERMS) {
+ yyerror2("extended permissions in conditional policies are only supported since module policy version %d, found module policy version %d",
+ MOD_POLICYDB_VERSION_COND_XPERMS, policydbp->policyvers);
+ return COND_ERR;
+ }
+
+ if (pass == 1) {
+ for (i = 0; i < 4; i++) {
+ while ((id = queue_remove(id_queue)))
+ free(id);
+ }
+ return (avrule_t *) 1; /* any non-NULL value */
+ }
+
+ /* populate avrule template with source/target/tclass */
+ if (define_te_avtab_xperms_helper(which, &avrule_template))
+ return COND_ERR;
+
+ id = queue_remove(id_queue);
+ if (strcmp(id, "ioctl") == 0) {
+ rc = define_te_avtab_ioctl(avrule_template, &rules);
+ } else if (strcmp(id, "nlmsg") == 0) {
+ rc = define_te_avtab_netlink(avrule_template, &rules);
+ } else {
+ yyerror2("only ioctl and nlmsg extended permissions are supported, found %s", id);
+ rc = -1;
+ }
+
+ free(id);
+ avrule_destroy(avrule_template);
+ free(avrule_template);
+
+ if (rc) {
+ avrule_destroy(rules);
+ return NULL;
+ }
+
+ return rules;
+}
+
int define_te_avtab_extended_perms(int which)
{
char *id;
@@ -2599,11 +2681,11 @@ int define_te_avtab_extended_perms(int which)
id = queue_remove(id_queue);
if (strcmp(id,"ioctl") == 0) {
- rc = define_te_avtab_ioctl(avrule_template);
+ rc = define_te_avtab_ioctl(avrule_template, NULL);
} else if (strcmp(id,"nlmsg") == 0) {
- rc = define_te_avtab_netlink(avrule_template);
+ rc = define_te_avtab_netlink(avrule_template, NULL);
} else {
- yyerror2("only ioctl extended permissions are supported, found %s", id);
+ yyerror2("only ioctl and nlmsg extended permissions are supported, found %s", id);
rc = -1;
}
@@ -15,6 +15,7 @@
avrule_t *define_cond_compute_type(int which);
avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *sl);
avrule_t *define_cond_te_avtab(int which);
+avrule_t *define_cond_te_avtab_extended_perms(int which);
avrule_t *define_cond_filename_trans(void);
cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2);
int define_attrib(void);
@@ -74,6 +74,7 @@ typedef int (* require_func_t)(int pass);
%type <ptr> cond_expr cond_expr_prim cond_pol_list cond_else
%type <ptr> cond_allow_def cond_auditallow_def cond_auditdeny_def cond_dontaudit_def
+%type <ptr> cond_xperm_allow_def cond_xperm_auditallow_def cond_xperm_dontaudit_def
%type <ptr> cond_transition_def cond_te_avtab_def cond_rule_def
%type <valptr> cexpr cexpr_prim op role_mls_op
%type <val> ipv4_addr_def number
@@ -432,6 +433,12 @@ cond_te_avtab_def : cond_allow_def
{ $$ = $1; }
| cond_dontaudit_def
{ $$ = $1; }
+ | cond_xperm_allow_def
+ { $$ = $1; }
+ | cond_xperm_auditallow_def
+ { $$ = $1; }
+ | cond_xperm_dontaudit_def
+ { $$ = $1; }
;
cond_allow_def : ALLOW names names ':' names names ';'
{ $$ = define_cond_te_avtab(AVRULE_ALLOWED) ;
@@ -449,7 +456,18 @@ cond_dontaudit_def : DONTAUDIT names names ':' names names ';'
{ $$ = define_cond_te_avtab(AVRULE_DONTAUDIT);
if ($$ == COND_ERR) YYABORT; }
;
- ;
+cond_xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';'
+ { $$ = define_cond_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED) ;
+ if ($$ == COND_ERR) YYABORT; }
+ ;
+cond_xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';'
+ { $$ = define_cond_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW) ;
+ if ($$ == COND_ERR) YYABORT; }
+ ;
+cond_xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';'
+ { $$ = define_cond_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT) ;
+ if ($$ == COND_ERR) YYABORT; }
+ ;
transition_def : TYPE_TRANSITION names names ':' names identifier filename ';'
{if (define_filename_trans()) YYABORT; }
| TYPE_TRANSITION names names ':' names identifier ';'
@@ -2,6 +2,7 @@
class CLASS1
class CLASS2
class CLASS3
+class CLASS4
class dir
class file
class process
@@ -10,6 +11,7 @@ common COMMON1 { CPERM1 }
class CLASS1 { PERM1 ioctl }
class CLASS2 inherits COMMON1
class CLASS3 inherits COMMON1 { PERM1 }
+class CLASS4 { nlmsg }
default_user { CLASS1 } source;
default_role { CLASS2 } target;
default_type { CLASS3 } source;
@@ -26,6 +28,7 @@ typealias TYPE1 alias TYPEALIAS1;
typeattribute TYPE1 ATTR1;
typebounds TYPE4 TYPE3;
bool BOOL1 true;
+bool BOOL2 false;
tunable TUNABLE1 false;
tunable TUNABLE2 true;
type_transition TYPE1 TYPE2 : CLASS1 TYPE3;
@@ -37,6 +40,7 @@ auditallow { TYPE1 TYPE2 } TYPE3 : CLASS1 { PERM1 };
dontaudit TYPE1 { TYPE2 TYPE3 } : CLASS3 { PERM1 CPERM1 };
neverallow TYPE1 TYPE2 : { CLASS2 CLASS3 } { CPERM1 };
allowxperm TYPE1 TYPE2 : CLASS1 ioctl { 0x456-0x5678 };
+allowxperm TYPE2 TYPE1 : CLASS4 nlmsg { 0x1 0x12 };
auditallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x2;
dontauditxperm TYPE1 TYPE2 : CLASS1 ioctl 0x3;
neverallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x4;
@@ -50,7 +54,8 @@ role_transition ROLE1 TYPE1 : CLASS1 ROLE2;
allow ROLE1 ROLE2;
roleattribute ROLE3 ROLE_ATTR1;
role ROLE1 types { TYPE1 };
-if ! BOOL1 { allow TYPE1 self: CLASS1 *; }
+if ! BOOL1 { allow TYPE1 self: CLASS1 *; dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6789 - 0x9876 }; }
+if BOOL2 { allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1 0x2 }; }
if TUNABLE1 xor TUNABLE2 { allow TYPE1 self: CLASS2 *; } else { allow TYPE1 self: CLASS3 *; }
optional { require { class CLASS2 { CPERM1 }; } allow TYPE1 self: CLASS2 *; }
user USER1 roles ROLE1;
@@ -2,6 +2,7 @@
class CLASS1
class CLASS2
class CLASS3
+class CLASS4
class dir
class file
class process
@@ -10,6 +11,7 @@ common COMMON1 { CPERM1 }
class CLASS1 { PERM1 ioctl }
class CLASS2 inherits COMMON1
class CLASS3 inherits COMMON1 { PERM1 }
+class CLASS4 { nlmsg }
default_user { CLASS1 } source;
default_role { CLASS2 } target;
default_type { CLASS3 } source;
@@ -17,6 +19,7 @@ policycap open_perms;
attribute ATTR1;
attribute ATTR2;
bool BOOL1 true;
+bool BOOL2 false;
type TYPE1;
type TYPE2;
type TYPE3;
@@ -37,6 +40,7 @@ dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 };
allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x456-0x4ff };
allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x500-0x55ff };
allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x5600-0x5678 };
+allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1 0x12 };
auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 };
dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 };
type_transition TYPE1 TYPE2:CLASS1 TYPE3;
@@ -49,6 +53,12 @@ type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME";
if (BOOL1) {
} else {
allow TYPE1 self:CLASS1 { PERM1 ioctl };
+ dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6789-0x67ff };
+ dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6800-0x97ff };
+ dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x9800-0x9876 };
+}
+if (BOOL2) {
+ allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1-0x2 };
}
role ROLE1;
role ROLE2;
@@ -2,6 +2,7 @@
class CLASS1
class CLASS2
class CLASS3
+class CLASS4
class dir
class file
class process
@@ -10,6 +11,7 @@ common COMMON1 { CPERM1 }
class CLASS1 { PERM1 ioctl }
class CLASS2 inherits COMMON1
class CLASS3 inherits COMMON1 { PERM1 }
+class CLASS4 { nlmsg }
default_user { CLASS1 } source;
default_role { CLASS2 } target;
default_type { CLASS3 } source;
@@ -17,6 +19,7 @@ policycap open_perms;
attribute ATTR1;
attribute ATTR2;
bool BOOL1 true;
+bool BOOL2 false;
type TYPE1;
type TYPE2;
type TYPE3;
@@ -37,6 +40,7 @@ dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 };
allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x456-0x4ff };
allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x500-0x55ff };
allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x5600-0x5678 };
+allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x1 0x12 };
auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 };
dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 };
type_transition TYPE1 TYPE2:CLASS1 TYPE3;
@@ -49,6 +53,12 @@ type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME";
if (BOOL1) {
} else {
allow TYPE1 self:CLASS1 { ioctl };
+ dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6789-0x67ff };
+ dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x6800-0x97ff };
+ dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x9800-0x9876 };
+}
+if (BOOL2) {
+ allowxperm TYPE2 TYPE1:CLASS4 nlmsg { 0x2 };
}
role ROLE1;
role ROLE2;