Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50322fe7 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds
Browse files

[PATCH] fuse: fix bug in negative lookup



If negative entries (nodeid == 0) were sent in reply to LOOKUP requests,
two bugs could be triggered:

- looking up a negative entry would return -EIO,

- revaildate on an entry which turned negative would send a FORGET
  request with zero nodeid, which would cause an abort() in the
  library.

The above would only happen if the 'negative_timeout=N' option was used,
otherwise lookups reply -ENOENT, which worked correctly.

Signed-off-by: default avatarMiklos Szeredi <miklos@szeredi.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 511030bc
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -111,6 +111,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)

		/* Doesn't hurt to "reset" the validity timeout */
		fuse_invalidate_entry_cache(entry);

		/* For negative dentries, always do a fresh lookup */
		if (!inode)
			return 0;

@@ -122,6 +124,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
		fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
		request_send(fc, req);
		err = req->out.h.error;
		/* Zero nodeid is same as -ENOENT */
		if (!err && !outarg.nodeid)
			err = -ENOENT;
		if (!err) {
			struct fuse_inode *fi = get_fuse_inode(inode);
			if (outarg.nodeid != get_node_id(inode)) {
@@ -190,8 +195,9 @@ 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)) ||
		     !valid_mode(outarg.attr.mode)))
	/* Zero nodeid is same as -ENOENT, but with valid timeout */
	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,