]>
Commit | Line | Data |
---|---|---|
23d51c33 JR |
1 | From db14d5bd9b6508adfcd2b910f454fae12fa4ba00 Mon Sep 17 00:00:00 2001 |
2 | From: Ian Jackson <ian.jackson@eu.citrix.com> | |
3 | Date: Fri, 14 Jun 2013 16:43:17 +0100 | |
4 | Subject: [PATCH 10/23] libelf: check nul-terminated strings properly | |
5 | ||
6 | It is not safe to simply take pointers into the ELF and use them as C | |
7 | pointers. They might not be properly nul-terminated (and the pointers | |
8 | might be wild). | |
9 | ||
10 | So we are going to introduce a new function elf_strval for safely | |
11 | getting strings. This will check that the addresses are in range and | |
12 | that there is a proper nul-terminated string. Of course it might | |
13 | discover that there isn't. In that case, it will be made to fail. | |
14 | This means that elf_note_name might fail, too. | |
15 | ||
16 | For the benefit of call sites which are just going to pass the value | |
17 | to a printf-like function, we provide elf_strfmt which returns | |
18 | "(invalid)" on failure rather than NULL. | |
19 | ||
20 | In this patch we introduce dummy definitions of these functions. We | |
21 | introduce calls to elf_strval and elf_strfmt everywhere, and update | |
22 | all the call sites with appropriate error checking. | |
23 | ||
24 | There is not yet any semantic change, since before this patch all the | |
25 | places where we introduce elf_strval dereferenced the value anyway, so | |
26 | it mustn't have been NULL. | |
27 | ||
28 | In future patches, when elf_strval is made able return NULL, when it | |
29 | does so it will mark the elf "broken" so that an appropriate | |
30 | diagnostic can be printed. | |
31 | ||
32 | This is part of the fix to a security issue, XSA-55. | |
33 | ||
34 | Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> | |
35 | Acked-by: Ian Campbell <ian.campbell@citrix.com> | |
36 | Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | |
37 | --- | |
38 | tools/xcutils/readnotes.c | 11 ++++++++--- | |
39 | xen/common/libelf/libelf-dominfo.c | 13 ++++++++++--- | |
40 | xen/common/libelf/libelf-tools.c | 10 +++++++--- | |
41 | xen/include/xen/libelf.h | 7 +++++-- | |
42 | 4 files changed, 30 insertions(+), 11 deletions(-) | |
43 | ||
44 | diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c | |
45 | index 7ff2530..cfae994 100644 | |
46 | --- a/tools/xcutils/readnotes.c | |
47 | +++ b/tools/xcutils/readnotes.c | |
48 | @@ -63,7 +63,7 @@ struct setup_header { | |
49 | static void print_string_note(const char *prefix, struct elf_binary *elf, | |
50 | ELF_HANDLE_DECL(elf_note) note) | |
51 | { | |
52 | - printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note)); | |
53 | + printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note))); | |
54 | } | |
55 | ||
56 | static void print_numeric_note(const char *prefix, struct elf_binary *elf, | |
57 | @@ -103,10 +103,14 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, | |
58 | { | |
59 | ELF_HANDLE_DECL(elf_note) note; | |
60 | int notes_found = 0; | |
61 | + const char *this_note_name; | |
62 | ||
63 | for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) ) | |
64 | { | |
65 | - if (0 != strcmp(elf_note_name(elf, note), "Xen")) | |
66 | + this_note_name = elf_note_name(elf, note); | |
67 | + if (NULL == this_note_name) | |
68 | + continue; | |
69 | + if (0 != strcmp(this_note_name, "Xen")) | |
70 | continue; | |
71 | ||
72 | notes_found++; | |
73 | @@ -294,7 +298,8 @@ int main(int argc, char **argv) | |
74 | ||
75 | shdr = elf_shdr_by_name(&elf, "__xen_guest"); | |
76 | if (ELF_HANDLE_VALID(shdr)) | |
77 | - printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr)); | |
78 | + printf("__xen_guest: %s\n", | |
79 | + elf_strfmt(&elf, elf_section_start(&elf, shdr))); | |
80 | ||
81 | return 0; | |
82 | } | |
83 | diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c | |
84 | index 7140d59..b217f8f 100644 | |
85 | --- a/xen/common/libelf/libelf-dominfo.c | |
86 | +++ b/xen/common/libelf/libelf-dominfo.c | |
87 | @@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf, | |
88 | ||
89 | if ( note_desc[type].str ) | |
90 | { | |
91 | - str = elf_note_desc(elf, note); | |
92 | + str = elf_strval(elf, elf_note_desc(elf, note)); | |
93 | + if (str == NULL) | |
94 | + /* elf_strval will mark elf broken if it fails so no need to log */ | |
95 | + return 0; | |
96 | elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__, | |
97 | note_desc[type].name, str); | |
98 | parms->elf_notes[type].type = XEN_ENT_STR; | |
99 | @@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf, | |
100 | { | |
101 | int xen_elfnotes = 0; | |
102 | ELF_HANDLE_DECL(elf_note) note; | |
103 | + const char *note_name; | |
104 | ||
105 | parms->elf_note_start = start; | |
106 | parms->elf_note_end = end; | |
107 | @@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf, | |
108 | ELF_HANDLE_PTRVAL(note) < parms->elf_note_end; | |
109 | note = elf_note_next(elf, note) ) | |
110 | { | |
111 | - if ( strcmp(elf_note_name(elf, note), "Xen") ) | |
112 | + note_name = elf_note_name(elf, note); | |
113 | + if ( note_name == NULL ) | |
114 | + continue; | |
115 | + if ( strcmp(note_name, "Xen") ) | |
116 | continue; | |
117 | if ( elf_xen_parse_note(elf, parms, note) ) | |
118 | return -1; | |
119 | @@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf, | |
120 | parms->elf_note_start = ELF_INVALID_PTRVAL; | |
121 | parms->elf_note_end = ELF_INVALID_PTRVAL; | |
122 | elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, | |
123 | - parms->guest_info); | |
124 | + elf_strfmt(elf, parms->guest_info)); | |
125 | elf_xen_parse_guest_info(elf, parms); | |
126 | break; | |
127 | } | |
128 | diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c | |
129 | index f1fd886..3a0cde1 100644 | |
130 | --- a/xen/common/libelf/libelf-tools.c | |
131 | +++ b/xen/common/libelf/libelf-tools.c | |
132 | @@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf, | |
133 | if ( ELF_PTRVAL_INVALID(elf->sec_strtab) ) | |
134 | return "unknown"; | |
135 | ||
136 | - return elf->sec_strtab + elf_uval(elf, shdr, sh_name); | |
137 | + return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name)); | |
138 | } | |
139 | ||
140 | ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr) | |
141 | @@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym | |
142 | ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab); | |
143 | ELF_HANDLE_DECL(elf_sym) sym; | |
144 | uint64_t info, name; | |
145 | + const char *sym_name; | |
146 | ||
147 | for ( ; ptr < end; ptr += elf_size(elf, sym) ) | |
148 | { | |
149 | @@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym | |
150 | name = elf_uval(elf, sym, st_name); | |
151 | if ( ELF32_ST_BIND(info) != STB_GLOBAL ) | |
152 | continue; | |
153 | - if ( strcmp(elf->sym_strtab + name, symbol) ) | |
154 | + sym_name = elf_strval(elf, elf->sym_strtab + name); | |
155 | + if ( sym_name == NULL ) /* out of range, oops */ | |
156 | + return ELF_INVALID_HANDLE(elf_sym); | |
157 | + if ( strcmp(sym_name, symbol) ) | |
158 | continue; | |
159 | return sym; | |
160 | } | |
161 | @@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index) | |
162 | ||
163 | const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note) | |
164 | { | |
165 | - return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note); | |
166 | + return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note)); | |
167 | } | |
168 | ||
169 | ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note) | |
170 | diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h | |
171 | index cefd3d3..af5b5c5 100644 | |
172 | --- a/xen/include/xen/libelf.h | |
173 | +++ b/xen/include/xen/libelf.h | |
174 | @@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr, | |
175 | uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr); | |
176 | ||
177 | ||
178 | +#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */ | |
179 | +#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */ | |
180 | + | |
181 | #define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz)) | |
182 | #define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz)) | |
183 | /* | |
184 | @@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n | |
185 | ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index); | |
186 | ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index); | |
187 | ||
188 | -const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); | |
189 | +const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */ | |
190 | ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); | |
191 | ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); | |
192 | ||
193 | @@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el | |
194 | ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol); | |
195 | ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index); | |
196 | ||
197 | -const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); | |
198 | +const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */ | |
199 | ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); | |
200 | uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); | |
201 | uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note), | |
202 | -- | |
203 | 1.7.2.5 | |
204 |