aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Holt <holt@sgi.com>2010-10-20 02:03:37 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-09 13:27:06 -0800
commit61690148345a4a1ccced61ad9c44862f74d947cf (patch)
treeefe8e4a48973e19e2a0ae5670be0ad330b504fa8
parent1b881c33e3d1afde2324ee9c324a0463b0e8df8b (diff)
Limit sysctl_tcp_mem and sysctl_udp_mem initializers to prevent integer overflows.
[ Upstream fixed this in a different way as parts of the commits: 8d987e5c7510 (net: avoid limits overflow) a9febbb4bd13 (sysctl: min/max bounds are optional) 27b3d80a7b6a (sysctl: fix min/max handling in __do_proc_doulongvec_minmax()) -DaveM ] On a 16TB x86_64 machine, sysctl_tcp_mem[2], sysctl_udp_mem[2], and sysctl_sctp_mem[2] can integer overflow. Set limit such that they are maximized without overflowing. Signed-off-by: Robin Holt <holt@sgi.com> To: "David S. Miller" <davem@davemloft.net> Cc: Willy Tarreau <w@1wt.eu> Cc: linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-sctp@vger.kernel.org Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Cc: "Pekka Savola (ipv6)" <pekkas@netcore.fi> Cc: James Morris <jmorris@namei.org> Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org> Cc: Patrick McHardy <kaber@trash.net> Cc: Vlad Yasevich <vladislav.yasevich@hp.com> Cc: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--net/ipv4/tcp.c4
-rw-r--r--net/ipv4/udp.c4
-rw-r--r--net/sctp/protocol.c4
3 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 46783087137d..734fe94827dc 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2940,12 +2940,14 @@ void __init tcp_init(void)
/* Set the pressure threshold to be a fraction of global memory that
* is up to 1/2 at 256 MB, decreasing toward zero with the amount of
- * memory, with a floor of 128 pages.
+ * memory, with a floor of 128 pages, and a ceiling that prevents an
+ * integer overflow.
*/
nr_pages = totalram_pages - totalhigh_pages;
limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
limit = max(limit, 128UL);
+ limit = min(limit, INT_MAX * 4UL / 3 / 2);
sysctl_tcp_mem[0] = limit / 4 * 3;
sysctl_tcp_mem[1] = limit;
sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index c322f4429fc9..31db78ca7469 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1832,12 +1832,14 @@ void __init udp_init(void)
udp_table_init(&udp_table);
/* Set the pressure threshold up by the same strategy of TCP. It is a
* fraction of global memory that is up to 1/2 at 256 MB, decreasing
- * toward zero with the amount of memory, with a floor of 128 pages.
+ * toward zero with the amount of memory, with a floor of 128 pages,
+ * and a ceiling that prevents an integer overflow.
*/
nr_pages = totalram_pages - totalhigh_pages;
limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
limit = max(limit, 128UL);
+ limit = min(limit, INT_MAX * 4UL / 3 / 2);
sysctl_udp_mem[0] = limit / 4 * 3;
sysctl_udp_mem[1] = limit;
sysctl_udp_mem[2] = sysctl_udp_mem[0] * 2;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 612dc878e05c..619f96568e8e 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1157,7 +1157,8 @@ SCTP_STATIC __init int sctp_init(void)
/* Set the pressure threshold to be a fraction of global memory that
* is up to 1/2 at 256 MB, decreasing toward zero with the amount of
- * memory, with a floor of 128 pages.
+ * memory, with a floor of 128 pages, and a ceiling that prevents an
+ * integer overflow.
* Note this initalizes the data in sctpv6_prot too
* Unabashedly stolen from tcp_init
*/
@@ -1165,6 +1166,7 @@ SCTP_STATIC __init int sctp_init(void)
limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
limit = max(limit, 128UL);
+ limit = min(limit, INT_MAX * 4UL / 3 / 2);
sysctl_sctp_mem[0] = limit / 4 * 3;
sysctl_sctp_mem[1] = limit;
sysctl_sctp_mem[2] = sysctl_sctp_mem[0] * 2;