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 mls;
16pub(super) mod parser;
17pub(super) mod permissions;
18pub(super) mod roles;
19pub(super) mod rules;
20pub(super) mod traits;
21pub(super) mod u24_index;
22
23use selinux_policy_derive::{Parse, Serialize, Validate};
24
25use error::{ParseError, ValidateError};
26use metadata::{Config, Counts, Magic, PolicyVersion, Signature};
27pub use metadata::{HandleUnknown, POLICYDB_VERSION_MAX};
28use parser::{Array, PolicyCursor, RemainingBytes};
29use traits::Validate;
30pub use u24_index::U24Index;
31
32pub(super) mod booleans;
33pub(super) mod policy_cap;
34pub(super) mod types;
35pub(super) mod users;
36
37pub use access_vector::AccessVector;
38pub use bitmap::IdSpan;
39pub use booleans::{ConditionalBoolean, ConditionalBooleanId};
40pub use classes::{Class, ClassDefault, ClassDefaultRange, ClassId};
41pub use common_symbols::CommonSymbol;
42pub use constraints::{
43 ConstraintOperator, ConstraintSubject, ConstraintTerm, MlsOperands, MlsOperator, NameExpression,
44};
45pub use context::{Context, MlsLevel, MlsRange};
46pub use id_type::*;
47pub use indexed::IdAndNameIndexed;
48pub use mls::{Category, Sensitivity};
49pub use parser::SymbolArray;
50pub use permissions::PermissionId;
51pub use policy_cap::{PolicyCap, PolicyCapSet};
52pub use roles::{Role, RoleId, RoleSet};
53pub use rules::{
54 AccessDecision, AccessVectorRules, ConditionalNode, IndexedAccessVectorRules,
55 SELINUX_AVD_FLAGS_PERMISSIVE, XpermsBitmap,
56};
57pub use types::*;
58pub use users::User;
59
60#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
62pub struct UserTag;
63
64pub type UserId = IdType<std::num::NonZeroU16, UserTag>;
66
67#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
69pub struct SensitivityTag;
70
71pub type SensitivityId = IdType<std::num::NonZeroU16, SensitivityTag>;
73
74#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
76pub struct CategoryTag;
77
78pub type CategoryId = IdType<std::num::NonZeroU16, CategoryTag>;
80
81pub type CategorySet = bitmap::IdSet<CategoryId>;
83
84pub type CategorySetBuilder = bitmap::IdSetBuilder<CategoryId>;
86
87#[derive(Debug, Clone, Parse, Serialize, Validate)]
90pub struct NewPolicy {
91 magic: Magic,
92 signature: Signature,
93 version: PolicyVersion,
94 config: Config,
95 counts: Counts,
96 policy_capabilities: PolicyCapSet,
97 permissive_map: PermissiveTypeSet,
98 common_symbols: IdAndNameIndexed<SymbolArray<CommonSymbol>>,
99 classes: IdAndNameIndexed<SymbolArray<Class>>,
100 roles: IdAndNameIndexed<SymbolArray<Role>>,
101 types: Types,
102 users: IdAndNameIndexed<SymbolArray<User>>,
103 conditional_booleans: IdAndNameIndexed<SymbolArray<ConditionalBoolean>>,
104 sensitivities: IdAndNameIndexed<SymbolArray<Sensitivity>>,
105 categories: IdAndNameIndexed<SymbolArray<Category>>,
106 access_vector_rules: IndexedAccessVectorRules,
107 conditional_nodes: Array<ConditionalNode>,
108 rest: RemainingBytes,
109}
110
111impl NewPolicy {
112 pub fn parse(data: &[u8]) -> Result<Self, ParseError> {
114 let mut cursor = PolicyCursor::new(data);
115 cursor.parse()
116 }
117
118 pub fn validate(&self) -> Result<(), ValidateError> {
120 Validate::validate(self, self)
121 }
122
123 pub fn policy_version(&self) -> u32 {
125 self.version.get()
126 }
127
128 pub fn handle_unknown(&self) -> HandleUnknown {
130 self.config.handle_unknown()
131 }
132
133 pub fn policy_capabilities(&self) -> &PolicyCapSet {
135 &self.policy_capabilities
136 }
137
138 pub fn permissive_map(&self) -> &PermissiveTypeSet {
140 &self.permissive_map
141 }
142
143 pub fn common_symbols(&self) -> &IdAndNameIndexed<SymbolArray<CommonSymbol>> {
145 &self.common_symbols
146 }
147
148 pub fn classes(&self) -> &IdAndNameIndexed<SymbolArray<Class>> {
150 &self.classes
151 }
152
153 pub fn roles(&self) -> &IdAndNameIndexed<SymbolArray<Role>> {
155 &self.roles
156 }
157
158 pub fn types(&self) -> &Types {
160 &self.types
161 }
162
163 pub fn users(&self) -> &IdAndNameIndexed<SymbolArray<User>> {
165 &self.users
166 }
167
168 pub fn conditional_booleans(&self) -> &IdAndNameIndexed<SymbolArray<ConditionalBoolean>> {
170 &self.conditional_booleans
171 }
172
173 pub fn sensitivities(&self) -> &IdAndNameIndexed<SymbolArray<Sensitivity>> {
175 &self.sensitivities
176 }
177
178 pub fn categories(&self) -> &IdAndNameIndexed<SymbolArray<Category>> {
180 &self.categories
181 }
182
183 pub fn access_vector_rules(&self) -> &IndexedAccessVectorRules {
185 &self.access_vector_rules
186 }
187
188 pub fn conditional_nodes(&self) -> &[ConditionalNode] {
190 self.conditional_nodes.as_ref()
191 }
192
193 pub fn rest_bytes(&self) -> std::sync::Arc<[u8]> {
195 self.rest.bytes.clone()
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use crate::new_policy::traits::{HasName, Parse, Serialize};
203
204 #[derive(Copy, Clone, Debug, Eq, PartialEq, Parse, Serialize, Validate)]
205 #[policy(wire_type = u32)]
206 enum TestEnum {
207 ValueOne = 1,
208 ValueTwo = 2,
209 }
210
211 #[test]
212 fn test_enum_derive() {
213 let mut cursor = PolicyCursor::new(&[1, 0, 0, 0]);
214 let parsed = TestEnum::parse(&mut cursor).unwrap();
215 assert_eq!(parsed, TestEnum::ValueOne);
216
217 let mut cursor = PolicyCursor::new(&[2, 0, 0, 0]);
218 let parsed = TestEnum::parse(&mut cursor).unwrap();
219 assert_eq!(parsed, TestEnum::ValueTwo);
220
221 let mut cursor = PolicyCursor::new(&[3, 0, 0, 0]);
222 let err = TestEnum::parse(&mut cursor).unwrap_err();
223 assert!(matches!(err, ParseError::InvalidEnumValue { enum_name: "TestEnum", value: 3 }));
224
225 let mut writer = Vec::new();
226 TestEnum::ValueOne.serialize(&mut writer).unwrap();
227 assert_eq!(writer, vec![1, 0, 0, 0]);
228
229 let mut writer = Vec::new();
230 TestEnum::ValueTwo.serialize(&mut writer).unwrap();
231 assert_eq!(writer, vec![2, 0, 0, 0]);
232
233 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
234 let policy = NewPolicy::parse(policy_bytes).unwrap();
235 TestEnum::ValueOne.validate(&policy).unwrap();
236 }
237
238 #[test]
239 fn test_real_policy_roundtrip() {
240 let policy_bytes = include_bytes!("../../testdata/policies/selinux_testsuite");
241 let new_policy = NewPolicy::parse(policy_bytes).unwrap();
242 new_policy.validate().unwrap();
243
244 assert!(new_policy.policy_version() >= 30);
246 assert_eq!(new_policy.handle_unknown(), HandleUnknown::Allow);
247
248 let _caps = new_policy.policy_capabilities();
252 let _permissive = new_policy.permissive_map();
253
254 assert!(!new_policy.common_symbols().is_empty());
256 let common = &new_policy.common_symbols()[0];
257 assert!(!common.name().is_empty());
258 assert!(!common.permissions().is_empty());
259
260 assert!(!new_policy.classes().is_empty());
262 let class = &new_policy.classes()[0];
263 assert!(!class.name().is_empty());
264
265 assert!(!new_policy.types().is_empty());
267 let t = &new_policy.types().iter().next().unwrap();
268 assert!(!t.name().is_empty());
269
270 assert!(!new_policy.users().is_empty());
272 let u = &new_policy.users()[0];
273 assert!(!u.name().is_empty());
274
275 assert!(!new_policy.conditional_booleans().is_empty());
277 let b = &new_policy.conditional_booleans()[0];
278 assert!(!b.name().is_empty());
279
280 assert!(!new_policy.sensitivities().is_empty());
282 let s = &new_policy.sensitivities()[0];
283 assert!(!s.name().is_empty());
284
285 assert!(!new_policy.categories().is_empty());
287 let c = &new_policy.categories()[0];
288 assert!(!c.name().is_empty());
289
290 let _nodes = new_policy.conditional_nodes();
292
293 let mut serialized = Vec::new();
295 new_policy.serialize(&mut serialized).unwrap();
296 assert_eq!(serialized.len(), policy_bytes.len());
297 assert_eq!(serialized, policy_bytes);
298 }
299}