aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2018-09-28 14:23:18 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-29 14:24:22 -0400
commit5cbdbd1a1f30a083aada44595ca42952fc31e866 (patch)
tree504887bd2f99020985c48601406fa1807f39b67e /net/tipc
parenta337531b942bd8a03e7052444d7e36972aac2d92 (diff)
tipc: refactor function tipc_msg_reverse()
The function tipc_msg_reverse() is reversing the header of a message while reusing the original buffer. We have seen at several occasions that this may have unfortunate side effects when the buffer to be reversed is a clone. In one of the following commits we will again need to reverse cloned buffers, so this is the right time to permanently eliminate this problem. In this commit we let the said function always consume the original buffer and replace it with a new one when applicable. 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')
-rw-r--r--net/tipc/msg.c58
1 files changed, 28 insertions, 30 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index b61891054709..00fbb5c4b2ef 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -499,54 +499,52 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
499/** 499/**
500 * tipc_msg_reverse(): swap source and destination addresses and add error code 500 * tipc_msg_reverse(): swap source and destination addresses and add error code
501 * @own_node: originating node id for reversed message 501 * @own_node: originating node id for reversed message
502 * @skb: buffer containing message to be reversed; may be replaced. 502 * @skb: buffer containing message to be reversed; will be consumed
503 * @err: error code to be set in message, if any 503 * @err: error code to be set in message, if any
504 * Consumes buffer at failure 504 * Replaces consumed buffer with new one when successful
505 * Returns true if success, otherwise false 505 * Returns true if success, otherwise false
506 */ 506 */
507bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err) 507bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err)
508{ 508{
509 struct sk_buff *_skb = *skb; 509 struct sk_buff *_skb = *skb;
510 struct tipc_msg *hdr; 510 struct tipc_msg *_hdr, *hdr;
511 struct tipc_msg ohdr; 511 int hlen, dlen;
512 int dlen;
513 512
514 if (skb_linearize(_skb)) 513 if (skb_linearize(_skb))
515 goto exit; 514 goto exit;
516 hdr = buf_msg(_skb); 515 _hdr = buf_msg(_skb);
517 dlen = min_t(uint, msg_data_sz(hdr), MAX_FORWARD_SIZE); 516 dlen = min_t(uint, msg_data_sz(_hdr), MAX_FORWARD_SIZE);
518 if (msg_dest_droppable(hdr)) 517 hlen = msg_hdr_sz(_hdr);
518
519 if (msg_dest_droppable(_hdr))
519 goto exit; 520 goto exit;
520 if (msg_errcode(hdr)) 521 if (msg_errcode(_hdr))
521 goto exit; 522 goto exit;
522 523
523 /* Take a copy of original header before altering message */ 524 /* Never return SHORT header */
524 memcpy(&ohdr, hdr, msg_hdr_sz(hdr)); 525 if (hlen == SHORT_H_SIZE)
525 526 hlen = BASIC_H_SIZE;
526 /* Never return SHORT header; expand by replacing buffer if necessary */
527 if (msg_short(hdr)) {
528 *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen, GFP_ATOMIC);
529 if (!*skb)
530 goto exit;
531 memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
532 kfree_skb(_skb);
533 _skb = *skb;
534 hdr = buf_msg(_skb);
535 memcpy(hdr, &ohdr, BASIC_H_SIZE);
536 msg_set_hdr_sz(hdr, BASIC_H_SIZE);
537 }
538 527
539 /* Now reverse the concerned fields */ 528 /* Allocate new buffer to return */
529 *skb = tipc_buf_acquire(hlen + dlen, GFP_ATOMIC);
530 if (!*skb)
531 goto exit;
532 memcpy((*skb)->data, _skb->data, msg_hdr_sz(_hdr));
533 memcpy((*skb)->data + hlen, msg_data(_hdr), dlen);
534
535 /* Build reverse header in new buffer */
536 hdr = buf_msg(*skb);
537 msg_set_hdr_sz(hdr, hlen);
540 msg_set_errcode(hdr, err); 538 msg_set_errcode(hdr, err);
541 msg_set_non_seq(hdr, 0); 539 msg_set_non_seq(hdr, 0);
542 msg_set_origport(hdr, msg_destport(&ohdr)); 540 msg_set_origport(hdr, msg_destport(_hdr));
543 msg_set_destport(hdr, msg_origport(&ohdr)); 541 msg_set_destport(hdr, msg_origport(_hdr));
544 msg_set_destnode(hdr, msg_prevnode(&ohdr)); 542 msg_set_destnode(hdr, msg_prevnode(_hdr));
545 msg_set_prevnode(hdr, own_node); 543 msg_set_prevnode(hdr, own_node);
546 msg_set_orignode(hdr, own_node); 544 msg_set_orignode(hdr, own_node);
547 msg_set_size(hdr, msg_hdr_sz(hdr) + dlen); 545 msg_set_size(hdr, hlen + dlen);
548 skb_trim(_skb, msg_size(hdr));
549 skb_orphan(_skb); 546 skb_orphan(_skb);
547 kfree_skb(_skb);
550 return true; 548 return true;
551exit: 549exit:
552 kfree_skb(_skb); 550 kfree_skb(_skb);