aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-05-15 23:23:48 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-15 23:23:48 -0400
commitf895f0cfbb77ff432bb6ae4df27b608adbe6573f (patch)
treeddd5f6ebbcfc309b563d886a0942f7ee573497ee
parentb394745df2d9d4c30bf1bcc55773bec6f3bc7c67 (diff)
parent6d004d6cc73920299adf4cfe25010b348fc94395 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Conflicts: net/ipv4/ip_vti.c Steffen Klassert says: ==================== pull request (net): ipsec 2014-05-15 This pull request has a merge conflict in net/ipv4/ip_vti.c between commit 8d89dcdf80d8 ("vti: don't allow to add the same tunnel twice") and commit a32452366b72 ("vti4:Don't count header length twice"). It can be solved like it is done in linux-next. 1) Fix a ipv6 xfrm output crash when a packet is rerouted by netfilter to not use IPsec. 2) vti4 counts some header lengths twice leading to an incorrect device mtu. Fix this by counting these headers only once. 3) We don't catch the case if an unsupported protocol is submitted to the xfrm protocol handlers, this can lead to NULL pointer dereferences. Fix this by adding the appropriate checks. 4) vti6 may unregister pernet ops twice on init errors. Fix this by removing one of the calls to do it only once. From Mathias Krause. 5) Set the vti tunnel mark before doing a lookup in the error handlers. Otherwise we don't find the correct xfrm state. ==================== The conflict in ip_vti.c was simple, 'net' had a commit removing a line from vti_tunnel_init() and this tree being merged had a commit adding a line to the same location. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/ip_vti.c5
-rw-r--r--net/ipv4/xfrm4_output.c32
-rw-r--r--net/ipv4/xfrm4_protocol.c19
-rw-r--r--net/ipv6/ip6_vti.c8
-rw-r--r--net/ipv6/xfrm6_output.c22
-rw-r--r--net/ipv6/xfrm6_protocol.c11
6 files changed, 66 insertions, 31 deletions
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index afcee51b90ed..13ef00f1e17b 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -239,6 +239,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
239static int vti4_err(struct sk_buff *skb, u32 info) 239static int vti4_err(struct sk_buff *skb, u32 info)
240{ 240{
241 __be32 spi; 241 __be32 spi;
242 __u32 mark;
242 struct xfrm_state *x; 243 struct xfrm_state *x;
243 struct ip_tunnel *tunnel; 244 struct ip_tunnel *tunnel;
244 struct ip_esp_hdr *esph; 245 struct ip_esp_hdr *esph;
@@ -254,6 +255,8 @@ static int vti4_err(struct sk_buff *skb, u32 info)
254 if (!tunnel) 255 if (!tunnel)
255 return -1; 256 return -1;
256 257
258 mark = be32_to_cpu(tunnel->parms.o_key);
259
257 switch (protocol) { 260 switch (protocol) {
258 case IPPROTO_ESP: 261 case IPPROTO_ESP:
259 esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); 262 esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
@@ -281,7 +284,7 @@ static int vti4_err(struct sk_buff *skb, u32 info)
281 return 0; 284 return 0;
282 } 285 }
283 286
284 x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, 287 x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
285 spi, protocol, AF_INET); 288 spi, protocol, AF_INET);
286 if (!x) 289 if (!x)
287 return 0; 290 return 0;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 40e701f2e1e0..186a8ecf92fa 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
62 if (err) 62 if (err)
63 return err; 63 return err;
64 64
65 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 65 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
66 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
67
68 skb->protocol = htons(ETH_P_IP);
69 66
70 return x->outer_mode->output2(x, skb); 67 return x->outer_mode->output2(x, skb);
71} 68}
@@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
73 70
74int xfrm4_output_finish(struct sk_buff *skb) 71int xfrm4_output_finish(struct sk_buff *skb)
75{ 72{
73 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
74 skb->protocol = htons(ETH_P_IP);
75
76#ifdef CONFIG_NETFILTER
77 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
78#endif
79
80 return xfrm_output(skb);
81}
82
83static int __xfrm4_output(struct sk_buff *skb)
84{
85 struct xfrm_state *x = skb_dst(skb)->xfrm;
86
76#ifdef CONFIG_NETFILTER 87#ifdef CONFIG_NETFILTER
77 if (!skb_dst(skb)->xfrm) { 88 if (!x) {
78 IPCB(skb)->flags |= IPSKB_REROUTED; 89 IPCB(skb)->flags |= IPSKB_REROUTED;
79 return dst_output(skb); 90 return dst_output(skb);
80 } 91 }
81
82 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
83#endif 92#endif
84 93
85 skb->protocol = htons(ETH_P_IP); 94 return x->outer_mode->afinfo->output_finish(skb);
86 return xfrm_output(skb);
87} 95}
88 96
89int xfrm4_output(struct sock *sk, struct sk_buff *skb) 97int xfrm4_output(struct sock *sk, struct sk_buff *skb)
90{ 98{
91 struct dst_entry *dst = skb_dst(skb);
92 struct xfrm_state *x = dst->xfrm;
93
94 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, 99 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
95 NULL, dst->dev, 100 NULL, skb_dst(skb)->dev, __xfrm4_output,
96 x->outer_mode->afinfo->output_finish,
97 !(IPCB(skb)->flags & IPSKB_REROUTED)); 101 !(IPCB(skb)->flags & IPSKB_REROUTED));
98} 102}
99 103
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c
index 7f7b243e8139..a2ce0101eaac 100644
--- a/net/ipv4/xfrm4_protocol.c
+++ b/net/ipv4/xfrm4_protocol.c
@@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{ 50{
51 int ret; 51 int ret;
52 struct xfrm4_protocol *handler; 52 struct xfrm4_protocol *handler;
53 struct xfrm4_protocol __rcu **head = proto_handlers(protocol);
53 54
54 for_each_protocol_rcu(*proto_handlers(protocol), handler) 55 if (!head)
56 return 0;
57
58 for_each_protocol_rcu(*head, handler)
55 if ((ret = handler->cb_handler(skb, err)) <= 0) 59 if ((ret = handler->cb_handler(skb, err)) <= 0)
56 return ret; 60 return ret;
57 61
@@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
64{ 68{
65 int ret; 69 int ret;
66 struct xfrm4_protocol *handler; 70 struct xfrm4_protocol *handler;
71 struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr);
67 72
68 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; 73 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
69 XFRM_SPI_SKB_CB(skb)->family = AF_INET; 74 XFRM_SPI_SKB_CB(skb)->family = AF_INET;
70 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); 75 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
71 76
72 for_each_protocol_rcu(*proto_handlers(nexthdr), handler) 77 if (!head)
78 goto out;
79
80 for_each_protocol_rcu(*head, handler)
73 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) 81 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
74 return ret; 82 return ret;
75 83
84out:
76 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 85 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
77 86
78 kfree_skb(skb); 87 kfree_skb(skb);
@@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler,
208 int ret = -EEXIST; 217 int ret = -EEXIST;
209 int priority = handler->priority; 218 int priority = handler->priority;
210 219
220 if (!proto_handlers(protocol) || !netproto(protocol))
221 return -EINVAL;
222
211 mutex_lock(&xfrm4_protocol_mutex); 223 mutex_lock(&xfrm4_protocol_mutex);
212 224
213 if (!rcu_dereference_protected(*proto_handlers(protocol), 225 if (!rcu_dereference_protected(*proto_handlers(protocol),
@@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
250 struct xfrm4_protocol *t; 262 struct xfrm4_protocol *t;
251 int ret = -ENOENT; 263 int ret = -ENOENT;
252 264
265 if (!proto_handlers(protocol) || !netproto(protocol))
266 return -EINVAL;
267
253 mutex_lock(&xfrm4_protocol_mutex); 268 mutex_lock(&xfrm4_protocol_mutex);
254 269
255 for (pprev = proto_handlers(protocol); 270 for (pprev = proto_handlers(protocol);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index b7c0f827140b..6cc9f9371cc5 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -511,6 +511,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
511 u8 type, u8 code, int offset, __be32 info) 511 u8 type, u8 code, int offset, __be32 info)
512{ 512{
513 __be32 spi; 513 __be32 spi;
514 __u32 mark;
514 struct xfrm_state *x; 515 struct xfrm_state *x;
515 struct ip6_tnl *t; 516 struct ip6_tnl *t;
516 struct ip_esp_hdr *esph; 517 struct ip_esp_hdr *esph;
@@ -524,6 +525,8 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
524 if (!t) 525 if (!t)
525 return -1; 526 return -1;
526 527
528 mark = be32_to_cpu(t->parms.o_key);
529
527 switch (protocol) { 530 switch (protocol) {
528 case IPPROTO_ESP: 531 case IPPROTO_ESP:
529 esph = (struct ip_esp_hdr *)(skb->data + offset); 532 esph = (struct ip_esp_hdr *)(skb->data + offset);
@@ -545,7 +548,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
545 type != NDISC_REDIRECT) 548 type != NDISC_REDIRECT)
546 return 0; 549 return 0;
547 550
548 x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, 551 x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
549 spi, protocol, AF_INET6); 552 spi, protocol, AF_INET6);
550 if (!x) 553 if (!x)
551 return 0; 554 return 0;
@@ -1097,7 +1100,6 @@ static int __init vti6_tunnel_init(void)
1097 1100
1098 err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); 1101 err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP);
1099 if (err < 0) { 1102 if (err < 0) {
1100 unregister_pernet_device(&vti6_net_ops);
1101 pr_err("%s: can't register vti6 protocol\n", __func__); 1103 pr_err("%s: can't register vti6 protocol\n", __func__);
1102 1104
1103 goto out; 1105 goto out;
@@ -1106,7 +1108,6 @@ static int __init vti6_tunnel_init(void)
1106 err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); 1108 err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH);
1107 if (err < 0) { 1109 if (err < 0) {
1108 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); 1110 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
1109 unregister_pernet_device(&vti6_net_ops);
1110 pr_err("%s: can't register vti6 protocol\n", __func__); 1111 pr_err("%s: can't register vti6 protocol\n", __func__);
1111 1112
1112 goto out; 1113 goto out;
@@ -1116,7 +1117,6 @@ static int __init vti6_tunnel_init(void)
1116 if (err < 0) { 1117 if (err < 0) {
1117 xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); 1118 xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
1118 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); 1119 xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
1119 unregister_pernet_device(&vti6_net_ops);
1120 pr_err("%s: can't register vti6 protocol\n", __func__); 1120 pr_err("%s: can't register vti6 protocol\n", __func__);
1121 1121
1122 goto out; 1122 goto out;
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 19ef329bdbf8..b930d080c66f 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
114 if (err) 114 if (err)
115 return err; 115 return err;
116 116
117 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
118#ifdef CONFIG_NETFILTER
119 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
120#endif
121
122 skb->protocol = htons(ETH_P_IPV6);
123 skb->local_df = 1; 117 skb->local_df = 1;
124 118
125 return x->outer_mode->output2(x, skb); 119 return x->outer_mode->output2(x, skb);
@@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
128 122
129int xfrm6_output_finish(struct sk_buff *skb) 123int xfrm6_output_finish(struct sk_buff *skb)
130{ 124{
125 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
126 skb->protocol = htons(ETH_P_IPV6);
127
131#ifdef CONFIG_NETFILTER 128#ifdef CONFIG_NETFILTER
132 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 129 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
133#endif 130#endif
134 131
135 skb->protocol = htons(ETH_P_IPV6);
136 return xfrm_output(skb); 132 return xfrm_output(skb);
137} 133}
138 134
@@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff *skb)
142 struct xfrm_state *x = dst->xfrm; 138 struct xfrm_state *x = dst->xfrm;
143 int mtu; 139 int mtu;
144 140
141#ifdef CONFIG_NETFILTER
142 if (!x) {
143 IP6CB(skb)->flags |= IP6SKB_REROUTED;
144 return dst_output(skb);
145 }
146#endif
147
145 if (skb->protocol == htons(ETH_P_IPV6)) 148 if (skb->protocol == htons(ETH_P_IPV6))
146 mtu = ip6_skb_dst_mtu(skb); 149 mtu = ip6_skb_dst_mtu(skb);
147 else 150 else
@@ -165,6 +168,7 @@ static int __xfrm6_output(struct sk_buff *skb)
165 168
166int xfrm6_output(struct sock *sk, struct sk_buff *skb) 169int xfrm6_output(struct sock *sk, struct sk_buff *skb)
167{ 170{
168 return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, 171 return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb,
169 skb_dst(skb)->dev, __xfrm6_output); 172 NULL, skb_dst(skb)->dev, __xfrm6_output,
173 !(IP6CB(skb)->flags & IP6SKB_REROUTED));
170} 174}
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c
index 6ab989c486f7..54d13f8dbbae 100644
--- a/net/ipv6/xfrm6_protocol.c
+++ b/net/ipv6/xfrm6_protocol.c
@@ -50,6 +50,10 @@ int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{ 50{
51 int ret; 51 int ret;
52 struct xfrm6_protocol *handler; 52 struct xfrm6_protocol *handler;
53 struct xfrm6_protocol __rcu **head = proto_handlers(protocol);
54
55 if (!head)
56 return 0;
53 57
54 for_each_protocol_rcu(*proto_handlers(protocol), handler) 58 for_each_protocol_rcu(*proto_handlers(protocol), handler)
55 if ((ret = handler->cb_handler(skb, err)) <= 0) 59 if ((ret = handler->cb_handler(skb, err)) <= 0)
@@ -184,10 +188,12 @@ int xfrm6_protocol_register(struct xfrm6_protocol *handler,
184 struct xfrm6_protocol __rcu **pprev; 188 struct xfrm6_protocol __rcu **pprev;
185 struct xfrm6_protocol *t; 189 struct xfrm6_protocol *t;
186 bool add_netproto = false; 190 bool add_netproto = false;
187
188 int ret = -EEXIST; 191 int ret = -EEXIST;
189 int priority = handler->priority; 192 int priority = handler->priority;
190 193
194 if (!proto_handlers(protocol) || !netproto(protocol))
195 return -EINVAL;
196
191 mutex_lock(&xfrm6_protocol_mutex); 197 mutex_lock(&xfrm6_protocol_mutex);
192 198
193 if (!rcu_dereference_protected(*proto_handlers(protocol), 199 if (!rcu_dereference_protected(*proto_handlers(protocol),
@@ -230,6 +236,9 @@ int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
230 struct xfrm6_protocol *t; 236 struct xfrm6_protocol *t;
231 int ret = -ENOENT; 237 int ret = -ENOENT;
232 238
239 if (!proto_handlers(protocol) || !netproto(protocol))
240 return -EINVAL;
241
233 mutex_lock(&xfrm6_protocol_mutex); 242 mutex_lock(&xfrm6_protocol_mutex);
234 243
235 for (pprev = proto_handlers(protocol); 244 for (pprev = proto_handlers(protocol);