diff options
author | Mateusz Guzik <mguzik@redhat.com> | 2016-06-05 17:14:14 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-06-07 22:07:09 -0400 |
commit | 1607f09c226d1378439c411baaaa020042750338 (patch) | |
tree | 664e5239468f2bc978c6b8c6f2fb64904c20f7e9 | |
parent | a01e718f7241c53f564402f7acff373eed5bd166 (diff) |
coredump: fix dumping through pipes
The offset in the core file used to be tracked with ->written field of
the coredump_params structure. The field was retired in favour of
file->f_pos.
However, ->f_pos is not maintained for pipes which leads to breakage.
Restore explicit tracking of the offset in coredump_params. Introduce
->pos field for this purpose since ->written was already reused.
Fixes: a00839395103 ("get rid of coredump_params->written").
Reported-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Signed-off-by: Mateusz Guzik <mguzik@redhat.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/coredump.c | 2 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 2 | ||||
-rw-r--r-- | fs/coredump.c | 4 | ||||
-rw-r--r-- | include/linux/binfmts.h | 1 |
5 files changed, 7 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 84fb984f29c1..85c85eb3e245 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c | |||
@@ -172,7 +172,7 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i, | |||
172 | if (rc < 0) | 172 | if (rc < 0) |
173 | goto out; | 173 | goto out; |
174 | 174 | ||
175 | skip = roundup(cprm->file->f_pos - total + sz, 4) - cprm->file->f_pos; | 175 | skip = roundup(cprm->pos - total + sz, 4) - cprm->pos; |
176 | if (!dump_skip(cprm, skip)) | 176 | if (!dump_skip(cprm, skip)) |
177 | goto Eio; | 177 | goto Eio; |
178 | out: | 178 | out: |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e158b22ef32f..a7a28110dc80 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -2275,7 +2275,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2275 | goto end_coredump; | 2275 | goto end_coredump; |
2276 | 2276 | ||
2277 | /* Align to page */ | 2277 | /* Align to page */ |
2278 | if (!dump_skip(cprm, dataoff - cprm->file->f_pos)) | 2278 | if (!dump_skip(cprm, dataoff - cprm->pos)) |
2279 | goto end_coredump; | 2279 | goto end_coredump; |
2280 | 2280 | ||
2281 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; | 2281 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 71ade0e556b7..203589311bf8 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1787,7 +1787,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) | |||
1787 | goto end_coredump; | 1787 | goto end_coredump; |
1788 | } | 1788 | } |
1789 | 1789 | ||
1790 | if (!dump_skip(cprm, dataoff - cprm->file->f_pos)) | 1790 | if (!dump_skip(cprm, dataoff - cprm->pos)) |
1791 | goto end_coredump; | 1791 | goto end_coredump; |
1792 | 1792 | ||
1793 | if (!elf_fdpic_dump_segments(cprm)) | 1793 | if (!elf_fdpic_dump_segments(cprm)) |
diff --git a/fs/coredump.c b/fs/coredump.c index 38a7ab87e10a..281b768000e6 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
@@ -794,6 +794,7 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr) | |||
794 | return 0; | 794 | return 0; |
795 | file->f_pos = pos; | 795 | file->f_pos = pos; |
796 | cprm->written += n; | 796 | cprm->written += n; |
797 | cprm->pos += n; | ||
797 | nr -= n; | 798 | nr -= n; |
798 | } | 799 | } |
799 | return 1; | 800 | return 1; |
@@ -808,6 +809,7 @@ int dump_skip(struct coredump_params *cprm, size_t nr) | |||
808 | if (dump_interrupted() || | 809 | if (dump_interrupted() || |
809 | file->f_op->llseek(file, nr, SEEK_CUR) < 0) | 810 | file->f_op->llseek(file, nr, SEEK_CUR) < 0) |
810 | return 0; | 811 | return 0; |
812 | cprm->pos += nr; | ||
811 | return 1; | 813 | return 1; |
812 | } else { | 814 | } else { |
813 | while (nr > PAGE_SIZE) { | 815 | while (nr > PAGE_SIZE) { |
@@ -822,7 +824,7 @@ EXPORT_SYMBOL(dump_skip); | |||
822 | 824 | ||
823 | int dump_align(struct coredump_params *cprm, int align) | 825 | int dump_align(struct coredump_params *cprm, int align) |
824 | { | 826 | { |
825 | unsigned mod = cprm->file->f_pos & (align - 1); | 827 | unsigned mod = cprm->pos & (align - 1); |
826 | if (align & (align - 1)) | 828 | if (align & (align - 1)) |
827 | return 0; | 829 | return 0; |
828 | return mod ? dump_skip(cprm, align - mod) : 1; | 830 | return mod ? dump_skip(cprm, align - mod) : 1; |
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 576e4639ca60..314b3caa701c 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h | |||
@@ -65,6 +65,7 @@ struct coredump_params { | |||
65 | unsigned long limit; | 65 | unsigned long limit; |
66 | unsigned long mm_flags; | 66 | unsigned long mm_flags; |
67 | loff_t written; | 67 | loff_t written; |
68 | loff_t pos; | ||
68 | }; | 69 | }; |
69 | 70 | ||
70 | /* | 71 | /* |