Skip to content

Commit 0276e79

Browse files
Anway-Agtelindrennergade
authored
Anway shmget syscall (#310)
* 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>
1 parent fae5344 commit 0276e79

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

src/safeposix/syscalls/fs_calls.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4979,27 +4979,69 @@ impl Cage {
49794979
None
49804980
}
49814981

4982-
//------------------SHMGET SYSCALL------------------
4983-
4984-
pub fn shmget_syscall(&self, key: i32, size: usize, shmflg: i32) -> i32 {
4982+
/// ### Description
4983+
///
4984+
/// `shmget_syscall` returns the shared memory segment identifier associated with a particular `key`
4985+
/// If a key doesn't exist, shmget creates a new memory segment and attaches it to the key.
4986+
/// Traditionally if the value of the key equals `IPC_PRIVATE`, we also create a new memory segment which
4987+
/// is not associated with a key during this syscall,
4988+
/// but for our implementaion, we return an error and only create a new memory
4989+
/// segment when the IPC_CREAT flag is specified in the`shmflag` argument.
4990+
///
4991+
/// ### Returns
4992+
///
4993+
/// An 32 bit integer which represens the identifier of the memory segment associated with the key
4994+
///
4995+
/// ### Arguments
4996+
///
4997+
/// `key` : An i32 value that references a memory segment
4998+
/// `size` : Size of the memory segment to be created if key doesn't exist
4999+
/// `shmflag` : mode flags which indicate whether to create a new key or not
5000+
/// The `shmflag` is composed of the following
5001+
/// * IPC_CREAT - specify that the system call creates a new segment
5002+
/// * IPC_EXCL - this flag is used with IPC_CREAT to cause this function to fail when IPC_CREAT is also used
5003+
/// and the key passed has a memory segment associated with it.
5004+
///
5005+
/// ### Errors
5006+
///
5007+
/// * ENOENT : the key equals the `IPC_PRIVATE` constant
5008+
/// * EEXIST : key exists and yet either `IPC_CREAT` or `IPC_EXCL` are passed as flags
5009+
/// * ENOENT : key did not exist and the `IPC_CREAT` flag was not passed
5010+
/// * EINVAL : the size passed was less than the minimum size of segment or greater than the maximum possible size
5011+
///
5012+
/// ### Panics
5013+
///
5014+
/// There are no cases where the function directly panics
5015+
///
5016+
pub fn shmget_syscall(&self, key: i32, size: usize, shmflg: i32) -> i32 {
5017+
//Check if the key passed equals the IPC_PRIVATE flag
49855018
if key == IPC_PRIVATE {
5019+
// Return error since this is not suppported currently
49865020
return syscall_error(Errno::ENOENT, "shmget", "IPC_PRIVATE not implemented");
49875021
}
5022+
// Variable to store shmid
49885023
let shmid: i32;
5024+
// data of the shm table
49895025
let metadata = &SHM_METADATA;
49905026

5027+
// Check if there exists a memory segment associated with the key passed as argument
49915028
match metadata.shmkeyidtable.entry(key) {
5029+
// If there exists a memory segment at that key
49925030
interface::RustHashEntry::Occupied(occupied) => {
5031+
// Produce an error if invalid flags are used with a valid key
49935032
if (IPC_CREAT | IPC_EXCL) == (shmflg & (IPC_CREAT | IPC_EXCL)) {
49945033
return syscall_error(
49955034
Errno::EEXIST,
49965035
"shmget",
49975036
"key already exists and IPC_CREAT and IPC_EXCL were used",
49985037
);
49995038
}
5039+
// Get the id of the occupied memory segment
50005040
shmid = *occupied.get();
50015041
}
5042+
// If the memory segment doesn't exist
50025043
interface::RustHashEntry::Vacant(vacant) => {
5044+
// Return an error if IPC_CREAT was not specified
50035045
if 0 == (shmflg & IPC_CREAT) {
50045046
return syscall_error(
50055047
Errno::ENOENT,
@@ -5008,6 +5050,8 @@ impl Cage {
50085050
);
50095051
}
50105052

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

5063+
// Generate a new id for the new memory segment
50195064
shmid = metadata.new_keyid();
5065+
// Insert new id in the hash table entry pointed by the key
50205066
vacant.insert(shmid);
5021-
let mode = (shmflg & 0x1FF) as u16; // mode is 9 least signficant bits of shmflag, even if we dont really do
5022-
// anything with them
5023-
5067+
// Mode of the new segment is the 9 least significant bits of the shmflag
5068+
let mode = (shmflg & 0x1FF) as u16;
5069+
// Create a new segment with the key, size, cageid of the calling process
50245070
let segment = new_shm_segment(
50255071
key,
50265072
size,
@@ -5029,10 +5075,12 @@ impl Cage {
50295075
DEFAULT_GID,
50305076
mode,
50315077
);
5078+
// Insert the newly created segment in the SHM table with its key
50325079
metadata.shmtable.insert(shmid, segment);
50335080
}
50345081
};
5035-
shmid // return the shmid
5082+
// Return the shmid
5083+
shmid
50365084
}
50375085

50385086
//------------------SHMAT SYSCALL------------------

src/tests/fs_tests.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4034,6 +4034,36 @@ pub mod fs_tests {
40344034

40354035
assert_eq!(cage.close_syscall(fd), 0);
40364036
assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS);
4037+
4038+
lindrustfinalize();
4039+
}
4040+
4041+
pub fn ut_lind_fs_shmget_syscall(){
4042+
// acquire locks and start env cleanup
4043+
let _thelock = setup::lock_and_init();
4044+
let cage = interface::cagetable_getref(1);
4045+
4046+
let key = 33123;
4047+
// Get shmid of a memory segment / create a new one if it doesn't exist
4048+
let shmid = cage.shmget_syscall(33123, 1024, IPC_CREAT);
4049+
assert_eq!(shmid,4);
4050+
4051+
// Check error upon asking for a valid key and passing the IPC_CREAT and IPC_EXCL flag
4052+
assert_eq!(cage.shmget_syscall(key, 1024, IPC_CREAT | IPC_EXCL),-(Errno::EEXIST as i32 ));
4053+
4054+
// Check error when passing IPC_CREAT flag as the key
4055+
assert_eq!(cage.shmget_syscall(IPC_PRIVATE,1024,IPC_PRIVATE),-(Errno::ENOENT as i32));
4056+
4057+
// Check if the function returns a correct shmid upon asking with a key that we know exists
4058+
assert_eq!(cage.shmget_syscall(key, 1024,0666),shmid);
4059+
4060+
// Check if the function returns the correct error when we don't pass IPC_CREAT for a key that doesn't exist
4061+
assert_eq!(cage.shmget_syscall(123456, 1024, 0),-(Errno::ENOENT as i32));
4062+
4063+
// Check if the size error is returned correctly
4064+
assert_eq!(cage.shmget_syscall(123456, (SHMMAX + 10 )as usize, IPC_CREAT),-(Errno::EINVAL as i32));
4065+
assert_eq!(cage.shmget_syscall(123456, 0 as usize, IPC_CREAT),-(Errno::EINVAL as i32));
4066+
40374067
lindrustfinalize();
40384068
}
40394069
}

0 commit comments

Comments
 (0)