add linux-2.6-523-raw-sockets.patch
[linux-2.6.git] / linux-2.6-523-raw-sockets.patch
1 diff --git a/include/linux/vserver/network.h b/include/linux/vserver/network.h
2 index 1775630..86715c2 100644
3 --- a/include/linux/vserver/network.h
4 +++ b/include/linux/vserver/network.h
5 @@ -47,6 +47,8 @@ static inline uint64_t __nxf_init_set(void) {
6  #define NXC_TUN_CREATE         0x00000001
7  
8  #define NXC_RAW_ICMP           0x00000100
9 +#define NXC_RAW_SOCKET         0x00000200
10 +#define NXC_RAW_SEND           0x00000400
11  
12  
13  /* address types */
14 diff --git a/net/core/sock.c b/net/core/sock.c
15 index d276d4b..ac135b9 100644
16 --- a/net/core/sock.c
17 +++ b/net/core/sock.c
18 @@ -395,7 +395,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
19  
20         /* Sorry... */
21         ret = -EPERM;
22 -       if (!capable(CAP_NET_RAW))
23 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET))
24                 goto out;
25  
26         ret = -EINVAL;
27 @@ -531,6 +531,19 @@ set_sndbuf:
28                 }
29                 goto set_sndbuf;
30  
31 +       case SO_SETXID:
32 +               if (current_vx_info()) {
33 +                       ret = -EPERM;
34 +                       break;
35 +               }
36 +               if (val < 0 || val > MAX_S_CONTEXT) {
37 +                       ret = -EINVAL;
38 +                       break;
39 +               }
40 +               sk->sk_xid = val;
41 +               sk->sk_nid = val;
42 +               break;
43 +
44         case SO_RCVBUF:
45                 /* Don't error on this BSD doesn't and if you think
46                    about it this is right. Otherwise apps have to
47 diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
48 index 026c3b1..1e9b53c 100644
49 --- a/net/ipv4/af_inet.c
50 +++ b/net/ipv4/af_inet.c
51 @@ -332,6 +332,9 @@ lookup_protocol:
52         if ((protocol == IPPROTO_ICMP) &&
53                 nx_capable(CAP_NET_RAW, NXC_RAW_ICMP))
54                 goto override;
55 +       if (sock->type == SOCK_RAW &&
56 +               nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET))
57 +               goto override;
58         if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
59                 goto out_rcu_unlock;
60  override:
61 diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
62 index 94bf105..dc81f1c 100644
63 --- a/net/ipv4/ip_options.c
64 +++ b/net/ipv4/ip_options.c
65 @@ -397,7 +397,7 @@ int ip_options_compile(struct net *net,
66                                         optptr[2] += 8;
67                                         break;
68                                       default:
69 -                                       if (!skb && !capable(CAP_NET_RAW)) {
70 +                                       if (!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) {
71                                                 pp_ptr = optptr + 3;
72                                                 goto error;
73                                         }
74 @@ -433,7 +433,7 @@ int ip_options_compile(struct net *net,
75                                 opt->router_alert = optptr - iph;
76                         break;
77                       case IPOPT_CIPSO:
78 -                       if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
79 +                       if ((!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) || opt->cipso) {
80                                 pp_ptr = optptr;
81                                 goto error;
82                         }
83 @@ -446,7 +446,7 @@ int ip_options_compile(struct net *net,
84                       case IPOPT_SEC:
85                       case IPOPT_SID:
86                       default:
87 -                       if (!skb && !capable(CAP_NET_RAW)) {
88 +                       if (!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) {
89                                 pp_ptr = optptr;
90                                 goto error;
91                         }
92 diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
93 index 8913f67..3583cba 100644
94 --- a/net/ipv4/raw.c
95 +++ b/net/ipv4/raw.c
96 @@ -108,7 +108,7 @@ void raw_unhash_sk(struct sock *sk)
97  EXPORT_SYMBOL_GPL(raw_unhash_sk);
98  
99  static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
100 -               unsigned short num, __be32 raddr, __be32 laddr, int dif)
101 +               unsigned short num, __be32 raddr, __be32 laddr, int dif, int tag)
102  {
103         struct hlist_node *node;
104  
105 @@ -117,6 +117,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
106  
107                 if (net_eq(sock_net(sk), net) && inet->num == num       &&
108                     !(inet->daddr && inet->daddr != raddr)              &&
109 +                   (!sk->sk_nx_info || tag == 1 || sk->sk_nid == tag)  &&
110                     v4_sock_addr_match(sk->sk_nx_info, inet, laddr)     &&
111                     !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
112                         goto found; /* gotcha */
113 @@ -169,7 +170,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
114         net = dev_net(skb->dev);
115         sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
116                              iph->saddr, iph->daddr,
117 -                            skb->dev->ifindex);
118 +                            skb->dev->ifindex, skb->skb_tag);
119  
120         while (sk) {
121                 delivered = 1;
122 @@ -182,7 +183,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
123                 }
124                 sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
125                                      iph->saddr, iph->daddr,
126 -                                    skb->dev->ifindex);
127 +                                    skb->dev->ifindex, skb->skb_tag);
128         }
129  out:
130         read_unlock(&raw_v4_hashinfo.lock);
131 @@ -277,8 +278,8 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
132                 net = dev_net(skb->dev);
133  
134                 while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
135 -                                               iph->daddr, iph->saddr,
136 -                                               skb->dev->ifindex)) != NULL) {
137 +                       iph->daddr, iph->saddr, skb->dev->ifindex,
138 +                       skb->skb_tag)) != NULL) {
139                         raw_err(raw_sk, skb, info);
140                         raw_sk = sk_next(raw_sk);
141                         iph = (struct iphdr *)skb->data;
142 @@ -384,7 +385,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
143                         skb_transport_header(skb))->type);
144  
145         err = -EPERM;
146 -       if (!nx_check(0, VS_ADMIN) && !capable(CAP_NET_RAW) &&
147 +       if (!nx_check(0, VS_ADMIN) && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET) &&
148                 sk->sk_nx_info &&
149                 !v4_addr_in_nx_info(sk->sk_nx_info, iph->saddr, NXA_MASK_BIND))
150                 goto error_free;