Commit e98f93e7 authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 6e1eb04a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -225,7 +225,7 @@ static struct dentry *vboxsf_dir_lookup(struct inode *parent,
	} else {
		inode = vboxsf_new_inode(parent->i_sb);
		if (!IS_ERR(inode))
			vboxsf_init_inode(sbi, inode, &fsinfo);
			vboxsf_init_inode(sbi, inode, &fsinfo, false);
	}

	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);
	/* The host may have given us different attr then requested */
	sf_i->force_restat = 1;
	vboxsf_init_inode(sbi, inode, info);
	vboxsf_init_inode(sbi, inode, info, false);

	d_instantiate(dentry, inode);

+2 −2
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
		err = -ENOMEM;
		goto fail_unmap;
	}
	vboxsf_init_inode(sbi, iroot, &sbi->root_info);
	vboxsf_init_inode(sbi, iroot, &sbi->root_info, false);
	unlock_new_inode(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 */
	sbi->o = ctx->o;
	vboxsf_init_inode(sbi, iroot, &sbi->root_info);
	vboxsf_init_inode(sbi, iroot, &sbi->root_info, true);

	return 0;
}
+43 −25
Original line number Diff line number Diff line
@@ -45,12 +45,12 @@ struct inode *vboxsf_new_inode(struct super_block *sb)
}

/* set [inode] attributes based on [info], uid/gid based on [sbi] */
void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
		       const struct shfl_fsobjinfo *info)
int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
		       const struct shfl_fsobjinfo *info, bool reinit)
{
	const struct shfl_fsobjattr *attr;
	s64 allocated;
	int mode;
	umode_t mode;

	attr = &info->attr;

@@ -75,9 +75,11 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
	inode->i_mapping->a_ops = &vboxsf_reg_aops;

	if (SHFL_IS_DIRECTORY(attr->mode)) {
		inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode;
		inode->i_mode &= ~sbi->o.dmask;
		inode->i_mode |= S_IFDIR;
		if (sbi->o.dmode_set)
			mode = sbi->o.dmode;
		mode &= ~sbi->o.dmask;
		mode |= S_IFDIR;
		if (!reinit) {
			inode->i_op = &vboxsf_dir_iops;
			inode->i_fop = &vboxsf_dir_fops;
			/*
@@ -85,19 +87,32 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
			 * 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)) {
		inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
		inode->i_mode &= ~sbi->o.fmask;
		inode->i_mode |= S_IFLNK;
		if (sbi->o.fmode_set)
			mode = sbi->o.fmode;
		mode &= ~sbi->o.fmask;
		mode |= S_IFLNK;
		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 {
		inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
		inode->i_mode &= ~sbi->o.fmask;
		inode->i_mode |= S_IFREG;
		if (sbi->o.fmode_set)
			mode = sbi->o.fmode;
		mode &= ~sbi->o.fmask;
		mode |= S_IFREG;
		if (!reinit) {
			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;
@@ -116,6 +131,7 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
				 info->change_time.ns_relative_to_unix_epoch);
	inode->i_mtime = ns_to_timespec64(
			   info->modification_time.ns_relative_to_unix_epoch);
	return 0;
}

int vboxsf_create_at_dentry(struct dentry *dentry,
@@ -199,7 +215,9 @@ int vboxsf_inode_revalidate(struct dentry *dentry)

	dentry->d_time = jiffies;
	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
+2 −2
Original line number Diff line number Diff line
@@ -82,8 +82,8 @@ extern const struct dentry_operations vboxsf_dentry_ops;

/* from utils.c */
struct inode *vboxsf_new_inode(struct super_block *sb);
void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
		       const struct shfl_fsobjinfo *info);
int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
		       const struct shfl_fsobjinfo *info, bool reinit);
int vboxsf_create_at_dentry(struct dentry *dentry,
			    struct shfl_createparms *params);
int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,