debuggers.hg

view xen/common/libelf/libelf-loader.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents eccfdeb41b80
children
line source
1 /*
2 * parse and load elf binaries
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
19 #include <stdarg.h>
21 #include "libelf-private.h"
23 /* ------------------------------------------------------------------------ */
25 int elf_init(struct elf_binary *elf, const char *image, size_t size)
26 {
27 const elf_shdr *shdr;
28 uint64_t i, count, section, offset;
30 if ( !elf_is_elfbinary(image) )
31 {
32 elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
33 return -1;
34 }
36 memset(elf, 0, sizeof(*elf));
37 elf->image = image;
38 elf->size = size;
39 elf->ehdr = (elf_ehdr *)image;
40 elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
41 elf->data = elf->ehdr->e32.e_ident[EI_DATA];
43 /* Sanity check phdr. */
44 offset = elf_uval(elf, elf->ehdr, e_phoff) +
45 elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
46 if ( offset > elf->size )
47 {
48 elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n",
49 __FUNCTION__, offset, (unsigned long)elf->size);
50 return -1;
51 }
53 /* Sanity check shdr. */
54 offset = elf_uval(elf, elf->ehdr, e_shoff) +
55 elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf);
56 if ( offset > elf->size )
57 {
58 elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n",
59 __FUNCTION__, offset, (unsigned long)elf->size);
60 return -1;
61 }
63 /* Find section string table. */
64 section = elf_uval(elf, elf->ehdr, e_shstrndx);
65 shdr = elf_shdr_by_index(elf, section);
66 if ( shdr != NULL )
67 elf->sec_strtab = elf_section_start(elf, shdr);
69 /* Find symbol table and symbol string table. */
70 count = elf_shdr_count(elf);
71 for ( i = 0; i < count; i++ )
72 {
73 shdr = elf_shdr_by_index(elf, i);
74 if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
75 continue;
76 elf->sym_tab = shdr;
77 shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link));
78 if ( shdr == NULL )
79 {
80 elf->sym_tab = NULL;
81 continue;
82 }
83 elf->sym_strtab = elf_section_start(elf, shdr);
84 break;
85 }
87 return 0;
88 }
90 #ifndef __XEN__
91 void elf_call_log_callback(struct elf_binary *elf, int iserr,
92 const char *fmt,...) {
93 va_list al;
95 if (!elf->log_callback)
96 return;
97 if (!(iserr || elf->verbose))
98 return;
100 va_start(al,fmt);
101 elf->log_callback(elf, elf->log_caller_data, iserr, fmt, al);
102 va_end(al);
103 }
105 void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
106 void *log_caller_data, int verbose)
107 {
108 elf->log_callback = log_callback;
109 elf->log_caller_data = log_caller_data;
110 elf->verbose = verbose;
111 }
112 #else
113 void elf_set_verbose(struct elf_binary *elf)
114 {
115 elf->verbose = 1;
116 }
117 #endif
119 /* Calculate the required additional kernel space for the elf image */
120 void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
121 {
122 uint64_t sz;
123 const elf_shdr *shdr;
124 int i, type;
126 if ( !elf->sym_tab )
127 return;
129 pstart = elf_round_up(elf, pstart);
131 /* Space to store the size of the elf image */
132 sz = sizeof(uint32_t);
134 /* Space for the elf and elf section headers */
135 sz += (elf_uval(elf, elf->ehdr, e_ehsize) +
136 elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize));
137 sz = elf_round_up(elf, sz);
139 /* Space for the symbol and string tables. */
140 for ( i = 0; i < elf_shdr_count(elf); i++ )
141 {
142 shdr = elf_shdr_by_index(elf, i);
143 type = elf_uval(elf, (elf_shdr *)shdr, sh_type);
144 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
145 sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
146 }
148 elf->bsd_symtab_pstart = pstart;
149 elf->bsd_symtab_pend = pstart + sz;
150 }
152 static void elf_load_bsdsyms(struct elf_binary *elf)
153 {
154 elf_ehdr *sym_ehdr;
155 unsigned long sz;
156 char *maxva, *symbase, *symtab_addr;
157 elf_shdr *shdr;
158 int i, type;
160 if ( !elf->bsd_symtab_pstart )
161 return;
163 #define elf_hdr_elm(_elf, _hdr, _elm, _val) \
164 do { \
165 if ( elf_64bit(_elf) ) \
166 (_hdr)->e64._elm = _val; \
167 else \
168 (_hdr)->e32._elm = _val; \
169 } while ( 0 )
171 symbase = elf_get_ptr(elf, elf->bsd_symtab_pstart);
172 symtab_addr = maxva = symbase + sizeof(uint32_t);
174 /* Set up Elf header. */
175 sym_ehdr = (elf_ehdr *)symtab_addr;
176 sz = elf_uval(elf, elf->ehdr, e_ehsize);
177 memcpy(sym_ehdr, elf->ehdr, sz);
178 maxva += sz; /* no round up */
180 elf_hdr_elm(elf, sym_ehdr, e_phoff, 0);
181 elf_hdr_elm(elf, sym_ehdr, e_shoff, elf_uval(elf, elf->ehdr, e_ehsize));
182 elf_hdr_elm(elf, sym_ehdr, e_phentsize, 0);
183 elf_hdr_elm(elf, sym_ehdr, e_phnum, 0);
185 /* Copy Elf section headers. */
186 shdr = (elf_shdr *)maxva;
187 sz = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize);
188 memcpy(shdr, elf->image + elf_uval(elf, elf->ehdr, e_shoff), sz);
189 maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
191 for ( i = 0; i < elf_shdr_count(elf); i++ )
192 {
193 type = elf_uval(elf, shdr, sh_type);
194 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
195 {
196 elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i,
197 elf_section_start(elf, shdr), maxva);
198 sz = elf_uval(elf, shdr, sh_size);
199 memcpy(maxva, elf_section_start(elf, shdr), sz);
200 /* Mangled to be based on ELF header location. */
201 elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
202 maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
203 }
204 shdr = (elf_shdr *)((long)shdr +
205 (long)elf_uval(elf, elf->ehdr, e_shentsize));
206 }
208 /* Write down the actual sym size. */
209 *(uint32_t *)symbase = maxva - symtab_addr;
211 #undef elf_ehdr_elm
212 }
214 void elf_parse_binary(struct elf_binary *elf)
215 {
216 const elf_phdr *phdr;
217 uint64_t low = -1;
218 uint64_t high = 0;
219 uint64_t i, count, paddr, memsz;
221 count = elf_uval(elf, elf->ehdr, e_phnum);
222 for ( i = 0; i < count; i++ )
223 {
224 phdr = elf_phdr_by_index(elf, i);
225 if ( !elf_phdr_is_loadable(elf, phdr) )
226 continue;
227 paddr = elf_uval(elf, phdr, p_paddr);
228 memsz = elf_uval(elf, phdr, p_memsz);
229 elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64
230 " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz);
231 if ( low > paddr )
232 low = paddr;
233 if ( high < paddr + memsz )
234 high = paddr + memsz;
235 }
236 elf->pstart = low;
237 elf->pend = high;
238 elf_msg(elf, "%s: memory: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
239 __FUNCTION__, elf->pstart, elf->pend);
240 }
242 void elf_load_binary(struct elf_binary *elf)
243 {
244 const elf_phdr *phdr;
245 uint64_t i, count, paddr, offset, filesz, memsz;
246 char *dest;
248 count = elf_uval(elf, elf->ehdr, e_phnum);
249 for ( i = 0; i < count; i++ )
250 {
251 phdr = elf_phdr_by_index(elf, i);
252 if ( !elf_phdr_is_loadable(elf, phdr) )
253 continue;
254 paddr = elf_uval(elf, phdr, p_paddr);
255 offset = elf_uval(elf, phdr, p_offset);
256 filesz = elf_uval(elf, phdr, p_filesz);
257 memsz = elf_uval(elf, phdr, p_memsz);
258 dest = elf_get_ptr(elf, paddr);
259 elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
260 __func__, i, dest, dest + filesz);
261 memcpy(dest, elf->image + offset, filesz);
262 memset(dest + filesz, 0, memsz - filesz);
263 }
265 elf_load_bsdsyms(elf);
266 }
268 void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
269 {
270 return elf->dest + addr - elf->pstart;
271 }
273 uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
274 {
275 const elf_sym *sym;
276 uint64_t value;
278 sym = elf_sym_by_name(elf, symbol);
279 if ( sym == NULL )
280 {
281 elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol);
282 return -1;
283 }
285 value = elf_uval(elf, sym, st_value);
286 elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __FUNCTION__,
287 symbol, value);
288 return value;
289 }
291 /*
292 * Local variables:
293 * mode: C
294 * c-set-style: "BSD"
295 * c-basic-offset: 4
296 * tab-width: 4
297 * indent-tabs-mode: nil
298 * End:
299 */