]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Apr 2018 14:00:12 +0000 (16:00 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 14 Apr 2018 14:00:12 +0000 (16:00 +0200)
added patches:
cdc_ether-flag-the-cinterion-ahs8-modem-by-gemalto-as-wwan.patch
ip_gre-clear-feature-flags-when-incompatible-o_flags-are-set.patch
l2tp-fix-race-in-duplicate-tunnel-detection.patch
l2tp-fix-races-in-tunnel-creation.patch
lan78xx-correctly-indicate-invalid-otp.patch
rds-mp-rds-may-use-an-invalid-c_path.patch
slip-check-if-rstate-is-initialized-before-uncompressing.patch
vhost-fix-vhost_copy_to_user.patch
vhost-fix-vhost_vq_access_ok-log-check.patch

queue-4.15/cdc_ether-flag-the-cinterion-ahs8-modem-by-gemalto-as-wwan.patch [new file with mode: 0644]
queue-4.15/ip_gre-clear-feature-flags-when-incompatible-o_flags-are-set.patch [new file with mode: 0644]
queue-4.15/l2tp-fix-race-in-duplicate-tunnel-detection.patch [new file with mode: 0644]
queue-4.15/l2tp-fix-races-in-tunnel-creation.patch [new file with mode: 0644]
queue-4.15/lan78xx-correctly-indicate-invalid-otp.patch [new file with mode: 0644]
queue-4.15/rds-mp-rds-may-use-an-invalid-c_path.patch [new file with mode: 0644]
queue-4.15/series
queue-4.15/slip-check-if-rstate-is-initialized-before-uncompressing.patch [new file with mode: 0644]
queue-4.15/vhost-fix-vhost_copy_to_user.patch [new file with mode: 0644]
queue-4.15/vhost-fix-vhost_vq_access_ok-log-check.patch [new file with mode: 0644]

diff --git a/queue-4.15/cdc_ether-flag-the-cinterion-ahs8-modem-by-gemalto-as-wwan.patch b/queue-4.15/cdc_ether-flag-the-cinterion-ahs8-modem-by-gemalto-as-wwan.patch
new file mode 100644 (file)
index 0000000..5e550d5
--- /dev/null
@@ -0,0 +1,42 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Bassem Boubaker <bassem.boubaker@actia.fr>
+Date: Wed, 11 Apr 2018 13:15:53 +0200
+Subject: cdc_ether: flag the Cinterion AHS8 modem by gemalto as WWAN
+
+From: Bassem Boubaker <bassem.boubaker@actia.fr>
+
+
+[ Upstream commit 53765341ee821c0a0f1dec41adc89c9096ad694c ]
+
+The Cinterion AHS8 is a 3G device with one embedded WWAN interface
+using cdc_ether as a driver.
+
+The modem is controlled via AT commands through the exposed TTYs.
+
+AT+CGDCONT write command can be used to activate or deactivate a WWAN
+connection for a PDP context defined with the same command. UE
+supports one WWAN adapter.
+
+Signed-off-by: Bassem Boubaker <bassem.boubaker@actia.fr>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/cdc_ether.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/usb/cdc_ether.c
++++ b/drivers/net/usb/cdc_ether.c
+@@ -896,6 +896,12 @@ static const struct usb_device_id produc
+                                     USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long)&wwan_info,
+ }, {
++      /* Cinterion AHS3 modem by GEMALTO */
++      USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x0055, USB_CLASS_COMM,
++                                    USB_CDC_SUBCLASS_ETHERNET,
++                                    USB_CDC_PROTO_NONE),
++      .driver_info = (unsigned long)&wwan_info,
++}, {
+       USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
+                       USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long) &cdc_info,
diff --git a/queue-4.15/ip_gre-clear-feature-flags-when-incompatible-o_flags-are-set.patch b/queue-4.15/ip_gre-clear-feature-flags-when-incompatible-o_flags-are-set.patch
new file mode 100644 (file)
index 0000000..c8ae5a4
--- /dev/null
@@ -0,0 +1,50 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Sabrina Dubroca <sd@queasysnail.net>
+Date: Tue, 10 Apr 2018 12:57:18 +0200
+Subject: ip_gre: clear feature flags when incompatible o_flags are set
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+
+[ Upstream commit 1cc5954f44150bb70cac07c3cc5df7cf0dfb61ec ]
+
+Commit dd9d598c6657 ("ip_gre: add the support for i/o_flags update via
+netlink") added the ability to change o_flags, but missed that the
+GSO/LLTX features are disabled by default, and only enabled some gre
+features are unused. Thus we also need to disable the GSO/LLTX features
+on the device when the TUNNEL_SEQ or TUNNEL_CSUM flags are set.
+
+These two examples should result in the same features being set:
+
+    ip link add gre_none type gre local 192.168.0.10 remote 192.168.0.20 ttl 255 key 0
+
+    ip link set gre_none type gre seq
+    ip link add gre_seq type gre local 192.168.0.10 remote 192.168.0.20 ttl 255 key 1 seq
+
+Fixes: dd9d598c6657 ("ip_gre: add the support for i/o_flags update via netlink")
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Reviewed-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: William Tu <u9012063@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_gre.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -796,8 +796,14 @@ static void ipgre_link_update(struct net
+                   tunnel->encap.type == TUNNEL_ENCAP_NONE) {
+                       dev->features |= NETIF_F_GSO_SOFTWARE;
+                       dev->hw_features |= NETIF_F_GSO_SOFTWARE;
++              } else {
++                      dev->features &= ~NETIF_F_GSO_SOFTWARE;
++                      dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
+               }
+               dev->features |= NETIF_F_LLTX;
++      } else {
++              dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
++              dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE);
+       }
+ }
diff --git a/queue-4.15/l2tp-fix-race-in-duplicate-tunnel-detection.patch b/queue-4.15/l2tp-fix-race-in-duplicate-tunnel-detection.patch
new file mode 100644 (file)
index 0000000..5af76f3
--- /dev/null
@@ -0,0 +1,119 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Tue, 10 Apr 2018 21:01:13 +0200
+Subject: l2tp: fix race in duplicate tunnel detection
+
+From: Guillaume Nault <g.nault@alphalink.fr>
+
+
+[ Upstream commit f6cd651b056ffd3b4e8496afd44d4ed44bf69136 ]
+
+We can't use l2tp_tunnel_find() to prevent l2tp_nl_cmd_tunnel_create()
+from creating a duplicate tunnel. A tunnel can be concurrently
+registered after l2tp_tunnel_find() returns. Therefore, searching for
+duplicates must be done at registration time.
+
+Finally, remove l2tp_tunnel_find() entirely as it isn't use anywhere
+anymore.
+
+Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP")
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_core.c    |   35 ++++++++++++++---------------------
+ net/l2tp/l2tp_core.h    |    1 -
+ net/l2tp/l2tp_netlink.c |    6 ------
+ 3 files changed, 14 insertions(+), 28 deletions(-)
+
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -335,26 +335,6 @@ err_tlock:
+ }
+ EXPORT_SYMBOL_GPL(l2tp_session_register);
+-/* Lookup a tunnel by id
+- */
+-struct l2tp_tunnel *l2tp_tunnel_find(const struct net *net, u32 tunnel_id)
+-{
+-      struct l2tp_tunnel *tunnel;
+-      struct l2tp_net *pn = l2tp_pernet(net);
+-
+-      rcu_read_lock_bh();
+-      list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
+-              if (tunnel->tunnel_id == tunnel_id) {
+-                      rcu_read_unlock_bh();
+-                      return tunnel;
+-              }
+-      }
+-      rcu_read_unlock_bh();
+-
+-      return NULL;
+-}
+-EXPORT_SYMBOL_GPL(l2tp_tunnel_find);
+-
+ struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth)
+ {
+       struct l2tp_net *pn = l2tp_pernet(net);
+@@ -1510,6 +1490,7 @@ static int l2tp_validate_socket(const st
+ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
+                        struct l2tp_tunnel_cfg *cfg)
+ {
++      struct l2tp_tunnel *tunnel_walk;
+       struct l2tp_net *pn;
+       struct socket *sock;
+       struct sock *sk;
+@@ -1538,7 +1519,16 @@ int l2tp_tunnel_register(struct l2tp_tun
+       tunnel->l2tp_net = net;
+       pn = l2tp_pernet(net);
++
+       spin_lock_bh(&pn->l2tp_tunnel_list_lock);
++      list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) {
++              if (tunnel_walk->tunnel_id == tunnel->tunnel_id) {
++                      spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
++
++                      ret = -EEXIST;
++                      goto err_sock;
++              }
++      }
+       list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
+       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
+@@ -1567,7 +1557,10 @@ int l2tp_tunnel_register(struct l2tp_tun
+       return 0;
+ err_sock:
+-      sockfd_put(sock);
++      if (tunnel->fd < 0)
++              sock_release(sock);
++      else
++              sockfd_put(sock);
+ err:
+       return ret;
+ }
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -225,7 +225,6 @@ struct l2tp_session *l2tp_session_get(co
+ struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth);
+ struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
+                                               const char *ifname);
+-struct l2tp_tunnel *l2tp_tunnel_find(const struct net *net, u32 tunnel_id);
+ struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth);
+ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id,
+--- a/net/l2tp/l2tp_netlink.c
++++ b/net/l2tp/l2tp_netlink.c
+@@ -236,12 +236,6 @@ static int l2tp_nl_cmd_tunnel_create(str
+       if (info->attrs[L2TP_ATTR_DEBUG])
+               cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
+-      tunnel = l2tp_tunnel_find(net, tunnel_id);
+-      if (tunnel != NULL) {
+-              ret = -EEXIST;
+-              goto out;
+-      }
+-
+       ret = -EINVAL;
+       switch (cfg.encap) {
+       case L2TP_ENCAPTYPE_UDP:
diff --git a/queue-4.15/l2tp-fix-races-in-tunnel-creation.patch b/queue-4.15/l2tp-fix-races-in-tunnel-creation.patch
new file mode 100644 (file)
index 0000000..f5e8510
--- /dev/null
@@ -0,0 +1,336 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Guillaume Nault <g.nault@alphalink.fr>
+Date: Tue, 10 Apr 2018 21:01:12 +0200
+Subject: l2tp: fix races in tunnel creation
+
+From: Guillaume Nault <g.nault@alphalink.fr>
+
+
+[ Upstream commit 6b9f34239b00e6956a267abed2bc559ede556ad6 ]
+
+l2tp_tunnel_create() inserts the new tunnel into the namespace's tunnel
+list and sets the socket's ->sk_user_data field, before returning it to
+the caller. Therefore, there are two ways the tunnel can be accessed
+and freed, before the caller even had the opportunity to take a
+reference. In practice, syzbot could crash the module by closing the
+socket right after a new tunnel was returned to pppol2tp_create().
+
+This patch moves tunnel registration out of l2tp_tunnel_create(), so
+that the caller can safely hold a reference before publishing the
+tunnel. This second step is done with the new l2tp_tunnel_register()
+function, which is now responsible for associating the tunnel to its
+socket and for inserting it into the namespace's list.
+
+While moving the code to l2tp_tunnel_register(), a few modifications
+have been done. First, the socket validation tests are done in a helper
+function, for clarity. Also, modifying the socket is now done after
+having inserted the tunnel to the namespace's tunnels list. This will
+allow insertion to fail, without having to revert theses modifications
+in the error path (a followup patch will check for duplicate tunnels
+before insertion). Either the socket is a kernel socket which we
+control, or it is a user-space socket for which we have a reference on
+the file descriptor. In any case, the socket isn't going to be closed
+from under us.
+
+Reported-by: syzbot+fbeeb5c3b538e8545644@syzkaller.appspotmail.com
+Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts")
+Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_core.c    |  192 +++++++++++++++++++++---------------------------
+ net/l2tp/l2tp_core.h    |    3 
+ net/l2tp/l2tp_netlink.c |   16 +++-
+ net/l2tp/l2tp_ppp.c     |    9 ++
+ 4 files changed, 110 insertions(+), 110 deletions(-)
+
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -1445,74 +1445,11 @@ int l2tp_tunnel_create(struct net *net,
+ {
+       struct l2tp_tunnel *tunnel = NULL;
+       int err;
+-      struct socket *sock = NULL;
+-      struct sock *sk = NULL;
+-      struct l2tp_net *pn;
+       enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
+-      /* Get the tunnel socket from the fd, which was opened by
+-       * the userspace L2TP daemon. If not specified, create a
+-       * kernel socket.
+-       */
+-      if (fd < 0) {
+-              err = l2tp_tunnel_sock_create(net, tunnel_id, peer_tunnel_id,
+-                              cfg, &sock);
+-              if (err < 0)
+-                      goto err;
+-      } else {
+-              sock = sockfd_lookup(fd, &err);
+-              if (!sock) {
+-                      pr_err("tunl %u: sockfd_lookup(fd=%d) returned %d\n",
+-                             tunnel_id, fd, err);
+-                      err = -EBADF;
+-                      goto err;
+-              }
+-
+-              /* Reject namespace mismatches */
+-              if (!net_eq(sock_net(sock->sk), net)) {
+-                      pr_err("tunl %u: netns mismatch\n", tunnel_id);
+-                      err = -EINVAL;
+-                      goto err;
+-              }
+-      }
+-
+-      sk = sock->sk;
+-
+       if (cfg != NULL)
+               encap = cfg->encap;
+-      /* Quick sanity checks */
+-      err = -EPROTONOSUPPORT;
+-      if (sk->sk_type != SOCK_DGRAM) {
+-              pr_debug("tunl %hu: fd %d wrong socket type\n",
+-                       tunnel_id, fd);
+-              goto err;
+-      }
+-      switch (encap) {
+-      case L2TP_ENCAPTYPE_UDP:
+-              if (sk->sk_protocol != IPPROTO_UDP) {
+-                      pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
+-                             tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP);
+-                      goto err;
+-              }
+-              break;
+-      case L2TP_ENCAPTYPE_IP:
+-              if (sk->sk_protocol != IPPROTO_L2TP) {
+-                      pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
+-                             tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP);
+-                      goto err;
+-              }
+-              break;
+-      }
+-
+-      /* Check if this socket has already been prepped */
+-      tunnel = l2tp_tunnel(sk);
+-      if (tunnel != NULL) {
+-              /* This socket has already been prepped */
+-              err = -EBUSY;
+-              goto err;
+-      }
+-
+       tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL);
+       if (tunnel == NULL) {
+               err = -ENOMEM;
+@@ -1529,72 +1466,113 @@ int l2tp_tunnel_create(struct net *net,
+       rwlock_init(&tunnel->hlist_lock);
+       tunnel->acpt_newsess = true;
+-      /* The net we belong to */
+-      tunnel->l2tp_net = net;
+-      pn = l2tp_pernet(net);
+-
+       if (cfg != NULL)
+               tunnel->debug = cfg->debug;
+-      /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
+       tunnel->encap = encap;
+-      if (encap == L2TP_ENCAPTYPE_UDP) {
+-              struct udp_tunnel_sock_cfg udp_cfg = { };
+-
+-              udp_cfg.sk_user_data = tunnel;
+-              udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
+-              udp_cfg.encap_rcv = l2tp_udp_encap_recv;
+-              udp_cfg.encap_destroy = l2tp_udp_encap_destroy;
+-
+-              setup_udp_tunnel_sock(net, sock, &udp_cfg);
+-      } else {
+-              sk->sk_user_data = tunnel;
+-      }
+-      /* Bump the reference count. The tunnel context is deleted
+-       * only when this drops to zero. A reference is also held on
+-       * the tunnel socket to ensure that it is not released while
+-       * the tunnel is extant. Must be done before sk_destruct is
+-       * set.
+-       */
+       refcount_set(&tunnel->ref_count, 1);
+-      sock_hold(sk);
+-      tunnel->sock = sk;
+       tunnel->fd = fd;
+-      /* Hook on the tunnel socket destructor so that we can cleanup
+-       * if the tunnel socket goes away.
+-       */
+-      tunnel->old_sk_destruct = sk->sk_destruct;
+-      sk->sk_destruct = &l2tp_tunnel_destruct;
+-      lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");
+-
+-      sk->sk_allocation = GFP_ATOMIC;
+-
+       /* Init delete workqueue struct */
+       INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work);
+-      /* Add tunnel to our list */
+       INIT_LIST_HEAD(&tunnel->list);
+-      spin_lock_bh(&pn->l2tp_tunnel_list_lock);
+-      list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
+-      spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
+       err = 0;
+ err:
+       if (tunnelp)
+               *tunnelp = tunnel;
+-      /* If tunnel's socket was created by the kernel, it doesn't
+-       *  have a file.
+-       */
+-      if (sock && sock->file)
+-              sockfd_put(sock);
+-
+       return err;
+ }
+ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
++static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
++                              enum l2tp_encap_type encap)
++{
++      if (!net_eq(sock_net(sk), net))
++              return -EINVAL;
++
++      if (sk->sk_type != SOCK_DGRAM)
++              return -EPROTONOSUPPORT;
++
++      if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) ||
++          (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP))
++              return -EPROTONOSUPPORT;
++
++      if (sk->sk_user_data)
++              return -EBUSY;
++
++      return 0;
++}
++
++int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
++                       struct l2tp_tunnel_cfg *cfg)
++{
++      struct l2tp_net *pn;
++      struct socket *sock;
++      struct sock *sk;
++      int ret;
++
++      if (tunnel->fd < 0) {
++              ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
++                                            tunnel->peer_tunnel_id, cfg,
++                                            &sock);
++              if (ret < 0)
++                      goto err;
++      } else {
++              sock = sockfd_lookup(tunnel->fd, &ret);
++              if (!sock)
++                      goto err;
++
++              ret = l2tp_validate_socket(sock->sk, net, tunnel->encap);
++              if (ret < 0)
++                      goto err_sock;
++      }
++
++      sk = sock->sk;
++
++      sock_hold(sk);
++      tunnel->sock = sk;
++      tunnel->l2tp_net = net;
++
++      pn = l2tp_pernet(net);
++      spin_lock_bh(&pn->l2tp_tunnel_list_lock);
++      list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
++      spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
++
++      if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
++              struct udp_tunnel_sock_cfg udp_cfg = {
++                      .sk_user_data = tunnel,
++                      .encap_type = UDP_ENCAP_L2TPINUDP,
++                      .encap_rcv = l2tp_udp_encap_recv,
++                      .encap_destroy = l2tp_udp_encap_destroy,
++              };
++
++              setup_udp_tunnel_sock(net, sock, &udp_cfg);
++      } else {
++              sk->sk_user_data = tunnel;
++      }
++
++      tunnel->old_sk_destruct = sk->sk_destruct;
++      sk->sk_destruct = &l2tp_tunnel_destruct;
++      lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class,
++                                 "l2tp_sock");
++      sk->sk_allocation = GFP_ATOMIC;
++
++      if (tunnel->fd >= 0)
++              sockfd_put(sock);
++
++      return 0;
++
++err_sock:
++      sockfd_put(sock);
++err:
++      return ret;
++}
++EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
++
+ /* This function is used by the netlink TUNNEL_DELETE command.
+  */
+ void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -231,6 +231,9 @@ struct l2tp_tunnel *l2tp_tunnel_find_nth
+ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id,
+                      u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg,
+                      struct l2tp_tunnel **tunnelp);
++int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
++                       struct l2tp_tunnel_cfg *cfg);
++
+ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);
+ void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);
+ struct l2tp_session *l2tp_session_create(int priv_size,
+--- a/net/l2tp/l2tp_netlink.c
++++ b/net/l2tp/l2tp_netlink.c
+@@ -251,9 +251,19 @@ static int l2tp_nl_cmd_tunnel_create(str
+               break;
+       }
+-      if (ret >= 0)
+-              ret = l2tp_tunnel_notify(&l2tp_nl_family, info,
+-                                       tunnel, L2TP_CMD_TUNNEL_CREATE);
++      if (ret < 0)
++              goto out;
++
++      l2tp_tunnel_inc_refcount(tunnel);
++      ret = l2tp_tunnel_register(tunnel, net, &cfg);
++      if (ret < 0) {
++              kfree(tunnel);
++              goto out;
++      }
++      ret = l2tp_tunnel_notify(&l2tp_nl_family, info, tunnel,
++                               L2TP_CMD_TUNNEL_CREATE);
++      l2tp_tunnel_dec_refcount(tunnel);
++
+ out:
+       return ret;
+ }
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -698,6 +698,15 @@ static int pppol2tp_connect(struct socke
+                       error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, &tcfg, &tunnel);
+                       if (error < 0)
+                               goto end;
++
++                      l2tp_tunnel_inc_refcount(tunnel);
++                      error = l2tp_tunnel_register(tunnel, sock_net(sk),
++                                                   &tcfg);
++                      if (error < 0) {
++                              kfree(tunnel);
++                              goto end;
++                      }
++                      drop_tunnel = true;
+               }
+       } else {
+               /* Error if we can't find the tunnel */
diff --git a/queue-4.15/lan78xx-correctly-indicate-invalid-otp.patch b/queue-4.15/lan78xx-correctly-indicate-invalid-otp.patch
new file mode 100644 (file)
index 0000000..5fe35d6
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 11 Apr 2018 10:59:17 +0100
+Subject: lan78xx: Correctly indicate invalid OTP
+
+From: Phil Elwell <phil@raspberrypi.org>
+
+
+[ Upstream commit 4bfc33807a9a02764bdd1e42e794b3b401240f27 ]
+
+lan78xx_read_otp tries to return -EINVAL in the event of invalid OTP
+content, but the value gets overwritten before it is returned and the
+read goes ahead anyway. Make the read conditional as it should be
+and preserve the error code.
+
+Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/lan78xx.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -928,7 +928,8 @@ static int lan78xx_read_otp(struct lan78
+                       offset += 0x100;
+               else
+                       ret = -EINVAL;
+-              ret = lan78xx_read_raw_otp(dev, offset, length, data);
++              if (!ret)
++                      ret = lan78xx_read_raw_otp(dev, offset, length, data);
+       }
+       return ret;
diff --git a/queue-4.15/rds-mp-rds-may-use-an-invalid-c_path.patch b/queue-4.15/rds-mp-rds-may-use-an-invalid-c_path.patch
new file mode 100644 (file)
index 0000000..ac69d49
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
+Date: Wed, 11 Apr 2018 00:57:25 -0700
+Subject: rds: MP-RDS may use an invalid c_path
+
+From: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
+
+
+[ Upstream commit a43cced9a348901f9015f4730b70b69e7c41a9c9 ]
+
+rds_sendmsg() calls rds_send_mprds_hash() to find a c_path to use to
+send a message.  Suppose the RDS connection is not yet up.  In
+rds_send_mprds_hash(), it does
+
+       if (conn->c_npaths == 0)
+               wait_event_interruptible(conn->c_hs_waitq,
+                                        (conn->c_npaths != 0));
+
+If it is interrupted before the connection is set up,
+rds_send_mprds_hash() will return a non-zero hash value.  Hence
+rds_sendmsg() will use a non-zero c_path to send the message.  But if
+the RDS connection ends up to be non-MP capable, the message will be
+lost as only the zero c_path can be used.
+
+Signed-off-by: Ka-Cheong Poon <ka-cheong.poon@oracle.com>
+Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rds/send.c |   15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006 Oracle.  All rights reserved.
++ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+  * licenses.  You may choose to be licensed under the terms of the GNU
+@@ -986,10 +986,15 @@ static int rds_send_mprds_hash(struct rd
+       if (conn->c_npaths == 0 && hash != 0) {
+               rds_send_ping(conn, 0);
+-              if (conn->c_npaths == 0) {
+-                      wait_event_interruptible(conn->c_hs_waitq,
+-                                               (conn->c_npaths != 0));
+-              }
++              /* The underlying connection is not up yet.  Need to wait
++               * until it is up to be sure that the non-zero c_path can be
++               * used.  But if we are interrupted, we have to use the zero
++               * c_path in case the connection ends up being non-MP capable.
++               */
++              if (conn->c_npaths == 0)
++                      if (wait_event_interruptible(conn->c_hs_waitq,
++                                                   conn->c_npaths != 0))
++                              hash = 0;
+               if (conn->c_npaths == 1)
+                       hash = 0;
+       }
index 8a6b3dcd5dd95f8159140cc862d3b88e03df2eb5..4dd0380f9cf94d173a6566aa2fd3b656c3ac5cc9 100644 (file)
@@ -1,2 +1,11 @@
 drm-i915-edp-do-not-do-link-training-fallback-or-prune-modes-on-edp.patch
 netfilter-ipset-missing-nfnl_lock-nfnl_unlock-is-added-to-ip_set_net_exit.patch
+cdc_ether-flag-the-cinterion-ahs8-modem-by-gemalto-as-wwan.patch
+rds-mp-rds-may-use-an-invalid-c_path.patch
+slip-check-if-rstate-is-initialized-before-uncompressing.patch
+vhost-fix-vhost_vq_access_ok-log-check.patch
+l2tp-fix-races-in-tunnel-creation.patch
+l2tp-fix-race-in-duplicate-tunnel-detection.patch
+ip_gre-clear-feature-flags-when-incompatible-o_flags-are-set.patch
+vhost-fix-vhost_copy_to_user.patch
+lan78xx-correctly-indicate-invalid-otp.patch
diff --git a/queue-4.15/slip-check-if-rstate-is-initialized-before-uncompressing.patch b/queue-4.15/slip-check-if-rstate-is-initialized-before-uncompressing.patch
new file mode 100644 (file)
index 0000000..4092c30
--- /dev/null
@@ -0,0 +1,76 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Tejaswi Tanikella <tejaswit@codeaurora.org>
+Date: Wed, 11 Apr 2018 16:34:47 +0530
+Subject: slip: Check if rstate is initialized before uncompressing
+
+From: Tejaswi Tanikella <tejaswit@codeaurora.org>
+
+
+[ Upstream commit 3f01ddb962dc506916c243f9524e8bef97119b77 ]
+
+On receiving a packet the state index points to the rstate which must be
+used to fill up IP and TCP headers. But if the state index points to a
+rstate which is unitialized, i.e. filled with zeros, it gets stuck in an
+infinite loop inside ip_fast_csum trying to compute the ip checsum of a
+header with zero length.
+
+89.666953:   <2> [<ffffff9dd3e94d38>] slhc_uncompress+0x464/0x468
+89.666965:   <2> [<ffffff9dd3e87d88>] ppp_receive_nonmp_frame+0x3b4/0x65c
+89.666978:   <2> [<ffffff9dd3e89dd4>] ppp_receive_frame+0x64/0x7e0
+89.666991:   <2> [<ffffff9dd3e8a708>] ppp_input+0x104/0x198
+89.667005:   <2> [<ffffff9dd3e93868>] pppopns_recv_core+0x238/0x370
+89.667027:   <2> [<ffffff9dd4428fc8>] __sk_receive_skb+0xdc/0x250
+89.667040:   <2> [<ffffff9dd3e939e4>] pppopns_recv+0x44/0x60
+89.667053:   <2> [<ffffff9dd4426848>] __sock_queue_rcv_skb+0x16c/0x24c
+89.667065:   <2> [<ffffff9dd4426954>] sock_queue_rcv_skb+0x2c/0x38
+89.667085:   <2> [<ffffff9dd44f7358>] raw_rcv+0x124/0x154
+89.667098:   <2> [<ffffff9dd44f7568>] raw_local_deliver+0x1e0/0x22c
+89.667117:   <2> [<ffffff9dd44c8ba0>] ip_local_deliver_finish+0x70/0x24c
+89.667131:   <2> [<ffffff9dd44c92f4>] ip_local_deliver+0x100/0x10c
+
+./scripts/faddr2line vmlinux slhc_uncompress+0x464/0x468 output:
+ ip_fast_csum at arch/arm64/include/asm/checksum.h:40
+ (inlined by) slhc_uncompress at drivers/net/slip/slhc.c:615
+
+Adding a variable to indicate if the current rstate is initialized. If
+such a packet arrives, move to toss state.
+
+Signed-off-by: Tejaswi Tanikella <tejaswit@codeaurora.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/slip/slhc.c |    5 +++++
+ include/net/slhc_vj.h   |    1 +
+ 2 files changed, 6 insertions(+)
+
+--- a/drivers/net/slip/slhc.c
++++ b/drivers/net/slip/slhc.c
+@@ -509,6 +509,10 @@ slhc_uncompress(struct slcompress *comp,
+               if(x < 0 || x > comp->rslot_limit)
+                       goto bad;
++              /* Check if the cstate is initialized */
++              if (!comp->rstate[x].initialized)
++                      goto bad;
++
+               comp->flags &=~ SLF_TOSS;
+               comp->recv_current = x;
+       } else {
+@@ -673,6 +677,7 @@ slhc_remember(struct slcompress *comp, u
+       if (cs->cs_tcp.doff > 5)
+         memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
+       cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
++      cs->initialized = true;
+       /* Put headers back on packet
+        * Neither header checksum is recalculated
+        */
+--- a/include/net/slhc_vj.h
++++ b/include/net/slhc_vj.h
+@@ -127,6 +127,7 @@ typedef __u32 int32;
+  */
+ struct cstate {
+       byte_t  cs_this;        /* connection id number (xmit) */
++      bool    initialized;    /* true if initialized */
+       struct cstate *next;    /* next in ring (xmit) */
+       struct iphdr cs_ip;     /* ip/tcp hdr from most recent packet */
+       struct tcphdr cs_tcp;
diff --git a/queue-4.15/vhost-fix-vhost_copy_to_user.patch b/queue-4.15/vhost-fix-vhost_copy_to_user.patch
new file mode 100644 (file)
index 0000000..d8c88de
--- /dev/null
@@ -0,0 +1,34 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Eric Auger <eric.auger@redhat.com>
+Date: Wed, 11 Apr 2018 15:30:38 +0200
+Subject: vhost: Fix vhost_copy_to_user()
+
+From: Eric Auger <eric.auger@redhat.com>
+
+
+[ Upstream commit 7ced6c98c7ab7a1f6743931e28671b833af79b1e ]
+
+vhost_copy_to_user is used to copy vring used elements to userspace.
+We should use VHOST_ADDR_USED instead of VHOST_ADDR_DESC.
+
+Fixes: f88949138058 ("vhost: introduce O(1) vq metadata cache")
+Signed-off-by: Eric Auger <eric.auger@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/vhost/vhost.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -756,7 +756,7 @@ static int vhost_copy_to_user(struct vho
+               struct iov_iter t;
+               void __user *uaddr = vhost_vq_meta_fetch(vq,
+                                    (u64)(uintptr_t)to, size,
+-                                   VHOST_ADDR_DESC);
++                                   VHOST_ADDR_USED);
+               if (uaddr)
+                       return __copy_to_user(uaddr, from, size);
diff --git a/queue-4.15/vhost-fix-vhost_vq_access_ok-log-check.patch b/queue-4.15/vhost-fix-vhost_vq_access_ok-log-check.patch
new file mode 100644 (file)
index 0000000..8d80d05
--- /dev/null
@@ -0,0 +1,56 @@
+From foo@baz Sat Apr 14 09:16:37 CEST 2018
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 11 Apr 2018 10:35:40 +0800
+Subject: vhost: fix vhost_vq_access_ok() log check
+
+From: Stefan Hajnoczi <stefanha@redhat.com>
+
+
+[ Upstream commit d14d2b78090c7de0557362b26a4ca591aa6a9faa ]
+
+Commit d65026c6c62e7d9616c8ceb5a53b68bcdc050525 ("vhost: validate log
+when IOTLB is enabled") introduced a regression.  The logic was
+originally:
+
+  if (vq->iotlb)
+      return 1;
+  return A && B;
+
+After the patch the short-circuit logic for A was inverted:
+
+  if (A || vq->iotlb)
+      return A;
+  return B;
+
+This patch fixes the regression by rewriting the checks in the obvious
+way, no longer returning A when vq->iotlb is non-NULL (which is hard to
+understand).
+
+Reported-by: syzbot+65a84dde0214b0387ccd@syzkaller.appspotmail.com
+Cc: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/vhost/vhost.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -1256,10 +1256,12 @@ static int vq_log_access_ok(struct vhost
+ /* Caller should have vq mutex and device mutex */
+ int vhost_vq_access_ok(struct vhost_virtqueue *vq)
+ {
+-      int ret = vq_log_access_ok(vq, vq->log_base);
++      if (!vq_log_access_ok(vq, vq->log_base))
++              return 0;
+-      if (ret || vq->iotlb)
+-              return ret;
++      /* Access validation occurs at prefetch time with IOTLB */
++      if (vq->iotlb)
++              return 1;
+       return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used);
+ }