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 /security/selinux/hooks.c | |
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>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0753b20e23fe..3c3fff33d1ce 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) { |