diff --git a/Makefile b/Makefile index 2ce135db10..1d7dd2c993 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ base: --manifest-path "$(SRC_DIR)/Cargo.toml" \ $(INITFS_CARGO_ARGS) $(INITFS_DRIVERS_CARGO_ARGS) # Build bootstrap - cd "$(SRC_DIR)/bootstrap" && $(CARGO) rustc $(BUILD_FLAGS) \ + cd "$(SRC_DIR)/bootstrap" && RUSTFLAGS= $(CARGO) rustc $(BUILD_FLAGS) \ -- -Ctarget-feature=+crt-static -Clinker="$(LINKER)" install-base: base $(SYSROOT)/bin/redoxfs @@ -117,3 +117,15 @@ install-base: base $(SYSROOT)/bin/redoxfs # Distribute initfs @mkdir -pv "$(DESTDIR)/usr/lib/boot" cp -v "$(BUILD_DIR)/initfs.img" "$(DESTDIR)/usr/lib/boot/initfs" + +# Device file symlinks + @mkdir -pv "$(DESTDIR)/dev" + ln -sf /scheme/null $(DESTDIR)/dev/null + ln -sf /scheme/pty/ptmx $(DESTDIR)/dev/ptmx + ln -sf /scheme/rand $(DESTDIR)/dev/random + ln -sf /scheme/rand $(DESTDIR)/dev/urandom + ln -sf /scheme/zero $(DESTDIR)/dev/zero + ln -sf libc:tty $(DESTDIR)/dev/tty + ln -sf libc:stdin $(DESTDIR)/dev/stdin + ln -sf libc:stdout $(DESTDIR)/dev/stdout + ln -sf libc:stderr $(DESTDIR)/dev/stderr diff --git a/bootstrap/src/exec.rs b/bootstrap/src/exec.rs index 85d78d2cc8..71858019fa 100644 --- a/bootstrap/src/exec.rs +++ b/bootstrap/src/exec.rs @@ -238,8 +238,6 @@ pub fn main() -> ! { .openat_into_upper(exe_reference, O_RDONLY | O_CLOEXEC, 0) .expect("failed to open init"); - drop(initfs_root_fd); - let FexecResult::Interp { path: interp_path, interp_override, @@ -265,24 +263,13 @@ pub fn main() -> ! { // null-terminated. Violating this should therefore give the "format error" ENOEXEC. let interp_cstr = CStr::from_bytes_with_nul(&interp_path).expect("interpreter not valid C str"); let interp_path = interp_cstr.to_str().expect("interpreter not UTF-8"); - let root_fd = FdGuard::new( - redox_rt::sys::openat_into_upper( - extrainfo.ns_fd.unwrap(), // initns, not initfs! - interp_path, - O_RDONLY | O_CLOEXEC, - 0, - ) - .expect("failed to open root fd"), - ) - .to_upper() - .unwrap(); let redox_path = redox_path::RedoxPath::from_absolute(interp_path) .expect("interpreter path is not a Scheme-rooted path"); - let (_, reference) = redox_path + let (_, interp_reference) = redox_path .as_parts() .expect("redox_path is not scheme root path"); - let interp_file = root_fd - .openat_into_upper(reference.as_ref(), O_RDONLY | O_CLOEXEC, 0) + let interp_file = initfs_root_fd + .openat_into_upper(interp_reference.as_ref(), O_RDONLY | O_CLOEXEC, 0) .expect("failed to open dynamic linker"); fexec_impl( diff --git a/drivers/graphics/fbbootlogd/src/scheme.rs b/drivers/graphics/fbbootlogd/src/scheme.rs index 812c4a5bc3..96424cc378 100644 --- a/drivers/graphics/fbbootlogd/src/scheme.rs +++ b/drivers/graphics/fbbootlogd/src/scheme.rs @@ -197,7 +197,7 @@ impl SchemeSync for FbbootlogScheme { } fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - FpathWriter::with_legacy(buf, "fbbootlog", |_| Ok(())) + FpathWriter::with(buf, "fbbootlog", |_| Ok(())) } fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> { diff --git a/drivers/graphics/fbcond/src/scheme.rs b/drivers/graphics/fbcond/src/scheme.rs index 352ebec735..b7ec833f89 100644 --- a/drivers/graphics/fbcond/src/scheme.rs +++ b/drivers/graphics/fbcond/src/scheme.rs @@ -144,7 +144,7 @@ impl SchemeSync for FbconScheme { } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - FpathWriter::with_legacy(buf, "fbcon", |w| { + FpathWriter::with(buf, "fbcon", |w| { let handle = self.get_vt_handle_mut(id)?; write!(w, "{}", handle.vt_i.0).unwrap(); Ok(()) diff --git a/drivers/storage/driver-block/src/lib.rs b/drivers/storage/driver-block/src/lib.rs index 5ecf4583ed..a5e9fcb91b 100644 --- a/drivers/storage/driver-block/src/lib.rs +++ b/drivers/storage/driver-block/src/lib.rs @@ -568,7 +568,7 @@ impl SchemeAsync for DiskSchemeInner { } async fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - FpathWriter::with_legacy(buf, &self.scheme_name, |w| { + FpathWriter::with(buf, &self.scheme_name, |w| { match *self.handles.get(id)? { Handle::List(_) => (), Handle::Disk(number) => { diff --git a/drivers/storage/nvmed/src/main.rs b/drivers/storage/nvmed/src/main.rs index beb1b68940..0e0de46ab6 100644 --- a/drivers/storage/nvmed/src/main.rs +++ b/drivers/storage/nvmed/src/main.rs @@ -39,19 +39,14 @@ impl Disk for NvmeDisk { } fn time_arm(time_handle: &mut File, secs: i64) -> io::Result<()> { - let mut time_buf = [0_u8; core::mem::size_of::()]; + let mut time_buf = syscall::TimeSpec::default(); if time_handle.read(&mut time_buf)? < time_buf.len() { return Err(io::Error::new( io::ErrorKind::InvalidData, "time read too small", )); } - - match libredox::data::timespec_from_mut_bytes(&mut time_buf) { - time => { - time.tv_sec += secs; - } - } + time_buf.tv_sec += secs; time_handle.write(&time_buf)?; Ok(()) } diff --git a/drivers/usb/xhcid/src/xhci/irq_reactor.rs b/drivers/usb/xhcid/src/xhci/irq_reactor.rs index 58eeb79f1c..b4620fd6f4 100644 --- a/drivers/usb/xhcid/src/xhci/irq_reactor.rs +++ b/drivers/usb/xhcid/src/xhci/irq_reactor.rs @@ -104,6 +104,12 @@ pub struct IrqReactor { pub type NewPendingTrb = State; +enum EventProcessResult { + NoEvent, + EventRingFull, + RegularEvent, +} + impl IrqReactor { pub fn new(hci: Arc>, irq_file: Option) -> Self { let device_enumerator_sender = hci.device_enumerator_sender.clone(); @@ -139,45 +145,14 @@ impl IrqReactor { let mut event_ring = hci_clone.primary_event_ring.lock().unwrap_or_else(|e| e.into_inner()); - let event_trb = &mut event_ring.ring.trbs[event_trb_index]; - - if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 { - continue 'trb_loop; - } - - trace!( - "Found event TRB at index {} with type {} and cycle bit {}: {:?}", - event_trb_index, - event_trb.trb_type(), - event_trb.cycle() as u8, - event_trb - ); - - if self.check_event_ring_full(event_trb.clone()) { - info!("Had to resize event TRB, retrying..."); - continue 'trb_loop; - } - - trace!("Handling requests"); - self.handle_requests(); - trace!("Requests handled"); - - match event_trb.trb_type() { - _ if event_trb.trb_type() == TrbType::PortStatusChange as u8 => { - trace!("Received a port status change!"); - self.handle_port_status_change(event_trb.clone()) - } //TODO Handle the other unprompted events - _ => { - self.acknowledge(event_trb.clone()); + loop { + match self.process_one_event(&mut event_ring, &mut event_trb_index) { + EventProcessResult::NoEvent | EventProcessResult::EventRingFull => { + continue 'trb_loop + } + EventProcessResult::RegularEvent => {} } } - - event_trb.reserved(false); - - self.update_erdp(&*event_ring); - hci_clone.event_handler_finished(); - - event_trb_index = event_ring.ring.next_index(); } } @@ -263,69 +238,102 @@ impl IrqReactor { loop { trace!("count: {}", count); - let event_trb = &mut event_ring.ring.trbs[event_trb_index]; - if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 { - if count == 0 { - // Linux 7.1 xhci-pci.c SPURIOUS_REBOOT: some - // Intel controllers (Panther Point, Lynx Point) - // generate spurious interrupts under load. - // Downgrade from warn to debug when quirked. - if self.hci.quirks.contains(crate::xhci::quirks::XhciQuirks::SPURIOUS_REBOOT) { - debug!("xhci: spurious interrupt (SPURIOUS_REBOOT quirk active) — ignoring"); - } else { - warn!("xhci: Received interrupt, but no event was found in the event ring. Ignoring interrupt."); + match self.process_one_event(&mut event_ring, &mut event_trb_index) { + EventProcessResult::NoEvent => { + if count == 0 { + // Linux 7.1 xhci-pci.c SPURIOUS_REBOOT: some + // Intel controllers (Panther Point, Lynx Point) + // generate spurious interrupts under load. + // Downgrade from warn to debug when quirked. + if self.hci.quirks.contains(crate::xhci::quirks::XhciQuirks::SPURIOUS_REBOOT) { + debug!("xhci: spurious interrupt (SPURIOUS_REBOOT quirk active) — ignoring"); + } else { + warn!("xhci: Received interrupt, but no event was found in the event ring. Ignoring interrupt.") + } } + self.unmask_interrupts(); + + // Process any events received between the NoEvent and unmasking interrupts + loop { + match self.process_one_event(&mut event_ring, &mut event_trb_index) { + EventProcessResult::NoEvent => break, + EventProcessResult::EventRingFull + | EventProcessResult::RegularEvent => {} + } + } + + continue 'trb_loop; } - //hci_clone.event_handler_finished(); - self.unmask_interrupts(); - continue 'trb_loop; - } else { - count += 1 - } - - info!( - "Found event TRB at index {} with type {} and cycle bit {}: {:?}", - event_trb_index, - event_trb.trb_type(), - event_trb.cycle() as u8, - event_trb - ); - - if self.check_event_ring_full(event_trb.clone()) { - info!("Had to resize event TRB, retrying..."); - //hci_clone.event_handler_finished(); - if self.hci.interrupt_is_pending(0) { - warn!("After incrementing the dequeue pointer, the interrupt bit is still pending.") - } else { - debug!("The interrupt bit is no longer pending."); + EventProcessResult::EventRingFull => { + // FIXME can this use the RegularEvent path? + if self.hci.interrupt_is_pending(0) { + warn!("After incrementing the dequeue pointer, the interrupt bit is still pending.") + } else { + debug!("The interrupt bit is no longer pending."); + } + self.unmask_interrupts(); + continue 'trb_loop; } - self.unmask_interrupts(); - continue 'trb_loop; - } - self.handle_requests(); - - match event_trb.trb_type() { - _ if event_trb.trb_type() == TrbType::PortStatusChange as u8 => { - trace!("Received a port status change!"); - self.handle_port_status_change(event_trb.clone()) - } //TODO Handle the other unprompted events - _ => { - trace!("Received a non-status trb"); - self.acknowledge(event_trb.clone()); + EventProcessResult::RegularEvent => { + count += 1; } } - - event_trb.reserved(false); - - self.update_erdp(&*event_ring); - self.hci.event_handler_finished(); - - event_trb_index = event_ring.ring.next_index(); } } } + fn process_one_event( + &mut self, + event_ring: &mut EventRing, + event_trb_index: &mut usize, + ) -> EventProcessResult { + let event_trb = &mut event_ring.ring.trbs[*event_trb_index]; + + if event_trb.completion_code() == TrbCompletionCode::Invalid as u8 { + //hci_clone.event_handler_finished(); + return EventProcessResult::NoEvent; + } + + trace!( + "Found event TRB at index {} with type {} and cycle bit {}: {:?}", + event_trb_index, + event_trb.trb_type(), + event_trb.cycle() as u8, + event_trb + ); + + if self.check_event_ring_full(event_trb.clone()) { + info!("Had to resize event TRB, retrying..."); + //hci_clone.event_handler_finished(); + return EventProcessResult::EventRingFull; + } + + trace!("Handling requests"); + self.handle_requests(); + trace!("Requests handled"); + + match event_trb.trb_type() { + _ if event_trb.trb_type() == TrbType::PortStatusChange as u8 => { + trace!("Received a port status change!"); + self.handle_port_status_change(event_trb.clone()) + } //TODO Handle the other unprompted events + _ => { + trace!("Received a non-status trb"); + self.acknowledge(event_trb.clone()); + } + } + + event_trb.reserved(false); + + self.update_erdp(&*event_ring); + self.hci.event_handler_finished(); + + *event_trb_index = event_ring.ring.next_index(); + + EventProcessResult::RegularEvent + } + /// Handles device attach/detach events as indicated by a PortStatusChange fn handle_port_status_change(&mut self, trb: Trb) { if let Some(root_hub_port_num) = trb.port_status_change_port_id() { diff --git a/ipcd/src/chan.rs b/ipcd/src/chan.rs index ec19751283..d4a195e237 100644 --- a/ipcd/src/chan.rs +++ b/ipcd/src/chan.rs @@ -331,7 +331,7 @@ impl<'sock> SchemeSync for ChanScheme<'sock> { } } fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - FpathWriter::with_legacy(buf, "chan", |w| { + FpathWriter::with(buf, "chan", |w| { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; if let Extra::SchemeRoot = handle.extra { return Ok(()); diff --git a/randd/src/main.rs b/randd/src/main.rs index 44ecd86b77..9d72417d71 100644 --- a/randd/src/main.rs +++ b/randd/src/main.rs @@ -3,11 +3,6 @@ use std::arch::asm; use rand_chacha::ChaCha20Rng; use rand_core::RngCore; -pub const MODE_PERM: u16 = 0x0FFF; -pub const MODE_EXEC: u16 = 0o1; -pub const MODE_WRITE: u16 = 0o2; -pub const MODE_READ: u16 = 0o4; - #[cfg(target_arch = "x86_64")] use raw_cpuid::CpuId; @@ -27,8 +22,6 @@ use sha2::{Digest, Sha256}; // We do not implement blocking reads as per linux /dev/random for the reasons outlined // here: https://www.2uo.de/myths-about-urandom/ -// Default file access mode for PRNG -const DEFAULT_PRNG_MODE: u16 = 0o644; // Rand crate recommends at least 256 bits of entropy to seed the RNG const SEED_BYTES: usize = 32; @@ -89,33 +82,9 @@ fn create_rdrand_seed() -> [u8; SEED_BYTES] { /// Contains information about an open file struct OpenFileInfo { o_flags: usize, - /// Flags used when opening file. - uid: u32, - gid: u32, - file_stat: Stat, } impl OpenFileInfo { - /// Tests if the current user has enough permissions to view the file, op is the operation, - /// like read and write, these modes are MODE_EXEC, MODE_READ, and MODE_WRITE - /// Copied from redoxfs - fn permission(&self, op: u16) -> bool { - let mut perm = self.file_stat.st_mode & 0o7; - if self.uid == self.file_stat.st_uid { - // If self.mode is 101100110, >> 6 would be 000000101 - // 0o7 is octal for 111, or, when expanded to 9 digits is 000000111 - perm |= (self.file_stat.st_mode >> 6) & 0o7; - // Since we erased the GID and OTHER bits when >>6'ing, |= will keep those bits in place. - } - if self.gid == self.file_stat.st_gid || self.file_stat.st_gid == 0 { - perm |= (self.file_stat.st_mode >> 3) & 0o7; - } - if self.uid == 0 { - //set the `other` bits to 111 - perm |= 0o7; - } - perm & op == op - } fn o_flag_set(&self, f: usize) -> bool { return (f & self.o_flags) == f; } @@ -141,7 +110,6 @@ struct RandScheme { // ChaCha20 is a Cryptographically Secure PRNG // https://docs.rs/rand/0.5.0/rand/prng/chacha/struct.ChaChaRng.html // Allows 2^64 streams of random numbers, which we will equate with file numbers - prng_stat: Stat, handles: HandleMap, } @@ -150,12 +118,6 @@ impl RandScheme { fn new() -> RandScheme { RandScheme { prng: ChaCha20Rng::from_seed(create_rdrand_seed()), - prng_stat: Stat { - st_mode: MODE_CHR | DEFAULT_PRNG_MODE, - st_gid: 0, - st_uid: 0, - ..Default::default() - }, handles: HandleMap::new(), } } @@ -169,12 +131,11 @@ impl RandScheme { /// Checks to see if the op (MODE_READ, MODE_WRITE) can be performed on the open file /// descriptor - Will return the open file info if successful, and error if the file /// descriptor is invalid, or the permission is denied. - fn can_perform_op_on_fd(&self, fd: usize, op: u16) -> Result<&OpenFileInfo> { - let file_info = self.get_fd(fd)?; - if !file_info.permission(op) { + fn can_perform_op_on_fd(&self, fd: usize, f: usize) -> Result<()> { + if !self.get_fd(fd)?.o_flag_set(f) { return Err(Error::new(EPERM)); } - Ok(file_info) + Ok(()) } /// Reseed the CSPRNG with the supplied entropy. /// TODO add this to an entropy pool and give a limited estimate to the amount of entropy @@ -201,20 +162,10 @@ impl RandScheme { return Err(Error::new(EEXIST)); } - let open_file_info = OpenFileInfo { - o_flags: flags, - file_stat: self.prng_stat, - uid: ctx.uid, - gid: ctx.gid, - }; + let open_file_info = OpenFileInfo { o_flags: flags }; - if (open_file_info.o_flag_set(O_RDONLY) || open_file_info.o_flag_set(O_RDWR)) - && !open_file_info.permission(MODE_READ) - { - return Err(Error::new(EPERM)); - } if (open_file_info.o_flag_set(O_WRONLY) || open_file_info.o_flag_set(O_RDWR)) - && !open_file_info.permission(MODE_WRITE) + && ctx.uid != 0 { return Err(Error::new(EPERM)); } @@ -227,108 +178,6 @@ impl RandScheme { }) } } -#[test] -fn test_scheme_perms() { - use syscall::{O_CLOEXEC, O_STAT}; - - let mut ctx = CallerCtx { - pid: 0, - uid: 1, - gid: 1, - id: unsafe { std::mem::zeroed() }, // Id doesn't have a public constructor - }; - - let mut scheme = RandScheme::new(); - scheme.prng_stat.st_mode = MODE_CHR | 0o200; - scheme.prng_stat.st_uid = 1; - scheme.prng_stat.st_gid = 1; - assert!(scheme.open_inner("/", O_RDWR, &ctx).is_err()); - assert!(scheme.open_inner("/", O_RDONLY, &ctx).is_err()); - - scheme.prng_stat.st_mode = MODE_CHR | 0o400; - let mut fd = match scheme.open("", O_RDONLY, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err()); - scheme.on_close(fd); - - assert!(scheme.open_inner("", O_WRONLY, &ctx).is_err()); - assert!(scheme.open_inner("", O_RDWR, &ctx).is_err()); - - scheme.prng_stat.st_mode = MODE_CHR | 0o600; - fd = match scheme.open_inner("", O_RDWR, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok()); - scheme.on_close(fd); - - ctx.uid = 2; - ctx.gid = 2; - fd = match scheme.open_inner("", O_STAT, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_err()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err()); - scheme.on_close(fd); - fd = match scheme.open_inner("", O_STAT | O_CLOEXEC, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_err()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err()); - scheme.on_close(fd); - - // Try another user in group (no group perms) - ctx.uid = 2; - ctx.gid = 1; - fd = match scheme.open_inner("", O_STAT | O_CLOEXEC, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_err()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_err()); - scheme.on_close(fd); - scheme.prng_stat.st_mode = MODE_CHR | 0o660; - fd = match scheme.open_inner("", O_STAT | O_CLOEXEC, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok()); - scheme.on_close(fd); - - // Check root can do anything - scheme.prng_stat.st_mode = MODE_CHR | 0o000; - ctx.uid = 0; - ctx.gid = 0; - fd = match scheme.open_inner("", O_STAT | O_CLOEXEC, &ctx).unwrap() { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok()); - scheme.on_close(fd); - - // Check the rand:/urandom URL (Equivalent to rand:/) - scheme.prng_stat.st_mode = MODE_CHR | 0o660; - ctx.uid = 2; - ctx.gid = 1; - fd = match scheme - .open_inner("/urandom", O_STAT | O_CLOEXEC, &ctx) - .unwrap() - { - OpenResult::ThisScheme { number, .. } => number, - _ => panic!(), - }; - assert!(scheme.can_perform_op_on_fd(fd, MODE_READ).is_ok()); - assert!(scheme.can_perform_op_on_fd(fd, MODE_WRITE).is_ok()); - scheme.on_close(fd); -} impl SchemeSync for RandScheme { fn scheme_root(&mut self) -> Result { @@ -360,7 +209,7 @@ impl SchemeSync for RandScheme { _ctx: &CallerCtx, ) -> Result { // Check fd and permissions - self.can_perform_op_on_fd(id, MODE_READ)?; + self.can_perform_op_on_fd(id, O_RDONLY)?; // Setting the stream will ensure that if two clients are reading concurrently, they won't get the same numbers self.prng.set_stream(id as u64); // Should probably find a way to re-instate the counter for this stream, but @@ -379,7 +228,7 @@ impl SchemeSync for RandScheme { _ctx: &CallerCtx, ) -> Result { // Check fd and permissions - self.can_perform_op_on_fd(id, MODE_WRITE)?; + self.can_perform_op_on_fd(id, O_WRONLY)?; // TODO - when we support other entropy sources, just add this to an entropy pool // TODO - consider having trusted and untrusted entropy writing paths @@ -397,31 +246,6 @@ impl SchemeSync for RandScheme { Ok(buf.len()) } - fn fchmod(&mut self, id: usize, mode: u16, ctx: &CallerCtx) -> Result<()> { - // Check fd and permissions - let file_info = self.get_fd(id)?; - // only root and owner can chmod - if ctx.uid != file_info.file_stat.st_uid && ctx.uid != 0 { - return Err(Error::new(EPERM)); - } - - self.prng_stat.st_mode = MODE_CHR | (mode & MODE_PERM); // Apply mask - Ok(()) - } - - fn fchown(&mut self, id: usize, uid: u32, gid: u32, ctx: &CallerCtx) -> Result<()> { - // Check fd and permissions - let file_info = self.get_fd(id)?; - // only root and owner can fchown - if ctx.uid != file_info.file_stat.st_uid && ctx.uid != 0 { - return Err(Error::new(EPERM)); - } - - self.prng_stat.st_uid = uid; - self.prng_stat.st_gid = gid; - Ok(()) - } - fn fcntl(&mut self, _id: usize, cmd: usize, _arg: usize, _ctx: &CallerCtx) -> Result { // /dev/random and /dev/urandom have no file status flags or locks. // F_GETFL/F_GETFD legitimately return 0; set commands are no-ops @@ -441,11 +265,10 @@ impl SchemeSync for RandScheme { FpathWriter::with(buf, "rand", |_| Ok(())) } - fn fstat(&mut self, file: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { - // Check fd and permissions - self.can_perform_op_on_fd(file, MODE_READ)?; - - *stat = self.prng_stat.clone(); + fn fstat(&mut self, _file: usize, stat: &mut Stat, _ctx: &CallerCtx) -> Result<()> { + stat.st_mode = 0o644 | MODE_CHR; + stat.st_uid = 0; + stat.st_gid = 0; Ok(()) } diff --git a/scheme-utils/src/lib.rs b/scheme-utils/src/lib.rs index b262939c6b..08e2380e19 100644 --- a/scheme-utils/src/lib.rs +++ b/scheme-utils/src/lib.rs @@ -92,17 +92,6 @@ impl<'a> FpathWriter<'a> { Ok(w.written) } - pub fn with_legacy( - buf: &'a mut [u8], - scheme_name: &str, - f: impl FnOnce(&mut Self) -> Result<()>, - ) -> Result { - let mut w = FpathWriter { buf, written: 0 }; - write!(w, "{scheme_name}:").unwrap(); - f(&mut w)?; - Ok(w.written) - } - pub fn push_str(&mut self, s: &str) { let count = core::cmp::min(s.len(), self.buf.len() - self.written); self.buf[self.written..self.written + count].copy_from_slice(&s.as_bytes()[..count]);