bpf: Add bpf_trampoline_ name prefix for DECLARE_BPF_DISPATCHER
[linux-2.6-microblaze.git] / include / linux / bpf.h
index 085a59a..fe1f8b0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/u64_stats_sync.h>
 #include <linux/refcount.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 
 struct bpf_verifier_env;
 struct bpf_verifier_log;
@@ -43,6 +44,15 @@ struct bpf_map_ops {
        int (*map_get_next_key)(struct bpf_map *map, void *key, void *next_key);
        void (*map_release_uref)(struct bpf_map *map);
        void *(*map_lookup_elem_sys_only)(struct bpf_map *map, void *key);
+       int (*map_lookup_batch)(struct bpf_map *map, const union bpf_attr *attr,
+                               union bpf_attr __user *uattr);
+       int (*map_lookup_and_delete_batch)(struct bpf_map *map,
+                                          const union bpf_attr *attr,
+                                          union bpf_attr __user *uattr);
+       int (*map_update_batch)(struct bpf_map *map, const union bpf_attr *attr,
+                               union bpf_attr __user *uattr);
+       int (*map_delete_batch)(struct bpf_map *map, const union bpf_attr *attr,
+                               union bpf_attr __user *uattr);
 
        /* funcs callable from userspace and from eBPF programs */
        void *(*map_lookup_elem)(struct bpf_map *map, void *key);
@@ -106,6 +116,7 @@ struct bpf_map {
        struct btf *btf;
        struct bpf_map_memory memory;
        char name[BPF_OBJ_NAME_LEN];
+       u32 btf_vmlinux_value_type_id;
        bool unpriv_array;
        bool frozen; /* write-once; write-protected by freeze_mutex */
        /* 22 bytes hole */
@@ -183,7 +194,8 @@ static inline bool bpf_map_offload_neutral(const struct bpf_map *map)
 
 static inline bool bpf_map_support_seq_show(const struct bpf_map *map)
 {
-       return map->btf && map->ops->map_seq_show_elem;
+       return (map->btf_value_type_id || map->btf_vmlinux_value_type_id) &&
+               map->ops->map_seq_show_elem;
 }
 
 int map_check_no_btf(const struct bpf_map *map,
@@ -349,6 +361,10 @@ struct bpf_verifier_ops {
                                  const struct bpf_insn *src,
                                  struct bpf_insn *dst,
                                  struct bpf_prog *prog, u32 *target_size);
+       int (*btf_struct_access)(struct bpf_verifier_log *log,
+                                const struct btf_type *t, int off, int size,
+                                enum bpf_access_type atype,
+                                u32 *next_btf_id);
 };
 
 struct bpf_prog_offload_ops {
@@ -417,6 +433,16 @@ struct btf_func_model {
  */
 #define BPF_TRAMP_F_SKIP_FRAME         BIT(2)
 
+/* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50
+ * bytes on x86.  Pick a number to fit into BPF_IMAGE_SIZE / 2
+ */
+#define BPF_MAX_TRAMP_PROGS 40
+
+struct bpf_tramp_progs {
+       struct bpf_prog *progs[BPF_MAX_TRAMP_PROGS];
+       int nr_progs;
+};
+
 /* Different use cases for BPF trampoline:
  * 1. replace nop at the function entry (kprobe equivalent)
  *    flags = BPF_TRAMP_F_RESTORE_REGS
@@ -437,9 +463,9 @@ struct btf_func_model {
  *      fentry = a set of program to run before calling original function
  *      fexit = a set of program to run after original function
  */
-int arch_prepare_bpf_trampoline(void *image, struct btf_func_model *m, u32 flags,
-                               struct bpf_prog **fentry_progs, int fentry_cnt,
-                               struct bpf_prog **fexit_progs, int fexit_cnt,
+int arch_prepare_bpf_trampoline(void *image, void *image_end,
+                               const struct btf_func_model *m, u32 flags,
+                               struct bpf_tramp_progs *tprogs,
                                void *orig_call);
 /* these two functions are called from generated trampoline */
 u64 notrace __bpf_prog_enter(void);
@@ -448,7 +474,9 @@ void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start);
 enum bpf_tramp_prog_type {
        BPF_TRAMP_FENTRY,
        BPF_TRAMP_FEXIT,
-       BPF_TRAMP_MAX
+       BPF_TRAMP_MODIFY_RETURN,
+       BPF_TRAMP_MAX,
+       BPF_TRAMP_REPLACE, /* more than MAX */
 };
 
 struct bpf_trampoline {
@@ -463,6 +491,11 @@ struct bpf_trampoline {
                void *addr;
                bool ftrace_managed;
        } func;
+       /* if !NULL this is BPF_PROG_TYPE_EXT program that extends another BPF
+        * program by replacing one of its functions. func.addr is the address
+        * of the function it replaced.
+        */
+       struct bpf_prog *extension_prog;
        /* list of BPF programs using this trampoline */
        struct hlist_head progs_hlist[BPF_TRAMP_MAX];
        /* Number of attached programs. A counter per kind. */
@@ -471,11 +504,76 @@ struct bpf_trampoline {
        void *image;
        u64 selector;
 };
+
+#define BPF_DISPATCHER_MAX 48 /* Fits in 2048B */
+
+struct bpf_dispatcher_prog {
+       struct bpf_prog *prog;
+       refcount_t users;
+};
+
+struct bpf_dispatcher {
+       /* dispatcher mutex */
+       struct mutex mutex;
+       void *func;
+       struct bpf_dispatcher_prog progs[BPF_DISPATCHER_MAX];
+       int num_progs;
+       void *image;
+       u32 image_off;
+};
+
+static __always_inline unsigned int bpf_dispatcher_nop_func(
+       const void *ctx,
+       const struct bpf_insn *insnsi,
+       unsigned int (*bpf_func)(const void *,
+                                const struct bpf_insn *))
+{
+       return bpf_func(ctx, insnsi);
+}
 #ifdef CONFIG_BPF_JIT
 struct bpf_trampoline *bpf_trampoline_lookup(u64 key);
 int bpf_trampoline_link_prog(struct bpf_prog *prog);
 int bpf_trampoline_unlink_prog(struct bpf_prog *prog);
 void bpf_trampoline_put(struct bpf_trampoline *tr);
+#define BPF_DISPATCHER_INIT(name) {                    \
+       .mutex = __MUTEX_INITIALIZER(name.mutex),       \
+       .func = &name##_func,                           \
+       .progs = {},                                    \
+       .num_progs = 0,                                 \
+       .image = NULL,                                  \
+       .image_off = 0                                  \
+}
+
+#define DEFINE_BPF_DISPATCHER(name)                                    \
+       noinline unsigned int bpf_dispatcher_##name##_func(             \
+               const void *ctx,                                        \
+               const struct bpf_insn *insnsi,                          \
+               unsigned int (*bpf_func)(const void *,                  \
+                                        const struct bpf_insn *))      \
+       {                                                               \
+               return bpf_func(ctx, insnsi);                           \
+       }                                                               \
+       EXPORT_SYMBOL(bpf_dispatcher_##name##_func);                    \
+       struct bpf_dispatcher bpf_dispatcher_##name =                   \
+               BPF_DISPATCHER_INIT(bpf_dispatcher_##name);
+#define DECLARE_BPF_DISPATCHER(name)                                   \
+       unsigned int bpf_dispatcher_##name##_func(                      \
+               const void *ctx,                                        \
+               const struct bpf_insn *insnsi,                          \
+               unsigned int (*bpf_func)(const void *,                  \
+                                        const struct bpf_insn *));     \
+       extern struct bpf_dispatcher bpf_dispatcher_##name;
+#define BPF_DISPATCHER_FUNC(name) bpf_dispatcher_##name##_func
+#define BPF_DISPATCHER_PTR(name) (&bpf_dispatcher_##name)
+void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from,
+                               struct bpf_prog *to);
+struct bpf_image {
+       struct latch_tree_node tnode;
+       unsigned char data[];
+};
+#define BPF_IMAGE_SIZE (PAGE_SIZE - sizeof(struct bpf_image))
+bool is_bpf_image_address(unsigned long address);
+void *bpf_image_alloc(void);
 #else
 static inline struct bpf_trampoline *bpf_trampoline_lookup(u64 key)
 {
@@ -490,9 +588,21 @@ static inline int bpf_trampoline_unlink_prog(struct bpf_prog *prog)
        return -ENOTSUPP;
 }
 static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {}
+#define DEFINE_BPF_DISPATCHER(name)
+#define DECLARE_BPF_DISPATCHER(name)
+#define BPF_DISPATCHER_FUNC(name) bpf_dispatcher_nop_func
+#define BPF_DISPATCHER_PTR(name) NULL
+static inline void bpf_dispatcher_change_prog(struct bpf_dispatcher *d,
+                                             struct bpf_prog *from,
+                                             struct bpf_prog *to) {}
+static inline bool is_bpf_image_address(unsigned long address)
+{
+       return false;
+}
 #endif
 
 struct bpf_func_info_aux {
+       u16 linkage;
        bool unreliable;
 };
 
@@ -603,6 +713,76 @@ struct bpf_array_aux {
        struct work_struct work;
 };
 
+struct bpf_struct_ops_value;
+struct btf_type;
+struct btf_member;
+
+#define BPF_STRUCT_OPS_MAX_NR_MEMBERS 64
+struct bpf_struct_ops {
+       const struct bpf_verifier_ops *verifier_ops;
+       int (*init)(struct btf *btf);
+       int (*check_member)(const struct btf_type *t,
+                           const struct btf_member *member);
+       int (*init_member)(const struct btf_type *t,
+                          const struct btf_member *member,
+                          void *kdata, const void *udata);
+       int (*reg)(void *kdata);
+       void (*unreg)(void *kdata);
+       const struct btf_type *type;
+       const struct btf_type *value_type;
+       const char *name;
+       struct btf_func_model func_models[BPF_STRUCT_OPS_MAX_NR_MEMBERS];
+       u32 type_id;
+       u32 value_id;
+};
+
+#if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL)
+#define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA))
+const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id);
+void bpf_struct_ops_init(struct btf *btf, struct bpf_verifier_log *log);
+bool bpf_struct_ops_get(const void *kdata);
+void bpf_struct_ops_put(const void *kdata);
+int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key,
+                                      void *value);
+static inline bool bpf_try_module_get(const void *data, struct module *owner)
+{
+       if (owner == BPF_MODULE_OWNER)
+               return bpf_struct_ops_get(data);
+       else
+               return try_module_get(owner);
+}
+static inline void bpf_module_put(const void *data, struct module *owner)
+{
+       if (owner == BPF_MODULE_OWNER)
+               bpf_struct_ops_put(data);
+       else
+               module_put(owner);
+}
+#else
+static inline const struct bpf_struct_ops *bpf_struct_ops_find(u32 type_id)
+{
+       return NULL;
+}
+static inline void bpf_struct_ops_init(struct btf *btf,
+                                      struct bpf_verifier_log *log)
+{
+}
+static inline bool bpf_try_module_get(const void *data, struct module *owner)
+{
+       return try_module_get(owner);
+}
+static inline void bpf_module_put(const void *data, struct module *owner)
+{
+       module_put(owner);
+}
+static inline int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map,
+                                                    void *key,
+                                                    void *value)
+{
+       return -EINVAL;
+}
+#endif
+
 struct bpf_array {
        struct bpf_map map;
        u32 elem_size;
@@ -690,7 +870,7 @@ struct bpf_prog_array_item {
 
 struct bpf_prog_array {
        struct rcu_head rcu;
-       struct bpf_prog_array_item items[0];
+       struct bpf_prog_array_item items[];
 };
 
 struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags);
@@ -716,7 +896,7 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array,
                struct bpf_prog *_prog;                 \
                struct bpf_prog_array *_array;          \
                u32 _ret = 1;                           \
-               preempt_disable();                      \
+               migrate_disable();                      \
                rcu_read_lock();                        \
                _array = rcu_dereference(array);        \
                if (unlikely(check_non_null && !_array))\
@@ -729,7 +909,7 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array,
                }                                       \
 _out:                                                  \
                rcu_read_unlock();                      \
-               preempt_enable();                       \
+               migrate_enable();                       \
                _ret;                                   \
         })
 
@@ -763,7 +943,7 @@ _out:                                                       \
                u32 ret;                                \
                u32 _ret = 1;                           \
                u32 _cn = 0;                            \
-               preempt_disable();                      \
+               migrate_disable();                      \
                rcu_read_lock();                        \
                _array = rcu_dereference(array);        \
                _item = &_array->items[0];              \
@@ -775,7 +955,7 @@ _out:                                                       \
                        _item++;                        \
                }                                       \
                rcu_read_unlock();                      \
-               preempt_enable();                       \
+               migrate_enable();                       \
                if (_ret)                               \
                        _ret = (_cn ? NET_XMIT_CN : NET_XMIT_SUCCESS);  \
                else                                    \
@@ -792,6 +972,36 @@ _out:                                                      \
 #ifdef CONFIG_BPF_SYSCALL
 DECLARE_PER_CPU(int, bpf_prog_active);
 
+/*
+ * Block execution of BPF programs attached to instrumentation (perf,
+ * kprobes, tracepoints) to prevent deadlocks on map operations as any of
+ * these events can happen inside a region which holds a map bucket lock
+ * and can deadlock on it.
+ *
+ * Use the preemption safe inc/dec variants on RT because migrate disable
+ * is preemptible on RT and preemption in the middle of the RMW operation
+ * might lead to inconsistent state. Use the raw variants for non RT
+ * kernels as migrate_disable() maps to preempt_disable() so the slightly
+ * more expensive save operation can be avoided.
+ */
+static inline void bpf_disable_instrumentation(void)
+{
+       migrate_disable();
+       if (IS_ENABLED(CONFIG_PREEMPT_RT))
+               this_cpu_inc(bpf_prog_active);
+       else
+               __this_cpu_inc(bpf_prog_active);
+}
+
+static inline void bpf_enable_instrumentation(void)
+{
+       if (IS_ENABLED(CONFIG_PREEMPT_RT))
+               this_cpu_dec(bpf_prog_active);
+       else
+               __this_cpu_dec(bpf_prog_active);
+       migrate_enable();
+}
+
 extern const struct file_operations bpf_map_fops;
 extern const struct file_operations bpf_prog_fops;
 
@@ -824,6 +1034,7 @@ void __bpf_free_used_maps(struct bpf_prog_aux *aux,
 void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
 void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock);
 
+struct bpf_map *bpf_map_get(u32 ufd);
 struct bpf_map *bpf_map_get_with_uref(u32 ufd);
 struct bpf_map *__bpf_map_get(struct fd f);
 void bpf_map_inc(struct bpf_map *map);
@@ -841,12 +1052,36 @@ void *bpf_map_area_alloc(u64 size, int numa_node);
 void *bpf_map_area_mmapable_alloc(u64 size, int numa_node);
 void bpf_map_area_free(void *base);
 void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
+int  generic_map_lookup_batch(struct bpf_map *map,
+                             const union bpf_attr *attr,
+                             union bpf_attr __user *uattr);
+int  generic_map_update_batch(struct bpf_map *map,
+                             const union bpf_attr *attr,
+                             union bpf_attr __user *uattr);
+int  generic_map_delete_batch(struct bpf_map *map,
+                             const union bpf_attr *attr,
+                             union bpf_attr __user *uattr);
 
 extern int sysctl_unprivileged_bpf_disabled;
 
 int bpf_map_new_fd(struct bpf_map *map, int flags);
 int bpf_prog_new_fd(struct bpf_prog *prog);
 
+struct bpf_link;
+
+struct bpf_link_ops {
+       void (*release)(struct bpf_link *link);
+       void (*dealloc)(struct bpf_link *link);
+};
+
+void bpf_link_init(struct bpf_link *link, const struct bpf_link_ops *ops,
+                  struct bpf_prog *prog);
+void bpf_link_inc(struct bpf_link *link);
+void bpf_link_put(struct bpf_link *link);
+int bpf_link_new_fd(struct bpf_link *link);
+struct file *bpf_link_new_file(struct bpf_link *link, int *reserved_fd);
+struct bpf_link *bpf_link_get_from_fd(u32 ufd);
+
 int bpf_obj_pin_user(u32 ufd, const char __user *pathname);
 int bpf_obj_get_user(const char __user *pathname, int flags);
 
@@ -897,14 +1132,16 @@ struct sk_buff;
 
 struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key);
 struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key);
-void __dev_map_flush(struct bpf_map *map);
+void __dev_flush(void);
+int dev_xdp_enqueue(struct net_device *dev, struct xdp_buff *xdp,
+                   struct net_device *dev_rx);
 int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
                    struct net_device *dev_rx);
 int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
                             struct bpf_prog *xdp_prog);
 
 struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key);
-void __cpu_map_flush(struct bpf_map *map);
+void __cpu_map_flush(void);
 int cpu_map_enqueue(struct bpf_cpu_map_entry *rcpu, struct xdp_buff *xdp,
                    struct net_device *dev_rx);
 
@@ -922,6 +1159,9 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr,
                          union bpf_attr __user *uattr);
 int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
                          union bpf_attr __user *uattr);
+int bpf_prog_test_run_tracing(struct bpf_prog *prog,
+                             const union bpf_attr *kattr,
+                             union bpf_attr __user *uattr);
 int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
                                     const union bpf_attr *kattr,
                                     union bpf_attr __user *uattr);
@@ -941,7 +1181,15 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
                           const char *func_name,
                           struct btf_func_model *m);
 
-int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog);
+struct bpf_reg_state;
+int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
+                            struct bpf_reg_state *regs);
+int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog,
+                         struct bpf_reg_state *reg);
+int btf_check_type_match(struct bpf_verifier_env *env, struct bpf_prog *prog,
+                        struct btf *btf, const struct btf_type *t);
+
+struct bpf_prog *bpf_prog_by_id(u32 id);
 
 #else /* !CONFIG_BPF_SYSCALL */
 static inline struct bpf_prog *bpf_prog_get(u32 ufd)
@@ -1004,13 +1252,20 @@ static inline struct net_device  *__dev_map_hash_lookup_elem(struct bpf_map *map
        return NULL;
 }
 
-static inline void __dev_map_flush(struct bpf_map *map)
+static inline void __dev_flush(void)
 {
 }
 
 struct xdp_buff;
 struct bpf_dtab_netdev;
 
+static inline
+int dev_xdp_enqueue(struct net_device *dev, struct xdp_buff *xdp,
+                   struct net_device *dev_rx)
+{
+       return 0;
+}
+
 static inline
 int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
                    struct net_device *dev_rx)
@@ -1033,7 +1288,7 @@ struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key)
        return NULL;
 }
 
-static inline void __cpu_map_flush(struct bpf_map *map)
+static inline void __cpu_map_flush(void)
 {
 }
 
@@ -1064,6 +1319,13 @@ static inline int bpf_prog_test_run_skb(struct bpf_prog *prog,
        return -ENOTSUPP;
 }
 
+static inline int bpf_prog_test_run_tracing(struct bpf_prog *prog,
+                                           const union bpf_attr *kattr,
+                                           union bpf_attr __user *uattr)
+{
+       return -ENOTSUPP;
+}
+
 static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
                                                   const union bpf_attr *kattr,
                                                   union bpf_attr __user *uattr)
@@ -1074,6 +1336,11 @@ static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
 static inline void bpf_map_put(struct bpf_map *map)
 {
 }
+
+static inline struct bpf_prog *bpf_prog_by_id(u32 id)
+{
+       return ERR_PTR(-ENOTSUPP);
+}
 #endif /* CONFIG_BPF_SYSCALL */
 
 static inline struct bpf_prog *bpf_prog_get_type(u32 ufd,
@@ -1155,6 +1422,8 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
 #if defined(CONFIG_BPF_STREAM_PARSER)
 int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which);
 int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
+void sock_map_unhash(struct sock *sk);
+void sock_map_close(struct sock *sk, long timeout);
 #else
 static inline int sock_map_prog_update(struct bpf_map *map,
                                       struct bpf_prog *prog, u32 which)
@@ -1167,7 +1436,7 @@ static inline int sock_map_get_from_fd(const union bpf_attr *attr,
 {
        return -EINVAL;
 }
-#endif
+#endif /* CONFIG_BPF_STREAM_PARSER */
 
 #if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)
 void bpf_sk_reuseport_detach(struct sock *sk);
@@ -1227,6 +1496,8 @@ extern const struct bpf_func_proto bpf_get_local_storage_proto;
 extern const struct bpf_func_proto bpf_strtol_proto;
 extern const struct bpf_func_proto bpf_strtoul_proto;
 extern const struct bpf_func_proto bpf_tcp_sock_proto;
+extern const struct bpf_func_proto bpf_jiffies64_proto;
+extern const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto;
 
 /* Shared helpers among cBPF and eBPF. */
 void bpf_user_rnd_init_once(void);