From b32a421b9755ece749a571eba5a297fc39e2d40b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 30 Dec 2018 09:58:58 -0700 Subject: [PATCH] Correct access control --- src/mount/redox/resource.rs | 111 +++++++++++++++++++----------------- src/mount/redox/scheme.rs | 4 +- 2 files changed, 60 insertions(+), 55 deletions(-) diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs index 9d7c75af62..f7d9ddc373 100644 --- a/src/mount/redox/resource.rs +++ b/src/mount/redox/resource.rs @@ -1,10 +1,9 @@ use std::cmp::{min, max}; use std::time::{SystemTime, UNIX_EPOCH}; -use syscall::data::TimeSpec; +use syscall::data::{Map, Stat, TimeSpec}; use syscall::error::{Error, Result, EBADF, EBUSY, EINVAL, EISDIR, EPERM}; -use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM}; -use syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END}; +use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM, PROT_READ, PROT_WRITE, SEEK_SET, SEEK_CUR, SEEK_END}; use disk::Disk; use filesystem::FileSystem; @@ -16,7 +15,7 @@ pub trait Resource { fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem) -> Result; fn write(&mut self, buf: &[u8], fs: &mut FileSystem) -> Result; fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem) -> Result; - fn fmap(&mut self, offset: usize, size: usize, maps: &mut Fmaps, fs: &mut FileSystem) -> Result; + fn fmap(&mut self, map: &Map, maps: &mut Fmaps, fs: &mut FileSystem) -> Result; fn funmap(&mut self, maps: &mut Fmaps, fs: &mut FileSystem) -> Result; fn fchmod(&mut self, mode: u16, fs: &mut FileSystem) -> Result; fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem) -> Result; @@ -90,7 +89,7 @@ impl Resource for DirResource { Ok(self.seek) } - fn fmap(&mut self, _offset: usize, _size: usize, _maps: &mut Fmaps, _fs: &mut FileSystem) -> Result { + fn fmap(&mut self, _map: &Map, _maps: &mut Fmaps, _fs: &mut FileSystem) -> Result { Err(Error::new(EBADF)) } fn funmap(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem) -> Result { @@ -278,56 +277,62 @@ impl Resource for FileResource { Ok(self.seek as usize) } - fn fmap(&mut self, offset: usize, size: usize, maps: &mut Fmaps, fs: &mut FileSystem) -> Result { - if self.flags & O_ACCMODE == O_RDWR { - let key_exact = FmapKey { - block: self.block, - offset, - size - }; - - let i = match maps.find_compatible(&key_exact) { - Ok((i, (key_existing, value))) => { - value.refcount += 1; - self.fmap = Some((i, key_exact)); - return Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_existing.offset)) - }, - Err(None) => { - // This is bad! - // We reached the limit of maps, and we can't reallocate - // because that would invalidate stuff. - // Sorry, nothing personal :( - return Err(Error::new(EBUSY)) - }, - Err(Some(i)) => { - // Can't do stuff in here because lifetime issues - i - } - }; - let key_round = key_exact.round(); - - let mut content = vec![0; key_round.size]; - let mut count = 0; - while count < key_round.size { - match fs.read_node(self.block, key_round.offset as u64 + count as u64, - &mut content[key_round.offset..][count..key_round.size])? { - 0 => break, - n => count += n - } - } - - let value = maps.insert(i, key_round, FmapValue { - buffer: content, - actual_size: count, - refcount: 1 - }); - - self.fmap = Some((i, key_exact)); - Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_round.offset)) - } else { - Err(Error::new(EBADF)) + fn fmap(&mut self, map: &Map, maps: &mut Fmaps, fs: &mut FileSystem) -> Result { + let accmode = self.flags & O_ACCMODE; + if map.flags & PROT_READ > 0 && ! (accmode == O_RDWR || accmode == O_RDONLY) { + return Err(Error::new(EBADF)); } + if map.flags & PROT_WRITE > 0 && ! (accmode == O_RDWR || accmode == O_WRONLY) { + return Err(Error::new(EBADF)); + } + //TODO: PROT_EXEC? + + let key_exact = FmapKey { + block: self.block, + offset: map.offset, + size: map.size + }; + + let i = match maps.find_compatible(&key_exact) { + Ok((i, (key_existing, value))) => { + value.refcount += 1; + self.fmap = Some((i, key_exact)); + return Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_existing.offset)) + }, + Err(None) => { + // This is bad! + // We reached the limit of maps, and we can't reallocate + // because that would invalidate stuff. + // Sorry, nothing personal :( + return Err(Error::new(EBUSY)) + }, + Err(Some(i)) => { + // Can't do stuff in here because lifetime issues + i + } + }; + let key_round = key_exact.round(); + + let mut content = vec![0; key_round.size]; + let mut count = 0; + while count < key_round.size { + match fs.read_node(self.block, key_round.offset as u64 + count as u64, + &mut content[key_round.offset..][count..key_round.size])? { + 0 => break, + n => count += n + } + } + + let value = maps.insert(i, key_round, FmapValue { + buffer: content, + actual_size: count, + refcount: 1 + }); + + self.fmap = Some((i, key_exact)); + Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_round.offset)) } + fn funmap(&mut self, maps: &mut Fmaps, fs: &mut FileSystem) -> Result { self.sync_fmap(maps, fs)?; if let Some((i, _)) = self.fmap.as_ref() { diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs index ad7e8b1ba0..198085745a 100644 --- a/src/mount/redox/scheme.rs +++ b/src/mount/redox/scheme.rs @@ -750,10 +750,10 @@ impl Scheme for FileScheme { } fn fmap(&self, id: usize, map: &Map) -> Result { - // println!("Fmap {}, {}, {}", id, offset, size); + // println!("Fmap {}, {:?}", id, map); let mut files = self.files.lock(); if let Some(file) = files.get_mut(&id) { - file.fmap(map.offset, map.size, &mut self.fmaps.lock(), &mut self.fs.borrow_mut()) + file.fmap(map, &mut self.fmaps.lock(), &mut self.fs.borrow_mut()) } else { Err(Error::new(EBADF)) }