Skip to content

Commit 7752f72

Browse files
committed
Merge branch 'l2tp-fixes'
Guillaume Nault says: ==================== l2tp: fixes for l2tp_ip and l2tp_ip6 socket handling This series addresses problems found while working on commit 32c2311 ("l2tp: fix racy SOCK_ZAPPED flag check in l2tp_ip{,6}_bind()"). The first three patches fix races in socket's connect, recv and bind operations. The last two ones fix scenarios where l2tp fails to correctly lookup its userspace sockets. Apart from the last patch, which is l2tp_ip6 specific, every patch fixes the same problem in the L2TP IPv4 and IPv6 code. All problems fixed by this series exist since the creation of the l2tp_ip and l2tp_ip6 modules. Changes since v1: * Patch #3: fix possible uninitialised use of 'ret' in l2tp_ip_bind(). ==================== Acked-by: James Chapman <[email protected]>
2 parents bb83d62 + 31e2f21 commit 7752f72

File tree

4 files changed

+81
-67
lines changed

4 files changed

+81
-67
lines changed

include/net/ipv6.h

+2
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,8 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
970970
int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
971971
char __user *optval, int __user *optlen);
972972

973+
int __ip6_datagram_connect(struct sock *sk, struct sockaddr *addr,
974+
int addr_len);
973975
int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
974976
int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *addr,
975977
int addr_len);

net/ipv6/datagram.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ void ip6_datagram_release_cb(struct sock *sk)
139139
}
140140
EXPORT_SYMBOL_GPL(ip6_datagram_release_cb);
141141

142-
static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
142+
int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
143+
int addr_len)
143144
{
144145
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
145146
struct inet_sock *inet = inet_sk(sk);
@@ -252,6 +253,7 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a
252253
out:
253254
return err;
254255
}
256+
EXPORT_SYMBOL_GPL(__ip6_datagram_connect);
255257

256258
int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
257259
{

net/l2tp/l2tp_ip.c

+34-29
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ static struct sock *__l2tp_ip_bind_lookup(struct net *net, __be32 laddr, int dif
6161
if ((l2tp->conn_id == tunnel_id) &&
6262
net_eq(sock_net(sk), net) &&
6363
!(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
64-
!(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
64+
(!sk->sk_bound_dev_if || !dif ||
65+
sk->sk_bound_dev_if == dif))
6566
goto found;
6667
}
6768

@@ -182,15 +183,17 @@ static int l2tp_ip_recv(struct sk_buff *skb)
182183
struct iphdr *iph = (struct iphdr *) skb_network_header(skb);
183184

184185
read_lock_bh(&l2tp_ip_lock);
185-
sk = __l2tp_ip_bind_lookup(net, iph->daddr, 0, tunnel_id);
186+
sk = __l2tp_ip_bind_lookup(net, iph->daddr, inet_iif(skb),
187+
tunnel_id);
188+
if (!sk) {
189+
read_unlock_bh(&l2tp_ip_lock);
190+
goto discard;
191+
}
192+
193+
sock_hold(sk);
186194
read_unlock_bh(&l2tp_ip_lock);
187195
}
188196

189-
if (sk == NULL)
190-
goto discard;
191-
192-
sock_hold(sk);
193-
194197
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
195198
goto discard_put;
196199

@@ -256,15 +259,9 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
256259
if (addr->l2tp_family != AF_INET)
257260
return -EINVAL;
258261

259-
ret = -EADDRINUSE;
260-
read_lock_bh(&l2tp_ip_lock);
261-
if (__l2tp_ip_bind_lookup(net, addr->l2tp_addr.s_addr,
262-
sk->sk_bound_dev_if, addr->l2tp_conn_id))
263-
goto out_in_use;
264-
265-
read_unlock_bh(&l2tp_ip_lock);
266-
267262
lock_sock(sk);
263+
264+
ret = -EINVAL;
268265
if (!sock_flag(sk, SOCK_ZAPPED))
269266
goto out;
270267

@@ -281,25 +278,28 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
281278
inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr;
282279
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
283280
inet->inet_saddr = 0; /* Use device */
284-
sk_dst_reset(sk);
285281

282+
write_lock_bh(&l2tp_ip_lock);
283+
if (__l2tp_ip_bind_lookup(net, addr->l2tp_addr.s_addr,
284+
sk->sk_bound_dev_if, addr->l2tp_conn_id)) {
285+
write_unlock_bh(&l2tp_ip_lock);
286+
ret = -EADDRINUSE;
287+
goto out;
288+
}
289+
290+
sk_dst_reset(sk);
286291
l2tp_ip_sk(sk)->conn_id = addr->l2tp_conn_id;
287292

288-
write_lock_bh(&l2tp_ip_lock);
289293
sk_add_bind_node(sk, &l2tp_ip_bind_table);
290294
sk_del_node_init(sk);
291295
write_unlock_bh(&l2tp_ip_lock);
296+
292297
ret = 0;
293298
sock_reset_flag(sk, SOCK_ZAPPED);
294299

295300
out:
296301
release_sock(sk);
297302

298-
return ret;
299-
300-
out_in_use:
301-
read_unlock_bh(&l2tp_ip_lock);
302-
303303
return ret;
304304
}
305305

@@ -308,29 +308,34 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
308308
struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr;
309309
int rc;
310310

311-
if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
312-
return -EINVAL;
313-
314311
if (addr_len < sizeof(*lsa))
315312
return -EINVAL;
316313

317314
if (ipv4_is_multicast(lsa->l2tp_addr.s_addr))
318315
return -EINVAL;
319316

320-
rc = ip4_datagram_connect(sk, uaddr, addr_len);
321-
if (rc < 0)
322-
return rc;
323-
324317
lock_sock(sk);
325318

319+
/* Must bind first - autobinding does not work */
320+
if (sock_flag(sk, SOCK_ZAPPED)) {
321+
rc = -EINVAL;
322+
goto out_sk;
323+
}
324+
325+
rc = __ip4_datagram_connect(sk, uaddr, addr_len);
326+
if (rc < 0)
327+
goto out_sk;
328+
326329
l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
327330

328331
write_lock_bh(&l2tp_ip_lock);
329332
hlist_del_init(&sk->sk_bind_node);
330333
sk_add_bind_node(sk, &l2tp_ip_bind_table);
331334
write_unlock_bh(&l2tp_ip_lock);
332335

336+
out_sk:
333337
release_sock(sk);
338+
334339
return rc;
335340
}
336341

net/l2tp/l2tp_ip6.c

+42-37
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ static struct sock *__l2tp_ip6_bind_lookup(struct net *net,
7272

7373
if ((l2tp->conn_id == tunnel_id) &&
7474
net_eq(sock_net(sk), net) &&
75-
!(addr && ipv6_addr_equal(addr, laddr)) &&
76-
!(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
75+
(!addr || ipv6_addr_equal(addr, laddr)) &&
76+
(!sk->sk_bound_dev_if || !dif ||
77+
sk->sk_bound_dev_if == dif))
7778
goto found;
7879
}
7980

@@ -196,16 +197,17 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
196197
struct ipv6hdr *iph = ipv6_hdr(skb);
197198

198199
read_lock_bh(&l2tp_ip6_lock);
199-
sk = __l2tp_ip6_bind_lookup(net, &iph->daddr,
200-
0, tunnel_id);
200+
sk = __l2tp_ip6_bind_lookup(net, &iph->daddr, inet6_iif(skb),
201+
tunnel_id);
202+
if (!sk) {
203+
read_unlock_bh(&l2tp_ip6_lock);
204+
goto discard;
205+
}
206+
207+
sock_hold(sk);
201208
read_unlock_bh(&l2tp_ip6_lock);
202209
}
203210

204-
if (sk == NULL)
205-
goto discard;
206-
207-
sock_hold(sk);
208-
209211
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
210212
goto discard_put;
211213

@@ -266,6 +268,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
266268
struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr;
267269
struct net *net = sock_net(sk);
268270
__be32 v4addr = 0;
271+
int bound_dev_if;
269272
int addr_type;
270273
int err;
271274

@@ -284,13 +287,6 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
284287
if (addr_type & IPV6_ADDR_MULTICAST)
285288
return -EADDRNOTAVAIL;
286289

287-
err = -EADDRINUSE;
288-
read_lock_bh(&l2tp_ip6_lock);
289-
if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr,
290-
sk->sk_bound_dev_if, addr->l2tp_conn_id))
291-
goto out_in_use;
292-
read_unlock_bh(&l2tp_ip6_lock);
293-
294290
lock_sock(sk);
295291

296292
err = -EINVAL;
@@ -300,28 +296,25 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
300296
if (sk->sk_state != TCP_CLOSE)
301297
goto out_unlock;
302298

299+
bound_dev_if = sk->sk_bound_dev_if;
300+
303301
/* Check if the address belongs to the host. */
304302
rcu_read_lock();
305303
if (addr_type != IPV6_ADDR_ANY) {
306304
struct net_device *dev = NULL;
307305

308306
if (addr_type & IPV6_ADDR_LINKLOCAL) {
309-
if (addr_len >= sizeof(struct sockaddr_in6) &&
310-
addr->l2tp_scope_id) {
311-
/* Override any existing binding, if another
312-
* one is supplied by user.
313-
*/
314-
sk->sk_bound_dev_if = addr->l2tp_scope_id;
315-
}
307+
if (addr->l2tp_scope_id)
308+
bound_dev_if = addr->l2tp_scope_id;
316309

317310
/* Binding to link-local address requires an
318-
interface */
319-
if (!sk->sk_bound_dev_if)
311+
* interface.
312+
*/
313+
if (!bound_dev_if)
320314
goto out_unlock_rcu;
321315

322316
err = -ENODEV;
323-
dev = dev_get_by_index_rcu(sock_net(sk),
324-
sk->sk_bound_dev_if);
317+
dev = dev_get_by_index_rcu(sock_net(sk), bound_dev_if);
325318
if (!dev)
326319
goto out_unlock_rcu;
327320
}
@@ -336,13 +329,22 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
336329
}
337330
rcu_read_unlock();
338331

339-
inet->inet_rcv_saddr = inet->inet_saddr = v4addr;
332+
write_lock_bh(&l2tp_ip6_lock);
333+
if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr, bound_dev_if,
334+
addr->l2tp_conn_id)) {
335+
write_unlock_bh(&l2tp_ip6_lock);
336+
err = -EADDRINUSE;
337+
goto out_unlock;
338+
}
339+
340+
inet->inet_saddr = v4addr;
341+
inet->inet_rcv_saddr = v4addr;
342+
sk->sk_bound_dev_if = bound_dev_if;
340343
sk->sk_v6_rcv_saddr = addr->l2tp_addr;
341344
np->saddr = addr->l2tp_addr;
342345

343346
l2tp_ip6_sk(sk)->conn_id = addr->l2tp_conn_id;
344347

345-
write_lock_bh(&l2tp_ip6_lock);
346348
sk_add_bind_node(sk, &l2tp_ip6_bind_table);
347349
sk_del_node_init(sk);
348350
write_unlock_bh(&l2tp_ip6_lock);
@@ -355,10 +357,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
355357
rcu_read_unlock();
356358
out_unlock:
357359
release_sock(sk);
358-
return err;
359360

360-
out_in_use:
361-
read_unlock_bh(&l2tp_ip6_lock);
362361
return err;
363362
}
364363

@@ -371,9 +370,6 @@ static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
371370
int addr_type;
372371
int rc;
373372

374-
if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
375-
return -EINVAL;
376-
377373
if (addr_len < sizeof(*lsa))
378374
return -EINVAL;
379375

@@ -390,17 +386,26 @@ static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
390386
return -EINVAL;
391387
}
392388

393-
rc = ip6_datagram_connect(sk, uaddr, addr_len);
394-
395389
lock_sock(sk);
396390

391+
/* Must bind first - autobinding does not work */
392+
if (sock_flag(sk, SOCK_ZAPPED)) {
393+
rc = -EINVAL;
394+
goto out_sk;
395+
}
396+
397+
rc = __ip6_datagram_connect(sk, uaddr, addr_len);
398+
if (rc < 0)
399+
goto out_sk;
400+
397401
l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
398402

399403
write_lock_bh(&l2tp_ip6_lock);
400404
hlist_del_init(&sk->sk_bind_node);
401405
sk_add_bind_node(sk, &l2tp_ip6_bind_table);
402406
write_unlock_bh(&l2tp_ip6_lock);
403407

408+
out_sk:
404409
release_sock(sk);
405410

406411
return rc;

0 commit comments

Comments
 (0)