The hibernation check in load_system_files() only converts the superblock to read-only under errors=remount-ro. With the default errors=continue (and with errors=panic), a hibernated volume is mounted read-write and the mount-time $LogFile emptying writes to it, although a hibernated volume must not be written to at all. Drop the on_errors term so that a hibernated volume, or a volume whose hibernation state cannot be determined, always mounts read-only. NVolErrors() is still recorded, so ntfs_reconfigure() keeps refusing remounts to read-write, and the $LogFile emptying is skipped by its !sb_rdonly() check. Also change the ntfs_error() calls inside check_windows_hibernation_status() to ntfs_warning(): they run before SB_RDONLY is set, so errors=panic could panic there, while the warnings preserve diagnostics for already read-only mounts. The read-only fallback message is logged unconditionally: with SB_RDONLY set, or on an already read-only mount, ntfs_error() cannot panic, and the reason for NVolErrors() stays visible. Cc: stable@vger.kernel.org Signed-off-by: Hongling Zeng --- Changes in v3: -Use ntfs_warning() for the hibernation diagnostics so that errors=panic cannot fire on this path. -Always log the read-only fallback message, including on already read-only mounts. --- fs/ntfs/super.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index f4a73e45773d..d1edf1a891e8 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -1169,7 +1169,7 @@ static int check_windows_hibernation_status(struct ntfs_volume *vol) return 0; } /* A real error occurred. */ - ntfs_error(vol->sb, "Failed to find inode number for hiberfil.sys."); + ntfs_warning(vol->sb, "Failed to find inode number for hiberfil.sys."); return ret; } /* Get the inode. */ @@ -1177,7 +1177,7 @@ static int check_windows_hibernation_status(struct ntfs_volume *vol) if (IS_ERR(vi)) { if (!IS_ERR(vi)) iput(vi); - ntfs_error(vol->sb, "Failed to load hiberfil.sys."); + ntfs_warning(vol->sb, "Failed to load hiberfil.sys."); return IS_ERR(vi) ? PTR_ERR(vi) : -EIO; } if (unlikely(i_size_read(vi) < NTFS_HIBERFIL_HEADER_SIZE)) { @@ -1188,7 +1188,7 @@ static int check_windows_hibernation_status(struct ntfs_volume *vol) folio = read_mapping_folio(vi->i_mapping, 0, NULL); if (IS_ERR(folio)) { - ntfs_error(vol->sb, "Failed to read from hiberfil.sys."); + ntfs_warning(vol->sb, "Failed to read from hiberfil.sys."); ret = PTR_ERR(folio); goto iput_out; } @@ -1581,11 +1581,16 @@ static bool load_system_files(struct ntfs_volume *vol) const char *es1; es1 = err < 0 ? es1a : es1b; - /* If a read-write mount, convert it to a read-only mount. */ - if (!sb_rdonly(sb) && vol->on_errors == ON_ERRORS_REMOUNT_RO) { + /* + * A Windows hibernation image is not a filesystem error, so + * this is a safety interlock rather than something the + * errors= policy may downgrade: always convert a read-write + * mount to read-only. + */ + if (!sb_rdonly(sb)) sb->s_flags |= SB_RDONLY; - ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); - } + + ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); NVolSetErrors(vol); } -- 2.25.1