1pub(super) mod access_vector;
6pub(super) mod bitmap;
7pub(super) mod classes;
8pub(super) mod common_symbols;
9pub(super) mod constraints;
10pub(super) mod context;
11pub(super) mod error;
12pub(super) mod id_type;
13pub(super) mod indexed;
14pub(super) mod metadata;
15pub(super) mod parser;
16pub(super) mod permissions;
17pub(super) mod traits;
18
19use selinux_policy_derive::{Parse, Serialize, Validate};
20
21use error::{ParseError, ValidateError};
22use metadata::{Config, Counts, Magic, PolicyVersion, Signature};
23pub use metadata::{HandleUnknown, POLICYDB_VERSION_MAX};
24use parser::{PolicyCursor, RemainingBytes};
25use traits::Validate;
26
27pub(super) mod types;
28
29pub use access_vector::AccessVector;
30pub use bitmap::{ExtensibleBitmap, IdSpan};
31pub use classes::{Class, ClassDefault, ClassDefaultRange, ClassId};
32pub use common_symbols::CommonSymbol;
33pub use constraints::{
34 ConstraintNames, ConstraintOperand, ConstraintOperator, ConstraintSubject, ConstraintTerm,
35};
36pub use context::{Context, MlsLevel, MlsRange};
37pub use id_type::*;
38pub use indexed::IdAndNameIndexed;
39pub use parser::SymbolArray;
40pub use permissions::PermissionId;
41pub use types::*;
42
43#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
45pub struct UserTag;
46
47pub type UserId = IdType<std::num::NonZeroU16, UserTag>;
49
50#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
52pub struct RoleTag;
53
54pub type RoleId = IdType<std::num::NonZeroU16, RoleTag>;
56
57#[derive(Debug, Clone, Parse, Serialize, Validate)]
60pub struct NewPolicy {
61 magic: Magic,
62 signature: Signature,
63 version: PolicyVersion,
64 config: Config,
65 counts: Counts,
66 policy_capabilities: ExtensibleBitmap,
67 permissive_map: PermissiveTypeSet,
68 common_symbols: IdAndNameIndexed<SymbolArray<CommonSymbol>>,
69 classes: IdAndNameIndexed<SymbolArray<Class>>,
70 rest: RemainingBytes,
71}
72
73impl NewPolicy {
74 pub fn parse(data: &[u8]) -> Result<Self, ParseError> {
76 let mut cursor = PolicyCursor::new(data);
77 cursor.parse()
78 }
79
80 pub fn validate(&self) -> Result<(), ValidateError> {
82 Validate::validate(self, self)
83 }
84
85 pub fn policy_version(&self) -> u32 {
87 self.version.get()
88 }
89
90 pub fn handle_unknown(&self) -> HandleUnknown {
92 self.config.handle_unknown()
93 }
94
95 pub fn policy_capabilities(&self) -> &ExtensibleBitmap {
97 &self.policy_capabilities
98 }
99
100 pub fn permissive_map(&self) -> &PermissiveTypeSet {
102 &self.permissive_map
103 }
104
105 pub fn common_symbols(&self) -> &IdAndNameIndexed<SymbolArray<CommonSymbol>> {
107 &self.common_symbols
108 }
109
110 pub fn classes(&self) -> &IdAndNameIndexed<SymbolArray<Class>> {
112 &self.classes
113 }
114
115 pub fn rest_bytes(&self) -> std::sync::Arc<[u8]> {
117 self.rest.bytes.clone()
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use crate::new_policy::traits::{HasName, Parse, Serialize};
125
126 #[derive(Copy, Clone, Debug, Eq, PartialEq, Parse, Serialize, Validate)]
127 #[policy(wire_type = u32)]
128 enum TestEnum {
129 ValueOne = 1,
130 ValueTwo = 2,
131 }
132
133 #[test]
134 fn test_enum_derive() {
135 let mut cursor = PolicyCursor::new(&[1, 0, 0, 0]);
136 let parsed = TestEnum::parse(&mut cursor).unwrap();
137 assert_eq!(parsed, TestEnum::ValueOne);
138
139 let mut cursor = PolicyCursor::new(&[2, 0, 0, 0]);
140 let parsed = TestEnum::parse(&mut cursor).unwrap();
141 assert_eq!(parsed, TestEnum::ValueTwo);
142
143 let mut cursor = PolicyCursor::new(&[3, 0, 0, 0]);
144 let err = TestEnum::parse(&mut cursor).unwrap_err();
145 assert!(matches!(err, ParseError::InvalidEnumValue { enum_name: "TestEnum", value: 3 }));
146
147 let mut writer = Vec::new();
148 TestEnum::ValueOne.serialize(&mut writer).unwrap();
149 assert_eq!(writer, vec![1, 0, 0, 0]);
150
151 let mut writer = Vec::new();
152 TestEnum::ValueTwo.serialize(&mut writer).unwrap();
153 assert_eq!(writer, vec![2, 0, 0, 0]);
154
155 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
156 let policy = NewPolicy::parse(policy_bytes).unwrap();
157 TestEnum::ValueOne.validate(&policy).unwrap();
158 }
159
160 #[test]
161 fn test_real_policy_roundtrip() {
162 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
163 let new_policy = NewPolicy::parse(policy_bytes).unwrap();
164 new_policy.validate().unwrap();
165
166 assert!(new_policy.policy_version() >= 30);
168 assert_eq!(new_policy.handle_unknown(), HandleUnknown::Allow);
169
170 let _caps = new_policy.policy_capabilities();
174 let _permissive = new_policy.permissive_map();
175
176 assert!(!new_policy.common_symbols().is_empty());
178 let common = &new_policy.common_symbols()[0];
179 assert!(!common.name().is_empty());
180 assert!(!common.permissions().is_empty());
181
182 assert!(!new_policy.classes().is_empty());
184 let class = &new_policy.classes()[0];
185 assert!(!class.name().is_empty());
186
187 let mut serialized = Vec::new();
189 new_policy.serialize(&mut serialized).unwrap();
190 assert_eq!(serialized.len(), policy_bytes.len());
191 assert_eq!(serialized, policy_bytes);
192 }
193}