Skip to content

Commit e98f93e

Browse files
author
Al Viro
committed
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>
1 parent 6e1eb04 commit e98f93e

4 files changed

Lines changed: 49 additions & 31 deletions

File tree

fs/vboxsf/dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ static struct dentry *vboxsf_dir_lookup(struct inode *parent,
225225
} else {
226226
inode = vboxsf_new_inode(parent->i_sb);
227227
if (!IS_ERR(inode))
228-
vboxsf_init_inode(sbi, inode, &fsinfo);
228+
vboxsf_init_inode(sbi, inode, &fsinfo, false);
229229
}
230230

231231
return d_splice_alias(inode, dentry);
@@ -245,7 +245,7 @@ static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry,
245245
sf_i = VBOXSF_I(inode);
246246
/* The host may have given us different attr then requested */
247247
sf_i->force_restat = 1;
248-
vboxsf_init_inode(sbi, inode, info);
248+
vboxsf_init_inode(sbi, inode, info, false);
249249

250250
d_instantiate(dentry, inode);
251251

fs/vboxsf/super.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
207207
err = -ENOMEM;
208208
goto fail_unmap;
209209
}
210-
vboxsf_init_inode(sbi, iroot, &sbi->root_info);
210+
vboxsf_init_inode(sbi, iroot, &sbi->root_info, false);
211211
unlock_new_inode(iroot);
212212

213213
droot = d_make_root(iroot);
@@ -418,7 +418,7 @@ static int vboxsf_reconfigure(struct fs_context *fc)
418418

419419
/* Apply changed options to the root inode */
420420
sbi->o = ctx->o;
421-
vboxsf_init_inode(sbi, iroot, &sbi->root_info);
421+
vboxsf_init_inode(sbi, iroot, &sbi->root_info, true);
422422

423423
return 0;
424424
}

fs/vboxsf/utils.c

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ struct inode *vboxsf_new_inode(struct super_block *sb)
4545
}
4646

4747
/* set [inode] attributes based on [info], uid/gid based on [sbi] */
48-
void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
49-
const struct shfl_fsobjinfo *info)
48+
int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
49+
const struct shfl_fsobjinfo *info, bool reinit)
5050
{
5151
const struct shfl_fsobjattr *attr;
5252
s64 allocated;
53-
int mode;
53+
umode_t mode;
5454

5555
attr = &info->attr;
5656

@@ -75,29 +75,44 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
7575
inode->i_mapping->a_ops = &vboxsf_reg_aops;
7676

7777
if (SHFL_IS_DIRECTORY(attr->mode)) {
78-
inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode;
79-
inode->i_mode &= ~sbi->o.dmask;
80-
inode->i_mode |= S_IFDIR;
81-
inode->i_op = &vboxsf_dir_iops;
82-
inode->i_fop = &vboxsf_dir_fops;
83-
/*
84-
* XXX: this probably should be set to the number of entries
85-
* in the directory plus two (. ..)
86-
*/
87-
set_nlink(inode, 1);
78+
if (sbi->o.dmode_set)
79+
mode = sbi->o.dmode;
80+
mode &= ~sbi->o.dmask;
81+
mode |= S_IFDIR;
82+
if (!reinit) {
83+
inode->i_op = &vboxsf_dir_iops;
84+
inode->i_fop = &vboxsf_dir_fops;
85+
/*
86+
* XXX: this probably should be set to the number of entries
87+
* in the directory plus two (. ..)
88+
*/
89+
set_nlink(inode, 1);
90+
} else if (!S_ISDIR(inode->i_mode))
91+
return -ESTALE;
92+
inode->i_mode = mode;
8893
} else if (SHFL_IS_SYMLINK(attr->mode)) {
89-
inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
90-
inode->i_mode &= ~sbi->o.fmask;
91-
inode->i_mode |= S_IFLNK;
92-
inode->i_op = &vboxsf_lnk_iops;
93-
set_nlink(inode, 1);
94+
if (sbi->o.fmode_set)
95+
mode = sbi->o.fmode;
96+
mode &= ~sbi->o.fmask;
97+
mode |= S_IFLNK;
98+
if (!reinit) {
99+
inode->i_op = &vboxsf_lnk_iops;
100+
set_nlink(inode, 1);
101+
} else if (!S_ISLNK(inode->i_mode))
102+
return -ESTALE;
103+
inode->i_mode = mode;
94104
} else {
95-
inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
96-
inode->i_mode &= ~sbi->o.fmask;
97-
inode->i_mode |= S_IFREG;
98-
inode->i_op = &vboxsf_reg_iops;
99-
inode->i_fop = &vboxsf_reg_fops;
100-
set_nlink(inode, 1);
105+
if (sbi->o.fmode_set)
106+
mode = sbi->o.fmode;
107+
mode &= ~sbi->o.fmask;
108+
mode |= S_IFREG;
109+
if (!reinit) {
110+
inode->i_op = &vboxsf_reg_iops;
111+
inode->i_fop = &vboxsf_reg_fops;
112+
set_nlink(inode, 1);
113+
} else if (!S_ISREG(inode->i_mode))
114+
return -ESTALE;
115+
inode->i_mode = mode;
101116
}
102117

103118
inode->i_uid = sbi->o.uid;
@@ -116,6 +131,7 @@ void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
116131
info->change_time.ns_relative_to_unix_epoch);
117132
inode->i_mtime = ns_to_timespec64(
118133
info->modification_time.ns_relative_to_unix_epoch);
134+
return 0;
119135
}
120136

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

200216
dentry->d_time = jiffies;
201217
sf_i->force_restat = 0;
202-
vboxsf_init_inode(sbi, inode, &info);
218+
err = vboxsf_init_inode(sbi, inode, &info, true);
219+
if (err)
220+
return err;
203221

204222
/*
205223
* If the file was changed on the host side we need to invalidate the

fs/vboxsf/vfsmod.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ extern const struct dentry_operations vboxsf_dentry_ops;
8282

8383
/* from utils.c */
8484
struct inode *vboxsf_new_inode(struct super_block *sb);
85-
void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
86-
const struct shfl_fsobjinfo *info);
85+
int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
86+
const struct shfl_fsobjinfo *info, bool reinit);
8787
int vboxsf_create_at_dentry(struct dentry *dentry,
8888
struct shfl_createparms *params);
8989
int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,

0 commit comments

Comments
 (0)