From: Miklos Szeredi Date: Wed, 14 Dec 2005 22:16:28 +0000 (+0000) Subject: fix X-Git-Tag: fuse_2_5_0_pre2~21 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=6470957cce815f8c707882093c8f76165f69cc55;p=qemu-gpiodev%2Flibfuse.git fix --- diff --git a/ChangeLog b/ChangeLog index bd5245c..d570853 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,9 @@ without largefile support. Bug report and help from Anthony Kolasny + * If lookup returns invalid mode, return -EIO instead of creating + a regular file. + 2005-12-12 Miklos Szeredi * Fix stale code in ifdef FreeBSD. Patch from Csaba Henk diff --git a/kernel/dir.c b/kernel/dir.c index 8c161b6..b1bf3aa 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -190,6 +190,12 @@ static struct dentry_operations fuse_dentry_operations = { #endif }; +static inline int valid_mode(int m) +{ + return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || + S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); +} + static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) { @@ -212,7 +218,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, fuse_lookup_init(req, dir, entry, &outarg); request_send(fc, req); err = req->out.h.error; - if (!err && outarg.nodeid && invalid_nodeid(outarg.nodeid)) + if (!err && ((outarg.nodeid && invalid_nodeid(outarg.nodeid)) || + !valid_mode(outarg.attr.mode))) err = -EIO; if (!err && outarg.nodeid) { inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, @@ -370,10 +377,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, fuse_put_request(fc, req); return err; } - if (invalid_nodeid(outarg.nodeid)) { - fuse_put_request(fc, req); - return -EIO; - } + err = -EIO; + if (invalid_nodeid(outarg.nodeid)) + goto out_put_request; + + if ((outarg.attr.mode ^ mode) & S_IFMT) + goto out_put_request; + inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); if (!inode) { @@ -382,8 +392,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, } fuse_put_request(fc, req); - /* Don't allow userspace to do really stupid things... */ - if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) { + if (dir_alias(inode)) { iput(inode); return -EIO; } @@ -392,6 +401,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, fuse_change_timeout(entry, &outarg); fuse_invalidate_attr(dir); return 0; + + out_put_request: + fuse_put_request(fc, req); + return err; } static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, diff --git a/kernel/inode.c b/kernel/inode.c index 8c7c7d6..464a519 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -160,12 +160,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) fuse_init_common(inode); init_special_inode(inode, inode->i_mode, new_decode_dev(attr->rdev)); - } else { - /* Don't let user create weird files */ - inode->i_mode = S_IFREG; - fuse_init_common(inode); - fuse_init_file_inode(inode); - } + } else + BUG(); } #ifdef KERNEL_2_6