aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2016-05-11 18:16:37 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-05-12 16:55:50 -0400
commit2c4cb04300fa160e9d78335c74184c4e66a56437 (patch)
treeff36e8066fe5092e23cc2519adfd976eb54bc0b8
parenta00839395103d5e2d132a6c4a9680256580ed3d1 (diff)
coredump: only charge written data against RLIMIT_CORE
Commit 9b56d54380ad ("dump_skip(): dump_seek() replacement taking coredump_params") introduced a regression with regard to RLIMIT_CORE. Previously, when a core dump was sparse, only the data that was actually written out would count against the limit. Now, the sparse ranges are also included, which leads to truncated core dumps when the actual disk usage is still well below the limit. Restore the old behavior by only counting what gets emitted and ignoring what gets skipped. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/coredump.c5
-rw-r--r--include/linux/binfmts.h1
2 files changed, 3 insertions, 3 deletions
diff --git a/fs/coredump.c b/fs/coredump.c
index 9db0c514438e..492c2db25dc9 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -782,7 +782,7 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr)
782 struct file *file = cprm->file; 782 struct file *file = cprm->file;
783 loff_t pos = file->f_pos; 783 loff_t pos = file->f_pos;
784 ssize_t n; 784 ssize_t n;
785 if (pos + nr > cprm->limit) 785 if (cprm->written + nr > cprm->limit)
786 return 0; 786 return 0;
787 while (nr) { 787 while (nr) {
788 if (dump_interrupted()) 788 if (dump_interrupted())
@@ -791,6 +791,7 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr)
791 if (n <= 0) 791 if (n <= 0)
792 return 0; 792 return 0;
793 file->f_pos = pos; 793 file->f_pos = pos;
794 cprm->written += n;
794 nr -= n; 795 nr -= n;
795 } 796 }
796 return 1; 797 return 1;
@@ -802,8 +803,6 @@ int dump_skip(struct coredump_params *cprm, size_t nr)
802 static char zeroes[PAGE_SIZE]; 803 static char zeroes[PAGE_SIZE];
803 struct file *file = cprm->file; 804 struct file *file = cprm->file;
804 if (file->f_op->llseek && file->f_op->llseek != no_llseek) { 805 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
805 if (file->f_pos + nr > cprm->limit)
806 return 0;
807 if (dump_interrupted() || 806 if (dump_interrupted() ||
808 file->f_op->llseek(file, nr, SEEK_CUR) < 0) 807 file->f_op->llseek(file, nr, SEEK_CUR) < 0)
809 return 0; 808 return 0;
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 39c6d6e1234e..576e4639ca60 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -64,6 +64,7 @@ struct coredump_params {
64 struct file *file; 64 struct file *file;
65 unsigned long limit; 65 unsigned long limit;
66 unsigned long mm_flags; 66 unsigned long mm_flags;
67 loff_t written;
67}; 68};
68 69
69/* 70/*