| From 4dff6c35f9ff1cf62dd4435517adae40a3dd2d8a Mon Sep 17 00:00:00 2001 |
| From: Xi Wang <xi.wang@gmail.com> |
| Date: Fri, 16 Dec 2011 12:44:15 +0000 |
| Subject: sctp: fix incorrect overflow check on autoclose |
| |
| |
| From: Xi Wang <xi.wang@gmail.com> |
| |
| [ Upstream commit 2692ba61a82203404abd7dd2a027bda962861f74 ] |
| |
| Commit 8ffd3208 voids the previous patches f6778aab and 810c0719 for |
| limiting the autoclose value. If userspace passes in -1 on 32-bit |
| platform, the overflow check didn't work and autoclose would be set |
| to 0xffffffff. |
| |
| This patch defines a max_autoclose (in seconds) for limiting the value |
| and exposes it through sysctl, with the following intentions. |
| |
| 1) Avoid overflowing autoclose * HZ. |
| |
| 2) Keep the default autoclose bound consistent across 32- and 64-bit |
| platforms (INT_MAX / HZ in this patch). |
| |
| 3) Keep the autoclose value consistent between setsockopt() and |
| getsockopt() calls. |
| |
| Suggested-by: Vlad Yasevich <vladislav.yasevich@hp.com> |
| Signed-off-by: Xi Wang <xi.wang@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| include/net/sctp/structs.h | 4 ++++ |
| net/sctp/associola.c | 2 +- |
| net/sctp/protocol.c | 3 +++ |
| net/sctp/socket.c | 2 -- |
| net/sctp/sysctl.c | 13 +++++++++++++ |
| 5 files changed, 21 insertions(+), 3 deletions(-) |
| |
| --- a/include/net/sctp/structs.h |
| +++ b/include/net/sctp/structs.h |
| @@ -236,6 +236,9 @@ extern struct sctp_globals { |
| * bits is an indicator of when to send and window update SACK. |
| */ |
| int rwnd_update_shift; |
| + |
| + /* Threshold for autoclose timeout, in seconds. */ |
| + unsigned long max_autoclose; |
| } sctp_globals; |
| |
| #define sctp_rto_initial (sctp_globals.rto_initial) |
| @@ -271,6 +274,7 @@ extern struct sctp_globals { |
| #define sctp_auth_enable (sctp_globals.auth_enable) |
| #define sctp_checksum_disable (sctp_globals.checksum_disable) |
| #define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift) |
| +#define sctp_max_autoclose (sctp_globals.max_autoclose) |
| |
| /* SCTP Socket type: UDP or TCP style. */ |
| typedef enum { |
| --- a/net/sctp/associola.c |
| +++ b/net/sctp/associola.c |
| @@ -173,7 +173,7 @@ static struct sctp_association *sctp_ass |
| asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; |
| asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; |
| asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = |
| - (unsigned long)sp->autoclose * HZ; |
| + min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ; |
| |
| /* Initializes the timers */ |
| for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) |
| --- a/net/sctp/protocol.c |
| +++ b/net/sctp/protocol.c |
| @@ -1144,6 +1144,9 @@ SCTP_STATIC __init int sctp_init(void) |
| sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; |
| sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; |
| |
| + /* Initialize maximum autoclose timeout. */ |
| + sctp_max_autoclose = INT_MAX / HZ; |
| + |
| /* Initialize handle used for association ids. */ |
| idr_init(&sctp_assocs_id); |
| |
| --- a/net/sctp/socket.c |
| +++ b/net/sctp/socket.c |
| @@ -2129,8 +2129,6 @@ static int sctp_setsockopt_autoclose(str |
| return -EINVAL; |
| if (copy_from_user(&sp->autoclose, optval, optlen)) |
| return -EFAULT; |
| - /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */ |
| - sp->autoclose = min_t(long, sp->autoclose, MAX_SCHEDULE_TIMEOUT / HZ); |
| |
| return 0; |
| } |
| --- a/net/sctp/sysctl.c |
| +++ b/net/sctp/sysctl.c |
| @@ -53,6 +53,10 @@ static int sack_timer_min = 1; |
| static int sack_timer_max = 500; |
| static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ |
| static int rwnd_scale_max = 16; |
| +static unsigned long max_autoclose_min = 0; |
| +static unsigned long max_autoclose_max = |
| + (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) |
| + ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; |
| |
| extern long sysctl_sctp_mem[3]; |
| extern int sysctl_sctp_rmem[3]; |
| @@ -251,6 +255,15 @@ static ctl_table sctp_table[] = { |
| .extra1 = &one, |
| .extra2 = &rwnd_scale_max, |
| }, |
| + { |
| + .procname = "max_autoclose", |
| + .data = &sctp_max_autoclose, |
| + .maxlen = sizeof(unsigned long), |
| + .mode = 0644, |
| + .proc_handler = &proc_doulongvec_minmax, |
| + .extra1 = &max_autoclose_min, |
| + .extra2 = &max_autoclose_max, |
| + }, |
| |
| { /* sentinel */ } |
| }; |