selinux/policy/
metadata.rs1#[cfg(test)]
6use super::Parse;
7#[cfg(test)]
8use super::error::ParseError;
9#[cfg(test)]
10use super::error::ValidateError;
11#[cfg(test)]
12use super::parser::PolicyCursor;
13#[cfg(test)]
14use super::{
15 Array, Counted, PolicyValidationContext, Validate, ValidateArray, array_type,
16 array_type_validate_deref_both,
17};
18
19#[cfg(test)]
20use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
21
22#[cfg(test)]
23use crate::new_policy::HandleUnknown;
24
25pub(super) const SELINUX_MAGIC: u32 = 0xf97cff8c;
26
27pub(super) const POLICYDB_STRING_MAX_LENGTH: u32 = 32;
28pub(super) const POLICYDB_SIGNATURE: &[u8] = b"SE Linux";
29
30pub(super) const POLICYDB_VERSION_MIN: u32 = 30;
31pub const POLICYDB_VERSION_MAX: u32 = 33;
32
33pub(super) const CONFIG_MLS_FLAG: u32 = 1;
34pub(super) const CONFIG_HANDLE_UNKNOWN_REJECT_FLAG: u32 = 1 << 1;
35pub(super) const CONFIG_HANDLE_UNKNOWN_ALLOW_FLAG: u32 = 1 << 2;
36pub(super) const CONFIG_HANDLE_UNKNOWN_MASK: u32 =
37 CONFIG_HANDLE_UNKNOWN_REJECT_FLAG | CONFIG_HANDLE_UNKNOWN_ALLOW_FLAG;
38
39#[cfg(test)]
40#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
41#[repr(C, packed)]
42pub(super) struct Magic(le::U32);
43
44#[cfg(test)]
45impl Validate for Magic {
46 type Error = ValidateError;
47
48 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
49 let found_magic = self.0.get();
50 if found_magic != SELINUX_MAGIC {
51 Err(ValidateError::InvalidMagic { found_magic })
52 } else {
53 Ok(())
54 }
55 }
56}
57
58#[cfg(test)]
59array_type!(Signature, SignatureMetadata, u8);
60
61#[cfg(test)]
62array_type_validate_deref_both!(Signature);
63
64#[cfg(test)]
65impl ValidateArray<SignatureMetadata, u8> for Signature {
66 type Error = ValidateError;
67
68 fn validate_array(
69 _context: &PolicyValidationContext,
70 _metadata: &SignatureMetadata,
71 items: &[u8],
72 ) -> Result<(), Self::Error> {
73 if items != POLICYDB_SIGNATURE {
74 Err(ValidateError::InvalidSignature { found_signature: items.to_owned() })
75 } else {
76 Ok(())
77 }
78 }
79}
80
81#[cfg(test)]
82#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
83#[repr(C, packed)]
84pub(super) struct SignatureMetadata(le::U32);
85
86#[cfg(test)]
87impl Validate for SignatureMetadata {
88 type Error = ValidateError;
89
90 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
92 let found_length = self.0.get();
93 if found_length > POLICYDB_STRING_MAX_LENGTH {
94 Err(ValidateError::InvalidSignatureLength { found_length })
95 } else {
96 Ok(())
97 }
98 }
99}
100
101#[cfg(test)]
102impl Counted for SignatureMetadata {
103 fn count(&self) -> u32 {
104 self.0.get()
105 }
106}
107
108#[cfg(test)]
109#[derive(Debug)]
110pub(super) struct Config {
111 #[allow(dead_code)]
112 config: le::U32,
113}
114
115#[cfg(test)]
116impl Parse for Config {
117 type Error = ParseError;
118
119 fn parse<'a>(bytes: PolicyCursor<'a>) -> Result<(Self, PolicyCursor<'a>), Self::Error> {
120 let (config, tail) = PolicyCursor::parse::<le::U32>(bytes)?;
121
122 let found_config = config.get();
123 if found_config & CONFIG_MLS_FLAG == 0 {
124 return Err(ParseError::ConfigMissingMlsFlag { found_config });
125 }
126 let _ = try_handle_unknown_fom_config(found_config)?;
127
128 Ok((Self { config }, tail))
129 }
130}
131
132#[cfg(test)]
133impl Validate for Config {
134 type Error = anyhow::Error;
135
136 fn validate(&self, _context: &PolicyValidationContext) -> Result<(), Self::Error> {
139 Ok(())
140 }
141}
142
143#[cfg(test)]
144fn try_handle_unknown_fom_config(config: u32) -> Result<HandleUnknown, ParseError> {
145 match config & CONFIG_HANDLE_UNKNOWN_MASK {
146 CONFIG_HANDLE_UNKNOWN_ALLOW_FLAG => Ok(HandleUnknown::Allow),
147 CONFIG_HANDLE_UNKNOWN_REJECT_FLAG => Ok(HandleUnknown::Reject),
148 0 => Ok(HandleUnknown::Deny),
149 _ => Err(ParseError::InvalidHandleUnknownConfigurationBits {
150 masked_bits: (config & CONFIG_HANDLE_UNKNOWN_MASK),
151 }),
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::super::parser::{PolicyCursor, PolicyData};
158 use super::super::testing::as_parse_error;
159
160 use super::*;
161
162 #[test]
164 fn no_magic() {
165 let mut bytes = [SELINUX_MAGIC.to_le_bytes().as_slice()].concat();
166 bytes.pop();
168 let data = PolicyData::from(bytes);
169 assert_eq!(
170 Err(ParseError::MissingData {
171 type_name: "selinux_lib_test::policy::metadata::Magic",
172 type_size: 4,
173 num_bytes: 3
174 }),
175 PolicyCursor::parse::<Magic>(PolicyCursor::new(&data)),
176 );
177 }
178
179 #[test]
180 fn missing_signature() {
181 let bytes = [(1 as u32).to_le_bytes().as_slice()].concat();
182 let data = PolicyData::from(bytes);
183 match Signature::parse(PolicyCursor::new(&data)).err().map(as_parse_error) {
184 Some(ParseError::MissingData { type_name: "u8", type_size: 1, num_bytes: 0 }) => {}
185 parse_err => {
186 assert!(false, "Expected Some(MissingData...), but got {:?}", parse_err);
187 }
188 }
189 }
190
191 #[test]
192 fn config_missing_mls_flag() {
193 let bytes = [(!CONFIG_MLS_FLAG).to_le_bytes().as_slice()].concat();
194 let data = PolicyData::from(bytes);
195 match Config::parse(PolicyCursor::new(&data)).err() {
196 Some(ParseError::ConfigMissingMlsFlag { .. }) => {}
197 parse_err => {
198 assert!(false, "Expected Some(ConfigMissingMlsFlag...), but got {:?}", parse_err);
199 }
200 }
201 }
202
203 #[test]
204 fn invalid_handle_unknown() {
205 let bytes = [(CONFIG_MLS_FLAG
206 | CONFIG_HANDLE_UNKNOWN_ALLOW_FLAG
207 | CONFIG_HANDLE_UNKNOWN_REJECT_FLAG)
208 .to_le_bytes()
209 .as_slice()]
210 .concat();
211 let data = PolicyData::from(bytes);
212 assert_eq!(
213 Some(ParseError::InvalidHandleUnknownConfigurationBits {
214 masked_bits: CONFIG_HANDLE_UNKNOWN_ALLOW_FLAG | CONFIG_HANDLE_UNKNOWN_REJECT_FLAG
215 }),
216 Config::parse(PolicyCursor::new(&data)).err()
217 );
218 }
219}