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>
This commit is contained in:
committed by
David S. Miller
parent
8252fceac0
commit
d618d09a68
@@ -174,7 +174,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
|
||||
|
||||
if (fragid == LAST_FRAGMENT) {
|
||||
TIPC_SKB_CB(head)->validated = false;
|
||||
if (unlikely(!tipc_msg_validate(head)))
|
||||
if (unlikely(!tipc_msg_validate(&head)))
|
||||
goto err;
|
||||
*buf = head;
|
||||
TIPC_SKB_CB(head)->tail = NULL;
|
||||
@@ -201,11 +201,21 @@ err:
|
||||
* TIPC will ignore the excess, under the assumption that it is optional info
|
||||
* introduced by a later release of the protocol.
|
||||
*/
|
||||
bool tipc_msg_validate(struct sk_buff *skb)
|
||||
bool tipc_msg_validate(struct sk_buff **_skb)
|
||||
{
|
||||
struct tipc_msg *msg;
|
||||
struct sk_buff *skb = *_skb;
|
||||
struct tipc_msg *hdr;
|
||||
int msz, hsz;
|
||||
|
||||
/* Ensure that flow control ratio condition is satisfied */
|
||||
if (unlikely(skb->truesize / buf_roundup_len(skb) > 4)) {
|
||||
skb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return false;
|
||||
kfree_skb(*_skb);
|
||||
*_skb = skb;
|
||||
}
|
||||
|
||||
if (unlikely(TIPC_SKB_CB(skb)->validated))
|
||||
return true;
|
||||
if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE)))
|
||||
@@ -217,11 +227,11 @@ bool tipc_msg_validate(struct sk_buff *skb)
|
||||
if (unlikely(!pskb_may_pull(skb, hsz)))
|
||||
return false;
|
||||
|
||||
msg = buf_msg(skb);
|
||||
if (unlikely(msg_version(msg) != TIPC_VERSION))
|
||||
hdr = buf_msg(skb);
|
||||
if (unlikely(msg_version(hdr) != TIPC_VERSION))
|
||||
return false;
|
||||
|
||||
msz = msg_size(msg);
|
||||
msz = msg_size(hdr);
|
||||
if (unlikely(msz < hsz))
|
||||
return false;
|
||||
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)
|
||||
skb_pull(*iskb, offset);
|
||||
imsz = msg_size(buf_msg(*iskb));
|
||||
skb_trim(*iskb, imsz);
|
||||
if (unlikely(!tipc_msg_validate(*iskb)))
|
||||
if (unlikely(!tipc_msg_validate(iskb)))
|
||||
goto none;
|
||||
*pos += align(imsz);
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user