Message ID | 1486664113.7793.111.camel@edumazet-glaptop3.roam.corp.google.com |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
On Thu, 2017-02-09 at 10:15 -0800, Eric Dumazet wrote: > From: Eric Dumazet <edumazet@google.com> > > 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: 85584672012e ("udp: Fix udp_poll() and ioctl()") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: Andrey Konovalov <andreyknvl@google.com> > Cc: Paolo Abeni <pabeni@redhat.com> > --- > net/l2tp/l2tp_core.h | 1 + > net/l2tp/l2tp_ip.c | 26 +++++++++++++++++++++++++- > net/l2tp/l2tp_ip6.c | 2 +- > 3 files changed, 27 insertions(+), 2 deletions(-) > > diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h > index 8f560f7140a05694c13904d9b171ba67d9d11292..aebf281d09eeb31c531eb624bd2ddd78cab8da9b 100644 > --- a/net/l2tp/l2tp_core.h > +++ b/net/l2tp/l2tp_core.h > @@ -263,6 +263,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, > int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, > const struct l2tp_nl_cmd_ops *ops); > void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); > +int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg); > > /* Session reference counts. Incremented when code obtains a reference > * to a session. > diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c > index 3d73278b86ca34bfbd774dc8f52e490169445e1b..d4e5d16d97d4b612f8a76557516288f4a011448a 100644 > --- a/net/l2tp/l2tp_ip.c > +++ b/net/l2tp/l2tp_ip.c > @@ -11,6 +11,7 @@ > > #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > > +#include <asm/ioctls.h> > #include <linux/icmp.h> > #include <linux/module.h> > #include <linux/skbuff.h> > @@ -553,6 +554,29 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg, > return err ? err : copied; > } > > +int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg) > +{ > + struct sk_buff *skb; > + int amount; > + > + switch (cmd) { > + case SIOCOUTQ: > + amount = sk_wmem_alloc_get(sk); > + break; > + case SIOCINQ: > + spin_lock_bh(&sk->sk_receive_queue.lock); > + skb = skb_peek(&sk->sk_receive_queue); > + amount = skb ? skb->len : 0; > + spin_unlock_bh(&sk->sk_receive_queue.lock); > + break; > + > + default: > + return -ENOIOCTLCMD; > + } > + > + return put_user(amount, (int __user *)arg); > +} > + > static struct proto l2tp_ip_prot = { > .name = "L2TP/IP", > .owner = THIS_MODULE, > @@ -561,7 +585,7 @@ static struct proto l2tp_ip_prot = { > .bind = l2tp_ip_bind, > .connect = l2tp_ip_connect, > .disconnect = l2tp_ip_disconnect, > - .ioctl = udp_ioctl, > + .ioctl = l2tp_ioctl, > .destroy = l2tp_ip_destroy_sock, > .setsockopt = ip_setsockopt, > .getsockopt = ip_getsockopt, > diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c > index 331ccf5a7bad80e011997e071489d7775b0c68c6..f47c45250f86c9189e0a6bbfd92b21cbe2069406 100644 > --- a/net/l2tp/l2tp_ip6.c > +++ b/net/l2tp/l2tp_ip6.c > @@ -722,7 +722,7 @@ static struct proto l2tp_ip6_prot = { > .bind = l2tp_ip6_bind, > .connect = l2tp_ip6_connect, > .disconnect = l2tp_ip6_disconnect, > - .ioctl = udp_ioctl, > + .ioctl = l2tp_ioctl, > .destroy = l2tp_ip6_destroy_sock, > .setsockopt = ipv6_setsockopt, > .getsockopt = ipv6_getsockopt, > > Thank you for taking care of this! LGTM. Acked-by: Paolo Abeni <pabeni@redhat.com>
Hi Eric,
[auto build test ERROR on net/master]
url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/l2tp-do-not-use-udp_ioctl/20170210-042926
config: x86_64-rhel (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
>> ERROR: "l2tp_ioctl" [net/l2tp/l2tp_ip6.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 8f560f7140a05694c13904d9b171ba67d9d11292..aebf281d09eeb31c531eb624bd2ddd78cab8da9b 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -263,6 +263,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops); void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); +int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg); /* Session reference counts. Incremented when code obtains a reference * to a session. diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 3d73278b86ca34bfbd774dc8f52e490169445e1b..d4e5d16d97d4b612f8a76557516288f4a011448a 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <asm/ioctls.h> #include <linux/icmp.h> #include <linux/module.h> #include <linux/skbuff.h> @@ -553,6 +554,29 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg, return err ? err : copied; } +int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg) +{ + struct sk_buff *skb; + int amount; + + switch (cmd) { + case SIOCOUTQ: + amount = sk_wmem_alloc_get(sk); + break; + case SIOCINQ: + spin_lock_bh(&sk->sk_receive_queue.lock); + skb = skb_peek(&sk->sk_receive_queue); + amount = skb ? skb->len : 0; + spin_unlock_bh(&sk->sk_receive_queue.lock); + break; + + default: + return -ENOIOCTLCMD; + } + + return put_user(amount, (int __user *)arg); +} + static struct proto l2tp_ip_prot = { .name = "L2TP/IP", .owner = THIS_MODULE, @@ -561,7 +585,7 @@ static struct proto l2tp_ip_prot = { .bind = l2tp_ip_bind, .connect = l2tp_ip_connect, .disconnect = l2tp_ip_disconnect, - .ioctl = udp_ioctl, + .ioctl = l2tp_ioctl, .destroy = l2tp_ip_destroy_sock, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 331ccf5a7bad80e011997e071489d7775b0c68c6..f47c45250f86c9189e0a6bbfd92b21cbe2069406 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -722,7 +722,7 @@ static struct proto l2tp_ip6_prot = { .bind = l2tp_ip6_bind, .connect = l2tp_ip6_connect, .disconnect = l2tp_ip6_disconnect, - .ioctl = udp_ioctl, + .ioctl = l2tp_ioctl, .destroy = l2tp_ip6_destroy_sock, .setsockopt = ipv6_setsockopt, .getsockopt = ipv6_getsockopt,