#pragma description SE Linux module #pragma author Ange Albertini import std.sys; #pragma pattern_limit 0 #pragma array_limit 0 #pragma endian little #pragma magic [ 8C FF 7C F9 ] @ 0x00 #pragma magic [ 8D FF 7C F9 ] @ 0x00 u32 version; u32 symbols_count; u32 object_contexts_count; u32 type_primary_names_count = 0; bool boundary_feature; using Header; enum magics: u32 { kernel = 0xf97cff8c, module = 0xf97cff8d, }; bitfield CONFIG { DENY_UNKNOWN: 1; MLS: 1; REJECT_UNKNOWN: 1; ALLOW_UNKNOWN: 1; padding: 4 + 3 * 8; }; enum policy_types: u32 { kernel = 0, base = 1, module = 2, }; policy_types type_g; enum targets: u32 { selinux = 0, xen = 1, }; targets target; struct list { u32 count; T item[count]; }; struct symbols_list { u32 primary_names_count; list [[inline]]; }; struct permission { u32 length; u32 value; char key[length]; }; struct extensible_bitmap_node { u32 startbit; u64 map; }; struct extensible_bitmap { u32 mapsize; std::assert(mapsize == 0x40 , "Incorrect mapsize"); u32 highbit; std::assert(!(highbit & 0x3F) , "Incorrect highbit"); u32 count; std::assert(!((highbit > 0) && (count == 0)) , "Incorrect bitmap"); extensible_bitmap_node node[count]; }; struct type_set { extensible_bitmap types; extensible_bitmap negset; u32 flag; }; enum expression_types: u32 { not = 1, and = 2, or = 3, attr = 4, names = 5, }; struct expression { expression_types type_; u32 attribute; u32 operator; if (type_ == expression_types::names) { extensible_bitmap names; if ((type_g == policy_types::kernel && version >= 29) || (type_g != policy_types::kernel)) type_set type_names; } }; struct constraint { u32 permissions; list [[inline]]; }; struct mls_range { u32 items; u32 sensitivity0; if (items > 1) u32 sensitivity1; extensible_bitmap category0; if (items > 1) extensible_bitmap category1; }; struct role_set { extensible_bitmap roles; u32 flags; }; struct mls_level { u32 sensitivity; extensible_bitmap category; }; struct semantic_category { u32 low; u32 high; }; struct mls_semantic_level { u32 sensitivity; list [[inline]]; }; struct mls_semantic_range { mls_semantic_level level0; mls_semantic_level level1; }; struct context_s { u32 user; u32 role; u32 type_; if (((type_g == policy_types::kernel) && (version >= 19)) || ((type_g == policy_types::base) && (version >= 5))) mls_range mls_range; }; struct common { u32 length; u32 value; u32 primary_names_count; u32 elements_count; char key[length]; permission permission[elements_count]; }; using commons = symbols_list; struct class { u32 key_length; u32 common_key_length; u32 value; u32 primary_names_count; u32 elements_count; u32 constraints_count; char key[key_length]; char common_key[common_key_length]; permission permissions[elements_count]; constraint constraints[constraints_count]; if (((type_g == policy_types::kernel) && (version >= 19)) || (type_g == policy_types::base && version >= 5)) u32 validatetrans_count; if ((type_g == policy_types::kernel && version >= 19) || (type_g == policy_types::base && version >= 5)) constraint validatetrans[validatetrans_count]; if ((type_g == policy_types::kernel && version >= 27) || (type_g == policy_types::base && version >= 15)) { u32 default_user; u32 default_role; u32 default_range; } if ((type_g == policy_types::kernel && version >= 28) || (type_g == policy_types::base && version >= 16)) u32 default_type; }; using classes = symbols_list; struct role_s { u32 length; u32 value; u32 bounds; char key[length]; extensible_bitmap dominates; if (type_g == policy_types::kernel) extensible_bitmap types; else type_set types; if ((type_g != policy_types::kernel && version >= 13)) { u32 flavor; extensible_bitmap roles; } }; using roles = symbols_list; struct type_s { u32 length; u32 value; if ((boundary_feature && (type_g != policy_types::kernel && version >= 10)) || !boundary_feature) u32 primary; if (boundary_feature) { u32 properties; u32 bounds; } if (!boundary_feature && (type_g != policy_types::kernel)) u32 flavor; if (!boundary_feature && (type_g != policy_types::kernel && version >= 8)) u32 flags; if (type_g != policy_types::kernel) extensible_bitmap types; char key[length]; }; struct types_s { u32 primary_names_count; type_primary_names_count = primary_names_count; list [[inline]]; }; struct user_s { u32 length; u32 value; if (boundary_feature) u32 bounds; char key[length]; if (type_g == policy_types::kernel) extensible_bitmap roles; else role_set roles; if ((type_g == policy_types::kernel && version >= 19) || (type_g == policy_types::module && version >= 5 && version < 6) || (type_g == policy_types::base && version >= 5 && version < 6)) { mls_range exp_range; mls_level exp_dftlevel; } if ((type_g == policy_types::module || type_g == policy_types::base) && (version >= 6)) { mls_semantic_range range; mls_semantic_range dfltlevel; } }; using users = symbols_list; struct bool_ { // conditional boolean u32 value; u32 state; u32 length; char key[length]; if ((type_g != policy_types::kernel && version >= 14)) u32 flags; }; using bools = symbols_list; struct level { u32 length; u32 isalias; char key[length]; mls_level level; }; using sensitivity_levels = symbols_list; struct category { u32 length; u32 value; u32 isalias; char key[length]; }; using categories = symbols_list; struct symbols { commons commons; classes classes; roles roles; types_s types; users users; if (symbols_count >= 6) bools bools; if (symbols_count >= 7) sensitivity_levels levels; if (symbols_count >= 8) categories cats; }; struct module_header { u32 name_length; std::assert(name_length >= 1, "Invalid 'name_length' in module header."); char name[name_length]; u32 version_length; std::assert(version_length >= 1, "Invalid 'version_length' in module header."); char version[version_length]; }; struct access_vector_old { u32 total; u32 source_type; u32 target_type; u32 target_class; u32 value; u32 data[8]; }; struct access_vector { u16 source_type; u16 target_type; u16 target_class; u16 specified; if ((specified & 0x700) != 0) { u8 xperms_specified; u8 xperms_drivers; u32 xperms_perms[8]; } else u32 data; }; struct avrule_item { u32 tclass; u32 data; }; struct avrule { u32 specified; u32 flags; type_set stypes; type_set ttypes; u32 length; avrule_item avrule_item[length]; if ((specified & (0x0100 | 0x0200 | 0x0400 | 0x0800)) != 0) { u8 xperms_specified; u8 xperms_driver; list perms[[inline]]; } }; struct avrule_list { u32 length; avrule avrule[length]; }; struct conditional_node_item { u32 expr_type; u32 boolean; }; struct access_vector_table_s { if (version < 20) list access_vector_table; else list access_vector_table; } [[inline]]; using cond_av_list = access_vector_table_s; struct conditional_node { u32 current_state; u32 length; conditional_node_item item[length]; if (type_g == policy_types::kernel) { cond_av_list true_list; cond_av_list false_list; } else { avrule_list avtrue_list; avrule_list avfalse_list; if (version >= 14) u32 flags; } }; struct conditional_list { u32 length; conditional_node conditional_node[length]; }; struct role_trans_item { u32 role; u32 type_; u32 new_role; if (type_g == policy_types::kernel && version >= 26) u32 tclass; }; using role_trans = list; struct role_allow_item { u32 role; u32 new_role; }; using role_allow = list; struct filename_trans_item_old { u32 length; char name[length]; u32 stype; u32 ttype; u32 tclass; u32 otype; }; struct filename_trans_item_item { extensible_bitmap stypes; u32 otype; }; struct filename_trans_item { u32 length; char name[length]; u32 ttype; u32 tclass; list types [[inline]]; }; struct role_trans_rule_item { role_set roles; role_set types; if (version >= 12) extensible_bitmap classes; u32 new_role; }; using role_trans_rule = list; struct role_allow_rule_item { role_set roles; role_set new_roles; }; using role_allow_rule = list; struct scope_s { u32 length; char key[length]; u32 scope; u32 decl_ids_len; std::assert(decl_ids_len >= 1, "Invalid 'decl_ids_len'"); u32 decl_id[decl_ids_len]; }; struct scope_index { extensible_bitmap scope[symbols_count]; u32 class_perms_len; extensible_bitmap class_perms_map[class_perms_len]; }; using scope_list = list; struct filename_trans_rule_item { u32 length; char name[length]; type_set stypes; type_set ttypes; u32 tclass; u32 otype; if (version >= 21) u32 flags; }; using filename_trans_rule = list; struct range_trans_rule_item { type_set stypes; type_set ttypes; extensible_bitmap tclasses; mls_semantic_range trange; }; using range_trans_rule = list; struct avrule_decl { u32 decl_id; u32 enabled; conditional_list cond_list; avrule_list avrules; role_trans_rule role_tr_rules; role_allow_rule role_allow_rules; if (version >= 11) filename_trans_rule filename_trans_rules; if (version >= 6) range_trans_rule range_tr_rules; scope_index required; scope_index declared; symbols symbols; }; struct avrule_block_item { u32 num_decls; if (num_decls > 0) avrule_decl avrule_decl[num_decls]; }; using avrule_block = list; struct initial_sid { u32 sid0; context_s context0; }; struct filesystem { u32 length; char key[length]; context_s context0; context_s context1; }; struct port { u32 protocol; u32 low_port; u32 high_port; context_s context; }; struct node { u32 addr; u32 mask; context_s context; }; struct fsuse { u32 behavior; u32 length; char name[length]; context_s context; }; struct node6 { u32 addr[4]; u32 mask[4]; context_s context; }; struct ibpkey { u32 low_pkey; u32 high_pkey; context_s context; }; struct ibpendport { u32 length; u32 port; char dev_name[length]; context_s context; }; struct ocontext_selinux { if (object_contexts_count < 1) break; list initial_sids; if (object_contexts_count < 2) break; list filesystems; if (object_contexts_count < 3) break; list ports; if (object_contexts_count < 4) break; list network_interfaces; // same type if (object_contexts_count < 5) break; list nodes; if (object_contexts_count < 6) break; list fsuses; if (object_contexts_count < 7) break; list nodes6; if (object_contexts_count < 8) break; list ibpkeys; if (object_contexts_count < 9) break; list ibpendports; }; struct xen_isid { u32 sid0; context_s context0; }; struct xen_pirq { u32 pirq; context_s context0; }; struct xen_ioport { u32 low_port; u32 high_port; context_s context0; }; struct xen_iomem { if (version >= 30) { u64 low_iomem; u64 high_iomem; } else { u32 low_iomem; u32 high_iomem; } context_s context; }; struct xen_pcidevice { u32 device; context_s context; }; struct xen_devicetree { u32 length; char name[length]; context_s context; }; struct ocontext_xen { if (object_contexts_count < 1) break; list xen_isids; if (object_contexts_count < 2) break; list xen_pirqs; if (object_contexts_count < 3) break; list xen_ioports; if (object_contexts_count < 4) break; list xen_iomems; if (object_contexts_count < 5) break; list xen_pcidevices; if (object_contexts_count < 6) break; list xen_devicetrees; if (object_contexts_count < 7) break; }; struct genfs2_item { u32 length; char name[length]; u32 sclass; context_s context0; }; struct genfs_item { u32 length; char fstype[length]; list [[inline]]; }; struct range_item { u32 source_type; u32 target_type; if (type_g == policy_types::kernel && version >= 21) u32 target_class; mls_range range_tr; }; struct Header { magics magic; std::assert(magic == magics::kernel || magic == magics::module , "Unexpected magic"); u32 policydb_str_len; char policydb_str[policydb_str_len]; std::assert(policydb_str == "SE Linux" || policydb_str == "SE Linux Module" || policydb_str == "XenFlask", "Unexpected signature"); if (policydb_str == "XenFlask") target = targets::xen; else target = targets::selinux; std::assert((magic == magics::kernel && (policydb_str == "SE Linux" || policydb_str == "XenFlask")) || (magic == magics::module && policydb_str == "SE Linux Module"), "Non matching magic and signature"); if (magic == magics::module) u32 policy_subtype; if (magic == magics::kernel) type_g = policy_types::kernel; else if (policy_subtype == policy_types::module) type_g = policy_types::module; else type_g = policy_types::base; u32 __policyvers; version = __policyvers; boundary_feature = (type_g == policy_types::kernel && version >= 24) || (type_g != policy_types::kernel && version >= 9); std::assert((magic == magics::kernel && 15 <= version && version <= 33) || (magic != magics::kernel && 4 <= version && version <= 21), "Non matching type_g != and type"); CONFIG config; u32 symbols_count_; symbols_count = symbols_count_; std::assert(0 <= symbols_count && symbols_count <= 9, "Invalid 'symbols_count' value."); u32 object_contexts_count_; object_contexts_count = object_contexts_count_; std::assert(0 <= object_contexts_count && object_contexts_count <= 9, "Invalid 'object_contexts_count' value."); if (magic == magics::module) module_header module_header; if ((type_g == policy_types::kernel && version >= 22) || (version >= 7)) extensible_bitmap policycaps; if (type_g == policy_types::kernel && version >= 23) extensible_bitmap permissive_map; symbols symbols; if (type_g == policy_types::kernel) { access_vector_table_s access_vector_table; } if (type_g == policy_types::kernel && version >= 16) conditional_list conditional_list; if (type_g == policy_types::kernel) { role_trans role_trans; role_allow role_allow; if (version >= 25) { if (version < 33) list filename_trans; else list filename_trans; } } else { list avrule_block; list scope_list[symbols_count]; } if (target == targets::selinux) ocontext_selinux ocontext_selinux; else ocontext_xen ocontext_xen; list genfs; if (((type_g == policy_types::kernel) && (version >= 19)) || ((type_g == policy_types::base) && (version == 5))) list range; if (type_g == policy_types::kernel) extensible_bitmap type_attr_map[type_primary_names_count]; }; Header header @ 0;