Skip to content

Commit 0eb7b02

Browse files
committed
Updated syscall handlers to use rust descriptor lookup
The C close() syscall handler is also now redundant, so it was removed.
1 parent 2e176e4 commit 0eb7b02

7 files changed

Lines changed: 75 additions & 118 deletions

File tree

src/main/bindings/rust/wrapper.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,12 +1743,6 @@ extern "C" {
17431743
args: *const SysCallArgs,
17441744
) -> SysCallReturn;
17451745
}
1746-
extern "C" {
1747-
pub fn syscallhandler_close(
1748-
sys: *mut SysCallHandler,
1749-
args: *const SysCallArgs,
1750-
) -> SysCallReturn;
1751-
}
17521746
extern "C" {
17531747
pub fn syscallhandler_dup(sys: *mut SysCallHandler, args: *const SysCallArgs) -> SysCallReturn;
17541748
}

src/main/host/descriptor/descriptor.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ void descriptor_unrefWeak(gpointer data) {
144144
void descriptor_close(LegacyDescriptor* descriptor, Host* host) {
145145
MAGIC_ASSERT(descriptor);
146146
MAGIC_ASSERT(descriptor->funcTable);
147+
148+
// if it's already closed, exit early
149+
if ((descriptor_getStatus(descriptor) & STATUS_DESCRIPTOR_CLOSED) != 0) {
150+
warning("Attempting to close an already-closed descriptor");
151+
return;
152+
}
153+
147154
trace("Descriptor %i calling vtable close now", descriptor->handle);
148155
descriptor_adjustStatus(descriptor, STATUS_DESCRIPTOR_CLOSED, TRUE);
149156

src/main/host/syscall/fcntl.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ fn fcntl(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
1313
let cmd: i32 = args.args[1].into();
1414

1515
// get the descriptor, or return early if it doesn't exist
16-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
17-
18-
// if it's a legacy descriptor, use the C syscall handler instead
19-
let desc = match desc {
16+
let desc = match syscall::get_descriptor(ctx.process, fd)? {
2017
CompatDescriptor::New(d) => d,
18+
// if it's a legacy descriptor, use the C syscall handler instead
2119
CompatDescriptor::Legacy(_) => {
2220
return unsafe {
2321
cshadow::syscallhandler_fcntl(

src/main/host/syscall/mod.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use crate::cshadow as c;
22
use crate::host::descriptor::{CompatDescriptor, FileStatus, PosixFile};
3+
use crate::host::process::Process;
4+
5+
use std::convert::TryInto;
36

47
pub mod fcntl;
58
pub mod unistd;
@@ -50,21 +53,16 @@ impl c::SysCallReturn {
5053
}
5154
}
5255

53-
/// Returns a pointer to the `CompatDescriptor` for the fd. The pointer will never be NULL.
56+
/// Returns the `CompatDescriptor` for the fd if it exists, otherwise returns EBADF.
5457
pub fn get_descriptor(
55-
fd: libc::c_int,
56-
process: *mut c::Process,
57-
) -> Result<*const CompatDescriptor, nix::errno::Errno> {
58+
process: &Process,
59+
fd: impl TryInto<u32>,
60+
) -> Result<&CompatDescriptor, nix::errno::Errno> {
5861
// check that fd is within bounds
59-
if fd < 0 {
60-
return Err(nix::errno::Errno::EBADF);
61-
}
62+
let fd: u32 = fd.try_into().map_err(|_| nix::errno::Errno::EBADF)?;
6263

63-
// check that the fd exists
64-
let desc = unsafe { c::process_getRegisteredCompatDescriptor(process, fd) };
65-
if desc.is_null() {
66-
return Err(nix::errno::Errno::EBADF);
64+
match process.get_descriptor(fd) {
65+
Some(desc) => Ok(desc),
66+
None => Err(nix::errno::Errno::EBADF),
6767
}
68-
69-
Ok(desc)
7068
}

src/main/host/syscall/unistd.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -227,32 +227,6 @@ static SysCallReturn _syscallhandler_writeHelper(SysCallHandler* sys, int fd,
227227
// System Calls
228228
///////////////////////////////////////////////////////////
229229

230-
SysCallReturn syscallhandler_close(SysCallHandler* sys,
231-
const SysCallArgs* args) {
232-
gint fd = args->args[0].as_i64;
233-
gint errorCode = 0;
234-
235-
trace("Trying to close fd %i", fd);
236-
237-
/* Check that fd is within bounds. */
238-
if (fd < 0) {
239-
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = -EBADF};
240-
}
241-
242-
/* Check if this is a virtual Shadow descriptor. */
243-
LegacyDescriptor* descriptor = process_getRegisteredLegacyDescriptor(sys->process, fd);
244-
errorCode = _syscallhandler_validateDescriptor(descriptor, DT_NONE);
245-
246-
if (descriptor && !errorCode) {
247-
trace("Closing descriptor %i", descriptor_getHandle(descriptor));
248-
descriptor_close(descriptor, sys->host);
249-
process_deregisterLegacyDescriptor(sys->process, descriptor);
250-
return (SysCallReturn){.state = SYSCALL_DONE};
251-
}
252-
253-
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = errorCode};
254-
}
255-
256230
SysCallReturn syscallhandler_dup(SysCallHandler* sys,
257231
const SysCallArgs* args) {
258232
gint fd = args->args[0].as_i64;

src/main/host/syscall/unistd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#include "main/host/syscall/protected.h"
1010

11-
SYSCALL_HANDLER(close);
1211
SYSCALL_HANDLER(dup);
1312
SYSCALL_HANDLER(exit_group);
1413
SYSCALL_HANDLER(getpid);

src/main/host/syscall/unistd.rs

Lines changed: 55 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::host::syscall_types::{PluginPtr, SysCallArgs, TypedPluginPtr};
1010
use crate::host::syscall_types::{SyscallError, SyscallResult};
1111
use crate::utility::event_queue::EventQueue;
1212

13+
use std::convert::{TryFrom, TryInto};
1314
use std::sync::Arc;
1415

1516
use atomic_refcell::AtomicRefCell;
@@ -21,72 +22,56 @@ pub fn close(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
2122

2223
trace!("Trying to close fd {}", fd);
2324

24-
// scope used to make sure that desc cannot be used after deregistering it
25-
{
26-
// get the descriptor, or return early if it doesn't exist
27-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
28-
29-
// if it's a legacy descriptor, use the C syscall handler instead
30-
if let CompatDescriptor::Legacy(_) = desc {
31-
return unsafe {
32-
c::syscallhandler_close(ctx.thread.csyscallhandler(), args as *const c::SysCallArgs)
33-
}
34-
.into();
35-
}
36-
}
25+
let fd: u32 = fd.try_into().map_err(|_| nix::errno::Errno::EBADF)?;
3726

3827
// according to "man 2 close", in Linux any errors that may occur will happen after the fd is
39-
// released, so we should always deregister the descriptor
40-
let desc = unsafe { c::process_deregisterCompatDescriptor(ctx.process.raw_mut(), fd) };
41-
let desc = CompatDescriptor::from_raw(desc).unwrap();
42-
let desc = match *desc {
43-
CompatDescriptor::New(d) => d,
44-
_ => unreachable!(),
45-
};
46-
47-
let result = EventQueue::queue_and_run(|event_queue| desc.close(event_queue));
28+
// released, so we should always deregister the descriptor even if there's an error while
29+
// closing
30+
let desc = ctx
31+
.process
32+
.deregister_descriptor(fd)
33+
.ok_or(nix::errno::Errno::EBADF)?;
4834

49-
if let Some(result) = result {
50-
result.into()
51-
} else {
52-
Ok(0.into())
53-
}
35+
// if there are still valid descriptors to the posix file, close() will do nothing
36+
// and return None
37+
EventQueue::queue_and_run(|event_queue| desc.close(ctx.host.chost(), event_queue))
38+
.unwrap_or(Ok(0.into()))
5439
}
5540

5641
pub fn dup(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
5742
let fd = libc::c_int::from(args.get(0));
5843

5944
// get the descriptor, or return early if it doesn't exist
60-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
61-
62-
match desc {
63-
CompatDescriptor::New(desc) => dup_helper(ctx, fd, desc),
45+
let desc = match syscall::get_descriptor(ctx.process, fd)? {
46+
CompatDescriptor::New(desc) => desc,
6447
// if it's a legacy descriptor, use the C syscall handler instead
6548
CompatDescriptor::Legacy(_) => unsafe {
66-
c::syscallhandler_dup(ctx.thread.csyscallhandler(), args as *const c::SysCallArgs)
67-
.into()
49+
return c::syscallhandler_dup(
50+
ctx.thread.csyscallhandler(),
51+
args as *const c::SysCallArgs,
52+
)
53+
.into();
6854
},
69-
}
70-
}
55+
};
7156

72-
pub fn dup_helper(ctx: &mut ThreadContext, fd: libc::c_int, desc: &Descriptor) -> SyscallResult {
73-
trace!("Duping fd {} ({:?})", fd, desc);
57+
// duplicate the descriptor
58+
let new_desc = CompatDescriptor::New(dup_helper(desc, None));
59+
let new_fd = ctx.process.register_descriptor(new_desc);
7460

61+
// return the new fd
62+
Ok(libc::c_int::try_from(new_fd).unwrap().into())
63+
}
64+
65+
pub fn dup_helper(desc: &Descriptor, flags: Option<DescriptorFlags>) -> Descriptor {
7566
// clone the descriptor (but not the flags)
7667
let mut new_desc = desc.clone();
7768
new_desc.set_flags(DescriptorFlags::empty());
7869

79-
// register the descriptor
80-
let new_desc = CompatDescriptor::New(new_desc);
81-
let new_fd = unsafe {
82-
c::process_registerCompatDescriptor(
83-
ctx.process.raw_mut(),
84-
CompatDescriptor::into_raw(Box::new(new_desc)),
85-
)
86-
};
70+
if let Some(flags) = flags {
71+
new_desc.set_flags(flags);
72+
}
8773

88-
// return the new fd
89-
Ok(new_fd.into())
74+
new_desc
9075
}
9176

9277
pub fn read(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
@@ -96,10 +81,11 @@ pub fn read(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
9681
let offset = 0;
9782

9883
// get the descriptor, or return early if it doesn't exist
99-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
100-
101-
match desc {
102-
CompatDescriptor::New(desc) => read_helper(ctx, fd, desc, buf_ptr, buf_size, offset),
84+
match syscall::get_descriptor(ctx.process, fd)? {
85+
CompatDescriptor::New(desc) => {
86+
let file = desc.get_file().clone();
87+
read_helper(ctx, fd, &file, buf_ptr, buf_size, offset)
88+
}
10389
// if it's a legacy descriptor, use the C syscall handler instead
10490
CompatDescriptor::Legacy(_) => unsafe {
10591
c::syscallhandler_read(ctx.thread.csyscallhandler(), args as *const SysCallArgs).into()
@@ -114,10 +100,11 @@ pub fn pread64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
114100
let offset = libc::off_t::from(args.get(3));
115101

116102
// get the descriptor, or return early if it doesn't exist
117-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
118-
119-
match desc {
120-
CompatDescriptor::New(desc) => read_helper(ctx, fd, desc, buf_ptr, buf_size, offset),
103+
match syscall::get_descriptor(ctx.process, fd)? {
104+
CompatDescriptor::New(desc) => {
105+
let file = desc.get_file().clone();
106+
read_helper(ctx, fd, &file, buf_ptr, buf_size, offset)
107+
}
121108
// if it's a legacy descriptor, use the C syscall handler instead
122109
CompatDescriptor::Legacy(_) => unsafe {
123110
c::syscallhandler_pread64(ctx.thread.csyscallhandler(), args as *const c::SysCallArgs)
@@ -129,12 +116,11 @@ pub fn pread64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
129116
fn read_helper(
130117
ctx: &mut ThreadContext,
131118
_fd: libc::c_int,
132-
desc: &Descriptor,
119+
posix_file: &PosixFile,
133120
buf_ptr: PluginPtr,
134121
buf_size: libc::size_t,
135122
offset: libc::off_t,
136123
) -> SyscallResult {
137-
let posix_file = desc.get_file();
138124
let file_flags = posix_file.borrow().get_flags();
139125

140126
let result =
@@ -164,10 +150,11 @@ pub fn write(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
164150
let offset = 0;
165151

166152
// get the descriptor, or return early if it doesn't exist
167-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
168-
169-
match desc {
170-
CompatDescriptor::New(desc) => write_helper(ctx, fd, desc, buf_ptr, buf_size, offset),
153+
match syscall::get_descriptor(ctx.process, fd)? {
154+
CompatDescriptor::New(desc) => {
155+
let file = desc.get_file().clone();
156+
write_helper(ctx, fd, &file, buf_ptr, buf_size, offset)
157+
}
171158
// if it's a legacy descriptor, use the C syscall handler instead
172159
CompatDescriptor::Legacy(_) => unsafe {
173160
c::syscallhandler_write(ctx.thread.csyscallhandler(), args as *const c::SysCallArgs)
@@ -183,10 +170,11 @@ pub fn pwrite64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
183170
let offset = libc::off_t::from(args.get(3));
184171

185172
// get the descriptor, or return early if it doesn't exist
186-
let desc = unsafe { &*syscall::get_descriptor(fd, ctx.process.raw_mut())? };
187-
188-
match desc {
189-
CompatDescriptor::New(desc) => write_helper(ctx, fd, desc, buf_ptr, buf_size, offset),
173+
match syscall::get_descriptor(ctx.process, fd)? {
174+
CompatDescriptor::New(desc) => {
175+
let file = desc.get_file().clone();
176+
write_helper(ctx, fd, &file, buf_ptr, buf_size, offset)
177+
}
190178
// if it's a legacy descriptor, use the C syscall handler instead
191179
CompatDescriptor::Legacy(_) => unsafe {
192180
c::syscallhandler_pwrite64(ctx.thread.csyscallhandler(), args as *const SysCallArgs)
@@ -198,15 +186,14 @@ pub fn pwrite64(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
198186
fn write_helper(
199187
ctx: &mut ThreadContext,
200188
_fd: libc::c_int,
201-
desc: &Descriptor,
189+
posix_file: &PosixFile,
202190
buf_ptr: PluginPtr,
203191
buf_size: libc::size_t,
204192
offset: libc::off_t,
205193
) -> SyscallResult {
206-
let posix_file = desc.get_file();
207194
let file_flags = posix_file.borrow().get_flags();
208195

209-
let result=
196+
let result =
210197
// call the file's write(), and run any resulting events
211198
EventQueue::queue_and_run(|event_queue| {
212199
posix_file.borrow_mut().write(

0 commit comments

Comments
 (0)