diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-05 15:32:35 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-09 00:16:22 -0500 |
commit | ecc8c7725e6c21528329b34acae2a1d64b3af89b (patch) | |
tree | ae1790c2ce0fe1c1f02e2bd0795b6636d65b4587 /fs/binfmt_elf.c | |
parent | 7d2f551f6dc933f87933e906e48583169bbc7c27 (diff) |
new helper: dump_emit()
dump_write() analog, takes core_dump_params instead of file,
keeps track of the amount written in cprm->written and checks for
cprm->limit. Start using it in binfmt_elf.c...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 60 |
1 files changed, 23 insertions, 37 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 501c8a4d6eb1..00fd9c969a27 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1225,35 +1225,23 @@ static int notesize(struct memelfnote *en) | |||
1225 | return sz; | 1225 | return sz; |
1226 | } | 1226 | } |
1227 | 1227 | ||
1228 | #define DUMP_WRITE(addr, nr, foffset) \ | 1228 | static int alignfile(struct coredump_params *cprm) |
1229 | do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0) | ||
1230 | |||
1231 | static int alignfile(struct file *file, loff_t *foffset) | ||
1232 | { | 1229 | { |
1233 | static const char buf[4] = { 0, }; | 1230 | static const char buf[4] = { 0, }; |
1234 | DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset); | 1231 | return dump_emit(cprm, buf, roundup(cprm->written, 4) - cprm->written); |
1235 | return 1; | ||
1236 | } | 1232 | } |
1237 | 1233 | ||
1238 | static int writenote(struct memelfnote *men, struct file *file, | 1234 | static int writenote(struct memelfnote *men, struct coredump_params *cprm) |
1239 | loff_t *foffset) | ||
1240 | { | 1235 | { |
1241 | struct elf_note en; | 1236 | struct elf_note en; |
1242 | en.n_namesz = strlen(men->name) + 1; | 1237 | en.n_namesz = strlen(men->name) + 1; |
1243 | en.n_descsz = men->datasz; | 1238 | en.n_descsz = men->datasz; |
1244 | en.n_type = men->type; | 1239 | en.n_type = men->type; |
1245 | 1240 | ||
1246 | DUMP_WRITE(&en, sizeof(en), foffset); | 1241 | return dump_emit(cprm, &en, sizeof(en)) && |
1247 | DUMP_WRITE(men->name, en.n_namesz, foffset); | 1242 | dump_emit(cprm, men->name, en.n_namesz) && alignfile(cprm) && |
1248 | if (!alignfile(file, foffset)) | 1243 | dump_emit(cprm, men->data, men->datasz) && alignfile(cprm); |
1249 | return 0; | ||
1250 | DUMP_WRITE(men->data, men->datasz, foffset); | ||
1251 | if (!alignfile(file, foffset)) | ||
1252 | return 0; | ||
1253 | |||
1254 | return 1; | ||
1255 | } | 1244 | } |
1256 | #undef DUMP_WRITE | ||
1257 | 1245 | ||
1258 | static void fill_elf_header(struct elfhdr *elf, int segs, | 1246 | static void fill_elf_header(struct elfhdr *elf, int segs, |
1259 | u16 machine, u32 flags) | 1247 | u16 machine, u32 flags) |
@@ -1702,7 +1690,7 @@ static size_t get_note_info_size(struct elf_note_info *info) | |||
1702 | * process-wide notes are interleaved after the first thread-specific note. | 1690 | * process-wide notes are interleaved after the first thread-specific note. |
1703 | */ | 1691 | */ |
1704 | static int write_note_info(struct elf_note_info *info, | 1692 | static int write_note_info(struct elf_note_info *info, |
1705 | struct file *file, loff_t *foffset) | 1693 | struct coredump_params *cprm) |
1706 | { | 1694 | { |
1707 | bool first = 1; | 1695 | bool first = 1; |
1708 | struct elf_thread_core_info *t = info->thread; | 1696 | struct elf_thread_core_info *t = info->thread; |
@@ -1710,22 +1698,22 @@ static int write_note_info(struct elf_note_info *info, | |||
1710 | do { | 1698 | do { |
1711 | int i; | 1699 | int i; |
1712 | 1700 | ||
1713 | if (!writenote(&t->notes[0], file, foffset)) | 1701 | if (!writenote(&t->notes[0], cprm)) |
1714 | return 0; | 1702 | return 0; |
1715 | 1703 | ||
1716 | if (first && !writenote(&info->psinfo, file, foffset)) | 1704 | if (first && !writenote(&info->psinfo, cprm)) |
1717 | return 0; | 1705 | return 0; |
1718 | if (first && !writenote(&info->signote, file, foffset)) | 1706 | if (first && !writenote(&info->signote, cprm)) |
1719 | return 0; | 1707 | return 0; |
1720 | if (first && !writenote(&info->auxv, file, foffset)) | 1708 | if (first && !writenote(&info->auxv, cprm)) |
1721 | return 0; | 1709 | return 0; |
1722 | if (first && info->files.data && | 1710 | if (first && info->files.data && |
1723 | !writenote(&info->files, file, foffset)) | 1711 | !writenote(&info->files, cprm)) |
1724 | return 0; | 1712 | return 0; |
1725 | 1713 | ||
1726 | for (i = 1; i < info->thread_notes; ++i) | 1714 | for (i = 1; i < info->thread_notes; ++i) |
1727 | if (t->notes[i].data && | 1715 | if (t->notes[i].data && |
1728 | !writenote(&t->notes[i], file, foffset)) | 1716 | !writenote(&t->notes[i], cprm)) |
1729 | return 0; | 1717 | return 0; |
1730 | 1718 | ||
1731 | first = 0; | 1719 | first = 0; |
@@ -1935,13 +1923,13 @@ static size_t get_note_info_size(struct elf_note_info *info) | |||
1935 | } | 1923 | } |
1936 | 1924 | ||
1937 | static int write_note_info(struct elf_note_info *info, | 1925 | static int write_note_info(struct elf_note_info *info, |
1938 | struct file *file, loff_t *foffset) | 1926 | struct coredump_params *cprm) |
1939 | { | 1927 | { |
1940 | int i; | 1928 | int i; |
1941 | struct list_head *t; | 1929 | struct list_head *t; |
1942 | 1930 | ||
1943 | for (i = 0; i < info->numnote; i++) | 1931 | for (i = 0; i < info->numnote; i++) |
1944 | if (!writenote(info->notes + i, file, foffset)) | 1932 | if (!writenote(info->notes + i, cprm)) |
1945 | return 0; | 1933 | return 0; |
1946 | 1934 | ||
1947 | /* write out the thread status notes section */ | 1935 | /* write out the thread status notes section */ |
@@ -1950,7 +1938,7 @@ static int write_note_info(struct elf_note_info *info, | |||
1950 | list_entry(t, struct elf_thread_status, list); | 1938 | list_entry(t, struct elf_thread_status, list); |
1951 | 1939 | ||
1952 | for (i = 0; i < tmp->num_notes; i++) | 1940 | for (i = 0; i < tmp->num_notes; i++) |
1953 | if (!writenote(&tmp->notes[i], file, foffset)) | 1941 | if (!writenote(&tmp->notes[i], cprm)) |
1954 | return 0; | 1942 | return 0; |
1955 | } | 1943 | } |
1956 | 1944 | ||
@@ -2136,13 +2124,10 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2136 | 2124 | ||
2137 | offset = dataoff; | 2125 | offset = dataoff; |
2138 | 2126 | ||
2139 | size += sizeof(*elf); | 2127 | if (!dump_emit(cprm, elf, sizeof(*elf))) |
2140 | if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf))) | ||
2141 | goto end_coredump; | 2128 | goto end_coredump; |
2142 | 2129 | ||
2143 | size += sizeof(*phdr4note); | 2130 | if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) |
2144 | if (size > cprm->limit | ||
2145 | || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note))) | ||
2146 | goto end_coredump; | 2131 | goto end_coredump; |
2147 | 2132 | ||
2148 | /* Write program headers for segments dump */ | 2133 | /* Write program headers for segments dump */ |
@@ -2164,19 +2149,20 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2164 | phdr.p_flags |= PF_X; | 2149 | phdr.p_flags |= PF_X; |
2165 | phdr.p_align = ELF_EXEC_PAGESIZE; | 2150 | phdr.p_align = ELF_EXEC_PAGESIZE; |
2166 | 2151 | ||
2167 | size += sizeof(phdr); | 2152 | if (!dump_emit(cprm, &phdr, sizeof(phdr))) |
2168 | if (size > cprm->limit | ||
2169 | || !dump_write(cprm->file, &phdr, sizeof(phdr))) | ||
2170 | goto end_coredump; | 2153 | goto end_coredump; |
2171 | } | 2154 | } |
2155 | size = cprm->written; | ||
2172 | 2156 | ||
2173 | if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit)) | 2157 | if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit)) |
2174 | goto end_coredump; | 2158 | goto end_coredump; |
2175 | 2159 | ||
2160 | cprm->written = foffset; /* will disappear */ | ||
2176 | /* write out the notes section */ | 2161 | /* write out the notes section */ |
2177 | if (!write_note_info(&info, cprm->file, &foffset)) | 2162 | if (!write_note_info(&info, cprm)) |
2178 | goto end_coredump; | 2163 | goto end_coredump; |
2179 | 2164 | ||
2165 | foffset = cprm->written; | ||
2180 | if (elf_coredump_extra_notes_write(cprm->file, &foffset)) | 2166 | if (elf_coredump_extra_notes_write(cprm->file, &foffset)) |
2181 | goto end_coredump; | 2167 | goto end_coredump; |
2182 | 2168 | ||