aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-12-14 22:16:28 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2005-12-14 22:16:28 +0000
commit6470957cce815f8c707882093c8f76165f69cc55 (patch)
treee7f471c274c4ead29fd25ea1e41006c8d6fb9b66
parente248e4bb1afb07b5fbdff3499764997dd48ecdd7 (diff)
downloadlibfuse-6470957cce815f8c707882093c8f76165f69cc55.tar.gz
fix
-rw-r--r--ChangeLog3
-rw-r--r--kernel/dir.c27
-rw-r--r--kernel/inode.c8
3 files changed, 25 insertions, 13 deletions
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 <miklos@szeredi.hu>
* 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