88#include <sys/types.h>
99#include <sys/wait.h>
1010#include <unistd.h>
11+ #include <semaphore.h>
12+ #include <sys/mman.h>
1113
1214#include "imfs.h"
1315
@@ -255,6 +257,16 @@ int main(int argc, char *argv[]) {
255257 exit (EXIT_FAILURE );
256258 }
257259
260+ // Create a semaphore to synchronize the grate and cage lifecycles.
261+ //
262+ // In this model, we call register_handler on the desired syscalls from the
263+ // grate rather than the newly forked child process.
264+ //
265+ // We use an unnamed semaphore to ensure that the cage only calls exec once the
266+ // grate has completed the necessary setup.
267+ sem_t * sem = mmap (NULL , sizeof (* sem ), PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANON , -1 , 0 );
268+ sem_init (sem , 1 , 0 );
269+
258270 int grateid = getpid ();
259271
260272 // Initialize imfs data structures.
@@ -264,48 +276,52 @@ int main(int argc, char *argv[]) {
264276 preload_files = getenv ("PRELOADS" );
265277 preloads (preload_files );
266278
267- pid_t pid = fork ();
268- if (pid < 0 ) {
279+ pid_t cageid = fork ();
280+ if (cageid < 0 ) {
269281 perror ("fork failed" );
270282 exit (EXIT_FAILURE );
271- } else if (pid == 0 ) {
272- int cageid = getpid ();
273- int ret ;
274- uint64_t fn_ptr_addr ;
283+ } else if (cageid == 0 ) {
284+ // Wait for grate to complete setup actions.
285+ sem_wait (sem );
275286
276- // OPEN
277- fn_ptr_addr = (uint64_t )(uintptr_t )& open_grate ;
278- ret = register_handler (cageid , 2 , 1 , grateid , fn_ptr_addr );
287+ if (execv (argv [1 ], & argv [1 ]) == -1 ) {
288+ perror ("execv failed" );
289+ exit (EXIT_FAILURE );
290+ }
291+ }
292+ int ret ;
293+ uint64_t fn_ptr_addr ;
279294
280- // LSEEK
281- fn_ptr_addr = (uint64_t )(uintptr_t )& lseek_grate ;
282- ret = register_handler (cageid , 8 , 1 , grateid , fn_ptr_addr );
295+ // OPEN
296+ fn_ptr_addr = (uint64_t )(uintptr_t )& open_grate ;
297+ ret = register_handler (cageid , 2 , 1 , grateid , fn_ptr_addr );
283298
284- // READ
285- fn_ptr_addr = (uint64_t )(uintptr_t )& read_grate ;
286- ret = register_handler (cageid , 0 , 1 , grateid , fn_ptr_addr );
299+ // LSEEK
300+ fn_ptr_addr = (uint64_t )(uintptr_t )& lseek_grate ;
301+ ret = register_handler (cageid , 8 , 1 , grateid , fn_ptr_addr );
287302
288- // WRITE
289- fn_ptr_addr = (uint64_t )(uintptr_t )& write_grate ;
290- ret = register_handler (cageid , 1 , 1 , grateid , fn_ptr_addr );
303+ // READ
304+ fn_ptr_addr = (uint64_t )(uintptr_t )& read_grate ;
305+ ret = register_handler (cageid , 0 , 1 , grateid , fn_ptr_addr );
291306
292- // CLOSE
293- fn_ptr_addr = (uint64_t )(uintptr_t )& close_grate ;
294- ret = register_handler (cageid , 3 , 1 , grateid , fn_ptr_addr );
307+ // WRITE
308+ fn_ptr_addr = (uint64_t )(uintptr_t )& write_grate ;
309+ ret = register_handler (cageid , 1 , 1 , grateid , fn_ptr_addr );
295310
296- // FCNTL
297- fn_ptr_addr = (uint64_t )(uintptr_t )& fcntl_grate ;
298- ret = register_handler (cageid , 72 , 1 , grateid , fn_ptr_addr );
311+ // CLOSE
312+ fn_ptr_addr = (uint64_t )(uintptr_t )& close_grate ;
313+ ret = register_handler (cageid , 3 , 1 , grateid , fn_ptr_addr );
299314
300- // UNLINK
301- fn_ptr_addr = (uint64_t )(uintptr_t )& unlink_grate ;
302- ret = register_handler (cageid , 87 , 1 , grateid , fn_ptr_addr );
315+ // FCNTL
316+ fn_ptr_addr = (uint64_t )(uintptr_t )& fcntl_grate ;
317+ ret = register_handler (cageid , 72 , 1 , grateid , fn_ptr_addr );
303318
304- if (execv (argv [1 ], & argv [1 ]) == -1 ) {
305- perror ("execv failed" );
306- exit (EXIT_FAILURE );
307- }
308- }
319+ // UNLINK
320+ fn_ptr_addr = (uint64_t )(uintptr_t )& unlink_grate ;
321+ ret = register_handler (cageid , 87 , 1 , grateid , fn_ptr_addr );
322+
323+ // Notify cage that it can proceed with execution.
324+ sem_post (sem );
309325
310326 int status ;
311327 int w ;
@@ -319,5 +335,9 @@ int main(int argc, char *argv[]) {
319335 }
320336 }
321337
338+ // Clean up the semaphore once the cage has exited.
339+ sem_destroy (sem );
340+ munmap (sem , sizeof (* sem ));
341+
322342 return 0 ;
323343}
0 commit comments