Skip to content

Commit

Permalink
Anway shmget syscall (#310)
Browse files Browse the repository at this point in the history
* first commit

* conflicts resolved

* changes

* final commit

* errors

* changes

* changes

* tests added

* test added

* conflicts resolved

* comments addressed

* tests added

* fixed newline

---------

Co-authored-by: lind <lind@nyu.edu>
Co-authored-by: Nicholas Renner <nicholassrenner@gmail.com>
  • Loading branch information
3 people authored Jul 22, 2024
1 parent fae5344 commit 0276e79
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 7 deletions.
62 changes: 55 additions & 7 deletions src/safeposix/syscalls/fs_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4979,27 +4979,69 @@ impl Cage {
None
}

//------------------SHMGET SYSCALL------------------

pub fn shmget_syscall(&self, key: i32, size: usize, shmflg: i32) -> i32 {
/// ### Description
///
/// `shmget_syscall` returns the shared memory segment identifier associated with a particular `key`
/// If a key doesn't exist, shmget creates a new memory segment and attaches it to the key.
/// Traditionally if the value of the key equals `IPC_PRIVATE`, we also create a new memory segment which
/// is not associated with a key during this syscall,
/// but for our implementaion, we return an error and only create a new memory
/// segment when the IPC_CREAT flag is specified in the`shmflag` argument.
///
/// ### Returns
///
/// An 32 bit integer which represens the identifier of the memory segment associated with the key
///
/// ### Arguments
///
/// `key` : An i32 value that references a memory segment
/// `size` : Size of the memory segment to be created if key doesn't exist
/// `shmflag` : mode flags which indicate whether to create a new key or not
/// The `shmflag` is composed of the following
/// * IPC_CREAT - specify that the system call creates a new segment
/// * IPC_EXCL - this flag is used with IPC_CREAT to cause this function to fail when IPC_CREAT is also used
/// and the key passed has a memory segment associated with it.
///
/// ### Errors
///
/// * ENOENT : the key equals the `IPC_PRIVATE` constant
/// * EEXIST : key exists and yet either `IPC_CREAT` or `IPC_EXCL` are passed as flags
/// * ENOENT : key did not exist and the `IPC_CREAT` flag was not passed
/// * EINVAL : the size passed was less than the minimum size of segment or greater than the maximum possible size
///
/// ### Panics
///
/// There are no cases where the function directly panics
///
pub fn shmget_syscall(&self, key: i32, size: usize, shmflg: i32) -> i32 {
//Check if the key passed equals the IPC_PRIVATE flag
if key == IPC_PRIVATE {
// Return error since this is not suppported currently
return syscall_error(Errno::ENOENT, "shmget", "IPC_PRIVATE not implemented");
}
// Variable to store shmid
let shmid: i32;
// data of the shm table
let metadata = &SHM_METADATA;

// Check if there exists a memory segment associated with the key passed as argument
match metadata.shmkeyidtable.entry(key) {
// If there exists a memory segment at that key
interface::RustHashEntry::Occupied(occupied) => {
// Produce an error if invalid flags are used with a valid key
if (IPC_CREAT | IPC_EXCL) == (shmflg & (IPC_CREAT | IPC_EXCL)) {
return syscall_error(
Errno::EEXIST,
"shmget",
"key already exists and IPC_CREAT and IPC_EXCL were used",
);
}
// Get the id of the occupied memory segment
shmid = *occupied.get();
}
// If the memory segment doesn't exist
interface::RustHashEntry::Vacant(vacant) => {
// Return an error if IPC_CREAT was not specified
if 0 == (shmflg & IPC_CREAT) {
return syscall_error(
Errno::ENOENT,
Expand All @@ -5008,6 +5050,8 @@ impl Cage {
);
}

// If memory segment doesn't exist and IPC_CREAT was specified - we create a new memory segment
// Check if the size passed is a valid value
if (size as u32) < SHMMIN || (size as u32) > SHMMAX {
return syscall_error(
Errno::EINVAL,
Expand All @@ -5016,11 +5060,13 @@ impl Cage {
);
}

// Generate a new id for the new memory segment
shmid = metadata.new_keyid();
// Insert new id in the hash table entry pointed by the key
vacant.insert(shmid);
let mode = (shmflg & 0x1FF) as u16; // mode is 9 least signficant bits of shmflag, even if we dont really do
// anything with them

// Mode of the new segment is the 9 least significant bits of the shmflag
let mode = (shmflg & 0x1FF) as u16;
// Create a new segment with the key, size, cageid of the calling process
let segment = new_shm_segment(
key,
size,
Expand All @@ -5029,10 +5075,12 @@ impl Cage {
DEFAULT_GID,
mode,
);
// Insert the newly created segment in the SHM table with its key
metadata.shmtable.insert(shmid, segment);
}
};
shmid // return the shmid
// Return the shmid
shmid
}

//------------------SHMAT SYSCALL------------------
Expand Down
30 changes: 30 additions & 0 deletions src/tests/fs_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4034,6 +4034,36 @@ pub mod fs_tests {

assert_eq!(cage.close_syscall(fd), 0);
assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS);

lindrustfinalize();
}

pub fn ut_lind_fs_shmget_syscall(){
// acquire locks and start env cleanup
let _thelock = setup::lock_and_init();
let cage = interface::cagetable_getref(1);

let key = 33123;
// Get shmid of a memory segment / create a new one if it doesn't exist
let shmid = cage.shmget_syscall(33123, 1024, IPC_CREAT);
assert_eq!(shmid,4);

// Check error upon asking for a valid key and passing the IPC_CREAT and IPC_EXCL flag
assert_eq!(cage.shmget_syscall(key, 1024, IPC_CREAT | IPC_EXCL),-(Errno::EEXIST as i32 ));

// Check error when passing IPC_CREAT flag as the key
assert_eq!(cage.shmget_syscall(IPC_PRIVATE,1024,IPC_PRIVATE),-(Errno::ENOENT as i32));

// Check if the function returns a correct shmid upon asking with a key that we know exists
assert_eq!(cage.shmget_syscall(key, 1024,0666),shmid);

// Check if the function returns the correct error when we don't pass IPC_CREAT for a key that doesn't exist
assert_eq!(cage.shmget_syscall(123456, 1024, 0),-(Errno::ENOENT as i32));

// Check if the size error is returned correctly
assert_eq!(cage.shmget_syscall(123456, (SHMMAX + 10 )as usize, IPC_CREAT),-(Errno::EINVAL as i32));
assert_eq!(cage.shmget_syscall(123456, 0 as usize, IPC_CREAT),-(Errno::EINVAL as i32));

lindrustfinalize();
}
}

0 comments on commit 0276e79

Please sign in to comment.