aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_aout.c49
-rw-r--r--fs/binfmt_elf.c52
-rw-r--r--fs/binfmt_elf_fdpic.c54
-rw-r--r--include/linux/coredump.h41
4 files changed, 79 insertions, 117 deletions
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index d2f8872dd767..15d80bb35d6f 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -24,6 +24,7 @@
24#include <linux/binfmts.h> 24#include <linux/binfmts.h>
25#include <linux/personality.h> 25#include <linux/personality.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/coredump.h>
27 28
28#include <asm/system.h> 29#include <asm/system.h>
29#include <asm/uaccess.h> 30#include <asm/uaccess.h>
@@ -60,42 +61,6 @@ static int set_brk(unsigned long start, unsigned long end)
60} 61}
61 62
62/* 63/*
63 * These are the only things you should do on a core-file: use only these
64 * macros to write out all the necessary info.
65 */
66
67static int dump_write(struct file *file, const void *addr, int nr)
68{
69 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
70}
71
72static int dump_seek(struct file *file, loff_t off)
73{
74 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
75 if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
76 return 0;
77 } else {
78 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
79 if (!buf)
80 return 0;
81 while (off > 0) {
82 unsigned long n = off;
83 if (n > PAGE_SIZE)
84 n = PAGE_SIZE;
85 if (!dump_write(file, buf, n))
86 return 0;
87 off -= n;
88 }
89 free_page((unsigned long)buf);
90 }
91 return 1;
92}
93
94#define DUMP_WRITE(addr, nr) \
95 if (!dump_write(file, (void *)(addr), (nr))) \
96 goto end_coredump;
97
98/*
99 * Routine writes a core dump image in the current directory. 64 * Routine writes a core dump image in the current directory.
100 * Currently only a stub-function. 65 * Currently only a stub-function.
101 * 66 *
@@ -146,7 +111,8 @@ static int aout_core_dump(struct coredump_params *cprm)
146 111
147 set_fs(KERNEL_DS); 112 set_fs(KERNEL_DS);
148/* struct user */ 113/* struct user */
149 DUMP_WRITE(&dump,sizeof(dump)); 114 if (!dump_write(file, &dump, sizeof(dump)))
115 goto end_coredump;
150/* Now dump all of the user data. Include malloced stuff as well */ 116/* Now dump all of the user data. Include malloced stuff as well */
151 if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump))) 117 if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump)))
152 goto end_coredump; 118 goto end_coredump;
@@ -156,17 +122,20 @@ static int aout_core_dump(struct coredump_params *cprm)
156 if (dump.u_dsize != 0) { 122 if (dump.u_dsize != 0) {
157 dump_start = START_DATA(dump); 123 dump_start = START_DATA(dump);
158 dump_size = dump.u_dsize << PAGE_SHIFT; 124 dump_size = dump.u_dsize << PAGE_SHIFT;
159 DUMP_WRITE(dump_start,dump_size); 125 if (!dump_write(file, dump_start, dump_size))
126 goto end_coredump;
160 } 127 }
161/* Now prepare to dump the stack area */ 128/* Now prepare to dump the stack area */
162 if (dump.u_ssize != 0) { 129 if (dump.u_ssize != 0) {
163 dump_start = START_STACK(dump); 130 dump_start = START_STACK(dump);
164 dump_size = dump.u_ssize << PAGE_SHIFT; 131 dump_size = dump.u_ssize << PAGE_SHIFT;
165 DUMP_WRITE(dump_start,dump_size); 132 if (!dump_write(file, dump_start, dump_size))
133 goto end_coredump;
166 } 134 }
167/* Finally dump the task struct. Not be used by gdb, but could be useful */ 135/* Finally dump the task struct. Not be used by gdb, but could be useful */
168 set_fs(KERNEL_DS); 136 set_fs(KERNEL_DS);
169 DUMP_WRITE(current,sizeof(*current)); 137 if (!dump_write(file, current, sizeof(*current)))
138 goto end_coredump;
170end_coredump: 139end_coredump:
171 set_fs(fs); 140 set_fs(fs);
172 return has_dumped; 141 return has_dumped;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fd5b2ea5d299..0bcfbb05c32d 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -31,6 +31,7 @@
31#include <linux/random.h> 31#include <linux/random.h>
32#include <linux/elf.h> 32#include <linux/elf.h>
33#include <linux/utsname.h> 33#include <linux/utsname.h>
34#include <linux/coredump.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
35#include <asm/param.h> 36#include <asm/param.h>
36#include <asm/page.h> 37#include <asm/page.h>
@@ -1085,36 +1086,6 @@ out:
1085 * Modelled on fs/exec.c:aout_core_dump() 1086 * Modelled on fs/exec.c:aout_core_dump()
1086 * Jeremy Fitzhardinge <jeremy@sw.oz.au> 1087 * Jeremy Fitzhardinge <jeremy@sw.oz.au>
1087 */ 1088 */
1088/*
1089 * These are the only things you should do on a core-file: use only these
1090 * functions to write out all the necessary info.
1091 */
1092static int dump_write(struct file *file, const void *addr, int nr)
1093{
1094 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
1095}
1096
1097static int dump_seek(struct file *file, loff_t off)
1098{
1099 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
1100 if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
1101 return 0;
1102 } else {
1103 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
1104 if (!buf)
1105 return 0;
1106 while (off > 0) {
1107 unsigned long n = off;
1108 if (n > PAGE_SIZE)
1109 n = PAGE_SIZE;
1110 if (!dump_write(file, buf, n))
1111 return 0;
1112 off -= n;
1113 }
1114 free_page((unsigned long)buf);
1115 }
1116 return 1;
1117}
1118 1089
1119/* 1090/*
1120 * Decide what to dump of a segment, part, all or none. 1091 * Decide what to dump of a segment, part, all or none.
@@ -1249,11 +1220,6 @@ static int writenote(struct memelfnote *men, struct file *file,
1249} 1220}
1250#undef DUMP_WRITE 1221#undef DUMP_WRITE
1251 1222
1252#define DUMP_WRITE(addr, nr) \
1253 if ((size += (nr)) > cprm->limit || \
1254 !dump_write(cprm->file, (addr), (nr))) \
1255 goto end_coredump;
1256
1257static void fill_elf_header(struct elfhdr *elf, int segs, 1223static void fill_elf_header(struct elfhdr *elf, int segs,
1258 u16 machine, u32 flags, u8 osabi) 1224 u16 machine, u32 flags, u8 osabi)
1259{ 1225{
@@ -1934,7 +1900,10 @@ static int elf_core_dump(struct coredump_params *cprm)
1934 fs = get_fs(); 1900 fs = get_fs();
1935 set_fs(KERNEL_DS); 1901 set_fs(KERNEL_DS);
1936 1902
1937 DUMP_WRITE(elf, sizeof(*elf)); 1903 size += sizeof(*elf);
1904 if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
1905 goto end_coredump;
1906
1938 offset += sizeof(*elf); /* Elf header */ 1907 offset += sizeof(*elf); /* Elf header */
1939 offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */ 1908 offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */
1940 foffset = offset; 1909 foffset = offset;
@@ -1948,7 +1917,11 @@ static int elf_core_dump(struct coredump_params *cprm)
1948 1917
1949 fill_elf_note_phdr(&phdr, sz, offset); 1918 fill_elf_note_phdr(&phdr, sz, offset);
1950 offset += sz; 1919 offset += sz;
1951 DUMP_WRITE(&phdr, sizeof(phdr)); 1920
1921 size += sizeof(phdr);
1922 if (size > cprm->limit
1923 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1924 goto end_coredump;
1952 } 1925 }
1953 1926
1954 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); 1927 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
@@ -1979,7 +1952,10 @@ static int elf_core_dump(struct coredump_params *cprm)
1979 phdr.p_flags |= PF_X; 1952 phdr.p_flags |= PF_X;
1980 phdr.p_align = ELF_EXEC_PAGESIZE; 1953 phdr.p_align = ELF_EXEC_PAGESIZE;
1981 1954
1982 DUMP_WRITE(&phdr, sizeof(phdr)); 1955 size += sizeof(phdr);
1956 if (size > cprm->limit
1957 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1958 goto end_coredump;
1983 } 1959 }
1984 1960
1985#ifdef ELF_CORE_WRITE_EXTRA_PHDRS 1961#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 32d9b44c3cb9..63edf40b569b 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -34,6 +34,7 @@
34#include <linux/elf.h> 34#include <linux/elf.h>
35#include <linux/elf-fdpic.h> 35#include <linux/elf-fdpic.h>
36#include <linux/elfcore.h> 36#include <linux/elfcore.h>
37#include <linux/coredump.h>
37 38
38#include <asm/uaccess.h> 39#include <asm/uaccess.h>
39#include <asm/param.h> 40#include <asm/param.h>
@@ -1216,37 +1217,6 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1216#ifdef CONFIG_ELF_CORE 1217#ifdef CONFIG_ELF_CORE
1217 1218
1218/* 1219/*
1219 * These are the only things you should do on a core-file: use only these
1220 * functions to write out all the necessary info.
1221 */
1222static int dump_write(struct file *file, const void *addr, int nr)
1223{
1224 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
1225}
1226
1227static int dump_seek(struct file *file, loff_t off)
1228{
1229 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
1230 if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
1231 return 0;
1232 } else {
1233 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
1234 if (!buf)
1235 return 0;
1236 while (off > 0) {
1237 unsigned long n = off;
1238 if (n > PAGE_SIZE)
1239 n = PAGE_SIZE;
1240 if (!dump_write(file, buf, n))
1241 return 0;
1242 off -= n;
1243 }
1244 free_page((unsigned long)buf);
1245 }
1246 return 1;
1247}
1248
1249/*
1250 * Decide whether a segment is worth dumping; default is yes to be 1220 * Decide whether a segment is worth dumping; default is yes to be
1251 * sure (missing info is worse than too much; etc). 1221 * sure (missing info is worse than too much; etc).
1252 * Personally I'd include everything, and use the coredump limit... 1222 * Personally I'd include everything, and use the coredump limit...
@@ -1354,11 +1324,6 @@ static int writenote(struct memelfnote *men, struct file *file,
1354} 1324}
1355#undef DUMP_WRITE 1325#undef DUMP_WRITE
1356 1326
1357#define DUMP_WRITE(addr, nr) \
1358 if ((size += (nr)) > cprm->limit || \
1359 !dump_write(cprm->file, (addr), (nr))) \
1360 goto end_coredump;
1361
1362static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) 1327static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
1363{ 1328{
1364 memcpy(elf->e_ident, ELFMAG, SELFMAG); 1329 memcpy(elf->e_ident, ELFMAG, SELFMAG);
@@ -1743,7 +1708,11 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1743 fs = get_fs(); 1708 fs = get_fs();
1744 set_fs(KERNEL_DS); 1709 set_fs(KERNEL_DS);
1745 1710
1746 DUMP_WRITE(elf, sizeof(*elf)); 1711 size += sizeof(*elf);
1712 if (size > cprm->limit
1713 || !dump_write(cprm->file, elf, sizeof(*elf)))
1714 goto end_coredump;
1715
1747 offset += sizeof(*elf); /* Elf header */ 1716 offset += sizeof(*elf); /* Elf header */
1748 offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */ 1717 offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */
1749 foffset = offset; 1718 foffset = offset;
@@ -1760,7 +1729,11 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1760 1729
1761 fill_elf_note_phdr(&phdr, sz, offset); 1730 fill_elf_note_phdr(&phdr, sz, offset);
1762 offset += sz; 1731 offset += sz;
1763 DUMP_WRITE(&phdr, sizeof(phdr)); 1732
1733 size += sizeof(phdr);
1734 if (size > cprm->limit
1735 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1736 goto end_coredump;
1764 } 1737 }
1765 1738
1766 /* Page-align dumped data */ 1739 /* Page-align dumped data */
@@ -1794,7 +1767,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
1794 phdr.p_flags |= PF_X; 1767 phdr.p_flags |= PF_X;
1795 phdr.p_align = ELF_EXEC_PAGESIZE; 1768 phdr.p_align = ELF_EXEC_PAGESIZE;
1796 1769
1797 DUMP_WRITE(&phdr, sizeof(phdr)); 1770 size += sizeof(phdr);
1771 if (size > cprm->limit
1772 || !dump_write(cprm->file, &phdr, sizeof(phdr)))
1773 goto end_coredump;
1798 } 1774 }
1799 1775
1800#ifdef ELF_CORE_WRITE_EXTRA_PHDRS 1776#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
new file mode 100644
index 000000000000..b3c91d7cede4
--- /dev/null
+++ b/include/linux/coredump.h
@@ -0,0 +1,41 @@
1#ifndef _LINUX_COREDUMP_H
2#define _LINUX_COREDUMP_H
3
4#include <linux/types.h>
5#include <linux/mm.h>
6#include <linux/fs.h>
7
8/*
9 * These are the only things you should do on a core-file: use only these
10 * functions to write out all the necessary info.
11 */
12static inline int dump_write(struct file *file, const void *addr, int nr)
13{
14 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
15}
16
17static inline int dump_seek(struct file *file, loff_t off)
18{
19 if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
20 if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
21 return 0;
22 } else {
23 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
24
25 if (!buf)
26 return 0;
27 while (off > 0) {
28 unsigned long n = off;
29
30 if (n > PAGE_SIZE)
31 n = PAGE_SIZE;
32 if (!dump_write(file, buf, n))
33 return 0;
34 off -= n;
35 }
36 free_page((unsigned long)buf);
37 }
38 return 1;
39}
40
41#endif /* _LINUX_COREDUMP_H */