diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-10-10 20:30:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-10-10 20:30:46 -0400 |
commit | 227b60f5102cda4e4ab792b526a59c8cb20cd9f8 (patch) | |
tree | 2c9e372601ba794894833b0618bc531a9f5d57c4 | |
parent | 06393009000779b00a558fd2f280882cc7dc2008 (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>
-rw-r--r-- | drivers/infiniband/core/cma.c | 22 | ||||
-rw-r--r-- | include/net/ip.h | 3 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 22 | ||||
-rw-r--r-- | net/ipv4/inet_hashtables.c | 13 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 75 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 1 | ||||
-rw-r--r-- | net/ipv4/udp.c | 6 | ||||
-rw-r--r-- | net/ipv6/inet6_hashtables.c | 12 | ||||
-rw-r--r-- | net/sctp/socket.c | 11 | ||||
-rw-r--r-- | security/selinux/hooks.c | 39 |
10 files changed, 146 insertions, 58 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9ffb9987450..2e641b255db 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -1866,13 +1866,14 @@ err1: | |||
1866 | static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) | 1866 | static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) |
1867 | { | 1867 | { |
1868 | struct rdma_bind_list *bind_list; | 1868 | struct rdma_bind_list *bind_list; |
1869 | int port, ret; | 1869 | int port, ret, low, high; |
1870 | 1870 | ||
1871 | bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); | 1871 | bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); |
1872 | if (!bind_list) | 1872 | if (!bind_list) |
1873 | return -ENOMEM; | 1873 | return -ENOMEM; |
1874 | 1874 | ||
1875 | retry: | 1875 | retry: |
1876 | /* FIXME: add proper port randomization per like inet_csk_get_port */ | ||
1876 | do { | 1877 | do { |
1877 | ret = idr_get_new_above(ps, bind_list, next_port, &port); | 1878 | ret = idr_get_new_above(ps, bind_list, next_port, &port); |
1878 | } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL)); | 1879 | } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL)); |
@@ -1880,18 +1881,19 @@ retry: | |||
1880 | if (ret) | 1881 | if (ret) |
1881 | goto err1; | 1882 | goto err1; |
1882 | 1883 | ||
1883 | if (port > sysctl_local_port_range[1]) { | 1884 | inet_get_local_port_range(&low, &high); |
1884 | if (next_port != sysctl_local_port_range[0]) { | 1885 | if (port > high) { |
1886 | if (next_port != low) { | ||
1885 | idr_remove(ps, port); | 1887 | idr_remove(ps, port); |
1886 | next_port = sysctl_local_port_range[0]; | 1888 | next_port = low; |
1887 | goto retry; | 1889 | goto retry; |
1888 | } | 1890 | } |
1889 | ret = -EADDRNOTAVAIL; | 1891 | ret = -EADDRNOTAVAIL; |
1890 | goto err2; | 1892 | goto err2; |
1891 | } | 1893 | } |
1892 | 1894 | ||
1893 | if (port == sysctl_local_port_range[1]) | 1895 | if (port == high) |
1894 | next_port = sysctl_local_port_range[0]; | 1896 | next_port = low; |
1895 | else | 1897 | else |
1896 | next_port = port + 1; | 1898 | next_port = port + 1; |
1897 | 1899 | ||
@@ -2769,12 +2771,12 @@ static void cma_remove_one(struct ib_device *device) | |||
2769 | 2771 | ||
2770 | static int cma_init(void) | 2772 | static int cma_init(void) |
2771 | { | 2773 | { |
2772 | int ret; | 2774 | int ret, low, high; |
2773 | 2775 | ||
2774 | get_random_bytes(&next_port, sizeof next_port); | 2776 | get_random_bytes(&next_port, sizeof next_port); |
2775 | next_port = ((unsigned int) next_port % | 2777 | inet_get_local_port_range(&low, &high); |
2776 | (sysctl_local_port_range[1] - sysctl_local_port_range[0])) + | 2778 | next_port = ((unsigned int) next_port % (high - low)) + low; |
2777 | sysctl_local_port_range[0]; | 2779 | |
2778 | cma_wq = create_singlethread_workqueue("rdma_cm"); | 2780 | cma_wq = create_singlethread_workqueue("rdma_cm"); |
2779 | if (!cma_wq) | 2781 | if (!cma_wq) |
2780 | return -ENOMEM; | 2782 | return -ENOMEM; |
diff --git a/include/net/ip.h b/include/net/ip.h index abf2820a112..3af3ed9d320 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -171,7 +171,8 @@ extern unsigned long snmp_fold_field(void *mib[], int offt); | |||
171 | extern int snmp_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); | 171 | extern int snmp_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); |
172 | extern void snmp_mib_free(void *ptr[2]); | 172 | extern void snmp_mib_free(void *ptr[2]); |
173 | 173 | ||
174 | extern int sysctl_local_port_range[2]; | 174 | extern void inet_get_local_port_range(int *low, int *high); |
175 | |||
175 | extern int sysctl_ip_default_ttl; | 176 | extern int sysctl_ip_default_ttl; |
176 | extern int sysctl_ip_nonlocal_bind; | 177 | extern int sysctl_ip_nonlocal_bind; |
177 | 178 | ||
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index fbe7714f21d..3cef12835c4 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -33,6 +33,19 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg); | |||
33 | * This array holds the first and last local port number. | 33 | * This array holds the first and last local port number. |
34 | */ | 34 | */ |
35 | int sysctl_local_port_range[2] = { 32768, 61000 }; | 35 | int sysctl_local_port_range[2] = { 32768, 61000 }; |
36 | DEFINE_SEQLOCK(sysctl_port_range_lock); | ||
37 | |||
38 | void inet_get_local_port_range(int *low, int *high) | ||
39 | { | ||
40 | unsigned seq; | ||
41 | do { | ||
42 | seq = read_seqbegin(&sysctl_port_range_lock); | ||
43 | |||
44 | *low = sysctl_local_port_range[0]; | ||
45 | *high = sysctl_local_port_range[1]; | ||
46 | } while (read_seqretry(&sysctl_port_range_lock, seq)); | ||
47 | } | ||
48 | EXPORT_SYMBOL(inet_get_local_port_range); | ||
36 | 49 | ||
37 | int inet_csk_bind_conflict(const struct sock *sk, | 50 | int inet_csk_bind_conflict(const struct sock *sk, |
38 | const struct inet_bind_bucket *tb) | 51 | const struct inet_bind_bucket *tb) |
@@ -77,10 +90,11 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, | |||
77 | 90 | ||
78 | local_bh_disable(); | 91 | local_bh_disable(); |
79 | if (!snum) { | 92 | if (!snum) { |
80 | int low = sysctl_local_port_range[0]; | 93 | int remaining, rover, low, high; |
81 | int high = sysctl_local_port_range[1]; | 94 | |
82 | int remaining = (high - low) + 1; | 95 | inet_get_local_port_range(&low, &high); |
83 | int rover = net_random() % (high - low) + low; | 96 | remaining = high - low; |
97 | rover = net_random() % remaining + low; | ||
84 | 98 | ||
85 | do { | 99 | do { |
86 | head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; | 100 | head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index fb662621c54..fac6398e436 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -279,19 +279,18 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row, | |||
279 | int ret; | 279 | int ret; |
280 | 280 | ||
281 | if (!snum) { | 281 | if (!snum) { |
282 | int low = sysctl_local_port_range[0]; | 282 | int i, remaining, low, high, port; |
283 | int high = sysctl_local_port_range[1]; | ||
284 | int range = high - low; | ||
285 | int i; | ||
286 | int port; | ||
287 | static u32 hint; | 283 | static u32 hint; |
288 | u32 offset = hint + inet_sk_port_offset(sk); | 284 | u32 offset = hint + inet_sk_port_offset(sk); |
289 | struct hlist_node *node; | 285 | struct hlist_node *node; |
290 | struct inet_timewait_sock *tw = NULL; | 286 | struct inet_timewait_sock *tw = NULL; |
291 | 287 | ||
288 | inet_get_local_port_range(&low, &high); | ||
289 | remaining = high - low; | ||
290 | |||
292 | local_bh_disable(); | 291 | local_bh_disable(); |
293 | for (i = 1; i <= range; i++) { | 292 | for (i = 1; i <= remaining; i++) { |
294 | port = low + (i + offset) % range; | 293 | port = low + (i + offset) % remaining; |
295 | head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; | 294 | head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; |
296 | spin_lock(&head->lock); | 295 | spin_lock(&head->lock); |
297 | 296 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 53ef0f4bbda..eb286abcf5d 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 | ||
93 | extern seqlock_t sysctl_port_range_lock; | ||
94 | extern int sysctl_local_port_range[2]; | ||
95 | |||
96 | /* Update system visible IP port range */ | ||
97 | static 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. */ | ||
106 | static 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. */ | ||
134 | static 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 | |||
92 | static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file * filp, | 161 | static 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, |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 8855e640e95..38cf73a5673 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -2470,6 +2470,5 @@ EXPORT_SYMBOL(tcp_v4_syn_recv_sock); | |||
2470 | EXPORT_SYMBOL(tcp_proc_register); | 2470 | EXPORT_SYMBOL(tcp_proc_register); |
2471 | EXPORT_SYMBOL(tcp_proc_unregister); | 2471 | EXPORT_SYMBOL(tcp_proc_unregister); |
2472 | #endif | 2472 | #endif |
2473 | EXPORT_SYMBOL(sysctl_local_port_range); | ||
2474 | EXPORT_SYMBOL(sysctl_tcp_low_latency); | 2473 | EXPORT_SYMBOL(sysctl_tcp_low_latency); |
2475 | 2474 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ef4d901ee9a..cb9fc58efb2 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -147,11 +147,11 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
147 | write_lock_bh(&udp_hash_lock); | 147 | write_lock_bh(&udp_hash_lock); |
148 | 148 | ||
149 | if (!snum) { | 149 | if (!snum) { |
150 | int i; | 150 | int i, low, high; |
151 | int low = sysctl_local_port_range[0]; | ||
152 | int high = sysctl_local_port_range[1]; | ||
153 | unsigned rover, best, best_size_so_far; | 151 | unsigned rover, best, best_size_so_far; |
154 | 152 | ||
153 | inet_get_local_port_range(&low, &high); | ||
154 | |||
155 | best_size_so_far = UINT_MAX; | 155 | best_size_so_far = UINT_MAX; |
156 | best = rover = net_random() % (high - low) + low; | 156 | best = rover = net_random() % (high - low) + low; |
157 | 157 | ||
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index ae6b0e7eb48..1c2c2765543 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -254,18 +254,18 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, | |||
254 | int ret; | 254 | int ret; |
255 | 255 | ||
256 | if (snum == 0) { | 256 | if (snum == 0) { |
257 | const int low = sysctl_local_port_range[0]; | 257 | int i, port, low, high, remaining; |
258 | const int high = sysctl_local_port_range[1]; | ||
259 | const int range = high - low; | ||
260 | int i, port; | ||
261 | static u32 hint; | 258 | static u32 hint; |
262 | const u32 offset = hint + inet6_sk_port_offset(sk); | 259 | const u32 offset = hint + inet6_sk_port_offset(sk); |
263 | struct hlist_node *node; | 260 | struct hlist_node *node; |
264 | struct inet_timewait_sock *tw = NULL; | 261 | struct inet_timewait_sock *tw = NULL; |
265 | 262 | ||
263 | inet_get_local_port_range(&low, &high); | ||
264 | remaining = high - low; | ||
265 | |||
266 | local_bh_disable(); | 266 | local_bh_disable(); |
267 | for (i = 1; i <= range; i++) { | 267 | for (i = 1; i <= remaining; i++) { |
268 | port = low + (i + offset) % range; | 268 | port = low + (i + offset) % remaining; |
269 | head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; | 269 | head = &hinfo->bhash[inet_bhashfn(port, hinfo->bhash_size)]; |
270 | spin_lock(&head->lock); | 270 | spin_lock(&head->lock); |
271 | 271 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 7cd58ef84ed..9c6a4b5f626 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5315,11 +5315,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5315 | 5315 | ||
5316 | if (snum == 0) { | 5316 | if (snum == 0) { |
5317 | /* Search for an available port. */ | 5317 | /* Search for an available port. */ |
5318 | unsigned int low = sysctl_local_port_range[0]; | 5318 | int low, high, remaining, index; |
5319 | unsigned int high = sysctl_local_port_range[1]; | 5319 | unsigned int rover; |
5320 | unsigned int remaining = (high - low) + 1; | 5320 | |
5321 | unsigned int rover = net_random() % remaining + low; | 5321 | inet_get_local_port_range(&low, &high); |
5322 | int index; | 5322 | remaining = (high - low) + 1; |
5323 | rover = net_random() % remaining + low; | ||
5323 | 5324 | ||
5324 | do { | 5325 | do { |
5325 | rover++; | 5326 | rover++; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0753b20e23f..3c3fff33d1c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #include <linux/netfilter_ipv6.h> | 47 | #include <linux/netfilter_ipv6.h> |
48 | #include <linux/tty.h> | 48 | #include <linux/tty.h> |
49 | #include <net/icmp.h> | 49 | #include <net/icmp.h> |
50 | #include <net/ip.h> /* for sysctl_local_port_range[] */ | 50 | #include <net/ip.h> /* for local_port_range[] */ |
51 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ | 51 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ |
52 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
53 | #include <asm/ioctls.h> | 53 | #include <asm/ioctls.h> |
@@ -3232,8 +3232,6 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3232 | /* Range of port numbers used to automatically bind. | 3232 | /* Range of port numbers used to automatically bind. |
3233 | Need to determine whether we should perform a name_bind | 3233 | Need to determine whether we should perform a name_bind |
3234 | permission check between the socket and the port number. */ | 3234 | permission check between the socket and the port number. */ |
3235 | #define ip_local_port_range_0 sysctl_local_port_range[0] | ||
3236 | #define ip_local_port_range_1 sysctl_local_port_range[1] | ||
3237 | 3235 | ||
3238 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3236 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3239 | { | 3237 | { |
@@ -3276,20 +3274,27 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3276 | addrp = (char *)&addr6->sin6_addr.s6_addr; | 3274 | addrp = (char *)&addr6->sin6_addr.s6_addr; |
3277 | } | 3275 | } |
3278 | 3276 | ||
3279 | if (snum&&(snum < max(PROT_SOCK,ip_local_port_range_0) || | 3277 | if (snum) { |
3280 | snum > ip_local_port_range_1)) { | 3278 | int low, high; |
3281 | err = security_port_sid(sk->sk_family, sk->sk_type, | 3279 | |
3282 | sk->sk_protocol, snum, &sid); | 3280 | inet_get_local_port_range(&low, &high); |
3283 | if (err) | 3281 | |
3284 | goto out; | 3282 | if (snum < max(PROT_SOCK, low) || snum > high) { |
3285 | AVC_AUDIT_DATA_INIT(&ad,NET); | 3283 | err = security_port_sid(sk->sk_family, |
3286 | ad.u.net.sport = htons(snum); | 3284 | sk->sk_type, |
3287 | ad.u.net.family = family; | 3285 | sk->sk_protocol, snum, |
3288 | err = avc_has_perm(isec->sid, sid, | 3286 | &sid); |
3289 | isec->sclass, | 3287 | if (err) |
3290 | SOCKET__NAME_BIND, &ad); | 3288 | goto out; |
3291 | if (err) | 3289 | AVC_AUDIT_DATA_INIT(&ad,NET); |
3292 | goto out; | 3290 | ad.u.net.sport = htons(snum); |
3291 | ad.u.net.family = family; | ||
3292 | err = avc_has_perm(isec->sid, sid, | ||
3293 | isec->sclass, | ||
3294 | SOCKET__NAME_BIND, &ad); | ||
3295 | if (err) | ||
3296 | goto out; | ||
3297 | } | ||
3293 | } | 3298 | } |
3294 | 3299 | ||
3295 | switch(isec->sclass) { | 3300 | switch(isec->sclass) { |