aboutsummaryrefslogtreecommitdiffstats
path: root/security
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 /security
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 'security')
-rw-r--r--security/selinux/hooks.c39
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
3238static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) 3236static 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) {