//! Two-link traversal and bounded loop refusal in the product kernel. use super::*; use os_vfs_paths::{Error as PathError, Mount, MountNamespace, PathState}; use os_vfs_symlink::{Error as LinkError, Link, SymlinkTable}; fn namespace() -> Result { let resolver = PathState::new(); let root = resolver.resolve(b"/sandbox").map_err(|_| "k1560-root")?; let first = Mount::new(resolver.resolve(b"/sandbox/veri") .map_err(|_| "k1560-first-path")?, 1).map_err(|_| "k1560-first-mount")?; let second = Mount::new(resolver.resolve(b"/sandbox/ara") .map_err(|_| "k1560-second-path")?, 2).map_err(|_| "k1560-second-mount")?; MountNamespace::new(root, first, second).map_err(|_| "k1560-namespace") } pub fn run(allocator: &mut memory::FrameAllocator) -> Result<(), &'static str> { let frames_before = allocator.remaining_pages(); let namespace = namespace()?; let first_link = Link::new(&namespace, b"/veri/kisa", b"/ara/ikinci") .map_err(|_| "k1560-first-link")?; let second_link = Link::new(&namespace, b"/ara/ikinci", b"/ara/dosya") .map_err(|_| "k1560-second-link")?; let table = SymlinkTable::new(first_link, second_link) .map_err(|_| "k1560-table")?; let result = table.resolve(&namespace, b"/veri/kisa") .map_err(|_| "k1560-resolve")?; if result.hops != 2 || result.route.volume != 2 || result.route.path.component(2) != Some("dosya") { return Err("k1560-two-hop-result"); } let self_link = Link::new(&namespace, b"/veri/dongu", b"/veri/dongu") .map_err(|_| "k1560-self-link")?; let loop_table = SymlinkTable::new(self_link, second_link) .map_err(|_| "k1560-loop-table")?; if loop_table.resolve(&namespace, b"/veri/dongu") != Err(LinkError::Eloop(40)) || Link::new(&namespace, b"/veri/kisa", b"/../../../disari") != Err(LinkError::Path(PathError::AboveRoot)) || namespace.cwd != namespace.process_root || namespace.generation != 0 || allocator.remaining_pages() != frames_before { return Err("k1560-bounds"); } write_line("TURKOS/OS/K1560-SYMLINK: HOPS=2 VOLUME=2 ELOOP=40 ROOT=REJECTED STATE=UNCHANGED FRAMES=UNCHANGED"); Ok(()) }