Skip to content

Commit

Permalink
Add resource transition functionality (#85)
Browse files Browse the repository at this point in the history
The resource_transition function keyword is now available for use.
  • Loading branch information
matt-sheets authored Jan 6, 2023
1 parent f06bd61 commit a3d2424
Show file tree
Hide file tree
Showing 7 changed files with 340 additions and 0 deletions.
16 changes: 16 additions & 0 deletions data/error_policies/resource_trans.cas
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
resource foo {
resource_transition(this, domain, bar, [quack]);

resource_transition(aaa, zap, bar, [file]);
resource_transition(foo, bbb, bar, [file]);
resource_transition(foo, zap, ccc, [file]);

// Policies must include at least one av rule
allow(domain, foo, file, [read]);
}

resource bar {}

domain zap {
resource_transition(foo, this, bar, [file dir]);
}
136 changes: 136 additions & 0 deletions data/expected_cil/resource_trans.cil

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions data/policies/resource_trans.cas
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource foo {
resource_transition(this, domain, bar, [file dir]);

// Policies must include at least one av rule
allow(domain, foo, file, [read]);
}

resource bar {}
4 changes: 4 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ impl Statement {
pub enum BuiltIns {
AvRule,
FileContext,
ResourceTransition,
DomainTransition,
}

Expand Down Expand Up @@ -425,6 +426,9 @@ impl FuncCall {
if self.name == constants::FILE_CONTEXT_FUNCTION_NAME {
return Some(BuiltIns::FileContext);
}
if self.name == constants::RESOURCE_TRANS_FUNCTION_NAME {
return Some(BuiltIns::ResourceTransition);
}
if self.name == constants::DOMTRANS_FUNCTION_NAME {
return Some(BuiltIns::DomainTransition);
}
Expand Down
1 change: 1 addition & 0 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub const DONTAUDIT_FUNCTION_NAME: &str = "dontaudit";
pub const AUDITALLOW_FUNCTION_NAME: &str = "auditallow";
pub const NEVERALLOW_FUNCTION_NAME: &str = "neverallow";
pub const FILE_CONTEXT_FUNCTION_NAME: &str = "file_context";
pub const RESOURCE_TRANS_FUNCTION_NAME: &str = "resource_transition";
pub const DOMTRANS_FUNCTION_NAME: &str = "domain_transition";
pub const SYSTEM_TYPE: &str = "machine_type";
pub const MONOLITHIC: &str = "monolithic";
Expand Down
158 changes: 158 additions & 0 deletions src/internal_rep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,139 @@ fn call_to_domain_transition<'a>(
})
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ResourcetransRule<'a> {
pub default: Cow<'a, CascadeString>,
pub domain: Cow<'a, CascadeString>,
pub parent: Cow<'a, CascadeString>,
pub file_type: FileType,
}

impl ResourcetransRule<'_> {
fn get_renamed_statement(&self, renames: &BTreeMap<String, String>) -> Self {
ResourcetransRule {
default: rename_cow(&self.default, renames),
domain: rename_cow(&self.domain, renames),
parent: rename_cow(&self.parent, renames),
file_type: self.file_type,
}
}
}

impl From<&ResourcetransRule<'_>> for sexp::Sexp {
fn from(r: &ResourcetransRule) -> Self {
list(&[
atom_s("typetransition"),
atom_s(&r.domain.get_cil_name()),
atom_s(&r.parent.get_cil_name()),
Sexp::Atom(Atom::S(r.file_type.to_string())),
atom_s(&r.default.get_cil_name()),
])
}
}

fn call_to_resource_transition<'a>(
c: &'a FuncCall,
types: &'a TypeMap,
class_perms: &ClassList,
context: &BlockContext<'a>,
file: &'a SimpleFile<String, String>,
) -> Result<Vec<ResourcetransRule<'a>>, CascadeErrors> {
let target_args = vec![
FunctionArgument::new(
&DeclaredArgument {
param_type: CascadeString::from(constants::RESOURCE),
is_list_param: false,
name: CascadeString::from("default"),
default: None,
},
types,
None,
)?,
FunctionArgument::new(
&DeclaredArgument {
param_type: CascadeString::from(constants::DOMAIN),
is_list_param: false,
name: CascadeString::from("domain"),
default: None,
},
types,
None,
)?,
FunctionArgument::new(
&DeclaredArgument {
param_type: CascadeString::from(constants::RESOURCE),
is_list_param: false,
name: CascadeString::from("parent"),
default: None,
},
types,
None,
)?,
FunctionArgument::new(
&DeclaredArgument {
param_type: CascadeString::from("obj_class"), //TODO: not really
is_list_param: true,
name: CascadeString::from("file_type"),
default: Some(Argument::List(vec![])),
},
types,
None,
)?,
];

let validated_args =
validate_arguments(c, &target_args, types, class_perms, context, Some(file))?;
let mut args_iter = validated_args.into_iter();
let mut ret = Vec::new();

let default = args_iter
.next()
.ok_or_else(|| ErrorItem::Internal(InternalError::new()))?
.get_name_or_string(context)?;
let domain = args_iter
.next()
.ok_or_else(|| ErrorItem::Internal(InternalError::new()))?
.get_name_or_string(context)?;
let parent = args_iter
.next()
.ok_or_else(|| ErrorItem::Internal(InternalError::new()))?
.get_name_or_string(context)?;
let file_types = args_iter
.next()
.ok_or_else(|| ErrorItem::Internal(InternalError::new()))?
.get_list(context)?;

if args_iter.next().is_some() {
return Err(ErrorItem::Internal(InternalError::new()).into());
}

for file_type in file_types {
let file_type = match file_type.to_string().parse::<FileType>() {
Ok(f) => f,
Err(_) => {
return Err(CascadeErrors::from(
ErrorItem::make_compile_or_internal_error(
"Not a valid file type",
Some(file),
file_type.get_range(),
"",
),
))
}
};

ret.push(ResourcetransRule {
default: Cow::Owned(default.clone()),
domain: Cow::Owned(domain.clone()),
parent: Cow::Owned(parent.clone()),
file_type,
});
}

Ok(ret)
}

fn check_associated_call(
annotation: &Annotation,
funcdecl: &FuncDecl,
Expand Down Expand Up @@ -2091,6 +2224,7 @@ impl TryFrom<&FunctionInfo<'_>> for sexp::Sexp {
ValidatedStatement::Call(c) => macro_cil.push(Sexp::from(&**c)),
ValidatedStatement::AvRule(a) => macro_cil.push(Sexp::from(a)),
ValidatedStatement::FcRule(f) => macro_cil.push(Sexp::from(f)),
ValidatedStatement::ResourcetransRule(r) => macro_cil.push(Sexp::from(r)),
ValidatedStatement::DomtransRule(d) => macro_cil.push(Sexp::from(d)),
}
}
Expand Down Expand Up @@ -2176,6 +2310,7 @@ pub enum ValidatedStatement<'a> {
Call(Box<ValidatedCall>),
AvRule(AvRule<'a>),
FcRule(FileContextRule<'a>),
ResourcetransRule(ResourcetransRule<'a>),
DomtransRule(DomtransRule<'a>),
}

Expand Down Expand Up @@ -2219,6 +2354,25 @@ impl<'a> ValidatedStatement<'a> {
))
}
}
Some(BuiltIns::ResourceTransition) => {
if in_resource {
Ok(
call_to_resource_transition(c, types, class_perms, &*context, file)?
.into_iter()
.map(ValidatedStatement::ResourcetransRule)
.collect(),
)
} else {
Err(CascadeErrors::from(
ErrorItem::make_compile_or_internal_error(
"resource_transition() calls are not allowed in domains",
Some(file),
c.name.get_range(),
"Not allowed here",
),
))
}
}
Some(BuiltIns::DomainTransition) => {
if !in_resource {
Ok(
Expand Down Expand Up @@ -2290,6 +2444,9 @@ impl<'a> ValidatedStatement<'a> {
ValidatedStatement::DomtransRule(d) => {
ValidatedStatement::DomtransRule(d.get_renamed_statement(renames))
}
ValidatedStatement::ResourcetransRule(r) => {
ValidatedStatement::ResourcetransRule(r.get_renamed_statement(renames))
}
}
}
}
Expand All @@ -2300,6 +2457,7 @@ impl From<&ValidatedStatement<'_>> for sexp::Sexp {
ValidatedStatement::Call(c) => Sexp::from(&**c),
ValidatedStatement::AvRule(a) => Sexp::from(a),
ValidatedStatement::FcRule(f) => Sexp::from(f),
ValidatedStatement::ResourcetransRule(r) => Sexp::from(r),
ValidatedStatement::DomtransRule(d) => Sexp::from(d),
}
}
Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,4 +1206,21 @@ mod tests {
fn valid_self() {
valid_policy_test("self.cas", &["allow qux self (file (read))"], &[]);
}

#[test]
fn invalid_resourcetrans() {
error_policy_test!("resource_trans.cas", 5, ErrorItem::Compile(_));
}

#[test]
fn valid_resourcetrans() {
valid_policy_test(
"resource_trans.cas",
&[
"(typetransition domain bar file foo)",
"(typetransition domain bar dir foo)",
],
&[],
);
}
}

0 comments on commit a3d2424

Please sign in to comment.