diff options
-rw-r--r-- | fs/binfmt_aout.c | 49 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 52 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 54 | ||||
-rw-r--r-- | include/linux/coredump.h | 41 |
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 | |||
67 | static 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 | |||
72 | static 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; | ||
170 | end_coredump: | 139 | end_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 | */ | ||
1092 | static 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 | |||
1097 | static 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 | |||
1257 | static void fill_elf_header(struct elfhdr *elf, int segs, | 1223 | static 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 | */ | ||
1222 | static 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 | |||
1227 | static 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 | |||
1362 | static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) | 1327 | static 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 | */ | ||
12 | static 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 | |||
17 | static 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 */ | ||