twizzler_security/sec_ctx/
user.rs1use core::fmt::Display;
2
3use heapless::Vec;
4use twizzler::object::{Object, ObjectBuilder, RawObject, TypedObject};
5use twizzler_abi::{
6 object::{ObjID, Protections},
7 syscall::{
8 sys_sctx_attach, sys_thread_active_sctx_id, sys_thread_set_active_sctx_id, ObjectCreate,
9 },
10};
11use twizzler_rt_abi::{
12 error::{ResourceError, TwzError},
13 object::MapFlags,
14};
15
16use super::{CtxMapItem, CtxMapItemType, SecCtxBase, SecCtxFlags};
17use crate::{
18 sec_ctx::{MAP_ITEMS_PER_OBJ, OBJECT_ROOT_OFFSET},
19 Cap, Del,
20};
21
22#[derive(Debug)]
23pub struct SecCtx {
25 uobj: Object<SecCtxBase>,
26}
27
28impl Default for SecCtx {
29 fn default() -> Self {
30 let obj = ObjectBuilder::default()
31 .build(SecCtxBase::default())
32 .unwrap();
33
34 Self { uobj: obj }
35 }
36}
37
38impl Display for SecCtx {
39 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40 let binding = self.uobj.clone();
41 let base = binding.base();
42
43 write!(f, "Sec Ctx ObjID: {} {{\n", self.uobj.id())?;
44 write!(f, "base: {:?}", base)?;
45 Ok(())
46 }
47}
48
49impl SecCtx {
50 pub fn active_ctx() -> SecCtx {
52 let curr_sec_ctx_id = sys_thread_active_sctx_id();
53
54 Self::try_from(curr_sec_ctx_id)
55 .expect("We should always be able to parse the currently attached security context")
56 }
57
58 pub fn attach(&self) -> Result<(), TwzError> {
60 sys_sctx_attach(self.id())
61 }
62
63 pub fn set_active(&self) -> Result<(), TwzError> {
65 sys_sctx_attach(self.id())?;
66 sys_thread_set_active_sctx_id(self.id())
67 }
68
69 pub fn base(&self) -> &SecCtxBase {
71 self.uobj.base()
72 }
73
74 pub fn new(
76 object_create_spec: ObjectCreate,
77 global_mask: Protections,
78 flags: SecCtxFlags,
79 ) -> Result<Self, TwzError> {
80 let new_obj =
81 ObjectBuilder::new(object_create_spec).build(SecCtxBase::new(global_mask, flags))?;
82
83 Ok(Self { uobj: new_obj })
84 }
85
86 pub fn insert_cap(&mut self, cap: Cap) -> Result<(), TwzError> {
88 let mut tx = self.uobj.clone().into_tx()?;
89 let mut base = tx.base_mut();
90
91 let mut map_item = {
92 base.offset += size_of::<Cap>();
93
94 CtxMapItem {
95 item_type: CtxMapItemType::Cap,
96 offset: base.offset + OBJECT_ROOT_OFFSET,
97 }
98 };
99
100 let alignment = 0x10 - (map_item.offset % 0x10);
101 map_item.offset += alignment;
102 base.offset += alignment;
104
105 #[cfg(feature = "log")]
106 log::debug!("write offset into object for entry: {:#X}", map_item.offset);
107
108 if let Some(vec) = base.map.get_mut(&cap.target) {
110 vec.push(map_item).map_err(|_| {
111 TwzError::Resource(ResourceError::OutOfResources)
113 })?;
114 } else {
115 let mut new_vec = Vec::<CtxMapItem, MAP_ITEMS_PER_OBJ>::new();
116 let _ = new_vec.push(map_item);
117 let _ = base.map.insert(cap.target, new_vec).map_err(|_| {
118 TwzError::Resource(ResourceError::OutOfResources)
120 })?;
121 };
122
123 let ptr = tx
124 .lea_mut(map_item.offset, size_of::<Cap>())
125 .expect("Write offset should not result in a pointer outside of the object")
126 .cast::<Cap>();
127
128 unsafe {
131 *ptr = cap;
132 }
133
134 tx.commit()?;
135
136 #[cfg(feature = "log")]
137 log::debug!("Added capability at ptr: {:#?}", ptr);
138 Ok(())
139 }
140
141 pub fn insert_del(&mut self, _del: Del) -> Result<(), TwzError> {
146 unimplemented!()
147 }
148
149 pub fn id(&self) -> ObjID {
151 self.uobj.id()
152 }
153
154 pub fn remove_cap(&mut self) {
159 unimplemented!()
160 }
161
162 pub fn remove_del(&mut self) {
167 unimplemented!()
168 }
169}
170
171impl TryFrom<ObjID> for SecCtx {
172 type Error = TwzError;
173 fn try_from(value: ObjID) -> Result<Self, Self::Error> {
174 let uobj = Object::<SecCtxBase>::map(value, MapFlags::READ | MapFlags::WRITE)?;
175
176 Ok(Self { uobj })
177 }
178}
179#[cfg(test)]
180#[cfg(feature = "user")]
181mod tests {
182 use super::*;
183 use crate::sec_ctx::SecCtxFlags;
184
185 extern crate test;
186
187 #[test]
188 #[test]
189 fn test_security_context_creation() {
190 let _default_sec_ctx = SecCtx::default();
191 let _new_sec_ctx =
192 SecCtx::new(Default::default(), Protections::all(), SecCtxFlags::empty())
193 .expect("new context should have been created!");
194 }
195}