aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-03-13 16:08:06 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-14 14:38:32 -0400
commitcf2157f88a5abf1a64b8c51a737a35e918dc67e5 (patch)
tree8896dd853ffa7676faeba4423d494a17fba67db1 /net
parent7764d6e83d2c3b50d9282f12144ebb10418c056e (diff)
tipc: move message validation function to msg.c
The function link_buf_validate() is in reality re-entrant and context independent, and will in later commits be called from several locations. Therefore, we move it to msg.c, make it outline and rename the it to tipc_msg_validate(). We also redesign the function to make proper use of pskb_may_pull() Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/tipc/link.c58
-rw-r--r--net/tipc/msg.c44
-rw-r--r--net/tipc/msg.h5
3 files changed, 47 insertions, 60 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 98609fdfb06a..944c8c663a2d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1048,61 +1048,6 @@ static void link_retrieve_defq(struct tipc_link *link,
1048} 1048}
1049 1049
1050/** 1050/**
1051 * link_recv_buf_validate - validate basic format of received message
1052 *
1053 * This routine ensures a TIPC message has an acceptable header, and at least
1054 * as much data as the header indicates it should. The routine also ensures
1055 * that the entire message header is stored in the main fragment of the message
1056 * buffer, to simplify future access to message header fields.
1057 *
1058 * Note: Having extra info present in the message header or data areas is OK.
1059 * TIPC will ignore the excess, under the assumption that it is optional info
1060 * introduced by a later release of the protocol.
1061 */
1062static int link_recv_buf_validate(struct sk_buff *buf)
1063{
1064 static u32 min_data_hdr_size[8] = {
1065 SHORT_H_SIZE, MCAST_H_SIZE, NAMED_H_SIZE, BASIC_H_SIZE,
1066 MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
1067 };
1068
1069 struct tipc_msg *msg;
1070 u32 tipc_hdr[2];
1071 u32 size;
1072 u32 hdr_size;
1073 u32 min_hdr_size;
1074
1075 /* If this packet comes from the defer queue, the skb has already
1076 * been validated
1077 */
1078 if (unlikely(TIPC_SKB_CB(buf)->deferred))
1079 return 1;
1080
1081 if (unlikely(buf->len < MIN_H_SIZE))
1082 return 0;
1083
1084 msg = skb_header_pointer(buf, 0, sizeof(tipc_hdr), tipc_hdr);
1085 if (msg == NULL)
1086 return 0;
1087
1088 if (unlikely(msg_version(msg) != TIPC_VERSION))
1089 return 0;
1090
1091 size = msg_size(msg);
1092 hdr_size = msg_hdr_sz(msg);
1093 min_hdr_size = msg_isdata(msg) ?
1094 min_data_hdr_size[msg_type(msg)] : INT_H_SIZE;
1095
1096 if (unlikely((hdr_size < min_hdr_size) ||
1097 (size < hdr_size) ||
1098 (buf->len < size) ||
1099 (size - hdr_size > TIPC_MAX_USER_MSG_SIZE)))
1100 return 0;
1101
1102 return pskb_may_pull(buf, hdr_size);
1103}
1104
1105/**
1106 * tipc_rcv - process TIPC packets/messages arriving from off-node 1051 * tipc_rcv - process TIPC packets/messages arriving from off-node
1107 * @net: the applicable net namespace 1052 * @net: the applicable net namespace
1108 * @skb: TIPC packet 1053 * @skb: TIPC packet
@@ -1127,7 +1072,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
1127 1072
1128 while ((skb = __skb_dequeue(&head))) { 1073 while ((skb = __skb_dequeue(&head))) {
1129 /* Ensure message is well-formed */ 1074 /* Ensure message is well-formed */
1130 if (unlikely(!link_recv_buf_validate(skb))) 1075 if (unlikely(!tipc_msg_validate(skb)))
1131 goto discard; 1076 goto discard;
1132 1077
1133 /* Ensure message data is a single contiguous unit */ 1078 /* Ensure message data is a single contiguous unit */
@@ -1398,7 +1343,6 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
1398 1343
1399 if (tipc_link_defer_pkt(&l_ptr->deferred_queue, buf)) { 1344 if (tipc_link_defer_pkt(&l_ptr->deferred_queue, buf)) {
1400 l_ptr->stats.deferred_recv++; 1345 l_ptr->stats.deferred_recv++;
1401 TIPC_SKB_CB(buf)->deferred = true;
1402 if ((skb_queue_len(&l_ptr->deferred_queue) % 16) == 1) 1346 if ((skb_queue_len(&l_ptr->deferred_queue) % 16) == 1)
1403 tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); 1347 tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
1404 } else { 1348 } else {
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index b6eb90cd3ef7..4a64caf6fa20 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/msg.c: TIPC message header routines 2 * net/tipc/msg.c: TIPC message header routines
3 * 3 *
4 * Copyright (c) 2000-2006, 2014, Ericsson AB 4 * Copyright (c) 2000-2006, 2014-2015, Ericsson AB
5 * Copyright (c) 2005, 2010-2011, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -181,6 +181,48 @@ err:
181 return 0; 181 return 0;
182} 182}
183 183
184/* tipc_msg_validate - validate basic format of received message
185 *
186 * This routine ensures a TIPC message has an acceptable header, and at least
187 * as much data as the header indicates it should. The routine also ensures
188 * that the entire message header is stored in the main fragment of the message
189 * buffer, to simplify future access to message header fields.
190 *
191 * Note: Having extra info present in the message header or data areas is OK.
192 * TIPC will ignore the excess, under the assumption that it is optional info
193 * introduced by a later release of the protocol.
194 */
195bool tipc_msg_validate(struct sk_buff *skb)
196{
197 struct tipc_msg *msg;
198 int msz, hsz;
199
200 if (unlikely(TIPC_SKB_CB(skb)->validated))
201 return true;
202 if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE)))
203 return false;
204
205 hsz = msg_hdr_sz(buf_msg(skb));
206 if (unlikely(hsz < MIN_H_SIZE) || (hsz > MAX_H_SIZE))
207 return false;
208 if (unlikely(!pskb_may_pull(skb, hsz)))
209 return false;
210
211 msg = buf_msg(skb);
212 if (unlikely(msg_version(msg) != TIPC_VERSION))
213 return false;
214
215 msz = msg_size(msg);
216 if (unlikely(msz < hsz))
217 return false;
218 if (unlikely((msz - hsz) > TIPC_MAX_USER_MSG_SIZE))
219 return false;
220 if (unlikely(skb->len < msz))
221 return false;
222
223 TIPC_SKB_CB(skb)->validated = true;
224 return true;
225}
184 226
185/** 227/**
186 * tipc_msg_build - create buffer chain containing specified header and data 228 * tipc_msg_build - create buffer chain containing specified header and data
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 7cece647394c..62306b8d2410 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/msg.h: Include file for TIPC message header routines 2 * net/tipc/msg.h: Include file for TIPC message header routines
3 * 3 *
4 * Copyright (c) 2000-2007, 2014, Ericsson AB 4 * Copyright (c) 2000-2007, 2014-2015 Ericsson AB
5 * Copyright (c) 2005-2008, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-2008, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -92,7 +92,7 @@ struct plist;
92struct tipc_skb_cb { 92struct tipc_skb_cb {
93 void *handle; 93 void *handle;
94 struct sk_buff *tail; 94 struct sk_buff *tail;
95 bool deferred; 95 bool validated;
96 bool wakeup_pending; 96 bool wakeup_pending;
97 bool bundling; 97 bool bundling;
98 u16 chain_sz; 98 u16 chain_sz;
@@ -758,6 +758,7 @@ static inline u32 msg_tot_origport(struct tipc_msg *m)
758} 758}
759 759
760struct sk_buff *tipc_buf_acquire(u32 size); 760struct sk_buff *tipc_buf_acquire(u32 size);
761bool tipc_msg_validate(struct sk_buff *skb);
761bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, 762bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode,
762 int err); 763 int err);
763void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, 764void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type,