Fix CVE-2017-7308 and CVE-2017-7618
This commit is contained in:
parent
1b724fad46
commit
21d113f3e9
|
@ -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
|
||||
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_HAMRADIO is not set
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
11
kernel.spec
11
kernel.spec
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue