aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h2
-rw-r--r--net/ipv4/syncookies.c25
-rw-r--r--net/ipv6/syncookies.c4
3 files changed, 22 insertions, 9 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 9e68e25c8b82..18c246c9b009 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -464,7 +464,7 @@ extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
464 __u16 *mss); 464 __u16 *mss);
465 465
466extern __u32 cookie_init_timestamp(struct request_sock *req); 466extern __u32 cookie_init_timestamp(struct request_sock *req);
467extern void cookie_check_timestamp(struct tcp_options_received *tcp_opt); 467extern bool cookie_check_timestamp(struct tcp_options_received *tcp_opt);
468 468
469/* From net/ipv6/syncookies.c */ 469/* From net/ipv6/syncookies.c */
470extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); 470extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 02bef6aa8b30..51b5662545d6 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -230,23 +230,36 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
230 * The lowest 4 bits are for snd_wscale 230 * The lowest 4 bits are for snd_wscale
231 * The next 4 lsb are for rcv_wscale 231 * The next 4 lsb are for rcv_wscale
232 * The next lsb is for sack_ok 232 * The next lsb is for sack_ok
233 *
234 * return false if we decode an option that should not be.
233 */ 235 */
234void cookie_check_timestamp(struct tcp_options_received *tcp_opt) 236bool cookie_check_timestamp(struct tcp_options_received *tcp_opt)
235{ 237{
236 /* echoed timestamp, 9 lowest bits contain options */ 238 /* echoed timestamp, 9 lowest bits contain options */
237 u32 options = tcp_opt->rcv_tsecr & TSMASK; 239 u32 options = tcp_opt->rcv_tsecr & TSMASK;
238 240
241 if (!tcp_opt->saw_tstamp) {
242 tcp_clear_options(tcp_opt);
243 return true;
244 }
245
246 if (!sysctl_tcp_timestamps)
247 return false;
248
239 tcp_opt->snd_wscale = options & 0xf; 249 tcp_opt->snd_wscale = options & 0xf;
240 options >>= 4; 250 options >>= 4;
241 tcp_opt->rcv_wscale = options & 0xf; 251 tcp_opt->rcv_wscale = options & 0xf;
242 252
243 tcp_opt->sack_ok = (options >> 4) & 0x1; 253 tcp_opt->sack_ok = (options >> 4) & 0x1;
244 254
245 if (tcp_opt->sack_ok) 255 if (tcp_opt->sack_ok && !sysctl_tcp_sack)
246 tcp_sack_reset(tcp_opt); 256 return false;
247 257
248 if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) 258 if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) {
249 tcp_opt->wscale_ok = 1; 259 tcp_opt->wscale_ok = 1;
260 return sysctl_tcp_window_scaling != 0;
261 }
262 return true;
250} 263}
251EXPORT_SYMBOL(cookie_check_timestamp); 264EXPORT_SYMBOL(cookie_check_timestamp);
252 265
@@ -281,8 +294,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
281 memset(&tcp_opt, 0, sizeof(tcp_opt)); 294 memset(&tcp_opt, 0, sizeof(tcp_opt));
282 tcp_parse_options(skb, &tcp_opt, &hash_location, 0); 295 tcp_parse_options(skb, &tcp_opt, &hash_location, 0);
283 296
284 if (tcp_opt.saw_tstamp) 297 if (!cookie_check_timestamp(&tcp_opt))
285 cookie_check_timestamp(&tcp_opt); 298 goto out;
286 299
287 ret = NULL; 300 ret = NULL;
288 req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ 301 req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 70d330f8c990..c7ee57421ece 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -180,8 +180,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
180 memset(&tcp_opt, 0, sizeof(tcp_opt)); 180 memset(&tcp_opt, 0, sizeof(tcp_opt));
181 tcp_parse_options(skb, &tcp_opt, &hash_location, 0); 181 tcp_parse_options(skb, &tcp_opt, &hash_location, 0);
182 182
183 if (tcp_opt.saw_tstamp) 183 if (!cookie_check_timestamp(&tcp_opt))
184 cookie_check_timestamp(&tcp_opt); 184 goto out;
185 185
186 ret = NULL; 186 ret = NULL;
187 req = inet6_reqsk_alloc(&tcp6_request_sock_ops); 187 req = inet6_reqsk_alloc(&tcp6_request_sock_ops);