aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/msg.c
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2017-11-15 15:23:56 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-15 20:49:00 -0500
commitd618d09a68e4eed7a435beb2e355250f6f40664a (patch)
tree293edbea3ef99f0c9c78de37a5d9dbb1b12791d7 /net/tipc/msg.c
parent8252fceac01570836f0cb9e922f56b4c0b1011df (diff)
tipc: enforce valid ratio between skb truesize and contents
The socket level flow control is based on the assumption that incoming buffers meet the condition (skb->truesize / roundup(skb->len) <= 4), where the latter value is rounded off upwards to the nearest 1k number. This does empirically hold true for the device drivers we know, but we cannot trust that it will always be so, e.g., in a system with jumbo frames and very small packets. We now introduce a check for this condition at packet arrival, and if we find it to be false, we copy the packet to a new, smaller buffer, where the condition will be true. We expect this to affect only a small fraction of all incoming packets, if at all. Acked-by: Ying Xue <ying.xue@windriver.com> 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.c24
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 */
204bool tipc_msg_validate(struct sk_buff *skb) 204bool 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;