diff options
Diffstat (limited to 'net/ipv4/sysctl_net_ipv4.c')
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index c8d283615c6f..1b861997fdc5 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -35,6 +35,8 @@ static int ip_local_port_range_min[] = { 1, 1 }; | |||
35 | static int ip_local_port_range_max[] = { 65535, 65535 }; | 35 | static int ip_local_port_range_max[] = { 65535, 65535 }; |
36 | static int tcp_adv_win_scale_min = -31; | 36 | static int tcp_adv_win_scale_min = -31; |
37 | static int tcp_adv_win_scale_max = 31; | 37 | static int tcp_adv_win_scale_max = 31; |
38 | static int ip_privileged_port_min; | ||
39 | static int ip_privileged_port_max = 65535; | ||
38 | static int ip_ttl_min = 1; | 40 | static int ip_ttl_min = 1; |
39 | static int ip_ttl_max = 255; | 41 | static int ip_ttl_max = 255; |
40 | static int tcp_syn_retries_min = 1; | 42 | static int tcp_syn_retries_min = 1; |
@@ -79,7 +81,12 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, | |||
79 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); | 81 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
80 | 82 | ||
81 | if (write && ret == 0) { | 83 | if (write && ret == 0) { |
82 | if (range[1] < range[0]) | 84 | /* Ensure that the upper limit is not smaller than the lower, |
85 | * and that the lower does not encroach upon the privileged | ||
86 | * port limit. | ||
87 | */ | ||
88 | if ((range[1] < range[0]) || | ||
89 | (range[0] < net->ipv4.sysctl_ip_prot_sock)) | ||
83 | ret = -EINVAL; | 90 | ret = -EINVAL; |
84 | else | 91 | else |
85 | set_local_port_range(net, range); | 92 | set_local_port_range(net, range); |
@@ -88,6 +95,40 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, | |||
88 | return ret; | 95 | return ret; |
89 | } | 96 | } |
90 | 97 | ||
98 | /* Validate changes from /proc interface. */ | ||
99 | static int ipv4_privileged_ports(struct ctl_table *table, int write, | ||
100 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
101 | { | ||
102 | struct net *net = container_of(table->data, struct net, | ||
103 | ipv4.sysctl_ip_prot_sock); | ||
104 | int ret; | ||
105 | int pports; | ||
106 | int range[2]; | ||
107 | struct ctl_table tmp = { | ||
108 | .data = &pports, | ||
109 | .maxlen = sizeof(pports), | ||
110 | .mode = table->mode, | ||
111 | .extra1 = &ip_privileged_port_min, | ||
112 | .extra2 = &ip_privileged_port_max, | ||
113 | }; | ||
114 | |||
115 | pports = net->ipv4.sysctl_ip_prot_sock; | ||
116 | |||
117 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); | ||
118 | |||
119 | if (write && ret == 0) { | ||
120 | inet_get_local_port_range(net, &range[0], &range[1]); | ||
121 | /* Ensure that the local port range doesn't overlap with the | ||
122 | * privileged port range. | ||
123 | */ | ||
124 | if (range[0] < pports) | ||
125 | ret = -EINVAL; | ||
126 | else | ||
127 | net->ipv4.sysctl_ip_prot_sock = pports; | ||
128 | } | ||
129 | |||
130 | return ret; | ||
131 | } | ||
91 | 132 | ||
92 | static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) | 133 | static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) |
93 | { | 134 | { |
@@ -964,6 +1005,13 @@ static struct ctl_table ipv4_net_table[] = { | |||
964 | .extra2 = &one, | 1005 | .extra2 = &one, |
965 | }, | 1006 | }, |
966 | #endif | 1007 | #endif |
1008 | { | ||
1009 | .procname = "ip_unprivileged_port_start", | ||
1010 | .maxlen = sizeof(int), | ||
1011 | .data = &init_net.ipv4.sysctl_ip_prot_sock, | ||
1012 | .mode = 0644, | ||
1013 | .proc_handler = ipv4_privileged_ports, | ||
1014 | }, | ||
967 | { } | 1015 | { } |
968 | }; | 1016 | }; |
969 | 1017 | ||