Skip to content

Commit c8ae067

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: "Fixes for crap of assorted ages: EOPENSTALE one is 4.2+, autofs one is 4.6, d_walk - 3.2+. The atomic_open() and coredump ones are regressions from this window" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: coredump: fix dumping through pipes fix a regression in atomic_open() fix d_walk()/non-delayed __d_free() race autofs braino fix for do_last() fix EOPENSTALE bug in do_last()
2 parents 2051877 + 1607f09 commit c8ae067

File tree

7 files changed

+24
-52
lines changed

7 files changed

+24
-52
lines changed

arch/powerpc/platforms/cell/spufs/coredump.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
172172
if (rc < 0)
173173
goto out;
174174

175-
skip = roundup(cprm->file->f_pos - total + sz, 4) - cprm->file->f_pos;
175+
skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
176176
if (!dump_skip(cprm, skip))
177177
goto Eio;
178178
out:

fs/binfmt_elf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2275,7 +2275,7 @@ static int elf_core_dump(struct coredump_params *cprm)
22752275
goto end_coredump;
22762276

22772277
/* Align to page */
2278-
if (!dump_skip(cprm, dataoff - cprm->file->f_pos))
2278+
if (!dump_skip(cprm, dataoff - cprm->pos))
22792279
goto end_coredump;
22802280

22812281
for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;

fs/binfmt_elf_fdpic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
17871787
goto end_coredump;
17881788
}
17891789

1790-
if (!dump_skip(cprm, dataoff - cprm->file->f_pos))
1790+
if (!dump_skip(cprm, dataoff - cprm->pos))
17911791
goto end_coredump;
17921792

17931793
if (!elf_fdpic_dump_segments(cprm))

fs/coredump.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr)
794794
return 0;
795795
file->f_pos = pos;
796796
cprm->written += n;
797+
cprm->pos += n;
797798
nr -= n;
798799
}
799800
return 1;
@@ -808,6 +809,7 @@ int dump_skip(struct coredump_params *cprm, size_t nr)
808809
if (dump_interrupted() ||
809810
file->f_op->llseek(file, nr, SEEK_CUR) < 0)
810811
return 0;
812+
cprm->pos += nr;
811813
return 1;
812814
} else {
813815
while (nr > PAGE_SIZE) {
@@ -822,7 +824,7 @@ EXPORT_SYMBOL(dump_skip);
822824

823825
int dump_align(struct coredump_params *cprm, int align)
824826
{
825-
unsigned mod = cprm->file->f_pos & (align - 1);
827+
unsigned mod = cprm->pos & (align - 1);
826828
if (align & (align - 1))
827829
return 0;
828830
return mod ? dump_skip(cprm, align - mod) : 1;

fs/dcache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,7 +1636,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
16361636
struct dentry *dentry = __d_alloc(parent->d_sb, name);
16371637
if (!dentry)
16381638
return NULL;
1639-
1639+
dentry->d_flags |= DCACHE_RCUACCESS;
16401640
spin_lock(&parent->d_lock);
16411641
/*
16421642
* don't need child lock because it is not subject
@@ -2358,7 +2358,6 @@ static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
23582358
{
23592359
BUG_ON(!d_unhashed(entry));
23602360
hlist_bl_lock(b);
2361-
entry->d_flags |= DCACHE_RCUACCESS;
23622361
hlist_bl_add_head_rcu(&entry->d_hash, b);
23632362
hlist_bl_unlock(b);
23642363
}
@@ -2843,6 +2842,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
28432842
/* ... and switch them in the tree */
28442843
if (IS_ROOT(dentry)) {
28452844
/* splicing a tree */
2845+
dentry->d_flags |= DCACHE_RCUACCESS;
28462846
dentry->d_parent = target->d_parent;
28472847
target->d_parent = target;
28482848
list_del_init(&target->d_child);

fs/namei.c

Lines changed: 15 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3030,9 +3030,13 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
30303030
}
30313031
if (*opened & FILE_CREATED)
30323032
fsnotify_create(dir, dentry);
3033-
path->dentry = dentry;
3034-
path->mnt = nd->path.mnt;
3035-
return 1;
3033+
if (unlikely(d_is_negative(dentry))) {
3034+
error = -ENOENT;
3035+
} else {
3036+
path->dentry = dentry;
3037+
path->mnt = nd->path.mnt;
3038+
return 1;
3039+
}
30363040
}
30373041
}
30383042
dput(dentry);
@@ -3201,9 +3205,7 @@ static int do_last(struct nameidata *nd,
32013205
int acc_mode = op->acc_mode;
32023206
unsigned seq;
32033207
struct inode *inode;
3204-
struct path save_parent = { .dentry = NULL, .mnt = NULL };
32053208
struct path path;
3206-
bool retried = false;
32073209
int error;
32083210

32093211
nd->flags &= ~LOOKUP_PARENT;
@@ -3246,7 +3248,6 @@ static int do_last(struct nameidata *nd,
32463248
return -EISDIR;
32473249
}
32483250

3249-
retry_lookup:
32503251
if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
32513252
error = mnt_want_write(nd->path.mnt);
32523253
if (!error)
@@ -3298,6 +3299,10 @@ static int do_last(struct nameidata *nd,
32983299
got_write = false;
32993300
}
33003301

3302+
error = follow_managed(&path, nd);
3303+
if (unlikely(error < 0))
3304+
return error;
3305+
33013306
if (unlikely(d_is_negative(path.dentry))) {
33023307
path_to_nameidata(&path, nd);
33033308
return -ENOENT;
@@ -3313,10 +3318,6 @@ static int do_last(struct nameidata *nd,
33133318
return -EEXIST;
33143319
}
33153320

3316-
error = follow_managed(&path, nd);
3317-
if (unlikely(error < 0))
3318-
return error;
3319-
33203321
seq = 0; /* out of RCU mode, so the value doesn't matter */
33213322
inode = d_backing_inode(path.dentry);
33223323
finish_lookup:
@@ -3327,23 +3328,14 @@ static int do_last(struct nameidata *nd,
33273328
if (unlikely(error))
33283329
return error;
33293330

3330-
if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
3331-
path_to_nameidata(&path, nd);
3332-
} else {
3333-
save_parent.dentry = nd->path.dentry;
3334-
save_parent.mnt = mntget(path.mnt);
3335-
nd->path.dentry = path.dentry;
3336-
3337-
}
3331+
path_to_nameidata(&path, nd);
33383332
nd->inode = inode;
33393333
nd->seq = seq;
33403334
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
33413335
finish_open:
33423336
error = complete_walk(nd);
3343-
if (error) {
3344-
path_put(&save_parent);
3337+
if (error)
33453338
return error;
3346-
}
33473339
audit_inode(nd->name, nd->path.dentry, 0);
33483340
error = -EISDIR;
33493341
if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
@@ -3366,13 +3358,9 @@ static int do_last(struct nameidata *nd,
33663358
goto out;
33673359
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
33683360
error = vfs_open(&nd->path, file, current_cred());
3369-
if (!error) {
3370-
*opened |= FILE_OPENED;
3371-
} else {
3372-
if (error == -EOPENSTALE)
3373-
goto stale_open;
3361+
if (error)
33743362
goto out;
3375-
}
3363+
*opened |= FILE_OPENED;
33763364
opened:
33773365
error = open_check_o_direct(file);
33783366
if (!error)
@@ -3388,26 +3376,7 @@ static int do_last(struct nameidata *nd,
33883376
}
33893377
if (got_write)
33903378
mnt_drop_write(nd->path.mnt);
3391-
path_put(&save_parent);
33923379
return error;
3393-
3394-
stale_open:
3395-
/* If no saved parent or already retried then can't retry */
3396-
if (!save_parent.dentry || retried)
3397-
goto out;
3398-
3399-
BUG_ON(save_parent.dentry != dir);
3400-
path_put(&nd->path);
3401-
nd->path = save_parent;
3402-
nd->inode = dir->d_inode;
3403-
save_parent.mnt = NULL;
3404-
save_parent.dentry = NULL;
3405-
if (got_write) {
3406-
mnt_drop_write(nd->path.mnt);
3407-
got_write = false;
3408-
}
3409-
retried = true;
3410-
goto retry_lookup;
34113380
}
34123381

34133382
static int do_tmpfile(struct nameidata *nd, unsigned flags,

include/linux/binfmts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct coredump_params {
6565
unsigned long limit;
6666
unsigned long mm_flags;
6767
loff_t written;
68+
loff_t pos;
6869
};
6970

7071
/*

0 commit comments

Comments
 (0)