@@ -441,6 +441,80 @@ void test_get_values_degenerate() {
441441 printf ("get_values degenerate-value handling OK\n" );
442442}
443443
444+ // oci_launch_cmd_matches_user backs the check in main.c that a launch command
445+ // file's username matches the user the worker-launcher was invoked for.
446+ void test_oci_launch_cmd_matches_user () {
447+ oci_launch_cmd olc ;
448+ memset (& olc , 0 , sizeof (olc ));
449+ olc .username = "alice" ;
450+ EXPECT (oci_launch_cmd_matches_user (& olc , "alice" ), "matching username rejected" );
451+ EXPECT (!oci_launch_cmd_matches_user (& olc , "bob" ), "mismatched username accepted" );
452+ olc .username = NULL ;
453+ EXPECT (!oci_launch_cmd_matches_user (& olc , "alice" ), "command with no username accepted" );
454+ EXPECT (!oci_launch_cmd_matches_user (NULL , "alice" ), "null command accepted" );
455+ }
456+
457+ // Write a launch command file that is valid except for the bind-mount source,
458+ // which is set to mount_source.
459+ static void write_olc_file (const char * path , const char * mount_source ) {
460+ FILE * f = fopen (path , "w" );
461+ EXPECT (f != NULL , "could not write launch command file" );
462+ fprintf (f ,
463+ "{\n"
464+ " \"username\": \"olcuser\",\n"
465+ " \"containerId\": \"85afb30b-286e-4d32-ab7a-9d5aad89bb88\",\n"
466+ " \"pidFile\": \"" TEST_ROOT "/olc/pid\",\n"
467+ " \"containerScriptPath\": \"" TEST_ROOT "/olc/script.sh\",\n"
468+ " \"reapLayerKeepCount\": 0,\n"
469+ " \"layers\": [ { \"mediaType\": \"application/vnd.squashfs\", \"path\": \"/layer\" } ],\n"
470+ " \"ociRuntimeConfig\": {\n"
471+ " \"linux\": { \"cgroupsPath\": \"/storm\" },\n"
472+ " \"process\": { \"args\": [\"/bin/true\"], \"cwd\": \"/\", \"env\": [\"A=B\"] },\n"
473+ " \"mounts\": [ { \"type\": \"bind\", \"source\": \"%s\", \"destination\": \"/dst\", \"options\": [\"rbind\", \"rprivate\"] } ]\n"
474+ " }\n"
475+ "}\n" , mount_source );
476+ fclose (f );
477+ }
478+
479+ // parse_oci_launch_cmd runs the bind-mount allow-list check (is_valid_mount ->
480+ // is_valid_mount_source) as part of validation, so a launch command whose mount
481+ // source is outside the configured directories must fail to parse. The source
482+ // is resolved with realpath, so build a real tree; run in a child so the
483+ // temporary config does not leak into later tests.
484+ void test_oci_parse_launch_cmd_mounts () {
485+ const char * base = TEST_ROOT "/olc" ;
486+ const char * allowed = TEST_ROOT "/olc/allowed" ;
487+ const char * good_src = TEST_ROOT "/olc/allowed/mount.conf" ;
488+ const char * bad_src = TEST_ROOT "/olc/outside.conf" ;
489+ EXPECT (mkdir (base , 0755 ) == 0 || errno == EEXIST , "could not create olc base" );
490+ EXPECT (mkdir (allowed , 0755 ) == 0 || errno == EEXIST , "could not create allowed dir" );
491+ FILE * g = fopen (good_src , "w" ); EXPECT (g != NULL , "could not create mount.conf" ); fclose (g );
492+ FILE * b = fopen (bad_src , "w" ); EXPECT (b != NULL , "could not create outside.conf" ); fclose (b );
493+
494+ const char * cfg = TEST_ROOT "/olc/wl.cfg" ;
495+ FILE * c = fopen (cfg , "w" );
496+ EXPECT (c != NULL , "could not write wl.cfg" );
497+ fprintf (c , "min.user.id=%d\n" , getuid ());
498+ fprintf (c , "worker.launcher.oci.allowed.mount.source.dirs=%s\n" , allowed );
499+ fclose (c );
500+ read_config (cfg );
501+
502+ const char * good_cmd = TEST_ROOT "/olc/good.json" ;
503+ const char * bad_cmd = TEST_ROOT "/olc/bad.json" ;
504+ write_olc_file (good_cmd , good_src );
505+ write_olc_file (bad_cmd , bad_src );
506+
507+ oci_launch_cmd * olc = parse_oci_launch_cmd (good_cmd );
508+ EXPECT (olc != NULL , "launch command with an allowed mount source rejected" );
509+ free_oci_launch_cmd (olc );
510+
511+ // the key case: the mount hookup must reject a source outside the allowed dirs
512+ olc = parse_oci_launch_cmd (bad_cmd );
513+ EXPECT (olc == NULL , "launch command with a mount source outside the allowed dirs accepted" );
514+
515+ printf ("parse_oci_launch_cmd mount-source enforcement OK\n" );
516+ }
517+
444518int main (int argc , char * * argv ) {
445519 LOGFILE = stdout ;
446520 ERRORFILE = stderr ;
@@ -496,7 +570,11 @@ int main(int argc, char **argv) {
496570 printf ("\nTesting mount path helpers\n" );
497571 test_mount_path_helpers ();
498572
573+ printf ("\nTesting oci_launch_cmd_matches_user\n" );
574+ test_oci_launch_cmd_matches_user ();
575+
499576 run_test_in_child ("test_mount_source_allowed_dirs" , test_mount_source_allowed_dirs );
577+ run_test_in_child ("test_oci_parse_launch_cmd_mounts" , test_oci_parse_launch_cmd_mounts );
500578
501579 run_test_in_child ("test_signal_container" , test_signal_container );
502580 run_test_in_child ("test_signal_container_group" , test_signal_container_group );
0 commit comments