summaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorAndrey Shvetsov <andrey.shvetsov@k2l.de>2020-01-16 18:22:39 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-05 13:05:36 +0000
commit8b6487d85ca9f9bfa9d75917451969a1d097a815 (patch)
tree563ef8d7a16bc96c5c900011eaaefbeb967bb2e9 /drivers/staging
parentdd05b1a0696050bd268cc47cca4464d8dedfe03a (diff)
downloadlinux-stable-8b6487d85ca9f9bfa9d75917451969a1d097a815.tar.gz
linux-stable-8b6487d85ca9f9bfa9d75917451969a1d097a815.tar.bz2
linux-stable-8b6487d85ca9f9bfa9d75917451969a1d097a815.zip
staging: most: net: fix buffer overflow
commit 4d1356ac12f4d5180d0df345d85ff0ee42b89c72 upstream. 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`. 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>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/most/aim-network/networking.c10
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);