Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Apr 2018 00:04:10 +0000 (17:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Apr 2018 00:04:10 +0000 (17:04 -0700)
Pull networking fixes from David Miller:

 1) The sockmap code has to free socket memory on close if there is
    corked data, from John Fastabend.

 2) Tunnel names coming from userspace need to be length validated. From
    Eric Dumazet.

 3) arp_filter() has to take VRFs properly into account, from Miguel
    Fadon Perlines.

 4) Fix oops in error path of tcf_bpf_init(), from Davide Caratti.

 5) Missing idr_remove() in u32_delete_key(), from Cong Wang.

 6) More syzbot stuff. Several use of uninitialized value fixes all
    over, from Eric Dumazet.

 7) Do not leak kernel memory to userspace in sctp, also from Eric
    Dumazet.

 8) Discard frames from unused ports in DSA, from Andrew Lunn.

 9) Fix DMA mapping and reset/failover problems in ibmvnic, from Thomas
    Falcon.

10) Do not access dp83640 PHY registers prematurely after reset, from
    Esben Haabendal.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (46 commits)
  vhost-net: set packet weight of tx polling to 2 * vq size
  net: thunderx: rework mac addresses list to u64 array
  inetpeer: fix uninit-value in inet_getpeer
  dp83640: Ensure against premature access to PHY registers after reset
  devlink: convert occ_get op to separate registration
  ARM: dts: ls1021a: Specify TBIPA register address
  net/fsl_pq_mdio: Allow explicit speficition of TBIPA address
  ibmvnic: Do not reset CRQ for Mobility driver resets
  ibmvnic: Fix failover case for non-redundant configuration
  ibmvnic: Fix reset scheduler error handling
  ibmvnic: Zero used TX descriptor counter on reset
  ibmvnic: Fix DMA mapping mistakes
  tipc: use the right skb in tipc_sk_fill_sock_diag()
  sctp: sctp_sockaddr_af must check minimal addr length for AF_INET6
  net: dsa: Discard frames from unused ports
  sctp: do not leak kernel memory to user space
  soreuseport: initialise timewait reuseport field
  ipv4: fix uninit-value in ip_route_output_key_hash_rcu()
  dccp: initialize ireq->ir_mark
  net: fix uninit-value in __hw_addr_add_ex()
  ...

1  2 
arch/arm/boot/dts/ls1021a.dtsi
net/ipv4/route.c
net/sctp/ipv6.c
net/sctp/socket.c

                        device_type = "mdio";
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       reg = <0x0 0x2d24000 0x0 0x4000>;
+                       reg = <0x0 0x2d24000 0x0 0x4000>,
+                             <0x0 0x2d10030 0x0 0x4>;
                };
  
                ptp_clock@2d10e00 {
                        clock-names = "ipg", "per";
                        big-endian;
                };
 +
 +              ocram1: sram@10000000 {
 +                      compatible = "mmio-sram";
 +                      reg = <0x0 0x10000000 0x0 0x10000>;
 +                      #address-cells = <1>;
 +                      #size-cells = <1>;
 +                      ranges = <0x0 0x0 0x10000000 0x10000>;
 +              };
 +
 +              ocram2: sram@10010000 {
 +                      compatible = "mmio-sram";
 +                      reg = <0x0 0x10010000 0x0 0x10000>;
 +                      #address-cells = <1>;
 +                      #size-cells = <1>;
 +                      ranges = <0x0 0x0 0x10010000 0x10000>;
 +              };
        };
  };
diff --combined net/ipv4/route.c
  #include <net/rtnetlink.h>
  #ifdef CONFIG_SYSCTL
  #include <linux/sysctl.h>
 -#include <linux/kmemleak.h>
  #endif
  #include <net/secure_seq.h>
  #include <net/ip_tunnels.h>
@@@ -2296,13 -2297,14 +2296,14 @@@ struct rtable *ip_route_output_key_hash
                                        const struct sk_buff *skb)
  {
        __u8 tos = RT_FL_TOS(fl4);
-       struct fib_result res;
+       struct fib_result res = {
+               .type           = RTN_UNSPEC,
+               .fi             = NULL,
+               .table          = NULL,
+               .tclassid       = 0,
+       };
        struct rtable *rth;
  
-       res.tclassid    = 0;
-       res.fi          = NULL;
-       res.table       = NULL;
        fl4->flowi4_iif = LOOPBACK_IFINDEX;
        fl4->flowi4_tos = tos & IPTOS_RT_MASK;
        fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
diff --combined net/sctp/ipv6.c
@@@ -427,41 -427,6 +427,41 @@@ static void sctp_v6_copy_addrlist(struc
        rcu_read_unlock();
  }
  
 +/* Copy over any ip options */
 +static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
 +{
 +      struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
 +      struct ipv6_txoptions *opt;
 +
 +      newnp = inet6_sk(newsk);
 +
 +      rcu_read_lock();
 +      opt = rcu_dereference(np->opt);
 +      if (opt) {
 +              opt = ipv6_dup_options(newsk, opt);
 +              if (!opt)
 +                      pr_err("%s: Failed to copy ip options\n", __func__);
 +      }
 +      RCU_INIT_POINTER(newnp->opt, opt);
 +      rcu_read_unlock();
 +}
 +
 +/* Account for the IP options */
 +static int sctp_v6_ip_options_len(struct sock *sk)
 +{
 +      struct ipv6_pinfo *np = inet6_sk(sk);
 +      struct ipv6_txoptions *opt;
 +      int len = 0;
 +
 +      rcu_read_lock();
 +      opt = rcu_dereference(np->opt);
 +      if (opt)
 +              len = opt->opt_flen + opt->opt_nflen;
 +
 +      rcu_read_unlock();
 +      return len;
 +}
 +
  /* Initialize a sockaddr_storage from in incoming skb. */
  static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
                             int is_saddr)
@@@ -701,6 -666,7 +701,6 @@@ static struct sock *sctp_v6_create_acce
        struct sock *newsk;
        struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
        struct sctp6_sock *newsctp6sk;
 -      struct ipv6_txoptions *opt;
  
        newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
        if (!newsk)
        newnp->ipv6_ac_list = NULL;
        newnp->ipv6_fl_list = NULL;
  
 -      rcu_read_lock();
 -      opt = rcu_dereference(np->opt);
 -      if (opt)
 -              opt = ipv6_dup_options(newsk, opt);
 -      RCU_INIT_POINTER(newnp->opt, opt);
 -      rcu_read_unlock();
 +      sctp_v6_copy_ip_options(sk, newsk);
  
        /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
         * and getpeername().
@@@ -757,8 -728,10 +757,10 @@@ static int sctp_v6_addr_to_user(struct 
                        sctp_v6_map_v4(addr);
        }
  
-       if (addr->sa.sa_family == AF_INET)
+       if (addr->sa.sa_family == AF_INET) {
+               memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
                return sizeof(struct sockaddr_in);
+       }
        return sizeof(struct sockaddr_in6);
  }
  
@@@ -1070,7 -1043,6 +1072,7 @@@ static struct sctp_af sctp_af_inet6 = 
        .ecn_capable       = sctp_v6_ecn_capable,
        .net_header_len    = sizeof(struct ipv6hdr),
        .sockaddr_len      = sizeof(struct sockaddr_in6),
 +      .ip_options_len    = sctp_v6_ip_options_len,
  #ifdef CONFIG_COMPAT
        .compat_setsockopt = compat_ipv6_setsockopt,
        .compat_getsockopt = compat_ipv6_getsockopt,
@@@ -1089,7 -1061,6 +1091,7 @@@ static struct sctp_pf sctp_pf_inet6 = 
        .addr_to_user  = sctp_v6_addr_to_user,
        .to_sk_saddr   = sctp_v6_to_sk_saddr,
        .to_sk_daddr   = sctp_v6_to_sk_daddr,
 +      .copy_ip_options = sctp_v6_copy_ip_options,
        .af            = &sctp_af_inet6,
  };
  
diff --combined net/sctp/socket.c
@@@ -357,11 -357,14 +357,14 @@@ static struct sctp_af *sctp_sockaddr_af
        if (!opt->pf->af_supported(addr->sa.sa_family, opt))
                return NULL;
  
-       /* V4 mapped address are really of AF_INET family */
-       if (addr->sa.sa_family == AF_INET6 &&
-           ipv6_addr_v4mapped(&addr->v6.sin6_addr) &&
-           !opt->pf->af_supported(AF_INET, opt))
-               return NULL;
+       if (addr->sa.sa_family == AF_INET6) {
+               if (len < SIN6_LEN_RFC2133)
+                       return NULL;
+               /* V4 mapped address are really of AF_INET family */
+               if (ipv6_addr_v4mapped(&addr->v6.sin6_addr) &&
+                   !opt->pf->af_supported(AF_INET, opt))
+                       return NULL;
+       }
  
        /* If we get this far, af is valid. */
        af = sctp_get_af_specific(addr->sa.sa_family);
@@@ -1046,12 -1049,6 +1049,12 @@@ static int sctp_setsockopt_bindx(struc
        /* Do the work. */
        switch (op) {
        case SCTP_BINDX_ADD_ADDR:
 +              /* Allow security module to validate bindx addresses. */
 +              err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_BINDX_ADD,
 +                                               (struct sockaddr *)kaddrs,
 +                                               addrs_size);
 +              if (err)
 +                      goto out;
                err = sctp_bindx_add(sk, kaddrs, addrcnt);
                if (err)
                        goto out;
@@@ -1261,7 -1258,6 +1264,7 @@@ static int __sctp_connect(struct sock *
  
        if (assoc_id)
                *assoc_id = asoc->assoc_id;
 +
        err = sctp_wait_for_connect(asoc, &timeo);
        /* Note: the asoc may be freed after the return of
         * sctp_wait_for_connect.
@@@ -1357,16 -1353,7 +1360,16 @@@ static int __sctp_setsockopt_connectx(s
        if (unlikely(IS_ERR(kaddrs)))
                return PTR_ERR(kaddrs);
  
 +      /* Allow security module to validate connectx addresses. */
 +      err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX,
 +                                       (struct sockaddr *)kaddrs,
 +                                        addrs_size);
 +      if (err)
 +              goto out_free;
 +
        err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
 +
 +out_free:
        kvfree(kaddrs);
  
        return err;
@@@ -1696,7 -1683,6 +1699,7 @@@ static int sctp_sendmsg_new_asoc(struc
        struct sctp_association *asoc;
        enum sctp_scope scope;
        struct cmsghdr *cmsg;
 +      struct sctp_af *af;
        int err;
  
        *tp = NULL;
  
        scope = sctp_scope(daddr);
  
 +      /* Label connection socket for first association 1-to-many
 +       * style for client sequence socket()->sendmsg(). This
 +       * needs to be done before sctp_assoc_add_peer() as that will
 +       * set up the initial packet that needs to account for any
 +       * security ip options (CIPSO/CALIPSO) added to the packet.
 +       */
 +      af = sctp_get_af_specific(daddr->sa.sa_family);
 +      if (!af)
 +              return -EINVAL;
 +      err = security_sctp_bind_connect(sk, SCTP_SENDMSG_CONNECT,
 +                                       (struct sockaddr *)daddr,
 +                                       af->sockaddr_len);
 +      if (err < 0)
 +              return err;
 +
        asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
        if (!asoc)
                return -ENOMEM;
@@@ -2964,8 -2935,6 +2967,8 @@@ static int sctp_setsockopt_primary_addr
  {
        struct sctp_prim prim;
        struct sctp_transport *trans;
 +      struct sctp_af *af;
 +      int err;
  
        if (optlen != sizeof(struct sctp_prim))
                return -EINVAL;
        if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
                return -EFAULT;
  
 +      /* Allow security module to validate address but need address len. */
 +      af = sctp_get_af_specific(prim.ssp_addr.ss_family);
 +      if (!af)
 +              return -EINVAL;
 +
 +      err = security_sctp_bind_connect(sk, SCTP_PRIMARY_ADDR,
 +                                       (struct sockaddr *)&prim.ssp_addr,
 +                                       af->sockaddr_len);
 +      if (err)
 +              return err;
 +
        trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id);
        if (!trans)
                return -EINVAL;
@@@ -3206,7 -3164,6 +3209,7 @@@ static int sctp_setsockopt_mappedv4(str
  static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
  {
        struct sctp_sock *sp = sctp_sk(sk);
 +      struct sctp_af *af = sp->pf->af;
        struct sctp_assoc_value params;
        struct sctp_association *asoc;
        int val;
        if (val) {
                int min_len, max_len;
  
 -              min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
 +              min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
 +              min_len -= af->ip_options_len(sk);
                min_len -= sizeof(struct sctphdr) +
                           sizeof(struct sctp_data_chunk);
  
        asoc = sctp_id2assoc(sk, params.assoc_id);
        if (asoc) {
                if (val == 0) {
 -                      val = asoc->pathmtu - sp->pf->af->net_header_len;
 +                      val = asoc->pathmtu - af->net_header_len;
 +                      val -= af->ip_options_len(sk);
                        val -= sizeof(struct sctphdr) +
                               sctp_datachk_len(&asoc->stream);
                }
@@@ -3315,13 -3270,6 +3318,13 @@@ static int sctp_setsockopt_peer_primary
        if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
                return -EADDRNOTAVAIL;
  
 +      /* Allow security module to validate address. */
 +      err = security_sctp_bind_connect(sk, SCTP_SET_PEER_PRIMARY_ADDR,
 +                                       (struct sockaddr *)&prim.sspp_addr,
 +                                       af->sockaddr_len);
 +      if (err)
 +              return err;
 +
        /* Create an ASCONF chunk with SET_PRIMARY parameter    */
        chunk = sctp_make_asconf_set_prim(asoc,
                                          (union sctp_addr *)&prim.sspp_addr);
@@@ -5195,11 -5143,9 +5198,11 @@@ int sctp_do_peeloff(struct sock *sk, sc
        sctp_copy_sock(sock->sk, sk, asoc);
  
        /* Make peeled-off sockets more like 1-1 accepted sockets.
 -       * Set the daddr and initialize id to something more random
 +       * Set the daddr and initialize id to something more random and also
 +       * copy over any ip options.
         */
        sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
 +      sp->pf->copy_ip_options(sk, sock->sk);
  
        /* Populate the fields of the newsk from the oldsk and migrate the
         * asoc to the newsk.
@@@ -8522,8 -8468,6 +8525,8 @@@ void sctp_copy_sock(struct sock *newsk
  {
        struct inet_sock *inet = inet_sk(sk);
        struct inet_sock *newinet;
 +      struct sctp_sock *sp = sctp_sk(sk);
 +      struct sctp_endpoint *ep = sp->ep;
  
        newsk->sk_type = sk->sk_type;
        newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
        if (newsk->sk_flags & SK_FLAGS_TIMESTAMP)
                net_enable_timestamp();
  
 -      security_sk_clone(sk, newsk);
 +      /* Set newsk security attributes from orginal sk and connection
 +       * security attribute from ep.
 +       */
 +      security_sctp_sk_clone(ep, sk, newsk);
  }
  
  static inline void sctp_copy_descendant(struct sock *sk_to,