diff options
author | Andrey Shvetsov <andrey.shvetsov@k2l.de> | 2020-01-16 18:22:39 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2020-01-29 13:40:23 +0100 |
commit | 47c852c1b360146084ad35e2ae840df8dffa2d4e (patch) | |
tree | df9b06a97405ab809db34c0253f0df2b69693165 | |
parent | 6372017d41a4723c6635e92fc03f8e55eb25e45b (diff) |
UPSTREAM: staging: most: net: fix buffer overflowASB-2020-02-05_4.9-p
If the length of the socket buffer is 0xFFFFFFFF (max size for an
unsigned int), then payload_len becomes 0xFFFFFFF1 after subtracting 14
(ETH_HLEN). Then, mdp_len is set to payload_len + 16 (MDP_HDR_LEN)
which overflows and results in a value of 2. These values for
payload_len and mdp_len will pass current buffer size checks.
This patch checks if derived from skb->len sum may overflow.
The check is based on the following idea:
For any `unsigned V1, V2` and derived `unsigned SUM = V1 + V2`,
`V1 + V2` overflows iif `SUM < V1`.
Bug: 143560807
Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200116172238.6046-1-andrey.shvetsov@microchip.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 4d1356ac12f4d5180d0df345d85ff0ee42b89c72)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I71197b2963735ba181314332737fc0c1ca2cab96
-rw-r--r-- | drivers/staging/most/aim-network/networking.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 4659a6450c04..6b18afb62145 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -87,6 +87,11 @@ static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) unsigned int payload_len = skb->len - ETH_HLEN; unsigned int mdp_len = payload_len + MDP_HDR_LEN; + if (mdp_len < skb->len) { + pr_err("drop: too large packet! (%u)\n", skb->len); + return -EINVAL; + } + if (mbo->buffer_length < mdp_len) { pr_err("drop: too small buffer! (%d for %d)\n", mbo->buffer_length, mdp_len); @@ -134,6 +139,11 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) u8 *buff = mbo->virt_address; unsigned int mep_len = skb->len + MEP_HDR_LEN; + if (mep_len < skb->len) { + pr_err("drop: too large packet! (%u)\n", skb->len); + return -EINVAL; + } + if (mbo->buffer_length < mep_len) { pr_err("drop: too small buffer! (%d for %d)\n", mbo->buffer_length, mep_len); |