Because bind-mounted subtrees of the volume may resolve to unexpected locations, change converting junctions and non-relative symbolic links into paths relative to the NTFS volume to be allowed only if the native_symlink=rel mount option is specified. Add the native_symlink= mount option to configure how absolute symbolic links and mount points (junctions) are handled. The option accepts "raw" or "rel", with "raw" being the default. Under "raw", the absolute target path (ni->target) is returned as-is without translation. Under "rel", ntfs_translate_junction() is called to rewrite the absolute path as a relative path anchored at the volume root. Signed-off-by: Hyunchul Lee --- fs/ntfs/file.c | 14 ++++++++------ fs/ntfs/inode.c | 4 ++++ fs/ntfs/super.c | 19 +++++++++++++++++++ fs/ntfs/volume.h | 3 +++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 6b0dfc56577b..6a7b638e523d 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -22,6 +22,7 @@ #include "ea.h" #include "iomap.h" #include "bitmap.h" +#include "volume.h" #include @@ -688,12 +689,13 @@ static const char *ntfs_get_link(struct dentry *dentry, struct inode *inode, if (ni->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT || (ni->reparse_tag == IO_REPARSE_TAG_SYMLINK && !(ni->reparse_flags & cpu_to_le32(SYMLINK_FLAG_RELATIVE)))) { - err = ntfs_translate_symlink_path(dentry, ni->target, &target); - if (err < 0) - return ERR_PTR(err); - - set_delayed_call(done, kfree_link, target); - return target; + if (NVolNativeSymlinkRel(ni->vol)) { + err = ntfs_translate_symlink_path(dentry, ni->target, &target); + if (err < 0) + return ERR_PTR(err); + set_delayed_call(done, kfree_link, target); + return target; + } } return ni->target; diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 07ca799a8f9a..76595f2e30ff 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -2378,6 +2378,10 @@ int ntfs_show_options(struct seq_file *sf, struct dentry *root) seq_puts(sf, ",discard"); if (NVolDisableSparse(vol)) seq_puts(sf, ",disable_sparse"); + if (NVolNativeSymlinkRel(vol)) + seq_puts(sf, ",native_symlink=rel"); + else + seq_puts(sf, ",native_symlink=raw"); if (vol->sb->s_flags & SB_POSIXACL) seq_puts(sf, ",acl"); return 0; diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index ca882e946a22..e032a247455c 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -43,6 +43,17 @@ static const struct constant_table ntfs_param_enums[] = { {} }; +enum { + NATIVE_SYMLINK_RAW, + NATIVE_SYMLINK_REL, +}; + +static const struct constant_table ntfs_native_symlink_enums[] = { + { "raw", NATIVE_SYMLINK_RAW }, + { "rel", NATIVE_SYMLINK_REL }, + {} +}; + enum { Opt_uid, Opt_gid, @@ -66,6 +77,7 @@ enum { Opt_acl, Opt_discard, Opt_nocase, + Opt_native_symlink, }; static const struct fs_parameter_spec ntfs_parameters[] = { @@ -91,6 +103,7 @@ static const struct fs_parameter_spec ntfs_parameters[] = { fsparam_flag("discard", Opt_discard), fsparam_flag("sparse", Opt_sparse), fsparam_flag("nocase", Opt_nocase), + fsparam_enum("native_symlink", Opt_native_symlink, ntfs_native_symlink_enums), {} }; @@ -215,6 +228,12 @@ static int ntfs_parse_param(struct fs_context *fc, struct fs_parameter *param) else NVolClearDisableSparse(vol); break; + case Opt_native_symlink: + if (result.uint_32 == NATIVE_SYMLINK_REL) + NVolSetNativeSymlinkRel(vol); + else + NVolClearNativeSymlinkRel(vol); + break; case Opt_sparse: break; default: diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h index 3348394dbc0d..55298689a7bb 100644 --- a/fs/ntfs/volume.h +++ b/fs/ntfs/volume.h @@ -177,6 +177,7 @@ struct ntfs_volume { * * NV_Discard Issue discard/TRIM commands for freed clusters. * NV_DisableSparse Disable creation of sparse regions. + * NV_NativeSymlinkRel Translate absolute Windows reparse targets (native_symlink=rel). */ enum { NV_Errors, @@ -194,6 +195,7 @@ enum { NV_CheckWindowsNames, NV_Discard, NV_DisableSparse, + NV_NativeSymlinkRel, }; /* @@ -230,6 +232,7 @@ DEFINE_NVOL_BIT_OPS(HideDotFiles) DEFINE_NVOL_BIT_OPS(CheckWindowsNames) DEFINE_NVOL_BIT_OPS(Discard) DEFINE_NVOL_BIT_OPS(DisableSparse) +DEFINE_NVOL_BIT_OPS(NativeSymlinkRel) static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr) { -- 2.43.0