From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: "xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,
"mattjd@gmail.com" <mattjd@gmail.com>,
"security@xen.org" <security@xen.org>
Subject: Re: [PATCH 10/22] libelf: check nul-terminated strings properly
Date: Tue, 11 Jun 2013 20:14:07 +0100 [thread overview]
Message-ID: <51B776FF.1070405@citrix.com> (raw)
In-Reply-To: <1370974865-19554-11-git-send-email-ian.jackson@eu.citrix.com>
On 11/06/13 19:20, Ian Jackson wrote:
> 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.
>
> This is part of the fix to a security issue, XSA-55.
>
> 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>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
>
> v7: Change readnotes.c check to use two if statements rather than ||.
>
> v2: Fix coding style, in one "if" statement.
> ---
> tools/xcutils/readnotes.c | 11 ++++++++---
> xen/common/libelf/libelf-dominfo.c | 13 ++++++++++---
> xen/common/libelf/libelf-tools.c | 10 +++++++---
> xen/include/xen/libelf.h | 7 +++++--
> 4 files changed, 30 insertions(+), 11 deletions(-)
>
> diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
> index 7ff2530..cfae994 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,14 @@ 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)
> + continue;
> + if (0 != strcmp(this_note_name, "Xen"))
> continue;
>
> notes_found++;
> @@ -294,7 +298,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 7bd3bdb..28c7b11 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),
next prev parent reply other threads:[~2013-06-11 19:14 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-11 18:20 [PATCH v7 00/22] XSA55 libelf fixes for unstable Ian Jackson
2013-06-11 18:20 ` [PATCH 01/22] libelf: abolish libelf-relocate.c Ian Jackson
2013-06-11 18:20 ` [PATCH 02/22] libxc: introduce xc_dom_seg_to_ptr_pages Ian Jackson
2013-06-11 18:44 ` Andrew Cooper
2013-06-11 18:20 ` [PATCH 03/22] libxc: Fix range checking in xc_dom_pfn_to_ptr etc Ian Jackson
2013-06-11 19:01 ` Andrew Cooper
2013-06-11 18:20 ` [PATCH 04/22] libelf: add `struct elf_binary*' parameter to elf_load_image Ian Jackson
2013-06-11 18:20 ` [PATCH 05/22] libelf: abolish elf_sval and elf_access_signed Ian Jackson
2013-06-11 18:20 ` [PATCH 06/22] libelf: move include of <asm/guest_access.h> to top of file Ian Jackson
2013-06-11 18:20 ` [PATCH 07/22] libelf/xc_dom_load_elf_symtab: Do not use "syms" uninitialised Ian Jackson
2013-06-11 18:20 ` [PATCH 08/22] libelf: introduce macros for memory access and pointer handling Ian Jackson
2013-06-11 18:20 ` [PATCH 09/22] tools/xcutils/readnotes: adjust print_l1_mfn_valid_note Ian Jackson
2013-06-11 18:20 ` [PATCH 10/22] libelf: check nul-terminated strings properly Ian Jackson
2013-06-11 19:14 ` Andrew Cooper [this message]
2013-06-11 18:20 ` [PATCH 11/22] libelf: check all pointer accesses Ian Jackson
2013-06-11 19:19 ` Andrew Cooper
2013-06-11 18:20 ` [PATCH 12/22] libelf: Check pointer references in elf_is_elfbinary Ian Jackson
2013-06-11 19:03 ` Andrew Cooper
2013-06-11 18:20 ` [PATCH 13/22] libelf: Make all callers call elf_check_broken Ian Jackson
2013-06-11 18:20 ` [PATCH 14/22] libelf: use C99 bool for booleans Ian Jackson
2013-06-11 19:04 ` Andrew Cooper
2013-06-11 18:20 ` [PATCH 15/22] libelf: use only unsigned integers Ian Jackson
2013-06-11 19:22 ` Andrew Cooper
2013-06-11 18:20 ` [PATCH 16/22] libelf: check loops for running away Ian Jackson
2013-06-11 19:28 ` Andrew Cooper
2013-06-11 18:21 ` [PATCH 17/22] libelf: abolish obsolete macros Ian Jackson
2013-06-11 18:21 ` [PATCH 18/22] libxc: Add range checking to xc_dom_binloader Ian Jackson
2013-06-11 19:11 ` Andrew Cooper
2013-06-11 18:21 ` [PATCH 19/22] libxc: check failure of xc_dom_*_to_ptr, xc_map_foreign_range Ian Jackson
2013-06-11 19:10 ` Andrew Cooper
2013-06-11 18:21 ` [PATCH 20/22] libxc: check return values from malloc Ian Jackson
2013-06-11 19:05 ` Andrew Cooper
2013-06-11 18:21 ` [PATCH 21/22] libxc: range checks in xc_dom_p2m_host and _guest Ian Jackson
2013-06-11 19:06 ` Andrew Cooper
2013-06-12 16:02 ` George Dunlap
2013-06-12 16:06 ` Ian Jackson
2013-06-12 16:08 ` George Dunlap
2013-06-12 18:26 ` Tim Deegan
2013-06-11 18:21 ` [PATCH 22/22] libxc: check blob size before proceeding in xc_dom_check_gzip Ian Jackson
2013-06-11 19:08 ` Andrew Cooper
2013-06-11 19:30 ` [PATCH v7 00/22] XSA55 libelf fixes for unstable Andrew Cooper
2013-06-12 13:45 ` Ian Jackson
2013-06-12 14:02 ` Ian Jackson
2013-06-12 14:19 ` Andrew Cooper
-- strict thread matches above, loose matches on Subject: below --
2013-06-11 18:22 [PATCH v7 00/22] XSA55 libelf fixes for Xen 4.2 Ian Jackson
2013-06-11 18:22 ` [PATCH 10/22] libelf: check nul-terminated strings properly Ian Jackson
2013-06-07 18:35 [PATCH v6 00/22] XSA55 libelf fixes for Xen 4.2 Ian Jackson
2013-06-07 18:35 ` [PATCH 10/22] libelf: check nul-terminated strings properly Ian Jackson
2013-06-07 18:27 [PATCH v6 00/22] XSA55 libelf fixes for unstable Ian Jackson
2013-06-07 18:27 ` [PATCH 10/22] libelf: check nul-terminated strings properly Ian Jackson
2013-06-10 23:17 ` Andrew Cooper
2013-06-11 15:17 ` Ian Jackson
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=51B776FF.1070405@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=ian.jackson@eu.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).