aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2013-06-21 13:31:08 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2013-06-26 08:36:24 +0000
commit50869d41a1af768fb0c39ff2d059a8bec102bc91 (patch)
treeb42a42eef829a8aad6c7b4d1b8252aa4aa435809
parent052803fcf280e0ade32c0ca64438c37476c84525 (diff)
downloadalpine_aports-50869d41a1af768fb0c39ff2d059a8bec102bc91.tar.bz2
alpine_aports-50869d41a1af768fb0c39ff2d059a8bec102bc91.tar.xz
alpine_aports-50869d41a1af768fb0c39ff2d059a8bec102bc91.zip
main/xen: security fix (CVE-2013-2194,CVE-2013-2195,CVE-2013-2196)
fixes #2109 (cherry picked from commit f78e9dea47b7c130cb417d9826c984d8664f01ec) Conflicts: main/xen/APKBUILD
-rw-r--r--main/xen/APKBUILD6
-rw-r--r--main/xen/xsa55.patch3431
2 files changed, 3436 insertions, 1 deletions
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD
index c052f76f4c..d0afed1e64 100644
--- a/main/xen/APKBUILD
+++ b/main/xen/APKBUILD
@@ -3,7 +3,7 @@
3# Maintainer: William Pitcock <nenolod@dereferenced.org> 3# Maintainer: William Pitcock <nenolod@dereferenced.org>
4pkgname=xen 4pkgname=xen
5pkgver=4.2.2 5pkgver=4.2.2
6pkgrel=2 6pkgrel=3
7pkgdesc="Xen hypervisor" 7pkgdesc="Xen hypervisor"
8url="http://www.xen.org/" 8url="http://www.xen.org/"
9arch="x86 x86_64" 9arch="x86 x86_64"
@@ -27,6 +27,7 @@ source="http://bits.xensource.com/oss-xen/release/$pkgver/$pkgname-$pkgver.tar.g
27 xsa52-4.2-unstable.patch 27 xsa52-4.2-unstable.patch
28 xsa53-4.2.patch 28 xsa53-4.2.patch
29 xsa54.patch 29 xsa54.patch
30 xsa55.patch
30 xsa56.patch 31 xsa56.patch
31 32
32 fix-pod2man-choking.patch 33 fix-pod2man-choking.patch
@@ -155,6 +156,7 @@ b3e3a57d189a4f86c9766eaf3b5207f4 xsa48-4.2.patch
15583a9cdd035bcd18bf035434a1ba08c38 xsa52-4.2-unstable.patch 15683a9cdd035bcd18bf035434a1ba08c38 xsa52-4.2-unstable.patch
15603a1a4ebc470ee7e638e04db2701a4f7 xsa53-4.2.patch 15703a1a4ebc470ee7e638e04db2701a4f7 xsa53-4.2.patch
157a8393d1ec6b886ea72ffe624a04ee10a xsa54.patch 158a8393d1ec6b886ea72ffe624a04ee10a xsa54.patch
15942cd104f2a33d67938a63a6372cff573 xsa55.patch
158e70b9128ffc2175cea314a533a7d8457 xsa56.patch 160e70b9128ffc2175cea314a533a7d8457 xsa56.patch
159c1d1a415415b0192e5dae9032962bf61 fix-pod2man-choking.patch 161c1d1a415415b0192e5dae9032962bf61 fix-pod2man-choking.patch
16095d8af17bf844d41a015ff32aae51ba1 xenstored.initd 16295d8af17bf844d41a015ff32aae51ba1 xenstored.initd
@@ -180,6 +182,7 @@ dc23077028584e71a08dd0dc9e81552c76744a5ce9d39df5958a95ae9cf3107b xsa48-4.2.patc
1805b8582185bf90386729e81db1f7780c69a891b074a87d9a619a90d6f639bea13 xsa52-4.2-unstable.patch 1825b8582185bf90386729e81db1f7780c69a891b074a87d9a619a90d6f639bea13 xsa52-4.2-unstable.patch
181785f7612bd229f7501f4e98e4760f307d90c64305ee14707d262b77f05fa683d xsa53-4.2.patch 183785f7612bd229f7501f4e98e4760f307d90c64305ee14707d262b77f05fa683d xsa53-4.2.patch
1825d94946b3c9cba52aae2bffd4b0ebb11d09181650b5322a3c85170674a05f6b7 xsa54.patch 1845d94946b3c9cba52aae2bffd4b0ebb11d09181650b5322a3c85170674a05f6b7 xsa54.patch
185ac3ebaf3ec37e28ba08e23d63626d7aaccf0a3f282dd0af9c24cc4df3fd8fae0 xsa55.patch
183a691c5f5332a42c0d38ddb4dc037eb902f01ba31033b64c47d02909a8de0257d xsa56.patch 186a691c5f5332a42c0d38ddb4dc037eb902f01ba31033b64c47d02909a8de0257d xsa56.patch
184b4e7d43364a06b2cb04527db3e9567524bc489fef475709fd8493ebf1e62406d fix-pod2man-choking.patch 187b4e7d43364a06b2cb04527db3e9567524bc489fef475709fd8493ebf1e62406d fix-pod2man-choking.patch
18581d335946c81311c86e2f2112b773a568a5a530c0db9802b2fe559e71bb8b381 xenstored.initd 18881d335946c81311c86e2f2112b773a568a5a530c0db9802b2fe559e71bb8b381 xenstored.initd
@@ -205,6 +208,7 @@ bda9105793f2327e1317991762120d0668af0e964076b18c9fdbfd509984b2e88d85df95702c46b2
205b64a965fab8534958e453c493211ed3a6555aafb90d18f6d56a45b41d3086a0029aee85b6b6eb93b0d861d5fdc0ef10fc32e9b4f83593b37c43922d838085dd8 xsa52-4.2-unstable.patch 208b64a965fab8534958e453c493211ed3a6555aafb90d18f6d56a45b41d3086a0029aee85b6b6eb93b0d861d5fdc0ef10fc32e9b4f83593b37c43922d838085dd8 xsa52-4.2-unstable.patch
2069b08924e563e79d2b308c1521da520c0579b334b61ac99a5593eabdb96dbda2da898b542cc47bda6d663c68343216d9d29c04853b6d1b6ecdde964b0cbb3f7ab xsa53-4.2.patch 2099b08924e563e79d2b308c1521da520c0579b334b61ac99a5593eabdb96dbda2da898b542cc47bda6d663c68343216d9d29c04853b6d1b6ecdde964b0cbb3f7ab xsa53-4.2.patch
207c9010be637d4f96ef03c880e1ef28228f762c5980108380a105bd190b631a882c8dff81e9421246d88d597e72f69ad1a8c672be6ddd06936acfcacd4575a2650 xsa54.patch 210c9010be637d4f96ef03c880e1ef28228f762c5980108380a105bd190b631a882c8dff81e9421246d88d597e72f69ad1a8c672be6ddd06936acfcacd4575a2650 xsa54.patch
211b4f43095163146a29ae258575bb03bd45f5a315d3cca7434a0b88c18eb1b6e1cf17ef13b4ac428a08797271a3dbc756d3f705a990991c8d2fc96f0f272c3665a xsa55.patch
20826a1c2cc92ddd4c1ab6712b0e41a0135d0e76a7fe3a14b651fb0235e352e5a24077414371acccb93058b7ce4d882b667386811170ba74570c53165837bcd983d xsa56.patch 21226a1c2cc92ddd4c1ab6712b0e41a0135d0e76a7fe3a14b651fb0235e352e5a24077414371acccb93058b7ce4d882b667386811170ba74570c53165837bcd983d xsa56.patch
209ffb1113fcec0853b690c177655c7d1136388efdebf0d7f625b80481b98eadd3e9ef461442ced53e11acf0e347800a2b0a41e18b05065b5d04bffdd8a4e127cec fix-pod2man-choking.patch 213ffb1113fcec0853b690c177655c7d1136388efdebf0d7f625b80481b98eadd3e9ef461442ced53e11acf0e347800a2b0a41e18b05065b5d04bffdd8a4e127cec fix-pod2man-choking.patch
210792b062e8a16a2efd3cb4662d379d1500527f2a7ca9228d7831c2bd34f3b9141df949153ea05463a7758c3e3dd9a4182492ad5505fa38e298ecf8c99db77b4ee xenstored.initd 214792b062e8a16a2efd3cb4662d379d1500527f2a7ca9228d7831c2bd34f3b9141df949153ea05463a7758c3e3dd9a4182492ad5505fa38e298ecf8c99db77b4ee xenstored.initd
diff --git a/main/xen/xsa55.patch b/main/xen/xsa55.patch
new file mode 100644
index 0000000000..35fe7afd06
--- /dev/null
+++ b/main/xen/xsa55.patch
@@ -0,0 +1,3431 @@
1diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
2index 876c148..1a5249c 100644
3--- a/tools/libxc/Makefile
4+++ b/tools/libxc/Makefile
5@@ -52,8 +52,13 @@ endif
6 vpath %.c ../../xen/common/libelf
7 CFLAGS += -I../../xen/common/libelf
8
9-GUEST_SRCS-y += libelf-tools.c libelf-loader.c
10-GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
11+ELF_SRCS-y += libelf-tools.c libelf-loader.c
12+ELF_SRCS-y += libelf-dominfo.c
13+
14+GUEST_SRCS-y += $(ELF_SRCS-y)
15+
16+$(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
17+$(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
18
19 # new domain builder
20 GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
21diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
22index cdf3333..dbd3349 100644
23--- a/tools/libxc/ia64/xc_ia64_dom_fwloader.c
24+++ b/tools/libxc/ia64/xc_ia64_dom_fwloader.c
25@@ -60,6 +60,8 @@ static int xc_dom_load_fw_kernel(struct xc_dom_image *dom)
26 unsigned long i;
27
28 dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
29+ if ( dest == NULL )
30+ return -1;
31 memcpy(dest, dom->kernel_blob, FW_SIZE);
32
33 /* Synchronize cache. */
34diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
35index 0882ce6..da435ce 100644
36--- a/tools/libxc/xc_cpuid_x86.c
37+++ b/tools/libxc/xc_cpuid_x86.c
38@@ -589,6 +589,8 @@ static int xc_cpuid_do_domctl(
39 static char *alloc_str(void)
40 {
41 char *s = malloc(33);
42+ if ( s == NULL )
43+ return s;
44 memset(s, 0, 33);
45 return s;
46 }
47@@ -600,6 +602,8 @@ void xc_cpuid_to_str(const unsigned int *regs, char **strs)
48 for ( i = 0; i < 4; i++ )
49 {
50 strs[i] = alloc_str();
51+ if ( strs[i] == NULL )
52+ continue;
53 for ( j = 0; j < 32; j++ )
54 strs[i][j] = !!((regs[i] & (1U << (31 - j)))) ? '1' : '0';
55 }
56@@ -680,7 +684,7 @@ int xc_cpuid_check(
57 const char **config,
58 char **config_transformed)
59 {
60- int i, j;
61+ int i, j, rc;
62 unsigned int regs[4];
63
64 memset(config_transformed, 0, 4 * sizeof(*config_transformed));
65@@ -692,6 +696,11 @@ int xc_cpuid_check(
66 if ( config[i] == NULL )
67 continue;
68 config_transformed[i] = alloc_str();
69+ if ( config_transformed[i] == NULL )
70+ {
71+ rc = -ENOMEM;
72+ goto fail_rc;
73+ }
74 for ( j = 0; j < 32; j++ )
75 {
76 unsigned char val = !!((regs[i] & (1U << (31 - j))));
77@@ -708,12 +717,14 @@ int xc_cpuid_check(
78 return 0;
79
80 fail:
81+ rc = -EPERM;
82+ fail_rc:
83 for ( i = 0; i < 4; i++ )
84 {
85 free(config_transformed[i]);
86 config_transformed[i] = NULL;
87 }
88- return -EPERM;
89+ return rc;
90 }
91
92 /*
93@@ -758,6 +769,11 @@ int xc_cpuid_set(
94 }
95
96 config_transformed[i] = alloc_str();
97+ if ( config_transformed[i] == NULL )
98+ {
99+ rc = -ENOMEM;
100+ goto fail;
101+ }
102
103 for ( j = 0; j < 32; j++ )
104 {
105diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h
106index 6a72aa9..d801f66 100644
107--- a/tools/libxc/xc_dom.h
108+++ b/tools/libxc/xc_dom.h
109@@ -140,9 +140,10 @@ struct xc_dom_image {
110
111 struct xc_dom_loader {
112 char *name;
113- int (*probe) (struct xc_dom_image * dom);
114- int (*parser) (struct xc_dom_image * dom);
115- int (*loader) (struct xc_dom_image * dom);
116+ /* Sadly the error returns from these functions are not consistent: */
117+ elf_negerrnoval (*probe) (struct xc_dom_image * dom);
118+ elf_negerrnoval (*parser) (struct xc_dom_image * dom);
119+ elf_errorstatus (*loader) (struct xc_dom_image * dom);
120
121 struct xc_dom_loader *next;
122 };
123@@ -275,27 +276,50 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
124
125 void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
126 xen_pfn_t count);
127+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first,
128+ xen_pfn_t count, xen_pfn_t *count_out);
129 void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
130 void xc_dom_unmap_all(struct xc_dom_image *dom);
131
132-static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
133- struct xc_dom_seg *seg)
134+static inline void *xc_dom_seg_to_ptr_pages(struct xc_dom_image *dom,
135+ struct xc_dom_seg *seg,
136+ xen_pfn_t *pages_out)
137 {
138 xen_vaddr_t segsize = seg->vend - seg->vstart;
139 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
140 xen_pfn_t pages = (segsize + page_size - 1) / page_size;
141+ void *retval;
142+
143+ retval = xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
144
145- return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
146+ *pages_out = retval ? pages : 0;
147+ return retval;
148+}
149+
150+static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
151+ struct xc_dom_seg *seg)
152+{
153+ xen_pfn_t dummy;
154+
155+ return xc_dom_seg_to_ptr_pages(dom, seg, &dummy);
156 }
157
158 static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
159- xen_vaddr_t vaddr)
160+ xen_vaddr_t vaddr,
161+ size_t *safe_region_out)
162 {
163 unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
164 xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
165 unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
166- void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
167- return (ptr ? (ptr + offset) : NULL);
168+ xen_pfn_t safe_region_count;
169+ void *ptr;
170+
171+ *safe_region_out = 0;
172+ ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count);
173+ if ( ptr == NULL )
174+ return ptr;
175+ *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset;
176+ return ptr;
177 }
178
179 static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
180@@ -307,6 +331,8 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
181 {
182 if (dom->shadow_enabled)
183 return pfn;
184+ if (pfn >= dom->total_pages)
185+ return INVALID_MFN;
186 return dom->p2m_host[pfn];
187 }
188
189@@ -315,6 +341,8 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
190 {
191 if (xc_dom_feature_translated(dom))
192 return pfn;
193+ if (pfn >= dom->total_pages)
194+ return INVALID_MFN;
195 return dom->p2m_host[pfn];
196 }
197
198diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c
199index 769e97d..553b366 100644
200--- a/tools/libxc/xc_dom_binloader.c
201+++ b/tools/libxc/xc_dom_binloader.c
202@@ -123,10 +123,13 @@ static struct xen_bin_image_table *find_table(struct xc_dom_image *dom)
203 uint32_t *probe_ptr;
204 uint32_t *probe_end;
205
206+ if ( dom->kernel_size < sizeof(*table) )
207+ return NULL;
208 probe_ptr = dom->kernel_blob;
209- probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
210- if ( (void*)probe_end > (dom->kernel_blob + 8192) )
211+ if ( dom->kernel_size > (8192 + sizeof(*table)) )
212 probe_end = dom->kernel_blob + 8192;
213+ else
214+ probe_end = dom->kernel_blob + dom->kernel_size - sizeof(*table);
215
216 for ( table = NULL; probe_ptr < probe_end; probe_ptr++ )
217 {
218@@ -249,6 +252,7 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
219 char *image = dom->kernel_blob;
220 char *dest;
221 size_t image_size = dom->kernel_size;
222+ size_t dest_size;
223 uint32_t start_addr;
224 uint32_t load_end_addr;
225 uint32_t bss_end_addr;
226@@ -272,7 +276,29 @@ static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
227 DOMPRINTF(" text_size: 0x%" PRIx32 "", text_size);
228 DOMPRINTF(" bss_size: 0x%" PRIx32 "", bss_size);
229
230- dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
231+ dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
232+ if ( dest == NULL )
233+ {
234+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
235+ " => NULL", __FUNCTION__);
236+ return -EINVAL;
237+ }
238+
239+ if ( dest_size < text_size ||
240+ dest_size - text_size < bss_size )
241+ {
242+ DOMPRINTF("%s: mapped region is too small for image", __FUNCTION__);
243+ return -EINVAL;
244+ }
245+
246+ if ( image_size < skip ||
247+ image_size - skip < text_size )
248+ {
249+ DOMPRINTF("%s: image is too small for declared text size",
250+ __FUNCTION__);
251+ return -EINVAL;
252+ }
253+
254 memcpy(dest, image + skip, text_size);
255 memset(dest + text_size, 0, bss_size);
256
257diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
258index 2a01d7c..e79e38d 100644
259--- a/tools/libxc/xc_dom_core.c
260+++ b/tools/libxc/xc_dom_core.c
261@@ -120,9 +120,17 @@ void *xc_dom_malloc(struct xc_dom_image *dom, size_t size)
262 {
263 struct xc_dom_mem *block;
264
265+ if ( size > SIZE_MAX - sizeof(*block) )
266+ {
267+ DOMPRINTF("%s: unreasonable allocation size", __FUNCTION__);
268+ return NULL;
269+ }
270 block = malloc(sizeof(*block) + size);
271 if ( block == NULL )
272+ {
273+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
274 return NULL;
275+ }
276 memset(block, 0, sizeof(*block) + size);
277 block->next = dom->memblocks;
278 dom->memblocks = block;
279@@ -138,7 +146,10 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
280
281 block = malloc(sizeof(*block));
282 if ( block == NULL )
283+ {
284+ DOMPRINTF("%s: allocation failed", __FUNCTION__);
285 return NULL;
286+ }
287 memset(block, 0, sizeof(*block));
288 block->mmap_len = size;
289 block->mmap_ptr = mmap(NULL, block->mmap_len,
290@@ -146,6 +157,7 @@ void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size)
291 -1, 0);
292 if ( block->mmap_ptr == MAP_FAILED )
293 {
294+ DOMPRINTF("%s: mmap failed", __FUNCTION__);
295 free(block);
296 return NULL;
297 }
298@@ -202,6 +214,7 @@ void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
299 close(fd);
300 if ( block != NULL )
301 free(block);
302+ DOMPRINTF("%s: failed (on file `%s')", __FUNCTION__, filename);
303 return NULL;
304 }
305
306@@ -271,6 +284,11 @@ size_t xc_dom_check_gzip(xc_interface *xch, void *blob, size_t ziplen)
307 unsigned char *gzlen;
308 size_t unziplen;
309
310+ if ( ziplen < 6 )
311+ /* Too small. We need (i.e. the subsequent code relies on)
312+ * 2 bytes for the magic number plus 4 bytes length. */
313+ return 0;
314+
315 if ( strncmp(blob, "\037\213", 2) )
316 /* not gzipped */
317 return 0;
318@@ -351,10 +369,19 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
319 void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
320 xen_pfn_t count)
321 {
322+ xen_pfn_t count_out_dummy;
323+ return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
324+}
325+
326+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
327+ xen_pfn_t count, xen_pfn_t *count_out)
328+{
329 struct xc_dom_phys *phys;
330 unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
331 char *mode = "unset";
332
333+ *count_out = 0;
334+
335 if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */
336 count > dom->total_pages ||
337 pfn > dom->total_pages - count )
338@@ -384,6 +411,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
339 phys->count);
340 return NULL;
341 }
342+ *count_out = count;
343 }
344 else
345 {
346@@ -391,6 +419,9 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
347 just hand out a pointer to it */
348 if ( pfn < phys->first )
349 continue;
350+ if ( pfn >= phys->first + phys->count )
351+ continue;
352+ *count_out = phys->count - (pfn - phys->first);
353 }
354 return phys->ptr + ((pfn - phys->first) << page_shift);
355 }
356@@ -478,7 +509,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom,
357 seg->vstart = start;
358 seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size;
359
360- if ( pages > dom->total_pages || /* double test avoids overflow probs */
361+ if ( pages > dom->total_pages || /* multiple test avoids overflow probs */
362+ seg->pfn > dom->total_pages ||
363 pages > dom->total_pages - seg->pfn)
364 {
365 xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY,
366@@ -855,6 +887,12 @@ int xc_dom_build_image(struct xc_dom_image *dom)
367 ramdisklen) != 0 )
368 goto err;
369 ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg);
370+ if ( ramdiskmap == NULL )
371+ {
372+ DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg) => NULL",
373+ __FUNCTION__);
374+ goto err;
375+ }
376 if ( unziplen )
377 {
378 if ( xc_dom_do_gunzip(dom->xch,
379diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c
380index 2e69559..be58276 100644
381--- a/tools/libxc/xc_dom_elfloader.c
382+++ b/tools/libxc/xc_dom_elfloader.c
383@@ -28,13 +28,14 @@
384
385 #include "xg_private.h"
386 #include "xc_dom.h"
387+#include "xc_bitops.h"
388
389 #define XEN_VER "xen-3.0"
390
391 /* ------------------------------------------------------------------------ */
392
393 static void log_callback(struct elf_binary *elf, void *caller_data,
394- int iserr, const char *fmt, va_list al) {
395+ bool iserr, const char *fmt, va_list al) {
396 xc_interface *xch = caller_data;
397
398 xc_reportv(xch,
399@@ -46,7 +47,7 @@ static void log_callback(struct elf_binary *elf, void *caller_data,
400
401 void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf,
402 int verbose) {
403- elf_set_log(elf, log_callback, xch, verbose);
404+ elf_set_log(elf, log_callback, xch, verbose /* convert to bool */);
405 }
406
407 /* ------------------------------------------------------------------------ */
408@@ -84,7 +85,7 @@ static char *xc_dom_guest_type(struct xc_dom_image *dom,
409 /* ------------------------------------------------------------------------ */
410 /* parse elf binary */
411
412-static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
413+static elf_negerrnoval check_elf_kernel(struct xc_dom_image *dom, bool verbose)
414 {
415 if ( dom->kernel_blob == NULL )
416 {
417@@ -95,7 +96,7 @@ static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
418 return -EINVAL;
419 }
420
421- if ( !elf_is_elfbinary(dom->kernel_blob) )
422+ if ( !elf_is_elfbinary(dom->kernel_blob, dom->kernel_size) )
423 {
424 if ( verbose )
425 xc_dom_panic(dom->xch,
426@@ -106,20 +107,21 @@ static int check_elf_kernel(struct xc_dom_image *dom, int verbose)
427 return 0;
428 }
429
430-static int xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
431+static elf_negerrnoval xc_dom_probe_elf_kernel(struct xc_dom_image *dom)
432 {
433 return check_elf_kernel(dom, 0);
434 }
435
436-static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
437- struct elf_binary *elf, int load)
438+static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
439+ struct elf_binary *elf, bool load)
440 {
441 struct elf_binary syms;
442- const elf_shdr *shdr, *shdr2;
443+ ELF_HANDLE_DECL(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
444 xen_vaddr_t symtab, maxaddr;
445- char *hdr;
446+ elf_ptrval hdr;
447 size_t size;
448- int h, count, type, i, tables = 0;
449+ unsigned h, count, type, i, tables = 0;
450+ unsigned long *strtab_referenced = NULL;
451
452 if ( elf_swap(elf) )
453 {
454@@ -130,31 +132,48 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
455
456 if ( load )
457 {
458+ char *hdr_ptr;
459+ size_t allow_size;
460+
461 if ( !dom->bsd_symtab_start )
462 return 0;
463 size = dom->kernel_seg.vend - dom->bsd_symtab_start;
464- hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
465- *(int *)hdr = size - sizeof(int);
466+ hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
467+ if ( hdr_ptr == NULL )
468+ {
469+ DOMPRINTF("%s/load: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
470+ " => NULL", __FUNCTION__);
471+ return -1;
472+ }
473+ elf->caller_xdest_base = hdr_ptr;
474+ elf->caller_xdest_size = allow_size;
475+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
476+ elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
477 }
478 else
479 {
480- size = sizeof(int) + elf_size(elf, elf->ehdr) +
481+ char *hdr_ptr;
482+
483+ size = sizeof(unsigned) + elf_size(elf, elf->ehdr) +
484 elf_shdr_count(elf) * elf_size(elf, shdr);
485- hdr = xc_dom_malloc(dom, size);
486- if ( hdr == NULL )
487+ hdr_ptr = xc_dom_malloc(dom, size);
488+ if ( hdr_ptr == NULL )
489 return 0;
490- dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
491+ elf->caller_xdest_base = hdr_ptr;
492+ elf->caller_xdest_size = size;
493+ hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
494+ dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
495 }
496
497- memcpy(hdr + sizeof(int),
498- elf->image,
499+ elf_memcpy_safe(elf, hdr + sizeof(unsigned),
500+ ELF_IMAGE_BASE(elf),
501 elf_size(elf, elf->ehdr));
502- memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
503- elf->image + elf_uval(elf, elf->ehdr, e_shoff),
504+ elf_memcpy_safe(elf, hdr + sizeof(unsigned) + elf_size(elf, elf->ehdr),
505+ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
506 elf_shdr_count(elf) * elf_size(elf, shdr));
507 if ( elf_64bit(elf) )
508 {
509- Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
510+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(unsigned));
511 ehdr->e_phoff = 0;
512 ehdr->e_phentsize = 0;
513 ehdr->e_phnum = 0;
514@@ -163,19 +182,42 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
515 }
516 else
517 {
518- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
519+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(unsigned));
520 ehdr->e_phoff = 0;
521 ehdr->e_phentsize = 0;
522 ehdr->e_phnum = 0;
523 ehdr->e_shoff = elf_size(elf, elf->ehdr);
524 ehdr->e_shstrndx = SHN_UNDEF;
525 }
526- if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
527+ if ( elf->caller_xdest_size < sizeof(unsigned) )
528+ {
529+ DOMPRINTF("%s/%s: header size %"PRIx64" too small",
530+ __FUNCTION__, load ? "load" : "parse",
531+ (uint64_t)elf->caller_xdest_size);
532+ return -1;
533+ }
534+ if ( elf_init(&syms, elf->caller_xdest_base + sizeof(unsigned),
535+ elf->caller_xdest_size - sizeof(unsigned)) )
536 return -1;
537
538+ /*
539+ * The caller_xdest_{base,size} and dest_{base,size} need to
540+ * remain valid so long as each struct elf_image does. The
541+ * principle we adopt is that these values are set when the
542+ * memory is allocated or mapped, and cleared when (and if)
543+ * they are unmapped.
544+ *
545+ * Mappings of the guest are normally undone by xc_dom_unmap_all
546+ * (directly or via xc_dom_release). We do not explicitly clear
547+ * these because in fact that happens only at the end of
548+ * xc_dom_boot_image, at which time all of these ELF loading
549+ * functions have returned. No relevant struct elf_binary*
550+ * escapes this file.
551+ */
552+
553 xc_elf_set_logfile(dom->xch, &syms, 1);
554
555- symtab = dom->bsd_symtab_start + sizeof(int);
556+ symtab = dom->bsd_symtab_start + sizeof(unsigned);
557 maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
558 elf_shdr_count(&syms) * elf_size(&syms, shdr));
559
560@@ -186,27 +228,40 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
561 symtab, maxaddr);
562
563 count = elf_shdr_count(&syms);
564+ /* elf_shdr_count guarantees that count is reasonable */
565+
566+ strtab_referenced = xc_dom_malloc(dom, bitmap_size(count));
567+ if ( strtab_referenced == NULL )
568+ return -1;
569+ bitmap_clear(strtab_referenced, count);
570+ /* Note the symtabs @h linked to by any strtab @i. */
571+ for ( i = 0; i < count; i++ )
572+ {
573+ shdr2 = elf_shdr_by_index(&syms, i);
574+ if ( elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB )
575+ {
576+ h = elf_uval(&syms, shdr2, sh_link);
577+ if (h < count)
578+ set_bit(h, strtab_referenced);
579+ }
580+ }
581+
582 for ( h = 0; h < count; h++ )
583 {
584 shdr = elf_shdr_by_index(&syms, h);
585+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
586+ /* input has an insane section header count field */
587+ break;
588 type = elf_uval(&syms, shdr, sh_type);
589 if ( type == SHT_STRTAB )
590 {
591- /* Look for a strtab @i linked to symtab @h. */
592- for ( i = 0; i < count; i++ )
593- {
594- shdr2 = elf_shdr_by_index(&syms, i);
595- if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
596- (elf_uval(&syms, shdr2, sh_link) == h) )
597- break;
598- }
599 /* Skip symtab @h if we found no corresponding strtab @i. */
600- if ( i == count )
601+ if ( !test_bit(h, strtab_referenced) )
602 {
603 if ( elf_64bit(&syms) )
604- *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
605+ elf_store_field(elf, shdr, e64.sh_offset, 0);
606 else
607- *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
608+ elf_store_field(elf, shdr, e32.sh_offset, 0);
609 continue;
610 }
611 }
612@@ -215,13 +270,13 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
613 {
614 /* Mangled to be based on ELF header location. */
615 if ( elf_64bit(&syms) )
616- *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
617+ elf_store_field(elf, shdr, e64.sh_offset, maxaddr - symtab);
618 else
619- *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
620+ elf_store_field(elf, shdr, e32.sh_offset, maxaddr - symtab);
621 size = elf_uval(&syms, shdr, sh_size);
622 maxaddr = elf_round_up(&syms, maxaddr + size);
623 tables++;
624- DOMPRINTF("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
625+ DOMPRINTF("%s: h=%u %s, size=0x%zx, maxaddr=0x%" PRIx64 "",
626 __FUNCTION__, h,
627 type == SHT_SYMTAB ? "symtab" : "strtab",
628 size, maxaddr);
629@@ -229,7 +284,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
630 if ( load )
631 {
632 shdr2 = elf_shdr_by_index(elf, h);
633- memcpy((void*)elf_section_start(&syms, shdr),
634+ elf_memcpy_safe(elf, elf_section_start(&syms, shdr),
635 elf_section_start(elf, shdr2),
636 size);
637 }
638@@ -237,11 +292,18 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
639
640 /* Name is NULL. */
641 if ( elf_64bit(&syms) )
642- *(Elf64_Word*)(&shdr->e64.sh_name) = 0;
643+ elf_store_field(elf, shdr, e64.sh_name, 0);
644 else
645- *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
646+ elf_store_field(elf, shdr, e32.sh_name, 0);
647 }
648
649+ if ( elf_check_broken(&syms) )
650+ DOMPRINTF("%s: symbols ELF broken: %s", __FUNCTION__,
651+ elf_check_broken(&syms));
652+ if ( elf_check_broken(elf) )
653+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
654+ elf_check_broken(elf));
655+
656 if ( tables == 0 )
657 {
658 DOMPRINTF("%s: no symbol table present", __FUNCTION__);
659@@ -253,16 +315,22 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
660 return 0;
661 }
662
663-static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
664+static elf_errorstatus xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
665+ /*
666+ * This function sometimes returns -1 for error and sometimes
667+ * an errno value. ?!?!
668+ */
669 {
670 struct elf_binary *elf;
671- int rc;
672+ elf_errorstatus rc;
673
674 rc = check_elf_kernel(dom, 1);
675 if ( rc != 0 )
676 return rc;
677
678 elf = xc_dom_malloc(dom, sizeof(*elf));
679+ if ( elf == NULL )
680+ return -1;
681 dom->private_loader = elf;
682 rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
683 xc_elf_set_logfile(dom->xch, elf, 1);
684@@ -274,23 +342,27 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
685 }
686
687 /* Find the section-header strings table. */
688- if ( elf->sec_strtab == NULL )
689+ if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
690 {
691 xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
692 " has no shstrtab", __FUNCTION__);
693- return -EINVAL;
694+ rc = -EINVAL;
695+ goto out;
696 }
697
698 /* parse binary and get xen meta info */
699 elf_parse_binary(elf);
700 if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
701- return rc;
702+ {
703+ goto out;
704+ }
705
706 if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
707 {
708 xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
709 " support unprivileged (DomU) operation", __FUNCTION__);
710- return -EINVAL;
711+ rc = -EINVAL;
712+ goto out;
713 }
714
715 /* find kernel segment */
716@@ -304,15 +376,30 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
717 DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
718 __FUNCTION__, dom->guest_type,
719 dom->kernel_seg.vstart, dom->kernel_seg.vend);
720- return 0;
721+ rc = 0;
722+out:
723+ if ( elf_check_broken(elf) )
724+ DOMPRINTF("%s: ELF broken: %s", __FUNCTION__,
725+ elf_check_broken(elf));
726+
727+ return rc;
728 }
729
730-static int xc_dom_load_elf_kernel(struct xc_dom_image *dom)
731+static elf_errorstatus xc_dom_load_elf_kernel(struct xc_dom_image *dom)
732 {
733 struct elf_binary *elf = dom->private_loader;
734- int rc;
735+ elf_errorstatus rc;
736+ xen_pfn_t pages;
737+
738+ elf->dest_base = xc_dom_seg_to_ptr_pages(dom, &dom->kernel_seg, &pages);
739+ if ( elf->dest_base == NULL )
740+ {
741+ DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->kernel_seg)"
742+ " => NULL", __FUNCTION__);
743+ return -1;
744+ }
745+ elf->dest_size = pages * XC_DOM_PAGE_SIZE(dom);
746
747- elf->dest = xc_dom_seg_to_ptr(dom, &dom->kernel_seg);
748 rc = elf_load_binary(elf);
749 if ( rc < 0 )
750 {
751diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c
752index dcd1523..076821c 100644
753--- a/tools/libxc/xc_dom_ia64.c
754+++ b/tools/libxc/xc_dom_ia64.c
755@@ -60,6 +60,12 @@ int start_info_ia64(struct xc_dom_image *dom)
756
757 DOMPRINTF_CALLED(dom->xch);
758
759+ if ( start_info == NULL )
760+ {
761+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
762+ return -1; /* our caller throws away our return value :-/ */
763+ }
764+
765 memset(start_info, 0, sizeof(*start_info));
766 sprintf(start_info->magic, dom->guest_type);
767 start_info->flags = dom->flags;
768@@ -182,6 +188,12 @@ int arch_setup_meminit(struct xc_dom_image *dom)
769
770 /* setup initial p2m */
771 dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * nbr);
772+ if ( dom->p2m_host == NULL )
773+ {
774+ DOMPRINTF("%s: xc_dom_malloc failed for p2m_host",
775+ __FUNCTION__);
776+ return -1;
777+ }
778 for ( pfn = 0; pfn < nbr; pfn++ )
779 dom->p2m_host[pfn] = start + pfn;
780
781diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c
782index 0cf1687..448d9a1 100644
783--- a/tools/libxc/xc_dom_x86.c
784+++ b/tools/libxc/xc_dom_x86.c
785@@ -144,6 +144,9 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
786 xen_vaddr_t addr;
787 xen_pfn_t pgpfn;
788
789+ if ( l2tab == NULL )
790+ goto pfn_error;
791+
792 for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
793 addr += PAGE_SIZE_X86 )
794 {
795@@ -151,6 +154,8 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
796 {
797 /* get L1 tab, make L2 entry */
798 l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
799+ if ( l1tab == NULL )
800+ goto pfn_error;
801 l2off = l2_table_offset_i386(addr);
802 l2tab[l2off] =
803 pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
804@@ -169,6 +174,11 @@ static int setup_pgtables_x86_32(struct xc_dom_image *dom)
805 l1tab = NULL;
806 }
807 return 0;
808+
809+pfn_error:
810+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
811+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
812+ return -EINVAL;
813 }
814
815 /*
816@@ -219,6 +229,12 @@ static xen_pfn_t move_l3_below_4G(struct xc_dom_image *dom,
817 goto out;
818
819 l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
820+ if ( l3tab == NULL )
821+ {
822+ DOMPRINTF("%s: xc_dom_pfn_to_ptr(dom, l3pfn, 1) => NULL",
823+ __FUNCTION__);
824+ return l3mfn; /* our one call site will call xc_dom_panic and fail */
825+ }
826 memset(l3tab, 0, XC_DOM_PAGE_SIZE(dom));
827
828 DOMPRINTF("%s: successfully relocated L3 below 4G. "
829@@ -262,6 +278,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
830 }
831
832 l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
833+ if ( l3tab == NULL )
834+ goto pfn_error;
835
836 for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
837 addr += PAGE_SIZE_X86 )
838@@ -270,6 +288,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
839 {
840 /* get L2 tab, make L3 entry */
841 l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
842+ if ( l2tab == NULL )
843+ goto pfn_error;
844 l3off = l3_table_offset_pae(addr);
845 l3tab[l3off] =
846 pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
847@@ -280,6 +300,8 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
848 {
849 /* get L1 tab, make L2 entry */
850 l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
851+ if ( l1tab == NULL )
852+ goto pfn_error;
853 l2off = l2_table_offset_pae(addr);
854 l2tab[l2off] =
855 pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
856@@ -306,6 +328,11 @@ static int setup_pgtables_x86_32_pae(struct xc_dom_image *dom)
857 l3tab[3] = pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
858 }
859 return 0;
860+
861+pfn_error:
862+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
863+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
864+ return -EINVAL;
865 }
866
867 #undef L1_PROT
868@@ -344,6 +371,9 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
869 uint64_t addr;
870 xen_pfn_t pgpfn;
871
872+ if ( l4tab == NULL )
873+ goto pfn_error;
874+
875 for ( addr = dom->parms.virt_base; addr < dom->virt_pgtab_end;
876 addr += PAGE_SIZE_X86 )
877 {
878@@ -351,6 +381,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
879 {
880 /* get L3 tab, make L4 entry */
881 l3tab = xc_dom_pfn_to_ptr(dom, l3pfn, 1);
882+ if ( l3tab == NULL )
883+ goto pfn_error;
884 l4off = l4_table_offset_x86_64(addr);
885 l4tab[l4off] =
886 pfn_to_paddr(xc_dom_p2m_guest(dom, l3pfn)) | L4_PROT;
887@@ -361,6 +393,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
888 {
889 /* get L2 tab, make L3 entry */
890 l2tab = xc_dom_pfn_to_ptr(dom, l2pfn, 1);
891+ if ( l2tab == NULL )
892+ goto pfn_error;
893 l3off = l3_table_offset_x86_64(addr);
894 l3tab[l3off] =
895 pfn_to_paddr(xc_dom_p2m_guest(dom, l2pfn)) | L3_PROT;
896@@ -373,6 +407,8 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
897 {
898 /* get L1 tab, make L2 entry */
899 l1tab = xc_dom_pfn_to_ptr(dom, l1pfn, 1);
900+ if ( l1tab == NULL )
901+ goto pfn_error;
902 l2off = l2_table_offset_x86_64(addr);
903 l2tab[l2off] =
904 pfn_to_paddr(xc_dom_p2m_guest(dom, l1pfn)) | L2_PROT;
905@@ -393,6 +429,11 @@ static int setup_pgtables_x86_64(struct xc_dom_image *dom)
906 l1tab = NULL;
907 }
908 return 0;
909+
910+pfn_error:
911+ xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
912+ "%s: xc_dom_pfn_to_ptr failed", __FUNCTION__);
913+ return -EINVAL;
914 }
915
916 #undef L1_PROT
917@@ -410,6 +451,8 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
918 if ( xc_dom_alloc_segment(dom, &dom->p2m_seg, "phys2mach", 0, p2m_size) )
919 return -1;
920 dom->p2m_guest = xc_dom_seg_to_ptr(dom, &dom->p2m_seg);
921+ if ( dom->p2m_guest == NULL )
922+ return -1;
923
924 /* allocate special pages */
925 dom->start_info_pfn = xc_dom_alloc_page(dom, "start info");
926@@ -434,6 +477,12 @@ static int start_info_x86_32(struct xc_dom_image *dom)
927
928 DOMPRINTF_CALLED(dom->xch);
929
930+ if ( start_info == NULL )
931+ {
932+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
933+ return -1; /* our caller throws away our return value :-/ */
934+ }
935+
936 memset(start_info, 0, sizeof(*start_info));
937 strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
938 start_info->magic[sizeof(start_info->magic) - 1] = '\0';
939@@ -474,6 +523,12 @@ static int start_info_x86_64(struct xc_dom_image *dom)
940
941 DOMPRINTF_CALLED(dom->xch);
942
943+ if ( start_info == NULL )
944+ {
945+ DOMPRINTF("%s: xc_dom_pfn_to_ptr failed on start_info", __FUNCTION__);
946+ return -1; /* our caller throws away our return value :-/ */
947+ }
948+
949 memset(start_info, 0, sizeof(*start_info));
950 strncpy(start_info->magic, dom->guest_type, sizeof(start_info->magic));
951 start_info->magic[sizeof(start_info->magic) - 1] = '\0';
952@@ -725,6 +780,9 @@ int arch_setup_meminit(struct xc_dom_image *dom)
953 }
954
955 dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
956+ if ( dom->p2m_host == NULL )
957+ return -EINVAL;
958+
959 if ( dom->superpages )
960 {
961 int count = dom->total_pages >> SUPERPAGE_PFN_SHIFT;
962diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
963index b4c0b10..f9ed6b2 100644
964--- a/tools/libxc/xc_domain_restore.c
965+++ b/tools/libxc/xc_domain_restore.c
966@@ -1180,6 +1180,11 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx,
967
968 /* Map relevant mfns */
969 pfn_err = calloc(j, sizeof(*pfn_err));
970+ if ( pfn_err == NULL )
971+ {
972+ PERROR("allocation for pfn_err failed");
973+ return -1;
974+ }
975 region_base = xc_map_foreign_bulk(
976 xch, dom, PROT_WRITE, region_mfn, pfn_err, j);
977
978@@ -1556,6 +1561,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
979 mfn = ctx->p2m[pfn];
980 buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
981 PROT_READ | PROT_WRITE, mfn);
982+ if ( buf == NULL )
983+ {
984+ ERROR("xc_map_foreign_range for generation id"
985+ " buffer failed");
986+ goto out;
987+ }
988
989 generationid = *(unsigned long long *)(buf + offset);
990 *(unsigned long long *)(buf + offset) = generationid + 1;
991@@ -1713,6 +1724,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
992 l3tab = (uint64_t *)
993 xc_map_foreign_range(xch, dom, PAGE_SIZE,
994 PROT_READ, ctx->p2m[i]);
995+ if ( l3tab == NULL )
996+ {
997+ PERROR("xc_map_foreign_range failed (for l3tab)");
998+ goto out;
999+ }
1000
1001 for ( j = 0; j < 4; j++ )
1002 l3ptes[j] = l3tab[j];
1003@@ -1739,6 +1755,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
1004 l3tab = (uint64_t *)
1005 xc_map_foreign_range(xch, dom, PAGE_SIZE,
1006 PROT_READ | PROT_WRITE, ctx->p2m[i]);
1007+ if ( l3tab == NULL )
1008+ {
1009+ PERROR("xc_map_foreign_range failed (for l3tab, 2nd)");
1010+ goto out;
1011+ }
1012
1013 for ( j = 0; j < 4; j++ )
1014 l3tab[j] = l3ptes[j];
1015@@ -1909,6 +1930,12 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
1016 SET_FIELD(ctxt, user_regs.edx, mfn);
1017 start_info = xc_map_foreign_range(
1018 xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
1019+ if ( start_info == NULL )
1020+ {
1021+ PERROR("xc_map_foreign_range failed (for start_info)");
1022+ goto out;
1023+ }
1024+
1025 SET_FIELD(start_info, nr_pages, dinfo->p2m_size);
1026 SET_FIELD(start_info, shared_info, shared_info_frame<<PAGE_SHIFT);
1027 SET_FIELD(start_info, flags, 0);
1028@@ -2056,6 +2083,11 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
1029 /* Restore contents of shared-info page. No checking needed. */
1030 new_shared_info = xc_map_foreign_range(
1031 xch, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
1032+ if ( new_shared_info == NULL )
1033+ {
1034+ PERROR("xc_map_foreign_range failed (for new_shared_info)");
1035+ goto out;
1036+ }
1037
1038 /* restore saved vcpu_info and arch specific info */
1039 MEMCPY_FIELD(new_shared_info, old_shared_info, vcpu_info);
1040diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
1041index cf5d7fb..8165287 100644
1042--- a/tools/libxc/xc_hvm_build_x86.c
1043+++ b/tools/libxc/xc_hvm_build_x86.c
1044@@ -104,21 +104,23 @@ static int loadelfimage(
1045 for ( i = 0; i < pages; i++ )
1046 entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i];
1047
1048- elf->dest = xc_map_foreign_ranges(
1049+ elf->dest_base = xc_map_foreign_ranges(
1050 xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
1051 entries, pages);
1052- if ( elf->dest == NULL )
1053+ if ( elf->dest_base == NULL )
1054 goto err;
1055+ elf->dest_size = pages * PAGE_SIZE;
1056
1057- elf->dest += elf->pstart & (PAGE_SIZE - 1);
1058+ ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1));
1059
1060 /* Load the initial elf image. */
1061 rc = elf_load_binary(elf);
1062 if ( rc < 0 )
1063 PERROR("Failed to load elf binary\n");
1064
1065- munmap(elf->dest, pages << PAGE_SHIFT);
1066- elf->dest = NULL;
1067+ munmap(elf->dest_base, pages << PAGE_SHIFT);
1068+ elf->dest_base = NULL;
1069+ elf->dest_size = 0;
1070
1071 err:
1072 free(entries);
1073@@ -401,11 +403,16 @@ static int setup_guest(xc_interface *xch,
1074 munmap(page0, PAGE_SIZE);
1075 }
1076
1077+ if ( elf_check_broken(&elf) )
1078+ ERROR("HVM ELF broken: %s", elf_check_broken(&elf));
1079+
1080 free(page_array);
1081 return 0;
1082
1083 error_out:
1084 free(page_array);
1085+ if ( elf_check_broken(&elf) )
1086+ ERROR("HVM ELF broken, failing: %s", elf_check_broken(&elf));
1087 return -1;
1088 }
1089
1090diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
1091index 787e742..98e041c 100644
1092--- a/tools/libxc/xc_linux_osdep.c
1093+++ b/tools/libxc/xc_linux_osdep.c
1094@@ -378,6 +378,8 @@ static void *linux_privcmd_map_foreign_range(xc_interface *xch, xc_osdep_handle
1095
1096 num = (size + XC_PAGE_SIZE - 1) >> XC_PAGE_SHIFT;
1097 arr = calloc(num, sizeof(xen_pfn_t));
1098+ if ( arr == NULL )
1099+ return NULL;
1100
1101 for ( i = 0; i < num; i++ )
1102 arr[i] = mfn + i;
1103@@ -402,6 +404,8 @@ static void *linux_privcmd_map_foreign_ranges(xc_interface *xch, xc_osdep_handle
1104 num_per_entry = chunksize >> XC_PAGE_SHIFT;
1105 num = num_per_entry * nentries;
1106 arr = calloc(num, sizeof(xen_pfn_t));
1107+ if ( arr == NULL )
1108+ return NULL;
1109
1110 for ( i = 0; i < nentries; i++ )
1111 for ( j = 0; j < num_per_entry; j++ )
1112diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c
1113index 089a361..36b9812 100644
1114--- a/tools/libxc/xc_offline_page.c
1115+++ b/tools/libxc/xc_offline_page.c
1116@@ -714,6 +714,11 @@ int xc_exchange_page(xc_interface *xch, int domid, xen_pfn_t mfn)
1117
1118 new_p = xc_map_foreign_range(xch, domid, PAGE_SIZE,
1119 PROT_READ|PROT_WRITE, new_mfn);
1120+ if ( new_p == NULL )
1121+ {
1122+ ERROR("failed to map new_p for copy, guest may be broken?");
1123+ goto failed;
1124+ }
1125 memcpy(new_p, backup, PAGE_SIZE);
1126 munmap(new_p, PAGE_SIZE);
1127 mops.arg1.mfn = new_mfn;
1128diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
1129index 3e03a91..848ceed 100644
1130--- a/tools/libxc/xc_private.c
1131+++ b/tools/libxc/xc_private.c
1132@@ -771,6 +771,8 @@ const char *xc_strerror(xc_interface *xch, int errcode)
1133 errbuf = pthread_getspecific(errbuf_pkey);
1134 if (errbuf == NULL) {
1135 errbuf = malloc(XS_BUFSIZE);
1136+ if ( errbuf == NULL )
1137+ return "(failed to allocate errbuf)";
1138 pthread_setspecific(errbuf_pkey, errbuf);
1139 }
1140
1141diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
1142index b7741ca..8952048 100644
1143--- a/tools/libxc/xenctrl.h
1144+++ b/tools/libxc/xenctrl.h
1145@@ -1778,7 +1778,7 @@ int xc_cpuid_set(xc_interface *xch,
1146 int xc_cpuid_apply_policy(xc_interface *xch,
1147 domid_t domid);
1148 void xc_cpuid_to_str(const unsigned int *regs,
1149- char **strs);
1150+ char **strs); /* some strs[] may be NULL if ENOMEM */
1151 int xc_mca_op(xc_interface *xch, struct xen_mc *mc);
1152 #endif
1153
1154diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
1155index c926186..5fa445e 100644
1156--- a/tools/xcutils/readnotes.c
1157+++ b/tools/xcutils/readnotes.c
1158@@ -61,51 +61,56 @@ struct setup_header {
1159 } __attribute__((packed));
1160
1161 static void print_string_note(const char *prefix, struct elf_binary *elf,
1162- const elf_note *note)
1163+ ELF_HANDLE_DECL(elf_note) note)
1164 {
1165- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
1166+ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
1167 }
1168
1169 static void print_numeric_note(const char *prefix, struct elf_binary *elf,
1170- const elf_note *note)
1171+ ELF_HANDLE_DECL(elf_note) note)
1172 {
1173 uint64_t value = elf_note_numeric(elf, note);
1174- int descsz = elf_uval(elf, note, descsz);
1175+ unsigned descsz = elf_uval(elf, note, descsz);
1176
1177 printf("%s: %#*" PRIx64 " (%d bytes)\n",
1178 prefix, 2+2*descsz, value, descsz);
1179 }
1180
1181 static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf,
1182- const elf_note *note)
1183+ ELF_HANDLE_DECL(elf_note) note)
1184 {
1185- int descsz = elf_uval(elf, note, descsz);
1186- const uint32_t *desc32 = elf_note_desc(elf, note);
1187- const uint64_t *desc64 = elf_note_desc(elf, note);
1188+ unsigned descsz = elf_uval(elf, note, descsz);
1189+ elf_ptrval desc = elf_note_desc(elf, note);
1190
1191 /* XXX should be able to cope with a list of values. */
1192 switch ( descsz / 2 )
1193 {
1194 case 8:
1195 printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix,
1196- desc64[0], desc64[1]);
1197+ elf_access_unsigned(elf, desc, 0, 8),
1198+ elf_access_unsigned(elf, desc, 8, 8));
1199 break;
1200 case 4:
1201 printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix,
1202- desc32[0],desc32[1]);
1203+ (uint32_t)elf_access_unsigned(elf, desc, 0, 4),
1204+ (uint32_t)elf_access_unsigned(elf, desc, 4, 4));
1205 break;
1206 }
1207
1208 }
1209
1210-static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end)
1211+static unsigned print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end)
1212 {
1213- const elf_note *note;
1214- int notes_found = 0;
1215+ ELF_HANDLE_DECL(elf_note) note;
1216+ unsigned notes_found = 0;
1217+ const char *this_note_name;
1218
1219- for ( note = start; note < end; note = elf_note_next(elf, note) )
1220+ for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
1221 {
1222- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
1223+ this_note_name = elf_note_name(elf, note);
1224+ if (NULL == this_note_name)
1225+ continue;
1226+ if (0 != strcmp(this_note_name, "Xen"))
1227 continue;
1228
1229 notes_found++;
1230@@ -156,7 +161,7 @@ static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_
1231 break;
1232 default:
1233 printf("unknown note type %#x\n",
1234- (int)elf_uval(elf, note, type));
1235+ (unsigned)elf_uval(elf, note, type));
1236 break;
1237 }
1238 }
1239@@ -166,12 +171,13 @@ static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_
1240 int main(int argc, char **argv)
1241 {
1242 const char *f;
1243- int fd,h,size,usize,count;
1244+ int fd;
1245+ unsigned h,size,usize,count;
1246 void *image,*tmp;
1247 struct stat st;
1248 struct elf_binary elf;
1249- const elf_shdr *shdr;
1250- int notes_found = 0;
1251+ ELF_HANDLE_DECL(elf_shdr) shdr;
1252+ unsigned notes_found = 0;
1253
1254 struct setup_header *hdr;
1255 uint64_t payload_offset, payload_length;
1256@@ -257,7 +263,7 @@ int main(int argc, char **argv)
1257 count = elf_phdr_count(&elf);
1258 for ( h=0; h < count; h++)
1259 {
1260- const elf_phdr *phdr;
1261+ ELF_HANDLE_DECL(elf_phdr) phdr;
1262 phdr = elf_phdr_by_index(&elf, h);
1263 if (elf_uval(&elf, phdr, p_type) != PT_NOTE)
1264 continue;
1265@@ -269,8 +275,8 @@ int main(int argc, char **argv)
1266 continue;
1267
1268 notes_found = print_notes(&elf,
1269- elf_segment_start(&elf, phdr),
1270- elf_segment_end(&elf, phdr));
1271+ ELF_MAKE_HANDLE(elf_note, elf_segment_start(&elf, phdr)),
1272+ ELF_MAKE_HANDLE(elf_note, elf_segment_end(&elf, phdr)));
1273 }
1274
1275 if ( notes_found == 0 )
1276@@ -278,13 +284,13 @@ int main(int argc, char **argv)
1277 count = elf_shdr_count(&elf);
1278 for ( h=0; h < count; h++)
1279 {
1280- const elf_shdr *shdr;
1281+ ELF_HANDLE_DECL(elf_shdr) shdr;
1282 shdr = elf_shdr_by_index(&elf, h);
1283 if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
1284 continue;
1285 notes_found = print_notes(&elf,
1286- elf_section_start(&elf, shdr),
1287- elf_section_end(&elf, shdr));
1288+ ELF_MAKE_HANDLE(elf_note, elf_section_start(&elf, shdr)),
1289+ ELF_MAKE_HANDLE(elf_note, elf_section_end(&elf, shdr)));
1290 if ( notes_found )
1291 fprintf(stderr, "using notes from SHT_NOTE section\n");
1292
1293@@ -292,8 +298,12 @@ int main(int argc, char **argv)
1294 }
1295
1296 shdr = elf_shdr_by_name(&elf, "__xen_guest");
1297- if (shdr)
1298- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
1299+ if (ELF_HANDLE_VALID(shdr))
1300+ printf("__xen_guest: %s\n",
1301+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
1302+
1303+ if (elf_check_broken(&elf))
1304+ printf("warning: broken ELF: %s\n", elf_check_broken(&elf));
1305
1306 return 0;
1307 }
1308diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
1309index 2d56130..dec0519 100644
1310--- a/xen/arch/arm/kernel.c
1311+++ b/xen/arch/arm/kernel.c
1312@@ -146,6 +146,8 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
1313 {
1314 int rc;
1315
1316+ memset(&info->elf.elf, 0, sizeof(info->elf.elf));
1317+
1318 info->kernel_order = get_order_from_bytes(KERNEL_FLASH_SIZE);
1319 info->kernel_img = alloc_xenheap_pages(info->kernel_order, 0);
1320 if ( info->kernel_img == NULL )
1321@@ -160,7 +162,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
1322 #endif
1323 elf_parse_binary(&info->elf.elf);
1324 if ( (rc = elf_xen_parse(&info->elf.elf, &info->elf.parms)) != 0 )
1325- return rc;
1326+ goto err;
1327
1328 /*
1329 * TODO: can the ELF header be used to find the physical address
1330@@ -169,7 +171,18 @@ static int kernel_try_elf_prepare(struct kernel_info *info)
1331 info->entry = info->elf.parms.virt_entry;
1332 info->load = kernel_elf_load;
1333
1334+ if ( elf_check_broken(&info->elf.elf) )
1335+ printk("Xen: warning: ELF kernel broken: %s\n",
1336+ elf_check_broken(&info->elf.elf));
1337+
1338 return 0;
1339+
1340+err:
1341+ if ( elf_check_broken(&info->elf.elf) )
1342+ printk("Xen: ELF kernel broken: %s\n",
1343+ elf_check_broken(&info->elf.elf));
1344+
1345+ return rc;
1346 }
1347
1348 int kernel_prepare(struct kernel_info *info)
1349diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
1350index 5adc223..3600dca 100644
1351--- a/xen/arch/x86/bzimage.c
1352+++ b/xen/arch/x86/bzimage.c
1353@@ -220,7 +220,7 @@ unsigned long __init bzimage_headroom(char *image_start,
1354 image_length = hdr->payload_length;
1355 }
1356
1357- if ( elf_is_elfbinary(image_start) )
1358+ if ( elf_is_elfbinary(image_start, image_length) )
1359 return 0;
1360
1361 orig_image_len = image_length;
1362@@ -251,7 +251,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im
1363 *image_len = hdr->payload_length;
1364 }
1365
1366- if ( elf_is_elfbinary(*image_start) )
1367+ if ( elf_is_elfbinary(*image_start, *image_len) )
1368 return 0;
1369
1370 BUG_ON(!(image_base < *image_start));
1371diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
1372index 469d363..0dbec96 100644
1373--- a/xen/arch/x86/domain_build.c
1374+++ b/xen/arch/x86/domain_build.c
1375@@ -374,7 +374,7 @@ int __init construct_dom0(
1376 #endif
1377 elf_parse_binary(&elf);
1378 if ( (rc = elf_xen_parse(&elf, &parms)) != 0 )
1379- return rc;
1380+ goto out;
1381
1382 /* compatibility check */
1383 compatible = 0;
1384@@ -413,14 +413,16 @@ int __init construct_dom0(
1385 if ( !compatible )
1386 {
1387 printk("Mismatch between Xen and DOM0 kernel\n");
1388- return -EINVAL;
1389+ rc = -EINVAL;
1390+ goto out;
1391 }
1392
1393 if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE &&
1394 !test_bit(XENFEAT_dom0, parms.f_supported) )
1395 {
1396 printk("Kernel does not support Dom0 operation\n");
1397- return -EINVAL;
1398+ rc = -EINVAL;
1399+ goto out;
1400 }
1401
1402 #if defined(__x86_64__)
1403@@ -734,7 +736,8 @@ int __init construct_dom0(
1404 (v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )
1405 {
1406 printk("DOM0 image overlaps with Xen private area.\n");
1407- return -EINVAL;
1408+ rc = -EINVAL;
1409+ goto out;
1410 }
1411
1412 if ( is_pv_32on64_domain(d) )
1413@@ -908,12 +911,13 @@ int __init construct_dom0(
1414 write_ptbase(v);
1415
1416 /* Copy the OS image and free temporary buffer. */
1417- elf.dest = (void*)vkern_start;
1418+ elf.dest_base = (void*)vkern_start;
1419+ elf.dest_size = vkern_end - vkern_start;
1420 rc = elf_load_binary(&elf);
1421 if ( rc < 0 )
1422 {
1423 printk("Failed to load the kernel binary\n");
1424- return rc;
1425+ goto out;
1426 }
1427 bootstrap_map(NULL);
1428
1429@@ -924,7 +928,8 @@ int __init construct_dom0(
1430 {
1431 write_ptbase(current);
1432 printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
1433- return -1;
1434+ rc = -1;
1435+ goto out;
1436 }
1437 hypercall_page_initialise(
1438 d, (void *)(unsigned long)parms.virt_hypercall);
1439@@ -1271,9 +1276,19 @@ int __init construct_dom0(
1440
1441 BUG_ON(rc != 0);
1442
1443- iommu_dom0_init(dom0);
1444+ if ( elf_check_broken(&elf) )
1445+ printk(" Xen warning: dom0 kernel broken ELF: %s\n",
1446+ elf_check_broken(&elf));
1447
1448+ iommu_dom0_init(dom0);
1449 return 0;
1450+
1451+out:
1452+ if ( elf_check_broken(&elf) )
1453+ printk(" Xen dom0 kernel broken ELF: %s\n",
1454+ elf_check_broken(&elf));
1455+
1456+ return rc;
1457 }
1458
1459 /*
1460diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile
1461index 18dc8e2..5bf8f76 100644
1462--- a/xen/common/libelf/Makefile
1463+++ b/xen/common/libelf/Makefile
1464@@ -2,6 +2,8 @@ obj-bin-y := libelf.o
1465
1466 SECTIONS := text data $(SPECIAL_DATA_SECTIONS)
1467
1468+CFLAGS += -Wno-pointer-sign
1469+
1470 libelf.o: libelf-temp.o Makefile
1471 $(OBJCOPY) $(foreach s,$(SECTIONS),--rename-section .$(s)=.init.$(s)) $< $@
1472
1473diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
1474index 523837f..412ea70 100644
1475--- a/xen/common/libelf/libelf-dominfo.c
1476+++ b/xen/common/libelf/libelf-dominfo.c
1477@@ -29,22 +29,22 @@ static const char *const elf_xen_feature_names[] = {
1478 [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb",
1479 [XENFEAT_dom0] = "dom0"
1480 };
1481-static const int elf_xen_features =
1482+static const unsigned elf_xen_features =
1483 sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]);
1484
1485-int elf_xen_parse_features(const char *features,
1486+elf_errorstatus elf_xen_parse_features(const char *features,
1487 uint32_t *supported,
1488 uint32_t *required)
1489 {
1490- char feature[64];
1491- int pos, len, i;
1492+ unsigned char feature[64];
1493+ unsigned pos, len, i;
1494
1495 if ( features == NULL )
1496 return 0;
1497
1498 for ( pos = 0; features[pos] != '\0'; pos += len )
1499 {
1500- memset(feature, 0, sizeof(feature));
1501+ elf_memset_unchecked(feature, 0, sizeof(feature));
1502 for ( len = 0;; len++ )
1503 {
1504 if ( len >= sizeof(feature)-1 )
1505@@ -94,14 +94,14 @@ int elf_xen_parse_features(const char *features,
1506 /* ------------------------------------------------------------------------ */
1507 /* xen elf notes */
1508
1509-int elf_xen_parse_note(struct elf_binary *elf,
1510+elf_errorstatus elf_xen_parse_note(struct elf_binary *elf,
1511 struct elf_dom_parms *parms,
1512- const elf_note *note)
1513+ ELF_HANDLE_DECL(elf_note) note)
1514 {
1515 /* *INDENT-OFF* */
1516 static const struct {
1517 char *name;
1518- int str;
1519+ bool str;
1520 } note_desc[] = {
1521 [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0},
1522 [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0},
1523@@ -125,7 +125,7 @@ int elf_xen_parse_note(struct elf_binary *elf,
1524 const char *str = NULL;
1525 uint64_t val = 0;
1526 unsigned int i;
1527- int type = elf_uval(elf, note, type);
1528+ unsigned type = elf_uval(elf, note, type);
1529
1530 if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) ||
1531 (note_desc[type].name == NULL) )
1532@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
1533
1534 if ( note_desc[type].str )
1535 {
1536- str = elf_note_desc(elf, note);
1537+ str = elf_strval(elf, elf_note_desc(elf, note));
1538+ if (str == NULL)
1539+ /* elf_strval will mark elf broken if it fails so no need to log */
1540+ return 0;
1541 elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
1542 note_desc[type].name, str);
1543 parms->elf_notes[type].type = XEN_ENT_STR;
1544@@ -213,23 +216,37 @@ int elf_xen_parse_note(struct elf_binary *elf,
1545 return 0;
1546 }
1547
1548-static int elf_xen_parse_notes(struct elf_binary *elf,
1549+#define ELF_NOTE_INVALID (~0U)
1550+
1551+static unsigned elf_xen_parse_notes(struct elf_binary *elf,
1552 struct elf_dom_parms *parms,
1553- const void *start, const void *end)
1554+ elf_ptrval start,
1555+ elf_ptrval end,
1556+ unsigned *total_note_count)
1557 {
1558- int xen_elfnotes = 0;
1559- const elf_note *note;
1560+ unsigned xen_elfnotes = 0;
1561+ ELF_HANDLE_DECL(elf_note) note;
1562+ const char *note_name;
1563
1564 parms->elf_note_start = start;
1565 parms->elf_note_end = end;
1566- for ( note = parms->elf_note_start;
1567- (void *)note < parms->elf_note_end;
1568+ for ( note = ELF_MAKE_HANDLE(elf_note, parms->elf_note_start);
1569+ ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
1570 note = elf_note_next(elf, note) )
1571 {
1572- if ( strcmp(elf_note_name(elf, note), "Xen") )
1573+ if ( *total_note_count >= ELF_MAX_TOTAL_NOTE_COUNT )
1574+ {
1575+ elf_mark_broken(elf, "too many ELF notes");
1576+ break;
1577+ }
1578+ (*total_note_count)++;
1579+ note_name = elf_note_name(elf, note);
1580+ if ( note_name == NULL )
1581+ continue;
1582+ if ( strcmp(note_name, "Xen") )
1583 continue;
1584 if ( elf_xen_parse_note(elf, parms, note) )
1585- return -1;
1586+ return ELF_NOTE_INVALID;
1587 xen_elfnotes++;
1588 }
1589 return xen_elfnotes;
1590@@ -238,48 +255,49 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
1591 /* ------------------------------------------------------------------------ */
1592 /* __xen_guest section */
1593
1594-int elf_xen_parse_guest_info(struct elf_binary *elf,
1595+elf_errorstatus elf_xen_parse_guest_info(struct elf_binary *elf,
1596 struct elf_dom_parms *parms)
1597 {
1598- const char *h;
1599- char name[32], value[128];
1600- int len;
1601+ elf_ptrval h;
1602+ unsigned char name[32], value[128];
1603+ unsigned len;
1604
1605 h = parms->guest_info;
1606- while ( *h )
1607+#define STAR(h) (elf_access_unsigned(elf, (h), 0, 1))
1608+ while ( STAR(h) )
1609 {
1610- memset(name, 0, sizeof(name));
1611- memset(value, 0, sizeof(value));
1612+ elf_memset_unchecked(name, 0, sizeof(name));
1613+ elf_memset_unchecked(value, 0, sizeof(value));
1614 for ( len = 0;; len++, h++ )
1615 {
1616 if ( len >= sizeof(name)-1 )
1617 break;
1618- if ( *h == '\0' )
1619+ if ( STAR(h) == '\0' )
1620 break;
1621- if ( *h == ',' )
1622+ if ( STAR(h) == ',' )
1623 {
1624 h++;
1625 break;
1626 }
1627- if ( *h == '=' )
1628+ if ( STAR(h) == '=' )
1629 {
1630 h++;
1631 for ( len = 0;; len++, h++ )
1632 {
1633 if ( len >= sizeof(value)-1 )
1634 break;
1635- if ( *h == '\0' )
1636+ if ( STAR(h) == '\0' )
1637 break;
1638- if ( *h == ',' )
1639+ if ( STAR(h) == ',' )
1640 {
1641 h++;
1642 break;
1643 }
1644- value[len] = *h;
1645+ value[len] = STAR(h);
1646 }
1647 break;
1648 }
1649- name[len] = *h;
1650+ name[len] = STAR(h);
1651 }
1652 elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value);
1653
1654@@ -325,12 +343,13 @@ int elf_xen_parse_guest_info(struct elf_binary *elf,
1655 /* ------------------------------------------------------------------------ */
1656 /* sanity checks */
1657
1658-static int elf_xen_note_check(struct elf_binary *elf,
1659+static elf_errorstatus elf_xen_note_check(struct elf_binary *elf,
1660 struct elf_dom_parms *parms)
1661 {
1662- if ( (parms->elf_note_start == NULL) && (parms->guest_info == NULL) )
1663+ if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) &&
1664+ (ELF_PTRVAL_INVALID(parms->guest_info)) )
1665 {
1666- int machine = elf_uval(elf, elf->ehdr, e_machine);
1667+ unsigned machine = elf_uval(elf, elf->ehdr, e_machine);
1668 if ( (machine == EM_386) || (machine == EM_X86_64) )
1669 {
1670 elf_err(elf, "%s: ERROR: Not a Xen-ELF image: "
1671@@ -368,7 +387,7 @@ static int elf_xen_note_check(struct elf_binary *elf,
1672 return 0;
1673 }
1674
1675-static int elf_xen_addr_calc_check(struct elf_binary *elf,
1676+static elf_errorstatus elf_xen_addr_calc_check(struct elf_binary *elf,
1677 struct elf_dom_parms *parms)
1678 {
1679 if ( (parms->elf_paddr_offset != UNSET_ADDR) &&
1680@@ -454,15 +473,16 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf,
1681 /* ------------------------------------------------------------------------ */
1682 /* glue it all together ... */
1683
1684-int elf_xen_parse(struct elf_binary *elf,
1685+elf_errorstatus elf_xen_parse(struct elf_binary *elf,
1686 struct elf_dom_parms *parms)
1687 {
1688- const elf_shdr *shdr;
1689- const elf_phdr *phdr;
1690- int xen_elfnotes = 0;
1691- int i, count, rc;
1692+ ELF_HANDLE_DECL(elf_shdr) shdr;
1693+ ELF_HANDLE_DECL(elf_phdr) phdr;
1694+ unsigned xen_elfnotes = 0;
1695+ unsigned i, count, more_notes;
1696+ unsigned total_note_count = 0;
1697
1698- memset(parms, 0, sizeof(*parms));
1699+ elf_memset_unchecked(parms, 0, sizeof(*parms));
1700 parms->virt_base = UNSET_ADDR;
1701 parms->virt_entry = UNSET_ADDR;
1702 parms->virt_hypercall = UNSET_ADDR;
1703@@ -475,6 +495,9 @@ int elf_xen_parse(struct elf_binary *elf,
1704 for ( i = 0; i < count; i++ )
1705 {
1706 phdr = elf_phdr_by_index(elf, i);
1707+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
1708+ /* input has an insane program header count field */
1709+ break;
1710 if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
1711 continue;
1712
1713@@ -485,13 +508,14 @@ int elf_xen_parse(struct elf_binary *elf,
1714 if (elf_uval(elf, phdr, p_offset) == 0)
1715 continue;
1716
1717- rc = elf_xen_parse_notes(elf, parms,
1718+ more_notes = elf_xen_parse_notes(elf, parms,
1719 elf_segment_start(elf, phdr),
1720- elf_segment_end(elf, phdr));
1721- if ( rc == -1 )
1722+ elf_segment_end(elf, phdr),
1723+ &total_note_count);
1724+ if ( more_notes == ELF_NOTE_INVALID )
1725 return -1;
1726
1727- xen_elfnotes += rc;
1728+ xen_elfnotes += more_notes;
1729 }
1730
1731 /*
1732@@ -504,21 +528,25 @@ int elf_xen_parse(struct elf_binary *elf,
1733 for ( i = 0; i < count; i++ )
1734 {
1735 shdr = elf_shdr_by_index(elf, i);
1736+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
1737+ /* input has an insane section header count field */
1738+ break;
1739
1740 if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
1741 continue;
1742
1743- rc = elf_xen_parse_notes(elf, parms,
1744+ more_notes = elf_xen_parse_notes(elf, parms,
1745 elf_section_start(elf, shdr),
1746- elf_section_end(elf, shdr));
1747+ elf_section_end(elf, shdr),
1748+ &total_note_count);
1749
1750- if ( rc == -1 )
1751+ if ( more_notes == ELF_NOTE_INVALID )
1752 return -1;
1753
1754- if ( xen_elfnotes == 0 && rc > 0 )
1755+ if ( xen_elfnotes == 0 && more_notes > 0 )
1756 elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
1757
1758- xen_elfnotes += rc;
1759+ xen_elfnotes += more_notes;
1760 }
1761
1762 }
1763@@ -528,20 +556,15 @@ int elf_xen_parse(struct elf_binary *elf,
1764 */
1765 if ( xen_elfnotes == 0 )
1766 {
1767- count = elf_shdr_count(elf);
1768- for ( i = 0; i < count; i++ )
1769+ shdr = elf_shdr_by_name(elf, "__xen_guest");
1770+ if ( ELF_HANDLE_VALID(shdr) )
1771 {
1772- shdr = elf_shdr_by_name(elf, "__xen_guest");
1773- if ( shdr )
1774- {
1775- parms->guest_info = elf_section_start(elf, shdr);
1776- parms->elf_note_start = NULL;
1777- parms->elf_note_end = NULL;
1778- elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
1779- parms->guest_info);
1780- elf_xen_parse_guest_info(elf, parms);
1781- break;
1782- }
1783+ parms->guest_info = elf_section_start(elf, shdr);
1784+ parms->elf_note_start = ELF_INVALID_PTRVAL;
1785+ parms->elf_note_end = ELF_INVALID_PTRVAL;
1786+ elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
1787+ elf_strfmt(elf, parms->guest_info));
1788+ elf_xen_parse_guest_info(elf, parms);
1789 }
1790 }
1791
1792diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
1793index ab58b8b..e2e75af 100644
1794--- a/xen/common/libelf/libelf-loader.c
1795+++ b/xen/common/libelf/libelf-loader.c
1796@@ -16,27 +16,33 @@
1797 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1798 */
1799
1800+#ifdef __XEN__
1801+#include <asm/guest_access.h>
1802+#endif
1803+
1804 #include "libelf-private.h"
1805
1806 /* ------------------------------------------------------------------------ */
1807
1808-int elf_init(struct elf_binary *elf, const char *image, size_t size)
1809+elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t size)
1810 {
1811- const elf_shdr *shdr;
1812+ ELF_HANDLE_DECL(elf_shdr) shdr;
1813 uint64_t i, count, section, offset;
1814
1815- if ( !elf_is_elfbinary(image) )
1816+ if ( !elf_is_elfbinary(image_input, size) )
1817 {
1818 elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__);
1819 return -1;
1820 }
1821
1822- memset(elf, 0, sizeof(*elf));
1823- elf->image = image;
1824+ elf_memset_unchecked(elf, 0, sizeof(*elf));
1825+ elf->image_base = image_input;
1826 elf->size = size;
1827- elf->ehdr = (elf_ehdr *)image;
1828- elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
1829- elf->data = elf->ehdr->e32.e_ident[EI_DATA];
1830+ elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input);
1831+ elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
1832+ elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
1833+ elf->caller_xdest_base = NULL;
1834+ elf->caller_xdest_size = 0;
1835
1836 /* Sanity check phdr. */
1837 offset = elf_uval(elf, elf->ehdr, e_phoff) +
1838@@ -61,7 +67,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size)
1839 /* Find section string table. */
1840 section = elf_uval(elf, elf->ehdr, e_shstrndx);
1841 shdr = elf_shdr_by_index(elf, section);
1842- if ( shdr != NULL )
1843+ if ( ELF_HANDLE_VALID(shdr) )
1844 elf->sec_strtab = elf_section_start(elf, shdr);
1845
1846 /* Find symbol table and symbol string table. */
1847@@ -69,13 +75,16 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size)
1848 for ( i = 0; i < count; i++ )
1849 {
1850 shdr = elf_shdr_by_index(elf, i);
1851+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
1852+ /* input has an insane section header count field */
1853+ break;
1854 if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
1855 continue;
1856 elf->sym_tab = shdr;
1857 shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link));
1858- if ( shdr == NULL )
1859+ if ( !ELF_HANDLE_VALID(shdr) )
1860 {
1861- elf->sym_tab = NULL;
1862+ elf->sym_tab = ELF_INVALID_HANDLE(elf_shdr);
1863 continue;
1864 }
1865 elf->sym_strtab = elf_section_start(elf, shdr);
1866@@ -86,7 +95,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size)
1867 }
1868
1869 #ifndef __XEN__
1870-void elf_call_log_callback(struct elf_binary *elf, int iserr,
1871+void elf_call_log_callback(struct elf_binary *elf, bool iserr,
1872 const char *fmt,...) {
1873 va_list al;
1874
1875@@ -101,36 +110,39 @@ void elf_call_log_callback(struct elf_binary *elf, int iserr,
1876 }
1877
1878 void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
1879- void *log_caller_data, int verbose)
1880+ void *log_caller_data, bool verbose)
1881 {
1882 elf->log_callback = log_callback;
1883 elf->log_caller_data = log_caller_data;
1884 elf->verbose = verbose;
1885 }
1886
1887-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
1888+static elf_errorstatus elf_load_image(struct elf_binary *elf,
1889+ elf_ptrval dst, elf_ptrval src,
1890+ uint64_t filesz, uint64_t memsz)
1891 {
1892- memcpy(dst, src, filesz);
1893- memset(dst + filesz, 0, memsz - filesz);
1894+ elf_memcpy_safe(elf, dst, src, filesz);
1895+ elf_memset_safe(elf, dst + filesz, 0, memsz - filesz);
1896 return 0;
1897 }
1898 #else
1899-#include <asm/guest_access.h>
1900
1901 void elf_set_verbose(struct elf_binary *elf)
1902 {
1903 elf->verbose = 1;
1904 }
1905
1906-static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
1907+static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
1908 {
1909- int rc;
1910+ elf_errorstatus rc;
1911 if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
1912 return -1;
1913- rc = raw_copy_to_guest(dst, src, filesz);
1914+ /* We trust the dom0 kernel image completely, so we don't care
1915+ * about overruns etc. here. */
1916+ rc = raw_copy_to_guest(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), filesz);
1917 if ( rc != 0 )
1918 return -1;
1919- rc = raw_clear_guest(dst + filesz, memsz - filesz);
1920+ rc = raw_clear_guest(ELF_UNSAFE_PTR(dst + filesz), memsz - filesz);
1921 if ( rc != 0 )
1922 return -1;
1923 return 0;
1924@@ -141,10 +153,10 @@ static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t
1925 void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
1926 {
1927 uint64_t sz;
1928- const elf_shdr *shdr;
1929- int i, type;
1930+ ELF_HANDLE_DECL(elf_shdr) shdr;
1931+ unsigned i, type;
1932
1933- if ( !elf->sym_tab )
1934+ if ( !ELF_HANDLE_VALID(elf->sym_tab) )
1935 return;
1936
1937 pstart = elf_round_up(elf, pstart);
1938@@ -161,7 +173,10 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
1939 for ( i = 0; i < elf_shdr_count(elf); i++ )
1940 {
1941 shdr = elf_shdr_by_index(elf, i);
1942- type = elf_uval(elf, (elf_shdr *)shdr, sh_type);
1943+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
1944+ /* input has an insane section header count field */
1945+ break;
1946+ type = elf_uval(elf, shdr, sh_type);
1947 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
1948 sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size));
1949 }
1950@@ -172,11 +187,13 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart)
1951
1952 static void elf_load_bsdsyms(struct elf_binary *elf)
1953 {
1954- elf_ehdr *sym_ehdr;
1955+ ELF_HANDLE_DECL(elf_ehdr) sym_ehdr;
1956 unsigned long sz;
1957- char *maxva, *symbase, *symtab_addr;
1958- elf_shdr *shdr;
1959- int i, type;
1960+ elf_ptrval maxva;
1961+ elf_ptrval symbase;
1962+ elf_ptrval symtab_addr;
1963+ ELF_HANDLE_DECL(elf_shdr) shdr;
1964+ unsigned i, type;
1965
1966 if ( !elf->bsd_symtab_pstart )
1967 return;
1968@@ -184,18 +201,18 @@ static void elf_load_bsdsyms(struct elf_binary *elf)
1969 #define elf_hdr_elm(_elf, _hdr, _elm, _val) \
1970 do { \
1971 if ( elf_64bit(_elf) ) \
1972- (_hdr)->e64._elm = _val; \
1973+ elf_store_field(_elf, _hdr, e64._elm, _val); \
1974 else \
1975- (_hdr)->e32._elm = _val; \
1976+ elf_store_field(_elf, _hdr, e32._elm, _val); \
1977 } while ( 0 )
1978
1979 symbase = elf_get_ptr(elf, elf->bsd_symtab_pstart);
1980 symtab_addr = maxva = symbase + sizeof(uint32_t);
1981
1982 /* Set up Elf header. */
1983- sym_ehdr = (elf_ehdr *)symtab_addr;
1984+ sym_ehdr = ELF_MAKE_HANDLE(elf_ehdr, symtab_addr);
1985 sz = elf_uval(elf, elf->ehdr, e_ehsize);
1986- memcpy(sym_ehdr, elf->ehdr, sz);
1987+ elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(sym_ehdr), ELF_HANDLE_PTRVAL(elf->ehdr), sz);
1988 maxva += sz; /* no round up */
1989
1990 elf_hdr_elm(elf, sym_ehdr, e_phoff, 0);
1991@@ -204,37 +221,50 @@ do { \
1992 elf_hdr_elm(elf, sym_ehdr, e_phnum, 0);
1993
1994 /* Copy Elf section headers. */
1995- shdr = (elf_shdr *)maxva;
1996+ shdr = ELF_MAKE_HANDLE(elf_shdr, maxva);
1997 sz = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize);
1998- memcpy(shdr, elf->image + elf_uval(elf, elf->ehdr, e_shoff), sz);
1999- maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
2000+ elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr),
2001+ ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
2002+ sz);
2003+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
2004
2005 for ( i = 0; i < elf_shdr_count(elf); i++ )
2006 {
2007+ elf_ptrval old_shdr_p;
2008+ elf_ptrval new_shdr_p;
2009+
2010 type = elf_uval(elf, shdr, sh_type);
2011 if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
2012 {
2013- elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i,
2014+ elf_msg(elf, "%s: shdr %i at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n", __func__, i,
2015 elf_section_start(elf, shdr), maxva);
2016 sz = elf_uval(elf, shdr, sh_size);
2017- memcpy(maxva, elf_section_start(elf, shdr), sz);
2018+ elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz);
2019 /* Mangled to be based on ELF header location. */
2020 elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr);
2021- maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz);
2022+ maxva = elf_round_up(elf, (unsigned long)maxva + sz);
2023 }
2024- shdr = (elf_shdr *)((long)shdr +
2025- (long)elf_uval(elf, elf->ehdr, e_shentsize));
2026+ old_shdr_p = ELF_HANDLE_PTRVAL(shdr);
2027+ new_shdr_p = old_shdr_p + elf_uval(elf, elf->ehdr, e_shentsize);
2028+ if ( new_shdr_p <= old_shdr_p ) /* wrapped or stuck */
2029+ {
2030+ elf_mark_broken(elf, "bad section header length");
2031+ break;
2032+ }
2033+ if ( !elf_access_ok(elf, new_shdr_p, 1) ) /* outside image */
2034+ break;
2035+ shdr = ELF_MAKE_HANDLE(elf_shdr, new_shdr_p);
2036 }
2037
2038 /* Write down the actual sym size. */
2039- *(uint32_t *)symbase = maxva - symtab_addr;
2040+ elf_store_val(elf, uint32_t, symbase, maxva - symtab_addr);
2041
2042 #undef elf_ehdr_elm
2043 }
2044
2045 void elf_parse_binary(struct elf_binary *elf)
2046 {
2047- const elf_phdr *phdr;
2048+ ELF_HANDLE_DECL(elf_phdr) phdr;
2049 uint64_t low = -1;
2050 uint64_t high = 0;
2051 uint64_t i, count, paddr, memsz;
2052@@ -243,6 +273,9 @@ void elf_parse_binary(struct elf_binary *elf)
2053 for ( i = 0; i < count; i++ )
2054 {
2055 phdr = elf_phdr_by_index(elf, i);
2056+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
2057+ /* input has an insane program header count field */
2058+ break;
2059 if ( !elf_phdr_is_loadable(elf, phdr) )
2060 continue;
2061 paddr = elf_uval(elf, phdr, p_paddr);
2062@@ -260,16 +293,25 @@ void elf_parse_binary(struct elf_binary *elf)
2063 __FUNCTION__, elf->pstart, elf->pend);
2064 }
2065
2066-int elf_load_binary(struct elf_binary *elf)
2067+elf_errorstatus elf_load_binary(struct elf_binary *elf)
2068 {
2069- const elf_phdr *phdr;
2070+ ELF_HANDLE_DECL(elf_phdr) phdr;
2071 uint64_t i, count, paddr, offset, filesz, memsz;
2072- char *dest;
2073+ elf_ptrval dest;
2074+ /*
2075+ * Let bizarre ELFs write the output image up to twice; this
2076+ * calculation is just to ensure our copying loop is no worse than
2077+ * O(domain_size).
2078+ */
2079+ uint64_t remain_allow_copy = (uint64_t)elf->dest_size * 2;
2080
2081 count = elf_uval(elf, elf->ehdr, e_phnum);
2082 for ( i = 0; i < count; i++ )
2083 {
2084 phdr = elf_phdr_by_index(elf, i);
2085+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(phdr), 1) )
2086+ /* input has an insane program header count field */
2087+ break;
2088 if ( !elf_phdr_is_loadable(elf, phdr) )
2089 continue;
2090 paddr = elf_uval(elf, phdr, p_paddr);
2091@@ -277,9 +319,23 @@ int elf_load_binary(struct elf_binary *elf)
2092 filesz = elf_uval(elf, phdr, p_filesz);
2093 memsz = elf_uval(elf, phdr, p_memsz);
2094 dest = elf_get_ptr(elf, paddr);
2095- elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
2096- __func__, i, dest, dest + filesz);
2097- if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
2098+
2099+ /*
2100+ * We need to check that the input image doesn't have us copy
2101+ * the whole image zillions of times, as that could lead to
2102+ * O(n^2) time behaviour and possible DoS by a malicous ELF.
2103+ */
2104+ if ( remain_allow_copy < memsz )
2105+ {
2106+ elf_mark_broken(elf, "program segments total to more"
2107+ " than the input image size");
2108+ break;
2109+ }
2110+ remain_allow_copy -= memsz;
2111+
2112+ elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n",
2113+ __func__, i, dest, (elf_ptrval)(dest + filesz));
2114+ if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 )
2115 return -1;
2116 }
2117
2118@@ -287,18 +343,18 @@ int elf_load_binary(struct elf_binary *elf)
2119 return 0;
2120 }
2121
2122-void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
2123+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr)
2124 {
2125- return elf->dest + addr - elf->pstart;
2126+ return ELF_REALPTR2PTRVAL(elf->dest_base) + addr - elf->pstart;
2127 }
2128
2129 uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
2130 {
2131- const elf_sym *sym;
2132+ ELF_HANDLE_DECL(elf_sym) sym;
2133 uint64_t value;
2134
2135 sym = elf_sym_by_name(elf, symbol);
2136- if ( sym == NULL )
2137+ if ( !ELF_HANDLE_VALID(sym) )
2138 {
2139 elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol);
2140 return -1;
2141diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h
2142index 3ef753c..277be04 100644
2143--- a/xen/common/libelf/libelf-private.h
2144+++ b/xen/common/libelf/libelf-private.h
2145@@ -77,7 +77,7 @@
2146 #define elf_err(elf, fmt, args ... ) \
2147 elf_call_log_callback(elf, 1, fmt , ## args );
2148
2149-void elf_call_log_callback(struct elf_binary*, int iserr, const char *fmt,...);
2150+void elf_call_log_callback(struct elf_binary*, bool iserr, const char *fmt,...);
2151
2152 #define safe_strcpy(d,s) \
2153 do { strncpy((d),(s),sizeof((d))-1); \
2154@@ -86,6 +86,19 @@ do { strncpy((d),(s),sizeof((d))-1); \
2155
2156 #endif
2157
2158+#undef memcpy
2159+#undef memset
2160+#undef memmove
2161+#undef strcpy
2162+
2163+#define memcpy MISTAKE_unspecified_memcpy
2164+#define memset MISTAKE_unspecified_memset
2165+#define memmove MISTAKE_unspecified_memmove
2166+#define strcpy MISTAKE_unspecified_strcpy
2167+ /* This prevents libelf from using these undecorated versions
2168+ * of memcpy, memset, memmove and strcpy. Every call site
2169+ * must either use elf_mem*_unchecked, or elf_mem*_safe. */
2170+
2171 #endif /* __LIBELF_PRIVATE_H_ */
2172
2173 /*
2174diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c
2175deleted file mode 100644
2176index 7ef4b01..0000000
2177--- a/xen/common/libelf/libelf-relocate.c
2178+++ /dev/null
2179@@ -1,372 +0,0 @@
2180-/*
2181- * ELF relocation code (not used by xen kernel right now).
2182- *
2183- * This library is free software; you can redistribute it and/or
2184- * modify it under the terms of the GNU Lesser General Public
2185- * License as published by the Free Software Foundation;
2186- * version 2.1 of the License.
2187- *
2188- * This library is distributed in the hope that it will be useful,
2189- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2190- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2191- * Lesser General Public License for more details.
2192- *
2193- * You should have received a copy of the GNU Lesser General Public
2194- * License along with this library; if not, write to the Free Software
2195- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2196- */
2197-
2198-#include "libelf-private.h"
2199-
2200-/* ------------------------------------------------------------------------ */
2201-
2202-static const char *rel_names_i386[] = {
2203- "R_386_NONE",
2204- "R_386_32",
2205- "R_386_PC32",
2206- "R_386_GOT32",
2207- "R_386_PLT32",
2208- "R_386_COPY",
2209- "R_386_GLOB_DAT",
2210- "R_386_JMP_SLOT",
2211- "R_386_RELATIVE",
2212- "R_386_GOTOFF",
2213- "R_386_GOTPC",
2214- "R_386_32PLT",
2215- "R_386_TLS_TPOFF",
2216- "R_386_TLS_IE",
2217- "R_386_TLS_GOTIE",
2218- "R_386_TLS_LE",
2219- "R_386_TLS_GD",
2220- "R_386_TLS_LDM",
2221- "R_386_16",
2222- "R_386_PC16",
2223- "R_386_8",
2224- "R_386_PC8",
2225- "R_386_TLS_GD_32",
2226- "R_386_TLS_GD_PUSH",
2227- "R_386_TLS_GD_CALL",
2228- "R_386_TLS_GD_POP",
2229- "R_386_TLS_LDM_32",
2230- "R_386_TLS_LDM_PUSH",
2231- "R_386_TLS_LDM_CALL",
2232- "R_386_TLS_LDM_POP",
2233- "R_386_TLS_LDO_32",
2234- "R_386_TLS_IE_32",
2235- "R_386_TLS_LE_32",
2236- "R_386_TLS_DTPMOD32",
2237- "R_386_TLS_DTPOFF32",
2238- "R_386_TLS_TPOFF32",
2239-};
2240-
2241-static int elf_reloc_i386(struct elf_binary *elf, int type,
2242- uint64_t addr, uint64_t value)
2243-{
2244- void *ptr = elf_get_ptr(elf, addr);
2245- uint32_t *u32;
2246-
2247- switch ( type )
2248- {
2249- case 1 /* R_386_32 */ :
2250- u32 = ptr;
2251- *u32 += elf->reloc_offset;
2252- break;
2253- case 2 /* R_386_PC32 */ :
2254- /* nothing */
2255- break;
2256- default:
2257- return -1;
2258- }
2259- return 0;
2260-}
2261-
2262-/* ------------------------------------------------------------------------ */
2263-
2264-static const char *rel_names_x86_64[] = {
2265- "R_X86_64_NONE",
2266- "R_X86_64_64",
2267- "R_X86_64_PC32",
2268- "R_X86_64_GOT32",
2269- "R_X86_64_PLT32",
2270- "R_X86_64_COPY",
2271- "R_X86_64_GLOB_DAT",
2272- "R_X86_64_JUMP_SLOT",
2273- "R_X86_64_RELATIVE",
2274- "R_X86_64_GOTPCREL",
2275- "R_X86_64_32",
2276- "R_X86_64_32S",
2277- "R_X86_64_16",
2278- "R_X86_64_PC16",
2279- "R_X86_64_8",
2280- "R_X86_64_PC8",
2281- "R_X86_64_DTPMOD64",
2282- "R_X86_64_DTPOFF64",
2283- "R_X86_64_TPOFF64",
2284- "R_X86_64_TLSGD",
2285- "R_X86_64_TLSLD",
2286- "R_X86_64_DTPOFF32",
2287- "R_X86_64_GOTTPOFF",
2288- "R_X86_64_TPOFF32",
2289-};
2290-
2291-static int elf_reloc_x86_64(struct elf_binary *elf, int type,
2292- uint64_t addr, uint64_t value)
2293-{
2294- void *ptr = elf_get_ptr(elf, addr);
2295- uint64_t *u64;
2296- uint32_t *u32;
2297- int32_t *s32;
2298-
2299- switch ( type )
2300- {
2301- case 1 /* R_X86_64_64 */ :
2302- u64 = ptr;
2303- value += elf->reloc_offset;
2304- *u64 = value;
2305- break;
2306- case 2 /* R_X86_64_PC32 */ :
2307- u32 = ptr;
2308- *u32 = value - addr;
2309- if ( *u32 != (uint32_t)(value - addr) )
2310- {
2311- elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32
2312- " != 0x%" PRIx32 "\n",
2313- *u32, (uint32_t) (value - addr));
2314- return -1;
2315- }
2316- break;
2317- case 10 /* R_X86_64_32 */ :
2318- u32 = ptr;
2319- value += elf->reloc_offset;
2320- *u32 = value;
2321- if ( *u32 != value )
2322- {
2323- elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32
2324- " != 0x%" PRIx64 "\n",
2325- *u32, value);
2326- return -1;
2327- }
2328- break;
2329- case 11 /* R_X86_64_32S */ :
2330- s32 = ptr;
2331- value += elf->reloc_offset;
2332- *s32 = value;
2333- if ( *s32 != (int64_t) value )
2334- {
2335- elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32
2336- " != 0x%" PRIx64 "\n",
2337- *s32, (int64_t) value);
2338- return -1;
2339- }
2340- break;
2341- default:
2342- return -1;
2343- }
2344- return 0;
2345-}
2346-
2347-/* ------------------------------------------------------------------------ */
2348-
2349-static struct relocs {
2350- const char **names;
2351- int count;
2352- int (*func) (struct elf_binary * elf, int type, uint64_t addr,
2353- uint64_t value);
2354-} relocs[] =
2355-/* *INDENT-OFF* */
2356-{
2357- [EM_386] = {
2358- .names = rel_names_i386,
2359- .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]),
2360- .func = elf_reloc_i386,
2361- },
2362- [EM_X86_64] = {
2363- .names = rel_names_x86_64,
2364- .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]),
2365- .func = elf_reloc_x86_64,
2366- }
2367-};
2368-/* *INDENT-ON* */
2369-
2370-/* ------------------------------------------------------------------------ */
2371-
2372-static const char *rela_name(int machine, int type)
2373-{
2374- if ( machine > sizeof(relocs) / sizeof(relocs[0]) )
2375- return "unknown mach";
2376- if ( !relocs[machine].names )
2377- return "unknown mach";
2378- if ( type > relocs[machine].count )
2379- return "unknown rela";
2380- return relocs[machine].names[type];
2381-}
2382-
2383-static int elf_reloc_section(struct elf_binary *elf,
2384- const elf_shdr * rels,
2385- const elf_shdr * sect, const elf_shdr * syms)
2386-{
2387- const void *ptr, *end;
2388- const elf_shdr *shdr;
2389- const elf_rela *rela;
2390- const elf_rel *rel;
2391- const elf_sym *sym;
2392- uint64_t s_type;
2393- uint64_t r_offset;
2394- uint64_t r_info;
2395- uint64_t r_addend;
2396- int r_type, r_sym;
2397- size_t rsize;
2398- uint64_t shndx, sbase, addr, value;
2399- const char *sname;
2400- int machine;
2401-
2402- machine = elf_uval(elf, elf->ehdr, e_machine);
2403- if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) ||
2404- (relocs[machine].func == NULL) )
2405- {
2406- elf_err(elf, "%s: can't handle machine %d\n",
2407- __FUNCTION__, machine);
2408- return -1;
2409- }
2410- if ( elf_swap(elf) )
2411- {
2412- elf_err(elf, "%s: non-native byte order, relocation not supported\n",
2413- __FUNCTION__);
2414- return -1;
2415- }
2416-
2417- s_type = elf_uval(elf, rels, sh_type);
2418- rsize = (SHT_REL == s_type) ? elf_size(elf, rel) : elf_size(elf, rela);
2419- ptr = elf_section_start(elf, rels);
2420- end = elf_section_end(elf, rels);
2421-
2422- for ( ; ptr < end; ptr += rsize )
2423- {
2424- switch ( s_type )
2425- {
2426- case SHT_REL:
2427- rel = ptr;
2428- r_offset = elf_uval(elf, rel, r_offset);
2429- r_info = elf_uval(elf, rel, r_info);
2430- r_addend = 0;
2431- break;
2432- case SHT_RELA:
2433- rela = ptr;
2434- r_offset = elf_uval(elf, rela, r_offset);
2435- r_info = elf_uval(elf, rela, r_info);
2436- r_addend = elf_uval(elf, rela, r_addend);
2437- break;
2438- default:
2439- /* can't happen */
2440- return -1;
2441- }
2442- if ( elf_64bit(elf) )
2443- {
2444- r_type = ELF64_R_TYPE(r_info);
2445- r_sym = ELF64_R_SYM(r_info);
2446- }
2447- else
2448- {
2449- r_type = ELF32_R_TYPE(r_info);
2450- r_sym = ELF32_R_SYM(r_info);
2451- }
2452-
2453- sym = elf_sym_by_index(elf, r_sym);
2454- shndx = elf_uval(elf, sym, st_shndx);
2455- switch ( shndx )
2456- {
2457- case SHN_UNDEF:
2458- sname = "*UNDEF*";
2459- sbase = 0;
2460- break;
2461- case SHN_COMMON:
2462- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
2463- __FUNCTION__, shndx);
2464- return -1;
2465- case SHN_ABS:
2466- sname = "*ABS*";
2467- sbase = 0;
2468- break;
2469- default:
2470- shdr = elf_shdr_by_index(elf, shndx);
2471- if ( shdr == NULL )
2472- {
2473- elf_err(elf, "%s: invalid section: %" PRId64 "\n",
2474- __FUNCTION__, shndx);
2475- return -1;
2476- }
2477- sname = elf_section_name(elf, shdr);
2478- sbase = elf_uval(elf, shdr, sh_addr);
2479- }
2480-
2481- addr = r_offset;
2482- value = elf_uval(elf, sym, st_value);
2483- value += r_addend;
2484-
2485- if ( elf->log_callback && (elf->verbose > 1) )
2486- {
2487- uint64_t st_name = elf_uval(elf, sym, st_name);
2488- const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*";
2489-
2490- elf_msg(elf,
2491- "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 ","
2492- " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]"
2493- " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n",
2494- __FUNCTION__, rela_name(machine, r_type), r_type, r_offset,
2495- r_addend, name, elf_uval(elf, sym, st_value), sname, sbase,
2496- addr, value);
2497- }
2498-
2499- if ( relocs[machine].func(elf, r_type, addr, value) == -1 )
2500- {
2501- elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n",
2502- __FUNCTION__, rela_name(machine, r_type), r_type);
2503- return -1;
2504- }
2505- }
2506- return 0;
2507-}
2508-
2509-int elf_reloc(struct elf_binary *elf)
2510-{
2511- const elf_shdr *rels, *sect, *syms;
2512- uint64_t i, count, type;
2513-
2514- count = elf_shdr_count(elf);
2515- for ( i = 0; i < count; i++ )
2516- {
2517- rels = elf_shdr_by_index(elf, i);
2518- type = elf_uval(elf, rels, sh_type);
2519- if ( (type != SHT_REL) && (type != SHT_RELA) )
2520- continue;
2521-
2522- sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info));
2523- syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link));
2524- if ( NULL == sect || NULL == syms )
2525- continue;
2526-
2527- if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) )
2528- {
2529- elf_msg(elf, "%s: relocations for %s, skipping\n",
2530- __FUNCTION__, elf_section_name(elf, sect));
2531- continue;
2532- }
2533-
2534- elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n",
2535- __FUNCTION__, elf_section_name(elf, sect),
2536- elf_uval(elf, sect, sh_addr));
2537- if ( elf_reloc_section(elf, rels, sect, syms) != 0 )
2538- return -1;
2539- }
2540- return 0;
2541-}
2542-
2543-/*
2544- * Local variables:
2545- * mode: C
2546- * c-set-style: "BSD"
2547- * c-basic-offset: 4
2548- * tab-width: 4
2549- * indent-tabs-mode: nil
2550- * End:
2551- */
2552diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
2553index cb97908..e202249 100644
2554--- a/xen/common/libelf/libelf-tools.c
2555+++ b/xen/common/libelf/libelf-tools.c
2556@@ -20,201 +20,292 @@
2557
2558 /* ------------------------------------------------------------------------ */
2559
2560-uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr,
2561- uint64_t offset, size_t size)
2562+void elf_mark_broken(struct elf_binary *elf, const char *msg)
2563 {
2564- int need_swap = elf_swap(elf);
2565+ if ( elf->broken == NULL )
2566+ elf->broken = msg;
2567+}
2568+
2569+const char *elf_check_broken(const struct elf_binary *elf)
2570+{
2571+ return elf->broken;
2572+}
2573+
2574+static bool elf_ptrval_in_range(elf_ptrval ptrval, uint64_t size,
2575+ const void *region, uint64_t regionsize)
2576+ /*
2577+ * Returns true if the putative memory area [ptrval,ptrval+size>
2578+ * is completely inside the region [region,region+regionsize>.
2579+ *
2580+ * ptrval and size are the untrusted inputs to be checked.
2581+ * region and regionsize are trusted and must be correct and valid,
2582+ * although it is OK for region to perhaps be maliciously NULL
2583+ * (but not some other malicious value).
2584+ */
2585+{
2586+ elf_ptrval regionp = (elf_ptrval)region;
2587+
2588+ if ( (region == NULL) ||
2589+ (ptrval < regionp) || /* start is before region */
2590+ (ptrval > regionp + regionsize) || /* start is after region */
2591+ (size > regionsize - (ptrval - regionp)) ) /* too big */
2592+ return 0;
2593+ return 1;
2594+}
2595+
2596+bool elf_access_ok(struct elf_binary * elf,
2597+ uint64_t ptrval, size_t size)
2598+{
2599+ if ( elf_ptrval_in_range(ptrval, size, elf->image_base, elf->size) )
2600+ return 1;
2601+ if ( elf_ptrval_in_range(ptrval, size, elf->dest_base, elf->dest_size) )
2602+ return 1;
2603+ if ( elf_ptrval_in_range(ptrval, size,
2604+ elf->caller_xdest_base, elf->caller_xdest_size) )
2605+ return 1;
2606+ elf_mark_broken(elf, "out of range access");
2607+ return 0;
2608+}
2609+
2610+void elf_memcpy_safe(struct elf_binary *elf, elf_ptrval dst,
2611+ elf_ptrval src, size_t size)
2612+{
2613+ if ( elf_access_ok(elf, dst, size) &&
2614+ elf_access_ok(elf, src, size) )
2615+ {
2616+ /* use memmove because these checks do not prove that the
2617+ * regions don't overlap and overlapping regions grant
2618+ * permission for compiler malice */
2619+ elf_memmove_unchecked(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), size);
2620+ }
2621+}
2622+
2623+void elf_memset_safe(struct elf_binary *elf, elf_ptrval dst, int c, size_t size)
2624+{
2625+ if ( elf_access_ok(elf, dst, size) )
2626+ {
2627+ elf_memset_unchecked(ELF_UNSAFE_PTR(dst), c, size);
2628+ }
2629+}
2630+
2631+uint64_t elf_access_unsigned(struct elf_binary * elf, elf_ptrval base,
2632+ uint64_t moreoffset, size_t size)
2633+{
2634+ elf_ptrval ptrval = base + moreoffset;
2635+ bool need_swap = elf_swap(elf);
2636 const uint8_t *u8;
2637 const uint16_t *u16;
2638 const uint32_t *u32;
2639 const uint64_t *u64;
2640
2641+ if ( !elf_access_ok(elf, ptrval, size) )
2642+ return 0;
2643+
2644 switch ( size )
2645 {
2646 case 1:
2647- u8 = ptr + offset;
2648+ u8 = (const void*)ptrval;
2649 return *u8;
2650 case 2:
2651- u16 = ptr + offset;
2652+ u16 = (const void*)ptrval;
2653 return need_swap ? bswap_16(*u16) : *u16;
2654 case 4:
2655- u32 = ptr + offset;
2656+ u32 = (const void*)ptrval;
2657 return need_swap ? bswap_32(*u32) : *u32;
2658 case 8:
2659- u64 = ptr + offset;
2660+ u64 = (const void*)ptrval;
2661 return need_swap ? bswap_64(*u64) : *u64;
2662 default:
2663 return 0;
2664 }
2665 }
2666
2667-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
2668- uint64_t offset, size_t size)
2669-{
2670- int need_swap = elf_swap(elf);
2671- const int8_t *s8;
2672- const int16_t *s16;
2673- const int32_t *s32;
2674- const int64_t *s64;
2675-
2676- switch ( size )
2677- {
2678- case 1:
2679- s8 = ptr + offset;
2680- return *s8;
2681- case 2:
2682- s16 = ptr + offset;
2683- return need_swap ? bswap_16(*s16) : *s16;
2684- case 4:
2685- s32 = ptr + offset;
2686- return need_swap ? bswap_32(*s32) : *s32;
2687- case 8:
2688- s64 = ptr + offset;
2689- return need_swap ? bswap_64(*s64) : *s64;
2690- default:
2691- return 0;
2692- }
2693-}
2694-
2695 uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr)
2696 {
2697- int elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
2698+ uint64_t elf_round = (elf_64bit(elf) ? 8 : 4) - 1;
2699
2700 return (addr + elf_round) & ~elf_round;
2701 }
2702
2703 /* ------------------------------------------------------------------------ */
2704
2705-int elf_shdr_count(struct elf_binary *elf)
2706+unsigned elf_shdr_count(struct elf_binary *elf)
2707 {
2708- return elf_uval(elf, elf->ehdr, e_shnum);
2709+ unsigned count = elf_uval(elf, elf->ehdr, e_shnum);
2710+ uint64_t max = elf->size / sizeof(Elf32_Shdr);
2711+ if (max > ~(unsigned)0)
2712+ max = ~(unsigned)0; /* Xen doesn't have limits.h :-/ */
2713+ if (count > max)
2714+ {
2715+ elf_mark_broken(elf, "far too many section headers");
2716+ count = max;
2717+ }
2718+ return count;
2719 }
2720
2721-int elf_phdr_count(struct elf_binary *elf)
2722+unsigned elf_phdr_count(struct elf_binary *elf)
2723 {
2724 return elf_uval(elf, elf->ehdr, e_phnum);
2725 }
2726
2727-const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name)
2728+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name)
2729 {
2730 uint64_t count = elf_shdr_count(elf);
2731- const elf_shdr *shdr;
2732+ ELF_HANDLE_DECL(elf_shdr) shdr;
2733 const char *sname;
2734- int i;
2735+ unsigned i;
2736
2737 for ( i = 0; i < count; i++ )
2738 {
2739 shdr = elf_shdr_by_index(elf, i);
2740+ if ( !elf_access_ok(elf, ELF_HANDLE_PTRVAL(shdr), 1) )
2741+ /* input has an insane section header count field */
2742+ break;
2743 sname = elf_section_name(elf, shdr);
2744 if ( sname && !strcmp(sname, name) )
2745 return shdr;
2746 }
2747- return NULL;
2748+ return ELF_INVALID_HANDLE(elf_shdr);
2749 }
2750
2751-const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index)
2752+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index)
2753 {
2754 uint64_t count = elf_shdr_count(elf);
2755- const void *ptr;
2756+ elf_ptrval ptr;
2757
2758 if ( index >= count )
2759- return NULL;
2760+ return ELF_INVALID_HANDLE(elf_shdr);
2761
2762- ptr = (elf->image
2763+ ptr = (ELF_IMAGE_BASE(elf)
2764 + elf_uval(elf, elf->ehdr, e_shoff)
2765 + elf_uval(elf, elf->ehdr, e_shentsize) * index);
2766- return ptr;
2767+ return ELF_MAKE_HANDLE(elf_shdr, ptr);
2768 }
2769
2770-const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index)
2771+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index)
2772 {
2773 uint64_t count = elf_uval(elf, elf->ehdr, e_phnum);
2774- const void *ptr;
2775+ elf_ptrval ptr;
2776
2777 if ( index >= count )
2778- return NULL;
2779+ return ELF_INVALID_HANDLE(elf_phdr);
2780
2781- ptr = (elf->image
2782+ ptr = (ELF_IMAGE_BASE(elf)
2783 + elf_uval(elf, elf->ehdr, e_phoff)
2784 + elf_uval(elf, elf->ehdr, e_phentsize) * index);
2785- return ptr;
2786+ return ELF_MAKE_HANDLE(elf_phdr, ptr);
2787 }
2788
2789-const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr)
2790+
2791+const char *elf_section_name(struct elf_binary *elf,
2792+ ELF_HANDLE_DECL(elf_shdr) shdr)
2793 {
2794- if ( elf->sec_strtab == NULL )
2795+ if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
2796 return "unknown";
2797- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
2798+
2799+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
2800 }
2801
2802-const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr)
2803+const char *elf_strval(struct elf_binary *elf, elf_ptrval start)
2804 {
2805- return elf->image + elf_uval(elf, shdr, sh_offset);
2806+ uint64_t length;
2807+
2808+ for ( length = 0; ; length++ ) {
2809+ if ( !elf_access_ok(elf, start + length, 1) )
2810+ return NULL;
2811+ if ( !elf_access_unsigned(elf, start, length, 1) )
2812+ /* ok */
2813+ return ELF_UNSAFE_PTR(start);
2814+ if ( length >= ELF_MAX_STRING_LENGTH )
2815+ {
2816+ elf_mark_broken(elf, "excessively long string");
2817+ return NULL;
2818+ }
2819+ }
2820 }
2821
2822-const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr)
2823+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start)
2824 {
2825- return elf->image
2826+ const char *str = elf_strval(elf, start);
2827+
2828+ if ( str == NULL )
2829+ return "(invalid)";
2830+ return str;
2831+}
2832+
2833+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
2834+{
2835+ return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset);
2836+}
2837+
2838+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
2839+{
2840+ return ELF_IMAGE_BASE(elf)
2841 + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
2842 }
2843
2844-const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr)
2845+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
2846 {
2847- return elf->image + elf_uval(elf, phdr, p_offset);
2848+ return ELF_IMAGE_BASE(elf)
2849+ + elf_uval(elf, phdr, p_offset);
2850 }
2851
2852-const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr)
2853+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
2854 {
2855- return elf->image
2856+ return ELF_IMAGE_BASE(elf)
2857 + elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
2858 }
2859
2860-const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol)
2861+ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol)
2862 {
2863- const void *ptr = elf_section_start(elf, elf->sym_tab);
2864- const void *end = elf_section_end(elf, elf->sym_tab);
2865- const elf_sym *sym;
2866+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
2867+ elf_ptrval end = elf_section_end(elf, elf->sym_tab);
2868+ ELF_HANDLE_DECL(elf_sym) sym;
2869 uint64_t info, name;
2870+ const char *sym_name;
2871
2872 for ( ; ptr < end; ptr += elf_size(elf, sym) )
2873 {
2874- sym = ptr;
2875+ sym = ELF_MAKE_HANDLE(elf_sym, ptr);
2876 info = elf_uval(elf, sym, st_info);
2877 name = elf_uval(elf, sym, st_name);
2878 if ( ELF32_ST_BIND(info) != STB_GLOBAL )
2879 continue;
2880- if ( strcmp(elf->sym_strtab + name, symbol) )
2881+ sym_name = elf_strval(elf, elf->sym_strtab + name);
2882+ if ( sym_name == NULL ) /* out of range, oops */
2883+ return ELF_INVALID_HANDLE(elf_sym);
2884+ if ( strcmp(sym_name, symbol) )
2885 continue;
2886 return sym;
2887 }
2888- return NULL;
2889+ return ELF_INVALID_HANDLE(elf_sym);
2890 }
2891
2892-const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index)
2893+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index)
2894 {
2895- const void *ptr = elf_section_start(elf, elf->sym_tab);
2896- const elf_sym *sym;
2897+ elf_ptrval ptr = elf_section_start(elf, elf->sym_tab);
2898+ ELF_HANDLE_DECL(elf_sym) sym;
2899
2900- sym = ptr + index * elf_size(elf, sym);
2901+ sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym));
2902 return sym;
2903 }
2904
2905-const char *elf_note_name(struct elf_binary *elf, const elf_note * note)
2906+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
2907 {
2908- return (void *)note + elf_size(elf, note);
2909+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
2910 }
2911
2912-const void *elf_note_desc(struct elf_binary *elf, const elf_note * note)
2913+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
2914 {
2915- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
2916+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
2917
2918- return (void *)note + elf_size(elf, note) + namesz;
2919+ return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz;
2920 }
2921
2922-uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note)
2923+uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
2924 {
2925- const void *desc = elf_note_desc(elf, note);
2926- int descsz = elf_uval(elf, note, descsz);
2927+ elf_ptrval desc = elf_note_desc(elf, note);
2928+ unsigned descsz = elf_uval(elf, note, descsz);
2929
2930 switch (descsz)
2931 {
2932@@ -228,11 +319,11 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note)
2933 }
2934 }
2935
2936-uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note,
2937+uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note,
2938 unsigned int unitsz, unsigned int idx)
2939 {
2940- const void *desc = elf_note_desc(elf, note);
2941- int descsz = elf_uval(elf, note, descsz);
2942+ elf_ptrval desc = elf_note_desc(elf, note);
2943+ unsigned descsz = elf_uval(elf, note, descsz);
2944
2945 if ( descsz % unitsz || idx >= descsz / unitsz )
2946 return 0;
2947@@ -248,24 +339,34 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note,
2948 }
2949 }
2950
2951-const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note)
2952+ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
2953 {
2954- int namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
2955- int descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
2956+ unsigned namesz = (elf_uval(elf, note, namesz) + 3) & ~3;
2957+ unsigned descsz = (elf_uval(elf, note, descsz) + 3) & ~3;
2958+
2959+ elf_ptrval ptrval = ELF_HANDLE_PTRVAL(note)
2960+ + elf_size(elf, note) + namesz + descsz;
2961
2962- return (void *)note + elf_size(elf, note) + namesz + descsz;
2963+ if ( ( ptrval <= ELF_HANDLE_PTRVAL(note) || /* wrapped or stuck */
2964+ !elf_access_ok(elf, ELF_HANDLE_PTRVAL(note), 1) ) )
2965+ ptrval = ELF_MAX_PTRVAL; /* terminate caller's loop */
2966+
2967+ return ELF_MAKE_HANDLE(elf_note, ptrval);
2968 }
2969
2970 /* ------------------------------------------------------------------------ */
2971
2972-int elf_is_elfbinary(const void *image)
2973+bool elf_is_elfbinary(const void *image_start, size_t image_size)
2974 {
2975- const Elf32_Ehdr *ehdr = image;
2976+ const Elf32_Ehdr *ehdr = image_start;
2977+
2978+ if ( image_size < sizeof(*ehdr) )
2979+ return 0;
2980
2981 return IS_ELF(*ehdr);
2982 }
2983
2984-int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr)
2985+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr)
2986 {
2987 uint64_t p_type = elf_uval(elf, phdr, p_type);
2988 uint64_t p_flags = elf_uval(elf, phdr, p_flags);
2989diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
2990index e8f6508..174f8da 100644
2991--- a/xen/include/xen/libelf.h
2992+++ b/xen/include/xen/libelf.h
2993@@ -29,6 +29,11 @@
2994 #error define architectural endianness
2995 #endif
2996
2997+#include <stdbool.h>
2998+
2999+typedef int elf_errorstatus; /* 0: ok; -ve (normally -1): error */
3000+typedef int elf_negerrnoval; /* 0: ok; -EFOO: error */
3001+
3002 #undef ELFSIZE
3003 #include "elfstructs.h"
3004 #ifdef __XEN__
3005@@ -42,12 +47,98 @@
3006
3007 struct elf_binary;
3008 typedef void elf_log_callback(struct elf_binary*, void *caller_data,
3009- int iserr, const char *fmt, va_list al);
3010+ bool iserr, const char *fmt, va_list al);
3011+
3012+#endif
3013+
3014+#define ELF_MAX_STRING_LENGTH 4096
3015+#define ELF_MAX_TOTAL_NOTE_COUNT 65536
3016+
3017+/* ------------------------------------------------------------------------ */
3018+
3019+/* Macros for accessing the input image and output area. */
3020+
3021+/*
3022+ * We abstract away the pointerness of these pointers, replacing
3023+ * various void*, char* and struct* with the following:
3024+ * elf_ptrval A pointer to a byte; one can do pointer arithmetic
3025+ * on this.
3026+ * HANDLE A pointer to a struct. There is one of these types
3027+ * for each pointer type - that is, for each "structname".
3028+ * In the arguments to the various HANDLE macros, structname
3029+ * must be a single identifier which is a typedef.
3030+ * It is not permitted to do arithmetic on these
3031+ * pointers. In the current code attempts to do so will
3032+ * compile, but in the next patch this will become a
3033+ * compile error.
3034+ */
3035+
3036+typedef uintptr_t elf_ptrval;
3037+
3038+#define ELF_REALPTR2PTRVAL(realpointer) ((elf_ptrval)(realpointer))
3039+ /* Converts an actual C pointer into a PTRVAL */
3040+
3041+#define ELF_HANDLE_DECL(structname) structname##_handle
3042+ /* Provides a type declaration for a HANDLE. */
3043
3044+#ifdef __XEN__
3045+# define ELF_PRPTRVAL "lu"
3046+ /*
3047+ * PRIuPTR is misdefined in xen/include/xen/inttypes.h, on 32-bit,
3048+ * to "u", when in fact uintptr_t is an unsigned long.
3049+ */
3050+#else
3051+# define ELF_PRPTRVAL PRIuPTR
3052 #endif
3053+ /* printf format a la PRId... for a PTRVAL */
3054+
3055+#define ELF_DEFINE_HANDLE(structname) \
3056+ typedef union { \
3057+ elf_ptrval ptrval; \
3058+ const structname *typeonly; /* for sizeof, offsetof, &c only */ \
3059+ } structname##_handle;
3060+ /*
3061+ * This must be invoked for each HANDLE type to define
3062+ * the actual C type used for that kind of HANDLE.
3063+ */
3064+
3065+#define ELF_MAKE_HANDLE(structname, ptrval) ((structname##_handle){ ptrval })
3066+ /* Converts a PTRVAL to a HANDLE */
3067+
3068+#define ELF_IMAGE_BASE(elf) ((elf_ptrval)(elf)->image_base)
3069+ /* Returns the base of the image as a PTRVAL. */
3070+
3071+#define ELF_HANDLE_PTRVAL(handleval) ((handleval).ptrval)
3072+ /* Converts a HANDLE to a PTRVAL. */
3073+
3074+#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_ptrval)(ptrval))
3075+ /*
3076+ * Turns a PTRVAL into an actual C pointer. Before this is done
3077+ * the caller must have ensured that the PTRVAL does in fact point
3078+ * to a permissible location.
3079+ */
3080+
3081+/* PTRVALs can be INVALID (ie, NULL). */
3082+#define ELF_INVALID_PTRVAL ((elf_ptrval)0) /* returns NULL PTRVAL */
3083+#define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \
3084+ ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL)
3085+#define ELF_PTRVAL_VALID(ptrval) (!!(ptrval)) /* } */
3086+#define ELF_HANDLE_VALID(handleval) (!!(handleval).ptrval) /* } predicates */
3087+#define ELF_PTRVAL_INVALID(ptrval) (!ELF_PTRVAL_VALID((ptrval))) /* } */
3088+
3089+#define ELF_MAX_PTRVAL (~(elf_ptrval)0)
3090+ /* PTRVAL value guaranteed to compare > to any valid PTRVAL */
3091+
3092+/* For internal use by other macros here */
3093+#define ELF__HANDLE_FIELD_TYPE(handleval, elm) \
3094+ typeof((handleval).typeonly->elm)
3095+#define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \
3096+ offsetof(typeof(*(handleval).typeonly),elm)
3097+
3098
3099 /* ------------------------------------------------------------------------ */
3100
3101+
3102 typedef union {
3103 Elf32_Ehdr e32;
3104 Elf64_Ehdr e64;
3105@@ -83,20 +174,32 @@ typedef union {
3106 Elf64_Note e64;
3107 } elf_note;
3108
3109+ELF_DEFINE_HANDLE(elf_ehdr)
3110+ELF_DEFINE_HANDLE(elf_shdr)
3111+ELF_DEFINE_HANDLE(elf_phdr)
3112+ELF_DEFINE_HANDLE(elf_sym)
3113+ELF_DEFINE_HANDLE(elf_note)
3114+
3115 struct elf_binary {
3116 /* elf binary */
3117- const char *image;
3118+ const void *image_base;
3119 size_t size;
3120 char class;
3121 char data;
3122
3123- const elf_ehdr *ehdr;
3124- const char *sec_strtab;
3125- const elf_shdr *sym_tab;
3126- const char *sym_strtab;
3127+ ELF_HANDLE_DECL(elf_ehdr) ehdr;
3128+ elf_ptrval sec_strtab;
3129+ ELF_HANDLE_DECL(elf_shdr) sym_tab;
3130+ uint64_t sym_strtab;
3131
3132 /* loaded to */
3133- char *dest;
3134+ /*
3135+ * dest_base and dest_size are trusted and must be correct;
3136+ * whenever dest_size is not 0, both of these must be valid
3137+ * so long as the struct elf_binary is in use.
3138+ */
3139+ char *dest_base;
3140+ size_t dest_size;
3141 uint64_t pstart;
3142 uint64_t pend;
3143 uint64_t reloc_offset;
3144@@ -104,12 +207,22 @@ struct elf_binary {
3145 uint64_t bsd_symtab_pstart;
3146 uint64_t bsd_symtab_pend;
3147
3148+ /*
3149+ * caller's other acceptable destination
3150+ *
3151+ * Again, these are trusted and must be valid (or 0) so long
3152+ * as the struct elf_binary is in use.
3153+ */
3154+ void *caller_xdest_base;
3155+ uint64_t caller_xdest_size;
3156+
3157 #ifndef __XEN__
3158 /* misc */
3159 elf_log_callback *log_callback;
3160 void *log_caller_data;
3161 #endif
3162- int verbose;
3163+ bool verbose;
3164+ const char *broken;
3165 };
3166
3167 /* ------------------------------------------------------------------------ */
3168@@ -127,88 +240,145 @@ struct elf_binary {
3169 #define elf_lsb(elf) (ELFDATA2LSB == (elf)->data)
3170 #define elf_swap(elf) (NATIVE_ELFDATA != (elf)->data)
3171
3172-#define elf_uval(elf, str, elem) \
3173- ((ELFCLASS64 == (elf)->class) \
3174- ? elf_access_unsigned((elf), (str), \
3175- offsetof(typeof(*(str)),e64.elem), \
3176- sizeof((str)->e64.elem)) \
3177- : elf_access_unsigned((elf), (str), \
3178- offsetof(typeof(*(str)),e32.elem), \
3179- sizeof((str)->e32.elem)))
3180-
3181-#define elf_sval(elf, str, elem) \
3182- ((ELFCLASS64 == (elf)->class) \
3183- ? elf_access_signed((elf), (str), \
3184- offsetof(typeof(*(str)),e64.elem), \
3185- sizeof((str)->e64.elem)) \
3186- : elf_access_signed((elf), (str), \
3187- offsetof(typeof(*(str)),e32.elem), \
3188- sizeof((str)->e32.elem)))
3189-
3190-#define elf_size(elf, str) \
3191- ((ELFCLASS64 == (elf)->class) \
3192- ? sizeof((str)->e64) : sizeof((str)->e32))
3193+#define elf_uval_3264(elf, handle, elem) \
3194+ elf_access_unsigned((elf), (handle).ptrval, \
3195+ offsetof(typeof(*(handle).typeonly),elem), \
3196+ sizeof((handle).typeonly->elem))
3197+
3198+#define elf_uval(elf, handle, elem) \
3199+ ((ELFCLASS64 == (elf)->class) \
3200+ ? elf_uval_3264(elf, handle, e64.elem) \
3201+ : elf_uval_3264(elf, handle, e32.elem))
3202+ /*
3203+ * Reads an unsigned field in a header structure in the ELF.
3204+ * str is a HANDLE, and elem is the field name in it.
3205+ */
3206
3207-uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
3208+
3209+#define elf_size(elf, handle_or_handletype) ({ \
3210+ typeof(handle_or_handletype) elf_size__dummy; \
3211+ ((ELFCLASS64 == (elf)->class) \
3212+ ? sizeof(elf_size__dummy.typeonly->e64) \
3213+ : sizeof(elf_size__dummy.typeonly->e32)); \
3214+})
3215+ /*
3216+ * Returns the size of the substructure for the appropriate 32/64-bitness.
3217+ * str should be a HANDLE.
3218+ */
3219+
3220+uint64_t elf_access_unsigned(struct elf_binary *elf, elf_ptrval ptr,
3221 uint64_t offset, size_t size);
3222-int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
3223- uint64_t offset, size_t size);
3224+ /* Reads a field at arbitrary offset and alignemnt */
3225
3226 uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
3227
3228+const char *elf_strval(struct elf_binary *elf, elf_ptrval start);
3229+ /* may return NULL if the string is out of range etc. */
3230+
3231+const char *elf_strfmt(struct elf_binary *elf, elf_ptrval start);
3232+ /* like elf_strval but returns "(invalid)" instead of NULL */
3233+
3234+void elf_memcpy_safe(struct elf_binary*, elf_ptrval dst, elf_ptrval src, size_t);
3235+void elf_memset_safe(struct elf_binary*, elf_ptrval dst, int c, size_t);
3236+ /*
3237+ * Versions of memcpy and memset which arrange never to write
3238+ * outside permitted areas.
3239+ */
3240+
3241+bool elf_access_ok(struct elf_binary * elf,
3242+ uint64_t ptrval, size_t size);
3243+
3244+#define elf_store_val(elf, type, ptr, val) \
3245+ ({ \
3246+ typeof(type) elf_store__val = (val); \
3247+ elf_ptrval elf_store__targ = ptr; \
3248+ if (elf_access_ok((elf), elf_store__targ, \
3249+ sizeof(elf_store__val))) { \
3250+ elf_memcpy_unchecked((void*)elf_store__targ, &elf_store__val, \
3251+ sizeof(elf_store__val)); \
3252+ } \
3253+ }) \
3254+ /* Stores a value at a particular PTRVAL. */
3255+
3256+#define elf_store_field(elf, hdr, elm, val) \
3257+ (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \
3258+ ELF_HANDLE_PTRVAL(hdr) + ELF__HANDLE_FIELD_OFFSET(hdr, elm), \
3259+ (val)))
3260+ /* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */
3261+
3262+
3263 /* ------------------------------------------------------------------------ */
3264 /* xc_libelf_tools.c */
3265
3266-int elf_shdr_count(struct elf_binary *elf);
3267-int elf_phdr_count(struct elf_binary *elf);
3268+unsigned elf_shdr_count(struct elf_binary *elf);
3269+unsigned elf_phdr_count(struct elf_binary *elf);
3270
3271-const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name);
3272-const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index);
3273-const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index);
3274+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name);
3275+ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, unsigned index);
3276+ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index);
3277
3278-const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr);
3279-const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr);
3280-const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr);
3281+const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
3282+elf_ptrval elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
3283+elf_ptrval elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
3284
3285-const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr);
3286-const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr);
3287+elf_ptrval elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
3288+elf_ptrval elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
3289
3290-const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol);
3291-const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index);
3292+ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
3293+ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, unsigned index);
3294
3295-const char *elf_note_name(struct elf_binary *elf, const elf_note * note);
3296-const void *elf_note_desc(struct elf_binary *elf, const elf_note * note);
3297-uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note);
3298-uint64_t elf_note_numeric_array(struct elf_binary *, const elf_note *,
3299+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
3300+elf_ptrval elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
3301+uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
3302+uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
3303 unsigned int unitsz, unsigned int idx);
3304-const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note);
3305
3306-int elf_is_elfbinary(const void *image);
3307-int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr);
3308+/*
3309+ * If you use elf_note_next in a loop, you must put a nontrivial upper
3310+ * bound on the returned value as part of your loop condition. In
3311+ * some cases elf_note_next will substitute ELF_PTRVAL_MAX as return
3312+ * value to indicate that the iteration isn't going well (for example,
3313+ * the putative "next" value would be earlier in memory). In this
3314+ * case the caller's loop must terminate. Checking against the
3315+ * end of the notes segment with a strict inequality is sufficient.
3316+ */
3317+ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
3318+
3319+/* (Only) checks that the image has the right magic number. */
3320+bool elf_is_elfbinary(const void *image_start, size_t image_size);
3321+
3322+bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr);
3323
3324 /* ------------------------------------------------------------------------ */
3325 /* xc_libelf_loader.c */
3326
3327-int elf_init(struct elf_binary *elf, const char *image, size_t size);
3328+elf_errorstatus elf_init(struct elf_binary *elf, const char *image, size_t size);
3329+ /*
3330+ * image and size must be correct. They will be recorded in
3331+ * *elf, and must remain valid while the elf is in use.
3332+ */
3333 #ifdef __XEN__
3334 void elf_set_verbose(struct elf_binary *elf);
3335 #else
3336 void elf_set_log(struct elf_binary *elf, elf_log_callback*,
3337- void *log_caller_pointer, int verbose);
3338+ void *log_caller_pointer, bool verbose);
3339 #endif
3340
3341 void elf_parse_binary(struct elf_binary *elf);
3342-int elf_load_binary(struct elf_binary *elf);
3343+elf_errorstatus elf_load_binary(struct elf_binary *elf);
3344
3345-void *elf_get_ptr(struct elf_binary *elf, unsigned long addr);
3346+elf_ptrval elf_get_ptr(struct elf_binary *elf, unsigned long addr);
3347 uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);
3348
3349 void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */
3350
3351+void elf_mark_broken(struct elf_binary *elf, const char *msg);
3352+const char *elf_check_broken(const struct elf_binary *elf); /* NULL means OK */
3353+
3354 /* ------------------------------------------------------------------------ */
3355 /* xc_libelf_relocate.c */
3356
3357-int elf_reloc(struct elf_binary *elf);
3358+elf_errorstatus elf_reloc(struct elf_binary *elf);
3359
3360 /* ------------------------------------------------------------------------ */
3361 /* xc_libelf_dominfo.c */
3362@@ -232,9 +402,9 @@ struct xen_elfnote {
3363
3364 struct elf_dom_parms {
3365 /* raw */
3366- const char *guest_info;
3367- const void *elf_note_start;
3368- const void *elf_note_end;
3369+ elf_ptrval guest_info;
3370+ elf_ptrval elf_note_start;
3371+ elf_ptrval elf_note_end;
3372 struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1];
3373
3374 /* parsed */
3375@@ -242,8 +412,8 @@ struct elf_dom_parms {
3376 char guest_ver[16];
3377 char xen_ver[16];
3378 char loader[16];
3379- int pae;
3380- int bsd_symtab;
3381+ int pae; /* some kind of enum apparently */
3382+ bool bsd_symtab;
3383 uint64_t virt_base;
3384 uint64_t virt_entry;
3385 uint64_t virt_hypercall;
3386@@ -273,10 +443,44 @@ int elf_xen_parse_features(const char *features,
3387 uint32_t *required);
3388 int elf_xen_parse_note(struct elf_binary *elf,
3389 struct elf_dom_parms *parms,
3390- const elf_note *note);
3391+ ELF_HANDLE_DECL(elf_note) note);
3392 int elf_xen_parse_guest_info(struct elf_binary *elf,
3393 struct elf_dom_parms *parms);
3394 int elf_xen_parse(struct elf_binary *elf,
3395 struct elf_dom_parms *parms);
3396
3397+static inline void *elf_memcpy_unchecked(void *dest, const void *src, size_t n)
3398+ { return memcpy(dest, src, n); }
3399+static inline void *elf_memmove_unchecked(void *dest, const void *src, size_t n)
3400+ { return memmove(dest, src, n); }
3401+static inline void *elf_memset_unchecked(void *s, int c, size_t n)
3402+ { return memset(s, c, n); }
3403+ /*
3404+ * Unsafe versions of memcpy, memmove memset which take actual C
3405+ * pointers. These are just like the real functions.
3406+ * We provide these so that in libelf-private.h we can #define
3407+ * memcpy, memset and memmove to undefined MISTAKE things.
3408+ */
3409+
3410+
3411+/* Advances past amount bytes of the current destination area. */
3412+static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount)
3413+{
3414+ if ( elf->dest_base == NULL )
3415+ {
3416+ elf_mark_broken(elf, "advancing in null image");
3417+ }
3418+ else if ( elf->dest_size >= amount )
3419+ {
3420+ elf->dest_base += amount;
3421+ elf->dest_size -= amount;
3422+ }
3423+ else
3424+ {
3425+ elf->dest_size = 0;
3426+ elf_mark_broken(elf, "advancing past end (image very short?)");
3427+ }
3428+}
3429+
3430+
3431 #endif /* __XEN_LIBELF_H__ */