1use crate::errors::ThreadError;
4use crate::security::{SecurityConfig, SecurityViolation, handle_security_violation};
5use crate::thread_new::ThreadId;
6use portable_atomic::{AtomicU64, AtomicUsize, Ordering};
7use alloc::{collections::BTreeMap, vec, vec::Vec};
8
9pub struct ThreadIsolation {
11 domains: BTreeMap<ThreadId, IsolationDomain>,
13 violations_detected: AtomicUsize,
15 boundary_crosses: AtomicU64,
17}
18
19impl ThreadIsolation {
20 pub fn new() -> Self {
21 Self {
22 domains: BTreeMap::new(),
23 violations_detected: AtomicUsize::new(0),
24 boundary_crosses: AtomicU64::new(0),
25 }
26 }
27
28 pub fn create_domain(
30 &mut self,
31 thread_id: ThreadId,
32 config: IsolationConfig,
33 ) -> Result<(), ThreadError> {
34 let domain = IsolationDomain::new(thread_id, config)?;
35 self.domains.insert(thread_id, domain);
36 Ok(())
37 }
38
39 pub fn check_access(
41 &self,
42 accessor_id: ThreadId,
43 target_id: ThreadId,
44 access_type: AccessType,
45 ) -> bool {
46 if accessor_id == target_id {
47 return true; }
49
50 let accessor_domain = match self.domains.get(&accessor_id) {
51 Some(domain) => domain,
52 None => return true, };
54
55 let allowed = accessor_domain.check_cross_domain_access(target_id, access_type);
56
57 if !allowed {
58 self.violations_detected.fetch_add(1, Ordering::Relaxed);
59 } else {
60 self.boundary_crosses.fetch_add(1, Ordering::Relaxed);
61 }
62
63 allowed
64 }
65
66 pub fn remove_domain(&mut self, thread_id: ThreadId) {
68 self.domains.remove(&thread_id);
69 }
70}
71
72#[derive(Debug, Clone)]
74pub struct IsolationConfig {
75 pub security_level: SecurityLevel,
77 pub allowed_operations: Vec<AccessType>,
79 pub memory_restrictions: MemoryRestrictions,
81 pub resource_limits: ResourceLimits,
83 pub ipc_policy: IpcPolicy,
85}
86
87impl Default for IsolationConfig {
88 fn default() -> Self {
89 Self {
90 security_level: SecurityLevel::Medium,
91 allowed_operations: vec![AccessType::Signal],
92 memory_restrictions: MemoryRestrictions::default(),
93 resource_limits: ResourceLimits::default(),
94 ipc_policy: IpcPolicy::Restricted,
95 }
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
101pub enum SecurityLevel {
102 Low,
104 Medium,
106 High,
108 Critical,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum AccessType {
115 MemoryRead,
117 MemoryWrite,
119 Signal,
121 ResourceShare,
123 Ipc,
125 ThreadControl,
127}
128
129#[derive(Debug, Clone)]
131pub struct MemoryRestrictions {
132 pub allowed_regions: Vec<MemoryRegion>,
134 pub forbidden_regions: Vec<MemoryRegion>,
136 pub heap_access: HeapAccessPolicy,
138 pub stack_access: StackAccessPolicy,
140}
141
142impl Default for MemoryRestrictions {
143 fn default() -> Self {
144 Self {
145 allowed_regions: Vec::new(),
146 forbidden_regions: Vec::new(),
147 heap_access: HeapAccessPolicy::Isolated,
148 stack_access: StackAccessPolicy::Private,
149 }
150 }
151}
152
153#[derive(Debug, Clone)]
155pub struct MemoryRegion {
156 pub start: usize,
157 pub size: usize,
158 pub permissions: MemoryPermissions,
159}
160
161#[derive(Debug, Clone, Copy)]
163pub struct MemoryPermissions {
164 pub read: bool,
165 pub write: bool,
166 pub execute: bool,
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub enum HeapAccessPolicy {
172 Isolated,
174 Shared,
176 None,
178}
179
180#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182pub enum StackAccessPolicy {
183 Private,
185 LimitedAccess,
187 Shared,
189}
190
191#[derive(Debug, Clone)]
193pub struct ResourceLimits {
194 pub max_memory: Option<usize>,
196 pub max_cpu_time: Option<u64>,
198 pub max_file_handles: Option<usize>,
200 pub max_network_connections: Option<usize>,
202}
203
204impl Default for ResourceLimits {
205 fn default() -> Self {
206 Self {
207 max_memory: Some(64 * 1024 * 1024), max_cpu_time: None,
209 max_file_handles: Some(256),
210 max_network_connections: Some(16),
211 }
212 }
213}
214
215#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub enum IpcPolicy {
218 Blocked,
220 Restricted,
222 Controlled,
224 Unrestricted,
226}
227
228#[derive(Debug)]
230pub struct IsolationDomain {
231 pub thread_id: ThreadId,
233 pub config: IsolationConfig,
235 pub resource_usage: ResourceUsage,
237 pub allowed_domains: Vec<ThreadId>,
239 pub created_at: u64,
241}
242
243impl IsolationDomain {
244 pub fn new(thread_id: ThreadId, config: IsolationConfig) -> Result<Self, ThreadError> {
246 Ok(Self {
247 thread_id,
248 config,
249 resource_usage: ResourceUsage::new(),
250 allowed_domains: Vec::new(),
251 created_at: crate::time::get_monotonic_time().as_nanos() as u64,
252 })
253 }
254
255 pub fn check_cross_domain_access(
257 &self,
258 target_domain: ThreadId,
259 access_type: AccessType,
260 ) -> bool {
261 if !self.config.allowed_operations.contains(&access_type) {
266 return false;
267 }
268
269 if !self.allowed_domains.is_empty() && !self.allowed_domains.contains(&target_domain) {
271 return false;
272 }
273
274 match self.config.security_level {
276 SecurityLevel::Low => true,
277 SecurityLevel::Medium => match access_type {
278 AccessType::MemoryWrite | AccessType::ThreadControl => false,
279 _ => true,
280 },
281 SecurityLevel::High => match access_type {
282 AccessType::Signal => true,
283 _ => false,
284 },
285 SecurityLevel::Critical => false, }
287 }
288
289 pub fn allow_domain_interaction(&mut self, domain_id: ThreadId) {
291 if !self.allowed_domains.contains(&domain_id) {
292 self.allowed_domains.push(domain_id);
293 }
294 }
295
296 pub fn disallow_domain_interaction(&mut self, domain_id: ThreadId) {
298 self.allowed_domains.retain(|&id| id != domain_id);
299 }
300
301 pub fn check_memory_access(&self, address: usize, size: usize, write: bool) -> bool {
303 for region in &self.config.memory_restrictions.forbidden_regions {
305 if address >= region.start && address < region.start + region.size {
306 return false;
307 }
308 }
309
310 if !self.config.memory_restrictions.allowed_regions.is_empty() {
312 let mut found = false;
313 for region in &self.config.memory_restrictions.allowed_regions {
314 if address >= region.start
315 && address + size <= region.start + region.size
316 && (!write || region.permissions.write) {
317 found = true;
318 break;
319 }
320 }
321 if !found {
322 return false;
323 }
324 }
325
326 true
327 }
328
329 pub fn update_resource_usage(&mut self, usage: ResourceUsage) -> Result<(), ThreadError> {
331 if let Some(max_memory) = self.config.resource_limits.max_memory {
333 if usage.memory_used > max_memory {
334 return Err(ThreadError::ResourceExhaustion());
335 }
336 }
337
338 if let Some(max_cpu) = self.config.resource_limits.max_cpu_time {
340 if usage.cpu_time_used > max_cpu {
341 return Err(ThreadError::ResourceExhaustion());
342 }
343 }
344
345 self.resource_usage = usage;
346 Ok(())
347 }
348}
349
350#[derive(Debug, Clone)]
352pub struct ResourceUsage {
353 pub memory_used: usize,
354 pub cpu_time_used: u64,
355 pub file_handles_used: usize,
356 pub network_connections_used: usize,
357}
358
359impl ResourceUsage {
360 pub fn new() -> Self {
361 Self {
362 memory_used: 0,
363 cpu_time_used: 0,
364 file_handles_used: 0,
365 network_connections_used: 0,
366 }
367 }
368}
369
370static mut THREAD_ISOLATION: Option<ThreadIsolation> = None;
372
373pub struct MemoryAccessGuard {
375 domain_id: ThreadId,
376 address: usize,
377 size: usize,
378}
379
380impl MemoryAccessGuard {
381 pub fn new(domain_id: ThreadId, address: usize, size: usize) -> Result<Self, ThreadError> {
383 if !check_memory_access(domain_id, address, size, false) {
385 handle_security_violation(SecurityViolation::IsolationViolation);
386 }
387
388 Ok(Self {
389 domain_id,
390 address,
391 size,
392 })
393 }
394
395 pub unsafe fn read_ptr<T>(&self) -> *const T {
397 self.address as *const T
398 }
399
400 pub unsafe fn write_ptr<T>(&self) -> Result<*mut T, ThreadError> {
402 if !check_memory_access(self.domain_id, self.address, self.size, true) {
403 handle_security_violation(SecurityViolation::IsolationViolation);
404 }
405 Ok(self.address as *mut T)
406 }
407}
408
409pub struct CrossDomainChannel {
411 sender_domain: ThreadId,
412 receiver_domain: ThreadId,
413 allowed: bool,
414}
415
416impl CrossDomainChannel {
417 pub fn new(sender: ThreadId, receiver: ThreadId) -> Result<Self, ThreadError> {
419 let allowed = check_cross_domain_access(sender, receiver, AccessType::Ipc);
420
421 if !allowed {
422 return Err(ThreadError::PermissionDenied());
423 }
424
425 Ok(Self {
426 sender_domain: sender,
427 receiver_domain: receiver,
428 allowed,
429 })
430 }
431
432 pub fn send<T>(&self, message: T) -> Result<(), ThreadError> {
434 if !self.allowed {
435 return Err(ThreadError::PermissionDenied());
436 }
437
438 Ok(())
441 }
442}
443
444pub fn init_thread_isolation(_config: SecurityConfig) -> Result<(), ThreadError> {
448 unsafe {
449 THREAD_ISOLATION = Some(ThreadIsolation::new());
450 }
451
452 Ok(())
454}
455
456pub fn create_isolation_domain(
458 thread_id: ThreadId,
459 config: IsolationConfig,
460) -> Result<(), ThreadError> {
461 unsafe {
462 if let Some(isolation) = &mut THREAD_ISOLATION {
463 isolation.create_domain(thread_id, config)
464 } else {
465 Err(ThreadError::InvalidState())
466 }
467 }
468}
469
470pub fn check_cross_domain_access(
472 accessor_id: ThreadId,
473 target_id: ThreadId,
474 access_type: AccessType,
475) -> bool {
476 unsafe {
477 if let Some(isolation) = &THREAD_ISOLATION {
478 isolation.check_access(accessor_id, target_id, access_type)
479 } else {
480 true }
482 }
483}
484
485pub fn check_memory_access(
487 domain_id: ThreadId,
488 address: usize,
489 size: usize,
490 write: bool,
491) -> bool {
492 unsafe {
493 if let Some(isolation) = &THREAD_ISOLATION {
494 if let Some(domain) = isolation.domains.get(&domain_id) {
495 domain.check_memory_access(address, size, write)
496 } else {
497 true }
499 } else {
500 true }
502 }
503}
504
505pub fn remove_isolation_domain(thread_id: ThreadId) {
507 unsafe {
508 if let Some(isolation) = &mut THREAD_ISOLATION {
509 isolation.remove_domain(thread_id);
510 }
511 }
512}
513
514#[derive(Debug, Clone)]
516pub struct IsolationStats {
517 pub domains_active: usize,
518 pub violations_detected: usize,
519 pub boundary_crosses: u64,
520 pub isolation_enabled: bool,
521}
522
523pub fn get_isolation_stats() -> IsolationStats {
525 unsafe {
526 if let Some(isolation) = &THREAD_ISOLATION {
527 IsolationStats {
528 domains_active: isolation.domains.len(),
529 violations_detected: isolation.violations_detected.load(Ordering::Relaxed),
530 boundary_crosses: isolation.boundary_crosses.load(Ordering::Relaxed),
531 isolation_enabled: true,
532 }
533 } else {
534 IsolationStats {
535 domains_active: 0,
536 violations_detected: 0,
537 boundary_crosses: 0,
538 isolation_enabled: false,
539 }
540 }
541 }
542}
543
544#[macro_export]
546macro_rules! isolated_thread {
547 ($thread_id:expr, $security_level:expr) => {{
548 use crate::security::isolation::{IsolationConfig, SecurityLevel, create_isolation_domain};
549 let config = IsolationConfig {
550 security_level: $security_level,
551 ..Default::default()
552 };
553 create_isolation_domain($thread_id, config)
554 }};
555}
556
557#[macro_export]
559macro_rules! cross_domain_access {
560 ($accessor:expr, $target:expr, $access_type:expr, $operation:expr) => {{
561 use crate::security::isolation::check_cross_domain_access;
562 if check_cross_domain_access($accessor, $target, $access_type) {
563 Some($operation)
564 } else {
565 None
566 }
567 }};
568}