| From stable-bounces@linux.kernel.org Wed Jun 6 22:50:52 2007 |
| Date: Wed, 06 Jun 2007 22:51:03 -0700 (PDT) |
| Message-Id: <20070606.225103.52166535.davem@davemloft.net> |
| To: stable@kernel.org |
| From: David Miller <davem@davemloft.net> |
| Cc: bunk@stusta.de |
| Subject: NET: "wrong timeout value" in sk_wait_data() v2 |
| |
| From: Vasily Averin <vvs@sw.ru> |
| |
| sys_setsockopt() do not check properly timeout values for |
| SO_RCVTIMEO/SO_SNDTIMEO, for example it's possible to set negative timeout |
| values. POSIX do not defines behaviour for sys_setsockopt in case negative |
| timeouts, but requires that setsockopt() shall fail with -EDOM if the send and |
| receive timeout values are too big to fit into the timeout fields in the socket |
| structure. |
| In current implementation negative timeout can lead to error messages like |
| "schedule_timeout: wrong timeout value". |
| |
| Proposed patch: |
| - checks tv_usec and returns -EDOM if it is wrong |
| - do not allows to set negative timeout values (sets 0 instead) and outputs |
| ratelimited information message about such attempts. |
| |
| Signed-off-By: Vasily Averin <vvs@sw.ru> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/core/sock.c | 12 ++++++++++++ |
| 1 file changed, 12 insertions(+) |
| |
| --- linux-2.6.21.4.orig/net/core/sock.c |
| +++ linux-2.6.21.4/net/core/sock.c |
| @@ -204,7 +204,19 @@ static int sock_set_timeout(long *timeo_ |
| return -EINVAL; |
| if (copy_from_user(&tv, optval, sizeof(tv))) |
| return -EFAULT; |
| + if (tv.tv_usec < 0 || tv.tv_usec >= USEC_PER_SEC) |
| + return -EDOM; |
| |
| + if (tv.tv_sec < 0) { |
| + static int warned = 0; |
| + *timeo_p = 0; |
| + if (warned < 10 && net_ratelimit()) |
| + warned++; |
| + printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) " |
| + "tries to set negative timeout\n", |
| + current->comm, current->pid); |
| + return 0; |
| + } |
| *timeo_p = MAX_SCHEDULE_TIMEOUT; |
| if (tv.tv_sec == 0 && tv.tv_usec == 0) |
| return 0; |