aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/sysctl_net_ipv4.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-10 20:30:46 -0400
committerDavid S. Miller <davem@davemloft.net>2007-10-10 20:30:46 -0400
commit227b60f5102cda4e4ab792b526a59c8cb20cd9f8 (patch)
tree2c9e372601ba794894833b0618bc531a9f5d57c4 /net/ipv4/sysctl_net_ipv4.c
parent06393009000779b00a558fd2f280882cc7dc2008 (diff)
[INET]: local port range robustness
Expansion of original idea from Denis V. Lunev <den@openvz.org> Add robustness and locking to the local_port_range sysctl. 1. Enforce that low < high when setting. 2. Use seqlock to ensure atomic update. The locking might seem like overkill, but there are cases where sysadmin might want to change value in the middle of a DoS attack. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/sysctl_net_ipv4.c')
-rw-r--r--net/ipv4/sysctl_net_ipv4.c75
1 files changed, 71 insertions, 4 deletions
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 53ef0f4bbdaa..eb286abcf5dc 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -12,6 +12,7 @@
12#include <linux/sysctl.h> 12#include <linux/sysctl.h>
13#include <linux/igmp.h> 13#include <linux/igmp.h>
14#include <linux/inetdevice.h> 14#include <linux/inetdevice.h>
15#include <linux/seqlock.h>
15#include <net/snmp.h> 16#include <net/snmp.h>
16#include <net/icmp.h> 17#include <net/icmp.h>
17#include <net/ip.h> 18#include <net/ip.h>
@@ -89,6 +90,74 @@ static int ipv4_sysctl_forward_strategy(ctl_table *table,
89 return 1; 90 return 1;
90} 91}
91 92
93extern seqlock_t sysctl_port_range_lock;
94extern int sysctl_local_port_range[2];
95
96/* Update system visible IP port range */
97static void set_local_port_range(int range[2])
98{
99 write_seqlock(&sysctl_port_range_lock);
100 sysctl_local_port_range[0] = range[0];
101 sysctl_local_port_range[1] = range[1];
102 write_sequnlock(&sysctl_port_range_lock);
103}
104
105/* Validate changes from /proc interface. */
106static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp,
107 void __user *buffer,
108 size_t *lenp, loff_t *ppos)
109{
110 int ret;
111 int range[2] = { sysctl_local_port_range[0],
112 sysctl_local_port_range[1] };
113 ctl_table tmp = {
114 .data = &range,
115 .maxlen = sizeof(range),
116 .mode = table->mode,
117 .extra1 = &ip_local_port_range_min,
118 .extra2 = &ip_local_port_range_max,
119 };
120
121 ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos);
122
123 if (write && ret == 0) {
124 if (range[1] <= range[0])
125 ret = -EINVAL;
126 else
127 set_local_port_range(range);
128 }
129
130 return ret;
131}
132
133/* Validate changes from sysctl interface. */
134static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name,
135 int nlen, void __user *oldval,
136 size_t __user *oldlenp,
137 void __user *newval, size_t newlen)
138{
139 int ret;
140 int range[2] = { sysctl_local_port_range[0],
141 sysctl_local_port_range[1] };
142 ctl_table tmp = {
143 .data = &range,
144 .maxlen = sizeof(range),
145 .mode = table->mode,
146 .extra1 = &ip_local_port_range_min,
147 .extra2 = &ip_local_port_range_max,
148 };
149
150 ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen);
151 if (ret == 0 && newval && newlen) {
152 if (range[1] <= range[0])
153 ret = -EINVAL;
154 else
155 set_local_port_range(range);
156 }
157 return ret;
158}
159
160
92static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file * filp, 161static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file * filp,
93 void __user *buffer, size_t *lenp, loff_t *ppos) 162 void __user *buffer, size_t *lenp, loff_t *ppos)
94{ 163{
@@ -427,10 +496,8 @@ ctl_table ipv4_table[] = {
427 .data = &sysctl_local_port_range, 496 .data = &sysctl_local_port_range,
428 .maxlen = sizeof(sysctl_local_port_range), 497 .maxlen = sizeof(sysctl_local_port_range),
429 .mode = 0644, 498 .mode = 0644,
430 .proc_handler = &proc_dointvec_minmax, 499 .proc_handler = &ipv4_local_port_range,
431 .strategy = &sysctl_intvec, 500 .strategy = &ipv4_sysctl_local_port_range,
432 .extra1 = ip_local_port_range_min,
433 .extra2 = ip_local_port_range_max
434 }, 501 },
435 { 502 {
436 .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_ALL, 503 .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_ALL,