@@ -414,72 +414,92 @@ bind_mount (int proc_fd,
414414 return BIND_MOUNT_ERROR_REOPEN_DEST ;
415415 }
416416
417- /* If we are in a case-insensitive filesystem, mountinfo might contain a
418- * different case combination of the path we requested to mount.
419- * This is due to the fact that the kernel, as of the beginning of 2021,
420- * populates mountinfo with whatever case combination first appeared in the
421- * dcache; kernel developers plan to change this in future so that it
422- * reflects the on-disk encoding instead.
423- * To avoid throwing an error when this happens, we use readlink() result
424- * instead of the provided @root_mount, so that we can compare the mountinfo
425- * entries with the same case combination that the kernel is expected to
426- * use. */
427- dest_proc = xasprintf ("/proc/self/fd/%d" , dest_fd );
428- oldroot_dest_proc = get_oldroot_path (dest_proc );
429- kernel_case_combination = readlink_malloc (oldroot_dest_proc );
430- if (kernel_case_combination == NULL )
417+ struct mount_attr attr = {
418+ .attr_clr = 0 ,
419+ .attr_set = MOUNT_ATTR_NOSUID | (devices ? 0 : MOUNT_ATTR_NODEV ) |
420+ (readonly ? MOUNT_ATTR_RDONLY : 0 ),
421+ };
422+ if (mount_setattr_wrapper (dest_fd , "" ,
423+ AT_EMPTY_PATH | (recursive ? AT_RECURSIVE : 0 ), & attr ,
424+ sizeof (attr )) == -1 )
431425 {
432- if (failing_path != NULL )
433- * failing_path = steal_pointer (& resolved_dest );
434-
435- return BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD ;
436- }
426+ if (errno != ENOSYS )
427+ {
428+ if (failing_path != NULL )
429+ * failing_path = steal_pointer (& resolved_dest );
437430
438- mount_tab = parse_mountinfo (proc_fd , kernel_case_combination );
439- if (mount_tab [0 ].mountpoint == NULL )
440- {
441- if (failing_path != NULL )
442- * failing_path = steal_pointer (& kernel_case_combination );
431+ return BIND_MOUNT_ERROR_MOUNT_SETATTR ;
432+ }
433+ else
434+ {
435+ /* If we are in a case-insensitive filesystem, mountinfo might contain a
436+ * different case combination of the path we requested to mount.
437+ * This is due to the fact that the kernel, as of the beginning of 2021,
438+ * populates mountinfo with whatever case combination first appeared in the
439+ * dcache; kernel developers plan to change this in future so that it
440+ * reflects the on-disk encoding instead.
441+ * To avoid throwing an error when this happens, we use readlink() result
442+ * instead of the provided @root_mount, so that we can compare the mountinfo
443+ * entries with the same case combination that the kernel is expected to
444+ * use. */
445+ dest_proc = xasprintf ("/proc/self/fd/%d" , dest_fd );
446+ oldroot_dest_proc = get_oldroot_path (dest_proc );
447+ kernel_case_combination = readlink_malloc (oldroot_dest_proc );
448+ if (kernel_case_combination == NULL )
449+ {
450+ if (failing_path != NULL )
451+ * failing_path = steal_pointer (& resolved_dest );
443452
444- errno = EINVAL ;
445- return BIND_MOUNT_ERROR_FIND_DEST_MOUNT ;
446- }
453+ return BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD ;
454+ }
447455
448- assert (path_equal (mount_tab [0 ].mountpoint , kernel_case_combination ));
449- current_flags = mount_tab [0 ].options ;
450- new_flags = current_flags | (devices ? 0 : MS_NODEV ) | MS_NOSUID | (readonly ? MS_RDONLY : 0 );
451- if (new_flags != current_flags &&
452- mount ("none" , resolved_dest ,
453- NULL , MS_SILENT | MS_BIND | MS_REMOUNT | new_flags , NULL ) != 0 )
454- {
455- if (failing_path != NULL )
456- * failing_path = steal_pointer (& resolved_dest );
456+ mount_tab = parse_mountinfo (proc_fd , kernel_case_combination );
457+ if (mount_tab [0 ].mountpoint == NULL )
458+ {
459+ if (failing_path != NULL )
460+ * failing_path = steal_pointer (& kernel_case_combination );
457461
458- return BIND_MOUNT_ERROR_REMOUNT_DEST ;
459- }
462+ errno = EINVAL ;
463+ return BIND_MOUNT_ERROR_FIND_DEST_MOUNT ;
464+ }
460465
461- /* We need to work around the fact that a bind mount does not apply the flags, so we need to manually
462- * apply the flags to all submounts in the recursive case.
463- * Note: This does not apply the flags to mounts which are later propagated into this namespace.
464- */
465- if (recursive )
466- {
467- for (i = 1 ; mount_tab [i ].mountpoint != NULL ; i ++ )
468- {
469- current_flags = mount_tab [i ].options ;
466+ assert (path_equal (mount_tab [0 ].mountpoint , kernel_case_combination ));
467+ current_flags = mount_tab [0 ].options ;
470468 new_flags = current_flags | (devices ? 0 : MS_NODEV ) | MS_NOSUID | (readonly ? MS_RDONLY : 0 );
471469 if (new_flags != current_flags &&
472- mount ("none" , mount_tab [ i ]. mountpoint ,
470+ mount ("none" , resolved_dest ,
473471 NULL , MS_SILENT | MS_BIND | MS_REMOUNT | new_flags , NULL ) != 0 )
474472 {
475- /* If we can't read the mountpoint we can't remount it, but that should
476- be safe to ignore because its not something the user can access. */
477- if (errno != EACCES )
478- {
479- if (failing_path != NULL )
480- * failing_path = xstrdup (mount_tab [i ].mountpoint );
473+ if (failing_path != NULL )
474+ * failing_path = steal_pointer (& resolved_dest );
475+
476+ return BIND_MOUNT_ERROR_REMOUNT_DEST ;
477+ }
481478
482- return BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT ;
479+ /* We need to work around the fact that a bind mount does not apply the flags, so we need to manually
480+ * apply the flags to all submounts in the recursive case.
481+ * Note: This does not apply the flags to mounts which are later propagated into this namespace.
482+ */
483+ if (recursive )
484+ {
485+ for (i = 1 ; mount_tab [i ].mountpoint != NULL ; i ++ )
486+ {
487+ current_flags = mount_tab [i ].options ;
488+ new_flags = current_flags | (devices ? 0 : MS_NODEV ) | MS_NOSUID | (readonly ? MS_RDONLY : 0 );
489+ if (new_flags != current_flags &&
490+ mount ("none" , mount_tab [i ].mountpoint ,
491+ NULL , MS_SILENT | MS_BIND | MS_REMOUNT | new_flags , NULL ) != 0 )
492+ {
493+ /* If we can't read the mountpoint we can't remount it, but that should
494+ be safe to ignore because its not something the user can access. */
495+ if (errno != EACCES )
496+ {
497+ if (failing_path != NULL )
498+ * failing_path = xstrdup (mount_tab [i ].mountpoint );
499+
500+ return BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT ;
501+ }
502+ }
483503 }
484504 }
485505 }
@@ -534,6 +554,10 @@ bind_mount_result_to_string (bind_mount_result res,
534554 failing_path );
535555 break ;
536556
557+ case BIND_MOUNT_ERROR_MOUNT_SETATTR :
558+ string = xasprintf ("mount_setattr() failed at \"%s\"" , failing_path );
559+ break ;
560+
537561 case BIND_MOUNT_SUCCESS :
538562 string = xstrdup ("Success" );
539563 break ;
@@ -587,6 +611,7 @@ die_with_bind_result (bind_mount_result res,
587611 case BIND_MOUNT_ERROR_REOPEN_DEST :
588612 case BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD :
589613 case BIND_MOUNT_ERROR_FIND_DEST_MOUNT :
614+ case BIND_MOUNT_ERROR_MOUNT_SETATTR :
590615 case BIND_MOUNT_SUCCESS :
591616 default :
592617 fprintf (stderr , ": %s" , strerror (saved_errno ));
0 commit comments