This is my attempt at documenting the policy grammar that is accepted by checkpolicy. The grammar was taken directly from the bison input file and edited to make it more readable for the wiki system.
Comments start with a # character and continue to the end of the line.
Keywords can be in all uppercase or all lowercase.
Convention followed in this document: Plain text is used for non-terminals. Basically it means that there is a defination of the thing else where. When a non-terminal is used on the right hand side of a grammar rule there should be some rule in the file with that non-terminal on the left hand side. Items in bold are literal, they must appear in the policy file exactly as written. Items in italics are used for things that can be replaced by some user specified text. They will also be surrounded with < and > signs to make them clearly different from keywords.
Any item in [ square brackets ] is an optional item. Items with a * after them can be repeated zero or more times. Items with a + after them can be repeated one or more times. Parenthesis are used to group items that can be repeated. Vertical lines | are used to indicate alternatives.
A file must contain either a base_policy or a module_policy.
base policy
base_policy = class_def+ initial_sid_def+ access_vectors [mls] te_rbac user_def+ [constraint_decl+] initial_sid_context_def+ [fs_context_def+] [fs_use_def+] [genfs_context_def+] [port_context_def+] [netif_context_def+] [node_context_def+]
class_def = CLASS <identifier>
initial_sid_def = SID <identifier>
access_vectors = [common_perms] av_perms_def+
av_perms_def = CLASS <identifier> { identifier_list } | CLASS <identifier> INHERITS <identifier> | CLASS <identifier> INHERITS <identifier> { identifier_list }
initial_sid_context_def = SID <identifier> security_context_def
constraint_decl = constraint_def | validatetrans_def
constraint_def = CONSTRAIN names names cexpr ;
validatetrans_def = VALIDATETRANS names cexpr ;
fs_context_def = FSCON number number security_context_def security_context_def
port_context_def = PORTCON <identifier> number security_context_def | PORTCON <identifier> number '-' number security_context_def
netif_context_def = NETIFCON <identifier> security_context_def security_context_def
node_context_def = NODECON <ipv4_addr> <ipv4_addr> security_context_def | NODECON <ipv6_addr> <ipv6_addr> security_context_def
fs_use_def = FSUSEXATTR <identifier> security_context_def ; | FSUSETASK <identifier> security_context_def ; | FSUSETRANS <identifier> security_context_def ;
genfs_context_def = GENFSCON <identifier> path '-' <identifier> security_context_def | GENFSCON <identifier> path '-' '-' security_context_def | GENFSCON <identifier> path security_context_def
security_context_def = <identifier> : <identifier> : <identifier> [: mls_range_def]
mls_range_def = mls_level_def '-' mls_level_def | mls_level_def
mls_level_def = <identifier> : id_comma_list | <identifier>
id_comma_list = <identifier> | id_comma_list ',' <identifier>
module policy
module_policy = MODULE <identifier> <version_identifier> ; avrules_block
avrules_block = avrule_decl+ user_def*
avrule_decl = rbac_decl | te_decl | cond_stmt_def | require_block | optional_block | ;
user_def = USER <identifier> ROLES names [LEVEL mls_level_def RANGE mls_range_def] ;
rbac_decl = role_type_def | role_dominance | role_trans_def | role_allow_def
te_decl = ATTRIBUTE <identifier> ; | type_def | TYPEALIAS <identifier> alias_def ; | TYPEATTRIBUTE <identifier> id_comma_list ; | BOOL <identifier> bool_val ; | transition_def | range_trans_def | te_avtab_def | PERMISSIVE <identifier> ;
te_rbac = ( te_decl | rbac_decl | cond_stmt_def | optional_block | policycap_def | ; )+
te_avtab_def = ALLOW names names : names names ; | AUDITALLOW names names : names names ; | AUDITDENY names names : names names ; | DONTAUDIT names names : names names ; | NEVERALLOW names names : names names ;
require_block = REQUIRE { require_decl+ }
require_decl = require_class ; | require_decl_def require_id_list ;
optional_block = OPTIONAL { avrules_block } [ ELSE { avrules_block } ]
cond_stmt_def = IF cond_expr { cond_pol_list } [ ELSE { cond_pol_list } ]
cond_expr = '(' cond_expr ')' | NOT cond_expr | cond_expr AND cond_expr | cond_expr OR cond_expr | cond_expr XOR cond_expr | cond_expr EQUALS cond_expr | cond_expr NOTEQUAL cond_expr | <identifier>
type_def = TYPE <identifier> alias_def [',' id_comma_list] ; | TYPE <identifier> [',' id_comma_list] ;
names = <identifier> | nested_id_set | * | ~ <identifier> | ~ nested_id_set | <identifier> - <identifier>
common_perms = common_perms_def | common_perms common_perms_def
common_perms_def = COMMON <identifier> { identifier_list }
mls = sensitivity_def+ dominance [category_def+] level_def+ mlspolicy_decl+
sensitivity_def = SENSITIVITY <identifier> alias_def ';' | SENSITIVITY <identifier> ';'
alias_def = ALIAS names
dominance = DOMINANCE <identifier> | DOMINANCE { identifier_list }
category_def = CATEGORY <identifier> alias_def ';' | CATEGORY <identifier> ';'
level_def = LEVEL <identifier> ':' id_comma_list ';' | LEVEL <identifier> ';'
mlspolicy_decl = mlsconstraint_def | mlsvalidatetrans_def
mlsconstraint_def = MLSCONSTRAIN names names cexpr ';'
mlsvalidatetrans_def = MLSVALIDATETRANS names cexpr ';'
bool_val = CTRUE | CFALSE
cond_pol_list = cond_pol_list cond_rule_def | /* empty */
cond_rule_def = cond_transition_def | cond_te_avtab_def | require_block
cond_transition_def = TYPE_TRANSITION names names ':' names <identifier> ';' | TYPE_MEMBER names names ':' names <identifier> ';' | TYPE_CHANGE names names ':' names <identifier> ';'
cond_te_avtab_def = ALLOW names names : names names ; | AUDITALLOW names names : names names ; | AUDITDENY names names : names names ; | DONTAUDIT names names : names names ;
transition_def = TYPE_TRANSITION names names : names <identifier> ; | TYPE_MEMBER names names : names <identifier> ; | TYPE_CHANGE names names : names <identifier> ;
range_trans_def = RANGE_TRANSITION names names mls_range_def ; | RANGE_TRANSITION names names : names mls_range_def ;
role_type_def = ROLE' <identifier> TYPES names ; | ROLE <identifier>;'
role_dominance = DOMINANCE { role_def+ }
role_trans_def = ROLE_TRANSITION names names <identifier> ;
role_allow_def = ALLOW names names ;
role_def = ROLE <identifier>_push ; | ROLE <identifier>_push { role_def+ }
cexpr = '(' cexpr ')' | NOT cexpr | cexpr AND cexpr | cexpr OR cexpr | cexpr_prim
cexpr_prim = U1 op U2 | R1 role_mls_op R2 | T1 op T2 | U1 op names_push | U2 op names_push | U3 op names_push | R1 op names_push | R2 op names_push | R3 op names_push | T1 op names_push | T2 op names_push | T3 op names_push | SAMEUSER | SOURCE ROLE names_push | TARGET ROLE names_push | ROLE role_mls_op | SOURCE TYPE names_push | TARGET TYPE names_push | L1 role_mls_op L2 | L1 role_mls_op H2 | H1 role_mls_op L2 | H1 role_mls_op H2 | L1 role_mls_op H1 | L2 role_mls_op H2
op = EQUALS | NOTEQUAL
role_mls_op = op | DOM | DOMBY | INCOMP
token definations
version_identifier = xxx
names_push = identifier_push | { identifier_list_push } | * | ~ identifier_push | ~ { identifier_list_push }
identifier_list_push = identifier_push | identifier_list_push identifier_push
identifier_push = IDENTIFIER
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 | '-' identifier | nested_id_set
identifier = IDENTIFIER
path = PATH
number = NUMBER
policycap_def = POLICYCAP identifier ;
version_identifier = VERSION_IDENTIFIER
require_class = CLASS identifier names
require_decl_def = ROLE | TYPE | ATTRIBUTE | USER | BOOL | SENSITIVITY | CATEGORY
require_id_list = identifier | require_id_list ',' identifier