selinux/policy/
symbols.rs

1// Copyright 2023 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 super::constraints::{ConstraintError, evaluate_constraint};
6use super::error::ValidateError;
7use super::extensible_bitmap::{
8    ExtensibleBitmap, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator,
9};
10use super::parser::PolicyCursor;
11use super::security_context::{CategoryIterator, Level, SecurityContext};
12use super::{
13    AccessVector, Array, CategoryId, ClassId, ClassPermissionId, Counted, Parse,
14    PolicyValidationContext, RoleId, SensitivityId, TypeId, UserId, Validate, ValidateArray,
15    array_type, array_type_validate_deref_both, array_type_validate_deref_data,
16    array_type_validate_deref_metadata_data_vec, array_type_validate_deref_none_data_vec,
17};
18
19use anyhow::{Context as _, anyhow};
20use std::fmt::Debug;
21use std::num::{NonZeroU8, NonZeroU32};
22use std::ops::Deref;
23use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
24
25/// ** Constraint term types ***
26///
27/// The `constraint_term_type` metadata field value for a [`ConstraintTerm`]
28/// that represents the "not" operator.
29pub(super) const CONSTRAINT_TERM_TYPE_NOT_OPERATOR: u32 = 1;
30/// The `constraint_term_type` metadata field value for a [`ConstraintTerm`]
31/// that represents the "and" operator.
32pub(super) const CONSTRAINT_TERM_TYPE_AND_OPERATOR: u32 = 2;
33/// The `constraint_term_type` metadata field value for a [`ConstraintTerm`]
34/// that represents the "or" operator.
35pub(super) const CONSTRAINT_TERM_TYPE_OR_OPERATOR: u32 = 3;
36/// The `constraint_term_type` metadata field value for a [`ConstraintTerm`]
37/// that represents a boolean expression where both arguments are fields of
38/// a source and/or target security context.
39pub(super) const CONSTRAINT_TERM_TYPE_EXPR: u32 = 4;
40/// The `constraint_term_type` metadata field value for a [`ConstraintTerm`]
41/// that represents a boolean expression where:
42///
43/// - the left-hand side is the user, role, or type of the source or target
44///   security context
45/// - the right-hand side is a set of users, roles, or types that are
46///   specified by name in the text policy, independent of the source
47///   or target security context.
48///
49/// In this case, the [`ConstraintTerm`] contains an [`ExtensibleBitmap`] that
50/// encodes the set of user, role, or type IDs corresponding to the names, and a
51/// [`TypeSet`] encoding the corresponding set of types.
52pub(super) const CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES: u32 = 5;
53
54/// ** Constraint expression operator types ***
55///
56/// Valid `expr_operator_type` metadata field values for a [`ConstraintTerm`]
57/// with `type` equal to `CONSTRAINT_TERM_TYPE_EXPR` or
58/// `CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES`.
59///
60/// NB. `EXPR_OPERATOR_TYPE_{DOM,DOMBY,INCOMP}` were previously valid for
61///      constraints on role IDs, but this was deprecated as of SELinux
62///      policy version 26.
63///
64/// The `expr_operator_type` value for an expression of form "A == B".
65/// Valid for constraints on user, role, and type IDs.
66pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_EQ: u32 = 1;
67/// The `expr_operator_type` value for an expression of form "A != B".
68/// Valid for constraints on user, role, and type IDs.
69pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_NE: u32 = 2;
70/// The `expr_operator_type` value for an expression of form "A dominates B".
71/// Valid for constraints on security levels.
72pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_DOM: u32 = 3;
73/// The `expr_operator_type` value for an expression of form "A is dominated
74/// by B".
75/// Valid for constraints on security levels.
76pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY: u32 = 4;
77/// The `expr_operator_type` value for an expression of form "A is
78/// incomparable to B".
79/// Valid for constraints on security levels.
80pub(super) const CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP: u32 = 5;
81
82/// ** Constraint expression types ***
83///
84/// Although these values each have a single bit set, they appear to be
85/// used as enum values rather than as bit masks: i.e., the policy compiler
86/// does not produce access vector rule structures that have more than
87/// one of these types.
88///
89/// Valid `expr_operand_type` metadata field values for a [`ConstraintTerm`]
90/// with `constraint_term_type` equal to `CONSTRAINT_TERM_TYPE_EXPR` or
91/// `CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES`.
92///
93/// When the `constraint_term_type` is equal to `CONSTRAINT_TERM_TYPE_EXPR` and
94/// the `expr_operand_type` value is `EXPR_OPERAND_TYPE_{USER,ROLE,TYPE}`, the
95/// expression compares the source's {user,role,type} ID to the target's
96/// {user,role,type} ID.
97///
98/// When the `constraint_term_type` is equal to
99/// `CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES`, then the right-hand side of the
100/// expression is the set of IDs listed in the [`ConstraintTerm`]'s `names`
101/// field. The left-hand side of the expression is the user, role, or type ID of
102/// either the target security context, or the source security context,
103/// depending on whether the `EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK` bit of
104/// the `expr_operand_type` field is set (--> target) or not (--> source).
105///
106/// The `expr_operand_type` value for an expression comparing user IDs.
107pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_USER: u32 = 0x1;
108/// The `expr_operand_type` value for an expression comparing role IDs.
109pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_ROLE: u32 = 0x2;
110/// The `expr_operand_type` value for an expression comparing type IDs.
111pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_TYPE: u32 = 0x4;
112/// The `expr_operand_type` value for an expression comparing the source
113/// context's low security level to the target context's low security level.
114pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2: u32 = 0x20;
115/// The `expr_operand_type` value for an expression comparing the source
116/// context's low security level to the target context's high security level.
117pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2: u32 = 0x40;
118/// The `expr_operand_type` value for an expression comparing the source
119/// context's high security level to the target context's low security level.
120pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2: u32 = 0x80;
121/// The `expr_operand_type` value for an expression comparing the source
122/// context's high security level to the target context's high security level.
123pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2: u32 = 0x100;
124/// The `expr_operand_type` value for an expression comparing the source
125/// context's low security level to the source context's high security level.
126pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1: u32 = 0x200;
127/// The `expr_operand_type` value for an expression comparing the target
128/// context's low security level to the target context's high security level.
129pub(super) const CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2: u32 = 0x400;
130
131/// For a [`ConstraintTerm`] with `constraint_term_type` equal to
132/// `CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES` the `expr_operand_type` may have the
133/// `EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK` bit set in addition to one of the
134/// `EXPR_OPERAND_TYPE_{USER,ROLE,TYPE}` bits.
135///
136/// If the `EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK` bit is set, then the
137/// expression compares the target's {user,role,type} ID to the set of IDs
138/// listed in the [`ConstraintTerm`]'s `names` field.
139///
140/// If the bit is not set, then the expression compares the source's
141/// {user,role,type} ID to the set of IDs listed in the [`ConstraintTerm`]'s
142/// `names` field.
143pub(super) const CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK: u32 = 0x8;
144
145/// Exact value of [`Type`] `properties` when the underlying data refers to an SELinux type.
146pub(super) const TYPE_PROPERTIES_TYPE: u32 = 1;
147
148/// Exact value of [`Type`] `properties` when the underlying data refers to an SELinux alias.
149pub(super) const TYPE_PROPERTIES_ALIAS: u32 = 0;
150
151/// Exact value of [`Type`] `properties` when the underlying data refers to an SELinux attribute.
152pub(super) const TYPE_PROPERTIES_ATTRIBUTE: u32 = 0;
153
154/// [`SymbolList`] is an [`Array`] of items with the count of items determined by [`Metadata`] as
155/// [`Counted`].
156#[derive(Debug, PartialEq)]
157pub(super) struct SymbolList<T>(Array<Metadata, Vec<T>>);
158
159impl<T> Deref for SymbolList<T> {
160    type Target = Array<Metadata, Vec<T>>;
161
162    fn deref(&self) -> &Self::Target {
163        &self.0
164    }
165}
166
167impl<T: Parse> Parse for SymbolList<T> {
168    type Error = <Array<Metadata, Vec<T>> as Parse>::Error;
169
170    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
171        let (array, tail) = Array::<Metadata, Vec<T>>::parse(bytes)?;
172        Ok((Self(array), tail))
173    }
174}
175
176impl<T> Validate for SymbolList<T>
177where
178    [T]: Validate,
179{
180    type Error = anyhow::Error;
181
182    /// [`SymbolList`] has no internal constraints beyond those imposed by [`Array`].
183    fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
184        self.metadata.validate(context).map_err(Into::<anyhow::Error>::into)?;
185        self.data.as_slice().validate(context).map_err(Into::<anyhow::Error>::into)?;
186
187        Ok(())
188    }
189}
190
191/// Binary metadata prefix to [`SymbolList`] objects.
192#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
193#[repr(C, packed)]
194pub(super) struct Metadata {
195    /// The number of primary names referred to in the associated [`SymbolList`].
196    primary_names_count: le::U32,
197    /// The number of objects in the associated [`SymbolList`] [`Array`].
198    count: le::U32,
199}
200
201impl Metadata {
202    pub fn primary_names_count(&self) -> u32 {
203        self.primary_names_count.get()
204    }
205}
206
207impl Counted for Metadata {
208    /// The number of items that follow a [`Metadata`] is the value stored in the `metadata.count`
209    /// field.
210    fn count(&self) -> u32 {
211        self.count.get()
212    }
213}
214
215impl Validate for Metadata {
216    type Error = anyhow::Error;
217
218    /// TODO: Should there be an upper bound on `primary_names_count` or `count`?
219    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
220        Ok(())
221    }
222}
223
224impl Validate for [CommonSymbol] {
225    type Error = <CommonSymbol as Validate>::Error;
226
227    /// [`CommonSymbols`] have no internal constraints beyond those imposed by individual
228    /// [`CommonSymbol`] objects.
229    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
230        Ok(())
231    }
232}
233
234array_type!(CommonSymbol, CommonSymbolMetadata, Permissions);
235
236array_type_validate_deref_none_data_vec!(CommonSymbol);
237
238impl CommonSymbol {
239    pub fn permissions(&self) -> &Permissions {
240        &self.data
241    }
242}
243
244pub(super) type CommonSymbols = Vec<CommonSymbol>;
245
246impl CommonSymbol {
247    /// Returns the name of this common symbol (a string), encoded a borrow of a byte slice. For
248    /// example, the policy statement `common file { common_file_perm }` induces a [`CommonSymbol`]
249    /// where `name_bytes() == "file".as_slice()`.
250    pub fn name_bytes(&self) -> &[u8] {
251        &self.metadata.data
252    }
253}
254
255impl Counted for CommonSymbol {
256    /// The count of items in the associated [`Permissions`] is exposed via
257    /// `CommonSymbolMetadata::count()`.
258    fn count(&self) -> u32 {
259        self.metadata.count()
260    }
261}
262
263impl ValidateArray<CommonSymbolMetadata, Permission> for CommonSymbol {
264    type Error = anyhow::Error;
265
266    /// [`CommonSymbol`] have no internal constraints beyond those imposed by [`Array`].
267    fn validate_array(
268        _context: &mut PolicyValidationContext,
269        _metadata: &CommonSymbolMetadata,
270        _items: &[Permission],
271    ) -> Result<(), Self::Error> {
272        Ok(())
273    }
274}
275
276array_type!(CommonSymbolMetadata, CommonSymbolStaticMetadata, Vec<u8>);
277
278array_type_validate_deref_both!(CommonSymbolMetadata);
279
280impl Counted for CommonSymbolMetadata {
281    /// The count of items in the associated [`Permissions`] is stored in the associated
282    /// `CommonSymbolStaticMetadata::count` field.
283    fn count(&self) -> u32 {
284        self.metadata.count.get()
285    }
286}
287
288impl ValidateArray<CommonSymbolStaticMetadata, u8> for CommonSymbolMetadata {
289    type Error = anyhow::Error;
290
291    /// Array of [`u8`] sized by [`CommonSymbolStaticMetadata`] requires no additional validation.
292    fn validate_array(
293        _context: &mut PolicyValidationContext,
294        _metadata: &CommonSymbolStaticMetadata,
295        _items: &[u8],
296    ) -> Result<(), Self::Error> {
297        Ok(())
298    }
299}
300
301/// Static (that is, fixed-sized) metadata for a common symbol.
302#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
303#[repr(C, packed)]
304pub(super) struct CommonSymbolStaticMetadata {
305    /// The length of the `[u8]` key stored in the associated [`CommonSymbolMetadata`].
306    length: le::U32,
307    /// An integer that identifies this this common symbol, unique to this common symbol relative
308    /// to all common symbols and classes in this policy.
309    id: le::U32,
310    /// The number of primary names referred to by the associated [`CommonSymbol`].
311    primary_names_count: le::U32,
312    /// The number of items stored in the [`Permissions`] in the associated [`CommonSymbol`].
313    count: le::U32,
314}
315
316impl Validate for CommonSymbolStaticMetadata {
317    type Error = anyhow::Error;
318
319    /// TODO: Should there be an upper bound on `length`?
320    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
321        Ok(())
322    }
323}
324
325impl Counted for CommonSymbolStaticMetadata {
326    /// The count of bytes in the `[u8]` in the associated [`CommonSymbolMetadata`].
327    fn count(&self) -> u32 {
328        self.length.get()
329    }
330}
331
332/// [`Permissions`] is a dynamically allocated slice (that is, [`Vec`]) of [`Permission`].
333pub(super) type Permissions = Vec<Permission>;
334
335impl Validate for Permissions {
336    type Error = anyhow::Error;
337
338    /// [`Permissions`] have no internal constraints beyond those imposed by individual
339    /// [`Permission`] objects.
340    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
341        Ok(())
342    }
343}
344
345array_type!(Permission, PermissionMetadata, Vec<u8>);
346
347array_type_validate_deref_both!(Permission);
348
349impl Permission {
350    /// Returns the name of this permission (a string), encoded a borrow of a byte slice. For
351    /// example the class named `"file"` class has a permission named `"entrypoint"` and the
352    /// `"process"` class has a permission named `"fork"`.
353    pub fn name_bytes(&self) -> &[u8] {
354        &self.data
355    }
356
357    /// Returns the ID of this permission in the scope of its associated class.
358    pub fn id(&self) -> ClassPermissionId {
359        let id = self.metadata.id.get() as u8;
360        ClassPermissionId(NonZeroU8::new(id).unwrap())
361    }
362}
363
364impl ValidateArray<PermissionMetadata, u8> for Permission {
365    type Error = anyhow::Error;
366
367    /// [`Permission`] has no internal constraints beyond those imposed by [`Array`].
368    fn validate_array(
369        _context: &mut PolicyValidationContext,
370        _metadata: &PermissionMetadata,
371        _items: &[u8],
372    ) -> Result<(), Self::Error> {
373        Ok(())
374    }
375}
376
377#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
378#[repr(C, packed)]
379pub(super) struct PermissionMetadata {
380    /// The length of the `[u8]` in the associated [`Permission`].
381    length: le::U32,
382    id: le::U32,
383}
384
385impl Counted for PermissionMetadata {
386    /// The count of bytes in the `[u8]` in the associated [`Permission`].
387    fn count(&self) -> u32 {
388        self.length.get()
389    }
390}
391
392impl Validate for PermissionMetadata {
393    type Error = anyhow::Error;
394
395    /// TODO: Should there be an upper bound on `length`?
396    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
397        // `id` must be a valid `AccessVector` bit-index in the range 1..=32.
398        if self.id < 1 || self.id > 32 {
399            return Err(anyhow!("Permission Id is not valid AV index"));
400        }
401        Ok(())
402    }
403}
404
405/// The list of [`Constraints`] associated with a class.
406pub(super) type Constraints = Vec<Constraint>;
407
408impl Validate for Constraints {
409    type Error = anyhow::Error;
410
411    /// [`Constraints`] has no internal constraints beyond those imposed by individual
412    /// [`Constraint`] objects.
413    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
414        Ok(())
415    }
416}
417
418/// A set of permissions and a boolean expression giving a constraint on those
419/// permissions, for a particular class. Corresponds to a single `constrain` or
420/// `mlsconstrain` statement in policy language.
421#[derive(Debug, PartialEq)]
422pub(super) struct Constraint {
423    access_vector: le::U32,
424    constraint_expr: ConstraintExpr,
425}
426
427impl Constraint {
428    pub(super) fn access_vector(&self) -> AccessVector {
429        AccessVector(self.access_vector.get())
430    }
431
432    pub(super) fn constraint_expr(&self) -> &ConstraintExpr {
433        &self.constraint_expr
434    }
435}
436
437impl Parse for Constraint {
438    type Error = anyhow::Error;
439
440    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
441        let tail = bytes;
442
443        let (access_vector, tail) = PolicyCursor::parse::<le::U32>(tail)?;
444        let (constraint_expr, tail) = ConstraintExpr::parse(tail)
445            .map_err(|error| anyhow!(error))
446            .context("parsing constraint expression")?;
447
448        Ok((Self { access_vector, constraint_expr }, tail))
449    }
450}
451
452// A [`ConstraintExpr`] describes a constraint expression, represented as a
453// postfix-ordered list of terms.
454array_type!(ConstraintExpr, ConstraintTermCount, ConstraintTerms);
455
456array_type_validate_deref_metadata_data_vec!(ConstraintExpr);
457
458impl ValidateArray<ConstraintTermCount, ConstraintTerm> for ConstraintExpr {
459    type Error = anyhow::Error;
460
461    /// [`ConstraintExpr`] has no internal constraints beyond those imposed by
462    /// [`Array`]. The `ParsedPolicy::validate()` function separately validates
463    /// that the constraint expression is well-formed.
464    fn validate_array(
465        _context: &mut PolicyValidationContext,
466        _metadata: &ConstraintTermCount,
467        _items: &[ConstraintTerm],
468    ) -> Result<(), Self::Error> {
469        Ok(())
470    }
471}
472
473impl ConstraintExpr {
474    pub(super) fn evaluate(
475        &self,
476        source_context: &SecurityContext,
477        target_context: &SecurityContext,
478    ) -> Result<bool, ConstraintError> {
479        evaluate_constraint(&self, source_context, target_context)
480    }
481
482    pub(super) fn constraint_terms(&self) -> &[ConstraintTerm] {
483        &self.data
484    }
485}
486
487#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
488#[repr(C, packed)]
489pub(super) struct ConstraintTermCount(le::U32);
490
491impl Counted for ConstraintTermCount {
492    fn count(&self) -> u32 {
493        self.0.get()
494    }
495}
496
497impl Validate for ConstraintTermCount {
498    type Error = anyhow::Error;
499
500    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
501        Ok(())
502    }
503}
504
505impl Validate for ConstraintTerms {
506    type Error = anyhow::Error;
507
508    /// [`ConstraintTerms`] have no internal constraints beyond those imposed by
509    /// individual [`ConstraintTerm`] objects. The `ParsedPolicy::validate()`
510    /// function separately validates that the constraint expression is
511    /// well-formed.
512    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
513        Ok(())
514    }
515}
516
517#[derive(Debug, PartialEq)]
518pub(super) struct ConstraintTerm {
519    metadata: ConstraintTermMetadata,
520    names: Option<ExtensibleBitmap>,
521    names_type_set: Option<TypeSet>,
522}
523
524pub(super) type ConstraintTerms = Vec<ConstraintTerm>;
525
526impl Parse for ConstraintTerm {
527    type Error = anyhow::Error;
528
529    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
530        let tail = bytes;
531
532        let (metadata, tail) = PolicyCursor::parse::<ConstraintTermMetadata>(tail)
533            .context("parsing constraint term metadata")?;
534
535        let (names, names_type_set, tail) = match metadata.constraint_term_type.get() {
536            CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES => {
537                let (names, tail) = ExtensibleBitmap::parse(tail)
538                    .map_err(Into::<anyhow::Error>::into)
539                    .context("parsing constraint term names")?;
540                let (names_type_set, tail) =
541                    TypeSet::parse(tail).context("parsing constraint term names type set")?;
542                (Some(names), Some(names_type_set), tail)
543            }
544            _ => (None, None, tail),
545        };
546
547        Ok((Self { metadata, names, names_type_set }, tail))
548    }
549}
550
551impl ConstraintTerm {
552    pub(super) fn constraint_term_type(&self) -> u32 {
553        self.metadata.constraint_term_type.get()
554    }
555
556    pub(super) fn expr_operand_type(&self) -> u32 {
557        self.metadata.expr_operand_type.get()
558    }
559
560    pub(super) fn expr_operator_type(&self) -> u32 {
561        self.metadata.expr_operator_type.get()
562    }
563
564    pub(super) fn names(&self) -> Option<&ExtensibleBitmap> {
565        self.names.as_ref()
566    }
567
568    // TODO: https://fxbug.dev/372400976 - Unused, unsure if needed.
569    // Possibly becomes interesting when the policy contains type
570    // attributes.
571    #[allow(dead_code)]
572    pub(super) fn names_type_set(&self) -> &Option<TypeSet> {
573        &self.names_type_set
574    }
575}
576
577#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
578#[repr(C, packed)]
579pub(super) struct ConstraintTermMetadata {
580    constraint_term_type: le::U32,
581    expr_operand_type: le::U32,
582    expr_operator_type: le::U32,
583}
584
585impl Validate for ConstraintTermMetadata {
586    type Error = anyhow::Error;
587
588    /// Further validation is done by the `ParsedPolicy::validate()` function,
589    /// which separately validates that constraint expressions are well-formed.
590    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
591        if !(self.constraint_term_type > 0
592            && self.constraint_term_type <= CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
593        {
594            return Err(anyhow!("invalid constraint term type"));
595        }
596        if !(self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR
597            || self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
598        {
599            if self.expr_operand_type != 0 {
600                return Err(anyhow!(
601                    "invalid operand type {} for constraint term type {}",
602                    self.expr_operand_type,
603                    self.constraint_term_type
604                ));
605            }
606            if self.expr_operator_type != 0 {
607                return Err(anyhow!(
608                    "invalid operator type {} for constraint term type {}",
609                    self.expr_operator_type,
610                    self.constraint_term_type
611                ));
612            }
613        }
614        // TODO: https://fxbug.dev/372400976 - Consider validating operator
615        // and operand types for expr and expr-with-names terms.
616        Ok(())
617    }
618}
619
620#[derive(Debug, PartialEq)]
621pub(super) struct TypeSet {
622    types: ExtensibleBitmap,
623    negative_set: ExtensibleBitmap,
624    flags: le::U32,
625}
626
627impl Parse for TypeSet {
628    type Error = anyhow::Error;
629
630    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
631        let tail = bytes;
632
633        let (types, tail) = ExtensibleBitmap::parse(tail)
634            .map_err(Into::<anyhow::Error>::into)
635            .context("parsing type set types")?;
636
637        let (negative_set, tail) = ExtensibleBitmap::parse(tail)
638            .map_err(Into::<anyhow::Error>::into)
639            .context("parsing type set negative set")?;
640
641        let (flags, tail) = PolicyCursor::parse::<le::U32>(tail)?;
642
643        Ok((Self { types, negative_set, flags }, tail))
644    }
645}
646
647/// Locates a class named `name` among `classes`. Returns the first such class found, though policy
648/// validation should ensure that only one such class exists.
649pub(super) fn find_class_by_name<'a>(classes: &'a Classes, name: &str) -> Option<&'a Class> {
650    let name_bytes = name.as_bytes();
651    classes.iter().find(|class| class.name_bytes() == name_bytes)
652}
653
654/// Locates a symbol named `name_bytes` among `common_symbols`. Returns
655/// the first such symbol found, though policy validation should ensure
656/// that only one exists.
657pub(super) fn find_common_symbol_by_name_bytes<'a>(
658    common_symbols: &'a CommonSymbols,
659    name_bytes: &[u8],
660) -> Option<&'a CommonSymbol> {
661    common_symbols.iter().find(|common_symbol| common_symbol.name_bytes() == name_bytes)
662}
663
664impl Validate for [Class] {
665    type Error = anyhow::Error;
666
667    fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
668        // TODO: Validate internal consistency between consecutive [`Class`] instances.
669        for class in self {
670            // TODO: Validate `self.constraints` and `self.validate_transitions`.
671            class.defaults().validate(context).context("class defaults")?;
672        }
673        Ok(())
674    }
675}
676
677#[derive(Debug, PartialEq)]
678pub(super) struct Class {
679    constraints: ClassConstraints,
680    validate_transitions: ClassValidateTransitions,
681    defaults: ClassDefaults,
682}
683
684pub(super) type Classes = Vec<Class>;
685
686impl Class {
687    /// Returns the name of the `common` from which this `class` inherits as a borrow of a byte
688    /// slice. For example, `common file { common_file_perm }`,
689    /// `class file inherits file { file_perm }` yields two [`Class`] objects, one that refers to a
690    /// permission named `"common_file_perm"` permission and has `self.common_name_bytes() == ""`,
691    /// and another that refers to a permission named `"file_perm"` and has
692    /// `self.common_name_bytes() == "file"`.
693    pub fn common_name_bytes(&self) -> &[u8] {
694        // `ClassCommonKey` is an `Array` of `[u8]` with metadata `ClassKey`, and
695        // `ClassKey::count()` returns the `common_key_length` field. That is, the `[u8]` string
696        // on `ClassCommonKey` is the "common key" (name in the inherited `common` statement) for
697        // this class.
698        let class_common_key: &ClassCommonKey = &self.constraints.metadata.metadata;
699        &class_common_key.data
700    }
701
702    /// Returns the name of this class as a borrow of a byte slice.
703    pub fn name_bytes(&self) -> &[u8] {
704        // `ClassKey` is an `Array` of `[u8]` with metadata `ClassMetadata`, and
705        // `ClassMetadata::count()` returns the `key_length` field. That is, the `[u8]` string on
706        // `ClassKey` is the "class key" (name in the `class` or `common` statement) for this class.
707        let class_key: &ClassKey = &self.constraints.metadata.metadata.metadata;
708        &class_key.data
709    }
710
711    /// Returns the id associated with this class. The id is used to index into collections
712    /// and bitmaps associated with this class. The id is 1-indexed, whereas most collections and
713    /// bitmaps are 0-indexed, so clients of this API will usually use `id - 1`.
714    pub fn id(&self) -> ClassId {
715        let class_metadata: &ClassMetadata = &self.constraints.metadata.metadata.metadata.metadata;
716        ClassId(NonZeroU32::new(class_metadata.id.get()).unwrap())
717    }
718
719    /// Returns the full listing of permissions used in this policy.
720    pub fn permissions(&self) -> &Permissions {
721        &self.constraints.metadata.data
722    }
723
724    /// Returns a list of permission masks and constraint expressions for this
725    /// class. The permissions in a given mask may be granted if the
726    /// corresponding constraint expression is satisfied.
727    ///
728    /// The same permission may appear in multiple entries in the returned list.
729    // TODO: https://fxbug.dev/372400976 - Is it accurate to change "may be
730    // granted to "are granted" above?
731    pub fn constraints(&self) -> &Vec<Constraint> {
732        &self.constraints.data
733    }
734
735    pub fn defaults(&self) -> &ClassDefaults {
736        &self.defaults
737    }
738}
739
740impl Parse for Class {
741    type Error = anyhow::Error;
742
743    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
744        let tail = bytes;
745
746        let (constraints, tail) = ClassConstraints::parse(tail)
747            .map_err(Into::<anyhow::Error>::into)
748            .context("parsing class constraints")?;
749
750        let (validate_transitions, tail) = ClassValidateTransitions::parse(tail)
751            .map_err(Into::<anyhow::Error>::into)
752            .context("parsing class validate transitions")?;
753
754        let (defaults, tail) =
755            PolicyCursor::parse::<ClassDefaults>(tail).context("parsing class defaults")?;
756
757        Ok((Self { constraints, validate_transitions, defaults }, tail))
758    }
759}
760
761#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
762#[repr(C, packed)]
763pub(super) struct ClassDefaults {
764    default_user: le::U32,
765    default_role: le::U32,
766    default_range: le::U32,
767    default_type: le::U32,
768}
769
770impl ClassDefaults {
771    pub fn user(&self) -> ClassDefault {
772        self.default_user.get().into()
773    }
774
775    pub fn role(&self) -> ClassDefault {
776        self.default_role.get().into()
777    }
778
779    pub fn range(&self) -> ClassDefaultRange {
780        self.default_range.get().into()
781    }
782
783    pub fn type_(&self) -> ClassDefault {
784        self.default_type.get().into()
785    }
786}
787
788impl Validate for ClassDefaults {
789    type Error = anyhow::Error;
790
791    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
792        ClassDefault::validate(self.default_user.get()).context("default user")?;
793        ClassDefault::validate(self.default_role.get()).context("default role")?;
794        ClassDefault::validate(self.default_type.get()).context("default type")?;
795        ClassDefaultRange::validate(self.default_range.get()).context("default range")?;
796        Ok(())
797    }
798}
799
800#[derive(PartialEq)]
801pub(super) enum ClassDefault {
802    Unspecified,
803    Source,
804    Target,
805}
806
807impl ClassDefault {
808    pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
809    pub(super) const DEFAULT_SOURCE: u32 = 1;
810    pub(super) const DEFAULT_TARGET: u32 = 2;
811
812    fn validate(value: u32) -> Result<(), ValidateError> {
813        match value {
814            Self::DEFAULT_UNSPECIFIED | Self::DEFAULT_SOURCE | Self::DEFAULT_TARGET => Ok(()),
815            value => Err(ValidateError::InvalidClassDefault { value }),
816        }
817    }
818}
819
820impl From<u32> for ClassDefault {
821    fn from(value: u32) -> Self {
822        match value {
823            Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
824            Self::DEFAULT_SOURCE => Self::Source,
825            Self::DEFAULT_TARGET => Self::Target,
826            v => panic!(
827                "invalid SELinux class default; expected {}, {}, or {}, but got {}",
828                Self::DEFAULT_UNSPECIFIED,
829                Self::DEFAULT_SOURCE,
830                Self::DEFAULT_TARGET,
831                v
832            ),
833        }
834    }
835}
836
837#[derive(PartialEq)]
838pub(super) enum ClassDefaultRange {
839    Unspecified,
840    SourceLow,
841    SourceHigh,
842    SourceLowHigh,
843    TargetLow,
844    TargetHigh,
845    TargetLowHigh,
846}
847
848impl ClassDefaultRange {
849    pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
850    pub(super) const DEFAULT_SOURCE_LOW: u32 = 1;
851    pub(super) const DEFAULT_SOURCE_HIGH: u32 = 2;
852    pub(super) const DEFAULT_SOURCE_LOW_HIGH: u32 = 3;
853    pub(super) const DEFAULT_TARGET_LOW: u32 = 4;
854    pub(super) const DEFAULT_TARGET_HIGH: u32 = 5;
855    pub(super) const DEFAULT_TARGET_LOW_HIGH: u32 = 6;
856    // TODO: Determine what this value means.
857    pub(super) const DEFAULT_UNKNOWN_USED_VALUE: u32 = 7;
858
859    fn validate(value: u32) -> Result<(), ValidateError> {
860        match value {
861            Self::DEFAULT_UNSPECIFIED
862            | Self::DEFAULT_SOURCE_LOW
863            | Self::DEFAULT_SOURCE_HIGH
864            | Self::DEFAULT_SOURCE_LOW_HIGH
865            | Self::DEFAULT_TARGET_LOW
866            | Self::DEFAULT_TARGET_HIGH
867            | Self::DEFAULT_TARGET_LOW_HIGH
868            | Self::DEFAULT_UNKNOWN_USED_VALUE => Ok(()),
869            value => Err(ValidateError::InvalidClassDefaultRange { value }),
870        }
871    }
872}
873
874impl From<u32> for ClassDefaultRange {
875    fn from(value: u32) -> Self {
876        match value {
877            Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
878            Self::DEFAULT_SOURCE_LOW => Self::SourceLow,
879            Self::DEFAULT_SOURCE_HIGH => Self::SourceHigh,
880            Self::DEFAULT_SOURCE_LOW_HIGH => Self::SourceLowHigh,
881            Self::DEFAULT_TARGET_LOW => Self::TargetLow,
882            Self::DEFAULT_TARGET_HIGH => Self::TargetHigh,
883            Self::DEFAULT_TARGET_LOW_HIGH => Self::TargetLowHigh,
884            v => panic!(
885                "invalid SELinux MLS range default; expected one of {:?}, but got {}",
886                [
887                    Self::DEFAULT_UNSPECIFIED,
888                    Self::DEFAULT_SOURCE_LOW,
889                    Self::DEFAULT_SOURCE_HIGH,
890                    Self::DEFAULT_SOURCE_LOW_HIGH,
891                    Self::DEFAULT_TARGET_LOW,
892                    Self::DEFAULT_TARGET_HIGH,
893                    Self::DEFAULT_TARGET_LOW_HIGH,
894                ],
895                v
896            ),
897        }
898    }
899}
900
901array_type!(ClassValidateTransitions, ClassValidateTransitionsCount, ConstraintTerms);
902
903array_type_validate_deref_metadata_data_vec!(ClassValidateTransitions);
904
905impl ValidateArray<ClassValidateTransitionsCount, ConstraintTerm> for ClassValidateTransitions {
906    type Error = anyhow::Error;
907
908    /// [`ClassValidateTransitions`] has no internal constraints beyond those imposed by [`Array`].
909    fn validate_array(
910        _context: &mut PolicyValidationContext,
911        _metadata: &ClassValidateTransitionsCount,
912        _items: &[ConstraintTerm],
913    ) -> Result<(), Self::Error> {
914        Ok(())
915    }
916}
917
918#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
919#[repr(C, packed)]
920pub(super) struct ClassValidateTransitionsCount(le::U32);
921
922impl Counted for ClassValidateTransitionsCount {
923    fn count(&self) -> u32 {
924        self.0.get()
925    }
926}
927
928impl Validate for ClassValidateTransitionsCount {
929    type Error = anyhow::Error;
930
931    /// TODO: Should there be an upper bound on class validate transitions count?
932    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
933        Ok(())
934    }
935}
936
937array_type!(ClassConstraints, ClassPermissions, Constraints);
938
939array_type_validate_deref_none_data_vec!(ClassConstraints);
940
941impl ValidateArray<ClassPermissions, Constraint> for ClassConstraints {
942    type Error = anyhow::Error;
943
944    /// [`ClassConstraints`] has no internal constraints beyond those imposed by [`Array`].
945    fn validate_array(
946        _context: &mut PolicyValidationContext,
947        _metadata: &ClassPermissions,
948        _items: &[Constraint],
949    ) -> Result<(), Self::Error> {
950        Ok(())
951    }
952}
953
954array_type!(ClassPermissions, ClassCommonKey, Permissions);
955
956array_type_validate_deref_none_data_vec!(ClassPermissions);
957
958impl ValidateArray<ClassCommonKey, Permission> for ClassPermissions {
959    type Error = anyhow::Error;
960
961    /// [`ClassPermissions`] has no internal constraints beyond those imposed by [`Array`].
962    fn validate_array(
963        _context: &mut PolicyValidationContext,
964        _metadata: &ClassCommonKey,
965        _items: &[Permission],
966    ) -> Result<(), Self::Error> {
967        Ok(())
968    }
969}
970
971impl Counted for ClassPermissions {
972    /// [`ClassPermissions`] acts as counted metadata for [`ClassConstraints`].
973    fn count(&self) -> u32 {
974        self.metadata.metadata.metadata.constraint_count.get()
975    }
976}
977
978array_type!(ClassCommonKey, ClassKey, Vec<u8>);
979
980array_type_validate_deref_data!(ClassCommonKey);
981
982impl ValidateArray<ClassKey, u8> for ClassCommonKey {
983    type Error = anyhow::Error;
984
985    /// [`ClassCommonKey`] has no internal constraints beyond those imposed by [`Array`].
986    fn validate_array(
987        _context: &mut PolicyValidationContext,
988        _metadata: &ClassKey,
989        _items: &[u8],
990    ) -> Result<(), Self::Error> {
991        Ok(())
992    }
993}
994
995impl Counted for ClassCommonKey {
996    /// [`ClassCommonKey`] acts as counted metadata for [`ClassPermissions`].
997    fn count(&self) -> u32 {
998        self.metadata.metadata.elements_count.get()
999    }
1000}
1001
1002array_type!(ClassKey, ClassMetadata, Vec<u8>);
1003
1004array_type_validate_deref_both!(ClassKey);
1005
1006impl ValidateArray<ClassMetadata, u8> for ClassKey {
1007    type Error = anyhow::Error;
1008
1009    /// [`ClassKey`] has no internal constraints beyond those imposed by [`Array`].
1010    fn validate_array(
1011        _context: &mut PolicyValidationContext,
1012        _metadata: &ClassMetadata,
1013        _items: &[u8],
1014    ) -> Result<(), Self::Error> {
1015        Ok(())
1016    }
1017}
1018
1019impl Counted for ClassKey {
1020    /// [`ClassKey`] acts as counted metadata for [`ClassCommonKey`].
1021    fn count(&self) -> u32 {
1022        self.metadata.common_key_length.get()
1023    }
1024}
1025
1026#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1027#[repr(C, packed)]
1028pub(super) struct ClassMetadata {
1029    key_length: le::U32,
1030    common_key_length: le::U32,
1031    id: le::U32,
1032    primary_names_count: le::U32,
1033    elements_count: le::U32,
1034    constraint_count: le::U32,
1035}
1036
1037impl Counted for ClassMetadata {
1038    fn count(&self) -> u32 {
1039        self.key_length.get()
1040    }
1041}
1042
1043impl Validate for ClassMetadata {
1044    type Error = anyhow::Error;
1045
1046    /// TODO: Should there be an upper bound `u32` values in [`ClassMetadata`]?
1047    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1048        if self.id.get() == 0 {
1049            return Err(ValidateError::NonOptionalIdIsZero.into());
1050        } else {
1051            Ok(())
1052        }
1053    }
1054}
1055
1056impl Validate for [Role] {
1057    type Error = anyhow::Error;
1058
1059    /// TODO: Validate internal consistency between consecutive [`Role`] instances.
1060    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1061        Ok(())
1062    }
1063}
1064
1065#[derive(Debug, PartialEq)]
1066pub(super) struct Role {
1067    metadata: RoleMetadata,
1068    role_dominates: ExtensibleBitmap,
1069    role_types: ExtensibleBitmap,
1070}
1071
1072impl Role {
1073    pub(super) fn id(&self) -> RoleId {
1074        RoleId(NonZeroU32::new(self.metadata.metadata.id.get()).unwrap())
1075    }
1076
1077    pub(super) fn name_bytes(&self) -> &[u8] {
1078        &self.metadata.data
1079    }
1080
1081    pub(super) fn types(&self) -> &ExtensibleBitmap {
1082        &self.role_types
1083    }
1084}
1085
1086impl Parse for Role {
1087    type Error = anyhow::Error;
1088
1089    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1090        let tail = bytes;
1091
1092        let (metadata, tail) = RoleMetadata::parse(tail)
1093            .map_err(Into::<anyhow::Error>::into)
1094            .context("parsing role metadata")?;
1095
1096        let (role_dominates, tail) = ExtensibleBitmap::parse(tail)
1097            .map_err(Into::<anyhow::Error>::into)
1098            .context("parsing role dominates")?;
1099
1100        let (role_types, tail) = ExtensibleBitmap::parse(tail)
1101            .map_err(Into::<anyhow::Error>::into)
1102            .context("parsing role types")?;
1103
1104        Ok((Self { metadata, role_dominates, role_types }, tail))
1105    }
1106}
1107
1108array_type!(RoleMetadata, RoleStaticMetadata, Vec<u8>);
1109
1110array_type_validate_deref_both!(RoleMetadata);
1111
1112impl ValidateArray<RoleStaticMetadata, u8> for RoleMetadata {
1113    type Error = anyhow::Error;
1114
1115    /// [`RoleMetadata`] has no internal constraints beyond those imposed by [`Array`].
1116    fn validate_array(
1117        _context: &mut PolicyValidationContext,
1118        _metadata: &RoleStaticMetadata,
1119        _items: &[u8],
1120    ) -> Result<(), Self::Error> {
1121        Ok(())
1122    }
1123}
1124
1125#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1126#[repr(C, packed)]
1127pub(super) struct RoleStaticMetadata {
1128    length: le::U32,
1129    id: le::U32,
1130    bounds: le::U32,
1131}
1132
1133impl Counted for RoleStaticMetadata {
1134    /// [`RoleStaticMetadata`] serves as [`Counted`] for a length-encoded `[u8]`.
1135    fn count(&self) -> u32 {
1136        self.length.get()
1137    }
1138}
1139
1140impl Validate for RoleStaticMetadata {
1141    type Error = anyhow::Error;
1142
1143    /// TODO: Should there be any constraints on `length`, `value`, or `bounds`?
1144    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1145        Ok(())
1146    }
1147}
1148
1149impl Validate for [Type] {
1150    type Error = anyhow::Error;
1151
1152    /// TODO: Validate internal consistency between consecutive [`Type`] instances.
1153    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1154        Ok(())
1155    }
1156}
1157
1158array_type!(Type, TypeMetadata, Vec<u8>);
1159
1160array_type_validate_deref_both!(Type);
1161
1162impl Type {
1163    /// Returns the name of this type.
1164    pub fn name_bytes(&self) -> &[u8] {
1165        &self.data
1166    }
1167
1168    /// Returns the id associated with this type. The id is used to index into collections and
1169    /// bitmaps associated with this type. The id is 1-indexed, whereas most collections and
1170    /// bitmaps are 0-indexed, so clients of this API will usually use `id - 1`.
1171    pub fn id(&self) -> TypeId {
1172        TypeId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1173    }
1174
1175    /// Returns the Id of the bounding type, if any.
1176    pub fn bounded_by(&self) -> Option<TypeId> {
1177        NonZeroU32::new(self.metadata.bounds.get()).map(|id| TypeId(id))
1178    }
1179
1180    /// Returns whether this type is from a `type [name];` policy statement.
1181    ///
1182    /// TODO: Eliminate `dead_code` guard.
1183    #[allow(dead_code)]
1184    pub fn is_type(&self) -> bool {
1185        self.metadata.properties.get() == TYPE_PROPERTIES_TYPE
1186    }
1187
1188    /// Returns whether this type is from a `typealias [typename] alias [aliasname];` policy
1189    /// statement.
1190    ///
1191    /// TODO: Eliminate `dead_code` guard.
1192    #[allow(dead_code)]
1193    pub fn is_alias(&self) -> bool {
1194        self.metadata.properties.get() == TYPE_PROPERTIES_ALIAS
1195    }
1196
1197    /// Returns whether this type is from an `attribute [name];` policy statement.
1198    ///
1199    /// TODO: Eliminate `dead_code` guard.
1200    #[allow(dead_code)]
1201    pub fn is_attribute(&self) -> bool {
1202        self.metadata.properties.get() == TYPE_PROPERTIES_ATTRIBUTE
1203    }
1204}
1205
1206impl ValidateArray<TypeMetadata, u8> for Type {
1207    type Error = anyhow::Error;
1208
1209    /// TODO: Validate that `PS::deref(&self.data)` is an ascii string that contains a valid type name.
1210    fn validate_array(
1211        _context: &mut PolicyValidationContext,
1212        _metadata: &TypeMetadata,
1213        _items: &[u8],
1214    ) -> Result<(), Self::Error> {
1215        Ok(())
1216    }
1217}
1218
1219#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1220#[repr(C, packed)]
1221pub(super) struct TypeMetadata {
1222    length: le::U32,
1223    id: le::U32,
1224    properties: le::U32,
1225    bounds: le::U32,
1226}
1227
1228impl Counted for TypeMetadata {
1229    fn count(&self) -> u32 {
1230        self.length.get()
1231    }
1232}
1233
1234impl Validate for TypeMetadata {
1235    type Error = anyhow::Error;
1236
1237    /// TODO: Validate [`TypeMetadata`] internals.
1238    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1239        Ok(())
1240    }
1241}
1242
1243impl Validate for [User] {
1244    type Error = anyhow::Error;
1245
1246    /// TODO: Validate internal consistency between consecutive [`User`] instances.
1247    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1248        Ok(())
1249    }
1250}
1251
1252#[derive(Debug, PartialEq)]
1253pub(super) struct User {
1254    user_data: UserData,
1255    roles: ExtensibleBitmap,
1256    expanded_range: MlsRange,
1257    default_level: MlsLevel,
1258}
1259
1260impl User {
1261    pub(super) fn id(&self) -> UserId {
1262        UserId(NonZeroU32::new(self.user_data.metadata.id.get()).unwrap())
1263    }
1264
1265    pub(super) fn name_bytes(&self) -> &[u8] {
1266        &self.user_data.data
1267    }
1268
1269    pub(super) fn roles(&self) -> &ExtensibleBitmap {
1270        &self.roles
1271    }
1272
1273    pub(super) fn mls_range(&self) -> &MlsRange {
1274        &self.expanded_range
1275    }
1276}
1277
1278impl Parse for User {
1279    type Error = anyhow::Error;
1280
1281    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1282        let tail = bytes;
1283
1284        let (user_data, tail) = UserData::parse(tail)
1285            .map_err(Into::<anyhow::Error>::into)
1286            .context("parsing user data")?;
1287
1288        let (roles, tail) = ExtensibleBitmap::parse(tail)
1289            .map_err(Into::<anyhow::Error>::into)
1290            .context("parsing user roles")?;
1291
1292        let (expanded_range, tail) =
1293            MlsRange::parse(tail).context("parsing user expanded range")?;
1294
1295        let (default_level, tail) = MlsLevel::parse(tail).context("parsing user default level")?;
1296
1297        Ok((Self { user_data, roles, expanded_range, default_level }, tail))
1298    }
1299}
1300
1301array_type!(UserData, UserMetadata, Vec<u8>);
1302
1303array_type_validate_deref_both!(UserData);
1304
1305impl ValidateArray<UserMetadata, u8> for UserData {
1306    type Error = anyhow::Error;
1307
1308    /// TODO: Validate consistency between [`UserMetadata`] in `self.metadata` and `[u8]` key in `self.data`.
1309    fn validate_array(
1310        _context: &mut PolicyValidationContext,
1311        _metadata: &UserMetadata,
1312        _items: &[u8],
1313    ) -> Result<(), Self::Error> {
1314        Ok(())
1315    }
1316}
1317
1318#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1319#[repr(C, packed)]
1320pub(super) struct UserMetadata {
1321    length: le::U32,
1322    id: le::U32,
1323    bounds: le::U32,
1324}
1325
1326impl Counted for UserMetadata {
1327    fn count(&self) -> u32 {
1328        self.length.get()
1329    }
1330}
1331
1332impl Validate for UserMetadata {
1333    type Error = anyhow::Error;
1334
1335    /// TODO: Validate [`UserMetadata`] internals.
1336    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1337        Ok(())
1338    }
1339}
1340
1341#[derive(Debug, PartialEq)]
1342pub(super) struct MlsLevel {
1343    sensitivity: le::U32,
1344    categories: ExtensibleBitmap,
1345}
1346
1347impl MlsLevel {
1348    pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_> {
1349        self.categories.indices_of_set_bits().map(|i| CategoryId(NonZeroU32::new(i + 1).unwrap()))
1350    }
1351}
1352
1353impl Parse for MlsLevel {
1354    type Error = anyhow::Error;
1355
1356    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1357        let tail = bytes;
1358
1359        let (sensitivity, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1360
1361        let (categories, tail) = ExtensibleBitmap::parse(tail)
1362            .map_err(Into::<anyhow::Error>::into)
1363            .context("parsing mls level categories")?;
1364
1365        Ok((Self { sensitivity, categories }, tail))
1366    }
1367}
1368
1369impl<'a> Level<'a, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> for MlsLevel {
1370    fn sensitivity(&self) -> SensitivityId {
1371        SensitivityId(NonZeroU32::new(self.sensitivity.get()).unwrap())
1372    }
1373
1374    fn category_spans(
1375        &'a self,
1376    ) -> CategoryIterator<ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> {
1377        CategoryIterator::new(self.categories.spans())
1378    }
1379}
1380
1381#[derive(Debug, PartialEq)]
1382pub(super) struct MlsRange {
1383    count: le::U32,
1384    low: MlsLevel,
1385    high: Option<MlsLevel>,
1386}
1387
1388impl MlsRange {
1389    pub fn low(&self) -> &MlsLevel {
1390        &self.low
1391    }
1392
1393    pub fn high(&self) -> &Option<MlsLevel> {
1394        &self.high
1395    }
1396}
1397
1398impl Parse for MlsRange {
1399    type Error = anyhow::Error;
1400
1401    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1402        let tail = bytes;
1403
1404        let (count, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1405
1406        // `MlsRange::parse()` cannot be implemented in terms of `MlsLevel::parse()` for the
1407        // low and optional high level, because of the order in which the sensitivity and
1408        // category bitmap fields appear.
1409        let (sensitivity_low, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1410
1411        let (low_categories, high_level, tail) = if count.get() > 1 {
1412            let (sensitivity_high, tail) = PolicyCursor::parse::<le::U32>(tail)?;
1413            let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1414                .map_err(Into::<anyhow::Error>::into)
1415                .context("parsing mls range low categories")?;
1416            let (high_categories, tail) = ExtensibleBitmap::parse(tail)
1417                .map_err(Into::<anyhow::Error>::into)
1418                .context("parsing mls range high categories")?;
1419
1420            (
1421                low_categories,
1422                Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
1423                tail,
1424            )
1425        } else {
1426            let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1427                .map_err(Into::<anyhow::Error>::into)
1428                .context("parsing mls range low categories")?;
1429
1430            (low_categories, None, tail)
1431        };
1432
1433        Ok((
1434            Self {
1435                count,
1436                low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
1437                high: high_level,
1438            },
1439            tail,
1440        ))
1441    }
1442}
1443
1444impl Validate for [ConditionalBoolean] {
1445    type Error = anyhow::Error;
1446
1447    /// TODO: Validate consistency of sequence of [`ConditionalBoolean`].
1448    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1449        Ok(())
1450    }
1451}
1452
1453array_type!(ConditionalBoolean, ConditionalBooleanMetadata, Vec<u8>);
1454
1455array_type_validate_deref_both!(ConditionalBoolean);
1456
1457impl ValidateArray<ConditionalBooleanMetadata, u8> for ConditionalBoolean {
1458    type Error = anyhow::Error;
1459
1460    /// TODO: Validate consistency between [`ConditionalBooleanMetadata`] and `[u8]` key.
1461    fn validate_array(
1462        _context: &mut PolicyValidationContext,
1463        _metadata: &ConditionalBooleanMetadata,
1464        _items: &[u8],
1465    ) -> Result<(), Self::Error> {
1466        Ok(())
1467    }
1468}
1469
1470#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1471#[repr(C, packed)]
1472pub(super) struct ConditionalBooleanMetadata {
1473    id: le::U32,
1474    /// Current active value of this conditional boolean.
1475    active: le::U32,
1476    length: le::U32,
1477}
1478
1479impl ConditionalBooleanMetadata {
1480    /// Returns the active value for the boolean.
1481    pub(super) fn active(&self) -> bool {
1482        self.active != le::U32::ZERO
1483    }
1484}
1485
1486impl Counted for ConditionalBooleanMetadata {
1487    /// [`ConditionalBooleanMetadata`] used as `M` in of `Array<PS, PS::Output<M>, PS::Slice<u8>>` with
1488    /// `self.length` denoting size of inner `[u8]`.
1489    fn count(&self) -> u32 {
1490        self.length.get()
1491    }
1492}
1493
1494impl Validate for ConditionalBooleanMetadata {
1495    type Error = anyhow::Error;
1496
1497    /// TODO: Validate internal consistency of [`ConditionalBooleanMetadata`].
1498    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1499        Ok(())
1500    }
1501}
1502
1503impl Validate for [Sensitivity] {
1504    type Error = anyhow::Error;
1505
1506    /// TODO: Validate consistency of sequence of [`Sensitivity`].
1507    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1508        Ok(())
1509    }
1510}
1511
1512#[derive(Debug, PartialEq)]
1513pub(super) struct Sensitivity {
1514    metadata: SensitivityMetadata,
1515    level: MlsLevel,
1516}
1517
1518impl Sensitivity {
1519    pub fn id(&self) -> SensitivityId {
1520        SensitivityId(NonZeroU32::new(self.level.sensitivity.get()).unwrap())
1521    }
1522
1523    pub fn name_bytes(&self) -> &[u8] {
1524        &self.metadata.data
1525    }
1526}
1527
1528impl Parse for Sensitivity {
1529    type Error = anyhow::Error;
1530
1531    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1532        let tail = bytes;
1533
1534        let (metadata, tail) = SensitivityMetadata::parse(tail)
1535            .map_err(Into::<anyhow::Error>::into)
1536            .context("parsing sensitivity metadata")?;
1537
1538        let (level, tail) = MlsLevel::parse(tail)
1539            .map_err(Into::<anyhow::Error>::into)
1540            .context("parsing sensitivity mls level")?;
1541
1542        Ok((Self { metadata, level }, tail))
1543    }
1544}
1545
1546impl Validate for Sensitivity {
1547    type Error = anyhow::Error;
1548
1549    /// TODO: Validate internal consistency of `self.metadata` and `self.level`.
1550    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1551        NonZeroU32::new(self.level.sensitivity.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1552        Ok(())
1553    }
1554}
1555
1556array_type!(SensitivityMetadata, SensitivityStaticMetadata, Vec<u8>);
1557
1558array_type_validate_deref_both!(SensitivityMetadata);
1559
1560impl ValidateArray<SensitivityStaticMetadata, u8> for SensitivityMetadata {
1561    type Error = anyhow::Error;
1562
1563    /// TODO: Validate consistency between [`SensitivityMetadata`] and `[u8]` key.
1564    fn validate_array(
1565        _context: &mut PolicyValidationContext,
1566        _metadata: &SensitivityStaticMetadata,
1567        _items: &[u8],
1568    ) -> Result<(), Self::Error> {
1569        Ok(())
1570    }
1571}
1572
1573#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1574#[repr(C, packed)]
1575pub(super) struct SensitivityStaticMetadata {
1576    length: le::U32,
1577    is_alias: le::U32,
1578}
1579
1580impl Counted for SensitivityStaticMetadata {
1581    /// [`SensitivityStaticMetadata`] used as `M` in of `Array<PS, PS::Output<M>, PS::Slice<u8>>` with
1582    /// `self.length` denoting size of inner `[u8]`.
1583    fn count(&self) -> u32 {
1584        self.length.get()
1585    }
1586}
1587
1588impl Validate for SensitivityStaticMetadata {
1589    type Error = anyhow::Error;
1590
1591    /// TODO: Validate internal consistency of [`SensitivityStaticMetadata`].
1592    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1593        Ok(())
1594    }
1595}
1596
1597impl Validate for [Category] {
1598    type Error = anyhow::Error;
1599
1600    /// TODO: Validate consistency of sequence of [`Category`].
1601    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1602        Ok(())
1603    }
1604}
1605
1606array_type!(Category, CategoryMetadata, Vec<u8>);
1607
1608array_type_validate_deref_both!(Category);
1609
1610impl Category {
1611    pub fn id(&self) -> CategoryId {
1612        CategoryId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1613    }
1614
1615    pub fn name_bytes(&self) -> &[u8] {
1616        &self.data
1617    }
1618}
1619
1620impl ValidateArray<CategoryMetadata, u8> for Category {
1621    type Error = anyhow::Error;
1622
1623    /// TODO: Validate consistency between [`CategoryMetadata`] and `[u8]` key.
1624    fn validate_array(
1625        _context: &mut PolicyValidationContext,
1626        _metadata: &CategoryMetadata,
1627        _items: &[u8],
1628    ) -> Result<(), Self::Error> {
1629        Ok(())
1630    }
1631}
1632
1633#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1634#[repr(C, packed)]
1635pub(super) struct CategoryMetadata {
1636    length: le::U32,
1637    id: le::U32,
1638    is_alias: le::U32,
1639}
1640
1641impl Counted for CategoryMetadata {
1642    /// [`CategoryMetadata`] used as `M` in of `Array<PS, PS::Output<M>, PS::Slice<u8>>` with
1643    /// `self.length` denoting size of inner `[u8]`.
1644    fn count(&self) -> u32 {
1645        self.length.get()
1646    }
1647}
1648
1649impl Validate for CategoryMetadata {
1650    type Error = anyhow::Error;
1651
1652    /// TODO: Validate internal consistency of [`CategoryMetadata`].
1653    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1654        NonZeroU32::new(self.id.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1655        Ok(())
1656    }
1657}
1658
1659#[cfg(test)]
1660mod tests {
1661    use super::super::security_context::Level;
1662    use super::super::{CategoryId, SensitivityId, UserId, parse_policy_by_value};
1663    use super::*;
1664
1665    use std::num::NonZeroU32;
1666
1667    #[test]
1668    fn mls_levels_for_user_context() {
1669        const TEST_POLICY: &[u8] = include_bytes! {"../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"};
1670        let policy = parse_policy_by_value(TEST_POLICY.to_vec()).unwrap();
1671        let policy = policy.validate().unwrap();
1672        let parsed_policy = policy.0.parsed_policy();
1673
1674        let user = parsed_policy.user(UserId(NonZeroU32::new(1).expect("user with id 1")));
1675        let mls_range = user.mls_range();
1676        let low_level = mls_range.low();
1677        let high_level = mls_range.high().as_ref().expect("user 1 has a high mls level");
1678
1679        assert_eq!(low_level.sensitivity(), SensitivityId(NonZeroU32::new(1).unwrap()));
1680        assert_eq!(
1681            low_level.category_ids().collect::<Vec<_>>(),
1682            vec![CategoryId(NonZeroU32::new(1).unwrap())]
1683        );
1684
1685        assert_eq!(high_level.sensitivity(), SensitivityId(NonZeroU32::new(2).unwrap()));
1686        assert_eq!(
1687            high_level.category_ids().collect::<Vec<_>>(),
1688            vec![
1689                CategoryId(NonZeroU32::new(1).unwrap()),
1690                CategoryId(NonZeroU32::new(2).unwrap()),
1691                CategoryId(NonZeroU32::new(3).unwrap()),
1692                CategoryId(NonZeroU32::new(4).unwrap()),
1693                CategoryId(NonZeroU32::new(5).unwrap()),
1694            ]
1695        );
1696    }
1697
1698    #[test]
1699    fn parse_mls_constrain_statement() {
1700        let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1701        let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1702        let parsed_policy = &policy.0;
1703        parsed_policy.validate().expect("validate policy");
1704
1705        let class = find_class_by_name(parsed_policy.classes(), "class_mls_constraints")
1706            .expect("look up class");
1707        let constraints = class.constraints();
1708        assert_eq!(constraints.len(), 6);
1709        // Expected (`constraint_term_type`, `expr_operator_type`,
1710        // `expr_operand_type`) values for the single term of the
1711        // corresponding class constraint.
1712        //
1713        // NB. Constraint statements appear in reverse order in binary policy
1714        // vs. text policy.
1715        let expected = [
1716            (
1717                CONSTRAINT_TERM_TYPE_EXPR,
1718                CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1719                CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1,
1720            ),
1721            (
1722                CONSTRAINT_TERM_TYPE_EXPR,
1723                CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1724                CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2,
1725            ),
1726            (
1727                CONSTRAINT_TERM_TYPE_EXPR,
1728                CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY,
1729                CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2,
1730            ),
1731            (
1732                CONSTRAINT_TERM_TYPE_EXPR,
1733                CONSTRAINT_EXPR_OPERATOR_TYPE_DOM,
1734                CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2,
1735            ),
1736            (
1737                CONSTRAINT_TERM_TYPE_EXPR,
1738                CONSTRAINT_EXPR_OPERATOR_TYPE_NE,
1739                CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2,
1740            ),
1741            (
1742                CONSTRAINT_TERM_TYPE_EXPR,
1743                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1744                CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2,
1745            ),
1746        ];
1747        for (i, constraint) in constraints.iter().enumerate() {
1748            assert_eq!(constraint.access_vector(), AccessVector(1), "constraint {}", i);
1749            let terms = constraint.constraint_expr().constraint_terms();
1750            assert_eq!(terms.len(), 1, "constraint {}", i);
1751            let term = &terms[0];
1752            assert_eq!(
1753                (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1754                expected[i],
1755                "constraint {}",
1756                i
1757            );
1758        }
1759    }
1760
1761    #[test]
1762    fn parse_constrain_statement() {
1763        let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1764        let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1765        let parsed_policy = &policy.0;
1766        parsed_policy.validate().expect("validate policy");
1767
1768        let class = find_class_by_name(parsed_policy.classes(), "class_constraint_nested")
1769            .expect("look up class");
1770        let constraints = class.constraints();
1771        assert_eq!(constraints.len(), 1);
1772        let constraint = &constraints[0];
1773        assert_eq!(constraint.access_vector(), AccessVector(1));
1774        let terms = constraint.constraint_expr().constraint_terms();
1775        assert_eq!(terms.len(), 8);
1776
1777        // Expected (`constraint_term_type`, `expr_operator_type`,
1778        // `expr_operand_type`) values for the constraint terms.
1779        //
1780        // NB. Constraint statements appear in reverse order in binary policy
1781        // vs. text policy.
1782        let expected = [
1783            (
1784                CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES,
1785                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1786                CONSTRAINT_EXPR_OPERAND_TYPE_USER
1787                    | CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK,
1788            ),
1789            (
1790                CONSTRAINT_TERM_TYPE_EXPR,
1791                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1792                CONSTRAINT_EXPR_OPERAND_TYPE_ROLE,
1793            ),
1794            (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1795            (
1796                CONSTRAINT_TERM_TYPE_EXPR,
1797                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1798                CONSTRAINT_EXPR_OPERAND_TYPE_USER,
1799            ),
1800            (
1801                CONSTRAINT_TERM_TYPE_EXPR,
1802                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1803                CONSTRAINT_EXPR_OPERAND_TYPE_TYPE,
1804            ),
1805            (CONSTRAINT_TERM_TYPE_NOT_OPERATOR, 0, 0),
1806            (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1807            (CONSTRAINT_TERM_TYPE_OR_OPERATOR, 0, 0),
1808        ];
1809        for (i, term) in terms.iter().enumerate() {
1810            assert_eq!(
1811                (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1812                expected[i],
1813                "term {}",
1814                i
1815            );
1816        }
1817    }
1818}