diff --git a/fs/ntfs/ea.c b/fs/ntfs/ea.c index 4fb10d51211c..4fbea76afe7e 100644 --- a/fs/ntfs/ea.c +++ b/fs/ntfs/ea.c @@ -406,37 +406,35 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len, * Check for the presence of an EA "$LXDEV" (used by WSL) * and return its value as a device address */ -int ntfs_ea_get_wsl_inode(struct inode *inode, dev_t *rdevp, unsigned int flags) +int ntfs_ea_get_wsl_inode(struct inode *inode, dev_t *rdevp, unsigned int flags, + bool *has_lxmod) { int err; __le32 v; + *has_lxmod = false; + if (!(flags & NTFS_VOL_UID)) { /* Load uid to lxuid EA */ err = ntfs_get_ea(inode, "$LXUID", sizeof("$LXUID") - 1, &v, sizeof(v)); - if (err < 0) - return err; - if (err != sizeof(v)) - return -EIO; - i_uid_write(inode, le32_to_cpu(v)); + if (err == sizeof(v)) + i_uid_write(inode, le32_to_cpu(v)); } if (!(flags & NTFS_VOL_GID)) { /* Load gid to lxgid EA */ err = ntfs_get_ea(inode, "$LXGID", sizeof("$LXGID") - 1, &v, sizeof(v)); - if (err < 0) - return err; - if (err != sizeof(v)) - return -EIO; - i_gid_write(inode, le32_to_cpu(v)); + if (err == sizeof(v)) + i_gid_write(inode, le32_to_cpu(v)); } /* Load mode to lxmod EA */ err = ntfs_get_ea(inode, "$LXMOD", sizeof("$LXMOD") - 1, &v, sizeof(v)); if (err == sizeof(v)) { inode->i_mode = le32_to_cpu(v); + *has_lxmod = true; } else { /* Everyone gets all permissions. */ inode->i_mode |= 0777; diff --git a/fs/ntfs/ea.h b/fs/ntfs/ea.h index 1f63bd55e057..acb39c2a6fbc 100644 --- a/fs/ntfs/ea.h +++ b/fs/ntfs/ea.h @@ -10,7 +10,8 @@ extern const struct xattr_handler *const ntfs_xattr_handlers[]; int ntfs_ea_set_wsl_not_symlink(struct ntfs_inode *ni, mode_t mode, dev_t dev); -int ntfs_ea_get_wsl_inode(struct inode *inode, dev_t *rdevp, unsigned int flags); +int ntfs_ea_get_wsl_inode(struct inode *inode, dev_t *rdevp, unsigned int flags, + bool *has_lxmod); int ntfs_ea_set_wsl_inode(struct inode *inode, dev_t rdev, __le16 *ea_size, unsigned int flags); ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size); diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index c8e49f83fd92..d4282822b3ce 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -342,14 +342,12 @@ int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, if (ia_valid & ATTR_MODE) flags |= NTFS_EA_MODE; - if (S_ISDIR(vi->i_mode)) - vi->i_mode &= ~vol->dmask; - else - vi->i_mode &= ~vol->fmask; - mutex_lock(&ni->mrec_lock); - ntfs_ea_set_wsl_inode(vi, 0, NULL, flags); + err = ntfs_ea_set_wsl_inode(vi, 0, NULL, flags); mutex_unlock(&ni->mrec_lock); + if (err) + goto out; + } mark_inode_dirty(vi); diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 50e244aa372e..39c7fd8c1149 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -682,6 +682,7 @@ static int ntfs_read_locked_inode(struct inode *vi) unsigned int name_len = 4, flags = 0; int extend_sys = 0; dev_t dev = 0; + bool has_lxmod = false; bool vol_err = true; ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no); @@ -862,7 +863,7 @@ static int ntfs_read_locked_inode(struct inode *vi) err = ntfs_attr_lookup(AT_EA_INFORMATION, NULL, 0, 0, 0, NULL, 0, ctx); if (!err) { NInoSetHasEA(ni); - ntfs_ea_get_wsl_inode(vi, &dev, flags); + ntfs_ea_get_wsl_inode(vi, &dev, flags, &has_lxmod); } if (ni->flags & FILE_ATTR_REPARSE_POINT) { @@ -886,16 +887,18 @@ static int ntfs_read_locked_inode(struct inode *vi) if (S_ISDIR(vi->i_mode)) { /* - * Apply the directory permissions mask set in the mount - * options. + * Apply the directory permissions mask set in the mount options + * when no per-file WSL mode is present. */ - vi->i_mode &= ~vol->dmask; + if (!has_lxmod) + vi->i_mode &= ~vol->dmask; /* Things break without this kludge! */ if (vi->i_nlink > 1) set_nlink(vi, 1); } else { - /* Apply the file permissions mask set in the mount options. */ - vi->i_mode &= ~vol->fmask; + /* Apply the file permissions mask when no WSL mode is present. */ + if (!has_lxmod) + vi->i_mode &= ~vol->fmask; } /* diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 0de5b63ef407..7091b2496fac 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -424,8 +424,6 @@ static struct ntfs_inode *__ntfs_create(struct mnt_idmap *idmap, struct inode *d * directories, also setup the index values to the defaults. */ if (S_ISDIR(mode)) { - mode &= ~vol->dmask; - NInoSetMstProtected(ni); ni->itype.index.block_size = 4096; ni->itype.index.block_size_bits = ntfs_ffs(4096) - 1; @@ -439,8 +437,6 @@ static struct ntfs_inode *__ntfs_create(struct mnt_idmap *idmap, struct inode *d ni->itype.index.vcn_size_bits = vol->sector_size_bits; } - } else { - mode &= ~vol->fmask; } if (IS_RDONLY(vi))