Commit 9dab6bbc authored by Andrey Shvetsov's avatar Andrey Shvetsov Committed by Greg Kroah-Hartman

staging: most: net: fix buffer overflow

commit 4d1356ac 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: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarAndrey Shvetsov <andrey.shvetsov@k2l.de>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200116172238.6046-1-andrey.shvetsov@microchip.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 26962313
...@@ -81,6 +81,11 @@ static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) ...@@ -81,6 +81,11 @@ static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
unsigned int payload_len = skb->len - ETH_HLEN; unsigned int payload_len = skb->len - ETH_HLEN;
unsigned int mdp_len = payload_len + MDP_HDR_LEN; 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) { if (mbo->buffer_length < mdp_len) {
pr_err("drop: too small buffer! (%d for %d)\n", pr_err("drop: too small buffer! (%d for %d)\n",
mbo->buffer_length, mdp_len); mbo->buffer_length, mdp_len);
...@@ -128,6 +133,11 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) ...@@ -128,6 +133,11 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
u8 *buff = mbo->virt_address; u8 *buff = mbo->virt_address;
unsigned int mep_len = skb->len + MEP_HDR_LEN; 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) { if (mbo->buffer_length < mep_len) {
pr_err("drop: too small buffer! (%d for %d)\n", pr_err("drop: too small buffer! (%d for %d)\n",
mbo->buffer_length, mep_len); mbo->buffer_length, mep_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment