From bd4f158ca795506569b503210e667dfd192c011e Mon Sep 17 00:00:00 2001 From: S.Çağlar Onur Date: Tue, 7 Dec 2010 11:07:12 -0500 Subject: [PATCH] linux-2.6-523-raw-sockets.patch --- include/linux/vserver/network.h | 2 ++ net/core/sock.c | 15 ++++++++++++++- net/ipv4/af_inet.c | 3 +++ net/ipv4/ip_options.c | 6 +++--- net/ipv4/raw.c | 13 +++++++------ 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/linux/vserver/network.h b/include/linux/vserver/network.h index 1775630..86715c2 100644 --- a/include/linux/vserver/network.h +++ b/include/linux/vserver/network.h @@ -47,6 +47,8 @@ static inline uint64_t __nxf_init_set(void) { #define NXC_TUN_CREATE 0x00000001 #define NXC_RAW_ICMP 0x00000100 +#define NXC_RAW_SOCKET 0x00000200 +#define NXC_RAW_SEND 0x00000400 /* address types */ diff --git a/net/core/sock.c b/net/core/sock.c index 53cb689..4638715 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -401,7 +401,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen) /* Sorry... */ ret = -EPERM; - if (!capable(CAP_NET_RAW)) + if (!nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) goto out; ret = -EINVAL; @@ -537,6 +537,19 @@ set_sndbuf: } goto set_sndbuf; + case SO_SETXID: + if (current_vx_info()) { + ret = -EPERM; + break; + } + if (val < 0 || val > MAX_S_CONTEXT) { + ret = -EINVAL; + break; + } + sk->sk_xid = val; + sk->sk_nid = val; + break; + case SO_RCVBUF: /* Don't error on this BSD doesn't and if you think about it this is right. Otherwise apps have to diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9e8942b..1c0b4a5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -332,6 +332,9 @@ lookup_protocol: if ((protocol == IPPROTO_ICMP) && nx_capable(CAP_NET_RAW, NXC_RAW_ICMP)) goto override; + if (sock->type == SOCK_RAW && + nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) + goto override; if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) goto out_rcu_unlock; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 94bf105..dc81f1c 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -397,7 +397,7 @@ int ip_options_compile(struct net *net, optptr[2] += 8; break; default: - if (!skb && !capable(CAP_NET_RAW)) { + if (!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) { pp_ptr = optptr + 3; goto error; } @@ -433,7 +433,7 @@ int ip_options_compile(struct net *net, opt->router_alert = optptr - iph; break; case IPOPT_CIPSO: - if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) { + if ((!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) || opt->cipso) { pp_ptr = optptr; goto error; } @@ -446,7 +446,7 @@ int ip_options_compile(struct net *net, case IPOPT_SEC: case IPOPT_SID: default: - if (!skb && !capable(CAP_NET_RAW)) { + if (!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) { pp_ptr = optptr; goto error; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 8913f67..3583cba 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -108,7 +108,7 @@ void raw_unhash_sk(struct sock *sk) EXPORT_SYMBOL_GPL(raw_unhash_sk); static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, - unsigned short num, __be32 raddr, __be32 laddr, int dif) + unsigned short num, __be32 raddr, __be32 laddr, int dif, int tag) { struct hlist_node *node; @@ -117,6 +117,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, if (net_eq(sock_net(sk), net) && inet->num == num && !(inet->daddr && inet->daddr != raddr) && + (!sk->sk_nx_info || tag == 1 || sk->sk_nid == tag) && v4_sock_addr_match(sk->sk_nx_info, inet, laddr) && !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) goto found; /* gotcha */ @@ -169,7 +170,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) net = dev_net(skb->dev); sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, iph->saddr, iph->daddr, - skb->dev->ifindex); + skb->dev->ifindex, skb->skb_tag); while (sk) { delivered = 1; @@ -182,7 +183,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) } sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, iph->saddr, iph->daddr, - skb->dev->ifindex); + skb->dev->ifindex, skb->skb_tag); } out: read_unlock(&raw_v4_hashinfo.lock); @@ -277,8 +278,8 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) net = dev_net(skb->dev); while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, - iph->daddr, iph->saddr, - skb->dev->ifindex)) != NULL) { + iph->daddr, iph->saddr, skb->dev->ifindex, + skb->skb_tag)) != NULL) { raw_err(raw_sk, skb, info); raw_sk = sk_next(raw_sk); iph = (struct iphdr *)skb->data; @@ -384,7 +385,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, skb_transport_header(skb))->type); err = -EPERM; - if (!nx_check(0, VS_ADMIN) && !capable(CAP_NET_RAW) && + if (!nx_check(0, VS_ADMIN) && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET) && sk->sk_nx_info && !v4_addr_in_nx_info(sk->sk_nx_info, iph->saddr, NXA_MASK_BIND)) goto error_free; -- 1.5.4.3