selinux/checkpolicy/policy_parse.y

950 lines
32 KiB
Plaintext
Raw Normal View History

/*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
/*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
* Support for enhanced MLS infrastructure.
*
* Updated: David Caplan, <dac@tresys.com>
*
* Added conditional policy language extensions
*
* Updated: Joshua Brindle <jbrindle@tresys.com>
* Karl MacMillan <kmacmillan@mentalrootkit.com>
* Jason Tang <jtang@tresys.com>
*
* Added support for binary policy modules
*
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2008 Tresys Technology, LLC
* Copyright (C) 2007 Red Hat Inc.
* 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.
*/
/* FLASK */
%{
#include <sys/types.h>
#include <assert.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/flask.h>
#include <sepol/policydb/hierarchy.h>
#include <sepol/policydb/polcaps.h>
#include "queue.h"
#include "checkpolicy.h"
#include "module_compiler.h"
#include "policy_define.h"
extern policydb_t *policydbp;
extern unsigned int pass;
extern char yytext[];
extern int yylex(void);
extern int yywarn(const char *msg);
extern int yyerror(const char *msg);
typedef int (* require_func_t)(int pass);
%}
%union {
unsigned int val;
uint64_t val64;
uintptr_t valptr;
void *ptr;
require_func_t require_func;
}
%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_transition_def cond_te_avtab_def cond_rule_def
%type <ptr> role_def roles
%type <valptr> cexpr cexpr_prim op role_mls_op
%type <val> ipv4_addr_def number
%type <val64> number64
%type <require_func> require_decl_def
%token PATH
%token QPATH
%token FILENAME
%token CLONE
%token COMMON
%token CLASS
%token CONSTRAIN
%token VALIDATETRANS
%token INHERITS
%token SID
%token ROLE
%token ROLEATTRIBUTE
%token ATTRIBUTE_ROLE
%token ROLES
%token TYPEALIAS
%token TYPEATTRIBUTE
%token TYPEBOUNDS
%token TYPE
%token TYPES
%token ALIAS
%token ATTRIBUTE
%token BOOL
%token TUNABLE
%token IF
%token ELSE
%token TYPE_TRANSITION
%token TYPE_MEMBER
%token TYPE_CHANGE
%token ROLE_TRANSITION
%token RANGE_TRANSITION
%token SENSITIVITY
%token DOMINANCE
%token DOM DOMBY INCOMP
%token CATEGORY
%token LEVEL
%token RANGE
%token MLSCONSTRAIN
%token MLSVALIDATETRANS
%token USER
%token NEVERALLOW
%token ALLOW
%token AUDITALLOW
%token AUDITDENY
%token DONTAUDIT
%token ALLOWXPERM
%token AUDITALLOWXPERM
%token DONTAUDITXPERM
%token NEVERALLOWXPERM
%token SOURCE
%token TARGET
%token SAMEUSER
%token FSCON PORTCON NETIFCON NODECON
%token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
%token FSUSEXATTR FSUSETASK FSUSETRANS
%token GENFSCON
%token U1 U2 U3 R1 R2 R3 T1 T2 T3 L1 L2 H1 H2
%token NOT AND OR XOR
%token CTRUE CFALSE
%token IDENTIFIER
%token NUMBER
%token EQUALS
%token NOTEQUAL
%token IPV4_ADDR
%token IPV6_ADDR
%token MODULE VERSION_IDENTIFIER REQUIRE OPTIONAL
%token POLICYCAP
%token PERMISSIVE
%token FILESYSTEM
%token DEFAULT_USER DEFAULT_ROLE DEFAULT_TYPE DEFAULT_RANGE
%token LOW_HIGH LOW HIGH
%left OR
%left XOR
%left AND
%right NOT
%left EQUALS NOTEQUAL
%%
policy : base_policy
| module_policy
;
base_policy : { if (define_policy(pass, 0) == -1) return -1; }
classes initial_sids access_vectors
{ if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; }
else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1; }}
opt_default_rules opt_mls te_rbac users opt_constraints
{ if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}}
initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts
;
classes : class_def
| classes class_def
;
class_def : CLASS identifier
{if (define_class()) return -1;}
;
initial_sids : initial_sid_def
| initial_sids initial_sid_def
;
initial_sid_def : SID identifier
{if (define_initial_sid()) return -1;}
;
access_vectors : opt_common_perms av_perms
;
opt_common_perms : common_perms
|
;
common_perms : common_perms_def
| common_perms common_perms_def
;
common_perms_def : COMMON identifier '{' identifier_list '}'
{if (define_common_perms()) return -1;}
;
av_perms : av_perms_def
| av_perms av_perms_def
;
av_perms_def : CLASS identifier '{' identifier_list '}'
{if (define_av_perms(FALSE)) return -1;}
| CLASS identifier INHERITS identifier
{if (define_av_perms(TRUE)) return -1;}
| CLASS identifier INHERITS identifier '{' identifier_list '}'
{if (define_av_perms(TRUE)) return -1;}
;
opt_default_rules : default_rules
|
;
default_rules : default_user_def
| default_role_def
| default_type_def
| default_range_def
| default_rules default_user_def
| default_rules default_role_def
| default_rules default_type_def
| default_rules default_range_def
;
default_user_def : DEFAULT_USER names SOURCE ';'
{if (define_default_user(DEFAULT_SOURCE)) return -1; }
| DEFAULT_USER names TARGET ';'
{if (define_default_user(DEFAULT_TARGET)) return -1; }
;
default_role_def : DEFAULT_ROLE names SOURCE ';'
{if (define_default_role(DEFAULT_SOURCE)) return -1; }
| DEFAULT_ROLE names TARGET ';'
{if (define_default_role(DEFAULT_TARGET)) return -1; }
;
default_type_def : DEFAULT_TYPE names SOURCE ';'
{if (define_default_type(DEFAULT_SOURCE)) return -1; }
| DEFAULT_TYPE names TARGET ';'
{if (define_default_type(DEFAULT_TARGET)) return -1; }
;
default_range_def : DEFAULT_RANGE names SOURCE LOW ';'
{if (define_default_range(DEFAULT_SOURCE_LOW)) return -1; }
| DEFAULT_RANGE names SOURCE HIGH ';'
{if (define_default_range(DEFAULT_SOURCE_HIGH)) return -1; }
| DEFAULT_RANGE names SOURCE LOW_HIGH ';'
{if (define_default_range(DEFAULT_SOURCE_LOW_HIGH)) return -1; }
| DEFAULT_RANGE names TARGET LOW ';'
{if (define_default_range(DEFAULT_TARGET_LOW)) return -1; }
| DEFAULT_RANGE names TARGET HIGH ';'
{if (define_default_range(DEFAULT_TARGET_HIGH)) return -1; }
| DEFAULT_RANGE names TARGET LOW_HIGH ';'
{if (define_default_range(DEFAULT_TARGET_LOW_HIGH)) return -1; }
;
opt_mls : mls
|
;
mls : sensitivities dominance opt_categories levels mlspolicy
;
sensitivities : sensitivity_def
| sensitivities sensitivity_def
;
sensitivity_def : SENSITIVITY identifier alias_def ';'
{if (define_sens()) return -1;}
| SENSITIVITY identifier ';'
{if (define_sens()) return -1;}
;
alias_def : ALIAS names
;
dominance : DOMINANCE identifier
{if (define_dominance()) return -1;}
| DOMINANCE '{' identifier_list '}'
{if (define_dominance()) return -1;}
;
opt_categories : categories
|
;
categories : category_def
| categories category_def
;
category_def : CATEGORY identifier alias_def ';'
{if (define_category()) return -1;}
| CATEGORY identifier ';'
{if (define_category()) return -1;}
;
levels : level_def
| levels level_def
;
level_def : LEVEL identifier ':' id_comma_list ';'
{if (define_level()) return -1;}
| LEVEL identifier ';'
{if (define_level()) return -1;}
;
mlspolicy : mlspolicy_decl
| mlspolicy mlspolicy_decl
;
mlspolicy_decl : mlsconstraint_def
| mlsvalidatetrans_def
;
mlsconstraint_def : MLSCONSTRAIN names names cexpr ';'
{ if (define_constraint((constraint_expr_t*)$4)) return -1; }
;
mlsvalidatetrans_def : MLSVALIDATETRANS names cexpr ';'
{ if (define_validatetrans((constraint_expr_t*)$3)) return -1; }
;
te_rbac : te_rbac_decl
| te_rbac te_rbac_decl
;
te_rbac_decl : te_decl
| rbac_decl
| cond_stmt_def
| optional_block
| policycap_def
| ';'
;
rbac_decl : attribute_role_def
| role_type_def
| role_dominance
| role_trans_def
| role_allow_def
| roleattribute_def
| role_attr_def
;
te_decl : attribute_def
| type_def
| typealias_def
| typeattribute_def
| typebounds_def
| bool_def
| tunable_def
| transition_def
| range_trans_def
| te_avtab_def
| permissive_def
;
attribute_def : ATTRIBUTE identifier ';'
{ if (define_attrib()) return -1;}
;
type_def : TYPE identifier alias_def opt_attr_list ';'
{if (define_type(1)) return -1;}
| TYPE identifier opt_attr_list ';'
{if (define_type(0)) return -1;}
;
typealias_def : TYPEALIAS identifier alias_def ';'
{if (define_typealias()) return -1;}
;
typeattribute_def : TYPEATTRIBUTE identifier id_comma_list ';'
{if (define_typeattribute()) return -1;}
;
typebounds_def : TYPEBOUNDS identifier id_comma_list ';'
{if (define_typebounds()) return -1;}
;
opt_attr_list : ',' id_comma_list
|
;
bool_def : BOOL identifier bool_val ';'
{ if (define_bool_tunable(0)) return -1; }
;
tunable_def : TUNABLE identifier bool_val ';'
{ if (define_bool_tunable(1)) return -1; }
;
bool_val : CTRUE
{ if (insert_id("T",0)) return -1; }
| CFALSE
{ if (insert_id("F",0)) return -1; }
;
cond_stmt_def : IF cond_expr '{' cond_pol_list '}' cond_else
{ if (pass == 2) { if (define_conditional((cond_expr_t*)$2, (avrule_t*)$4, (avrule_t*)$6) < 0) return -1; }}
;
cond_else : ELSE '{' cond_pol_list '}'
{ $$ = $3; }
| /* empty */
{ $$ = NULL; }
;
cond_expr : '(' cond_expr ')'
{ $$ = $2;}
| NOT cond_expr
{ $$ = define_cond_expr(COND_NOT, $2, 0);
if ($$ == 0) return -1; }
| cond_expr AND cond_expr
{ $$ = define_cond_expr(COND_AND, $1, $3);
if ($$ == 0) return -1; }
| cond_expr OR cond_expr
{ $$ = define_cond_expr(COND_OR, $1, $3);
if ($$ == 0) return -1; }
| cond_expr XOR cond_expr
{ $$ = define_cond_expr(COND_XOR, $1, $3);
if ($$ == 0) return -1; }
| cond_expr EQUALS cond_expr
{ $$ = define_cond_expr(COND_EQ, $1, $3);
if ($$ == 0) return -1; }
| cond_expr NOTEQUAL cond_expr
{ $$ = define_cond_expr(COND_NEQ, $1, $3);
if ($$ == 0) return -1; }
| cond_expr_prim
{ $$ = $1; }
;
cond_expr_prim : identifier
{ $$ = define_cond_expr(COND_BOOL,0, 0);
if ($$ == COND_ERR) return -1; }
;
cond_pol_list : cond_pol_list cond_rule_def
{ $$ = define_cond_pol_list((avrule_t *)$1, (avrule_t *)$2); }
| /* empty */
{ $$ = NULL; }
;
cond_rule_def : cond_transition_def
{ $$ = $1; }
| cond_te_avtab_def
{ $$ = $1; }
| require_block
{ $$ = NULL; }
;
cond_transition_def : TYPE_TRANSITION names names ':' names identifier filename ';'
{ $$ = define_cond_filename_trans() ;
if ($$ == COND_ERR) return -1;}
| TYPE_TRANSITION names names ':' names identifier ';'
{ $$ = define_cond_compute_type(AVRULE_TRANSITION) ;
if ($$ == COND_ERR) return -1;}
| TYPE_MEMBER names names ':' names identifier ';'
{ $$ = define_cond_compute_type(AVRULE_MEMBER) ;
if ($$ == COND_ERR) return -1;}
| TYPE_CHANGE names names ':' names identifier ';'
{ $$ = define_cond_compute_type(AVRULE_CHANGE) ;
if ($$ == COND_ERR) return -1;}
;
cond_te_avtab_def : cond_allow_def
{ $$ = $1; }
| cond_auditallow_def
{ $$ = $1; }
| cond_auditdeny_def
{ $$ = $1; }
| cond_dontaudit_def
{ $$ = $1; }
;
cond_allow_def : ALLOW names names ':' names names ';'
{ $$ = define_cond_te_avtab(AVRULE_ALLOWED) ;
if ($$ == COND_ERR) return -1; }
;
cond_auditallow_def : AUDITALLOW names names ':' names names ';'
{ $$ = define_cond_te_avtab(AVRULE_AUDITALLOW) ;
if ($$ == COND_ERR) return -1; }
;
cond_auditdeny_def : AUDITDENY names names ':' names names ';'
{ $$ = define_cond_te_avtab(AVRULE_AUDITDENY) ;
if ($$ == COND_ERR) return -1; }
;
cond_dontaudit_def : DONTAUDIT names names ':' names names ';'
{ $$ = define_cond_te_avtab(AVRULE_DONTAUDIT);
if ($$ == COND_ERR) return -1; }
;
;
transition_def : TYPE_TRANSITION names names ':' names identifier filename ';'
{if (define_filename_trans()) return -1; }
| TYPE_TRANSITION names names ':' names identifier ';'
{if (define_compute_type(AVRULE_TRANSITION)) return -1;}
| TYPE_MEMBER names names ':' names identifier ';'
{if (define_compute_type(AVRULE_MEMBER)) return -1;}
| TYPE_CHANGE names names ':' names identifier ';'
{if (define_compute_type(AVRULE_CHANGE)) return -1;}
;
range_trans_def : RANGE_TRANSITION names names mls_range_def ';'
{ if (define_range_trans(0)) return -1; }
| RANGE_TRANSITION names names ':' names mls_range_def ';'
{ if (define_range_trans(1)) return -1; }
;
te_avtab_def : allow_def
| auditallow_def
| auditdeny_def
| dontaudit_def
| neverallow_def
| xperm_allow_def
| xperm_auditallow_def
| xperm_dontaudit_def
| xperm_neverallow_def
;
allow_def : ALLOW names names ':' names names ';'
{if (define_te_avtab(AVRULE_ALLOWED)) return -1; }
;
auditallow_def : AUDITALLOW names names ':' names names ';'
{if (define_te_avtab(AVRULE_AUDITALLOW)) return -1; }
;
auditdeny_def : AUDITDENY names names ':' names names ';'
{if (define_te_avtab(AVRULE_AUDITDENY)) return -1; }
;
dontaudit_def : DONTAUDIT names names ':' names names ';'
{if (define_te_avtab(AVRULE_DONTAUDIT)) return -1; }
;
neverallow_def : NEVERALLOW names names ':' names names ';'
{if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; }
;
xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED)) return -1; }
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
;
xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW)) return -1; }
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
;
xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) return -1; }
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
;
xperm_neverallow_def : NEVERALLOWXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) return -1; }
;
attribute_role_def : ATTRIBUTE_ROLE identifier ';'
{if (define_attrib_role()) return -1; }
;
role_type_def : ROLE identifier TYPES names ';'
{if (define_role_types()) return -1;}
;
role_attr_def : ROLE identifier opt_attr_list ';'
{if (define_role_attr()) return -1;}
;
role_dominance : DOMINANCE '{' roles '}'
;
role_trans_def : ROLE_TRANSITION names names identifier ';'
{if (define_role_trans(0)) return -1; }
| ROLE_TRANSITION names names ':' names identifier ';'
{if (define_role_trans(1)) return -1;}
;
role_allow_def : ALLOW names names ';'
{if (define_role_allow()) return -1; }
;
roles : role_def
{ $$ = $1; }
| roles role_def
{ $$ = merge_roles_dom((role_datum_t*)$1, (role_datum_t*)$2); if ($$ == 0) return -1;}
;
role_def : ROLE identifier_push ';'
{$$ = define_role_dom(NULL); if ($$ == 0) return -1;}
| ROLE identifier_push '{' roles '}'
{$$ = define_role_dom((role_datum_t*)$4); if ($$ == 0) return -1;}
;
roleattribute_def : ROLEATTRIBUTE identifier id_comma_list ';'
{if (define_roleattribute()) return -1;}
;
opt_constraints : constraints
|
;
constraints : constraint_decl
| constraints constraint_decl
;
constraint_decl : constraint_def
| validatetrans_def
;
constraint_def : CONSTRAIN names names cexpr ';'
{ if (define_constraint((constraint_expr_t*)$4)) return -1; }
;
validatetrans_def : VALIDATETRANS names cexpr ';'
{ if (define_validatetrans((constraint_expr_t*)$3)) return -1; }
;
cexpr : '(' cexpr ')'
{ $$ = $2; }
| NOT cexpr
{ $$ = define_cexpr(CEXPR_NOT, $2, 0);
if ($$ == 0) return -1; }
| cexpr AND cexpr
{ $$ = define_cexpr(CEXPR_AND, $1, $3);
if ($$ == 0) return -1; }
| cexpr OR cexpr
{ $$ = define_cexpr(CEXPR_OR, $1, $3);
if ($$ == 0) return -1; }
| cexpr_prim
{ $$ = $1; }
;
cexpr_prim : U1 op U2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, $2);
if ($$ == 0) return -1; }
| R1 role_mls_op R2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2);
if ($$ == 0) return -1; }
| T1 op T2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_TYPE, $2);
if ($$ == 0) return -1; }
| U1 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_USER, $2);
if ($$ == 0) return -1; }
| U2 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_TARGET), $2);
if ($$ == 0) return -1; }
| U3 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_XTARGET), $2);
if ($$ == 0) return -1; }
| R1 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, $2);
if ($$ == 0) return -1; }
| R2 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), $2);
if ($$ == 0) return -1; }
| R3 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_XTARGET), $2);
if ($$ == 0) return -1; }
| T1 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, $2);
if ($$ == 0) return -1; }
| T2 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), $2);
if ($$ == 0) return -1; }
| T3 op { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_XTARGET), $2);
if ($$ == 0) return -1; }
| SAMEUSER
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, CEXPR_EQ);
if ($$ == 0) return -1; }
| SOURCE ROLE { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, CEXPR_EQ);
if ($$ == 0) return -1; }
| TARGET ROLE { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), CEXPR_EQ);
if ($$ == 0) return -1; }
| ROLE role_mls_op
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2);
if ($$ == 0) return -1; }
| SOURCE TYPE { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, CEXPR_EQ);
if ($$ == 0) return -1; }
| TARGET TYPE { if (insert_separator(1)) return -1; } names_push
{ $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), CEXPR_EQ);
if ($$ == 0) return -1; }
| L1 role_mls_op L2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1L2, $2);
if ($$ == 0) return -1; }
| L1 role_mls_op H2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1H2, $2);
if ($$ == 0) return -1; }
| H1 role_mls_op L2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_H1L2, $2);
if ($$ == 0) return -1; }
| H1 role_mls_op H2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_H1H2, $2);
if ($$ == 0) return -1; }
| L1 role_mls_op H1
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1H1, $2);
if ($$ == 0) return -1; }
| L2 role_mls_op H2
{ $$ = define_cexpr(CEXPR_ATTR, CEXPR_L2H2, $2);
if ($$ == 0) return -1; }
;
op : EQUALS
{ $$ = CEXPR_EQ; }
| NOTEQUAL
{ $$ = CEXPR_NEQ; }
;
role_mls_op : op
{ $$ = $1; }
| DOM
{ $$ = CEXPR_DOM; }
| DOMBY
{ $$ = CEXPR_DOMBY; }
| INCOMP
{ $$ = CEXPR_INCOMP; }
;
users : user_def
| users user_def
;
user_def : USER identifier ROLES names opt_mls_user ';'
{if (define_user()) return -1;}
;
opt_mls_user : LEVEL mls_level_def RANGE mls_range_def
|
;
initial_sid_contexts : initial_sid_context_def
| initial_sid_contexts initial_sid_context_def
;
initial_sid_context_def : SID identifier security_context_def
{if (define_initial_sid_context()) return -1;}
;
opt_dev_contexts : dev_contexts |
;
dev_contexts : dev_context_def
| dev_contexts dev_context_def
;
dev_context_def : pirq_context_def |
iomem_context_def |
ioport_context_def |
pci_context_def |
dtree_context_def
;
pirq_context_def : PIRQCON number security_context_def
{if (define_pirq_context($2)) return -1;}
;
iomem_context_def : IOMEMCON number64 security_context_def
{if (define_iomem_context($2,$2)) return -1;}
| IOMEMCON number64 '-' number64 security_context_def
{if (define_iomem_context($2,$4)) return -1;}
;
ioport_context_def : IOPORTCON number security_context_def
{if (define_ioport_context($2,$2)) return -1;}
| IOPORTCON number '-' number security_context_def
{if (define_ioport_context($2,$4)) return -1;}
;
pci_context_def : PCIDEVICECON number security_context_def
{if (define_pcidevice_context($2)) return -1;}
;
dtree_context_def : DEVICETREECON path security_context_def
{if (define_devicetree_context()) return -1;}
;
opt_fs_contexts : fs_contexts
|
;
fs_contexts : fs_context_def
| fs_contexts fs_context_def
;
fs_context_def : FSCON number number security_context_def security_context_def
{if (define_fs_context($2,$3)) return -1;}
;
net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts
;
opt_port_contexts : port_contexts
|
;
port_contexts : port_context_def
| port_contexts port_context_def
;
port_context_def : PORTCON identifier number security_context_def
{if (define_port_context($3,$3)) return -1;}
| PORTCON identifier number '-' number security_context_def
{if (define_port_context($3,$5)) return -1;}
;
opt_netif_contexts : netif_contexts
|
;
netif_contexts : netif_context_def
| netif_contexts netif_context_def
;
netif_context_def : NETIFCON identifier security_context_def security_context_def
{if (define_netif_context()) return -1;}
;
opt_node_contexts : node_contexts
|
;
node_contexts : node_context_def
| node_contexts node_context_def
;
node_context_def : NODECON ipv4_addr_def ipv4_addr_def security_context_def
{if (define_ipv4_node_context()) return -1;}
| NODECON ipv6_addr ipv6_addr security_context_def
{if (define_ipv6_node_context()) return -1;}
;
opt_fs_uses : fs_uses
|
;
fs_uses : fs_use_def
| fs_uses fs_use_def
;
fs_use_def : FSUSEXATTR filesystem security_context_def ';'
{if (define_fs_use(SECURITY_FS_USE_XATTR)) return -1;}
| FSUSETASK identifier security_context_def ';'
{if (define_fs_use(SECURITY_FS_USE_TASK)) return -1;}
| FSUSETRANS identifier security_context_def ';'
{if (define_fs_use(SECURITY_FS_USE_TRANS)) return -1;}
;
opt_genfs_contexts : genfs_contexts
|
;
genfs_contexts : genfs_context_def
| genfs_contexts genfs_context_def
;
genfs_context_def : GENFSCON filesystem path '-' identifier security_context_def
{if (define_genfs_context(1)) return -1;}
| GENFSCON filesystem path '-' '-' {insert_id("-", 0);} security_context_def
{if (define_genfs_context(1)) return -1;}
| GENFSCON filesystem path security_context_def
{if (define_genfs_context(0)) return -1;}
;
ipv4_addr_def : IPV4_ADDR
{ if (insert_id(yytext,0)) return -1; }
;
xperms : xperm
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
{ if (insert_separator(0)) return -1; }
| nested_xperm_set
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
{ if (insert_separator(0)) return -1; }
| tilde xperm
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
{ if (insert_id("~", 0)) return -1; }
| tilde nested_xperm_set
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
{ if (insert_id("~", 0)) return -1;
if (insert_separator(0)) return -1; }
;
nested_xperm_set : '{' nested_xperm_list '}'
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
;
nested_xperm_list : nested_xperm_element
| nested_xperm_list nested_xperm_element
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
;
nested_xperm_element: xperm '-' { if (insert_id("-", 0)) return -1; } xperm
| xperm
| nested_xperm_set
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
;
xperm : number
Add support for ioctl command whitelisting Adds support for new policy statements whitelisting individual ioctl commands. Ioctls provide many of the operations necessary for driver control. The typical driver supports a device specific set of operations accessible by the ioctl system call and specified by the command argument. SELinux provides per operation access control to many system operations e.g. chown, kill, setuid, ipc_lock, etc. Ioclts on the other hand are granted on a per file descriptor basis using the ioctl permission, meaning that the set of operations provided by the driver are granted on an all-or-nothing basis. In some cases this may be acceptable, but often the same driver provides a large and diverse set of operations such as benign and necessary functionality as well as dangerous capabilities or access to system information that should be restricted. Example policy: allow <source> <target>:<class> { 0x8900-0x8905 0x8910 } auditallow <source> <target>:<class> 0x8901 The ioctl permission is still required in order to make an ioctl call. If no individual ioctl commands are specified, only the ioctl permission is checked by the kernel - i.e. status quo. This allows ioctl whitelisting to done in a targeted manner, protecting desired drivers without requiring every ioctl command to be known and specified before use and otherwise allowing existing policy to be used as-is. This only implements ioctl whitelisting support for monolithic kernel policies built via checkpolicy. Support for modules and CIL remains to be done. Bug: 19419509 Change-Id: I198e8c9279b94d8ce4ae5625018daa99577ee970 Signed-off-by: Jeff Vander Stoep <jeffv@google.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
2015-04-22 20:53:25 +00:00
{ if (insert_id(yytext,0)) return -1; }
;
security_context_def : identifier ':' identifier ':' identifier opt_mls_range_def
;
opt_mls_range_def : ':' mls_range_def
|
;
mls_range_def : mls_level_def '-' mls_level_def
{if (insert_separator(0)) return -1;}
| mls_level_def
{if (insert_separator(0)) return -1;}
;
mls_level_def : identifier ':' id_comma_list
{if (insert_separator(0)) return -1;}
| identifier
{if (insert_separator(0)) return -1;}
;
id_comma_list : identifier
| id_comma_list ',' identifier
;
tilde : '~'
;
asterisk : '*'
;
names : identifier
{ if (insert_separator(0)) return -1; }
| nested_id_set
{ if (insert_separator(0)) return -1; }
| asterisk
{ if (insert_id("*", 0)) return -1;
if (insert_separator(0)) return -1; }
| tilde identifier
{ if (insert_id("~", 0)) return -1;
if (insert_separator(0)) return -1; }
| tilde nested_id_set
{ if (insert_id("~", 0)) return -1;
if (insert_separator(0)) return -1; }
| identifier '-' { if (insert_id("-", 0)) return -1; } identifier
{ if (insert_separator(0)) return -1; }
;
tilde_push : tilde
{ if (insert_id("~", 1)) return -1; }
;
asterisk_push : asterisk
{ if (insert_id("*", 1)) return -1; }
;
names_push : identifier_push
| '{' identifier_list_push '}'
| asterisk_push
| tilde_push identifier_push
| tilde_push '{' identifier_list_push '}'
;
identifier_list_push : identifier_push
| identifier_list_push identifier_push
;
identifier_push : IDENTIFIER
{ if (insert_id(yytext, 1)) return -1; }
;
identifier_list : identifier
| identifier_list identifier
;
nested_id_set : '{' nested_id_list '}'
;
nested_id_list : nested_id_element | nested_id_list nested_id_element
;
nested_id_element : identifier | '-' { if (insert_id("-", 0)) return -1; } identifier | nested_id_set
;
identifier : IDENTIFIER
{ if (insert_id(yytext,0)) return -1; }
;
filesystem : FILESYSTEM
{ if (insert_id(yytext,0)) return -1; }
| IDENTIFIER
{ if (insert_id(yytext,0)) return -1; }
;
path : PATH
{ if (insert_id(yytext,0)) return -1; }
| QPATH
{ yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; }
;
filename : FILENAME
{ yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; }
;
number : NUMBER
{ $$ = strtoul(yytext,NULL,0); }
;
number64 : NUMBER
{ $$ = strtoull(yytext,NULL,0); }
;
ipv6_addr : IPV6_ADDR
{ if (insert_id(yytext,0)) return -1; }
;
policycap_def : POLICYCAP identifier ';'
{if (define_polcap()) return -1;}
;
permissive_def : PERMISSIVE identifier ';'
{if (define_permissive()) return -1;}
/*********** module grammar below ***********/
module_policy : module_def avrules_block
{ if (end_avrule_block(pass) == -1) return -1;
if (policydb_index_others(NULL, policydbp, 0)) return -1;
}
;
module_def : MODULE identifier version_identifier ';'
{ if (define_policy(pass, 1) == -1) return -1; }
;
version_identifier : VERSION_IDENTIFIER
{ if (insert_id(yytext,0)) return -1; }
| number
{ if (insert_id(yytext,0)) return -1; }
| ipv4_addr_def /* version can look like ipv4 address */
;
avrules_block : avrule_decls avrule_user_defs
;
avrule_decls : avrule_decls avrule_decl
| avrule_decl
;
avrule_decl : rbac_decl
| te_decl
| cond_stmt_def
| require_block
| optional_block
| ';'
;
require_block : REQUIRE '{' require_list '}'
;
require_list : require_list require_decl
| require_decl
;
require_decl : require_class ';'
| require_decl_def require_id_list ';'
;
require_class : CLASS identifier names
{ if (require_class(pass)) return -1; }
;
require_decl_def : ROLE { $$ = require_role; }
| TYPE { $$ = require_type; }
| ATTRIBUTE { $$ = require_attribute; }
| ATTRIBUTE_ROLE { $$ = require_attribute_role; }
| USER { $$ = require_user; }
| BOOL { $$ = require_bool; }
| TUNABLE { $$ = require_tunable; }
| SENSITIVITY { $$ = require_sens; }
| CATEGORY { $$ = require_cat; }
;
require_id_list : identifier
{ if ($<require_func>0 (pass)) return -1; }
| require_id_list ',' identifier
{ if ($<require_func>0 (pass)) return -1; }
;
optional_block : optional_decl '{' avrules_block '}'
{ if (end_avrule_block(pass) == -1) return -1; }
optional_else
{ if (end_optional(pass) == -1) return -1; }
;
optional_else : else_decl '{' avrules_block '}'
{ if (end_avrule_block(pass) == -1) return -1; }
| /* empty */
;
optional_decl : OPTIONAL
{ if (begin_optional(pass) == -1) return -1; }
;
else_decl : ELSE
{ if (begin_optional_else(pass) == -1) return -1; }
;
avrule_user_defs : user_def avrule_user_defs
| /* empty */
;