51
51
# define CLONE_NEWTIME 0x00000080 /* New time namespace */
52
52
# endif
53
53
54
+ /* Defined in chroot_realpath.c */
55
+ char * chroot_realpath (const char * chroot , const char * path , char resolved_path []);
56
+
54
57
static const char * console_socket = NULL ;
55
58
56
59
# define LIBCRIU_MIN_VERSION 31500
@@ -283,7 +286,8 @@ restore_cgroup_v1_mount (runtime_spec_schema_config_schema *def, libcrun_error_t
283
286
/* First check if there is actually a cgroup mount in the container. */
284
287
for (i = 0 ; i < def -> mounts_len ; i ++ )
285
288
{
286
- if (strcmp (def -> mounts [i ]-> type , "cgroup" ) == 0 )
289
+ char * type = def -> mounts [i ]-> type ;
290
+ if (type && strcmp (type , "cgroup" ) == 0 )
287
291
{
288
292
has_cgroup_mount = true;
289
293
break ;
@@ -353,7 +357,8 @@ checkpoint_cgroup_v1_mount (runtime_spec_schema_config_schema *def, libcrun_erro
353
357
/* First check if there is actually a cgroup mount in the container. */
354
358
for (i = 0 ; i < def -> mounts_len ; i ++ )
355
359
{
356
- if (strcmp (def -> mounts [i ]-> type , "cgroup" ) == 0 )
360
+ char * type = def -> mounts [i ]-> type ;
361
+ if (type && strcmp (type , "cgroup" ) == 0 )
357
362
{
358
363
has_cgroup_mount = true;
359
364
break ;
@@ -413,7 +418,7 @@ libcrun_container_checkpoint_linux_criu (libcrun_container_status_t *status, lib
413
418
cleanup_wrapper struct libcriu_wrapper_s * wrapper = NULL ;
414
419
cleanup_free char * descriptors_path = NULL ;
415
420
cleanup_free char * freezer_path = NULL ;
416
- cleanup_free char * path = NULL ;
421
+ cleanup_free char * rootfs = NULL ;
417
422
cleanup_close int image_fd = -1 ;
418
423
cleanup_close int work_fd = -1 ;
419
424
int cgroup_mode ;
@@ -552,13 +557,13 @@ libcrun_container_checkpoint_linux_criu (libcrun_container_status_t *status, lib
552
557
if (UNLIKELY (ret < 0 ))
553
558
return crun_error_wrap (err , "error saving CRIU descriptors file" );
554
559
555
- ret = append_paths (& path , err , status -> bundle , status -> rootfs , NULL );
560
+ ret = append_paths (& rootfs , err , status -> bundle , status -> rootfs , NULL );
556
561
if (UNLIKELY (ret < 0 ))
557
562
return ret ;
558
563
559
- ret = libcriu_wrapper -> criu_set_root (path );
564
+ ret = libcriu_wrapper -> criu_set_root (rootfs );
560
565
if (UNLIKELY (ret != 0 ))
561
- return crun_make_error (err , 0 , "error setting CRIU root to `%s`" , path );
566
+ return crun_make_error (err , 0 , "error setting CRIU root to `%s`" , rootfs );
562
567
563
568
cgroup_mode = libcrun_get_cgroup_mode (err );
564
569
if (UNLIKELY (cgroup_mode < 0 ))
@@ -575,17 +580,20 @@ libcrun_container_checkpoint_linux_criu (libcrun_container_status_t *status, lib
575
580
/* Tell CRIU about external bind mounts. */
576
581
for (i = 0 ; i < def -> mounts_len ; i ++ )
577
582
{
578
- size_t j ;
579
-
580
- for (j = 0 ; j < def -> mounts [i ]-> options_len ; j ++ )
583
+ if (is_bind_mount (def -> mounts [i ], NULL ))
581
584
{
582
- if (strcmp (def -> mounts [i ]-> options [j ], "bind" ) == 0 || strcmp (def -> mounts [i ]-> options [j ], "rbind" ) == 0 )
583
- {
584
- ret = libcriu_wrapper -> criu_add_ext_mount (def -> mounts [i ]-> destination , def -> mounts [i ]-> destination );
585
- if (UNLIKELY (ret < 0 ))
586
- return crun_make_error (err , - ret , "CRIU: failed adding external mount to `%s`" , def -> mounts [i ]-> destination );
587
- break ;
588
- }
585
+ /* We need to resolve mount destination inside container's root for CRIU to handle. */
586
+ char buf [PATH_MAX ];
587
+ const char * dest_in_root ;
588
+
589
+ dest_in_root = chroot_realpath (rootfs , def -> mounts [i ]-> destination , buf );
590
+ if (UNLIKELY (dest_in_root == NULL ))
591
+ return crun_make_error (err , errno , "unable to resolve external bind mount `%s` under rootfs" , def -> mounts [i ]-> destination );
592
+ dest_in_root += strlen (rootfs );
593
+
594
+ ret = libcriu_wrapper -> criu_add_ext_mount (dest_in_root , dest_in_root );
595
+ if (UNLIKELY (ret < 0 ))
596
+ return crun_make_error (err , - ret , "CRIU: failed adding external mount to `%s`" , def -> mounts [i ]-> destination );
589
597
}
590
598
}
591
599
@@ -720,17 +728,18 @@ prepare_restore_mounts (runtime_spec_schema_config_schema *def, char *root, libc
720
728
size_t j ;
721
729
722
730
/* cgroup restore should be handled by CRIU itself */
723
- if (strcmp (type , "cgroup" ) == 0 || strcmp (type , "cgroup2" ) == 0 )
731
+ if (type && ( strcmp (type , "cgroup" ) == 0 || strcmp (type , "cgroup2" ) == 0 ) )
724
732
continue ;
725
733
726
734
/* Check if the mountpoint is on a tmpfs. CRIU restores
727
735
* all tmpfs. We do need to recreate directories on a tmpfs. */
736
+ size_t dest_len = strlen (dest );
728
737
for (j = 0 ; j < def -> mounts_len ; j ++ )
729
738
{
730
- cleanup_free char * dest_loop = NULL ;
731
-
732
- xasprintf ( & dest_loop , "%s/" , def -> mounts [j ]-> destination );
733
- if (strncmp ( dest , dest_loop , strlen ( dest_loop )) == 0 && strcmp ( def -> mounts [j ]-> type , "tmpfs" ) == 0 )
739
+ if ( def -> mounts [ j ] -> type == NULL || strcmp ( def -> mounts [ j ] -> type , "tmpfs" ) != 0 )
740
+ continue ;
741
+ size_t mount_len = strlen ( def -> mounts [j ]-> destination );
742
+ if (mount_len < dest_len && dest [ mount_len ] == '/' && strncmp ( dest , def -> mounts [j ]-> destination , mount_len ) == 0 )
734
743
{
735
744
/* This is a mountpoint which is on a tmpfs.*/
736
745
on_tmpfs = true;
@@ -742,16 +751,11 @@ prepare_restore_mounts (runtime_spec_schema_config_schema *def, char *root, libc
742
751
continue ;
743
752
744
753
/* For bind mounts check if the source is a file or a directory. */
745
- for ( j = 0 ; j < def -> mounts [i ]-> options_len ; j ++ )
754
+ if ( is_bind_mount ( def -> mounts [i ], NULL ) )
746
755
{
747
- const char * opt = def -> mounts [i ]-> options [j ];
748
- if (strcmp (opt , "bind" ) == 0 || strcmp (opt , "rbind" ) == 0 )
749
- {
750
- is_dir = crun_dir_p (def -> mounts [i ]-> source , false, err );
751
- if (UNLIKELY (is_dir < 0 ))
752
- return is_dir ;
753
- break ;
754
- }
756
+ is_dir = crun_dir_p (def -> mounts [i ]-> source , false, err );
757
+ if (UNLIKELY (is_dir < 0 ))
758
+ return is_dir ;
755
759
}
756
760
757
761
root_fd = open (root , O_RDONLY | O_CLOEXEC );
@@ -789,6 +793,7 @@ libcrun_container_restore_linux_criu (libcrun_container_status_t *status, libcru
789
793
cleanup_close int inherit_new_pid_fd = -1 ;
790
794
cleanup_close int image_fd = -1 ;
791
795
cleanup_free char * root = NULL ;
796
+ cleanup_free char * rootfs = NULL ;
792
797
cleanup_free char * bundle_cleanup = NULL ;
793
798
cleanup_close int work_fd = -1 ;
794
799
int ret_out ;
@@ -899,19 +904,25 @@ libcrun_container_restore_linux_criu (libcrun_container_status_t *status, libcru
899
904
}
900
905
901
906
/* Tell CRIU about external bind mounts. */
907
+ ret = append_paths (& rootfs , err , status -> bundle , status -> rootfs , NULL );
908
+ if (UNLIKELY (ret < 0 ))
909
+ return ret ;
902
910
for (i = 0 ; i < def -> mounts_len ; i ++ )
903
911
{
904
- size_t j ;
905
-
906
- for (j = 0 ; j < def -> mounts [i ]-> options_len ; j ++ )
912
+ if (is_bind_mount (def -> mounts [i ], NULL ))
907
913
{
908
- if (strcmp (def -> mounts [i ]-> options [j ], "bind" ) == 0 || strcmp (def -> mounts [i ]-> options [j ], "rbind" ) == 0 )
909
- {
910
- ret = libcriu_wrapper -> criu_add_ext_mount (def -> mounts [i ]-> destination , def -> mounts [i ]-> source );
911
- if (UNLIKELY (ret < 0 ))
912
- return crun_make_error (err , - ret , "CRIU: failed adding external mount to `%s`" , def -> mounts [i ]-> source );
913
- break ;
914
- }
914
+ /* We need to resolve mount destination inside container's root for CRIU to handle. */
915
+ char buf [PATH_MAX ];
916
+ const char * dest_in_root ;
917
+
918
+ dest_in_root = chroot_realpath (rootfs , def -> mounts [i ]-> destination , buf );
919
+ if (UNLIKELY (dest_in_root == NULL ))
920
+ return crun_make_error (err , errno , "unable to resolve external bind mount `%s` under rootfs" , def -> mounts [i ]-> destination );
921
+ dest_in_root += strlen (rootfs );
922
+
923
+ ret = libcriu_wrapper -> criu_add_ext_mount (dest_in_root , def -> mounts [i ]-> source );
924
+ if (UNLIKELY (ret < 0 ))
925
+ return crun_make_error (err , - ret , "CRIU: failed adding external mount to `%s`" , def -> mounts [i ]-> source );
915
926
}
916
927
}
917
928
0 commit comments