diff options
author | David S. Miller <davem@davemloft.net> | 2017-03-03 00:16:08 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-03-03 00:16:08 +0300 |
commit | 6ab2b999e7babba1ae20c64a90889723c07ade72 (patch) | |
tree | f3ce8a513c47f132de3009e49ec501ad3e95b15b /net/batman-adv | |
parent | f1304f7ba3981e71dcf2ac7db92949eeab49b1bf (diff) | |
parent | 51c6b429c0c95e67edd1cb0b548c5cf6a6604763 (diff) | |
download | linux-6ab2b999e7babba1ae20c64a90889723c07ade72.tar.xz |
Merge tag 'batadv-net-for-davem-20170301' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says:
====================
Here are two batman-adv bugfixes:
- fix a potential double free when fragment merges fail,
by Sven Eckelmann
- fix failing tranmission of the 16th (last) fragment if that exists,
by Linus Lüssing
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/fragmentation.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index ead18ca836de..11a23fd6e1a0 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -239,8 +239,10 @@ err_unlock: spin_unlock_bh(&chain->lock); err: - if (!ret) + if (!ret) { kfree(frag_entry_new); + kfree_skb(skb); + } return ret; } @@ -313,7 +315,7 @@ free: * * There are three possible outcomes: 1) Packet is merged: Return true and * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb - * to NULL; 3) Error: Return false and leave skb as is. + * to NULL; 3) Error: Return false and free skb. * * Return: true when packet is merged or buffered, false when skb is not not * used. @@ -338,9 +340,9 @@ bool batadv_frag_skb_buffer(struct sk_buff **skb, goto out_err; out: - *skb = skb_out; ret = true; out_err: + *skb = skb_out; return ret; } @@ -499,6 +501,12 @@ int batadv_frag_send_packet(struct sk_buff *skb, /* Eat and send fragments from the tail of skb */ while (skb->len > max_fragment_size) { + /* The initial check in this function should cover this case */ + if (unlikely(frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1)) { + ret = -EINVAL; + goto put_primary_if; + } + skb_fragment = batadv_frag_create(skb, &frag_header, mtu); if (!skb_fragment) { ret = -ENOMEM; @@ -515,12 +523,6 @@ int batadv_frag_send_packet(struct sk_buff *skb, } frag_header.no++; - - /* The initial check in this function should cover this case */ - if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) { - ret = -EINVAL; - goto put_primary_if; - } } /* Make room for the fragment header. */ |