diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-12-07 07:20:47 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-08 15:34:09 -0500 |
commit | f19872575ff7819a3723154657a497d9bca66b33 (patch) | |
tree | 3c84b591c773611a6c4c00589f69a6639e83b8e0 | |
parent | ad9f4f50fe9288bbe65b7dfd76d8820afac6a24c (diff) |
tcp: protect sysctl_tcp_cookie_size reads
Make sure sysctl_tcp_cookie_size is read once in
tcp_cookie_size_check(), or we might return an illegal value to caller
if sysctl_tcp_cookie_size is changed by another cpu.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: William Allen Simpson <william.allen.simpson@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/tcp_output.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 0d4a3cebfb46..61c2463e2753 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -385,27 +385,30 @@ struct tcp_out_options { | |||
385 | */ | 385 | */ |
386 | static u8 tcp_cookie_size_check(u8 desired) | 386 | static u8 tcp_cookie_size_check(u8 desired) |
387 | { | 387 | { |
388 | if (desired > 0) { | 388 | int cookie_size; |
389 | |||
390 | if (desired > 0) | ||
389 | /* previously specified */ | 391 | /* previously specified */ |
390 | return desired; | 392 | return desired; |
391 | } | 393 | |
392 | if (sysctl_tcp_cookie_size <= 0) { | 394 | cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size); |
395 | if (cookie_size <= 0) | ||
393 | /* no default specified */ | 396 | /* no default specified */ |
394 | return 0; | 397 | return 0; |
395 | } | 398 | |
396 | if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) { | 399 | if (cookie_size <= TCP_COOKIE_MIN) |
397 | /* value too small, specify minimum */ | 400 | /* value too small, specify minimum */ |
398 | return TCP_COOKIE_MIN; | 401 | return TCP_COOKIE_MIN; |
399 | } | 402 | |
400 | if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) { | 403 | if (cookie_size >= TCP_COOKIE_MAX) |
401 | /* value too large, specify maximum */ | 404 | /* value too large, specify maximum */ |
402 | return TCP_COOKIE_MAX; | 405 | return TCP_COOKIE_MAX; |
403 | } | 406 | |
404 | if (0x1 & sysctl_tcp_cookie_size) { | 407 | if (cookie_size & 1) |
405 | /* 8-bit multiple, illegal, fix it */ | 408 | /* 8-bit multiple, illegal, fix it */ |
406 | return (u8)(sysctl_tcp_cookie_size + 0x1); | 409 | cookie_size++; |
407 | } | 410 | |
408 | return (u8)sysctl_tcp_cookie_size; | 411 | return (u8)cookie_size; |
409 | } | 412 | } |
410 | 413 | ||
411 | /* Write previously computed TCP options to the packet. | 414 | /* Write previously computed TCP options to the packet. |