All of lore.kernel.org
 help / color / mirror / Atom feed
* [net-next  1/1] tipc: enforce valid ratio between skb truesize and contents
@ 2017-11-15 20:23 Jon Maloy
  2017-11-16  1:50 ` David Miller
  2017-11-21 12:17 ` David Laight
  0 siblings, 2 replies; 3+ messages in thread
From: Jon Maloy @ 2017-11-15 20:23 UTC (permalink / raw)
  To: davem, netdev
  Cc: mohan.krishna.ghanta.krishnamurthy, tung.q.nguyen, hoang.h.le,
	jon.maloy, canh.d.luu, ying.xue, tipc-discussion

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>
---
 net/tipc/msg.c  | 24 +++++++++++++++++-------
 net/tipc/msg.h  |  7 ++++++-
 net/tipc/node.c |  2 +-
 3 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 1649d45..b0d07b3 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)
 
 	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 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
  * 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;
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index d97d1ea..791b058 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -926,7 +926,7 @@ static inline bool msg_is_reset(struct tipc_msg *hdr)
 }
 
 struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp);
-bool tipc_msg_validate(struct sk_buff *skb);
+bool tipc_msg_validate(struct sk_buff **_skb);
 bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
 void tipc_skb_reject(struct net *net, int err, struct sk_buff *skb,
 		     struct sk_buff_head *xmitq);
@@ -954,6 +954,11 @@ static inline u16 buf_seqno(struct sk_buff *skb)
 	return msg_seqno(buf_msg(skb));
 }
 
+static inline int buf_roundup_len(struct sk_buff *skb)
+{
+	return (skb->len / 1024 + 1) * 1024;
+}
+
 /* tipc_skb_peek(): peek and reserve first buffer in list
  * @list: list to be peeked in
  * Returns pointer to first buffer in list, if any
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 009a816..507017f 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1539,7 +1539,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
 	__skb_queue_head_init(&xmitq);
 
 	/* Ensure message is well-formed before touching the header */
-	if (unlikely(!tipc_msg_validate(skb)))
+	if (unlikely(!tipc_msg_validate(&skb)))
 		goto discard;
 	hdr = buf_msg(skb);
 	usr = msg_user(hdr);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [net-next 1/1] tipc: enforce valid ratio between skb truesize and contents
  2017-11-15 20:23 [net-next 1/1] tipc: enforce valid ratio between skb truesize and contents Jon Maloy
@ 2017-11-16  1:50 ` David Miller
  2017-11-21 12:17 ` David Laight
  1 sibling, 0 replies; 3+ messages in thread
From: David Miller @ 2017-11-16  1:50 UTC (permalink / raw)
  To: jon.maloy
  Cc: netdev, tipc-discussion, hoang.h.le, ying.xue,
	mohan.krishna.ghanta.krishnamurthy

From: Jon Maloy <jon.maloy@ericsson.com>
Date: Wed, 15 Nov 2017 21:23:56 +0100

> 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>

Applied.

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [net-next  1/1] tipc: enforce valid ratio between skb truesize and contents
  2017-11-15 20:23 [net-next 1/1] tipc: enforce valid ratio between skb truesize and contents Jon Maloy
  2017-11-16  1:50 ` David Miller
@ 2017-11-21 12:17 ` David Laight
  1 sibling, 0 replies; 3+ messages in thread
From: David Laight @ 2017-11-21 12:17 UTC (permalink / raw)
  To: 'Jon Maloy', davem, netdev
  Cc: mohan.krishna.ghanta.krishnamurthy, tung.q.nguyen, hoang.h.le,
	canh.d.luu, ying.xue, tipc-discussion

From: Jon Maloy
> Sent: 15 November 2017 20:24
> 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.

I'd be more worried about drivers that set skb->truesize to the amount
of data in the skb rather than the memory used by the skb.

Last I looked some of the usbnet drivers lied badly.

	David

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-11-21 12:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-15 20:23 [net-next 1/1] tipc: enforce valid ratio between skb truesize and contents Jon Maloy
2017-11-16  1:50 ` David Miller
2017-11-21 12:17 ` David Laight

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.