Commit 29322d0db98e5a84f5cc6a55655bee3dc4ffb5ab

Authored by Jon Paul Maloy
Committed by David S. Miller
1 parent b6e195fd4f

tipc: fix bug in multicast/broadcast message reassembly

Since commit 37e22164a8a3c39bdad45aa463b1e69a1fdf4110 ("tipc: rename and
move message reassembly function") reassembly of long broadcast messages
has been broken. This is because we test for a non-NULL return value
of the *buf parameter as criteria for succesful reassembly. However, this
parameter is left defined even after reception of the first fragment,
when reassebly is still incomplete. This leads to a kernel crash as soon
as a the first fragment of a long broadcast message is received.

We fix this with this commit, by implementing a stricter behavior of the
function and its return values.

This commit should be applied to both net and net-next.

Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 8 additions and 3 deletions Side-by-side Diff

... ... @@ -101,9 +101,11 @@
101 101 }
102 102  
103 103 /* tipc_buf_append(): Append a buffer to the fragment list of another buffer
104   - * Let first buffer become head buffer
105   - * Returns 1 and sets *buf to headbuf if chain is complete, otherwise 0
106   - * Leaves headbuf pointer at NULL if failure
  104 + * @*headbuf: in: NULL for first frag, otherwise value returned from prev call
  105 + * out: set when successful non-complete reassembly, otherwise NULL
  106 + * @*buf: in: the buffer to append. Always defined
  107 + * out: head buf after sucessful complete reassembly, otherwise NULL
  108 + * Returns 1 when reassembly complete, otherwise 0
107 109 */
108 110 int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
109 111 {
... ... @@ -122,6 +124,7 @@
122 124 goto out_free;
123 125 head = *headbuf = frag;
124 126 skb_frag_list_init(head);
  127 + *buf = NULL;
125 128 return 0;
126 129 }
127 130 if (!head)
... ... @@ -150,6 +153,8 @@
150 153 out_free:
151 154 pr_warn_ratelimited("Unable to build fragment list\n");
152 155 kfree_skb(*buf);
  156 + kfree_skb(*headbuf);
  157 + *buf = *headbuf = NULL;
153 158 return 0;
154 159 }