mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 21:35:07 +00:00
vboxsf: don't allow to change the inode type
vboxsf_init_inode() is used both for initial setup of inode and for metadata updates. Tell it whether we are updating a live inode or setting up a new instance and have it refuse to change type in the former case. [fixed the braino caught by Hans de Goede <hdegoede@redhat.com>] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
6e1eb04a87
commit
e98f93e7ca
@ -225,7 +225,7 @@ static struct dentry *vboxsf_dir_lookup(struct inode *parent,
|
|||||||
} else {
|
} else {
|
||||||
inode = vboxsf_new_inode(parent->i_sb);
|
inode = vboxsf_new_inode(parent->i_sb);
|
||||||
if (!IS_ERR(inode))
|
if (!IS_ERR(inode))
|
||||||
vboxsf_init_inode(sbi, inode, &fsinfo);
|
vboxsf_init_inode(sbi, inode, &fsinfo, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return d_splice_alias(inode, dentry);
|
return d_splice_alias(inode, dentry);
|
||||||
@ -245,7 +245,7 @@ static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry,
|
|||||||
sf_i = VBOXSF_I(inode);
|
sf_i = VBOXSF_I(inode);
|
||||||
/* The host may have given us different attr then requested */
|
/* The host may have given us different attr then requested */
|
||||||
sf_i->force_restat = 1;
|
sf_i->force_restat = 1;
|
||||||
vboxsf_init_inode(sbi, inode, info);
|
vboxsf_init_inode(sbi, inode, info, false);
|
||||||
|
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
|
|||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto fail_unmap;
|
goto fail_unmap;
|
||||||
}
|
}
|
||||||
vboxsf_init_inode(sbi, iroot, &sbi->root_info);
|
vboxsf_init_inode(sbi, iroot, &sbi->root_info, false);
|
||||||
unlock_new_inode(iroot);
|
unlock_new_inode(iroot);
|
||||||
|
|
||||||
droot = d_make_root(iroot);
|
droot = d_make_root(iroot);
|
||||||
@ -418,7 +418,7 @@ static int vboxsf_reconfigure(struct fs_context *fc)
|
|||||||
|
|
||||||
/* Apply changed options to the root inode */
|
/* Apply changed options to the root inode */
|
||||||
sbi->o = ctx->o;
|
sbi->o = ctx->o;
|
||||||
vboxsf_init_inode(sbi, iroot, &sbi->root_info);
|
vboxsf_init_inode(sbi, iroot, &sbi->root_info, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -45,12 +45,12 @@ struct inode *vboxsf_new_inode(struct super_block *sb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set [inode] attributes based on [info], uid/gid based on [sbi] */
|
/* set [inode] attributes based on [info], uid/gid based on [sbi] */
|
||||||
void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
|
int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
|
||||||
const struct shfl_fsobjinfo *info)
|
const struct shfl_fsobjinfo *info, bool reinit)
|
||||||
{
|
{
|
||||||
const struct shfl_fsobjattr *attr;
|
const struct shfl_fsobjattr *attr;
|
||||||
s64 allocated;
|
s64 allocated;
|
||||||
int mode;
|
umode_t mode;
|
||||||
|
|
||||||
attr = &info->attr;
|
attr = &info->attr;
|
||||||
|
|
||||||
@ -75,29 +75,44 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
|
|||||||
inode->i_mapping->a_ops = &vboxsf_reg_aops;
|
inode->i_mapping->a_ops = &vboxsf_reg_aops;
|
||||||
|
|
||||||
if (SHFL_IS_DIRECTORY(attr->mode)) {
|
if (SHFL_IS_DIRECTORY(attr->mode)) {
|
||||||
inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode;
|
if (sbi->o.dmode_set)
|
||||||
inode->i_mode &= ~sbi->o.dmask;
|
mode = sbi->o.dmode;
|
||||||
inode->i_mode |= S_IFDIR;
|
mode &= ~sbi->o.dmask;
|
||||||
inode->i_op = &vboxsf_dir_iops;
|
mode |= S_IFDIR;
|
||||||
inode->i_fop = &vboxsf_dir_fops;
|
if (!reinit) {
|
||||||
/*
|
inode->i_op = &vboxsf_dir_iops;
|
||||||
* XXX: this probably should be set to the number of entries
|
inode->i_fop = &vboxsf_dir_fops;
|
||||||
* in the directory plus two (. ..)
|
/*
|
||||||
*/
|
* XXX: this probably should be set to the number of entries
|
||||||
set_nlink(inode, 1);
|
* in the directory plus two (. ..)
|
||||||
|
*/
|
||||||
|
set_nlink(inode, 1);
|
||||||
|
} else if (!S_ISDIR(inode->i_mode))
|
||||||
|
return -ESTALE;
|
||||||
|
inode->i_mode = mode;
|
||||||
} else if (SHFL_IS_SYMLINK(attr->mode)) {
|
} else if (SHFL_IS_SYMLINK(attr->mode)) {
|
||||||
inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
|
if (sbi->o.fmode_set)
|
||||||
inode->i_mode &= ~sbi->o.fmask;
|
mode = sbi->o.fmode;
|
||||||
inode->i_mode |= S_IFLNK;
|
mode &= ~sbi->o.fmask;
|
||||||
inode->i_op = &vboxsf_lnk_iops;
|
mode |= S_IFLNK;
|
||||||
set_nlink(inode, 1);
|
if (!reinit) {
|
||||||
|
inode->i_op = &vboxsf_lnk_iops;
|
||||||
|
set_nlink(inode, 1);
|
||||||
|
} else if (!S_ISLNK(inode->i_mode))
|
||||||
|
return -ESTALE;
|
||||||
|
inode->i_mode = mode;
|
||||||
} else {
|
} else {
|
||||||
inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
|
if (sbi->o.fmode_set)
|
||||||
inode->i_mode &= ~sbi->o.fmask;
|
mode = sbi->o.fmode;
|
||||||
inode->i_mode |= S_IFREG;
|
mode &= ~sbi->o.fmask;
|
||||||
inode->i_op = &vboxsf_reg_iops;
|
mode |= S_IFREG;
|
||||||
inode->i_fop = &vboxsf_reg_fops;
|
if (!reinit) {
|
||||||
set_nlink(inode, 1);
|
inode->i_op = &vboxsf_reg_iops;
|
||||||
|
inode->i_fop = &vboxsf_reg_fops;
|
||||||
|
set_nlink(inode, 1);
|
||||||
|
} else if (!S_ISREG(inode->i_mode))
|
||||||
|
return -ESTALE;
|
||||||
|
inode->i_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode->i_uid = sbi->o.uid;
|
inode->i_uid = sbi->o.uid;
|
||||||
@ -116,6 +131,7 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
|
|||||||
info->change_time.ns_relative_to_unix_epoch);
|
info->change_time.ns_relative_to_unix_epoch);
|
||||||
inode->i_mtime = ns_to_timespec64(
|
inode->i_mtime = ns_to_timespec64(
|
||||||
info->modification_time.ns_relative_to_unix_epoch);
|
info->modification_time.ns_relative_to_unix_epoch);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vboxsf_create_at_dentry(struct dentry *dentry,
|
int vboxsf_create_at_dentry(struct dentry *dentry,
|
||||||
@ -199,7 +215,9 @@ int vboxsf_inode_revalidate(struct dentry *dentry)
|
|||||||
|
|
||||||
dentry->d_time = jiffies;
|
dentry->d_time = jiffies;
|
||||||
sf_i->force_restat = 0;
|
sf_i->force_restat = 0;
|
||||||
vboxsf_init_inode(sbi, inode, &info);
|
err = vboxsf_init_inode(sbi, inode, &info, true);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the file was changed on the host side we need to invalidate the
|
* If the file was changed on the host side we need to invalidate the
|
||||||
|
@ -82,8 +82,8 @@ extern const struct dentry_operations vboxsf_dentry_ops;
|
|||||||
|
|
||||||
/* from utils.c */
|
/* from utils.c */
|
||||||
struct inode *vboxsf_new_inode(struct super_block *sb);
|
struct inode *vboxsf_new_inode(struct super_block *sb);
|
||||||
void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
|
int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
|
||||||
const struct shfl_fsobjinfo *info);
|
const struct shfl_fsobjinfo *info, bool reinit);
|
||||||
int vboxsf_create_at_dentry(struct dentry *dentry,
|
int vboxsf_create_at_dentry(struct dentry *dentry,
|
||||||
struct shfl_createparms *params);
|
struct shfl_createparms *params);
|
||||||
int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
|
int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user