aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/msg.c24
-rw-r--r--net/tipc/msg.h7
-rw-r--r--net/tipc/node.c2
3 files changed, 24 insertions, 9 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;
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index bf8f57ccc70c..3e4384c222f7 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)
926} 926}
927 927
928struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp); 928struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp);
929bool tipc_msg_validate(struct sk_buff *skb); 929bool tipc_msg_validate(struct sk_buff **_skb);
930bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err); 930bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
931void tipc_skb_reject(struct net *net, int err, struct sk_buff *skb, 931void tipc_skb_reject(struct net *net, int err, struct sk_buff *skb,
932 struct sk_buff_head *xmitq); 932 struct sk_buff_head *xmitq);
@@ -954,6 +954,11 @@ static inline u16 buf_seqno(struct sk_buff *skb)
954 return msg_seqno(buf_msg(skb)); 954 return msg_seqno(buf_msg(skb));
955} 955}
956 956
957static inline int buf_roundup_len(struct sk_buff *skb)
958{
959 return (skb->len / 1024 + 1) * 1024;
960}
961
957/* tipc_skb_peek(): peek and reserve first buffer in list 962/* tipc_skb_peek(): peek and reserve first buffer in list
958 * @list: list to be peeked in 963 * @list: list to be peeked in
959 * Returns pointer to first buffer in list, if any 964 * Returns pointer to first buffer in list, if any
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 009a81631280..507017fe0f1b 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)
1539 __skb_queue_head_init(&xmitq); 1539 __skb_queue_head_init(&xmitq);
1540 1540
1541 /* Ensure message is well-formed before touching the header */ 1541 /* Ensure message is well-formed before touching the header */
1542 if (unlikely(!tipc_msg_validate(skb))) 1542 if (unlikely(!tipc_msg_validate(&skb)))
1543 goto discard; 1543 goto discard;
1544 hdr = buf_msg(skb); 1544 hdr = buf_msg(skb);
1545 usr = msg_user(hdr); 1545 usr = msg_user(hdr);