]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Jun 2018 18:17:15 +0000 (20:17 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Jun 2018 18:17:15 +0000 (20:17 +0200)
added patches:
af_key-always-verify-length-of-provided-sadb_key.patch

queue-3.18/af_key-always-verify-length-of-provided-sadb_key.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/af_key-always-verify-length-of-provided-sadb_key.patch b/queue-3.18/af_key-always-verify-length-of-provided-sadb_key.patch
new file mode 100644 (file)
index 0000000..1a3888a
--- /dev/null
@@ -0,0 +1,108 @@
+From 4b66af2d6356a00e94bcdea3e7fea324e8b5c6f4 Mon Sep 17 00:00:00 2001
+From: Kevin Easton <kevin@guarana.org>
+Date: Sat, 7 Apr 2018 11:40:33 -0400
+Subject: af_key: Always verify length of provided sadb_key
+
+From: Kevin Easton <kevin@guarana.org>
+
+commit 4b66af2d6356a00e94bcdea3e7fea324e8b5c6f4 upstream.
+
+Key extensions (struct sadb_key) include a user-specified number of key
+bits.  The kernel uses that number to determine how much key data to copy
+out of the message in pfkey_msg2xfrm_state().
+
+The length of the sadb_key message must be verified to be long enough,
+even in the case of SADB_X_AALG_NULL.  Furthermore, the sadb_key_len value
+must be long enough to include both the key data and the struct sadb_key
+itself.
+
+Introduce a helper function verify_key_len(), and call it from
+parse_exthdrs() where other exthdr types are similarly checked for
+correctness.
+
+Signed-off-by: Kevin Easton <kevin@guarana.org>
+Reported-by: syzbot+5022a34ca5a3d49b84223653fab632dfb7b4cf37@syzkaller.appspotmail.com
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: Zubin Mithra <zsm@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/key/af_key.c |   45 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 35 insertions(+), 10 deletions(-)
+
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -437,6 +437,24 @@ static int verify_address_len(const void
+       return 0;
+ }
++static inline int sadb_key_len(const struct sadb_key *key)
++{
++      int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8);
++
++      return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes,
++                          sizeof(uint64_t));
++}
++
++static int verify_key_len(const void *p)
++{
++      const struct sadb_key *key = p;
++
++      if (sadb_key_len(key) > key->sadb_key_len)
++              return -EINVAL;
++
++      return 0;
++}
++
+ static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx)
+ {
+       return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) +
+@@ -533,16 +551,25 @@ static int parse_exthdrs(struct sk_buff
+                               return -EINVAL;
+                       if (ext_hdrs[ext_type-1] != NULL)
+                               return -EINVAL;
+-                      if (ext_type == SADB_EXT_ADDRESS_SRC ||
+-                          ext_type == SADB_EXT_ADDRESS_DST ||
+-                          ext_type == SADB_EXT_ADDRESS_PROXY ||
+-                          ext_type == SADB_X_EXT_NAT_T_OA) {
++                      switch (ext_type) {
++                      case SADB_EXT_ADDRESS_SRC:
++                      case SADB_EXT_ADDRESS_DST:
++                      case SADB_EXT_ADDRESS_PROXY:
++                      case SADB_X_EXT_NAT_T_OA:
+                               if (verify_address_len(p))
+                                       return -EINVAL;
+-                      }
+-                      if (ext_type == SADB_X_EXT_SEC_CTX) {
++                              break;
++                      case SADB_X_EXT_SEC_CTX:
+                               if (verify_sec_ctx_len(p))
+                                       return -EINVAL;
++                              break;
++                      case SADB_EXT_KEY_AUTH:
++                      case SADB_EXT_KEY_ENCRYPT:
++                              if (verify_key_len(p))
++                                      return -EINVAL;
++                              break;
++                      default:
++                              break;
+                       }
+                       ext_hdrs[ext_type-1] = (void *) p;
+               }
+@@ -1111,14 +1138,12 @@ static struct xfrm_state * pfkey_msg2xfr
+       key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
+       if (key != NULL &&
+           sa->sadb_sa_auth != SADB_X_AALG_NULL &&
+-          ((key->sadb_key_bits+7) / 8 == 0 ||
+-           (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
++          key->sadb_key_bits == 0)
+               return ERR_PTR(-EINVAL);
+       key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
+       if (key != NULL &&
+           sa->sadb_sa_encrypt != SADB_EALG_NULL &&
+-          ((key->sadb_key_bits+7) / 8 == 0 ||
+-           (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
++          key->sadb_key_bits == 0)
+               return ERR_PTR(-EINVAL);
+       x = xfrm_state_alloc(net);
index 93e933cfbaaa73fac33d31d524eae45b69483a3f..8049485e930bae0fa16012787f76dabc39ff54f5 100644 (file)
@@ -1,2 +1,3 @@
 tools-build-no-need-to-make-libapi-for-perf-explicitly.patch
 tools-build-fix-makefile-s-to-properly-invoke-tools-build.patch
+af_key-always-verify-length-of-provided-sadb_key.patch