Skip to content

Commit c7aa36d

Browse files
committed
Fix rights checks across the codebase.
* Fix path_open granting more rights than requested * Add missing rights checks in: fd_fdstat_set_flags, fd_filestat_get, poll_oneoff * Fix `open_scratch_directory` not requesting any rights. * Properly request needed rights in various tests * Add some extra trace-level logging
1 parent 3b3a5a0 commit c7aa36d

File tree

12 files changed

+60
-34
lines changed

12 files changed

+60
-34
lines changed

crates/test-programs/wasi-tests/src/bin/fd_advise.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ unsafe fn test_fd_advise(dir_fd: wasi::Fd) {
99
0,
1010
"file",
1111
wasi::OFLAGS_CREAT,
12-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
12+
wasi::RIGHTS_FD_READ
13+
| wasi::RIGHTS_FD_WRITE
14+
| wasi::RIGHTS_FD_ADVISE
15+
| wasi::RIGHTS_FD_FILESTAT_GET
16+
| wasi::RIGHTS_FD_ALLOCATE,
1317
0,
1418
0,
1519
)

crates/test-programs/wasi-tests/src/bin/fd_filestat_set.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ unsafe fn test_fd_filestat_set(dir_fd: wasi::Fd) {
99
0,
1010
"file",
1111
wasi::OFLAGS_CREAT,
12-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
12+
wasi::RIGHTS_FD_READ
13+
| wasi::RIGHTS_FD_WRITE
14+
| wasi::RIGHTS_FD_FILESTAT_GET
15+
| wasi::RIGHTS_FD_FILESTAT_SET_SIZE
16+
| wasi::RIGHTS_FD_FILESTAT_SET_TIMES,
1317
0,
1418
0,
1519
)

crates/test-programs/wasi-tests/src/bin/fd_readdir.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ unsafe fn test_fd_readdir(dir_fd: wasi::Fd) {
9090
0,
9191
"file",
9292
wasi::OFLAGS_CREAT,
93-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
93+
wasi::RIGHTS_FD_READ
94+
| wasi::RIGHTS_FD_WRITE
95+
| wasi::RIGHTS_FD_READDIR
96+
| wasi::RIGHTS_FD_FILESTAT_GET,
9497
0,
9598
0,
9699
)

crates/test-programs/wasi-tests/src/bin/file_allocate.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ unsafe fn test_file_allocate(dir_fd: wasi::Fd) {
99
0,
1010
"file",
1111
wasi::OFLAGS_CREAT,
12-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
12+
wasi::RIGHTS_FD_READ
13+
| wasi::RIGHTS_FD_WRITE
14+
| wasi::RIGHTS_FD_ALLOCATE
15+
| wasi::RIGHTS_FD_FILESTAT_GET,
1316
0,
1417
0,
1518
)

crates/test-programs/wasi-tests/src/bin/file_seek_tell.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ unsafe fn test_file_seek_tell(dir_fd: wasi::Fd) {
99
0,
1010
"file",
1111
wasi::OFLAGS_CREAT,
12-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
12+
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_TELL,
1313
0,
1414
0,
1515
)

crates/test-programs/wasi-tests/src/bin/path_link.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@ use more_asserts::assert_gt;
22
use std::{env, process};
33
use wasi_tests::{create_file, open_scratch_directory};
44

5+
const TEST_RIGHTS: wasi::Rights = wasi::RIGHTS_FD_READ
6+
| wasi::RIGHTS_PATH_LINK_SOURCE
7+
| wasi::RIGHTS_PATH_LINK_TARGET
8+
| wasi::RIGHTS_FD_FILESTAT_GET
9+
| wasi::RIGHTS_PATH_OPEN
10+
| wasi::RIGHTS_PATH_UNLINK_FILE;
11+
512
unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> wasi::Fd {
6-
let file_fd = wasi::path_open(dir_fd, 0, name, flags, 0, 0, 0)
13+
let file_fd = wasi::path_open(dir_fd, 0, name, flags, TEST_RIGHTS, TEST_RIGHTS, 0)
714
.unwrap_or_else(|_| panic!("opening '{}'", name));
815
assert_gt!(
916
file_fd,
@@ -14,7 +21,7 @@ unsafe fn create_or_open(dir_fd: wasi::Fd, name: &str, flags: wasi::Oflags) -> w
1421
}
1522

1623
unsafe fn open_link(dir_fd: wasi::Fd, name: &str) -> wasi::Fd {
17-
let file_fd = wasi::path_open(dir_fd, 0, name, 0, 0, 0, 0)
24+
let file_fd = wasi::path_open(dir_fd, 0, name, 0, TEST_RIGHTS, TEST_RIGHTS, 0)
1825
.unwrap_or_else(|_| panic!("opening a link '{}'", name));
1926
assert_gt!(
2027
file_fd,

crates/test-programs/wasi-tests/src/bin/path_open_read_without_rights.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,9 @@
11
use std::{env, process};
22
use wasi_tests::open_scratch_directory;
3-
use wasi_tests::{drop_rights, fd_get_rights};
3+
use wasi_tests::{drop_rights, fd_get_rights, create_file};
44

55
const TEST_FILENAME: &'static str = "file";
66

7-
unsafe fn create_testfile(dir_fd: wasi::Fd) {
8-
let fd = wasi::path_open(
9-
dir_fd,
10-
0,
11-
TEST_FILENAME,
12-
wasi::OFLAGS_CREAT | wasi::OFLAGS_EXCL,
13-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
14-
0,
15-
0,
16-
)
17-
.expect("creating a file");
18-
wasi::fd_close(fd).expect("closing a file");
19-
}
20-
217
unsafe fn try_read_file(dir_fd: wasi::Fd) {
228
let fd = wasi::path_open(dir_fd, 0, TEST_FILENAME, 0, 0, 0, 0).expect("opening the file");
239

@@ -45,7 +31,7 @@ unsafe fn try_read_file(dir_fd: wasi::Fd) {
4531
}
4632

4733
unsafe fn test_read_rights(dir_fd: wasi::Fd) {
48-
create_testfile(dir_fd);
34+
create_file(dir_fd, TEST_FILENAME);
4935
drop_rights(dir_fd, wasi::RIGHTS_FD_READ, wasi::RIGHTS_FD_READ);
5036

5137
let (rbase, rinher) = fd_get_rights(dir_fd);

crates/test-programs/wasi-tests/src/bin/poll_oneoff.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ unsafe fn test_fd_readwrite_valid_fd(dir_fd: wasi::Fd) {
197197
0,
198198
"file",
199199
wasi::OFLAGS_CREAT,
200-
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
200+
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_POLL_FD_READWRITE,
201201
0,
202202
0,
203203
)

crates/test-programs/wasi-tests/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ pub fn open_scratch_directory(path: &str) -> Result<wasi::Fd, String> {
2424
}
2525
dst.set_len(stat.u.dir.pr_name_len);
2626
if dst == path.as_bytes() {
27-
return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, 0, 0, 0)
27+
let (base, inherit) = fd_get_rights(i);
28+
return Ok(wasi::path_open(i, 0, ".", wasi::OFLAGS_DIRECTORY, base, inherit, 0)
2829
.expect("failed to open dir"));
2930
}
3031
}

crates/wasi-common/src/fdentry.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ impl FdEntry {
157157
) -> Result<()> {
158158
if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0
159159
{
160+
log::trace!(
161+
" | validate_rights failed: required: rights_base = {}, rights_inheriting = {}; actual: rights_base = {}, rights_inheriting = {}",
162+
rights_base, rights_inheriting, self.rights_base, self.rights_inheriting
163+
);
160164
Err(Error::ENOTCAPABLE)
161165
} else {
162166
Ok(())

crates/wasi-common/src/hostcalls_impl/fs.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::fdentry::{Descriptor, FdEntry};
55
use crate::helpers::*;
66
use crate::memory::*;
77
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
8-
use crate::sys::fdentry_impl::determine_type_rights;
98
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
109
use crate::sys::{host_impl, hostcalls_impl};
1110
use crate::{helpers, host, wasi, wasi32, Error, Result};
@@ -308,7 +307,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
308307

309308
let fd = wasi_ctx
310309
.get_fd_entry(fd)?
311-
.as_descriptor(0, 0)?
310+
.as_descriptor(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?
312311
.as_os_handle();
313312

314313
hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags)
@@ -574,6 +573,11 @@ pub(crate) unsafe fn path_open(
574573

575574
let (needed_base, needed_inheriting) =
576575
path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags);
576+
trace!(
577+
" | needed_base = {}, needed_inheriting = {}",
578+
needed_base,
579+
needed_inheriting
580+
);
577581
let fe = wasi_ctx.get_fd_entry(dirfd)?;
578582
let resolved = path_get(
579583
fe,
@@ -593,13 +597,20 @@ pub(crate) unsafe fn path_open(
593597
| wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE)
594598
!= 0;
595599

600+
trace!(
601+
" | calling path_open impl: read={}, write={}",
602+
read,
603+
write
604+
);
596605
let fd = hostcalls_impl::path_open(resolved, read, write, oflags, fs_flags)?;
597606

598-
// Determine the type of the new file descriptor and which rights contradict with this type
599-
let (_ty, max_base, max_inheriting) = determine_type_rights(&fd)?;
600607
let mut fe = FdEntry::from(fd)?;
601-
fe.rights_base &= max_base;
602-
fe.rights_inheriting &= max_inheriting;
608+
// We need to manually deny the rights which are not explicitly requested.
609+
// This should not be needed, but currently determine_type_and_access_rights,
610+
// which is used by FdEntry::from, may grant extra rights while inferring it
611+
// from the open mode.
612+
fe.rights_base &= fs_rights_base;
613+
fe.rights_inheriting &= fs_rights_inheriting;
603614
let guest_fd = wasi_ctx.insert_fd_entry(fe)?;
604615

605616
trace!(" | *fd={:?}", guest_fd);
@@ -709,7 +720,10 @@ pub(crate) unsafe fn fd_filestat_get(
709720
filestat_ptr
710721
);
711722

712-
let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
723+
let fd = wasi_ctx
724+
.get_fd_entry(fd)?
725+
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)?
726+
.as_file()?;
713727

714728
let host_filestat = hostcalls_impl::fd_filestat_get_impl(fd)?;
715729

crates/wasi-common/src/hostcalls_impl/misc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,9 @@ pub(crate) fn poll_oneoff(
242242
{
243243
let wasi_fd = unsafe { subscription.u.fd_readwrite.file_descriptor };
244244
let rights = if r#type == wasi::__WASI_EVENTTYPE_FD_READ {
245-
wasi::__WASI_RIGHTS_FD_READ
245+
wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_POLL_FD_READWRITE
246246
} else {
247-
wasi::__WASI_RIGHTS_FD_WRITE
247+
wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_POLL_FD_READWRITE
248248
};
249249

250250
match unsafe {

0 commit comments

Comments
 (0)