checkpolicy: add support for xperms in conditional policies

Add support for extended permission rules in conditional policies.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
This commit is contained in:
Christian Göttsche 2024-11-11 14:51:04 +01:00 committed by James Carter
parent 438b16d177
commit 32c24c247e
6 changed files with 141 additions and 15 deletions

View File

@ -1882,6 +1882,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;
@ -1892,8 +1894,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;
}
@ -1995,7 +2001,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;
}
@ -2477,9 +2483,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;
@ -2501,7 +2507,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 */
@ -2530,7 +2542,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);
}
}
}
@ -2544,12 +2562,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;
@ -2584,7 +2605,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);
}
}
}
@ -2598,9 +2625,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;
@ -2622,11 +2704,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;
}

View File

@ -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);

View File

@ -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 ';'

View File

@ -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;

View File

@ -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;

View File

@ -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;