Skip to content

Commit 95c607d

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "A couple of fixes for bugs caught while digging in fs/namei.c. The first one is this cycle regression, the second is 3.11 and later" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: path_openat(): fix double fput() namei: d_is_negative() should be checked before ->d_seq validation
2 parents af64728 + f15133d commit 95c607d

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

fs/namei.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,7 @@ static int lookup_fast(struct nameidata *nd,
14151415
*/
14161416
if (nd->flags & LOOKUP_RCU) {
14171417
unsigned seq;
1418+
bool negative;
14181419
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
14191420
if (!dentry)
14201421
goto unlazy;
@@ -1424,8 +1425,11 @@ static int lookup_fast(struct nameidata *nd,
14241425
* the dentry name information from lookup.
14251426
*/
14261427
*inode = dentry->d_inode;
1428+
negative = d_is_negative(dentry);
14271429
if (read_seqcount_retry(&dentry->d_seq, seq))
14281430
return -ECHILD;
1431+
if (negative)
1432+
return -ENOENT;
14291433

14301434
/*
14311435
* This sequence count validates that the parent had no
@@ -1472,6 +1476,10 @@ static int lookup_fast(struct nameidata *nd,
14721476
goto need_lookup;
14731477
}
14741478

1479+
if (unlikely(d_is_negative(dentry))) {
1480+
dput(dentry);
1481+
return -ENOENT;
1482+
}
14751483
path->mnt = mnt;
14761484
path->dentry = dentry;
14771485
err = follow_managed(path, nd->flags);
@@ -1583,10 +1591,10 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
15831591
goto out_err;
15841592

15851593
inode = path->dentry->d_inode;
1594+
err = -ENOENT;
1595+
if (d_is_negative(path->dentry))
1596+
goto out_path_put;
15861597
}
1587-
err = -ENOENT;
1588-
if (d_is_negative(path->dentry))
1589-
goto out_path_put;
15901598

15911599
if (should_follow_link(path->dentry, follow)) {
15921600
if (nd->flags & LOOKUP_RCU) {
@@ -3036,14 +3044,13 @@ static int do_last(struct nameidata *nd, struct path *path,
30363044

30373045
BUG_ON(nd->flags & LOOKUP_RCU);
30383046
inode = path->dentry->d_inode;
3039-
finish_lookup:
3040-
/* we _can_ be in RCU mode here */
30413047
error = -ENOENT;
30423048
if (d_is_negative(path->dentry)) {
30433049
path_to_nameidata(path, nd);
30443050
goto out;
30453051
}
3046-
3052+
finish_lookup:
3053+
/* we _can_ be in RCU mode here */
30473054
if (should_follow_link(path->dentry, !symlink_ok)) {
30483055
if (nd->flags & LOOKUP_RCU) {
30493056
if (unlikely(nd->path.mnt != path->mnt ||
@@ -3226,7 +3233,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
32263233

32273234
if (unlikely(file->f_flags & __O_TMPFILE)) {
32283235
error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
3229-
goto out;
3236+
goto out2;
32303237
}
32313238

32323239
error = path_init(dfd, pathname, flags, nd);
@@ -3256,6 +3263,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
32563263
}
32573264
out:
32583265
path_cleanup(nd);
3266+
out2:
32593267
if (!(opened & FILE_OPENED)) {
32603268
BUG_ON(!error);
32613269
put_filp(file);

0 commit comments

Comments
 (0)