Skip to content

Commit b9dee56

Browse files
edumazetgregkh
authored andcommitted
l2tp: do not use udp_ioctl()
[ Upstream commit 72fb96e7bdbbdd4421b0726992496531060f3636 ] udp_ioctl(), as its name suggests, is used by UDP protocols, but is also used by L2TP :( L2TP should use its own handler, because it really does not look the same. SIOCINQ for instance should not assume UDP checksum or headers. Thanks to Andrey and syzkaller team for providing the report and a nice reproducer. While crashes only happen on recent kernels (after commit 7c13f97ffde6 ("udp: do fwd memory scheduling on dequeue")), this probably needs to be backported to older kernels. Fixes: 7c13f97ffde6 ("udp: do fwd memory scheduling on dequeue") Fixes: 8558467 ("udp: Fix udp_poll() and ioctl()") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Andrey Konovalov <andreyknvl@google.com> Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent afb4feb commit b9dee56

3 files changed

Lines changed: 28 additions & 2 deletions

File tree

net/l2tp/l2tp_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb,
273273
int l2tp_nl_register_ops(enum l2tp_pwtype pw_type,
274274
const struct l2tp_nl_cmd_ops *ops);
275275
void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
276+
int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
276277

277278
/* Session reference counts. Incremented when code obtains a reference
278279
* to a session.

net/l2tp/l2tp_ip.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1313

14+
#include <asm/ioctls.h>
1415
#include <linux/icmp.h>
1516
#include <linux/module.h>
1617
#include <linux/skbuff.h>
@@ -555,6 +556,30 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg,
555556
return err ? err : copied;
556557
}
557558

559+
int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
560+
{
561+
struct sk_buff *skb;
562+
int amount;
563+
564+
switch (cmd) {
565+
case SIOCOUTQ:
566+
amount = sk_wmem_alloc_get(sk);
567+
break;
568+
case SIOCINQ:
569+
spin_lock_bh(&sk->sk_receive_queue.lock);
570+
skb = skb_peek(&sk->sk_receive_queue);
571+
amount = skb ? skb->len : 0;
572+
spin_unlock_bh(&sk->sk_receive_queue.lock);
573+
break;
574+
575+
default:
576+
return -ENOIOCTLCMD;
577+
}
578+
579+
return put_user(amount, (int __user *)arg);
580+
}
581+
EXPORT_SYMBOL(l2tp_ioctl);
582+
558583
static struct proto l2tp_ip_prot = {
559584
.name = "L2TP/IP",
560585
.owner = THIS_MODULE,
@@ -563,7 +588,7 @@ static struct proto l2tp_ip_prot = {
563588
.bind = l2tp_ip_bind,
564589
.connect = l2tp_ip_connect,
565590
.disconnect = l2tp_ip_disconnect,
566-
.ioctl = udp_ioctl,
591+
.ioctl = l2tp_ioctl,
567592
.destroy = l2tp_ip_destroy_sock,
568593
.setsockopt = ip_setsockopt,
569594
.getsockopt = ip_getsockopt,

net/l2tp/l2tp_ip6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ static struct proto l2tp_ip6_prot = {
714714
.bind = l2tp_ip6_bind,
715715
.connect = l2tp_ip6_connect,
716716
.disconnect = l2tp_ip6_disconnect,
717-
.ioctl = udp_ioctl,
717+
.ioctl = l2tp_ioctl,
718718
.destroy = l2tp_ip6_destroy_sock,
719719
.setsockopt = ipv6_setsockopt,
720720
.getsockopt = ipv6_getsockopt,

0 commit comments

Comments
 (0)