Skip to main content

selinux/policy/
parser.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::fmt::Debug;
6use std::marker::PhantomData;
7use std::ops::Deref;
8use std::sync::Arc;
9
10use selinux_policy_derive::{Parse, Serialize, Validate};
11use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
12
13use super::Policy;
14use super::error::{ParseError, SerializeError, ValidateError};
15use super::metadata::PolicyVersion;
16use super::traits::{Parse, Serialize, Validate};
17
18/// Raw binary policy data buffer.
19pub type PolicyData = Arc<[u8]>;
20
21/// Cursor used to parse elements from the binary policy data.
22#[derive(Debug)]
23pub struct PolicyCursor<'a> {
24    data: &'a [u8],
25    offset: usize,
26    policy_version: PolicyVersion,
27    types_count: u32,
28}
29
30impl<'a> PolicyCursor<'a> {
31    /// Creates a new [`PolicyCursor`] wrapping the supplied `data`.
32    pub fn new(data: &'a [u8]) -> Self {
33        Self { data, offset: 0, policy_version: PolicyVersion::V30, types_count: 0 }
34    }
35
36    /// Sets the SELinux policy database version on this cursor.
37    pub fn set_policy_version(&mut self, version: PolicyVersion) {
38        self.policy_version = version;
39    }
40
41    /// Returns the SELinux policy database version recorded on this cursor.
42    pub fn policy_version(&self) -> PolicyVersion {
43        self.policy_version
44    }
45
46    /// Sets the number of types recorded on this cursor.
47    pub fn set_types_count(&mut self, count: u32) {
48        self.types_count = count;
49    }
50
51    /// Returns the number of types recorded on this cursor.
52    pub fn types_count(&self) -> u32 {
53        self.types_count
54    }
55
56    /// Returns the current offset of the cursor.
57    pub fn offset(&self) -> usize {
58        self.offset
59    }
60
61    /// Parses a type `T` that implements [`Parse`] from the cursor.
62    pub fn parse<T: Parse>(&mut self) -> Result<T, ParseError> {
63        T::parse(self)
64    }
65
66    /// Parses `count` contiguous elements of type `T` from the cursor.
67    fn parse_elements<T: Parse>(&mut self, count: usize) -> Result<Box<[T]>, ParseError> {
68        let mut elements = Vec::with_capacity(count);
69        for _ in 0..count {
70            elements.push(self.parse()?);
71        }
72        Ok(elements.into_boxed_slice())
73    }
74
75    /// Reads a generic sized, zerocopyable type directly from the cursor.
76    fn read<T: FromBytes + KnownLayout + Immutable + Unaligned>(
77        &mut self,
78    ) -> Result<T, ParseError> {
79        let size = std::mem::size_of::<T>();
80        let bytes = self.read_bytes(size)?;
81        // Safe because T is FromBytes, Immutable, Unaligned and bytes is exactly `size` bytes.
82        let value = T::read_from_bytes(bytes).map_err(|_| ParseError::MissingData {
83            type_name: std::any::type_name::<T>(),
84            type_size: size,
85            num_bytes: bytes.len(),
86        })?;
87        Ok(value)
88    }
89
90    /// Reads a byte slice of `count` bytes from the cursor.
91    pub fn read_bytes(&mut self, count: usize) -> Result<&'a [u8], ParseError> {
92        if self.offset + count > self.data.len() {
93            return Err(ParseError::MissingData {
94                type_name: "bytes",
95                type_size: count,
96                num_bytes: self.data.len() - self.offset,
97            });
98        }
99        let bytes = &self.data[self.offset..self.offset + count];
100        self.offset += count;
101        Ok(bytes)
102    }
103}
104
105/// Writer used to serialize elements into a byte vector for a specific policy version.
106#[derive(Debug)]
107pub struct PolicyWriter<'a> {
108    version: PolicyVersion,
109    writer: &'a mut Vec<u8>,
110}
111
112impl<'a> PolicyWriter<'a> {
113    /// Creates a new [`PolicyWriter`] wrapping `writer` for the specified `version`.
114    pub fn new(version: PolicyVersion, writer: &'a mut Vec<u8>) -> Self {
115        Self { version, writer }
116    }
117
118    /// Returns target [`PolicyVersion`].
119    pub fn version(&self) -> PolicyVersion {
120        self.version
121    }
122
123    /// Appends raw bytes into destination writer.
124    pub fn write_bytes(&mut self, bytes: &[u8]) {
125        self.writer.extend_from_slice(bytes);
126    }
127}
128
129impl Parse for u8 {
130    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
131        cursor.read::<u8>()
132    }
133}
134
135impl Serialize for u8 {
136    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
137        writer.write_bytes(&[*self]);
138        Ok(())
139    }
140}
141
142impl Validate for u8 {
143    fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
144        Ok(())
145    }
146}
147
148impl Parse for u16 {
149    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
150        let val: le::U16 = cursor.read::<le::U16>()?;
151        Ok(val.get())
152    }
153}
154
155impl Serialize for u16 {
156    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
157        let val = le::U16::new(*self);
158        writer.write_bytes(zerocopy::IntoBytes::as_bytes(&val));
159        Ok(())
160    }
161}
162
163impl Validate for u16 {
164    fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
165        Ok(())
166    }
167}
168
169impl Parse for u32 {
170    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
171        let val: le::U32 = cursor.read::<le::U32>()?;
172        Ok(val.get())
173    }
174}
175
176impl Serialize for u32 {
177    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
178        let val = le::U32::new(*self);
179        writer.write_bytes(zerocopy::IntoBytes::as_bytes(&val));
180        Ok(())
181    }
182}
183
184impl Validate for u32 {
185    fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
186        Ok(())
187    }
188}
189
190/// Container representing a `u32` count followed by that many raw bytes.
191#[derive(Debug, Clone, PartialEq, Eq, Validate)]
192pub struct ByteArray {
193    data: Box<[u8]>,
194}
195
196impl Deref for ByteArray {
197    type Target = [u8];
198    fn deref(&self) -> &Self::Target {
199        &self.data
200    }
201}
202
203impl AsRef<[u8]> for ByteArray {
204    fn as_ref(&self) -> &[u8] {
205        &self.data
206    }
207}
208
209impl Parse for ByteArray {
210    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
211        let count = u32::parse(cursor)? as usize;
212        let bytes = cursor.read_bytes(count)?;
213        Ok(Self { data: bytes.to_vec().into_boxed_slice() })
214    }
215}
216
217impl Serialize for ByteArray {
218    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
219        let count = self.data.len() as u32;
220        count.serialize(writer)?;
221        writer.write_bytes(&self.data);
222        Ok(())
223    }
224}
225
226impl Parse for u64 {
227    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
228        let val: le::U64 = cursor.read::<le::U64>()?;
229        Ok(val.get())
230    }
231}
232
233impl Serialize for u64 {
234    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
235        let val = le::U64::new(*self);
236        writer.write_bytes(zerocopy::IntoBytes::as_bytes(&val));
237        Ok(())
238    }
239}
240
241impl Validate for u64 {
242    fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
243        Ok(())
244    }
245}
246
247impl<T: Parse, const N: usize> Parse for [T; N] {
248    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
249        let mut items = Vec::with_capacity(N);
250        for _ in 0..N {
251            items.push(T::parse(cursor)?);
252        }
253        Ok(items.try_into().ok().expect("pushed N items"))
254    }
255}
256
257impl<T: Serialize, const N: usize> Serialize for [T; N] {
258    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
259        for item in self {
260            item.serialize(writer)?;
261        }
262        Ok(())
263    }
264}
265
266impl<T: Validate, const N: usize> Validate for [T; N] {
267    fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
268        for item in self {
269            item.validate(policy)?;
270        }
271        Ok(())
272    }
273}
274
275impl<T: Serialize> Serialize for Box<[T]> {
276    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
277        for item in self.iter() {
278            item.serialize(writer)?;
279        }
280        Ok(())
281    }
282}
283
284impl<T: Validate> Validate for Box<[T]> {
285    fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
286        for item in self.iter() {
287            item.validate(policy)?;
288        }
289        Ok(())
290    }
291}
292
293impl<T> Parse for PhantomData<T> {
294    fn parse(_cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
295        Ok(Self)
296    }
297}
298
299impl<T> Serialize for PhantomData<T> {
300    fn serialize(&self, _writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
301        Ok(())
302    }
303}
304
305impl<T> Validate for PhantomData<T> {
306    fn validate(&self, _policy: &Policy) -> Result<(), ValidateError> {
307        Ok(())
308    }
309}
310
311/// Standard policy array container, storing elements in a heap-allocated slice.
312/// Prefixed by a 32-bit count field in the binary policy format.
313#[derive(Debug, Clone, PartialEq, Eq, Hash, Validate)]
314pub struct Array<T> {
315    elements: Box<[T]>,
316}
317
318impl<T> Default for Array<T> {
319    fn default() -> Self {
320        Self { elements: Box::new([]) }
321    }
322}
323
324impl<T> From<Vec<T>> for Array<T> {
325    fn from(v: Vec<T>) -> Self {
326        Self { elements: v.into_boxed_slice() }
327    }
328}
329
330impl<T> Deref for Array<T> {
331    type Target = [T];
332    fn deref(&self) -> &Self::Target {
333        &self.elements
334    }
335}
336
337#[cfg(test)]
338impl<T> std::ops::DerefMut for Array<T> {
339    fn deref_mut(&mut self) -> &mut Self::Target {
340        &mut self.elements
341    }
342}
343
344impl<T> AsRef<[T]> for Array<T> {
345    fn as_ref(&self) -> &[T] {
346        &self.elements
347    }
348}
349
350impl<T: Parse> Parse for Array<T> {
351    fn parse(cursor: &mut PolicyCursor<'_>) -> Result<Self, ParseError> {
352        let count = u32::parse(cursor)? as usize;
353        let elements = cursor.parse_elements(count)?;
354        Ok(Self { elements })
355    }
356}
357
358impl<T: Serialize> Serialize for Array<T> {
359    fn serialize(&self, writer: &mut PolicyWriter<'_>) -> Result<(), SerializeError> {
360        let count = self.elements.len() as u32;
361        count.serialize(writer)?;
362        self.elements.serialize(writer)
363    }
364}
365
366/// Symbol list header and associated array of items.
367///
368/// In the SELinux binary policy database, each symbol table is prefixed by a header
369/// containing a `primary_names_count` field, followed by the array of items (which itself
370/// is prefixed by an `items_count` field).
371#[derive(Debug, Parse, Serialize)]
372pub struct SymbolArray<T> {
373    /// Number of primary names in this array (excluding aliases).
374    /// Included in the policy to allow allocation of index structures to be optimized.
375    primary_names_count: u32,
376    items: Array<T>,
377}
378
379impl<T> Deref for SymbolArray<T> {
380    type Target = [T];
381    fn deref(&self) -> &Self::Target {
382        &self.items
383    }
384}
385
386#[cfg(test)]
387impl<T> std::ops::DerefMut for SymbolArray<T> {
388    fn deref_mut(&mut self) -> &mut Self::Target {
389        &mut self.items
390    }
391}
392
393impl<T: Validate> Validate for SymbolArray<T> {
394    fn validate(&self, policy: &Policy) -> Result<(), ValidateError> {
395        self.items.validate(policy)?;
396        if self.primary_names_count > self.items.len() as u32 {
397            return Err(ValidateError::InvalidPrimaryNamesCount {
398                expected_at_most: self.items.len() as u32,
399                found: self.primary_names_count,
400            });
401        }
402        Ok(())
403    }
404}
405
406#[cfg(test)]
407mod tests {
408    use super::*;
409    use crate::policy::metadata::PolicyVersion;
410
411    #[test]
412    fn test_policy_cursor_parse_u32() {
413        let data = [1, 0, 0, 0, 2, 0, 0, 0];
414        let mut cursor = PolicyCursor::new(&data);
415
416        let val1 = cursor.parse::<u32>().unwrap();
417        assert_eq!(val1, 1);
418        assert_eq!(cursor.offset, 4);
419
420        let val2 = cursor.parse::<u32>().unwrap();
421        assert_eq!(val2, 2);
422        assert_eq!(cursor.offset, 8);
423    }
424
425    #[test]
426    fn test_policy_cursor_parse_u64() {
427        let data = [1, 0, 0, 0, 0, 0, 0, 0];
428        let mut cursor = PolicyCursor::new(&data);
429        let val = cursor.parse::<u64>().unwrap();
430        assert_eq!(val, 1);
431        assert_eq!(cursor.offset, 8);
432    }
433
434    #[test]
435    fn test_policy_cursor_parse_elements() {
436        let data = [1, 0, 0, 0, 2, 0, 0, 0];
437        let mut cursor = PolicyCursor::new(&data);
438
439        let elements = cursor.parse_elements::<u32>(2).unwrap();
440        assert_eq!(elements.as_ref(), &[1, 2]);
441        assert_eq!(cursor.offset, 8);
442    }
443
444    #[test]
445    fn test_policy_cursor_missing_data_u32() {
446        let data = [1, 0];
447        let mut cursor = PolicyCursor::new(&data);
448
449        let err = cursor.parse::<u32>().unwrap_err();
450        assert!(matches!(
451            err,
452            ParseError::MissingData { type_name: "bytes", type_size: 4, num_bytes: 2 }
453        ));
454    }
455
456    #[test]
457    fn test_u32_serialize() {
458        let val = 42u32;
459        let mut writer = Vec::new();
460        let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
461        val.serialize(&mut policy_writer).unwrap();
462        assert_eq!(writer, [42, 0, 0, 0]);
463    }
464
465    #[test]
466    fn test_u64_serialize() {
467        let val = 42u64;
468        let mut writer = Vec::new();
469        let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
470        val.serialize(&mut policy_writer).unwrap();
471        assert_eq!(writer, [42, 0, 0, 0, 0, 0, 0, 0]);
472    }
473
474    #[test]
475    fn test_policy_cursor_byte_array() {
476        let data = [4, 0, 0, 0, 5, 6, 7, 8];
477        let mut cursor = PolicyCursor::new(&data);
478
479        let array = cursor.parse::<ByteArray>().unwrap();
480        assert_eq!(array.as_ref(), &[5, 6, 7, 8]);
481        assert_eq!(cursor.offset, 8);
482    }
483
484    #[test]
485    fn test_policy_cursor_byte_array_missing_data() {
486        let data = [5, 0, 0, 0, 6, 7, 8];
487        let mut cursor = PolicyCursor::new(&data);
488
489        let err = cursor.parse::<ByteArray>().unwrap_err();
490        assert!(matches!(
491            err,
492            ParseError::MissingData { type_name: "bytes", type_size: 5, num_bytes: 3 }
493        ));
494    }
495
496    #[test]
497    fn test_byte_array_serialize() {
498        let array = ByteArray { data: vec![5, 6, 7, 8].into_boxed_slice() };
499        let mut writer = Vec::new();
500        let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
501        array.serialize(&mut policy_writer).unwrap();
502        assert_eq!(writer, [4, 0, 0, 0, 5, 6, 7, 8]);
503    }
504
505    #[test]
506    fn test_array_parse_and_serialize() {
507        let data = [2, 0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0];
508        let mut cursor = PolicyCursor::new(&data);
509
510        let array = cursor.parse::<Array<u32>>().unwrap();
511        assert_eq!(array.as_ref(), &[10, 20]);
512        assert_eq!(cursor.offset, 12);
513
514        let mut writer = Vec::new();
515        let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
516        array.serialize(&mut policy_writer).unwrap();
517        assert_eq!(writer, data);
518    }
519
520    #[test]
521    fn test_symbol_array_parse_and_serialize() {
522        // primary_names_count = 5, array count = 2, elements = [10, 20]
523        let data = [5, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0];
524        let mut cursor = PolicyCursor::new(&data);
525
526        let sym_array = cursor.parse::<SymbolArray<u32>>().unwrap();
527        assert_eq!(sym_array.primary_names_count, 5);
528        assert_eq!(sym_array.as_ref(), &[10, 20]);
529        assert_eq!(cursor.offset, 16);
530
531        let mut writer = Vec::new();
532        let mut policy_writer = PolicyWriter::new(PolicyVersion::V33, &mut writer);
533        sym_array.serialize(&mut policy_writer).unwrap();
534        assert_eq!(writer, data);
535    }
536}