aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-01-06 03:19:43 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:56 -0500
commit39ee059affaf57a152c64cd3a0adc3f48f02ed71 (patch)
treed656f8b3eb40cd1019a82d4381bbfa33e6caec8e
parent6ad84acab972f4dfc78e6fdb04c419f82c497d29 (diff)
[PATCH] fuse: check file type in lookup
Previously invalid types were quietly changed to regular files, but at revalidation the inode was changed to bad. This was rather inconsistent behavior. Now check if the type is valid on initial lookup, and return -EIO if not. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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)