Fix CVE-2017-7308 and CVE-2017-7618

This commit is contained in:
Justin M. Forbes 2017-04-11 15:12:58 -05:00
parent 1b724fad46
commit 21d113f3e9
10 changed files with 378 additions and 7 deletions

107
CVE-2017-7308.patch Normal file
View File

@ -0,0 +1,107 @@
From 2b6867c2ce76c596676bec7d2d525af525fdc6e2 Mon Sep 17 00:00:00 2001
From: Andrey Konovalov <andreyknvl@google.com>
Date: Wed, 29 Mar 2017 16:11:20 +0200
Subject: [PATCH] net/packet: fix overflow in check for priv area size
Subtracting tp_sizeof_priv from tp_block_size and casting to int
to check whether one is less then the other doesn't always work
(both of them are unsigned ints).
Compare them as is instead.
Also cast tp_sizeof_priv to u64 before using BLK_PLUS_PRIV, as
it can overflow inside BLK_PLUS_PRIV otherwise.
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/packet/af_packet.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index a0dbe7c..2323ee3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4193,8 +4193,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
goto out;
if (po->tp_version >= TPACKET_V3 &&
- (int)(req->tp_block_size -
- BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
+ req->tp_block_size <=
+ BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
goto out;
if (unlikely(req->tp_frame_size < po->tp_hdrlen +
po->tp_reserve))
--
2.9.3
From 8f8d28e4d6d815a391285e121c3a53a0b6cb9e7b Mon Sep 17 00:00:00 2001
From: Andrey Konovalov <andreyknvl@google.com>
Date: Wed, 29 Mar 2017 16:11:21 +0200
Subject: [PATCH] net/packet: fix overflow in check for tp_frame_nr
When calculating rb->frames_per_block * req->tp_block_nr the result
can overflow.
Add a check that tp_block_size * tp_block_nr <= UINT_MAX.
Since frames_per_block <= tp_block_size, the expression would
never overflow.
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/packet/af_packet.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2323ee3..3ac286e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4205,6 +4205,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
if (unlikely(rb->frames_per_block == 0))
goto out;
+ if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+ goto out;
if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
req->tp_frame_nr))
goto out;
--
2.9.3
From bcc5364bdcfe131e6379363f089e7b4108d35b70 Mon Sep 17 00:00:00 2001
From: Andrey Konovalov <andreyknvl@google.com>
Date: Wed, 29 Mar 2017 16:11:22 +0200
Subject: [PATCH] net/packet: fix overflow in check for tp_reserve
When calculating po->tp_hdrlen + po->tp_reserve the result can overflow.
Fix by checking that tp_reserve <= INT_MAX on assign.
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/packet/af_packet.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 3ac286e..8489bef 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3665,6 +3665,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return -EBUSY;
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;
+ if (val > INT_MAX)
+ return -EINVAL;
po->tp_reserve = val;
return 0;
}
--
2.9.3

254
CVE-2017-7618.patch Normal file
View File

@ -0,0 +1,254 @@
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: 2017-04-10 9:27:57
Subject: [PATCH v2] crypto: ahash - Fix EINPROGRESS notification callback
On Mon, Apr 10, 2017 at 11:21:27AM +0200, Sabrina Dubroca wrote:
>
> > Cc: <vger@stable.kernel.org>
>
> Should that be stable@vger.kernel.org?
Oops :)
> > Reported-by: Sabrina Dubroca <sdubroca@redhat.com>
> > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> The definition of ahash_request_flags() was missing, so I added:
>
> static inline u32 ahash_request_flags(struct ahash_request *req)
> {
> return req->base.flags;
> }
>
> And with this, my tests seem fine.
>
> Tested-by: Sabrina Dubroca <sd@queasysnail.net>
> Could also you change the 'Reported-by:' to that email address?
OK, here is v2.
---8<---
The ahash API modifies the request's callback function in order
to clean up after itself in some corner cases (unaligned final
and missing finup).
When the request is complete ahash will restore the original
callback and everything is fine. However, when the request gets
an EBUSY on a full queue, an EINPROGRESS callback is made while
the request is still ongoing.
In this case the ahash API will incorrectly call its own callback.
This patch fixes the problem by creating a temporary request
object on the stack which is used to relay EINPROGRESS back to
the original completion function.
This patch also adds code to preserve the original flags value.
Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...")
Cc: <stable@vger.kernel.org>
Reported-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/crypto/ahash.c b/crypto/ahash.c
index e58c497..1810feb 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -32,6 +32,7 @@ struct ahash_request_priv {
crypto_completion_t complete;
void *data;
u8 *result;
+ u32 flags;
void *ubuf[] CRYPTO_MINALIGN_ATTR;
};
@@ -253,6 +254,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
priv->result = req->result;
priv->complete = req->base.complete;
priv->data = req->base.data;
+ priv->flags = req->base.flags;
+
/*
* WARNING: We do not backup req->priv here! The req->priv
* is for internal use of the Crypto API and the
@@ -267,38 +270,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
return 0;
}
-static void ahash_restore_req(struct ahash_request *req)
+static void ahash_restore_req(struct ahash_request *req, int err)
{
struct ahash_request_priv *priv = req->priv;
+ if (!err)
+ memcpy(priv->result, req->result,
+ crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+
/* Restore the original crypto request. */
req->result = priv->result;
- req->base.complete = priv->complete;
- req->base.data = priv->data;
+
+ ahash_request_set_callback(req, priv->flags,
+ priv->complete, priv->data);
req->priv = NULL;
/* Free the req->priv.priv from the ADJUSTED request. */
kzfree(priv);
}
-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
+static void ahash_notify_einprogress(struct ahash_request *req)
{
struct ahash_request_priv *priv = req->priv;
+ struct crypto_async_request oreq;
- if (err == -EINPROGRESS)
- return;
+ oreq.data = priv->data;
- if (!err)
- memcpy(priv->result, req->result,
- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
- ahash_restore_req(req);
+ priv->complete(&oreq, -EINPROGRESS);
}
static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
{
struct ahash_request *areq = req->data;
+ if (err == -EINPROGRESS) {
+ ahash_notify_einprogress(areq);
+ return;
+ }
+
/*
* Restore the original request, see ahash_op_unaligned() for what
* goes where.
@@ -309,7 +318,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
*/
/* First copy req->result into req->priv.result */
- ahash_op_unaligned_finish(areq, err);
+ ahash_restore_req(areq, err);
/* Complete the ORIGINAL request. */
areq->base.complete(&areq->base, err);
@@ -325,7 +334,12 @@ static int ahash_op_unaligned(struct ahash_request *req,
return err;
err = op(req);
- ahash_op_unaligned_finish(req, err);
+ if (err == -EINPROGRESS ||
+ (err == -EBUSY && (ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
+ return err;
+
+ ahash_restore_req(req, err);
return err;
}
@@ -360,25 +374,14 @@ int crypto_ahash_digest(struct ahash_request *req)
}
EXPORT_SYMBOL_GPL(crypto_ahash_digest);
-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
+static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
{
- struct ahash_request_priv *priv = req->priv;
+ struct ahash_request *areq = req->data;
if (err == -EINPROGRESS)
return;
- if (!err)
- memcpy(priv->result, req->result,
- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
- ahash_restore_req(req);
-}
-
-static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
-{
- struct ahash_request *areq = req->data;
-
- ahash_def_finup_finish2(areq, err);
+ ahash_restore_req(areq, err);
areq->base.complete(&areq->base, err);
}
@@ -389,11 +392,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err)
goto out;
req->base.complete = ahash_def_finup_done2;
- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
err = crypto_ahash_reqtfm(req)->final(req);
+ if (err == -EINPROGRESS ||
+ (err == -EBUSY && (ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
+ return err;
out:
- ahash_def_finup_finish2(req, err);
+ ahash_restore_req(req, err);
return err;
}
@@ -401,7 +408,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
{
struct ahash_request *areq = req->data;
+ if (err == -EINPROGRESS) {
+ ahash_notify_einprogress(areq);
+ return;
+ }
+
+ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
err = ahash_def_finup_finish1(areq, err);
+ if (areq->priv)
+ return;
areq->base.complete(&areq->base, err);
}
@@ -416,6 +432,11 @@ static int ahash_def_finup(struct ahash_request *req)
return err;
err = tfm->update(req);
+ if (err == -EINPROGRESS ||
+ (err == -EBUSY && (ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
+ return err;
+
return ahash_def_finup_finish1(req, err);
}
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 1d4f365..f6d9af3e 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -166,6 +166,16 @@ static inline struct ahash_instance *ahash_alloc_instance(
return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
}
+static inline void ahash_request_complete(struct ahash_request *req, int err)
+{
+ req->base.complete(&req->base, err);
+}
+
+static inline u32 ahash_request_flags(struct ahash_request *req)
+{
+ return req->base.flags;
+}
+
static inline struct crypto_ahash *crypto_spawn_ahash(
struct crypto_ahash_spawn *spawn)
{
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

View File

@ -1 +0,0 @@
# CONFIG_HAMRADIO is not set

View File

@ -1707,7 +1707,7 @@ CONFIG_GREENASIA_FF=y
# CONFIG_GS_FPGABOOT is not set
CONFIG_GTP=m
CONFIG_HAMACHI=m
# CONFIG_HAMRADIO is not set
CONFIG_HAMRADIO=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_HAPPYMEAL=m
CONFIG_HARDENED_USERCOPY=y

View File

@ -1690,7 +1690,7 @@ CONFIG_GREENASIA_FF=y
# CONFIG_GS_FPGABOOT is not set
CONFIG_GTP=m
CONFIG_HAMACHI=m
# CONFIG_HAMRADIO is not set
CONFIG_HAMRADIO=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_HAPPYMEAL=m
CONFIG_HARDENED_USERCOPY=y

View File

@ -1865,7 +1865,7 @@ CONFIG_GREENASIA_FF=y
CONFIG_GS_FPGABOOT=m
CONFIG_GTP=m
CONFIG_HAMACHI=m
# CONFIG_HAMRADIO is not set
CONFIG_HAMRADIO=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_HAPPYMEAL=m
CONFIG_HARDENED_USERCOPY=y

View File

@ -1774,7 +1774,7 @@ CONFIG_GREENASIA_FF=y
# CONFIG_GS_FPGABOOT is not set
CONFIG_GTP=m
CONFIG_HAMACHI=m
# CONFIG_HAMRADIO is not set
CONFIG_HAMRADIO=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_HAPPYMEAL=m
CONFIG_HARDENED_USERCOPY=y

View File

@ -1758,7 +1758,7 @@ CONFIG_GREENASIA_FF=y
# CONFIG_GS_FPGABOOT is not set
CONFIG_GTP=m
CONFIG_HAMACHI=m
# CONFIG_HAMRADIO is not set
CONFIG_HAMRADIO=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_HAPPYMEAL=m
CONFIG_HARDENED_USERCOPY=y

View File

@ -1849,7 +1849,7 @@ CONFIG_GREENASIA_FF=y
CONFIG_GS_FPGABOOT=m
CONFIG_GTP=m
CONFIG_HAMACHI=m
# CONFIG_HAMRADIO is not set
CONFIG_HAMRADIO=y
CONFIG_HANGCHECK_TIMER=m
CONFIG_HAPPYMEAL=m
CONFIG_HARDENED_USERCOPY=y

View File

@ -622,6 +622,12 @@ Patch862: 1-2-media-cxusb-Use-a-dma-capable-buffer-also-for-reading.patch
#rhbz 1441310
Patch863: rhbz_1441310.patch
# CVE-2017-7618 rhbz 1441095 1441093
Patch865: CVE-2017-7618.patch
# CVE-2017-7308 rhbz 1437404 1437406
Patch866: CVE-2017-7308.patch
# END OF PATCH DEFINITIONS
%endif
@ -2191,6 +2197,11 @@ fi
#
#
%changelog
* Tue Apr 11 2017 Justin M. Forbes <jforbes@fedoraproject.org>
- Fix CVE-2017-7618 (rhbz 1441095 1441093)
- Fix CVE-2017-7308 (rhbz 1437404 1437406)
- Turn on CONFIG_HAMRADIO for arm (rhbz 1425990)
* Tue Apr 11 2017 Laura Abbott <labbott@fedoraproject.org>
- Fix for openshift networking (rhbz 1441310)