diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2006-01-06 03:19:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:56 -0500 |
commit | 39ee059affaf57a152c64cd3a0adc3f48f02ed71 (patch) | |
tree | d656f8b3eb40cd1019a82d4381bbfa33e6caec8e /fs/fuse | |
parent | 6ad84acab972f4dfc78e6fdb04c419f82c497d29 (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>
Diffstat (limited to 'fs/fuse')
-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) |