Skip to contentSkip to conversation

vfs: Don't leak a path when get_empty_filp in dentry_open

PATCH NAK Eric W. Biederman 2 participants 3 messages Jan 16, 2014 – Jan 17, 2014 VFS

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 vfs: Don't leak a path when get_empty_filp in dentry_open

Normally in dentry_open the passed in path is placed on the new filp removing the caller from needing to worry about it. In the rare case that we can not allocate a filp the path is not consumed. None of the callers of dentry_open call path_put in their error handling when dentry_open fails so call path_put for them on error and keep everyone's error handling simple.

---
 fs/open.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
fs/open.c +2 -0
index 4b3e1edf2fe4..0afa243941da 100644
@@ -843,6 +843,8 @@ struct file *dentry_open(const struct path *path, int flags,
 			put_filp(f);
 			f = ERR_PTR(error);
 		}
+	} else {
+		path_put(path);
 	}
 	return f;
 }
Signature · 1 line
1.7.5.4
maintainer NAK
#1 lore raw
Quoted 7 lines · Eric W. Biederman

Normally in dentry_open the passed in path is placed on the new filp removing the caller from needing to worry about it. In the rare case that we can not allocate a filp the path is not consumed. None of the callers of dentry_open call path_put in their error handling when dentry_open fails so call path_put for them on error and keep everyone's error handling simple.

You are misreading that code. _No_ path in dentry_open() drops that sucker, no matter whether we succeed or fail. do_dentry_open() grabs an extra reference on success, so those fput() on other failure exits just balance that.

The calling conventions are not "transfer the reference you held into struct file, caller must drop on failure"; it's "clone the reference into struct file; caller's reference remains in all cases".

IOW, you are looking for path_put() in error handling in callers, when in fact it's on common paths (and quite often in callers of callers of callers). Makes life simpler, actually. Try to convert it to your variant of calling conventions and you'll see that callers become more complex and brittle. As it is, this patch is simply broken - you'll get double path_put() out of it, not to mention the different treatment of refcounts depending on the kind of failure exit that had been taken.

NAK.

#2 lore raw
Quoted 9 lines · Al Viro
Quoted 7 lines · Eric W. Biederman

Normally in dentry_open the passed in path is placed on the new filp removing the caller from needing to worry about it. In the rare case that we can not allocate a filp the path is not consumed. None of the callers of dentry_open call path_put in their error handling when dentry_open fails so call path_put for them on error and keep everyone's error handling simple.

Quoted 4 lines

You are misreading that code. _No_ path in dentry_open() drops that sucker, no matter whether we succeed or fail. do_dentry_open() grabs an extra reference on success, so those fput() on other failure exits just balance that.

Yep you are right. My mistake. The weird code flow tricked me.

Eric