diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-03-13 16:08:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-14 14:38:32 -0400 |
commit | cf2157f88a5abf1a64b8c51a737a35e918dc67e5 (patch) | |
tree | 8896dd853ffa7676faeba4423d494a17fba67db1 /net | |
parent | 7764d6e83d2c3b50d9282f12144ebb10418c056e (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.c | 58 | ||||
-rw-r--r-- | net/tipc/msg.c | 44 | ||||
-rw-r--r-- | net/tipc/msg.h | 5 |
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 | */ | ||
1062 | static 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 | */ | ||
195 | bool 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; | |||
92 | struct tipc_skb_cb { | 92 | struct 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 | ||
760 | struct sk_buff *tipc_buf_acquire(u32 size); | 760 | struct sk_buff *tipc_buf_acquire(u32 size); |
761 | bool tipc_msg_validate(struct sk_buff *skb); | ||
761 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, | 762 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, |
762 | int err); | 763 | int err); |
763 | void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, | 764 | void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, |