xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
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),

  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).