From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xensource.com
Cc: andrew.cooper3@citrix.com, mattjd@gmail.com,
Ian Jackson <ian.jackson@eu.citrix.com>,
security@xen.org
Subject: [PATCH 09/16] libelf: check nul-terminated strings properly
Date: Tue, 4 Jun 2013 18:59:56 +0100 [thread overview]
Message-ID: <1370368803-9436-10-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1370368803-9436-1-git-send-email-ian.jackson@eu.citrix.com>
It is not safe to simply take pointers into the ELF and use them as C
pointers. They might not be properly nul-terminated (and the pointers
might be wild).
So we are going to introduce a new function elf_strval for safely
getting strings. This will check that the addresses are in range and
that there is a proper nul-terminated string. Of course it might
discover that there isn't. In that case, it will be made to fail.
This means that elf_note_name might fail, too.
For the benefit of call sites which are just going to pass the value
to a printf-like function, we provide elf_strfmt which returns
"(invalid)" on failure rather than NULL.
In this patch we introduce dummy definitions of these functions. We
introduce calls to elf_strval and elf_strfmt everywhere, and update
all the call sites with appropriate error checking.
There is not yet any semantic change, since before this patch all the
places where we introduce elf_strval dereferenced the value anyway, so
it mustn't have been NULL.
In future patches, when elf_strval is made able return NULL, when it
does so it will mark the elf "broken" so that an appropriate
diagnostic can be printed.
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
v2: Fix coding style, in one "if" statement.
---
tools/xcutils/readnotes.c | 10 +++++++---
xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
xen/common/libelf/libelf-tools.c | 10 +++++++---
xen/include/xen/libelf.h | 7 +++++--
4 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
index 7ff2530..ca86ba5 100644
--- a/tools/xcutils/readnotes.c
+++ b/tools/xcutils/readnotes.c
@@ -63,7 +63,7 @@ struct setup_header {
static void print_string_note(const char *prefix, struct elf_binary *elf,
ELF_HANDLE_DECL(elf_note) note)
{
- printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note));
+ printf("%s: %s\n", prefix, elf_strfmt(elf, elf_note_desc(elf, note)));
}
static void print_numeric_note(const char *prefix, struct elf_binary *elf,
@@ -103,10 +103,13 @@ static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start,
{
ELF_HANDLE_DECL(elf_note) note;
int notes_found = 0;
+ const char *this_note_name;
for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) )
{
- if (0 != strcmp(elf_note_name(elf, note), "Xen"))
+ this_note_name = elf_note_name(elf, note);
+ if (NULL == this_note_name ||
+ 0 != strcmp(this_note_name, "Xen"))
continue;
notes_found++;
@@ -294,7 +297,8 @@ int main(int argc, char **argv)
shdr = elf_shdr_by_name(&elf, "__xen_guest");
if (ELF_HANDLE_VALID(shdr))
- printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr));
+ printf("__xen_guest: %s\n",
+ elf_strfmt(&elf, elf_section_start(&elf, shdr)));
return 0;
}
diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c
index 566f6f9..ba0dc83 100644
--- a/xen/common/libelf/libelf-dominfo.c
+++ b/xen/common/libelf/libelf-dominfo.c
@@ -137,7 +137,10 @@ int elf_xen_parse_note(struct elf_binary *elf,
if ( note_desc[type].str )
{
- str = elf_note_desc(elf, note);
+ str = elf_strval(elf, elf_note_desc(elf, note));
+ if (str == NULL)
+ /* elf_strval will mark elf broken if it fails so no need to log */
+ return 0;
elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__,
note_desc[type].name, str);
parms->elf_notes[type].type = XEN_ENT_STR;
@@ -220,6 +223,7 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
{
int xen_elfnotes = 0;
ELF_HANDLE_DECL(elf_note) note;
+ const char *note_name;
parms->elf_note_start = start;
parms->elf_note_end = end;
@@ -227,7 +231,10 @@ static int elf_xen_parse_notes(struct elf_binary *elf,
ELF_HANDLE_PTRVAL(note) < parms->elf_note_end;
note = elf_note_next(elf, note) )
{
- if ( strcmp(elf_note_name(elf, note), "Xen") )
+ note_name = elf_note_name(elf, note);
+ if ( note_name == NULL )
+ continue;
+ if ( strcmp(note_name, "Xen") )
continue;
if ( elf_xen_parse_note(elf, parms, note) )
return -1;
@@ -541,7 +548,7 @@ int elf_xen_parse(struct elf_binary *elf,
parms->elf_note_start = ELF_INVALID_PTRVAL;
parms->elf_note_end = ELF_INVALID_PTRVAL;
elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
- parms->guest_info);
+ elf_strfmt(elf, parms->guest_info));
elf_xen_parse_guest_info(elf, parms);
break;
}
diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c
index bf68bcd..fa7dedd 100644
--- a/xen/common/libelf/libelf-tools.c
+++ b/xen/common/libelf/libelf-tools.c
@@ -119,7 +119,7 @@ const char *elf_section_name(struct elf_binary *elf,
if ( ELF_PTRVAL_INVALID(elf->sec_strtab) )
return "unknown";
- return elf->sec_strtab + elf_uval(elf, shdr, sh_name);
+ return elf_strval(elf, elf->sec_strtab + elf_uval(elf, shdr, sh_name));
}
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr)
@@ -151,6 +151,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab);
ELF_HANDLE_DECL(elf_sym) sym;
uint64_t info, name;
+ const char *sym_name;
for ( ; ptr < end; ptr += elf_size(elf, sym) )
{
@@ -159,7 +160,10 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *sym
name = elf_uval(elf, sym, st_name);
if ( ELF32_ST_BIND(info) != STB_GLOBAL )
continue;
- if ( strcmp(elf->sym_strtab + name, symbol) )
+ sym_name = elf_strval(elf, elf->sym_strtab + name);
+ if ( sym_name == NULL ) /* out of range, oops */
+ return ELF_INVALID_HANDLE(elf_sym);
+ if ( strcmp(sym_name, symbol) )
continue;
return sym;
}
@@ -177,7 +181,7 @@ ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index)
const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
{
- return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note);
+ return elf_strval(elf, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note));
}
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note)
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
index dc9b5ae..0c2c11e 100644
--- a/xen/include/xen/libelf.h
+++ b/xen/include/xen/libelf.h
@@ -252,6 +252,9 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr,
uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
+#define elf_strval(elf,x) ((const char*)(x)) /* may return NULL in the future */
+#define elf_strfmt(elf,x) ((const char*)(x)) /* will return (invalid) instead */
+
#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz))
#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz))
/*
@@ -279,7 +282,7 @@ ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *n
ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index);
ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index);
-const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
+const char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); /* might return NULL if inputs are invalid */
ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr);
@@ -289,7 +292,7 @@ ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(el
ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol);
ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index);
-const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
+const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); /* may return NULL */
ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note);
uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note),
--
1.7.2.5
next prev parent reply other threads:[~2013-06-04 17:59 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-04 17:59 [PATCH 4 00/16] XSA55 libelf fixes for unstable Ian Jackson
2013-06-04 17:59 ` [PATCH 01/16] libelf: abolish libelf-relocate.c Ian Jackson
2013-06-04 17:59 ` [PATCH 02/16] libxc: introduce xc_dom_seg_to_ptr_pages Ian Jackson
2013-06-04 17:59 ` [PATCH 03/16] libelf: add `struct elf_binary*' parameter to elf_load_image Ian Jackson
2013-06-05 10:32 ` George Dunlap
2013-06-05 11:01 ` Andrew Cooper
2013-06-05 11:54 ` Ian Jackson
2013-06-04 17:59 ` [PATCH 04/16] libelf: abolish elf_sval and elf_access_signed Ian Jackson
2013-06-04 17:59 ` [PATCH 05/16] libelf: move include of <asm/guest_access.h> to top of file Ian Jackson
2013-06-04 17:59 ` [PATCH 06/16] libelf/xc_dom_load_elf_symtab: Do not use "syms" uninitialised Ian Jackson
2013-06-04 17:59 ` [PATCH 07/16] libelf: introduce macros for memory access and pointer handling Ian Jackson
2013-06-04 17:59 ` [PATCH 08/16] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note Ian Jackson
2013-06-04 17:59 ` Ian Jackson [this message]
2013-06-04 17:59 ` [PATCH 10/16] libelf: check all pointer accesses Ian Jackson
2013-06-06 11:19 ` George Dunlap
2013-06-06 14:51 ` Ian Jackson
2013-06-06 16:20 ` George Dunlap
2013-06-06 18:11 ` Ian Jackson
2013-06-06 12:25 ` Matthew Daley
2013-06-06 14:59 ` Ian Jackson
2013-06-07 3:44 ` Matthew Daley
2013-06-06 15:30 ` Ian Campbell
2013-06-07 4:03 ` Matthew Daley
2013-06-04 17:59 ` [PATCH 11/16] libelf: Check pointer references in elf_is_elfbinary Ian Jackson
2013-06-04 17:59 ` [PATCH 12/16] libelf: Make all callers call elf_check_broken Ian Jackson
2013-06-05 14:51 ` Andrew Cooper
2013-06-05 15:31 ` Andrew Cooper
2013-06-06 14:08 ` George Dunlap
2013-06-06 18:41 ` Ian Jackson
2013-06-04 18:00 ` [PATCH 13/16] libelf: use C99 bool for booleans Ian Jackson
2013-06-06 14:28 ` George Dunlap
2013-06-06 14:46 ` Ian Jackson
2013-06-04 18:00 ` [PATCH 14/16] libelf: use only unsigned integers Ian Jackson
2013-06-06 16:07 ` George Dunlap
2013-06-06 18:14 ` Ian Jackson
2013-06-07 7:14 ` Jan Beulich
2013-06-07 14:35 ` Ian Jackson
2013-06-07 15:50 ` Jan Beulich
2013-06-04 18:00 ` [PATCH 15/16] libelf: check loops for running away Ian Jackson
2013-06-04 18:00 ` [PATCH 16/16] libelf: abolish obsolete macros Ian Jackson
2013-06-04 18:08 ` [PATCH 4 00/16] XSA55 libelf fixes for unstable Ian Jackson
2013-06-04 21:39 ` Andrew Cooper
2013-06-05 11:53 ` Ian Jackson
2013-06-06 14:04 ` Matthew Daley
2013-06-06 18:39 ` Ian Jackson
2013-06-07 3:35 ` Matthew Daley
-- strict thread matches above, loose matches on Subject: below --
2013-06-03 15:41 [PATCH v3.1 " Ian Jackson
2013-06-03 15:41 ` [PATCH 09/16] libelf: check nul-terminated strings properly Ian Jackson
2013-06-04 14:49 ` Matthew Daley
2013-06-04 15:15 ` Ian Jackson
2013-06-04 15:27 ` Matthew Daley
2013-06-04 17:13 ` Ian Jackson
2013-06-05 2:08 ` Matthew Daley
2013-06-05 7:24 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1370368803-9436-10-git-send-email-ian.jackson@eu.citrix.com \
--to=ian.jackson@eu.citrix.com \
--cc=andrew.cooper3@citrix.com \
--cc=mattjd@gmail.com \
--cc=security@xen.org \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).