@@ -801,6 +801,40 @@ static MountPointFlags fstab_options_to_flags(const char *options, bool is_swap)
801801 return flags ;
802802}
803803
804+ static int canonicalize_mount_path (const char * path , const char * type , bool initrd , char * * ret ) {
805+ _cleanup_free_ char * p = NULL ;
806+ bool changed ;
807+ int r ;
808+
809+ assert (path );
810+ assert (type );
811+ assert (STR_IN_SET (type , "where" , "what" ));
812+ assert (ret );
813+
814+ // FIXME: when chase() learns to chase non-existent paths, use this here and drop the prefixing with
815+ // /sysroot on error below.
816+ r = chase (path , initrd ? "/sysroot" : NULL , CHASE_PREFIX_ROOT | CHASE_NONEXISTENT , & p , NULL );
817+ if (r < 0 ) {
818+ log_debug_errno (r , "Failed to chase '%s', using as-is: %m" , path );
819+
820+ if (initrd )
821+ p = path_join ("/sysroot" , path );
822+ else
823+ p = strdup (path );
824+ if (!p )
825+ return log_oom ();
826+
827+ path_simplify (p );
828+ }
829+
830+ changed = !streq (path , p );
831+ if (changed )
832+ log_debug ("Canonicalized %s=%s to %s" , type , path , p );
833+
834+ * ret = TAKE_PTR (p );
835+ return changed ;
836+ }
837+
804838static int parse_fstab_one (
805839 const char * source ,
806840 const char * what_original ,
@@ -813,7 +847,7 @@ static int parse_fstab_one(
813847
814848 _cleanup_free_ char * what = NULL , * where = NULL ;
815849 MountPointFlags flags ;
816- bool is_swap ;
850+ bool is_swap , where_changed ;
817851 int r ;
818852
819853 assert (what_original );
@@ -848,49 +882,41 @@ static int parse_fstab_one(
848882 assert (where_original ); /* 'where' is not necessary for swap entry. */
849883
850884 if (!is_path (where_original )) {
851- log_warning ("Mount point %s is not a valid path, ignoring." , where );
885+ log_warning ("Mount point %s is not a valid path, ignoring." , where_original );
852886 return 0 ;
853887 }
854888
855889 /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
856890 * mount units, but causes problems since it historically worked to have symlinks in e.g.
857891 * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
858892 * where a symlink refers to another mount target; this works assuming the sub-mountpoint
859- * target is the final directory.
860- *
861- * FIXME: when chase() learns to chase non-existent paths, use this here and
862- * drop the prefixing with /sysroot on error below.
863- */
864- r = chase (where_original , initrd ? "/sysroot" : NULL , CHASE_PREFIX_ROOT | CHASE_NONEXISTENT , & where , NULL );
865- if (r < 0 ) {
866- /* If we can't canonicalize, continue as if it wasn't a symlink */
867- log_debug_errno (r , "Failed to read symlink target for %s, using as-is: %m" , where_original );
893+ * target is the final directory. */
894+ r = canonicalize_mount_path (where_original , "where" , initrd , & where );
895+ if (r < 0 )
896+ return r ;
897+ where_changed = r > 0 ;
868898
869- if (initrd )
870- where = path_join ("/sysroot" , where_original );
871- else
872- where = strdup (where_original );
873- if (!where )
874- return log_oom ();
899+ if (initrd && fstab_is_bind (options , fstype )) {
900+ /* When in initrd, the source of bind mount needs to be prepended with /sysroot as well. */
901+ _cleanup_free_ char * p = NULL ;
875902
876- path_simplify (where );
877- }
903+ r = canonicalize_mount_path (what , "what" , initrd , & p );
904+ if (r < 0 )
905+ return r ;
878906
879- if (streq (where , where_original )) /* If it was fully canonicalized, suppress the change */
880- where = mfree (where );
881- else
882- log_debug ("Canonicalized what=%s where=%s to %s" , what , where_original , where );
907+ free_and_replace (what , p );
908+ }
883909
884910 log_debug ("Found entry what=%s where=%s type=%s makefs=%s growfs=%s pcrfs=%s noauto=%s nofail=%s" ,
885911 what , where , strna (fstype ),
886912 yes_no (flags & MOUNT_MAKEFS ), yes_no (flags & MOUNT_GROWFS ), yes_no (flags & MOUNT_PCRFS ),
887913 yes_no (flags & MOUNT_NOAUTO ), yes_no (flags & MOUNT_NOFAIL ));
888914
889- bool is_sysroot = in_initrd () && path_equal (where ?: where_original , "/sysroot" );
915+ bool is_sysroot = in_initrd () && path_equal (where , "/sysroot" );
890916 /* See comment from add_sysroot_usr_mount() about the need for extra indirection in case /usr needs
891917 * to be mounted in order for the root fs to be synthesized based on configuration included in /usr/,
892918 * e.g. systemd-repart. */
893- bool is_sysroot_usr = in_initrd () && path_equal (where ?: where_original , "/sysroot/usr" );
919+ bool is_sysroot_usr = in_initrd () && path_equal (where , "/sysroot/usr" );
894920
895921 const char * target_unit =
896922 initrd ? SPECIAL_INITRD_FS_TARGET :
@@ -902,8 +928,8 @@ static int parse_fstab_one(
902928 r = add_mount (source ,
903929 arg_dest ,
904930 what ,
905- is_sysroot_usr ? "/sysusr/usr" : where ?: where_original ,
906- !is_sysroot_usr && where ? where_original : NULL ,
931+ is_sysroot_usr ? "/sysusr/usr" : where ,
932+ !is_sysroot_usr && where_changed ? where_original : NULL ,
907933 fstype ,
908934 options ,
909935 passno ,
0 commit comments