diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-06-21 13:31:08 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-06-26 08:36:24 +0000 |
commit | 50869d41a1af768fb0c39ff2d059a8bec102bc91 (patch) | |
tree | b42a42eef829a8aad6c7b4d1b8252aa4aa435809 | |
parent | 052803fcf280e0ade32c0ca64438c37476c84525 (diff) | |
download | alpine_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/APKBUILD | 6 | ||||
-rw-r--r-- | main/xen/xsa55.patch | 3431 |
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> |
4 | pkgname=xen | 4 | pkgname=xen |
5 | pkgver=4.2.2 | 5 | pkgver=4.2.2 |
6 | pkgrel=2 | 6 | pkgrel=3 |
7 | pkgdesc="Xen hypervisor" | 7 | pkgdesc="Xen hypervisor" |
8 | url="http://www.xen.org/" | 8 | url="http://www.xen.org/" |
9 | arch="x86 x86_64" | 9 | arch="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 | |||
155 | 83a9cdd035bcd18bf035434a1ba08c38 xsa52-4.2-unstable.patch | 156 | 83a9cdd035bcd18bf035434a1ba08c38 xsa52-4.2-unstable.patch |
156 | 03a1a4ebc470ee7e638e04db2701a4f7 xsa53-4.2.patch | 157 | 03a1a4ebc470ee7e638e04db2701a4f7 xsa53-4.2.patch |
157 | a8393d1ec6b886ea72ffe624a04ee10a xsa54.patch | 158 | a8393d1ec6b886ea72ffe624a04ee10a xsa54.patch |
159 | 42cd104f2a33d67938a63a6372cff573 xsa55.patch | ||
158 | e70b9128ffc2175cea314a533a7d8457 xsa56.patch | 160 | e70b9128ffc2175cea314a533a7d8457 xsa56.patch |
159 | c1d1a415415b0192e5dae9032962bf61 fix-pod2man-choking.patch | 161 | c1d1a415415b0192e5dae9032962bf61 fix-pod2man-choking.patch |
160 | 95d8af17bf844d41a015ff32aae51ba1 xenstored.initd | 162 | 95d8af17bf844d41a015ff32aae51ba1 xenstored.initd |
@@ -180,6 +182,7 @@ dc23077028584e71a08dd0dc9e81552c76744a5ce9d39df5958a95ae9cf3107b xsa48-4.2.patc | |||
180 | 5b8582185bf90386729e81db1f7780c69a891b074a87d9a619a90d6f639bea13 xsa52-4.2-unstable.patch | 182 | 5b8582185bf90386729e81db1f7780c69a891b074a87d9a619a90d6f639bea13 xsa52-4.2-unstable.patch |
181 | 785f7612bd229f7501f4e98e4760f307d90c64305ee14707d262b77f05fa683d xsa53-4.2.patch | 183 | 785f7612bd229f7501f4e98e4760f307d90c64305ee14707d262b77f05fa683d xsa53-4.2.patch |
182 | 5d94946b3c9cba52aae2bffd4b0ebb11d09181650b5322a3c85170674a05f6b7 xsa54.patch | 184 | 5d94946b3c9cba52aae2bffd4b0ebb11d09181650b5322a3c85170674a05f6b7 xsa54.patch |
185 | ac3ebaf3ec37e28ba08e23d63626d7aaccf0a3f282dd0af9c24cc4df3fd8fae0 xsa55.patch | ||
183 | a691c5f5332a42c0d38ddb4dc037eb902f01ba31033b64c47d02909a8de0257d xsa56.patch | 186 | a691c5f5332a42c0d38ddb4dc037eb902f01ba31033b64c47d02909a8de0257d xsa56.patch |
184 | b4e7d43364a06b2cb04527db3e9567524bc489fef475709fd8493ebf1e62406d fix-pod2man-choking.patch | 187 | b4e7d43364a06b2cb04527db3e9567524bc489fef475709fd8493ebf1e62406d fix-pod2man-choking.patch |
185 | 81d335946c81311c86e2f2112b773a568a5a530c0db9802b2fe559e71bb8b381 xenstored.initd | 188 | 81d335946c81311c86e2f2112b773a568a5a530c0db9802b2fe559e71bb8b381 xenstored.initd |
@@ -205,6 +208,7 @@ bda9105793f2327e1317991762120d0668af0e964076b18c9fdbfd509984b2e88d85df95702c46b2 | |||
205 | b64a965fab8534958e453c493211ed3a6555aafb90d18f6d56a45b41d3086a0029aee85b6b6eb93b0d861d5fdc0ef10fc32e9b4f83593b37c43922d838085dd8 xsa52-4.2-unstable.patch | 208 | b64a965fab8534958e453c493211ed3a6555aafb90d18f6d56a45b41d3086a0029aee85b6b6eb93b0d861d5fdc0ef10fc32e9b4f83593b37c43922d838085dd8 xsa52-4.2-unstable.patch |
206 | 9b08924e563e79d2b308c1521da520c0579b334b61ac99a5593eabdb96dbda2da898b542cc47bda6d663c68343216d9d29c04853b6d1b6ecdde964b0cbb3f7ab xsa53-4.2.patch | 209 | 9b08924e563e79d2b308c1521da520c0579b334b61ac99a5593eabdb96dbda2da898b542cc47bda6d663c68343216d9d29c04853b6d1b6ecdde964b0cbb3f7ab xsa53-4.2.patch |
207 | c9010be637d4f96ef03c880e1ef28228f762c5980108380a105bd190b631a882c8dff81e9421246d88d597e72f69ad1a8c672be6ddd06936acfcacd4575a2650 xsa54.patch | 210 | c9010be637d4f96ef03c880e1ef28228f762c5980108380a105bd190b631a882c8dff81e9421246d88d597e72f69ad1a8c672be6ddd06936acfcacd4575a2650 xsa54.patch |
211 | b4f43095163146a29ae258575bb03bd45f5a315d3cca7434a0b88c18eb1b6e1cf17ef13b4ac428a08797271a3dbc756d3f705a990991c8d2fc96f0f272c3665a xsa55.patch | ||
208 | 26a1c2cc92ddd4c1ab6712b0e41a0135d0e76a7fe3a14b651fb0235e352e5a24077414371acccb93058b7ce4d882b667386811170ba74570c53165837bcd983d xsa56.patch | 212 | 26a1c2cc92ddd4c1ab6712b0e41a0135d0e76a7fe3a14b651fb0235e352e5a24077414371acccb93058b7ce4d882b667386811170ba74570c53165837bcd983d xsa56.patch |
209 | ffb1113fcec0853b690c177655c7d1136388efdebf0d7f625b80481b98eadd3e9ef461442ced53e11acf0e347800a2b0a41e18b05065b5d04bffdd8a4e127cec fix-pod2man-choking.patch | 213 | ffb1113fcec0853b690c177655c7d1136388efdebf0d7f625b80481b98eadd3e9ef461442ced53e11acf0e347800a2b0a41e18b05065b5d04bffdd8a4e127cec fix-pod2man-choking.patch |
210 | 792b062e8a16a2efd3cb4662d379d1500527f2a7ca9228d7831c2bd34f3b9141df949153ea05463a7758c3e3dd9a4182492ad5505fa38e298ecf8c99db77b4ee xenstored.initd | 214 | 792b062e8a16a2efd3cb4662d379d1500527f2a7ca9228d7831c2bd34f3b9141df949153ea05463a7758c3e3dd9a4182492ad5505fa38e298ecf8c99db77b4ee 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 @@ | |||
1 | diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile | ||
2 | index 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 | ||
21 | diff --git a/tools/libxc/ia64/xc_ia64_dom_fwloader.c b/tools/libxc/ia64/xc_ia64_dom_fwloader.c | ||
22 | index 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. */ | ||
34 | diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c | ||
35 | index 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 | { | ||
105 | diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h | ||
106 | index 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 | |||
198 | diff --git a/tools/libxc/xc_dom_binloader.c b/tools/libxc/xc_dom_binloader.c | ||
199 | index 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 | |||
257 | diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c | ||
258 | index 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, | ||
379 | diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c | ||
380 | index 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 | { | ||
751 | diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c | ||
752 | index 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 | |||
781 | diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c | ||
782 | index 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; | ||
962 | diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c | ||
963 | index 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); | ||
1040 | diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c | ||
1041 | index 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 | |||
1090 | diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c | ||
1091 | index 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++ ) | ||
1112 | diff --git a/tools/libxc/xc_offline_page.c b/tools/libxc/xc_offline_page.c | ||
1113 | index 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; | ||
1128 | diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c | ||
1129 | index 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 | |||
1141 | diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h | ||
1142 | index 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 | |||
1154 | diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c | ||
1155 | index 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 | } | ||
1308 | diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c | ||
1309 | index 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) | ||
1349 | diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c | ||
1350 | index 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)); | ||
1371 | diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c | ||
1372 | index 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 | /* | ||
1460 | diff --git a/xen/common/libelf/Makefile b/xen/common/libelf/Makefile | ||
1461 | index 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 | |||
1473 | diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c | ||
1474 | index 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 | |||
1792 | diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c | ||
1793 | index 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; | ||
2141 | diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h | ||
2142 | index 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 | /* | ||
2174 | diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c | ||
2175 | deleted file mode 100644 | ||
2176 | index 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 | - */ | ||
2552 | diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c | ||
2553 | index 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); | ||
2989 | diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h | ||
2990 | index 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__ */ | ||