summaryrefslogtreecommitdiffstats
path: root/net/tipc/msg.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-10-19 11:33:00 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-21 22:08:24 -0400
commit45c8b7b175ceb2d542e0fe15247377bf3bce29ec (patch)
treefc27cba7a71607103f6dcd3346fefb6f12c722ae /net/tipc/msg.c
parent1241365f1aeb24ef0ffe82970f7c558022ddc85f (diff)
tipc: allow non-linear first fragment buffer
The current code for message reassembly is erroneously assuming that the the first arriving fragment buffer always is linear, and then goes ahead resetting the fragment list of that buffer in anticipation of more arriving fragments. However, if the buffer already happens to be non-linear, we will inadvertently drop the already attached fragment list, and later on trig a BUG() in __pskb_pull_tail(). We see this happen when running fragmented TIPC multicast across UDP, something made possible since commit d0f91938bede ("tipc: add ip/udp media type") We fix this by not resetting the fragment list when the buffer is non- linear, and by initiatlizing our private fragment list tail pointer to the tail of the existing fragment list. Fixes: commit d0f91938bede ("tipc: add ip/udp media type") Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r--net/tipc/msg.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index c5ac436235e0..5f73450159df 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -121,7 +121,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
121{ 121{
122 struct sk_buff *head = *headbuf; 122 struct sk_buff *head = *headbuf;
123 struct sk_buff *frag = *buf; 123 struct sk_buff *frag = *buf;
124 struct sk_buff *tail; 124 struct sk_buff *tail = NULL;
125 struct tipc_msg *msg; 125 struct tipc_msg *msg;
126 u32 fragid; 126 u32 fragid;
127 int delta; 127 int delta;
@@ -141,9 +141,15 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
141 if (unlikely(skb_unclone(frag, GFP_ATOMIC))) 141 if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
142 goto err; 142 goto err;
143 head = *headbuf = frag; 143 head = *headbuf = frag;
144 skb_frag_list_init(head);
145 TIPC_SKB_CB(head)->tail = NULL;
146 *buf = NULL; 144 *buf = NULL;
145 TIPC_SKB_CB(head)->tail = NULL;
146 if (skb_is_nonlinear(head)) {
147 skb_walk_frags(head, tail) {
148 TIPC_SKB_CB(head)->tail = tail;
149 }
150 } else {
151 skb_frag_list_init(head);
152 }
147 return 0; 153 return 0;
148 } 154 }
149 155