diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-11 15:53:38 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-11 15:53:38 -0800 |
commit | 2dab597441667d6c04451a7dcf215241ad4c74f6 (patch) | |
tree | f56a6f7fcabf3a9b82a5e77ef9c96268224efbd1 /fs/open.c | |
parent | d2478521afc20227658a10a8c5c2bf1a2aa615b3 (diff) | |
download | linux-stable-2dab597441667d6c04451a7dcf215241ad4c74f6.tar.gz linux-stable-2dab597441667d6c04451a7dcf215241ad4c74f6.tar.bz2 linux-stable-2dab597441667d6c04451a7dcf215241ad4c74f6.zip |
Fix possible filp_cachep memory corruption
In commit 31e6b01f4183 ("fs: rcu-walk for path lookup") we started doing
path lookup using RCU, which then falls back to a careful non-RCU lookup
in case of problems (LOOKUP_REVAL). So do_filp_open() has this "re-do
the lookup carefully" looping case.
However, that means that we must not release the open-intent file data
if we are going to loop around and use it once more!
Fix this by moving the release of the open-intent data to the function
that allocates it (do_filp_open() itself) rather than the helper
functions that can get called multiple times (finish_open() and
do_last()). This makes the logic for the lifetime of that field much
more obvious, and avoids the possible double free.
Reported-by: J. R. Okajima <hooanon05@yahoo.co.jp>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Cc: Nick Piggin <npiggin@kernel.dk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/open.c b/fs/open.c index e52389e1f05b..5a2c6ebc22b5 100644 --- a/fs/open.c +++ b/fs/open.c @@ -790,6 +790,8 @@ struct file *nameidata_to_filp(struct nameidata *nd) /* Pick up the filp from the open intent */ filp = nd->intent.open.file; + nd->intent.open.file = NULL; + /* Has the filesystem initialised the file for us? */ if (filp->f_path.dentry == NULL) { path_get(&nd->path); |