Skip to content

Commit fae5344

Browse files
Anway-Agtelind
andauthored
Exec syscall (#305)
* initial commit * exec comments and tests added * commits resolved * comments resolved * minor change in test case * minor changes * comments resolution --------- Co-authored-by: lind <lind@nyu.edu>
1 parent f045767 commit fae5344

File tree

3 files changed

+143
-62
lines changed

3 files changed

+143
-62
lines changed

src/safeposix/syscalls/sys_calls.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,16 +409,50 @@ impl Cage {
409409
0
410410
}
411411

412+
/// ### Description
413+
///
414+
/// The exec system call replaces the current Cage object image with a new
415+
/// Cage object and exec is called immediately after a process(Cage) forks.
416+
/// For our purposes this translates to removing the parent cage object
417+
/// from the cagetable and adding the child object to it. We also close
418+
/// any file descriptors that the parent object holds if the `O_CLOEX`
419+
/// flag has been set on that file descriptor
420+
///
421+
/// ### Arguments
422+
///
423+
/// `child_cageid`: uid of the new child Cage object
424+
///
425+
/// ### Returns
426+
///
427+
/// Returns 0 upon successfully update the current running image
428+
///
429+
/// ### Errors
430+
///
431+
/// This syscall doesn't directly have any cases where it returns an error
432+
///
433+
/// ### Panics
434+
///
435+
/// This function doesn't directly panic - but the unmap memory mappings
436+
/// function panics if it cannot create an shm entry or if the unwrapping
437+
/// on the file descriptor fails due to an invalid fd
438+
///
439+
/// For more information please refer to - [https://man7.org/linux/man-pages/man3/exec.3.html]
412440
pub fn exec_syscall(&self, child_cageid: u64) -> i32 {
441+
// We remove the current running process from the cagetable
413442
interface::cagetable_remove(self.cageid);
414-
443+
// Function call to unmap shared memory mappings of the current process
415444
self.unmap_shm_mappings();
416445

446+
// Initialize an empty vector to hold file descriptors
417447
let mut cloexecvec = vec![];
418448
for fd in 0..MAXFD {
449+
// Get mutex of the file descriptor
419450
let checkedfd = self.get_filedescriptor(fd).unwrap();
420451
let unlocked_fd = checkedfd.read();
421452
if let Some(filedesc_enum) = &*unlocked_fd {
453+
// For each valid file descriptor we chech if the O_CLOEXEC flag is set or not
454+
// The O_CLOEXEC flag determines whether the fd should be closed upon calling
455+
// exec or not
422456
if match filedesc_enum {
423457
File(f) => f.flags & O_CLOEXEC,
424458
Stream(s) => s.flags & O_CLOEXEC,
@@ -427,21 +461,30 @@ impl Cage {
427461
Epoll(p) => p.flags & O_CLOEXEC,
428462
} != 0
429463
{
464+
// If the flag is set - we add the fd to our vector
430465
cloexecvec.push(fd);
431466
}
432467
}
433468
}
434469

470+
//For each fd in our close vector list
471+
//We call the close_syscall which takes in a file decsriptor
472+
//and closes it
435473
for fdnum in cloexecvec {
436474
self.close_syscall(fdnum);
437475
}
438476

439-
// we grab the parent cages main threads sigset and store it at 0
440-
// this way the child can initialize the sigset properly when it establishes its
441-
// own mainthreadid
477+
// We clone the parent cage's main threads and store them at index 0
478+
// This is done since there isn't a thread established for the child Cage object
479+
// yet - And there is no threadId to store it at.
480+
// The child Cage object can then initialize and store the sigset appropriately
481+
// when it establishes its own main thread id.
482+
// A sigset is a data structure that keeps track of which signals are affected by the process
442483
let newsigset = interface::RustHashMap::new();
443484
if !interface::RUSTPOSIX_TESTSUITE.load(interface::RustAtomicOrdering::Relaxed) {
444-
// we don't add these for the test suite
485+
// When rustposix runs independently (not as Lind paired with NaCL runtime) we
486+
// do not handle signals The test suite runs rustposix independently
487+
// and hence we do not handle signals for the test suite
445488
let mainsigsetatomic = self
446489
.sigset
447490
.get(
@@ -456,6 +499,9 @@ impl Cage {
456499
newsigset.insert(0, mainsigset);
457500
}
458501

502+
// Initialize a new cage object to replace the current running image
503+
// We set all the ids to -1 to indicate the loading phase
504+
// We clone the fd table with the memories unmapped
459505
let newcage = Cage {
460506
cageid: child_cageid,
461507
cwd: interface::RustLock::new(self.cwd.read().clone()),
@@ -477,8 +523,8 @@ impl Cage {
477523
main_threadid: interface::RustAtomicU64::new(0),
478524
interval_timer: self.interval_timer.clone_with_new_cageid(child_cageid),
479525
};
480-
//wasteful clone of fdtable, but mutability constraints exist
481526

527+
// Insert new cage with updated fd tables to be inserted in the cagetable
482528
interface::cagetable_insert(child_cageid, newcage);
483529
0
484530
}

src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
mod fs_tests;
55
mod ipc_tests;
66
mod networking_tests;
7+
mod sys_tests;
78
use rand::Rng;
89
use std::net::{TcpListener, UdpSocket};
910

src/tests/sys_tests.rs

Lines changed: 90 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,139 @@
1-
#![allow(dead_code)] //suppress warning for these functions not being used in targets other than the tests
1+
#![allow(dead_code)] //suppress warning for these functions not being used in targets other than the
2+
// tests
23

34
#[allow(unused_parens)]
4-
#[cfg(test)]
5-
pub mod test_sys {
5+
#[cfg(test)]
6+
pub mod sys_tests {
67
use super::super::*;
78
use crate::interface;
8-
use crate::safeposix::syscalls::sys_calls::*;
9-
10-
pub fn test_sys() {
11-
ut_lind_getpid();
12-
ut_lind_getppid();
13-
ut_lind_getegid();
14-
ut_lind_getuid();
15-
ut_lind_geteuid();
16-
ut_lind_getgid();
17-
ut_lind_fork();
18-
}
9+
use crate::safeposix::cage::{FileDescriptor::*, *};
10+
use crate::safeposix::{cage::*, dispatcher::*, filesystem};
1911

12+
#[test]
2013
pub fn ut_lind_getpid() {
21-
lindrustinit(0);
22-
let cage = interface::cagetable_getref(1);
23-
assert_eq!(cage.getpid_syscall(),1);
14+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
15+
// and also performs clean env setup
16+
let _thelock = setup::lock_and_init();
17+
let cage = interface::cagetable_getref(1);
18+
assert_eq!(cage.getpid_syscall(), 1);
2419
lindrustfinalize();
25-
}
20+
}
2621

22+
#[test]
2723
pub fn ut_lind_getppid() {
28-
lindrustinit(0);
29-
let cage = interface::cagetable_getref(1);
24+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
25+
// and also performs clean env setup
26+
let _thelock = setup::lock_and_init();
27+
let cage = interface::cagetable_getref(1);
3028
cage.fork_syscall(2);
3129
let cage2 = interface::cagetable_getref(2);
32-
assert_eq!(cage2.getppid_syscall(),1);
33-
lindrustfinalize();
34-
35-
}
30+
assert_eq!(cage2.getppid_syscall(), 1);
31+
lindrustfinalize();
32+
}
3633

34+
#[test]
3735
pub fn ut_lind_getuid() {
38-
lindrustinit(0);
36+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
37+
// and also performs clean env setup
38+
let _thelock = setup::lock_and_init();
39+
let cage = interface::cagetable_getref(1);
3940
// The first call to geteuid always returns -1
40-
assert_eq!(cage.getuid_syscall(),-1);
41+
assert_eq!(cage.getuid_syscall(), -1);
4142
// Subsequent calls return the default value
42-
assert_eq!(cage.getuid_syscall(),DEFAULT_UID);
43+
assert_eq!(cage.getuid_syscall(), DEFAULT_UID as i32);
4344
lindrustfinalize()
4445
}
4546

47+
#[test]
4648
pub fn ut_lind_geteuid() {
47-
lindrustinit(0);
49+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
50+
// and also performs clean env setup
51+
let _thelock = setup::lock_and_init();
4852
let cage = interface::cagetable_getref(1);
4953
// The first call to geteuid always returns -1
50-
assert_eq!(cage.geteuid_syscall(),-1);
54+
assert_eq!(cage.geteuid_syscall(), -1);
5155
// Subsequent calls return the default value
52-
assert_eq!(cage.geteuid_syscall(),DEFAULT_UID);
56+
assert_eq!(cage.geteuid_syscall(), DEFAULT_UID as i32);
5357
lindrustfinalize()
5458
}
5559

60+
#[test]
5661
pub fn ut_lind_getgid() {
57-
lindrustinit(0);
62+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
63+
// and also performs clean env setup
64+
let _thelock = setup::lock_and_init();
5865
let cage = interface::cagetable_getref(1);
5966
// The first call to geteuid always returns -1
60-
assert_eq!(cage.getgid_syscall(),-1);
67+
assert_eq!(cage.getgid_syscall(), -1);
6168
// Subsequent calls return the default value
62-
assert_eq!(cage.getgid_syscall(),DEFAULT_GID);
69+
assert_eq!(cage.getgid_syscall(), DEFAULT_GID as i32);
6370
lindrustfinalize()
64-
}
71+
}
6572

73+
#[test]
6674
pub fn ut_lind_getegid() {
67-
lindrustinit(0);
75+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
76+
// and also performs clean env setup
77+
let _thelock = setup::lock_and_init();
6878
let cage = interface::cagetable_getref(1);
6979
// The first call to geteuid always returns -1
70-
assert_eq!(cage.getegid_syscall(),-1);
80+
assert_eq!(cage.getegid_syscall(), -1);
7181
// Subsequent calls return the default value
72-
assert_eq!(cage.getegid_syscall(),DEFAULT_GID);
82+
assert_eq!(cage.getegid_syscall(), DEFAULT_GID as i32);
7383
lindrustfinalize()
74-
}
84+
}
7585

86+
#[test]
7687
pub fn ut_lind_fork() {
7788
// Since the fork syscall is heavily tested in relation to other syscalls
7889
// we only perform simple checks for testing the sanity of the fork syscall
79-
lindrustinit(0);
80-
let cage = interface::cagetable_getref(1);
81-
// Spawn a new child object using the fork syscall
82-
cage.fork_syscall(2);
90+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
91+
// and also performs clean env setup
92+
let _thelock = setup::lock_and_init();
93+
let cage = interface::cagetable_getref(1);
94+
// Spawn a new child object using the fork syscall
95+
cage.fork_syscall(2);
8396
// Search for the new cage object with cage_id = 2
84-
let child_cage = interface::cagetable_getref(2);
97+
let child_cage = interface::cagetable_getref(2);
8598
// Assert the parent value is the the id of the first cage object
86-
assert_eq!(child_cage.getpid_syscall(),1);
87-
// Assert that the cage id of the child is the value passed in the original fork syscall
88-
assert_eq!(child_cage.getuid(),2);
89-
// Assert that the cwd is the same as the parent cage object
90-
assert_eq!(child_cage.cwd.read(),cage.cwd.read())
99+
assert_eq!(child_cage.getppid_syscall(), 1);
100+
// Assert that the cage id of the child is the value passed in the original fork
101+
// syscall
102+
assert_eq!(child_cage.getuid_syscall(), -1);
103+
assert_eq!(child_cage.getuid_syscall(), DEFAULT_UID as i32);
104+
lindrustfinalize();
91105
}
92106

107+
#[test]
93108
pub fn ut_lind_exit() {
94-
// Since exit function is heavily used and tested in other syscalls and their tests
95-
// We only perform preliminary checks for checking the sanity of this syscall
96-
// We don't check for cases such as exiting a cage twice - since the exiting process
97-
// is handled by the NaCl runtime - and it ensures that a cage does not exit twice
98-
lindrustinit(0);
109+
// Since exit function is heavily used and tested in other syscalls and their
110+
// tests We only perform preliminary checks for checking the sanity of
111+
// this syscall We don't check for cases such as exiting a cage twice -
112+
// since the exiting process is handled by the NaCl runtime - and it
113+
// ensures that a cage does not exit twice acquiring a lock on TESTMUTEX
114+
// prevents other tests from running concurrently, and also performs
115+
// clean env setup
116+
let _thelock = setup::lock_and_init();
99117
let cage = interface::cagetable_getref(1);
100118
// Call the exit call
101-
assert_eq(cage.exit_syscall(EXIT_SUCCESS),EXIT_SUCCESS);
102-
lindrustfinalize();
119+
assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS);
120+
lindrustfinalize();
103121
}
104-
}
105122

123+
#[test]
124+
pub fn ut_lind_exec() {
125+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
126+
// and also performs clean env setup
127+
let _thelock = setup::lock_and_init();
128+
let cage1 = interface::cagetable_getref(1);
129+
// Spawn a new child
130+
cage1.fork_syscall(2);
131+
// Assert that the fork was correct
132+
let child_cage = interface::cagetable_getref(2);
133+
assert_eq!(child_cage.getuid_syscall(), -1);
134+
assert_eq!(child_cage.getuid_syscall(), DEFAULT_UID as i32);
135+
// Spawn exec and check if it returns 0
136+
assert_eq!(cage1.exec_syscall(2), 0);
137+
lindrustfinalize();
138+
}
139+
}

0 commit comments

Comments
 (0)