aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMateusz Guzik <mguzik@redhat.com>2016-06-05 17:14:14 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-06-07 22:07:09 -0400
commit1607f09c226d1378439c411baaaa020042750338 (patch)
tree664e5239468f2bc978c6b8c6f2fb64904c20f7e9
parenta01e718f7241c53f564402f7acff373eed5bd166 (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.c2
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/binfmt_elf_fdpic.c2
-rw-r--r--fs/coredump.c4
-rw-r--r--include/linux/binfmts.h1
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;
178out: 178out:
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
823int dump_align(struct coredump_params *cprm, int align) 825int 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/*