From 19dd39e7c05c2e9706e72b5369d1ab3cf463d3d1 Mon Sep 17 00:00:00 2001 From: Ange Albertini Date: Wed, 12 Jul 2023 20:25:47 +0200 Subject: [PATCH] patterns: Added SE Linux binary format pattern (#139) * SE Linux policy binary module, base, kernel and packages * Updated README with SELinux patterns * SELinux test files --- README.md | 2 + patterns/selinux.hexpat | 713 +++++++++++++++++++ patterns/selinuxpp.hexpat | 28 + tests/patterns/test_data/selinux.hexpat.bin | Bin 0 -> 36410 bytes tests/patterns/test_data/selinuxpp.hexpat.pp | Bin 0 -> 36489 bytes 5 files changed, 743 insertions(+) create mode 100644 patterns/selinux.hexpat create mode 100644 patterns/selinuxpp.hexpat create mode 100644 tests/patterns/test_data/selinux.hexpat.bin create mode 100644 tests/patterns/test_data/selinuxpp.hexpat.pp diff --git a/README.md b/README.md index 761f37a..5f068d5 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout | | Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files | | BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files | +| BIN | | [`patterns/selinux.hexpat`](patterns/selinux.pat) | SE Linux modules | | BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format | | BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) | | CCHVA | | [`patterns/cchva.hexpat`](patterns/cchva.hexpat) | Command and Conquer Voxel Animation | @@ -74,6 +75,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets | | PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format | | PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields | +| PP | [`patterns/selinuxpp.hexpat`](patterns/selinuxpp.pat) | SE Linux package | | PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) | | PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format | | PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files | diff --git a/patterns/selinux.hexpat b/patterns/selinux.hexpat new file mode 100644 index 0000000..6372a9f --- /dev/null +++ b/patterns/selinux.hexpat @@ -0,0 +1,713 @@ +#include +#pragma pattern_limit 13107200 +#pragma endian little + +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, +}; + + +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"); + u32 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; diff --git a/patterns/selinuxpp.hexpat b/patterns/selinuxpp.hexpat new file mode 100644 index 0000000..ad08786 --- /dev/null +++ b/patterns/selinuxpp.hexpat @@ -0,0 +1,28 @@ +// SE Linux Policy Package +// Extension: PP +// https://github.com/SELinuxProject/selinux/blob/master/libsepol/src/module.c + +#pragma endian little +#include + +enum section_types : u32 { + file_context = 0xf97cff90, + module = 0xf97cff8d, + user = 0x097cff91, + user_extra = 0x097cff92, + netfilter = 0x097cff93, +}; + +struct section_s { + section_types *type : u32; +}; + +struct header_s { + u32 magic; + std::assert(magic == 0xf97cff8f, "invalid magic"); + u32 version; + u32 sections_count; + section_s sections[sections_count]; +}; + +header_s header @ 0x00; diff --git a/tests/patterns/test_data/selinux.hexpat.bin b/tests/patterns/test_data/selinux.hexpat.bin new file mode 100644 index 0000000000000000000000000000000000000000..26e1cc451ae944cabcc240e60382e7638c2d6d05 GIT binary patch literal 36410 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 literal 0 HcmV?d00001 diff --git a/tests/patterns/test_data/selinuxpp.hexpat.pp b/tests/patterns/test_data/selinuxpp.hexpat.pp new file mode 100644 index 0000000000000000000000000000000000000000..63475a5c87af5d9047a6597b42e10f0a6120c9c0 GIT binary patch literal 36489 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 literal 0 HcmV?d00001