mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
ntfs: respect per-file chmod mode over mount masks
fmask and dmask provide the default permissions for files without WSL
metadata. Once chmod stores a mode in $LXMOD, however, that per-file mode
must take precedence so selected files can retain permissions such as
execute across remounts.
Record whether $LXMOD was found while loading an inode and apply the mount
masks only when it is absent. Do not remask the in-memory mode after
setattr persists it. Continue loading $LXMOD even when optional $LXUID or
$LXGID metadata is missing, since chmod may create only $LXMOD.
Fixes: fc053f05ca ("ntfs: add reparse and ea operations")
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
71feaa7686
commit
4d730a4dd7
20
fs/ntfs/ea.c
20
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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user