aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c27
-rw-r--r--fs/fuse/inode.c8
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
169static 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
169static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 175static 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
355static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, 368static 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
146static int fuse_inode_eq(struct inode *inode, void *_nodeidp) 142static int fuse_inode_eq(struct inode *inode, void *_nodeidp)