All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xensource.com
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	Wei Liu <wei.liu2@citrix.com>,
	George Dunlap <George.Dunlap@eu.citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Tim Deegan <tim@xen.org>, Jan Beulich <JBeulich@suse.com>,
	Ian Jackson <Ian.Jackson@eu.citrix.com>
Subject: [PATCH 1/8] libelf: loop safety: Introduce elf_iter_ok and elf_strcmp_safe
Date: Fri, 9 Dec 2016 15:44:42 +0000	[thread overview]
Message-ID: <1481298289-13546-2-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1481298289-13546-1-git-send-email-ian.jackson@eu.citrix.com>

This will allow us to keep track of the total amount of work we are
doing.  When it becomes excessive, we mark the ELF broken, and stop
processing.

This is a more robust way of preventing DoS problems by bad images
than attempting to prove, for each of the (sometimes rather deeply
nested) loops, that the total work is "reasonable".  We bound the
notional work by 4x the image size (plus 1M).

Also introduce elf_strcmp_safe, which unconditionally does the work,
but increments the count so any outer loop may be aborted if
necessary.

Currently there are no callers, so no functional change.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 xen/common/libelf/libelf-loader.c | 14 ++++++++++++++
 xen/include/xen/libelf.h          | 21 +++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
index a72cd8a..00479af 100644
--- a/xen/common/libelf/libelf-loader.c
+++ b/xen/common/libelf/libelf-loader.c
@@ -38,6 +38,7 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t
     ELF_HANDLE_DECL(elf_shdr) shdr;
     unsigned i, count, section, link;
     uint64_t offset;
+    const uint64_t max_size_for_deacc = (1UL << 63)/ELF_MAX_ITERATION_FACTOR;
 
     if ( !elf_is_elfbinary(image_input, size) )
     {
@@ -52,6 +53,10 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t
     elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]);
     elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]);
 
+    elf->iteration_deaccumulator = 1024*1024 +
+        (size > max_size_for_deacc ? max_size_for_deacc : size)
+        * ELF_MAX_ITERATION_FACTOR;        
+
     /* Sanity check phdr. */
     offset = elf_uval(elf, elf->ehdr, e_phoff) +
         elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
@@ -546,6 +551,15 @@ uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol)
     return value;
 }
 
+bool elf_iter_ok_counted(struct elf_binary *elf, uint64_t maxcopysz) {
+    if (maxcopysz > elf->iteration_deaccumulator)
+        elf_mark_broken(elf, "excessive iteration - too much work to parse");
+    if (elf->broken)
+        return false;
+    elf->iteration_deaccumulator -= maxcopysz;
+    return true;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
index 1b763f3..294231a 100644
--- a/xen/include/xen/libelf.h
+++ b/xen/include/xen/libelf.h
@@ -56,6 +56,8 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data,
 #define ELF_MAX_STRING_LENGTH 4096
 #define ELF_MAX_TOTAL_NOTE_COUNT 65536
 
+#define ELF_MAX_ITERATION_FACTOR 4
+
 /* ------------------------------------------------------------------------ */
 
 /* Macros for accessing the input image and output area. */
@@ -201,6 +203,9 @@ struct elf_binary {
     uint64_t bsd_symtab_pstart;
     uint64_t bsd_symtab_pend;
 
+    /* private */
+    uint64_t iteration_deaccumulator;
+    
     /*
      * caller's other acceptable destination.
      * Set by elf_set_xdest.  Do not set these directly.
@@ -264,6 +269,14 @@ uint64_t elf_access_unsigned(struct elf_binary *elf, elf_ptrval ptr,
 
 uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
 
+bool elf_iter_ok_counted(struct elf_binary *elf, uint64_t count);
+  /* It is OK for count to be out by a smallish constant factor.
+   * It is OK for count to be 0, as we clamp it to 1, so we
+   * can use lengths or sizes from the image. */
+
+static inline bool elf_iter_ok(struct elf_binary *elf)
+    { return elf_iter_ok_counted(elf,1); }
+
 const char *elf_strval(struct elf_binary *elf, elf_ptrval start);
   /* may return NULL if the string is out of range etc. */
 
@@ -463,6 +476,14 @@ static inline void *elf_memset_unchecked(void *s, int c, size_t n)
    * memcpy, memset and memmove to undefined MISTAKE things.
    */
 
+static inline int elf_strcmp_safe(struct elf_binary *elf,
+                                  const char *a, const char *b) {
+    elf_iter_ok_counted(elf, strlen(b));
+    return strcmp(a,b);
+}
+  /* Unlike other *_safe functions, elf_strcmp_safe is called on
+   * values already extracted from the image (eg by elf_strval),
+   * and fixed constant strings (typically, the latter is "b"). */
 
 /* Advances past amount bytes of the current destination area. */
 static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount)
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2016-12-09 15:44 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-08 14:18 [PATCH] libelf: Fix div0 issues in elf_{shdr, phdr}_count() Andrew Cooper
2016-12-08 14:41 ` Jan Beulich
2016-12-08 14:46   ` Andrew Cooper
2016-12-08 15:17     ` Jan Beulich
2016-12-08 15:23       ` Andrew Cooper
2016-12-08 15:47         ` Ian Jackson
2016-12-08 16:09           ` Jan Beulich
2016-12-08 17:28           ` Ian Jackson
2016-12-09  8:38             ` Jan Beulich
2016-12-09 11:54               ` Ian Jackson
2016-12-09 13:03                 ` Jan Beulich
2016-12-09 15:44                 ` [PATCH 0/8] libelf: safety enhancements Ian Jackson
2016-12-09 15:44                   ` Ian Jackson [this message]
2016-12-12 15:02                     ` [PATCH 1/8] libelf: loop safety: Introduce elf_iter_ok and elf_strcmp_safe Jan Beulich
2016-12-12 15:23                       ` Ian Jackson
2016-12-12 15:15                     ` Jan Beulich
2016-12-12 15:51                     ` Jan Beulich
2016-12-12 16:00                       ` Ian Jackson
2016-12-12 16:16                         ` Jan Beulich
2016-12-12 16:56                           ` Ian Jackson
2016-12-13  7:24                             ` Jan Beulich
2016-12-13 16:04                               ` Ian Jackson
2016-12-13 16:37                                 ` Jan Beulich
2016-12-09 15:44                   ` [PATCH 2/8] libelf: loop safety: Pass `elf' to elf_xen_parse_features Ian Jackson
2016-12-12 15:03                     ` Jan Beulich
2016-12-09 15:44                   ` [PATCH 3/8] libelf: loop safety: Call elf_iter_ok[_counted] in every loop Ian Jackson
2016-12-12 15:12                     ` Jan Beulich
2016-12-12 15:38                       ` Ian Jackson
2016-12-12 15:56                         ` Jan Beulich
2016-12-12 16:02                           ` Ian Jackson
2016-12-09 15:44                   ` [PATCH 4/8] libelf: loop safety: Call elf_iter_ok_counted at every *mem*_unsafe Ian Jackson
2016-12-12 15:19                     ` Jan Beulich
2016-12-12 15:54                       ` Ian Jackson
2016-12-12 15:58                         ` Jan Beulich
2016-12-12 16:03                           ` Ian Jackson
2016-12-09 15:44                   ` [PATCH 5/8] libelf: loop safety: Replace all calls to strcmp Ian Jackson
2016-12-12 15:22                     ` Jan Beulich
2016-12-12 15:44                       ` Ian Jackson
2016-12-09 15:44                   ` [PATCH 6/8] libelf: loop safety cleanup: Remove obsolete check in elf_shdr_count Ian Jackson
2016-12-12 15:41                     ` Jan Beulich
2016-12-09 15:44                   ` [PATCH 7/8] libelf: loop safety cleanup: Remove superseded image size copy check Ian Jackson
2016-12-12 16:26                     ` Jan Beulich
2016-12-09 15:44                   ` [PATCH 8/8] libelf: safety: Document safety principles in header file Ian Jackson
2016-12-15 16:43                     ` Jan Beulich
2016-12-16  4:28                       ` George Dunlap
2016-12-16 11:33                         ` Ian Jackson
2016-12-16 11:58                           ` Jan Beulich
2016-12-16 11:43                       ` Ian Jackson
2016-12-16 12:31                         ` Jan Beulich
2016-12-08 14:48   ` [PATCH] libelf: Fix div0 issues in elf_{shdr, phdr}_count() 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=1481298289-13546-2-git-send-email-ian.jackson@eu.citrix.com \
    --to=ian.jackson@eu.citrix.com \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=tim@xen.org \
    --cc=wei.liu2@citrix.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.