1. 01 Feb, 2019 11 commits
    • Sandipan Das's avatar
      bpf: powerpc64: add JIT support for bpf line info · 6f20c71d
      Sandipan Das authored
      This adds support for generating bpf line info for
      JITed programs.
      Signed-off-by: default avatarSandipan Das <sandipan@linux.ibm.com>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      6f20c71d
    • Daniel Borkmann's avatar
      Merge branch 'bpf-spinlocks' · 2863debf
      Daniel Borkmann authored
      Alexei Starovoitov says:
      
      ====================
      Many algorithms need to read and modify several variables atomically.
      Until now it was hard to impossible to implement such algorithms in BPF.
      Hence introduce support for bpf_spin_lock.
      
      The api consists of 'struct bpf_spin_lock' that should be placed
      inside hash/array/cgroup_local_storage element
      and bpf_spin_lock/unlock() helper function.
      
      Example:
      struct hash_elem {
          int cnt;
          struct bpf_spin_lock lock;
      };
      struct hash_elem * val = bpf_map_lookup_elem(&hash_map, &key);
      if (val) {
          bpf_spin_lock(&val->lock);
          val->cnt++;
          bpf_spin_unlock(&val->lock);
      }
      
      and BPF_F_LOCK flag for lookup/update bpf syscall commands that
      allows user space to read/write map elements under lock.
      
      Together these primitives allow race free access to map elements
      from bpf programs and from user space.
      
      Key restriction: root only.
      Key requirement: maps must be annotated with BTF.
      
      This concept was discussed at Linux Plumbers Conference 2018.
      Thank you everyone who participated and helped to iron out details
      of api and implementation.
      
      Patch 1: bpf_spin_lock support in the verifier, BTF, hash, array.
      Patch 2: bpf_spin_lock in cgroup local storage.
      Patches 3,4,5: tests
      Patch 6: BPF_F_LOCK flag to lookup/update
      Patches 7,8,9: tests
      
      v6->v7:
      - fixed this_cpu->__this_cpu per Peter's suggestion and added Ack.
      - simplified bpf_spin_lock and load/store overlap check in the verifier
        as suggested by Andrii
      - rebase
      
      v5->v6:
      - adopted arch_spinlock approach suggested by Peter
      - switched to spin_lock_irqsave equivalent as the simplest way
        to avoid deadlocks in rare case of nested networking progs
        (cgroup-bpf prog in preempt_disable vs clsbpf in softirq sharing
        the same map with bpf_spin_lock)
        bpf_spin_lock is only allowed in networking progs that don't
        have arbitrary entry points unlike tracing progs.
      - rebase and split test_verifier tests
      
      v4->v5:
      - disallow bpf_spin_lock for tracing progs due to insufficient preemption checks
      - socket filter progs cannot use bpf_spin_lock due to missing preempt_disable
      - fix atomic_set_release. Spotted by Peter.
      - fixed hash_of_maps
      
      v3->v4:
      - fix BPF_EXIST | BPF_NOEXIST check patch 6. Spotted by Jakub. Thanks!
      - rebase
      
      v2->v3:
      - fixed build on ia64 and archs where qspinlock is not supported
      - fixed missing lock init during lookup w/o BPF_F_LOCK. Spotted by Martin
      
      v1->v2:
      - addressed several issues spotted by Daniel and Martin in patch 1
      - added test11 to patch 4 as suggested by Daniel
      ====================
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      2863debf
    • Alexei Starovoitov's avatar
      selftests/bpf: test for BPF_F_LOCK · ba72a7b4
      Alexei Starovoitov authored
      Add C based test that runs 4 bpf programs in parallel
      that update the same hash and array maps.
      And another 2 threads that read from these two maps
      via lookup(key, value, BPF_F_LOCK) api
      to make sure the user space sees consistent value in both
      hash and array elements while user space races with kernel bpf progs.
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      ba72a7b4
    • Alexei Starovoitov's avatar
      libbpf: introduce bpf_map_lookup_elem_flags() · df5d22fa
      Alexei Starovoitov authored
      Introduce
      int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
      helper to lookup array/hash/cgroup_local_storage elements with BPF_F_LOCK flag.
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      df5d22fa
    • Alexei Starovoitov's avatar
      tools/bpf: sync uapi/bpf.h · e44ac9a2
      Alexei Starovoitov authored
      add BPF_F_LOCK definition to tools/include/uapi/linux/bpf.h
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      e44ac9a2
    • Alexei Starovoitov's avatar
      bpf: introduce BPF_F_LOCK flag · 96049f3a
      Alexei Starovoitov authored
      Introduce BPF_F_LOCK flag for map_lookup and map_update syscall commands
      and for map_update() helper function.
      In all these cases take a lock of existing element (which was provided
      in BTF description) before copying (in or out) the rest of map value.
      
      Implementation details that are part of uapi:
      
      Array:
      The array map takes the element lock for lookup/update.
      
      Hash:
      hash map also takes the lock for lookup/update and tries to avoid the bucket lock.
      If old element exists it takes the element lock and updates the element in place.
      If element doesn't exist it allocates new one and inserts into hash table
      while holding the bucket lock.
      In rare case the hashmap has to take both the bucket lock and the element lock
      to update old value in place.
      
      Cgroup local storage:
      It is similar to array. update in place and lookup are done with lock taken.
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      96049f3a
    • Alexei Starovoitov's avatar
      selftests/bpf: add bpf_spin_lock C test · ab963beb
      Alexei Starovoitov authored
      add bpf_spin_lock C based test that requires latest llvm with BTF support
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      ab963beb
    • Alexei Starovoitov's avatar
      selftests/bpf: add bpf_spin_lock verifier tests · b4d4556c
      Alexei Starovoitov authored
      add bpf_spin_lock tests to test_verifier.c that don't require
      latest llvm with BTF support
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      b4d4556c
    • Alexei Starovoitov's avatar
      tools/bpf: sync include/uapi/linux/bpf.h · 7dac3ae4
      Alexei Starovoitov authored
      sync bpf.h
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      7dac3ae4
    • Alexei Starovoitov's avatar
      bpf: add support for bpf_spin_lock to cgroup local storage · e16d2f1a
      Alexei Starovoitov authored
      Allow 'struct bpf_spin_lock' to reside inside cgroup local storage.
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      e16d2f1a
    • Alexei Starovoitov's avatar
      bpf: introduce bpf_spin_lock · d83525ca
      Alexei Starovoitov authored
      Introduce 'struct bpf_spin_lock' and bpf_spin_lock/unlock() helpers to let
      bpf program serialize access to other variables.
      
      Example:
      struct hash_elem {
          int cnt;
          struct bpf_spin_lock lock;
      };
      struct hash_elem * val = bpf_map_lookup_elem(&hash_map, &key);
      if (val) {
          bpf_spin_lock(&val->lock);
          val->cnt++;
          bpf_spin_unlock(&val->lock);
      }
      
      Restrictions and safety checks:
      - bpf_spin_lock is only allowed inside HASH and ARRAY maps.
      - BTF description of the map is mandatory for safety analysis.
      - bpf program can take one bpf_spin_lock at a time, since two or more can
        cause dead locks.
      - only one 'struct bpf_spin_lock' is allowed per map element.
        It drastically simplifies implementation yet allows bpf program to use
        any number of bpf_spin_locks.
      - when bpf_spin_lock is taken the calls (either bpf2bpf or helpers) are not allowed.
      - bpf program must bpf_spin_unlock() before return.
      - bpf program can access 'struct bpf_spin_lock' only via
        bpf_spin_lock()/bpf_spin_unlock() helpers.
      - load/store into 'struct bpf_spin_lock lock;' field is not allowed.
      - to use bpf_spin_lock() helper the BTF description of map value must be
        a struct and have 'struct bpf_spin_lock anyname;' field at the top level.
        Nested lock inside another struct is not allowed.
      - syscall map_lookup doesn't copy bpf_spin_lock field to user space.
      - syscall map_update and program map_update do not update bpf_spin_lock field.
      - bpf_spin_lock cannot be on the stack or inside networking packet.
        bpf_spin_lock can only be inside HASH or ARRAY map value.
      - bpf_spin_lock is available to root only and to all program types.
      - bpf_spin_lock is not allowed in inner maps of map-in-map.
      - ld_abs is not allowed inside spin_lock-ed region.
      - tracing progs and socket filter progs cannot use bpf_spin_lock due to
        insufficient preemption checks
      
      Implementation details:
      - cgroup-bpf class of programs can nest with xdp/tc programs.
        Hence bpf_spin_lock is equivalent to spin_lock_irqsave.
        Other solutions to avoid nested bpf_spin_lock are possible.
        Like making sure that all networking progs run with softirq disabled.
        spin_lock_irqsave is the simplest and doesn't add overhead to the
        programs that don't use it.
      - arch_spinlock_t is used when its implemented as queued_spin_lock
      - archs can force their own arch_spinlock_t
      - on architectures where queued_spin_lock is not available and
        sizeof(arch_spinlock_t) != sizeof(__u32) trivial lock is used.
      - presence of bpf_spin_lock inside map value could have been indicated via
        extra flag during map_create, but specifying it via BTF is cleaner.
        It provides introspection for map key/value and reduces user mistakes.
      
      Next steps:
      - allow bpf_spin_lock in other map types (like cgroup local storage)
      - introduce BPF_F_LOCK flag for bpf_map_update() syscall and helper
        to request kernel to grab bpf_spin_lock before rewriting the value.
        That will serialize access to map elements.
      Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
      Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
      Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
      d83525ca
  2. 31 Jan, 2019 9 commits
  3. 30 Jan, 2019 20 commits