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::{ParseError, 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::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        ClassPermissionId(NonZeroU32::new(self.metadata.id.get()).unwrap())
360    }
361}
362
363impl ValidateArray<PermissionMetadata, u8> for Permission {
364    type Error = anyhow::Error;
365
366    /// [`Permission`] has no internal constraints beyond those imposed by [`Array`].
367    fn validate_array(
368        _context: &mut PolicyValidationContext,
369        _metadata: &PermissionMetadata,
370        _items: &[u8],
371    ) -> Result<(), Self::Error> {
372        Ok(())
373    }
374}
375
376#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
377#[repr(C, packed)]
378pub(super) struct PermissionMetadata {
379    /// The length of the `[u8]` in the associated [`Permission`].
380    length: le::U32,
381    id: le::U32,
382}
383
384impl Counted for PermissionMetadata {
385    /// The count of bytes in the `[u8]` in the associated [`Permission`].
386    fn count(&self) -> u32 {
387        self.length.get()
388    }
389}
390
391impl Validate for PermissionMetadata {
392    type Error = anyhow::Error;
393
394    /// TODO: Should there be an upper bound on `length`?
395    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
396        Ok(())
397    }
398}
399
400/// The list of [`Constraints`] associated with a class.
401pub(super) type Constraints = Vec<Constraint>;
402
403impl Validate for Constraints {
404    type Error = anyhow::Error;
405
406    /// [`Constraints`] has no internal constraints beyond those imposed by individual
407    /// [`Constraint`] objects.
408    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
409        Ok(())
410    }
411}
412
413/// A set of permissions and a boolean expression giving a constraint on those
414/// permissions, for a particular class. Corresponds to a single `constrain` or
415/// `mlsconstrain` statement in policy language.
416#[derive(Debug, PartialEq)]
417pub(super) struct Constraint {
418    access_vector: le::U32,
419    constraint_expr: ConstraintExpr,
420}
421
422impl Constraint {
423    pub(super) fn access_vector(&self) -> AccessVector {
424        AccessVector(self.access_vector.get())
425    }
426
427    pub(super) fn constraint_expr(&self) -> &ConstraintExpr {
428        &self.constraint_expr
429    }
430}
431
432impl Parse for Constraint {
433    type Error = anyhow::Error;
434
435    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
436        let tail = bytes;
437
438        let num_bytes = tail.len();
439        let (access_vector, tail) = PolicyCursor::parse::<le::U32>(tail).ok_or_else(|| {
440            Into::<anyhow::Error>::into(ParseError::MissingData {
441                type_name: "AccessVector",
442                type_size: std::mem::size_of::<le::U32>(),
443                num_bytes,
444            })
445        })?;
446        let (constraint_expr, tail) = ConstraintExpr::parse(tail)
447            .map_err(|error| anyhow!(error))
448            .context("parsing constraint expression")?;
449
450        Ok((Self { access_vector, constraint_expr }, tail))
451    }
452}
453
454// A [`ConstraintExpr`] describes a constraint expression, represented as a
455// postfix-ordered list of terms.
456array_type!(ConstraintExpr, ConstraintTermCount, ConstraintTerms);
457
458array_type_validate_deref_metadata_data_vec!(ConstraintExpr);
459
460impl ValidateArray<ConstraintTermCount, ConstraintTerm> for ConstraintExpr {
461    type Error = anyhow::Error;
462
463    /// [`ConstraintExpr`] has no internal constraints beyond those imposed by
464    /// [`Array`]. The `ParsedPolicy::validate()` function separately validates
465    /// that the constraint expression is well-formed.
466    fn validate_array(
467        _context: &mut PolicyValidationContext,
468        _metadata: &ConstraintTermCount,
469        _items: &[ConstraintTerm],
470    ) -> Result<(), Self::Error> {
471        Ok(())
472    }
473}
474
475impl ConstraintExpr {
476    pub(super) fn evaluate(
477        &self,
478        source_context: &SecurityContext,
479        target_context: &SecurityContext,
480    ) -> Result<bool, ConstraintError> {
481        evaluate_constraint(&self, source_context, target_context)
482    }
483
484    pub(super) fn constraint_terms(&self) -> &[ConstraintTerm] {
485        &self.data
486    }
487}
488
489#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
490#[repr(C, packed)]
491pub(super) struct ConstraintTermCount(le::U32);
492
493impl Counted for ConstraintTermCount {
494    fn count(&self) -> u32 {
495        self.0.get()
496    }
497}
498
499impl Validate for ConstraintTermCount {
500    type Error = anyhow::Error;
501
502    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
503        Ok(())
504    }
505}
506
507impl Validate for ConstraintTerms {
508    type Error = anyhow::Error;
509
510    /// [`ConstraintTerms`] have no internal constraints beyond those imposed by
511    /// individual [`ConstraintTerm`] objects. The `ParsedPolicy::validate()`
512    /// function separately validates that the constraint expression is
513    /// well-formed.
514    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
515        Ok(())
516    }
517}
518
519#[derive(Debug, PartialEq)]
520pub(super) struct ConstraintTerm {
521    metadata: ConstraintTermMetadata,
522    names: Option<ExtensibleBitmap>,
523    names_type_set: Option<TypeSet>,
524}
525
526pub(super) type ConstraintTerms = Vec<ConstraintTerm>;
527
528impl Parse for ConstraintTerm {
529    type Error = anyhow::Error;
530
531    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
532        let tail = bytes;
533
534        let (metadata, tail) = PolicyCursor::parse::<ConstraintTermMetadata>(tail)
535            .context("parsing constraint term metadata")?;
536
537        let (names, names_type_set, tail) = match metadata.constraint_term_type.get() {
538            CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES => {
539                let (names, tail) = ExtensibleBitmap::parse(tail)
540                    .map_err(Into::<anyhow::Error>::into)
541                    .context("parsing constraint term names")?;
542                let (names_type_set, tail) =
543                    TypeSet::parse(tail).context("parsing constraint term names type set")?;
544                (Some(names), Some(names_type_set), tail)
545            }
546            _ => (None, None, tail),
547        };
548
549        Ok((Self { metadata, names, names_type_set }, tail))
550    }
551}
552
553impl ConstraintTerm {
554    pub(super) fn constraint_term_type(&self) -> u32 {
555        self.metadata.constraint_term_type.get()
556    }
557
558    pub(super) fn expr_operand_type(&self) -> u32 {
559        self.metadata.expr_operand_type.get()
560    }
561
562    pub(super) fn expr_operator_type(&self) -> u32 {
563        self.metadata.expr_operator_type.get()
564    }
565
566    pub(super) fn names(&self) -> Option<&ExtensibleBitmap> {
567        self.names.as_ref()
568    }
569
570    // TODO: https://fxbug.dev/372400976 - Unused, unsure if needed.
571    // Possibly becomes interesting when the policy contains type
572    // attributes.
573    #[allow(dead_code)]
574    pub(super) fn names_type_set(&self) -> &Option<TypeSet> {
575        &self.names_type_set
576    }
577}
578
579#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
580#[repr(C, packed)]
581pub(super) struct ConstraintTermMetadata {
582    constraint_term_type: le::U32,
583    expr_operand_type: le::U32,
584    expr_operator_type: le::U32,
585}
586
587impl Validate for ConstraintTermMetadata {
588    type Error = anyhow::Error;
589
590    /// Further validation is done by the `ParsedPolicy::validate()` function,
591    /// which separately validates that constraint expressions are well-formed.
592    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
593        if !(self.constraint_term_type > 0
594            && self.constraint_term_type <= CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
595        {
596            return Err(anyhow!("invalid constraint term type"));
597        }
598        if !(self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR
599            || self.constraint_term_type == CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES)
600        {
601            if self.expr_operand_type != 0 {
602                return Err(anyhow!(
603                    "invalid operand type {} for constraint term type {}",
604                    self.expr_operand_type,
605                    self.constraint_term_type
606                ));
607            }
608            if self.expr_operator_type != 0 {
609                return Err(anyhow!(
610                    "invalid operator type {} for constraint term type {}",
611                    self.expr_operator_type,
612                    self.constraint_term_type
613                ));
614            }
615        }
616        // TODO: https://fxbug.dev/372400976 - Consider validating operator
617        // and operand types for expr and expr-with-names terms.
618        Ok(())
619    }
620}
621
622#[derive(Debug, PartialEq)]
623pub(super) struct TypeSet {
624    types: ExtensibleBitmap,
625    negative_set: ExtensibleBitmap,
626    flags: le::U32,
627}
628
629impl Parse for TypeSet {
630    type Error = anyhow::Error;
631
632    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
633        let tail = bytes;
634
635        let (types, tail) = ExtensibleBitmap::parse(tail)
636            .map_err(Into::<anyhow::Error>::into)
637            .context("parsing type set types")?;
638
639        let (negative_set, tail) = ExtensibleBitmap::parse(tail)
640            .map_err(Into::<anyhow::Error>::into)
641            .context("parsing type set negative set")?;
642
643        let num_bytes = tail.len();
644        let (flags, tail) = PolicyCursor::parse::<le::U32>(tail).ok_or_else(|| {
645            Into::<anyhow::Error>::into(ParseError::MissingData {
646                type_name: "TypeSetFlags",
647                type_size: std::mem::size_of::<le::U32>(),
648                num_bytes,
649            })
650        })?;
651
652        Ok((Self { types, negative_set, flags }, tail))
653    }
654}
655
656/// Locates a class named `name` among `classes`. Returns the first such class found, though policy
657/// validation should ensure that only one such class exists.
658pub(super) fn find_class_by_name<'a>(classes: &'a Classes, name: &str) -> Option<&'a Class> {
659    find_class_by_name_bytes(classes, name.as_bytes())
660}
661
662fn find_class_by_name_bytes<'a>(classes: &'a Classes, name_bytes: &[u8]) -> Option<&'a Class> {
663    for cls in classes.into_iter() {
664        if cls.name_bytes() == name_bytes {
665            return Some(cls);
666        }
667    }
668
669    None
670}
671
672/// Locates a symbol named `name_bytes` among `common_symbols`. Returns
673/// the first such symbol found, though policy validation should ensure
674/// that only one exists.
675pub(super) fn find_common_symbol_by_name_bytes<'a>(
676    common_symbols: &'a CommonSymbols,
677    name_bytes: &[u8],
678) -> Option<&'a CommonSymbol> {
679    for common_symbol in common_symbols.into_iter() {
680        if common_symbol.name_bytes() == name_bytes {
681            return Some(common_symbol);
682        }
683    }
684
685    None
686}
687
688impl Validate for [Class] {
689    type Error = anyhow::Error;
690
691    fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
692        // TODO: Validate internal consistency between consecutive [`Class`] instances.
693        for class in self {
694            // TODO: Validate `self.constraints` and `self.validate_transitions`.
695            class.defaults().validate(context).context("class defaults")?;
696        }
697        Ok(())
698    }
699}
700
701#[derive(Debug, PartialEq)]
702pub(super) struct Class {
703    constraints: ClassConstraints,
704    validate_transitions: ClassValidateTransitions,
705    defaults: ClassDefaults,
706}
707
708pub(super) type Classes = Vec<Class>;
709
710impl Class {
711    /// Returns the name of the `common` from which this `class` inherits as a borrow of a byte
712    /// slice. For example, `common file { common_file_perm }`,
713    /// `class file inherits file { file_perm }` yields two [`Class`] objects, one that refers to a
714    /// permission named `"common_file_perm"` permission and has `self.common_name_bytes() == ""`,
715    /// and another that refers to a permission named `"file_perm"` and has
716    /// `self.common_name_bytes() == "file"`.
717    pub fn common_name_bytes(&self) -> &[u8] {
718        // `ClassCommonKey` is an `Array` of `[u8]` with metadata `ClassKey`, and
719        // `ClassKey::count()` returns the `common_key_length` field. That is, the `[u8]` string
720        // on `ClassCommonKey` is the "common key" (name in the inherited `common` statement) for
721        // this class.
722        let class_common_key: &ClassCommonKey = &self.constraints.metadata.metadata;
723        &class_common_key.data
724    }
725
726    /// Returns the name of this class as a borrow of a byte slice.
727    pub fn name_bytes(&self) -> &[u8] {
728        // `ClassKey` is an `Array` of `[u8]` with metadata `ClassMetadata`, and
729        // `ClassMetadata::count()` returns the `key_length` field. That is, the `[u8]` string on
730        // `ClassKey` is the "class key" (name in the `class` or `common` statement) for this class.
731        let class_key: &ClassKey = &self.constraints.metadata.metadata.metadata;
732        &class_key.data
733    }
734
735    /// Returns the id associated with this class. The id is used to index into collections
736    /// and bitmaps associated with this class. The id is 1-indexed, whereas most collections and
737    /// bitmaps are 0-indexed, so clients of this API will usually use `id - 1`.
738    pub fn id(&self) -> ClassId {
739        let class_metadata: &ClassMetadata = &self.constraints.metadata.metadata.metadata.metadata;
740        ClassId(NonZeroU32::new(class_metadata.id.get()).unwrap())
741    }
742
743    /// Returns the full listing of permissions used in this policy.
744    pub fn permissions(&self) -> &Permissions {
745        &self.constraints.metadata.data
746    }
747
748    /// Returns a list of permission masks and constraint expressions for this
749    /// class. The permissions in a given mask may be granted if the
750    /// corresponding constraint expression is satisfied.
751    ///
752    /// The same permission may appear in multiple entries in the returned list.
753    // TODO: https://fxbug.dev/372400976 - Is it accurate to change "may be
754    // granted to "are granted" above?
755    pub fn constraints(&self) -> &Vec<Constraint> {
756        &self.constraints.data
757    }
758
759    pub fn defaults(&self) -> &ClassDefaults {
760        &self.defaults
761    }
762}
763
764impl Parse for Class {
765    type Error = anyhow::Error;
766
767    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
768        let tail = bytes;
769
770        let (constraints, tail) = ClassConstraints::parse(tail)
771            .map_err(Into::<anyhow::Error>::into)
772            .context("parsing class constraints")?;
773
774        let (validate_transitions, tail) = ClassValidateTransitions::parse(tail)
775            .map_err(Into::<anyhow::Error>::into)
776            .context("parsing class validate transitions")?;
777
778        let (defaults, tail) =
779            PolicyCursor::parse::<ClassDefaults>(tail).context("parsing class defaults")?;
780
781        Ok((Self { constraints, validate_transitions, defaults }, tail))
782    }
783}
784
785#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
786#[repr(C, packed)]
787pub(super) struct ClassDefaults {
788    default_user: le::U32,
789    default_role: le::U32,
790    default_range: le::U32,
791    default_type: le::U32,
792}
793
794impl ClassDefaults {
795    pub fn user(&self) -> ClassDefault {
796        self.default_user.get().into()
797    }
798
799    pub fn role(&self) -> ClassDefault {
800        self.default_role.get().into()
801    }
802
803    pub fn range(&self) -> ClassDefaultRange {
804        self.default_range.get().into()
805    }
806
807    pub fn type_(&self) -> ClassDefault {
808        self.default_type.get().into()
809    }
810}
811
812impl Validate for ClassDefaults {
813    type Error = anyhow::Error;
814
815    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
816        ClassDefault::validate(self.default_user.get()).context("default user")?;
817        ClassDefault::validate(self.default_role.get()).context("default role")?;
818        ClassDefault::validate(self.default_type.get()).context("default type")?;
819        ClassDefaultRange::validate(self.default_range.get()).context("default range")?;
820        Ok(())
821    }
822}
823
824#[derive(PartialEq)]
825pub(super) enum ClassDefault {
826    Unspecified,
827    Source,
828    Target,
829}
830
831impl ClassDefault {
832    pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
833    pub(super) const DEFAULT_SOURCE: u32 = 1;
834    pub(super) const DEFAULT_TARGET: u32 = 2;
835
836    fn validate(value: u32) -> Result<(), ValidateError> {
837        match value {
838            Self::DEFAULT_UNSPECIFIED | Self::DEFAULT_SOURCE | Self::DEFAULT_TARGET => Ok(()),
839            value => Err(ValidateError::InvalidClassDefault { value }),
840        }
841    }
842}
843
844impl From<u32> for ClassDefault {
845    fn from(value: u32) -> Self {
846        match value {
847            Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
848            Self::DEFAULT_SOURCE => Self::Source,
849            Self::DEFAULT_TARGET => Self::Target,
850            v => panic!(
851                "invalid SELinux class default; expected {}, {}, or {}, but got {}",
852                Self::DEFAULT_UNSPECIFIED,
853                Self::DEFAULT_SOURCE,
854                Self::DEFAULT_TARGET,
855                v
856            ),
857        }
858    }
859}
860
861#[derive(PartialEq)]
862pub(super) enum ClassDefaultRange {
863    Unspecified,
864    SourceLow,
865    SourceHigh,
866    SourceLowHigh,
867    TargetLow,
868    TargetHigh,
869    TargetLowHigh,
870}
871
872impl ClassDefaultRange {
873    pub(super) const DEFAULT_UNSPECIFIED: u32 = 0;
874    pub(super) const DEFAULT_SOURCE_LOW: u32 = 1;
875    pub(super) const DEFAULT_SOURCE_HIGH: u32 = 2;
876    pub(super) const DEFAULT_SOURCE_LOW_HIGH: u32 = 3;
877    pub(super) const DEFAULT_TARGET_LOW: u32 = 4;
878    pub(super) const DEFAULT_TARGET_HIGH: u32 = 5;
879    pub(super) const DEFAULT_TARGET_LOW_HIGH: u32 = 6;
880    // TODO: Determine what this value means.
881    pub(super) const DEFAULT_UNKNOWN_USED_VALUE: u32 = 7;
882
883    fn validate(value: u32) -> Result<(), ValidateError> {
884        match value {
885            Self::DEFAULT_UNSPECIFIED
886            | Self::DEFAULT_SOURCE_LOW
887            | Self::DEFAULT_SOURCE_HIGH
888            | Self::DEFAULT_SOURCE_LOW_HIGH
889            | Self::DEFAULT_TARGET_LOW
890            | Self::DEFAULT_TARGET_HIGH
891            | Self::DEFAULT_TARGET_LOW_HIGH
892            | Self::DEFAULT_UNKNOWN_USED_VALUE => Ok(()),
893            value => Err(ValidateError::InvalidClassDefaultRange { value }),
894        }
895    }
896}
897
898impl From<u32> for ClassDefaultRange {
899    fn from(value: u32) -> Self {
900        match value {
901            Self::DEFAULT_UNSPECIFIED => Self::Unspecified,
902            Self::DEFAULT_SOURCE_LOW => Self::SourceLow,
903            Self::DEFAULT_SOURCE_HIGH => Self::SourceHigh,
904            Self::DEFAULT_SOURCE_LOW_HIGH => Self::SourceLowHigh,
905            Self::DEFAULT_TARGET_LOW => Self::TargetLow,
906            Self::DEFAULT_TARGET_HIGH => Self::TargetHigh,
907            Self::DEFAULT_TARGET_LOW_HIGH => Self::TargetLowHigh,
908            v => panic!(
909                "invalid SELinux MLS range default; expected one of {:?}, but got {}",
910                [
911                    Self::DEFAULT_UNSPECIFIED,
912                    Self::DEFAULT_SOURCE_LOW,
913                    Self::DEFAULT_SOURCE_HIGH,
914                    Self::DEFAULT_SOURCE_LOW_HIGH,
915                    Self::DEFAULT_TARGET_LOW,
916                    Self::DEFAULT_TARGET_HIGH,
917                    Self::DEFAULT_TARGET_LOW_HIGH,
918                ],
919                v
920            ),
921        }
922    }
923}
924
925array_type!(ClassValidateTransitions, ClassValidateTransitionsCount, ConstraintTerms);
926
927array_type_validate_deref_metadata_data_vec!(ClassValidateTransitions);
928
929impl ValidateArray<ClassValidateTransitionsCount, ConstraintTerm> for ClassValidateTransitions {
930    type Error = anyhow::Error;
931
932    /// [`ClassValidateTransitions`] has no internal constraints beyond those imposed by [`Array`].
933    fn validate_array(
934        _context: &mut PolicyValidationContext,
935        _metadata: &ClassValidateTransitionsCount,
936        _items: &[ConstraintTerm],
937    ) -> Result<(), Self::Error> {
938        Ok(())
939    }
940}
941
942#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
943#[repr(C, packed)]
944pub(super) struct ClassValidateTransitionsCount(le::U32);
945
946impl Counted for ClassValidateTransitionsCount {
947    fn count(&self) -> u32 {
948        self.0.get()
949    }
950}
951
952impl Validate for ClassValidateTransitionsCount {
953    type Error = anyhow::Error;
954
955    /// TODO: Should there be an upper bound on class validate transitions count?
956    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
957        Ok(())
958    }
959}
960
961array_type!(ClassConstraints, ClassPermissions, Constraints);
962
963array_type_validate_deref_none_data_vec!(ClassConstraints);
964
965impl ValidateArray<ClassPermissions, Constraint> for ClassConstraints {
966    type Error = anyhow::Error;
967
968    /// [`ClassConstraints`] has no internal constraints beyond those imposed by [`Array`].
969    fn validate_array(
970        _context: &mut PolicyValidationContext,
971        _metadata: &ClassPermissions,
972        _items: &[Constraint],
973    ) -> Result<(), Self::Error> {
974        Ok(())
975    }
976}
977
978array_type!(ClassPermissions, ClassCommonKey, Permissions);
979
980array_type_validate_deref_none_data_vec!(ClassPermissions);
981
982impl ValidateArray<ClassCommonKey, Permission> for ClassPermissions {
983    type Error = anyhow::Error;
984
985    /// [`ClassPermissions`] has no internal constraints beyond those imposed by [`Array`].
986    fn validate_array(
987        _context: &mut PolicyValidationContext,
988        _metadata: &ClassCommonKey,
989        _items: &[Permission],
990    ) -> Result<(), Self::Error> {
991        Ok(())
992    }
993}
994
995impl Counted for ClassPermissions {
996    /// [`ClassPermissions`] acts as counted metadata for [`ClassConstraints`].
997    fn count(&self) -> u32 {
998        self.metadata.metadata.metadata.constraint_count.get()
999    }
1000}
1001
1002array_type!(ClassCommonKey, ClassKey, Vec<u8>);
1003
1004array_type_validate_deref_data!(ClassCommonKey);
1005
1006impl ValidateArray<ClassKey, u8> for ClassCommonKey {
1007    type Error = anyhow::Error;
1008
1009    /// [`ClassCommonKey`] has no internal constraints beyond those imposed by [`Array`].
1010    fn validate_array(
1011        _context: &mut PolicyValidationContext,
1012        _metadata: &ClassKey,
1013        _items: &[u8],
1014    ) -> Result<(), Self::Error> {
1015        Ok(())
1016    }
1017}
1018
1019impl Counted for ClassCommonKey {
1020    /// [`ClassCommonKey`] acts as counted metadata for [`ClassPermissions`].
1021    fn count(&self) -> u32 {
1022        self.metadata.metadata.elements_count.get()
1023    }
1024}
1025
1026array_type!(ClassKey, ClassMetadata, Vec<u8>);
1027
1028array_type_validate_deref_both!(ClassKey);
1029
1030impl ValidateArray<ClassMetadata, u8> for ClassKey {
1031    type Error = anyhow::Error;
1032
1033    /// [`ClassKey`] has no internal constraints beyond those imposed by [`Array`].
1034    fn validate_array(
1035        _context: &mut PolicyValidationContext,
1036        _metadata: &ClassMetadata,
1037        _items: &[u8],
1038    ) -> Result<(), Self::Error> {
1039        Ok(())
1040    }
1041}
1042
1043impl Counted for ClassKey {
1044    /// [`ClassKey`] acts as counted metadata for [`ClassCommonKey`].
1045    fn count(&self) -> u32 {
1046        self.metadata.common_key_length.get()
1047    }
1048}
1049
1050#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1051#[repr(C, packed)]
1052pub(super) struct ClassMetadata {
1053    key_length: le::U32,
1054    common_key_length: le::U32,
1055    id: le::U32,
1056    primary_names_count: le::U32,
1057    elements_count: le::U32,
1058    constraint_count: le::U32,
1059}
1060
1061impl Counted for ClassMetadata {
1062    fn count(&self) -> u32 {
1063        self.key_length.get()
1064    }
1065}
1066
1067impl Validate for ClassMetadata {
1068    type Error = anyhow::Error;
1069
1070    /// TODO: Should there be an upper bound `u32` values in [`ClassMetadata`]?
1071    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1072        if self.id.get() == 0 {
1073            return Err(ValidateError::NonOptionalIdIsZero.into());
1074        } else {
1075            Ok(())
1076        }
1077    }
1078}
1079
1080impl Validate for [Role] {
1081    type Error = anyhow::Error;
1082
1083    /// TODO: Validate internal consistency between consecutive [`Role`] instances.
1084    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1085        Ok(())
1086    }
1087}
1088
1089#[derive(Debug, PartialEq)]
1090pub(super) struct Role {
1091    metadata: RoleMetadata,
1092    role_dominates: ExtensibleBitmap,
1093    role_types: ExtensibleBitmap,
1094}
1095
1096impl Role {
1097    pub(super) fn id(&self) -> RoleId {
1098        RoleId(NonZeroU32::new(self.metadata.metadata.id.get()).unwrap())
1099    }
1100
1101    pub(super) fn name_bytes(&self) -> &[u8] {
1102        &self.metadata.data
1103    }
1104
1105    pub(super) fn types(&self) -> &ExtensibleBitmap {
1106        &self.role_types
1107    }
1108}
1109
1110impl Parse for Role {
1111    type Error = anyhow::Error;
1112
1113    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1114        let tail = bytes;
1115
1116        let (metadata, tail) = RoleMetadata::parse(tail)
1117            .map_err(Into::<anyhow::Error>::into)
1118            .context("parsing role metadata")?;
1119
1120        let (role_dominates, tail) = ExtensibleBitmap::parse(tail)
1121            .map_err(Into::<anyhow::Error>::into)
1122            .context("parsing role dominates")?;
1123
1124        let (role_types, tail) = ExtensibleBitmap::parse(tail)
1125            .map_err(Into::<anyhow::Error>::into)
1126            .context("parsing role types")?;
1127
1128        Ok((Self { metadata, role_dominates, role_types }, tail))
1129    }
1130}
1131
1132array_type!(RoleMetadata, RoleStaticMetadata, Vec<u8>);
1133
1134array_type_validate_deref_both!(RoleMetadata);
1135
1136impl ValidateArray<RoleStaticMetadata, u8> for RoleMetadata {
1137    type Error = anyhow::Error;
1138
1139    /// [`RoleMetadata`] has no internal constraints beyond those imposed by [`Array`].
1140    fn validate_array(
1141        _context: &mut PolicyValidationContext,
1142        _metadata: &RoleStaticMetadata,
1143        _items: &[u8],
1144    ) -> Result<(), Self::Error> {
1145        Ok(())
1146    }
1147}
1148
1149#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1150#[repr(C, packed)]
1151pub(super) struct RoleStaticMetadata {
1152    length: le::U32,
1153    id: le::U32,
1154    bounds: le::U32,
1155}
1156
1157impl Counted for RoleStaticMetadata {
1158    /// [`RoleStaticMetadata`] serves as [`Counted`] for a length-encoded `[u8]`.
1159    fn count(&self) -> u32 {
1160        self.length.get()
1161    }
1162}
1163
1164impl Validate for RoleStaticMetadata {
1165    type Error = anyhow::Error;
1166
1167    /// TODO: Should there be any constraints on `length`, `value`, or `bounds`?
1168    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1169        Ok(())
1170    }
1171}
1172
1173impl Validate for [Type] {
1174    type Error = anyhow::Error;
1175
1176    /// TODO: Validate internal consistency between consecutive [`Type`] instances.
1177    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1178        Ok(())
1179    }
1180}
1181
1182array_type!(Type, TypeMetadata, Vec<u8>);
1183
1184array_type_validate_deref_both!(Type);
1185
1186impl Type {
1187    /// Returns the name of this type.
1188    pub fn name_bytes(&self) -> &[u8] {
1189        &self.data
1190    }
1191
1192    /// Returns the id associated with this type. The id is used to index into collections and
1193    /// bitmaps associated with this type. The id is 1-indexed, whereas most collections and
1194    /// bitmaps are 0-indexed, so clients of this API will usually use `id - 1`.
1195    pub fn id(&self) -> TypeId {
1196        TypeId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1197    }
1198
1199    /// Returns the Id of the bounding type, if any.
1200    pub fn bounded_by(&self) -> Option<TypeId> {
1201        NonZeroU32::new(self.metadata.bounds.get()).map(|id| TypeId(id))
1202    }
1203
1204    /// Returns whether this type is from a `type [name];` policy statement.
1205    ///
1206    /// TODO: Eliminate `dead_code` guard.
1207    #[allow(dead_code)]
1208    pub fn is_type(&self) -> bool {
1209        self.metadata.properties.get() == TYPE_PROPERTIES_TYPE
1210    }
1211
1212    /// Returns whether this type is from a `typealias [typename] alias [aliasname];` policy
1213    /// statement.
1214    ///
1215    /// TODO: Eliminate `dead_code` guard.
1216    #[allow(dead_code)]
1217    pub fn is_alias(&self) -> bool {
1218        self.metadata.properties.get() == TYPE_PROPERTIES_ALIAS
1219    }
1220
1221    /// Returns whether this type is from an `attribute [name];` policy statement.
1222    ///
1223    /// TODO: Eliminate `dead_code` guard.
1224    #[allow(dead_code)]
1225    pub fn is_attribute(&self) -> bool {
1226        self.metadata.properties.get() == TYPE_PROPERTIES_ATTRIBUTE
1227    }
1228}
1229
1230impl ValidateArray<TypeMetadata, u8> for Type {
1231    type Error = anyhow::Error;
1232
1233    /// TODO: Validate that `PS::deref(&self.data)` is an ascii string that contains a valid type name.
1234    fn validate_array(
1235        _context: &mut PolicyValidationContext,
1236        _metadata: &TypeMetadata,
1237        _items: &[u8],
1238    ) -> Result<(), Self::Error> {
1239        Ok(())
1240    }
1241}
1242
1243#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1244#[repr(C, packed)]
1245pub(super) struct TypeMetadata {
1246    length: le::U32,
1247    id: le::U32,
1248    properties: le::U32,
1249    bounds: le::U32,
1250}
1251
1252impl Counted for TypeMetadata {
1253    fn count(&self) -> u32 {
1254        self.length.get()
1255    }
1256}
1257
1258impl Validate for TypeMetadata {
1259    type Error = anyhow::Error;
1260
1261    /// TODO: Validate [`TypeMetadata`] internals.
1262    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1263        Ok(())
1264    }
1265}
1266
1267impl Validate for [User] {
1268    type Error = anyhow::Error;
1269
1270    /// TODO: Validate internal consistency between consecutive [`User`] instances.
1271    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1272        Ok(())
1273    }
1274}
1275
1276#[derive(Debug, PartialEq)]
1277pub(super) struct User {
1278    user_data: UserData,
1279    roles: ExtensibleBitmap,
1280    expanded_range: MlsRange,
1281    default_level: MlsLevel,
1282}
1283
1284impl User {
1285    pub(super) fn id(&self) -> UserId {
1286        UserId(NonZeroU32::new(self.user_data.metadata.id.get()).unwrap())
1287    }
1288
1289    pub(super) fn name_bytes(&self) -> &[u8] {
1290        &self.user_data.data
1291    }
1292
1293    pub(super) fn roles(&self) -> &ExtensibleBitmap {
1294        &self.roles
1295    }
1296
1297    pub(super) fn mls_range(&self) -> &MlsRange {
1298        &self.expanded_range
1299    }
1300}
1301
1302impl Parse for User {
1303    type Error = anyhow::Error;
1304
1305    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1306        let tail = bytes;
1307
1308        let (user_data, tail) = UserData::parse(tail)
1309            .map_err(Into::<anyhow::Error>::into)
1310            .context("parsing user data")?;
1311
1312        let (roles, tail) = ExtensibleBitmap::parse(tail)
1313            .map_err(Into::<anyhow::Error>::into)
1314            .context("parsing user roles")?;
1315
1316        let (expanded_range, tail) =
1317            MlsRange::parse(tail).context("parsing user expanded range")?;
1318
1319        let (default_level, tail) = MlsLevel::parse(tail).context("parsing user default level")?;
1320
1321        Ok((Self { user_data, roles, expanded_range, default_level }, tail))
1322    }
1323}
1324
1325array_type!(UserData, UserMetadata, Vec<u8>);
1326
1327array_type_validate_deref_both!(UserData);
1328
1329impl ValidateArray<UserMetadata, u8> for UserData {
1330    type Error = anyhow::Error;
1331
1332    /// TODO: Validate consistency between [`UserMetadata`] in `self.metadata` and `[u8]` key in `self.data`.
1333    fn validate_array(
1334        _context: &mut PolicyValidationContext,
1335        _metadata: &UserMetadata,
1336        _items: &[u8],
1337    ) -> Result<(), Self::Error> {
1338        Ok(())
1339    }
1340}
1341
1342#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1343#[repr(C, packed)]
1344pub(super) struct UserMetadata {
1345    length: le::U32,
1346    id: le::U32,
1347    bounds: le::U32,
1348}
1349
1350impl Counted for UserMetadata {
1351    fn count(&self) -> u32 {
1352        self.length.get()
1353    }
1354}
1355
1356impl Validate for UserMetadata {
1357    type Error = anyhow::Error;
1358
1359    /// TODO: Validate [`UserMetadata`] internals.
1360    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1361        Ok(())
1362    }
1363}
1364
1365#[derive(Debug, PartialEq)]
1366pub(super) struct MlsLevel {
1367    sensitivity: le::U32,
1368    categories: ExtensibleBitmap,
1369}
1370
1371impl MlsLevel {
1372    pub fn category_ids(&self) -> impl Iterator<Item = CategoryId> + use<'_> {
1373        self.categories.indices_of_set_bits().map(|i| CategoryId(NonZeroU32::new(i + 1).unwrap()))
1374    }
1375}
1376
1377impl Parse for MlsLevel {
1378    type Error = anyhow::Error;
1379
1380    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1381        let tail = bytes;
1382
1383        let num_bytes = tail.len();
1384        let (sensitivity, tail) =
1385            PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1386                type_name: "MlsLevelSensitivity",
1387                type_size: std::mem::size_of::<le::U32>(),
1388                num_bytes,
1389            })?;
1390
1391        let (categories, tail) = ExtensibleBitmap::parse(tail)
1392            .map_err(Into::<anyhow::Error>::into)
1393            .context("parsing mls level categories")?;
1394
1395        Ok((Self { sensitivity, categories }, tail))
1396    }
1397}
1398
1399impl<'a> Level<'a, ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> for MlsLevel {
1400    fn sensitivity(&self) -> SensitivityId {
1401        SensitivityId(NonZeroU32::new(self.sensitivity.get()).unwrap())
1402    }
1403
1404    fn category_spans(
1405        &'a self,
1406    ) -> CategoryIterator<ExtensibleBitmapSpan, ExtensibleBitmapSpansIterator<'a>> {
1407        CategoryIterator::new(self.categories.spans())
1408    }
1409}
1410
1411#[derive(Debug, PartialEq)]
1412pub(super) struct MlsRange {
1413    count: le::U32,
1414    low: MlsLevel,
1415    high: Option<MlsLevel>,
1416}
1417
1418impl MlsRange {
1419    pub fn low(&self) -> &MlsLevel {
1420        &self.low
1421    }
1422
1423    pub fn high(&self) -> &Option<MlsLevel> {
1424        &self.high
1425    }
1426}
1427
1428impl Parse for MlsRange {
1429    type Error = anyhow::Error;
1430
1431    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1432        let tail = bytes;
1433
1434        let num_bytes = tail.len();
1435        let (count, tail) =
1436            PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1437                type_name: "MlsLevelCount",
1438                type_size: std::mem::size_of::<le::U32>(),
1439                num_bytes,
1440            })?;
1441
1442        // `MlsRange::parse()` cannot be implemented in terms of `MlsLevel::parse()` for the
1443        // low and optional high level, because of the order in which the sensitivity and
1444        // category bitmap fields appear.
1445        let num_bytes = tail.len();
1446        let (sensitivity_low, tail) =
1447            PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1448                type_name: "MlsLevelSensitivityLow",
1449                type_size: std::mem::size_of::<le::U32>(),
1450                num_bytes,
1451            })?;
1452
1453        let (low_categories, high_level, tail) = if count.get() > 1 {
1454            let num_bytes = tail.len();
1455            let (sensitivity_high, tail) =
1456                PolicyCursor::parse::<le::U32>(tail).ok_or(ParseError::MissingData {
1457                    type_name: "MlsLevelSensitivityHigh",
1458                    type_size: std::mem::size_of::<le::U32>(),
1459                    num_bytes,
1460                })?;
1461            let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1462                .map_err(Into::<anyhow::Error>::into)
1463                .context("parsing mls range low categories")?;
1464            let (high_categories, tail) = ExtensibleBitmap::parse(tail)
1465                .map_err(Into::<anyhow::Error>::into)
1466                .context("parsing mls range high categories")?;
1467
1468            (
1469                low_categories,
1470                Some(MlsLevel { sensitivity: sensitivity_high, categories: high_categories }),
1471                tail,
1472            )
1473        } else {
1474            let (low_categories, tail) = ExtensibleBitmap::parse(tail)
1475                .map_err(Into::<anyhow::Error>::into)
1476                .context("parsing mls range low categories")?;
1477
1478            (low_categories, None, tail)
1479        };
1480
1481        Ok((
1482            Self {
1483                count,
1484                low: MlsLevel { sensitivity: sensitivity_low, categories: low_categories },
1485                high: high_level,
1486            },
1487            tail,
1488        ))
1489    }
1490}
1491
1492impl Validate for [ConditionalBoolean] {
1493    type Error = anyhow::Error;
1494
1495    /// TODO: Validate consistency of sequence of [`ConditionalBoolean`].
1496    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1497        Ok(())
1498    }
1499}
1500
1501array_type!(ConditionalBoolean, ConditionalBooleanMetadata, Vec<u8>);
1502
1503array_type_validate_deref_both!(ConditionalBoolean);
1504
1505impl ValidateArray<ConditionalBooleanMetadata, u8> for ConditionalBoolean {
1506    type Error = anyhow::Error;
1507
1508    /// TODO: Validate consistency between [`ConditionalBooleanMetadata`] and `[u8]` key.
1509    fn validate_array(
1510        _context: &mut PolicyValidationContext,
1511        _metadata: &ConditionalBooleanMetadata,
1512        _items: &[u8],
1513    ) -> Result<(), Self::Error> {
1514        Ok(())
1515    }
1516}
1517
1518#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1519#[repr(C, packed)]
1520pub(super) struct ConditionalBooleanMetadata {
1521    id: le::U32,
1522    /// Current active value of this conditional boolean.
1523    active: le::U32,
1524    length: le::U32,
1525}
1526
1527impl ConditionalBooleanMetadata {
1528    /// Returns the active value for the boolean.
1529    pub(super) fn active(&self) -> bool {
1530        self.active != le::U32::ZERO
1531    }
1532}
1533
1534impl Counted for ConditionalBooleanMetadata {
1535    /// [`ConditionalBooleanMetadata`] used as `M` in of `Array<PS, PS::Output<M>, PS::Slice<u8>>` with
1536    /// `self.length` denoting size of inner `[u8]`.
1537    fn count(&self) -> u32 {
1538        self.length.get()
1539    }
1540}
1541
1542impl Validate for ConditionalBooleanMetadata {
1543    type Error = anyhow::Error;
1544
1545    /// TODO: Validate internal consistency of [`ConditionalBooleanMetadata`].
1546    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1547        Ok(())
1548    }
1549}
1550
1551impl Validate for [Sensitivity] {
1552    type Error = anyhow::Error;
1553
1554    /// TODO: Validate consistency of sequence of [`Sensitivity`].
1555    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1556        Ok(())
1557    }
1558}
1559
1560#[derive(Debug, PartialEq)]
1561pub(super) struct Sensitivity {
1562    metadata: SensitivityMetadata,
1563    level: MlsLevel,
1564}
1565
1566impl Sensitivity {
1567    pub fn id(&self) -> SensitivityId {
1568        SensitivityId(NonZeroU32::new(self.level.sensitivity.get()).unwrap())
1569    }
1570
1571    pub fn name_bytes(&self) -> &[u8] {
1572        &self.metadata.data
1573    }
1574}
1575
1576impl Parse for Sensitivity {
1577    type Error = anyhow::Error;
1578
1579    fn parse(bytes: PolicyCursor) -> Result<(Self, PolicyCursor), Self::Error> {
1580        let tail = bytes;
1581
1582        let (metadata, tail) = SensitivityMetadata::parse(tail)
1583            .map_err(Into::<anyhow::Error>::into)
1584            .context("parsing sensitivity metadata")?;
1585
1586        let (level, tail) = MlsLevel::parse(tail)
1587            .map_err(Into::<anyhow::Error>::into)
1588            .context("parsing sensitivity mls level")?;
1589
1590        Ok((Self { metadata, level }, tail))
1591    }
1592}
1593
1594impl Validate for Sensitivity {
1595    type Error = anyhow::Error;
1596
1597    /// TODO: Validate internal consistency of `self.metadata` and `self.level`.
1598    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1599        NonZeroU32::new(self.level.sensitivity.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1600        Ok(())
1601    }
1602}
1603
1604array_type!(SensitivityMetadata, SensitivityStaticMetadata, Vec<u8>);
1605
1606array_type_validate_deref_both!(SensitivityMetadata);
1607
1608impl ValidateArray<SensitivityStaticMetadata, u8> for SensitivityMetadata {
1609    type Error = anyhow::Error;
1610
1611    /// TODO: Validate consistency between [`SensitivityMetadata`] and `[u8]` key.
1612    fn validate_array(
1613        _context: &mut PolicyValidationContext,
1614        _metadata: &SensitivityStaticMetadata,
1615        _items: &[u8],
1616    ) -> Result<(), Self::Error> {
1617        Ok(())
1618    }
1619}
1620
1621#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1622#[repr(C, packed)]
1623pub(super) struct SensitivityStaticMetadata {
1624    length: le::U32,
1625    is_alias: le::U32,
1626}
1627
1628impl Counted for SensitivityStaticMetadata {
1629    /// [`SensitivityStaticMetadata`] used as `M` in of `Array<PS, PS::Output<M>, PS::Slice<u8>>` with
1630    /// `self.length` denoting size of inner `[u8]`.
1631    fn count(&self) -> u32 {
1632        self.length.get()
1633    }
1634}
1635
1636impl Validate for SensitivityStaticMetadata {
1637    type Error = anyhow::Error;
1638
1639    /// TODO: Validate internal consistency of [`SensitivityStaticMetadata`].
1640    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1641        Ok(())
1642    }
1643}
1644
1645impl Validate for [Category] {
1646    type Error = anyhow::Error;
1647
1648    /// TODO: Validate consistency of sequence of [`Category`].
1649    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1650        Ok(())
1651    }
1652}
1653
1654array_type!(Category, CategoryMetadata, Vec<u8>);
1655
1656array_type_validate_deref_both!(Category);
1657
1658impl Category {
1659    pub fn id(&self) -> CategoryId {
1660        CategoryId(NonZeroU32::new(self.metadata.id.get()).unwrap())
1661    }
1662
1663    pub fn name_bytes(&self) -> &[u8] {
1664        &self.data
1665    }
1666}
1667
1668impl ValidateArray<CategoryMetadata, u8> for Category {
1669    type Error = anyhow::Error;
1670
1671    /// TODO: Validate consistency between [`CategoryMetadata`] and `[u8]` key.
1672    fn validate_array(
1673        _context: &mut PolicyValidationContext,
1674        _metadata: &CategoryMetadata,
1675        _items: &[u8],
1676    ) -> Result<(), Self::Error> {
1677        Ok(())
1678    }
1679}
1680
1681#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
1682#[repr(C, packed)]
1683pub(super) struct CategoryMetadata {
1684    length: le::U32,
1685    id: le::U32,
1686    is_alias: le::U32,
1687}
1688
1689impl Counted for CategoryMetadata {
1690    /// [`CategoryMetadata`] used as `M` in of `Array<PS, PS::Output<M>, PS::Slice<u8>>` with
1691    /// `self.length` denoting size of inner `[u8]`.
1692    fn count(&self) -> u32 {
1693        self.length.get()
1694    }
1695}
1696
1697impl Validate for CategoryMetadata {
1698    type Error = anyhow::Error;
1699
1700    /// TODO: Validate internal consistency of [`CategoryMetadata`].
1701    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
1702        NonZeroU32::new(self.id.get()).ok_or(ValidateError::NonOptionalIdIsZero)?;
1703        Ok(())
1704    }
1705}
1706
1707#[cfg(test)]
1708mod tests {
1709    use super::super::security_context::Level;
1710    use super::super::{CategoryId, SensitivityId, UserId, parse_policy_by_value};
1711    use super::*;
1712
1713    use std::num::NonZeroU32;
1714
1715    #[test]
1716    fn mls_levels_for_user_context() {
1717        const TEST_POLICY: &[u8] = include_bytes! {"../../testdata/micro_policies/multiple_levels_and_categories_policy.pp"};
1718        let policy = parse_policy_by_value(TEST_POLICY.to_vec()).unwrap();
1719        let policy = policy.validate().unwrap();
1720        let parsed_policy = policy.0.parsed_policy();
1721
1722        let user = parsed_policy.user(UserId(NonZeroU32::new(1).expect("user with id 1")));
1723        let mls_range = user.mls_range();
1724        let low_level = mls_range.low();
1725        let high_level = mls_range.high().as_ref().expect("user 1 has a high mls level");
1726
1727        assert_eq!(low_level.sensitivity(), SensitivityId(NonZeroU32::new(1).unwrap()));
1728        assert_eq!(
1729            low_level.category_ids().collect::<Vec<_>>(),
1730            vec![CategoryId(NonZeroU32::new(1).unwrap())]
1731        );
1732
1733        assert_eq!(high_level.sensitivity(), SensitivityId(NonZeroU32::new(2).unwrap()));
1734        assert_eq!(
1735            high_level.category_ids().collect::<Vec<_>>(),
1736            vec![
1737                CategoryId(NonZeroU32::new(1).unwrap()),
1738                CategoryId(NonZeroU32::new(2).unwrap()),
1739                CategoryId(NonZeroU32::new(3).unwrap()),
1740                CategoryId(NonZeroU32::new(4).unwrap()),
1741                CategoryId(NonZeroU32::new(5).unwrap()),
1742            ]
1743        );
1744    }
1745
1746    #[test]
1747    fn parse_mls_constrain_statement() {
1748        let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1749        let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1750        let parsed_policy = &policy.0;
1751        parsed_policy.validate().expect("validate policy");
1752
1753        let class = find_class_by_name(parsed_policy.classes(), "class_mls_constraints")
1754            .expect("look up class");
1755        let constraints = class.constraints();
1756        assert_eq!(constraints.len(), 6);
1757        // Expected (`constraint_term_type`, `expr_operator_type`,
1758        // `expr_operand_type`) values for the single term of the
1759        // corresponding class constraint.
1760        //
1761        // NB. Constraint statements appear in reverse order in binary policy
1762        // vs. text policy.
1763        let expected = [
1764            (
1765                CONSTRAINT_TERM_TYPE_EXPR,
1766                CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1767                CONSTRAINT_EXPR_OPERAND_TYPE_L1_H1,
1768            ),
1769            (
1770                CONSTRAINT_TERM_TYPE_EXPR,
1771                CONSTRAINT_EXPR_OPERATOR_TYPE_INCOMP,
1772                CONSTRAINT_EXPR_OPERAND_TYPE_H1_H2,
1773            ),
1774            (
1775                CONSTRAINT_TERM_TYPE_EXPR,
1776                CONSTRAINT_EXPR_OPERATOR_TYPE_DOMBY,
1777                CONSTRAINT_EXPR_OPERAND_TYPE_L1_H2,
1778            ),
1779            (
1780                CONSTRAINT_TERM_TYPE_EXPR,
1781                CONSTRAINT_EXPR_OPERATOR_TYPE_DOM,
1782                CONSTRAINT_EXPR_OPERAND_TYPE_H1_L2,
1783            ),
1784            (
1785                CONSTRAINT_TERM_TYPE_EXPR,
1786                CONSTRAINT_EXPR_OPERATOR_TYPE_NE,
1787                CONSTRAINT_EXPR_OPERAND_TYPE_L2_H2,
1788            ),
1789            (
1790                CONSTRAINT_TERM_TYPE_EXPR,
1791                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1792                CONSTRAINT_EXPR_OPERAND_TYPE_L1_L2,
1793            ),
1794        ];
1795        for (i, constraint) in constraints.iter().enumerate() {
1796            assert_eq!(constraint.access_vector(), AccessVector(1), "constraint {}", i);
1797            let terms = constraint.constraint_expr().constraint_terms();
1798            assert_eq!(terms.len(), 1, "constraint {}", i);
1799            let term = &terms[0];
1800            assert_eq!(
1801                (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1802                expected[i],
1803                "constraint {}",
1804                i
1805            );
1806        }
1807    }
1808
1809    #[test]
1810    fn parse_constrain_statement() {
1811        let policy_bytes = include_bytes!("../../testdata/micro_policies/constraints_policy.pp");
1812        let policy = parse_policy_by_value(policy_bytes.to_vec()).expect("parse policy");
1813        let parsed_policy = &policy.0;
1814        parsed_policy.validate().expect("validate policy");
1815
1816        let class = find_class_by_name(parsed_policy.classes(), "class_constraint_nested")
1817            .expect("look up class");
1818        let constraints = class.constraints();
1819        assert_eq!(constraints.len(), 1);
1820        let constraint = &constraints[0];
1821        assert_eq!(constraint.access_vector(), AccessVector(1));
1822        let terms = constraint.constraint_expr().constraint_terms();
1823        assert_eq!(terms.len(), 8);
1824
1825        // Expected (`constraint_term_type`, `expr_operator_type`,
1826        // `expr_operand_type`) values for the constraint terms.
1827        //
1828        // NB. Constraint statements appear in reverse order in binary policy
1829        // vs. text policy.
1830        let expected = [
1831            (
1832                CONSTRAINT_TERM_TYPE_EXPR_WITH_NAMES,
1833                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1834                CONSTRAINT_EXPR_OPERAND_TYPE_USER
1835                    | CONSTRAINT_EXPR_WITH_NAMES_OPERAND_TYPE_TARGET_MASK,
1836            ),
1837            (
1838                CONSTRAINT_TERM_TYPE_EXPR,
1839                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1840                CONSTRAINT_EXPR_OPERAND_TYPE_ROLE,
1841            ),
1842            (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1843            (
1844                CONSTRAINT_TERM_TYPE_EXPR,
1845                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1846                CONSTRAINT_EXPR_OPERAND_TYPE_USER,
1847            ),
1848            (
1849                CONSTRAINT_TERM_TYPE_EXPR,
1850                CONSTRAINT_EXPR_OPERATOR_TYPE_EQ,
1851                CONSTRAINT_EXPR_OPERAND_TYPE_TYPE,
1852            ),
1853            (CONSTRAINT_TERM_TYPE_NOT_OPERATOR, 0, 0),
1854            (CONSTRAINT_TERM_TYPE_AND_OPERATOR, 0, 0),
1855            (CONSTRAINT_TERM_TYPE_OR_OPERATOR, 0, 0),
1856        ];
1857        for (i, term) in terms.iter().enumerate() {
1858            assert_eq!(
1859                (term.constraint_term_type(), term.expr_operator_type(), term.expr_operand_type()),
1860                expected[i],
1861                "term {}",
1862                i
1863            );
1864        }
1865    }
1866}