diff options
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 1649d456e22d..b0d07b35909d 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -174,7 +174,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) | |||
174 | 174 | ||
175 | if (fragid == LAST_FRAGMENT) { | 175 | if (fragid == LAST_FRAGMENT) { |
176 | TIPC_SKB_CB(head)->validated = false; | 176 | TIPC_SKB_CB(head)->validated = false; |
177 | if (unlikely(!tipc_msg_validate(head))) | 177 | if (unlikely(!tipc_msg_validate(&head))) |
178 | goto err; | 178 | goto err; |
179 | *buf = head; | 179 | *buf = head; |
180 | TIPC_SKB_CB(head)->tail = NULL; | 180 | TIPC_SKB_CB(head)->tail = NULL; |
@@ -201,11 +201,21 @@ err: | |||
201 | * TIPC will ignore the excess, under the assumption that it is optional info | 201 | * TIPC will ignore the excess, under the assumption that it is optional info |
202 | * introduced by a later release of the protocol. | 202 | * introduced by a later release of the protocol. |
203 | */ | 203 | */ |
204 | bool tipc_msg_validate(struct sk_buff *skb) | 204 | bool tipc_msg_validate(struct sk_buff **_skb) |
205 | { | 205 | { |
206 | struct tipc_msg *msg; | 206 | struct sk_buff *skb = *_skb; |
207 | struct tipc_msg *hdr; | ||
207 | int msz, hsz; | 208 | int msz, hsz; |
208 | 209 | ||
210 | /* Ensure that flow control ratio condition is satisfied */ | ||
211 | if (unlikely(skb->truesize / buf_roundup_len(skb) > 4)) { | ||
212 | skb = skb_copy(skb, GFP_ATOMIC); | ||
213 | if (!skb) | ||
214 | return false; | ||
215 | kfree_skb(*_skb); | ||
216 | *_skb = skb; | ||
217 | } | ||
218 | |||
209 | if (unlikely(TIPC_SKB_CB(skb)->validated)) | 219 | if (unlikely(TIPC_SKB_CB(skb)->validated)) |
210 | return true; | 220 | return true; |
211 | if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE))) | 221 | if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE))) |
@@ -217,11 +227,11 @@ bool tipc_msg_validate(struct sk_buff *skb) | |||
217 | if (unlikely(!pskb_may_pull(skb, hsz))) | 227 | if (unlikely(!pskb_may_pull(skb, hsz))) |
218 | return false; | 228 | return false; |
219 | 229 | ||
220 | msg = buf_msg(skb); | 230 | hdr = buf_msg(skb); |
221 | if (unlikely(msg_version(msg) != TIPC_VERSION)) | 231 | if (unlikely(msg_version(hdr) != TIPC_VERSION)) |
222 | return false; | 232 | return false; |
223 | 233 | ||
224 | msz = msg_size(msg); | 234 | msz = msg_size(hdr); |
225 | if (unlikely(msz < hsz)) | 235 | if (unlikely(msz < hsz)) |
226 | return false; | 236 | return false; |
227 | if (unlikely((msz - hsz) > TIPC_MAX_USER_MSG_SIZE)) | 237 | if (unlikely((msz - hsz) > TIPC_MAX_USER_MSG_SIZE)) |
@@ -411,7 +421,7 @@ bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) | |||
411 | skb_pull(*iskb, offset); | 421 | skb_pull(*iskb, offset); |
412 | imsz = msg_size(buf_msg(*iskb)); | 422 | imsz = msg_size(buf_msg(*iskb)); |
413 | skb_trim(*iskb, imsz); | 423 | skb_trim(*iskb, imsz); |
414 | if (unlikely(!tipc_msg_validate(*iskb))) | 424 | if (unlikely(!tipc_msg_validate(iskb))) |
415 | goto none; | 425 | goto none; |
416 | *pos += align(imsz); | 426 | *pos += align(imsz); |
417 | return true; | 427 | return true; |