From: Al Viro Date: Fri, 29 Oct 2010 07:30:42 +0000 (-0400) Subject: fix open/umount race X-Git-Tag: upstream/snapshot3+hdmi~12586^2~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d893f1bc2a9f0f7dcb4b433452c59f9bedac0d7d;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git fix open/umount race nameidata_to_filp() drops nd->path or transfers it to opened file. In the former case it's a Bad Idea(tm) to do mnt_drop_write() on nd->path.mnt, since we might race with umount and vfsmount in question might be gone already. Fix: don't drop it, then... IOW, have nameidata_to_filp() grab nd->path in case it transfers it to file and do path_drop() in callers. After they are through with accessing nd->path... Reported-by: Miklos Szeredi Signed-off-by: Al Viro --- diff --git a/fs/namei.c b/fs/namei.c index f7dbc06..5362af9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1574,6 +1574,7 @@ static struct file *finish_open(struct nameidata *nd, */ if (will_truncate) mnt_drop_write(nd->path.mnt); + path_put(&nd->path); return filp; exit: @@ -1675,6 +1676,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, } filp = nameidata_to_filp(nd); mnt_drop_write(nd->path.mnt); + path_put(&nd->path); if (!IS_ERR(filp)) { error = ima_file_check(filp, acc_mode); if (error) { diff --git a/fs/open.c b/fs/open.c index d74e198..4197b9e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -786,11 +786,11 @@ struct file *nameidata_to_filp(struct nameidata *nd) /* Pick up the filp from the open intent */ filp = nd->intent.open.file; /* Has the filesystem initialised the file for us? */ - if (filp->f_path.dentry == NULL) + if (filp->f_path.dentry == NULL) { + path_get(&nd->path); filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, NULL, cred); - else - path_put(&nd->path); + } return filp; }