Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Mar 2019 19:22:57 +0000 (12:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Mar 2019 19:22:57 +0000 (12:22 -0700)
Pull networking fixes from David Miller:
 "Fixes here and there, a couple new device IDs, as usual:

   1) Fix BQL race in dpaa2-eth driver, from Ioana Ciornei.

   2) Fix 64-bit division in iwlwifi, from Arnd Bergmann.

   3) Fix documentation for some eBPF helpers, from Quentin Monnet.

   4) Some UAPI bpf header sync with tools, also from Quentin Monnet.

   5) Set descriptor ownership bit at the right time for jumbo frames in
      stmmac driver, from Aaro Koskinen.

   6) Set IFF_UP properly in tun driver, from Eric Dumazet.

   7) Fix load/store doubleword instruction generation in powerpc eBPF
      JIT, from Naveen N. Rao.

   8) nla_nest_start() return value checks all over, from Kangjie Lu.

   9) Fix asoc_id handling in SCTP after the SCTP_*_ASSOC changes this
      merge window. From Marcelo Ricardo Leitner and Xin Long.

  10) Fix memory corruption with large MTUs in stmmac, from Aaro
      Koskinen.

  11) Do not use ipv4 header for ipv6 flows in TCP and DCCP, from Eric
      Dumazet.

  12) Fix topology subscription cancellation in tipc, from Erik Hugne.

  13) Memory leak in genetlink error path, from Yue Haibing.

  14) Valid control actions properly in packet scheduler, from Davide
      Caratti.

  15) Even if we get EEXIST, we still need to rehash if a shrink was
      delayed. From Herbert Xu.

  16) Fix interrupt mask handling in interrupt handler of r8169, from
      Heiner Kallweit.

  17) Fix leak in ehea driver, from Wen Yang"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (168 commits)
  dpaa2-eth: fix race condition with bql frame accounting
  chelsio: use BUG() instead of BUG_ON(1)
  net: devlink: skip info_get op call if it is not defined in dumpit
  net: phy: bcm54xx: Encode link speed and activity into LEDs
  tipc: change to check tipc_own_id to return in tipc_net_stop
  net: usb: aqc111: Extend HWID table by QNAP device
  net: sched: Kconfig: update reference link for PIE
  net: dsa: qca8k: extend slave-bus implementations
  net: dsa: qca8k: remove leftover phy accessors
  dt-bindings: net: dsa: qca8k: support internal mdio-bus
  dt-bindings: net: dsa: qca8k: fix example
  net: phy: don't clear BMCR in genphy_soft_reset
  bpf, libbpf: clarify bump in libbpf version info
  bpf, libbpf: fix version info and add it to shared object
  rxrpc: avoid clang -Wuninitialized warning
  tipc: tipc clang warning
  net: sched: fix cleanup NULL pointer exception in act_mirr
  r8169: fix cable re-plugging issue
  net: ethernet: ti: fix possible object reference leak
  net: ibm: fix possible object reference leak
  ...

1  2 
tools/lib/bpf/libbpf.c

diff --combined tools/lib/bpf/libbpf.c
index e6ad87512519f559156b74f856b59c4855ee5c6e,5e977d2688da792684bca5d7e16a69e6cf375558..11c25d9ea43124fc6e67fab5a7dc8b93f5dc9e4a
@@@ -112,11 -112,6 +112,11 @@@ void libbpf_print(enum libbpf_print_lev
  # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
  #endif
  
 +static inline __u64 ptr_to_u64(const void *ptr)
 +{
 +      return (__u64) (unsigned long) ptr;
 +}
 +
  struct bpf_capabilities {
        /* v4.14: kernel support for program & map names. */
        __u32 name:1;
@@@ -627,7 -622,7 +627,7 @@@ bpf_object__init_maps(struct bpf_objec
        bool strict = !(flags & MAPS_RELAX_COMPAT);
        int i, map_idx, map_def_sz, nr_maps = 0;
        Elf_Scn *scn;
 -      Elf_Data *data;
 +      Elf_Data *data = NULL;
        Elf_Data *symbols = obj->efile.symbols;
  
        if (obj->efile.maps_shndx < 0)
@@@ -840,12 -835,19 +840,19 @@@ static int bpf_object__elf_collect(stru
                        obj->efile.maps_shndx = idx;
                else if (strcmp(name, BTF_ELF_SEC) == 0) {
                        obj->btf = btf__new(data->d_buf, data->d_size);
-                       if (IS_ERR(obj->btf) || btf__load(obj->btf)) {
+                       if (IS_ERR(obj->btf)) {
                                pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
                                           BTF_ELF_SEC, PTR_ERR(obj->btf));
-                               if (!IS_ERR(obj->btf))
-                                       btf__free(obj->btf);
                                obj->btf = NULL;
+                               continue;
+                       }
+                       err = btf__load(obj->btf);
+                       if (err) {
+                               pr_warning("Error loading %s into kernel: %d. Ignored and continue.\n",
+                                          BTF_ELF_SEC, err);
+                               btf__free(obj->btf);
+                               obj->btf = NULL;
+                               err = 0;
                        }
                } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
                        btf_ext_data = data;
@@@ -3004,249 -3006,3 +3011,249 @@@ bpf_perf_event_read_simple(void *mmap_m
        ring_buffer_write_tail(header, data_tail);
        return ret;
  }
 +
 +struct bpf_prog_info_array_desc {
 +      int     array_offset;   /* e.g. offset of jited_prog_insns */
 +      int     count_offset;   /* e.g. offset of jited_prog_len */
 +      int     size_offset;    /* > 0: offset of rec size,
 +                               * < 0: fix size of -size_offset
 +                               */
 +};
 +
 +static struct bpf_prog_info_array_desc bpf_prog_info_array_desc[] = {
 +      [BPF_PROG_INFO_JITED_INSNS] = {
 +              offsetof(struct bpf_prog_info, jited_prog_insns),
 +              offsetof(struct bpf_prog_info, jited_prog_len),
 +              -1,
 +      },
 +      [BPF_PROG_INFO_XLATED_INSNS] = {
 +              offsetof(struct bpf_prog_info, xlated_prog_insns),
 +              offsetof(struct bpf_prog_info, xlated_prog_len),
 +              -1,
 +      },
 +      [BPF_PROG_INFO_MAP_IDS] = {
 +              offsetof(struct bpf_prog_info, map_ids),
 +              offsetof(struct bpf_prog_info, nr_map_ids),
 +              -(int)sizeof(__u32),
 +      },
 +      [BPF_PROG_INFO_JITED_KSYMS] = {
 +              offsetof(struct bpf_prog_info, jited_ksyms),
 +              offsetof(struct bpf_prog_info, nr_jited_ksyms),
 +              -(int)sizeof(__u64),
 +      },
 +      [BPF_PROG_INFO_JITED_FUNC_LENS] = {
 +              offsetof(struct bpf_prog_info, jited_func_lens),
 +              offsetof(struct bpf_prog_info, nr_jited_func_lens),
 +              -(int)sizeof(__u32),
 +      },
 +      [BPF_PROG_INFO_FUNC_INFO] = {
 +              offsetof(struct bpf_prog_info, func_info),
 +              offsetof(struct bpf_prog_info, nr_func_info),
 +              offsetof(struct bpf_prog_info, func_info_rec_size),
 +      },
 +      [BPF_PROG_INFO_LINE_INFO] = {
 +              offsetof(struct bpf_prog_info, line_info),
 +              offsetof(struct bpf_prog_info, nr_line_info),
 +              offsetof(struct bpf_prog_info, line_info_rec_size),
 +      },
 +      [BPF_PROG_INFO_JITED_LINE_INFO] = {
 +              offsetof(struct bpf_prog_info, jited_line_info),
 +              offsetof(struct bpf_prog_info, nr_jited_line_info),
 +              offsetof(struct bpf_prog_info, jited_line_info_rec_size),
 +      },
 +      [BPF_PROG_INFO_PROG_TAGS] = {
 +              offsetof(struct bpf_prog_info, prog_tags),
 +              offsetof(struct bpf_prog_info, nr_prog_tags),
 +              -(int)sizeof(__u8) * BPF_TAG_SIZE,
 +      },
 +
 +};
 +
 +static __u32 bpf_prog_info_read_offset_u32(struct bpf_prog_info *info, int offset)
 +{
 +      __u32 *array = (__u32 *)info;
 +
 +      if (offset >= 0)
 +              return array[offset / sizeof(__u32)];
 +      return -(int)offset;
 +}
 +
 +static __u64 bpf_prog_info_read_offset_u64(struct bpf_prog_info *info, int offset)
 +{
 +      __u64 *array = (__u64 *)info;
 +
 +      if (offset >= 0)
 +              return array[offset / sizeof(__u64)];
 +      return -(int)offset;
 +}
 +
 +static void bpf_prog_info_set_offset_u32(struct bpf_prog_info *info, int offset,
 +                                       __u32 val)
 +{
 +      __u32 *array = (__u32 *)info;
 +
 +      if (offset >= 0)
 +              array[offset / sizeof(__u32)] = val;
 +}
 +
 +static void bpf_prog_info_set_offset_u64(struct bpf_prog_info *info, int offset,
 +                                       __u64 val)
 +{
 +      __u64 *array = (__u64 *)info;
 +
 +      if (offset >= 0)
 +              array[offset / sizeof(__u64)] = val;
 +}
 +
 +struct bpf_prog_info_linear *
 +bpf_program__get_prog_info_linear(int fd, __u64 arrays)
 +{
 +      struct bpf_prog_info_linear *info_linear;
 +      struct bpf_prog_info info = {};
 +      __u32 info_len = sizeof(info);
 +      __u32 data_len = 0;
 +      int i, err;
 +      void *ptr;
 +
 +      if (arrays >> BPF_PROG_INFO_LAST_ARRAY)
 +              return ERR_PTR(-EINVAL);
 +
 +      /* step 1: get array dimensions */
 +      err = bpf_obj_get_info_by_fd(fd, &info, &info_len);
 +      if (err) {
 +              pr_debug("can't get prog info: %s", strerror(errno));
 +              return ERR_PTR(-EFAULT);
 +      }
 +
 +      /* step 2: calculate total size of all arrays */
 +      for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
 +              bool include_array = (arrays & (1UL << i)) > 0;
 +              struct bpf_prog_info_array_desc *desc;
 +              __u32 count, size;
 +
 +              desc = bpf_prog_info_array_desc + i;
 +
 +              /* kernel is too old to support this field */
 +              if (info_len < desc->array_offset + sizeof(__u32) ||
 +                  info_len < desc->count_offset + sizeof(__u32) ||
 +                  (desc->size_offset > 0 && info_len < desc->size_offset))
 +                      include_array = false;
 +
 +              if (!include_array) {
 +                      arrays &= ~(1UL << i);  /* clear the bit */
 +                      continue;
 +              }
 +
 +              count = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
 +              size  = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
 +
 +              data_len += count * size;
 +      }
 +
 +      /* step 3: allocate continuous memory */
 +      data_len = roundup(data_len, sizeof(__u64));
 +      info_linear = malloc(sizeof(struct bpf_prog_info_linear) + data_len);
 +      if (!info_linear)
 +              return ERR_PTR(-ENOMEM);
 +
 +      /* step 4: fill data to info_linear->info */
 +      info_linear->arrays = arrays;
 +      memset(&info_linear->info, 0, sizeof(info));
 +      ptr = info_linear->data;
 +
 +      for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
 +              struct bpf_prog_info_array_desc *desc;
 +              __u32 count, size;
 +
 +              if ((arrays & (1UL << i)) == 0)
 +                      continue;
 +
 +              desc  = bpf_prog_info_array_desc + i;
 +              count = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
 +              size  = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
 +              bpf_prog_info_set_offset_u32(&info_linear->info,
 +                                           desc->count_offset, count);
 +              bpf_prog_info_set_offset_u32(&info_linear->info,
 +                                           desc->size_offset, size);
 +              bpf_prog_info_set_offset_u64(&info_linear->info,
 +                                           desc->array_offset,
 +                                           ptr_to_u64(ptr));
 +              ptr += count * size;
 +      }
 +
 +      /* step 5: call syscall again to get required arrays */
 +      err = bpf_obj_get_info_by_fd(fd, &info_linear->info, &info_len);
 +      if (err) {
 +              pr_debug("can't get prog info: %s", strerror(errno));
 +              free(info_linear);
 +              return ERR_PTR(-EFAULT);
 +      }
 +
 +      /* step 6: verify the data */
 +      for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
 +              struct bpf_prog_info_array_desc *desc;
 +              __u32 v1, v2;
 +
 +              if ((arrays & (1UL << i)) == 0)
 +                      continue;
 +
 +              desc = bpf_prog_info_array_desc + i;
 +              v1 = bpf_prog_info_read_offset_u32(&info, desc->count_offset);
 +              v2 = bpf_prog_info_read_offset_u32(&info_linear->info,
 +                                                 desc->count_offset);
 +              if (v1 != v2)
 +                      pr_warning("%s: mismatch in element count\n", __func__);
 +
 +              v1 = bpf_prog_info_read_offset_u32(&info, desc->size_offset);
 +              v2 = bpf_prog_info_read_offset_u32(&info_linear->info,
 +                                                 desc->size_offset);
 +              if (v1 != v2)
 +                      pr_warning("%s: mismatch in rec size\n", __func__);
 +      }
 +
 +      /* step 7: update info_len and data_len */
 +      info_linear->info_len = sizeof(struct bpf_prog_info);
 +      info_linear->data_len = data_len;
 +
 +      return info_linear;
 +}
 +
 +void bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear)
 +{
 +      int i;
 +
 +      for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
 +              struct bpf_prog_info_array_desc *desc;
 +              __u64 addr, offs;
 +
 +              if ((info_linear->arrays & (1UL << i)) == 0)
 +                      continue;
 +
 +              desc = bpf_prog_info_array_desc + i;
 +              addr = bpf_prog_info_read_offset_u64(&info_linear->info,
 +                                                   desc->array_offset);
 +              offs = addr - ptr_to_u64(info_linear->data);
 +              bpf_prog_info_set_offset_u64(&info_linear->info,
 +                                           desc->array_offset, offs);
 +      }
 +}
 +
 +void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear)
 +{
 +      int i;
 +
 +      for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) {
 +              struct bpf_prog_info_array_desc *desc;
 +              __u64 addr, offs;
 +
 +              if ((info_linear->arrays & (1UL << i)) == 0)
 +                      continue;
 +
 +              desc = bpf_prog_info_array_desc + i;
 +              offs = bpf_prog_info_read_offset_u64(&info_linear->info,
 +                                                   desc->array_offset);
 +              addr = offs + ptr_to_u64(info_linear->data);
 +              bpf_prog_info_set_offset_u64(&info_linear->info,
 +                                           desc->array_offset, addr);
 +      }
 +}