diff options
-rw-r--r-- | fs/fuse/dir.c | 27 | ||||
-rw-r--r-- | fs/fuse/inode.c | 8 |
2 files changed, 22 insertions, 13 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index f156392d019e..417bcee466f6 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -166,6 +166,12 @@ static struct dentry_operations fuse_dentry_operations = { | |||
166 | .d_revalidate = fuse_dentry_revalidate, | 166 | .d_revalidate = fuse_dentry_revalidate, |
167 | }; | 167 | }; |
168 | 168 | ||
169 | static inline int valid_mode(int m) | ||
170 | { | ||
171 | return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || | ||
172 | S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); | ||
173 | } | ||
174 | |||
169 | static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | 175 | static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, |
170 | struct nameidata *nd) | 176 | struct nameidata *nd) |
171 | { | 177 | { |
@@ -185,7 +191,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
185 | fuse_lookup_init(req, dir, entry, &outarg); | 191 | fuse_lookup_init(req, dir, entry, &outarg); |
186 | request_send(fc, req); | 192 | request_send(fc, req); |
187 | err = req->out.h.error; | 193 | err = req->out.h.error; |
188 | if (!err && outarg.nodeid && invalid_nodeid(outarg.nodeid)) | 194 | if (!err && ((outarg.nodeid && invalid_nodeid(outarg.nodeid)) || |
195 | !valid_mode(outarg.attr.mode))) | ||
189 | err = -EIO; | 196 | err = -EIO; |
190 | if (!err && outarg.nodeid) { | 197 | if (!err && outarg.nodeid) { |
191 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 198 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
@@ -328,10 +335,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
328 | fuse_put_request(fc, req); | 335 | fuse_put_request(fc, req); |
329 | return err; | 336 | return err; |
330 | } | 337 | } |
331 | if (invalid_nodeid(outarg.nodeid)) { | 338 | err = -EIO; |
332 | fuse_put_request(fc, req); | 339 | if (invalid_nodeid(outarg.nodeid)) |
333 | return -EIO; | 340 | goto out_put_request; |
334 | } | 341 | |
342 | if ((outarg.attr.mode ^ mode) & S_IFMT) | ||
343 | goto out_put_request; | ||
344 | |||
335 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 345 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
336 | &outarg.attr); | 346 | &outarg.attr); |
337 | if (!inode) { | 347 | if (!inode) { |
@@ -340,8 +350,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
340 | } | 350 | } |
341 | fuse_put_request(fc, req); | 351 | fuse_put_request(fc, req); |
342 | 352 | ||
343 | /* Don't allow userspace to do really stupid things... */ | 353 | if (dir_alias(inode)) { |
344 | if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) { | ||
345 | iput(inode); | 354 | iput(inode); |
346 | return -EIO; | 355 | return -EIO; |
347 | } | 356 | } |
@@ -350,6 +359,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
350 | fuse_change_timeout(entry, &outarg); | 359 | fuse_change_timeout(entry, &outarg); |
351 | fuse_invalidate_attr(dir); | 360 | fuse_invalidate_attr(dir); |
352 | return 0; | 361 | return 0; |
362 | |||
363 | out_put_request: | ||
364 | fuse_put_request(fc, req); | ||
365 | return err; | ||
353 | } | 366 | } |
354 | 367 | ||
355 | static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, | 368 | static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index e4541869831e..04c80cc957a3 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -135,12 +135,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) | |||
135 | fuse_init_common(inode); | 135 | fuse_init_common(inode); |
136 | init_special_inode(inode, inode->i_mode, | 136 | init_special_inode(inode, inode->i_mode, |
137 | new_decode_dev(attr->rdev)); | 137 | new_decode_dev(attr->rdev)); |
138 | } else { | 138 | } else |
139 | /* Don't let user create weird files */ | 139 | BUG(); |
140 | inode->i_mode = S_IFREG; | ||
141 | fuse_init_common(inode); | ||
142 | fuse_init_file_inode(inode); | ||
143 | } | ||
144 | } | 140 | } |
145 | 141 | ||
146 | static int fuse_inode_eq(struct inode *inode, void *_nodeidp) | 142 | static int fuse_inode_eq(struct inode *inode, void *_nodeidp) |