use crate::cap::cnode; use crate::cap::object::ObjectTag; use crate::cap::ops; use crate::cap::pool::POOL; use crate::cap::table::Rights; use crate::error::KernelError; use crate::proc::PROCESSES; use crate::types::Pid; fn bootstrap_test_cnode(pid: Pid, ptable: &mut crate::proc::ProcessManager) { crate::tests::helpers::bootstrap_test_cnode(pid, ptable); } crate::kernel_test!( fn derive_from_empty_slot_fails() { let mut allocator = crate::mem::phys::BitmapFrameAllocator; let mut ptable = PROCESSES.lock(); let created = ptable.allocate(&mut allocator).expect("alloc"); ptable.start(created).expect("start"); let pid = created.pid(); bootstrap_test_cnode(pid, &mut ptable); let src_addr = 80u64; let dest_addr = 81u64; let (cnode_id, cnode_gen, depth, gv, gb) = cnode::cnode_coords(pid, &ptable).expect("coords"); let result = { let mut pool = POOL.lock_after(&ptable); ops::derive_via_cnode( &mut pool, cnode_id, cnode_gen, src_addr, dest_addr, depth, gv, gb, Rights::ALL, ) }; assert!( matches!(result, Err(KernelError::SlotEmpty)), "derive from empty slot should return SlotEmpty" ); ptable.destroy(pid, &mut allocator); } ); crate::kernel_test!( fn derive_cannot_escalate_rights() { let mut allocator = crate::mem::phys::BitmapFrameAllocator; let mut ptable = PROCESSES.lock(); let created = ptable.allocate(&mut allocator).expect("alloc"); ptable.start(created).expect("start"); let pid = created.pid(); bootstrap_test_cnode(pid, &mut ptable); let src_addr = 82u64; let dest_addr = 83u64; let (cnode_id, cnode_gen, depth, gv, gb) = cnode::cnode_coords(pid, &ptable).expect("coords"); { let mut pool = POOL.lock_after(&ptable); ops::create_via_cnode( &mut pool, cnode_id, cnode_gen, src_addr, depth, gv, gb, ObjectTag::Endpoint, ) .expect("create"); } { let pool = POOL.lock_after(&ptable); let old_cap = cnode::resolve_and_clear(&pool, cnode_id, cnode_gen, src_addr, depth, gv, gb) .expect("clear slot"); let new_cap = old_cap.with_rights(Rights::READ | Rights::GRANT); cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, src_addr, depth, gv, gb, new_cap) .expect("reinsert cap"); } { let mut pool = POOL.lock_after(&ptable); ops::derive_via_cnode( &mut pool, cnode_id, cnode_gen, src_addr, dest_addr, depth, gv, gb, Rights::ALL, ) .expect("derive"); } { let pool = POOL.lock_after(&ptable); let cap = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_addr, depth, gv, gb) .expect("read derived slot"); assert!( cap.rights().contains(Rights::READ), "derived should have READ" ); assert!( cap.rights().contains(Rights::GRANT), "derived should have GRANT" ); assert!( !cap.rights().contains(Rights::WRITE), "derived should NOT have WRITE (not in source)" ); assert!( !cap.rights().contains(Rights::REVOKE), "derived should NOT have REVOKE (not in source)" ); } ptable.destroy(pid, &mut allocator); } ); crate::kernel_test!( fn revoke_eagerly_invalidates_derived() { let mut allocator = crate::mem::phys::BitmapFrameAllocator; let mut ptable = PROCESSES.lock(); let created = ptable.allocate(&mut allocator).expect("alloc"); ptable.start(created).expect("start"); let pid = created.pid(); bootstrap_test_cnode(pid, &mut ptable); let src_addr = 84u64; let dest_addr = 85u64; let (cnode_id, cnode_gen, depth, gv, gb) = cnode::cnode_coords(pid, &ptable).expect("coords"); { let mut pool = POOL.lock_after(&ptable); ops::create_via_cnode( &mut pool, cnode_id, cnode_gen, src_addr, depth, gv, gb, ObjectTag::Endpoint, ) .expect("create"); } { let mut pool = POOL.lock_after(&ptable); ops::derive_via_cnode( &mut pool, cnode_id, cnode_gen, src_addr, dest_addr, depth, gv, gb, Rights::ALL, ) .expect("derive"); } ops::revoke_via_cnode(pid, src_addr, &mut ptable).expect("revoke"); { let pool = POOL.lock_after(&ptable); let src_result = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, src_addr, depth, gv, gb); assert!( matches!(src_result, Err(KernelError::SlotEmpty)), "source slot should be empty after revoke" ); let dest_result = cnode::resolve_and_read(&pool, cnode_id, cnode_gen, dest_addr, depth, gv, gb); assert!( matches!(dest_result, Err(KernelError::SlotEmpty)), "derived slot should be eagerly cleared by revoke's invalidate_stale_caps" ); } { let pool = POOL.lock_after(&ptable); let result = ops::identify_via_cnode(&pool, cnode_id, cnode_gen, dest_addr, depth, gv, gb); assert!( matches!(result, Err(KernelError::SlotEmpty)), "identify on eagerly-invalidated slot should return SlotEmpty" ); } ptable.destroy(pid, &mut allocator); } );