Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/include/linux/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 115 kB image not shown  

Quelle  bpf.h   Sprache: C

 
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
 */

#ifndef _LINUX_BPF_H
#define _LINUX_BPF_H 1

#include <uapi/linux/bpf.h>
#include <uapi/linux/filter.h>

#include <linux/workqueue.h>
#include <linux/file.h>
#include <linux/percpu.h>
#include <linux/err.h>
#include <linux/rbtree_latch.h>
#include <linux/numa.h>
#include <linux/mm_types.h>
#include <linux/wait.h>
#include <linux/refcount.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/capability.h>
#include <linux/sched/mm.h>
#include <linux/slab.h>
#include <linux/percpu-refcount.h>
#include <linux/stddef.h>
#include <linux/bpfptr.h>
#include <linux/btf.h>
#include <linux/rcupdate_trace.h>
#include <linux/static_call.h>
#include <linux/memcontrol.h>
#include <linux/cfi.h>
#include <asm/rqspinlock.h>

struct bpf_verifier_env;
struct bpf_verifier_log;
struct perf_event;
struct bpf_prog;
struct bpf_prog_aux;
struct bpf_map;
struct bpf_arena;
struct sock;
struct seq_file;
struct btf;
struct btf_type;
struct exception_table_entry;
struct seq_operations;
struct bpf_iter_aux_info;
struct bpf_local_storage;
struct bpf_local_storage_map;
struct kobject;
struct mem_cgroup;
struct module;
struct bpf_func_state;
struct ftrace_ops;
struct cgroup;
struct bpf_token;
struct user_namespace;
struct super_block;
struct inode;

extern struct idr btf_idr;
extern spinlock_t btf_idr_lock;
extern struct kobject *btf_kobj;
extern struct bpf_mem_alloc bpf_global_ma, bpf_global_percpu_ma;
extern bool bpf_global_ma_set;

typedef u64 (*bpf_callback_t)(u64, u64, u64, u64, u64);
typedef int (*bpf_iter_init_seq_priv_t)(void *private_data,
     struct bpf_iter_aux_info *aux);
typedef void (*bpf_iter_fini_seq_priv_t)(void *private_data);
typedef unsigned int (*bpf_func_t)(const void *,
       const struct bpf_insn *);
struct bpf_iter_seq_info {
 const struct seq_operations *seq_ops;
 bpf_iter_init_seq_priv_t init_seq_private;
 bpf_iter_fini_seq_priv_t fini_seq_private;
 u32 seq_priv_size;
};

/* map is generic key/value storage optionally accessible by eBPF programs */
struct bpf_map_ops {
 /* funcs callable from userspace (via syscall) */
 int (*map_alloc_check)(union bpf_attr *attr);
 struct bpf_map *(*map_alloc)(union bpf_attr *attr);
 void (*map_release)(struct bpf_map *map, struct file *map_file);
 void (*map_free)(struct bpf_map *map);
 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_elem)(struct bpf_map *map, void *key,
       void *value, u64 flags);
 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, struct file *map_file,
    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);
 long (*map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags);
 long (*map_delete_elem)(struct bpf_map *map, void *key);
 long (*map_push_elem)(struct bpf_map *map, void *value, u64 flags);
 long (*map_pop_elem)(struct bpf_map *map, void *value);
 long (*map_peek_elem)(struct bpf_map *map, void *value);
 void *(*map_lookup_percpu_elem)(struct bpf_map *map, void *key, u32 cpu);

 /* funcs called by prog_array and perf_event_array map */
 void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file,
    int fd);
 /* If need_defer is true, the implementation should guarantee that
 * the to-be-put element is still alive before the bpf program, which
 * may manipulate it, exists.
 */

 void (*map_fd_put_ptr)(struct bpf_map *map, void *ptr, bool need_defer);
 int (*map_gen_lookup)(struct bpf_map *map, struct bpf_insn *insn_buf);
 u32 (*map_fd_sys_lookup_elem)(void *ptr);
 void (*map_seq_show_elem)(struct bpf_map *map, void *key,
      struct seq_file *m);
 int (*map_check_btf)(const struct bpf_map *map,
        const struct btf *btf,
        const struct btf_type *key_type,
        const struct btf_type *value_type);

 /* Prog poke tracking helpers. */
 int (*map_poke_track)(struct bpf_map *map, struct bpf_prog_aux *aux);
 void (*map_poke_untrack)(struct bpf_map *map, struct bpf_prog_aux *aux);
 void (*map_poke_run)(struct bpf_map *map, u32 key, struct bpf_prog *old,
        struct bpf_prog *new);

 /* Direct value access helpers. */
 int (*map_direct_value_addr)(const struct bpf_map *map,
         u64 *imm, u32 off);
 int (*map_direct_value_meta)(const struct bpf_map *map,
         u64 imm, u32 *off);
 int (*map_mmap)(struct bpf_map *map, struct vm_area_struct *vma);
 __poll_t (*map_poll)(struct bpf_map *map, struct file *filp,
        struct poll_table_struct *pts);
 unsigned long (*map_get_unmapped_area)(struct file *filep, unsigned long addr,
            unsigned long len, unsigned long pgoff,
            unsigned long flags);

 /* Functions called by bpf_local_storage maps */
 int (*map_local_storage_charge)(struct bpf_local_storage_map *smap,
     void *owner, u32 size);
 void (*map_local_storage_uncharge)(struct bpf_local_storage_map *smap,
        void *owner, u32 size);
 struct bpf_local_storage __rcu ** (*map_owner_storage_ptr)(void *owner);

 /* Misc helpers.*/
 long (*map_redirect)(struct bpf_map *map, u64 key, u64 flags);

 /* map_meta_equal must be implemented for maps that can be
 * used as an inner map.  It is a runtime check to ensure
 * an inner map can be inserted to an outer map.
 *
 * Some properties of the inner map has been used during the
 * verification time.  When inserting an inner map at the runtime,
 * map_meta_equal has to ensure the inserting map has the same
 * properties that the verifier has used earlier.
 */

 bool (*map_meta_equal)(const struct bpf_map *meta0,
          const struct bpf_map *meta1);


 int (*map_set_for_each_callback_args)(struct bpf_verifier_env *env,
           struct bpf_func_state *caller,
           struct bpf_func_state *callee);
 long (*map_for_each_callback)(struct bpf_map *map,
         bpf_callback_t callback_fn,
         void *callback_ctx, u64 flags);

 u64 (*map_mem_usage)(const struct bpf_map *map);

 /* BTF id of struct allocated by map_alloc */
 int *map_btf_id;

 /* bpf_iter info used to open a seq_file */
 const struct bpf_iter_seq_info *iter_seq_info;
};

enum {
 /* Support at most 11 fields in a BTF type */
 BTF_FIELDS_MAX    = 11,
};

enum btf_field_type {
 BPF_SPIN_LOCK  = (1 << 0),
 BPF_TIMER      = (1 << 1),
 BPF_KPTR_UNREF = (1 << 2),
 BPF_KPTR_REF   = (1 << 3),
 BPF_KPTR_PERCPU = (1 << 4),
 BPF_KPTR       = BPF_KPTR_UNREF | BPF_KPTR_REF | BPF_KPTR_PERCPU,
 BPF_LIST_HEAD  = (1 << 5),
 BPF_LIST_NODE  = (1 << 6),
 BPF_RB_ROOT    = (1 << 7),
 BPF_RB_NODE    = (1 << 8),
 BPF_GRAPH_NODE = BPF_RB_NODE | BPF_LIST_NODE,
 BPF_GRAPH_ROOT = BPF_RB_ROOT | BPF_LIST_HEAD,
 BPF_REFCOUNT   = (1 << 9),
 BPF_WORKQUEUE  = (1 << 10),
 BPF_UPTR       = (1 << 11),
 BPF_RES_SPIN_LOCK = (1 << 12),
};

enum bpf_cgroup_storage_type {
 BPF_CGROUP_STORAGE_SHARED,
 BPF_CGROUP_STORAGE_PERCPU,
 __BPF_CGROUP_STORAGE_MAX
#define MAX_BPF_CGROUP_STORAGE_TYPE __BPF_CGROUP_STORAGE_MAX
};

#ifdef CONFIG_CGROUP_BPF
define for_each_cgroup_storage_type(stype) \
 for (stype = 0; stype < MAX_BPF_CGROUP_STORAGE_TYPE; stype++)
#else
define for_each_cgroup_storage_type(stype) for (; false; )
#endif /* CONFIG_CGROUP_BPF */

typedef void (*btf_dtor_kfunc_t)(void *);

struct btf_field_kptr {
 struct btf *btf;
 struct module *module;
 /* dtor used if btf_is_kernel(btf), otherwise the type is
 * program-allocated, dtor is NULL,  and __bpf_obj_drop_impl is used
 */

 btf_dtor_kfunc_t dtor;
 u32 btf_id;
};

struct btf_field_graph_root {
 struct btf *btf;
 u32 value_btf_id;
 u32 node_offset;
 struct btf_record *value_rec;
};

struct btf_field {
 u32 offset;
 u32 size;
 enum btf_field_type type;
 union {
  struct btf_field_kptr kptr;
  struct btf_field_graph_root graph_root;
 };
};

struct btf_record {
 u32 cnt;
 u32 field_mask;
 int spin_lock_off;
 int res_spin_lock_off;
 int timer_off;
 int wq_off;
 int refcount_off;
 struct btf_field fields[];
};

/* Non-opaque version of bpf_rb_node in uapi/linux/bpf.h */
struct bpf_rb_node_kern {
 struct rb_node rb_node;
 void *owner;
} __attribute__((aligned(8)));

/* Non-opaque version of bpf_list_node in uapi/linux/bpf.h */
struct bpf_list_node_kern {
 struct list_head list_head;
 void *owner;
} __attribute__((aligned(8)));

/* 'Ownership' of program-containing map is claimed by the first program
 * that is going to use this map or by the first program which FD is
 * stored in the map to make sure that all callers and callees have the
 * same prog type, JITed flag and xdp_has_frags flag.
 */

struct bpf_map_owner {
 enum bpf_prog_type type;
 bool jited;
 bool xdp_has_frags;
 u64 storage_cookie[MAX_BPF_CGROUP_STORAGE_TYPE];
 const struct btf_type *attach_func_proto;
 enum bpf_attach_type expected_attach_type;
};

struct bpf_map {
 const struct bpf_map_ops *ops;
 struct bpf_map *inner_map_meta;
#ifdef CONFIG_SECURITY
 void *security;
#endif
 enum bpf_map_type map_type;
 u32 key_size;
 u32 value_size;
 u32 max_entries;
 u64 map_extra; /* any per-map-type extra fields */
 u32 map_flags;
 u32 id;
 struct btf_record *record;
 int numa_node;
 u32 btf_key_type_id;
 u32 btf_value_type_id;
 u32 btf_vmlinux_value_type_id;
 struct btf *btf;
#ifdef CONFIG_MEMCG
 struct obj_cgroup *objcg;
#endif
 char name[BPF_OBJ_NAME_LEN];
 struct mutex freeze_mutex;
 atomic64_t refcnt;
 atomic64_t usercnt;
 /* rcu is used before freeing and work is only used during freeing */
 union {
  struct work_struct work;
  struct rcu_head rcu;
 };
 atomic64_t writecnt;
 spinlock_t owner_lock;
 struct bpf_map_owner *owner;
 bool bypass_spec_v1;
 bool frozen; /* write-once; write-protected by freeze_mutex */
 bool free_after_mult_rcu_gp;
 bool free_after_rcu_gp;
 atomic64_t sleepable_refcnt;
 s64 __percpu *elem_count;
 u64 cookie; /* write-once */
};

static inline const char *btf_field_type_name(enum btf_field_type type)
{
 switch (type) {
 case BPF_SPIN_LOCK:
  return "bpf_spin_lock";
 case BPF_RES_SPIN_LOCK:
  return "bpf_res_spin_lock";
 case BPF_TIMER:
  return "bpf_timer";
 case BPF_WORKQUEUE:
  return "bpf_wq";
 case BPF_KPTR_UNREF:
 case BPF_KPTR_REF:
  return "kptr";
 case BPF_KPTR_PERCPU:
  return "percpu_kptr";
 case BPF_UPTR:
  return "uptr";
 case BPF_LIST_HEAD:
  return "bpf_list_head";
 case BPF_LIST_NODE:
  return "bpf_list_node";
 case BPF_RB_ROOT:
  return "bpf_rb_root";
 case BPF_RB_NODE:
  return "bpf_rb_node";
 case BPF_REFCOUNT:
  return "bpf_refcount";
 default:
  WARN_ON_ONCE(1);
  return "unknown";
 }
}

#if IS_ENABLED(CONFIG_DEBUG_KERNEL)
#define BPF_WARN_ONCE(cond, format...) WARN_ONCE(cond, format)
#else
#define BPF_WARN_ONCE(cond, format...) BUILD_BUG_ON_INVALID(cond)
#endif

static inline u32 btf_field_type_size(enum btf_field_type type)
{
 switch (type) {
 case BPF_SPIN_LOCK:
  return sizeof(struct bpf_spin_lock);
 case BPF_RES_SPIN_LOCK:
  return sizeof(struct bpf_res_spin_lock);
 case BPF_TIMER:
  return sizeof(struct bpf_timer);
 case BPF_WORKQUEUE:
  return sizeof(struct bpf_wq);
 case BPF_KPTR_UNREF:
 case BPF_KPTR_REF:
 case BPF_KPTR_PERCPU:
 case BPF_UPTR:
  return sizeof(u64);
 case BPF_LIST_HEAD:
  return sizeof(struct bpf_list_head);
 case BPF_LIST_NODE:
  return sizeof(struct bpf_list_node);
 case BPF_RB_ROOT:
  return sizeof(struct bpf_rb_root);
 case BPF_RB_NODE:
  return sizeof(struct bpf_rb_node);
 case BPF_REFCOUNT:
  return sizeof(struct bpf_refcount);
 default:
  WARN_ON_ONCE(1);
  return 0;
 }
}

static inline u32 btf_field_type_align(enum btf_field_type type)
{
 switch (type) {
 case BPF_SPIN_LOCK:
  return __alignof__(struct bpf_spin_lock);
 case BPF_RES_SPIN_LOCK:
  return __alignof__(struct bpf_res_spin_lock);
 case BPF_TIMER:
  return __alignof__(struct bpf_timer);
 case BPF_WORKQUEUE:
  return __alignof__(struct bpf_wq);
 case BPF_KPTR_UNREF:
 case BPF_KPTR_REF:
 case BPF_KPTR_PERCPU:
 case BPF_UPTR:
  return __alignof__(u64);
 case BPF_LIST_HEAD:
  return __alignof__(struct bpf_list_head);
 case BPF_LIST_NODE:
  return __alignof__(struct bpf_list_node);
 case BPF_RB_ROOT:
  return __alignof__(struct bpf_rb_root);
 case BPF_RB_NODE:
  return __alignof__(struct bpf_rb_node);
 case BPF_REFCOUNT:
  return __alignof__(struct bpf_refcount);
 default:
  WARN_ON_ONCE(1);
  return 0;
 }
}

static inline void bpf_obj_init_field(const struct btf_field *field, void *addr)
{
 memset(addr, 0, field->size);

 switch (field->type) {
 case BPF_REFCOUNT:
  refcount_set((refcount_t *)addr, 1);
  break;
 case BPF_RB_NODE:
  RB_CLEAR_NODE((struct rb_node *)addr);
  break;
 case BPF_LIST_HEAD:
 case BPF_LIST_NODE:
  INIT_LIST_HEAD((struct list_head *)addr);
  break;
 case BPF_RB_ROOT:
  /* RB_ROOT_CACHED 0-inits, no need to do anything after memset */
 case BPF_SPIN_LOCK:
 case BPF_RES_SPIN_LOCK:
 case BPF_TIMER:
 case BPF_WORKQUEUE:
 case BPF_KPTR_UNREF:
 case BPF_KPTR_REF:
 case BPF_KPTR_PERCPU:
 case BPF_UPTR:
  break;
 default:
  WARN_ON_ONCE(1);
  return;
 }
}

static inline bool btf_record_has_field(const struct btf_record *rec, enum btf_field_type type)
{
 if (IS_ERR_OR_NULL(rec))
  return false;
 return rec->field_mask & type;
}

static inline void bpf_obj_init(const struct btf_record *rec, void *obj)
{
 int i;

 if (IS_ERR_OR_NULL(rec))
  return;
 for (i = 0; i < rec->cnt; i++)
  bpf_obj_init_field(&rec->fields[i], obj + rec->fields[i].offset);
}

/* 'dst' must be a temporary buffer and should not point to memory that is being
 * used in parallel by a bpf program or bpf syscall, otherwise the access from
 * the bpf program or bpf syscall may be corrupted by the reinitialization,
 * leading to weird problems. Even 'dst' is newly-allocated from bpf memory
 * allocator, it is still possible for 'dst' to be used in parallel by a bpf
 * program or bpf syscall.
 */

static inline void check_and_init_map_value(struct bpf_map *map, void *dst)
{
 bpf_obj_init(map->record, dst);
}

/* memcpy that is used with 8-byte aligned pointers, power-of-8 size and
 * forced to use 'long' read/writes to try to atomically copy long counters.
 * Best-effort only.  No barriers here, since it _will_ race with concurrent
 * updates from BPF programs. Called from bpf syscall and mostly used with
 * size 8 or 16 bytes, so ask compiler to inline it.
 */

static inline void bpf_long_memcpy(void *dst, const void *src, u32 size)
{
 const long *lsrc = src;
 long *ldst = dst;

 size /= sizeof(long);
 while (size--)
  data_race(*ldst++ = *lsrc++);
}

/* copy everything but bpf_spin_lock, bpf_timer, and kptrs. There could be one of each. */
static inline void bpf_obj_memcpy(struct btf_record *rec,
      void *dst, void *src, u32 size,
      bool long_memcpy)
{
 u32 curr_off = 0;
 int i;

 if (IS_ERR_OR_NULL(rec)) {
  if (long_memcpy)
   bpf_long_memcpy(dst, src, round_up(size, 8));
  else
   memcpy(dst, src, size);
  return;
 }

 for (i = 0; i < rec->cnt; i++) {
  u32 next_off = rec->fields[i].offset;
  u32 sz = next_off - curr_off;

  memcpy(dst + curr_off, src + curr_off, sz);
  curr_off += rec->fields[i].size + sz;
 }
 memcpy(dst + curr_off, src + curr_off, size - curr_off);
}

static inline void copy_map_value(struct bpf_map *map, void *dst, void *src)
{
 bpf_obj_memcpy(map->record, dst, src, map->value_size, false);
}

static inline void copy_map_value_long(struct bpf_map *map, void *dst, void *src)
{
 bpf_obj_memcpy(map->record, dst, src, map->value_size, true);
}

static inline void bpf_obj_swap_uptrs(const struct btf_record *rec, void *dst, void *src)
{
 unsigned long *src_uptr, *dst_uptr;
 const struct btf_field *field;
 int i;

 if (!btf_record_has_field(rec, BPF_UPTR))
  return;

 for (i = 0, field = rec->fields; i < rec->cnt; i++, field++) {
  if (field->type != BPF_UPTR)
   continue;

  src_uptr = src + field->offset;
  dst_uptr = dst + field->offset;
  swap(*src_uptr, *dst_uptr);
 }
}

static inline void bpf_obj_memzero(struct btf_record *rec, void *dst, u32 size)
{
 u32 curr_off = 0;
 int i;

 if (IS_ERR_OR_NULL(rec)) {
  memset(dst, 0, size);
  return;
 }

 for (i = 0; i < rec->cnt; i++) {
  u32 next_off = rec->fields[i].offset;
  u32 sz = next_off - curr_off;

  memset(dst + curr_off, 0, sz);
  curr_off += rec->fields[i].size + sz;
 }
 memset(dst + curr_off, 0, size - curr_off);
}

static inline void zero_map_value(struct bpf_map *map, void *dst)
{
 bpf_obj_memzero(map->record, dst, map->value_size);
}

void copy_map_value_locked(struct bpf_map *map, void *dst, void *src,
      bool lock_src);
void bpf_timer_cancel_and_free(void *timer);
void bpf_wq_cancel_and_free(void *timer);
void bpf_list_head_free(const struct btf_field *field, void *list_head,
   struct bpf_spin_lock *spin_lock);
void bpf_rb_root_free(const struct btf_field *field, void *rb_root,
        struct bpf_spin_lock *spin_lock);
u64 bpf_arena_get_kern_vm_start(struct bpf_arena *arena);
u64 bpf_arena_get_user_vm_start(struct bpf_arena *arena);
int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size);

struct bpf_offload_dev;
struct bpf_offloaded_map;

struct bpf_map_dev_ops {
 int (*map_get_next_key)(struct bpf_offloaded_map *map,
    void *key, void *next_key);
 int (*map_lookup_elem)(struct bpf_offloaded_map *map,
          void *key, void *value);
 int (*map_update_elem)(struct bpf_offloaded_map *map,
          void *key, void *value, u64 flags);
 int (*map_delete_elem)(struct bpf_offloaded_map *map, void *key);
};

struct bpf_offloaded_map {
 struct bpf_map map;
 struct net_device *netdev;
 const struct bpf_map_dev_ops *dev_ops;
 void *dev_priv;
 struct list_head offloads;
};

static inline struct bpf_offloaded_map *map_to_offmap(struct bpf_map *map)
{
 return container_of(map, struct bpf_offloaded_map, map);
}

static inline bool bpf_map_offload_neutral(const struct bpf_map *map)
{
 return map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY;
}

static inline bool bpf_map_support_seq_show(const struct bpf_map *map)
{
 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,
       const struct btf *btf,
       const struct btf_type *key_type,
       const struct btf_type *value_type);

bool bpf_map_meta_equal(const struct bpf_map *meta0,
   const struct bpf_map *meta1);

extern const struct bpf_map_ops bpf_map_offload_ops;

/* bpf_type_flag contains a set of flags that are applicable to the values of
 * arg_type, ret_type and reg_type. For example, a pointer value may be null,
 * or a memory is read-only. We classify types into two categories: base types
 * and extended types. Extended types are base types combined with a type flag.
 *
 * Currently there are no more than 32 base types in arg_type, ret_type and
 * reg_types.
 */

#define BPF_BASE_TYPE_BITS 8

enum bpf_type_flag {
 /* PTR may be NULL. */
 PTR_MAYBE_NULL  = BIT(0 + BPF_BASE_TYPE_BITS),

 /* MEM is read-only. When applied on bpf_arg, it indicates the arg is
 * compatible with both mutable and immutable memory.
 */

 MEM_RDONLY  = BIT(1 + BPF_BASE_TYPE_BITS),

 /* MEM points to BPF ring buffer reservation. */
 MEM_RINGBUF  = BIT(2 + BPF_BASE_TYPE_BITS),

 /* MEM is in user address space. */
 MEM_USER  = BIT(3 + BPF_BASE_TYPE_BITS),

 /* MEM is a percpu memory. MEM_PERCPU tags PTR_TO_BTF_ID. When tagged
 * with MEM_PERCPU, PTR_TO_BTF_ID _cannot_ be directly accessed. In
 * order to drop this tag, it must be passed into bpf_per_cpu_ptr()
 * or bpf_this_cpu_ptr(), which will return the pointer corresponding
 * to the specified cpu.
 */

 MEM_PERCPU  = BIT(4 + BPF_BASE_TYPE_BITS),

 /* Indicates that the argument will be released. */
 OBJ_RELEASE  = BIT(5 + BPF_BASE_TYPE_BITS),

 /* PTR is not trusted. This is only used with PTR_TO_BTF_ID, to mark
 * unreferenced and referenced kptr loaded from map value using a load
 * instruction, so that they can only be dereferenced but not escape the
 * BPF program into the kernel (i.e. cannot be passed as arguments to
 * kfunc or bpf helpers).
 */

 PTR_UNTRUSTED  = BIT(6 + BPF_BASE_TYPE_BITS),

 /* MEM can be uninitialized. */
 MEM_UNINIT  = BIT(7 + BPF_BASE_TYPE_BITS),

 /* DYNPTR points to memory local to the bpf program. */
 DYNPTR_TYPE_LOCAL = BIT(8 + BPF_BASE_TYPE_BITS),

 /* DYNPTR points to a kernel-produced ringbuf record. */
 DYNPTR_TYPE_RINGBUF = BIT(9 + BPF_BASE_TYPE_BITS),

 /* Size is known at compile time. */
 MEM_FIXED_SIZE  = BIT(10 + BPF_BASE_TYPE_BITS),

 /* MEM is of an allocated object of type in program BTF. This is used to
 * tag PTR_TO_BTF_ID allocated using bpf_obj_new.
 */

 MEM_ALLOC  = BIT(11 + BPF_BASE_TYPE_BITS),

 /* PTR was passed from the kernel in a trusted context, and may be
 * passed to KF_TRUSTED_ARGS kfuncs or BPF helper functions.
 * Confusingly, this is _not_ the opposite of PTR_UNTRUSTED above.
 * PTR_UNTRUSTED refers to a kptr that was read directly from a map
 * without invoking bpf_kptr_xchg(). What we really need to know is
 * whether a pointer is safe to pass to a kfunc or BPF helper function.
 * While PTR_UNTRUSTED pointers are unsafe to pass to kfuncs and BPF
 * helpers, they do not cover all possible instances of unsafe
 * pointers. For example, a pointer that was obtained from walking a
 * struct will _not_ get the PTR_UNTRUSTED type modifier, despite the
 * fact that it may be NULL, invalid, etc. This is due to backwards
 * compatibility requirements, as this was the behavior that was first
 * introduced when kptrs were added. The behavior is now considered
 * deprecated, and PTR_UNTRUSTED will eventually be removed.
 *
 * PTR_TRUSTED, on the other hand, is a pointer that the kernel
 * guarantees to be valid and safe to pass to kfuncs and BPF helpers.
 * For example, pointers passed to tracepoint arguments are considered
 * PTR_TRUSTED, as are pointers that are passed to struct_ops
 * callbacks. As alluded to above, pointers that are obtained from
 * walking PTR_TRUSTED pointers are _not_ trusted. For example, if a
 * struct task_struct *task is PTR_TRUSTED, then accessing
 * task->last_wakee will lose the PTR_TRUSTED modifier when it's stored
 * in a BPF register. Similarly, pointers passed to certain programs
 * types such as kretprobes are not guaranteed to be valid, as they may
 * for example contain an object that was recently freed.
 */

 PTR_TRUSTED  = BIT(12 + BPF_BASE_TYPE_BITS),

 /* MEM is tagged with rcu and memory access needs rcu_read_lock protection. */
 MEM_RCU   = BIT(13 + BPF_BASE_TYPE_BITS),

 /* Used to tag PTR_TO_BTF_ID | MEM_ALLOC references which are non-owning.
 * Currently only valid for linked-list and rbtree nodes. If the nodes
 * have a bpf_refcount_field, they must be tagged MEM_RCU as well.
 */

 NON_OWN_REF  = BIT(14 + BPF_BASE_TYPE_BITS),

 /* DYNPTR points to sk_buff */
 DYNPTR_TYPE_SKB  = BIT(15 + BPF_BASE_TYPE_BITS),

 /* DYNPTR points to xdp_buff */
 DYNPTR_TYPE_XDP  = BIT(16 + BPF_BASE_TYPE_BITS),

 /* Memory must be aligned on some architectures, used in combination with
 * MEM_FIXED_SIZE.
 */

 MEM_ALIGNED  = BIT(17 + BPF_BASE_TYPE_BITS),

 /* MEM is being written to, often combined with MEM_UNINIT. Non-presence
 * of MEM_WRITE means that MEM is only being read. MEM_WRITE without the
 * MEM_UNINIT means that memory needs to be initialized since it is also
 * read.
 */

 MEM_WRITE  = BIT(18 + BPF_BASE_TYPE_BITS),

 __BPF_TYPE_FLAG_MAX,
 __BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1,
};

#define DYNPTR_TYPE_FLAG_MASK (DYNPTR_TYPE_LOCAL | DYNPTR_TYPE_RINGBUF | DYNPTR_TYPE_SKB \
     | DYNPTR_TYPE_XDP)

/* Max number of base types. */
#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS)

/* Max number of all types. */
#define BPF_TYPE_LIMIT  (__BPF_TYPE_LAST_FLAG | (__BPF_TYPE_LAST_FLAG - 1))

/* function argument constraints */
enum bpf_arg_type {
 ARG_DONTCARE = 0, /* unused argument in helper function */

 /* the following constraints used to prototype
 * bpf_map_lookup/update/delete_elem() functions
 */

 ARG_CONST_MAP_PTR, /* const argument used as pointer to bpf_map */
 ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
 ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */

 /* Used to prototype bpf_memcmp() and other functions that access data
 * on eBPF program stack
 */

 ARG_PTR_TO_MEM,  /* pointer to valid memory (stack, packet, map value) */
 ARG_PTR_TO_ARENA,

 ARG_CONST_SIZE,  /* number of bytes accessed from memory */
 ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */

 ARG_PTR_TO_CTX,  /* pointer to context */
 ARG_ANYTHING,  /* any (initialized) argument is ok */
 ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */
 ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */
 ARG_PTR_TO_SOCKET, /* pointer to bpf_sock (fullsock) */
 ARG_PTR_TO_BTF_ID, /* pointer to in-kernel struct */
 ARG_PTR_TO_RINGBUF_MEM, /* pointer to dynamically reserved ringbuf memory */
 ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */
 ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */
 ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */
 ARG_PTR_TO_FUNC, /* pointer to a bpf program function */
 ARG_PTR_TO_STACK, /* pointer to stack */
 ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */
 ARG_PTR_TO_TIMER, /* pointer to bpf_timer */
 ARG_KPTR_XCHG_DEST, /* pointer to destination that kptrs are bpf_kptr_xchg'd into */
 ARG_PTR_TO_DYNPTR,      /* pointer to bpf_dynptr. See bpf_type_flag for dynptr type */
 __BPF_ARG_TYPE_MAX,

 /* Extended arg_types. */
 ARG_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MAP_VALUE,
 ARG_PTR_TO_MEM_OR_NULL  = PTR_MAYBE_NULL | ARG_PTR_TO_MEM,
 ARG_PTR_TO_CTX_OR_NULL  = PTR_MAYBE_NULL | ARG_PTR_TO_CTX,
 ARG_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_SOCKET,
 ARG_PTR_TO_STACK_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_STACK,
 ARG_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_BTF_ID,
 /* Pointer to memory does not need to be initialized, since helper function
 * fills all bytes or clears them in error case.
 */

 ARG_PTR_TO_UNINIT_MEM  = MEM_UNINIT | MEM_WRITE | ARG_PTR_TO_MEM,
 /* Pointer to valid memory of size known at compile time. */
 ARG_PTR_TO_FIXED_SIZE_MEM = MEM_FIXED_SIZE | ARG_PTR_TO_MEM,

 /* This must be the last entry. Its purpose is to ensure the enum is
 * wide enough to hold the higher bits reserved for bpf_type_flag.
 */

 __BPF_ARG_TYPE_LIMIT = BPF_TYPE_LIMIT,
};
static_assert(__BPF_ARG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);

/* type of values returned from helper functions */
enum bpf_return_type {
 RET_INTEGER,   /* function returns integer */
 RET_VOID,   /* function doesn't return anything */
 RET_PTR_TO_MAP_VALUE,  /* returns a pointer to map elem value */
 RET_PTR_TO_SOCKET,  /* returns a pointer to a socket */
 RET_PTR_TO_TCP_SOCK,  /* returns a pointer to a tcp_sock */
 RET_PTR_TO_SOCK_COMMON,  /* returns a pointer to a sock_common */
 RET_PTR_TO_MEM,   /* returns a pointer to memory */
 RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */
 RET_PTR_TO_BTF_ID,  /* returns a pointer to a btf_id */
 __BPF_RET_TYPE_MAX,

 /* Extended ret_types. */
 RET_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_MAP_VALUE,
 RET_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCKET,
 RET_PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_TCP_SOCK,
 RET_PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCK_COMMON,
 RET_PTR_TO_RINGBUF_MEM_OR_NULL = PTR_MAYBE_NULL | MEM_RINGBUF | RET_PTR_TO_MEM,
 RET_PTR_TO_DYNPTR_MEM_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_MEM,
 RET_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_BTF_ID,
 RET_PTR_TO_BTF_ID_TRUSTED = PTR_TRUSTED  | RET_PTR_TO_BTF_ID,

 /* This must be the last entry. Its purpose is to ensure the enum is
 * wide enough to hold the higher bits reserved for bpf_type_flag.
 */

 __BPF_RET_TYPE_LIMIT = BPF_TYPE_LIMIT,
};
static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);

/* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs
 * to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
 * instructions after verifying
 */

struct bpf_func_proto {
 u64 (*func)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
 bool gpl_only;
 bool pkt_access;
 bool might_sleep;
 /* set to true if helper follows contract for llvm
 * attribute bpf_fastcall:
 * - void functions do not scratch r0
 * - functions taking N arguments scratch only registers r1-rN
 */

 bool allow_fastcall;
 enum bpf_return_type ret_type;
 union {
  struct {
   enum bpf_arg_type arg1_type;
   enum bpf_arg_type arg2_type;
   enum bpf_arg_type arg3_type;
   enum bpf_arg_type arg4_type;
   enum bpf_arg_type arg5_type;
  };
  enum bpf_arg_type arg_type[5];
 };
 union {
  struct {
   u32 *arg1_btf_id;
   u32 *arg2_btf_id;
   u32 *arg3_btf_id;
   u32 *arg4_btf_id;
   u32 *arg5_btf_id;
  };
  u32 *arg_btf_id[5];
  struct {
   size_t arg1_size;
   size_t arg2_size;
   size_t arg3_size;
   size_t arg4_size;
   size_t arg5_size;
  };
  size_t arg_size[5];
 };
 int *ret_btf_id; /* return value btf_id */
 bool (*allowed)(const struct bpf_prog *prog);
};

/* bpf_context is intentionally undefined structure. Pointer to bpf_context is
 * the first argument to eBPF programs.
 * For socket filters: 'struct bpf_context *' == 'struct sk_buff *'
 */

struct bpf_context;

enum bpf_access_type {
 BPF_READ = 1,
 BPF_WRITE = 2
};

/* types of values stored in eBPF registers */
/* Pointer types represent:
 * pointer
 * pointer + imm
 * pointer + (u16) var
 * pointer + (u16) var + imm
 * if (range > 0) then [ptr, ptr + range - off) is safe to access
 * if (id > 0) means that some 'var' was added
 * if (off > 0) means that 'imm' was added
 */

enum bpf_reg_type {
 NOT_INIT = 0,   /* nothing was written into register */
 SCALAR_VALUE,   /* reg doesn't contain a valid pointer */
 PTR_TO_CTX,   /* reg points to bpf_context */
 CONST_PTR_TO_MAP,  /* reg points to struct bpf_map */
 PTR_TO_MAP_VALUE,  /* reg points to map element value */
 PTR_TO_MAP_KEY,   /* reg points to a map element key */
 PTR_TO_STACK,   /* reg == frame_pointer + offset */
 PTR_TO_PACKET_META,  /* skb->data - meta_len */
 PTR_TO_PACKET,   /* reg points to skb->data */
 PTR_TO_PACKET_END,  /* skb->data + headlen */
 PTR_TO_FLOW_KEYS,  /* reg points to bpf_flow_keys */
 PTR_TO_SOCKET,   /* reg points to struct bpf_sock */
 PTR_TO_SOCK_COMMON,  /* reg points to sock_common */
 PTR_TO_TCP_SOCK,  /* reg points to struct tcp_sock */
 PTR_TO_TP_BUFFER,  /* reg points to a writable raw tp's buffer */
 PTR_TO_XDP_SOCK,  /* reg points to struct xdp_sock */
 /* PTR_TO_BTF_ID points to a kernel struct that does not need
 * to be null checked by the BPF program. This does not imply the
 * pointer is _not_ null and in practice this can easily be a null
 * pointer when reading pointer chains. The assumption is program
 * context will handle null pointer dereference typically via fault
 * handling. The verifier must keep this in mind and can make no
 * assumptions about null or non-null when doing branch analysis.
 * Further, when passed into helpers the helpers can not, without
 * additional context, assume the value is non-null.
 */

 PTR_TO_BTF_ID,
 PTR_TO_MEM,   /* reg points to valid memory region */
 PTR_TO_ARENA,
 PTR_TO_BUF,   /* reg points to a read/write buffer */
 PTR_TO_FUNC,   /* reg points to a bpf program function */
 CONST_PTR_TO_DYNPTR,  /* reg points to a const struct bpf_dynptr */
 __BPF_REG_TYPE_MAX,

 /* Extended reg_types. */
 PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | PTR_TO_MAP_VALUE,
 PTR_TO_SOCKET_OR_NULL  = PTR_MAYBE_NULL | PTR_TO_SOCKET,
 PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCK_COMMON,
 PTR_TO_TCP_SOCK_OR_NULL  = PTR_MAYBE_NULL | PTR_TO_TCP_SOCK,
 /* PTR_TO_BTF_ID_OR_NULL points to a kernel struct that has not
 * been checked for null. Used primarily to inform the verifier
 * an explicit null check is required for this struct.
 */

 PTR_TO_BTF_ID_OR_NULL  = PTR_MAYBE_NULL | PTR_TO_BTF_ID,

 /* This must be the last entry. Its purpose is to ensure the enum is
 * wide enough to hold the higher bits reserved for bpf_type_flag.
 */

 __BPF_REG_TYPE_LIMIT = BPF_TYPE_LIMIT,
};
static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);

/* The information passed from prog-specific *_is_valid_access
 * back to the verifier.
 */

struct bpf_insn_access_aux {
 enum bpf_reg_type reg_type;
 bool is_ldsx;
 union {
  int ctx_field_size;
  struct {
   struct btf *btf;
   u32 btf_id;
   u32 ref_obj_id;
  };
 };
 struct bpf_verifier_log *log; /* for verbose logs */
 bool is_retval; /* is accessing function return value ? */
};

static inline void
bpf_ctx_record_field_size(struct bpf_insn_access_aux *aux, u32 size)
{
 aux->ctx_field_size = size;
}

static bool bpf_is_ldimm64(const struct bpf_insn *insn)
{
 return insn->code == (BPF_LD | BPF_IMM | BPF_DW);
}

static inline bool bpf_pseudo_func(const struct bpf_insn *insn)
{
 return bpf_is_ldimm64(insn) && insn->src_reg == BPF_PSEUDO_FUNC;
}

/* Given a BPF_ATOMIC instruction @atomic_insn, return true if it is an
 * atomic load or store, and false if it is a read-modify-write instruction.
 */

static inline bool
bpf_atomic_is_load_store(const struct bpf_insn *atomic_insn)
{
 switch (atomic_insn->imm) {
 case BPF_LOAD_ACQ:
 case BPF_STORE_REL:
  return true;
 default:
  return false;
 }
}

struct bpf_prog_ops {
 int (*test_run)(struct bpf_prog *prog, const union bpf_attr *kattr,
   union bpf_attr __user *uattr);
};

struct bpf_reg_state;
struct bpf_verifier_ops {
 /* return eBPF function prototype for verification */
 const struct bpf_func_proto *
 (*get_func_proto)(enum bpf_func_id func_id,
     const struct bpf_prog *prog);

 /* return true if 'size' wide access at offset 'off' within bpf_context
 * with 'type' (read or write) is allowed
 */

 bool (*is_valid_access)(int off, int size, enum bpf_access_type type,
    const struct bpf_prog *prog,
    struct bpf_insn_access_aux *info);
 int (*gen_prologue)(struct bpf_insn *insn, bool direct_write,
       const struct bpf_prog *prog);
 int (*gen_epilogue)(struct bpf_insn *insn, const struct bpf_prog *prog,
       s16 ctx_stack_off);
 int (*gen_ld_abs)(const struct bpf_insn *orig,
     struct bpf_insn *insn_buf);
 u32 (*convert_ctx_access)(enum bpf_access_type type,
      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 bpf_reg_state *reg,
     int off, int size);
};

struct bpf_prog_offload_ops {
 /* verifier basic callbacks */
 int (*insn_hook)(struct bpf_verifier_env *env,
    int insn_idx, int prev_insn_idx);
 int (*finalize)(struct bpf_verifier_env *env);
 /* verifier optimization callbacks (called after .finalize) */
 int (*replace_insn)(struct bpf_verifier_env *env, u32 off,
       struct bpf_insn *insn);
 int (*remove_insns)(struct bpf_verifier_env *env, u32 off, u32 cnt);
 /* program management callbacks */
 int (*prepare)(struct bpf_prog *prog);
 int (*translate)(struct bpf_prog *prog);
 void (*destroy)(struct bpf_prog *prog);
};

struct bpf_prog_offload {
 struct bpf_prog  *prog;
 struct net_device *netdev;
 struct bpf_offload_dev *offdev;
 void   *dev_priv;
 struct list_head offloads;
 bool   dev_state;
 bool   opt_failed;
 void   *jited_image;
 u32   jited_len;
};

/* The longest tracepoint has 12 args.
 * See include/trace/bpf_probe.h
 */

#define MAX_BPF_FUNC_ARGS 12

/* The maximum number of arguments passed through registers
 * a single function may have.
 */

#define MAX_BPF_FUNC_REG_ARGS 5

/* The argument is a structure. */
#define BTF_FMODEL_STRUCT_ARG  BIT(0)

/* The argument is signed. */
#define BTF_FMODEL_SIGNED_ARG  BIT(1)

struct btf_func_model {
 u8 ret_size;
 u8 ret_flags;
 u8 nr_args;
 u8 arg_size[MAX_BPF_FUNC_ARGS];
 u8 arg_flags[MAX_BPF_FUNC_ARGS];
};

/* Restore arguments before returning from trampoline to let original function
 * continue executing. This flag is used for fentry progs when there are no
 * fexit progs.
 */

#define BPF_TRAMP_F_RESTORE_REGS BIT(0)
/* Call original function after fentry progs, but before fexit progs.
 * Makes sense for fentry/fexit, normal calls and indirect calls.
 */

#define BPF_TRAMP_F_CALL_ORIG  BIT(1)
/* Skip current frame and return to parent.  Makes sense for fentry/fexit
 * programs only. Should not be used with normal calls and indirect calls.
 */

#define BPF_TRAMP_F_SKIP_FRAME  BIT(2)
/* Store IP address of the caller on the trampoline stack,
 * so it's available for trampoline's programs.
 */

#define BPF_TRAMP_F_IP_ARG  BIT(3)
/* Return the return value of fentry prog. Only used by bpf_struct_ops. */
#define BPF_TRAMP_F_RET_FENTRY_RET BIT(4)

/* Get original function from stack instead of from provided direct address.
 * Makes sense for trampolines with fexit or fmod_ret programs.
 */

#define BPF_TRAMP_F_ORIG_STACK  BIT(5)

/* This trampoline is on a function with another ftrace_ops with IPMODIFY,
 * e.g., a live patch. This flag is set and cleared by ftrace call backs,
 */

#define BPF_TRAMP_F_SHARE_IPMODIFY BIT(6)

/* Indicate that current trampoline is in a tail call context. Then, it has to
 * cache and restore tail_call_cnt to avoid infinite tail call loop.
 */

#define BPF_TRAMP_F_TAIL_CALL_CTX BIT(7)

/*
 * Indicate the trampoline should be suitable to receive indirect calls;
 * without this indirectly calling the generated code can result in #UD/#CP,
 * depending on the CFI options.
 *
 * Used by bpf_struct_ops.
 *
 * Incompatible with FENTRY usage, overloads @func_addr argument.
 */

#define BPF_TRAMP_F_INDIRECT  BIT(8)

/* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50
 * bytes on x86.
 */

enum {
#if defined(__s390x__)
 BPF_MAX_TRAMP_LINKS = 27,
#else
 BPF_MAX_TRAMP_LINKS = 38,
#endif
};

struct bpf_tramp_links {
 struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
 int nr_links;
};

struct bpf_tramp_run_ctx;

/* Different use cases for BPF trampoline:
 * 1. replace nop at the function entry (kprobe equivalent)
 *    flags = BPF_TRAMP_F_RESTORE_REGS
 *    fentry = a set of programs to run before returning from trampoline
 *
 * 2. replace nop at the function entry (kprobe + kretprobe equivalent)
 *    flags = BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_SKIP_FRAME
 *    orig_call = fentry_ip + MCOUNT_INSN_SIZE
 *    fentry = a set of program to run before calling original function
 *    fexit = a set of program to run after original function
 *
 * 3. replace direct call instruction anywhere in the function body
 *    or assign a function pointer for indirect call (like tcp_congestion_ops->cong_avoid)
 *    With flags = 0
 *      fentry = a set of programs to run before returning from trampoline
 *    With flags = BPF_TRAMP_F_CALL_ORIG
 *      orig_call = original callback addr or direct function addr
 *      fentry = a set of program to run before calling original function
 *      fexit = a set of program to run after original function
 */

struct bpf_tramp_image;
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
    const struct btf_func_model *m, u32 flags,
    struct bpf_tramp_links *tlinks,
    void *func_addr);
void *arch_alloc_bpf_trampoline(unsigned int size);
void arch_free_bpf_trampoline(void *image, unsigned int size);
int __must_check arch_protect_bpf_trampoline(void *image, unsigned int size);
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
        struct bpf_tramp_links *tlinks, void *func_addr);

u64 notrace __bpf_prog_enter_sleepable_recur(struct bpf_prog *prog,
          struct bpf_tramp_run_ctx *run_ctx);
void notrace __bpf_prog_exit_sleepable_recur(struct bpf_prog *prog, u64 start,
          struct bpf_tramp_run_ctx *run_ctx);
void notrace __bpf_tramp_enter(struct bpf_tramp_image *tr);
void notrace __bpf_tramp_exit(struct bpf_tramp_image *tr);
typedef u64 (*bpf_trampoline_enter_t)(struct bpf_prog *prog,
          struct bpf_tramp_run_ctx *run_ctx);
typedef void (*bpf_trampoline_exit_t)(struct bpf_prog *prog, u64 start,
          struct bpf_tramp_run_ctx *run_ctx);
bpf_trampoline_enter_t bpf_trampoline_enter(const struct bpf_prog *prog);
bpf_trampoline_exit_t bpf_trampoline_exit(const struct bpf_prog *prog);

struct bpf_ksym {
 unsigned long   start;
 unsigned long   end;
 char    name[KSYM_NAME_LEN];
 struct list_head  lnode;
 struct latch_tree_node  tnode;
 bool    prog;
};

enum bpf_tramp_prog_type {
 BPF_TRAMP_FENTRY,
 BPF_TRAMP_FEXIT,
 BPF_TRAMP_MODIFY_RETURN,
 BPF_TRAMP_MAX,
 BPF_TRAMP_REPLACE, /* more than MAX */
};

struct bpf_tramp_image {
 void *image;
 int size;
 struct bpf_ksym ksym;
 struct percpu_ref pcref;
 void *ip_after_call;
 void *ip_epilogue;
 union {
  struct rcu_head rcu;
  struct work_struct work;
 };
};

struct bpf_trampoline {
 /* hlist for trampoline_table */
 struct hlist_node hlist;
 struct ftrace_ops *fops;
 /* serializes access to fields of this trampoline */
 struct mutex mutex;
 refcount_t refcnt;
 u32 flags;
 u64 key;
 struct {
  struct btf_func_model model;
  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. */
 int progs_cnt[BPF_TRAMP_MAX];
 /* Executable image of trampoline */
 struct bpf_tramp_image *cur_image;
};

struct bpf_attach_target_info {
 struct btf_func_model fmodel;
 long tgt_addr;
 struct module *tgt_mod;
 const char *tgt_name;
 const struct btf_type *tgt_type;
};

#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;
 void *rw_image;
 u32 image_off;
 struct bpf_ksym ksym;
#ifdef CONFIG_HAVE_STATIC_CALL
 struct static_call_key *sc_key;
 void *sc_tramp;
#endif
};

#ifndef __bpfcall
#define __bpfcall __nocfi
#endif

static __always_inline __bpfcall unsigned int bpf_dispatcher_nop_func(
 const void *ctx,
 const struct bpf_insn *insnsi,
 bpf_func_t bpf_func)
{
 return bpf_func(ctx, insnsi);
}

/* the implementation of the opaque uapi struct bpf_dynptr */
struct bpf_dynptr_kern {
 void *data;
 /* Size represents the number of usable bytes of dynptr data.
 * If for example the offset is at 4 for a local dynptr whose data is
 * of type u64, the number of usable bytes is 4.
 *
 * The upper 8 bits are reserved. It is as follows:
 * Bits 0 - 23 = size
 * Bits 24 - 30 = dynptr type
 * Bit 31 = whether dynptr is read-only
 */

 u32 size;
 u32 offset;
} __aligned(8);

enum bpf_dynptr_type {
 BPF_DYNPTR_TYPE_INVALID,
 /* Points to memory that is local to the bpf program */
 BPF_DYNPTR_TYPE_LOCAL,
 /* Underlying data is a ringbuf record */
 BPF_DYNPTR_TYPE_RINGBUF,
 /* Underlying data is a sk_buff */
 BPF_DYNPTR_TYPE_SKB,
 /* Underlying data is a xdp_buff */
 BPF_DYNPTR_TYPE_XDP,
};

int bpf_dynptr_check_size(u32 size);
u32 __bpf_dynptr_size(const struct bpf_dynptr_kern *ptr);
const void *__bpf_dynptr_data(const struct bpf_dynptr_kern *ptr, u32 len);
void *__bpf_dynptr_data_rw(const struct bpf_dynptr_kern *ptr, u32 len);
bool __bpf_dynptr_is_rdonly(const struct bpf_dynptr_kern *ptr);
int __bpf_dynptr_write(const struct bpf_dynptr_kern *dst, u32 offset,
         void *src, u32 len, u64 flags);
void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr *p, u32 offset,
       void *buffer__opt, u32 buffer__szk);

static inline int bpf_dynptr_check_off_len(const struct bpf_dynptr_kern *ptr, u32 offset, u32 len)
{
 u32 size = __bpf_dynptr_size(ptr);

 if (len > size || offset > size - len)
  return -E2BIG;

 return 0;
}

#ifdef CONFIG_BPF_JIT
int bpf_trampoline_link_prog(struct bpf_tramp_link *link,
        struct bpf_trampoline *tr,
        struct bpf_prog *tgt_prog);
int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
          struct bpf_trampoline *tr,
          struct bpf_prog *tgt_prog);
struct bpf_trampoline *bpf_trampoline_get(u64 key,
       struct bpf_attach_target_info *tgt_info);
void bpf_trampoline_put(struct bpf_trampoline *tr);
int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_funcs);

/*
 * When the architecture supports STATIC_CALL replace the bpf_dispatcher_fn
 * indirection with a direct call to the bpf program. If the architecture does
 * not have STATIC_CALL, avoid a double-indirection.
 */

#ifdef CONFIG_HAVE_STATIC_CALL

#define __BPF_DISPATCHER_SC_INIT(_name)    \
 .sc_key = &STATIC_CALL_KEY(_name),   \
 .sc_tramp = STATIC_CALL_TRAMP_ADDR(_name),

#define __BPF_DISPATCHER_SC(name)    \
 DEFINE_STATIC_CALL(bpf_dispatcher_##name##_call, bpf_dispatcher_nop_func)

#define __BPF_DISPATCHER_CALL(name)    \
 static_call(bpf_dispatcher_##name##_call)(ctx, insnsi, bpf_func)

#define __BPF_DISPATCHER_UPDATE(_d, _new)   \
 __static_call_update((_d)->sc_key, (_d)->sc_tramp, (_new))

#else
#define __BPF_DISPATCHER_SC_INIT(name)
#define __BPF_DISPATCHER_SC(name)
#define __BPF_DISPATCHER_CALL(name)  bpf_func(ctx, insnsi)
#define __BPF_DISPATCHER_UPDATE(_d, _new)
#endif

#define BPF_DISPATCHER_INIT(_name) {    \
 .mutex = __MUTEX_INITIALIZER(_name.mutex),  \
 .func = &_name##_func,     \
 .progs = {},      \
 .num_progs = 0,      \
 .image = NULL,      \
 .image_off = 0,      \
 .ksym = {      \
  .name  = #_name,    \
  .lnode = LIST_HEAD_INIT(_name.ksym.lnode), \
 },       \
 __BPF_DISPATCHER_SC_INIT(_name##_call)   \
}

#define DEFINE_BPF_DISPATCHER(name)     \
 __BPF_DISPATCHER_SC(name);     \
 noinline __bpfcall unsigned int bpf_dispatcher_##name##_func( \
  const void *ctx,     \
  const struct bpf_insn *insnsi,    \
  bpf_func_t bpf_func)     \
 {        \
  return __BPF_DISPATCHER_CALL(name);   \
 }        \
 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,    \
  bpf_func_t bpf_func);     \
 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);
/* Called only from JIT-enabled code, so there's no need for stubs. */
void bpf_image_ksym_init(void *data, unsigned int size, struct bpf_ksym *ksym);
void bpf_image_ksym_add(struct bpf_ksym *ksym);
void bpf_image_ksym_del(struct bpf_ksym *ksym);
void bpf_ksym_add(struct bpf_ksym *ksym);
void bpf_ksym_del(struct bpf_ksym *ksym);
int bpf_jit_charge_modmem(u32 size);
void bpf_jit_uncharge_modmem(u32 size);
bool bpf_prog_has_trampoline(const struct bpf_prog *prog);
#else
static inline int bpf_trampoline_link_prog(struct bpf_tramp_link *link,
        struct bpf_trampoline *tr,
        struct bpf_prog *tgt_prog)
{
 return -ENOTSUPP;
}
static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
          struct bpf_trampoline *tr,
          struct bpf_prog *tgt_prog)
{
 return -ENOTSUPP;
}
static inline struct bpf_trampoline *bpf_trampoline_get(u64 key,
       struct bpf_attach_target_info *tgt_info)
{
 return NULL;
}
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;
}
static inline bool bpf_prog_has_trampoline(const struct bpf_prog *prog)
{
 return false;
}
#endif

struct bpf_func_info_aux {
 u16 linkage;
 bool unreliable;
 bool called : 1;
 bool verified : 1;
};

enum bpf_jit_poke_reason {
 BPF_POKE_REASON_TAIL_CALL,
};

/* Descriptor of pokes pointing /into/ the JITed image. */
struct bpf_jit_poke_descriptor {
 void *tailcall_target;
 void *tailcall_bypass;
 void *bypass_addr;
 void *aux;
 union {
  struct {
   struct bpf_map *map;
   u32 key;
  } tail_call;
 };
 bool tailcall_target_stable;
 u8 adj_off;
 u16 reason;
 u32 insn_idx;
};

/* reg_type info for ctx arguments */
struct bpf_ctx_arg_aux {
 u32 offset;
 enum bpf_reg_type reg_type;
 struct btf *btf;
 u32 btf_id;
 u32 ref_obj_id;
 bool refcounted;
};

struct btf_mod_pair {
 struct btf *btf;
 struct module *module;
};

struct bpf_kfunc_desc_tab;

enum bpf_stream_id {
 BPF_STDOUT = 1,
 BPF_STDERR = 2,
};

struct bpf_stream_elem {
 struct llist_node node;
 int total_len;
 int consumed_len;
 char str[];
};

enum {
 /* 100k bytes */
 BPF_STREAM_MAX_CAPACITY = 100000ULL,
};

struct bpf_stream {
 atomic_t capacity;
 struct llist_head log; /* list of in-flight stream elements in LIFO order */

 struct mutex lock;  /* lock protecting backlog_{head,tail} */
 struct llist_node *backlog_head; /* list of in-flight stream elements in FIFO order */
 struct llist_node *backlog_tail; /* tail of the list above */
};

struct bpf_stream_stage {
 struct llist_head log;
 int len;
};

struct bpf_prog_aux {
 atomic64_t refcnt;
 u32 used_map_cnt;
 u32 used_btf_cnt;
 u32 max_ctx_offset;
 u32 max_pkt_offset;
 u32 max_tp_access;
 u32 stack_depth;
 u32 id;
 u32 func_cnt; /* used by non-func prog as the number of func progs */
 u32 real_func_cnt; /* includes hidden progs, only used for JIT and freeing progs */
 u32 func_idx; /* 0 for non-func prog, the index in func array for func prog */
 u32 attach_btf_id; /* in-kernel BTF type id to attach to */
 u32 attach_st_ops_member_off;
 u32 ctx_arg_info_size;
 u32 max_rdonly_access;
 u32 max_rdwr_access;
 struct btf *attach_btf;
 struct bpf_ctx_arg_aux *ctx_arg_info;
 void __percpu *priv_stack_ptr;
 struct mutex dst_mutex; /* protects dst_* pointers below, *after* prog becomes visible */
 struct bpf_prog *dst_prog;
 struct bpf_trampoline *dst_trampoline;
 enum bpf_prog_type saved_dst_prog_type;
 enum bpf_attach_type saved_dst_attach_type;
 bool verifier_zext; /* Zero extensions has been inserted by verifier. */
 bool dev_bound; /* Program is bound to the netdev. */
 bool offload_requested; /* Program is bound and offloaded to the netdev. */
 bool attach_btf_trace; /* true if attaching to BTF-enabled raw tp */
 bool attach_tracing_prog; /* true if tracing another tracing program */
 bool func_proto_unreliable;
 bool tail_call_reachable;
 bool xdp_has_frags;
 bool exception_cb;
 bool exception_boundary;
 bool is_extended; /* true if extended by freplace program */
 bool jits_use_priv_stack;
 bool priv_stack_requested;
 bool changes_pkt_data;
 bool might_sleep;
 u64 prog_array_member_cnt; /* counts how many times as member of prog_array */
 struct mutex ext_mutex; /* mutex for is_extended and prog_array_member_cnt */
 struct bpf_arena *arena;
 void (*recursion_detected)(struct bpf_prog *prog); /* callback if recursion is detected */
 /* BTF_KIND_FUNC_PROTO for valid attach_btf_id */
 const struct btf_type *attach_func_proto;
 /* function name for valid attach_btf_id */
 const char *attach_func_name;
 struct bpf_prog **func;
 void *jit_data; /* JIT specific data. arch dependent */
 struct bpf_jit_poke_descriptor *poke_tab;
 struct bpf_kfunc_desc_tab *kfunc_tab;
 struct bpf_kfunc_btf_tab *kfunc_btf_tab;
 u32 size_poke_tab;
#ifdef CONFIG_FINEIBT
 struct bpf_ksym ksym_prefix;
#endif
 struct bpf_ksym ksym;
 const struct bpf_prog_ops *ops;
 const struct bpf_struct_ops *st_ops;
 struct bpf_map **used_maps;
 struct mutex used_maps_mutex; /* mutex for used_maps and used_map_cnt */
 struct btf_mod_pair *used_btfs;
 struct bpf_prog *prog;
 struct user_struct *user;
 u64 load_time; /* ns since boottime */
 u32 verified_insns;
 int cgroup_atype; /* enum cgroup_bpf_attach_type */
 struct bpf_map *cgroup_storage[MAX_BPF_CGROUP_STORAGE_TYPE];
 char name[BPF_OBJ_NAME_LEN];
 u64 (*bpf_exception_cb)(u64 cookie, u64 sp, u64 bp, u64, u64);
#ifdef CONFIG_SECURITY
 void *security;
#endif
 struct bpf_token *token;
 struct bpf_prog_offload *offload;
 struct btf *btf;
 struct bpf_func_info *func_info;
 struct bpf_func_info_aux *func_info_aux;
 /* bpf_line_info loaded from userspace.  linfo->insn_off
 * has the xlated insn offset.
 * Both the main and sub prog share the same linfo.
 * The subprog can access its first linfo by
 * using the linfo_idx.
 */

 struct bpf_line_info *linfo;
 /* jited_linfo is the jited addr of the linfo.  It has a
 * one to one mapping to linfo:
 * jited_linfo[i] is the jited addr for the linfo[i]->insn_off.
 * Both the main and sub prog share the same jited_linfo.
 * The subprog can access its first jited_linfo by
 * using the linfo_idx.
 */

 void **jited_linfo;
 u32 func_info_cnt;
 u32 nr_linfo;
 /* subprog can use linfo_idx to access its first linfo and
 * jited_linfo.
 * main prog always has linfo_idx == 0
 */

 u32 linfo_idx;
 struct module *mod;
 u32 num_exentries;
 struct exception_table_entry *extable;
 union {
  struct work_struct work;
  struct rcu_head rcu;
 };
 struct bpf_stream stream[2];
};

struct bpf_prog {
 u16   pages;  /* Number of allocated pages */
 u16   jited:1, /* Is our filter JIT'ed? */
    jit_requested:1,/* archs need to JIT the prog */
    gpl_compatible:1, /* Is filter GPL compatible? */
    cb_access:1, /* Is control block accessed? */
    dst_needed:1, /* Do we need dst entry? */
    blinding_requested:1, /* needs constant blinding */
    blinded:1, /* Was blinded */
    is_func:1, /* program is a bpf function */
    kprobe_override:1, /* Do we override a kprobe? */
    has_callchain_buf:1, /* callchain buffer allocated? */
    enforce_expected_attach_type:1, /* Enforce expected_attach_type checking at attach time */
    call_get_stack:1, /* Do we call bpf_get_stack() or bpf_get_stackid() */
    call_get_func_ip:1, /* Do we call get_func_ip() */
    tstamp_type_access:1, /* Accessed __sk_buff->tstamp_type */
    sleepable:1; /* BPF program is sleepable */
 enum bpf_prog_type type;  /* Type of BPF program */
 enum bpf_attach_type expected_attach_type; /* For some prog types */
 u32   len;  /* Number of filter blocks */
 u32   jited_len; /* Size of jited insns in bytes */
 u8   tag[BPF_TAG_SIZE];
 struct bpf_prog_stats __percpu *stats;
 int __percpu  *active;
 unsigned int  (*bpf_func)(const void *ctx,
         const struct bpf_insn *insn);
 struct bpf_prog_aux *aux;  /* Auxiliary fields */
 struct sock_fprog_kern *orig_prog; /* Original BPF program */
 /* Instructions for interpreter */
 union {
  DECLARE_FLEX_ARRAY(struct sock_filter, insns);
  DECLARE_FLEX_ARRAY(struct bpf_insn, insnsi);
 };
};

struct bpf_array_aux {
 /* Programs with direct jumps into programs part of this array. */
 struct list_head poke_progs;
 struct bpf_map *map;
 struct mutex poke_mutex;
 struct work_struct work;
};

struct bpf_link {
 atomic64_t refcnt;
 u32 id;
 enum bpf_link_type type;
 const struct bpf_link_ops *ops;
 struct bpf_prog *prog;

 u32 flags;
 enum bpf_attach_type attach_type;

 /* rcu is used before freeing, work can be used to schedule that
 * RCU-based freeing before that, so they never overlap
 */

 union {
  struct rcu_head rcu;
  struct work_struct work;
 };
 /* whether BPF link itself has "sleepable" semantics, which can differ
 * from underlying BPF program having a "sleepable" semantics, as BPF
 * link's semantics is determined by target attach hook
 */

 bool sleepable;
};

struct bpf_link_ops {
 void (*release)(struct bpf_link *link);
 /* deallocate link resources callback, called without RCU grace period
 * waiting
 */

 void (*dealloc)(struct bpf_link *link);
 /* deallocate link resources callback, called after RCU grace period;
 * if either the underlying BPF program is sleepable or BPF link's
 * target hook is sleepable, we'll go through tasks trace RCU GP and
 * then "classic" RCU GP; this need for chaining tasks trace and
 * classic RCU GPs is designated by setting bpf_link->sleepable flag
 */

 void (*dealloc_deferred)(struct bpf_link *link);
 int (*detach)(struct bpf_link *link);
 int (*update_prog)(struct bpf_link *link, struct bpf_prog *new_prog,
      struct bpf_prog *old_prog);
 void (*show_fdinfo)(const struct bpf_link *link, struct seq_file *seq);
 int (*fill_link_info)(const struct bpf_link *link,
         struct bpf_link_info *info);
 int (*update_map)(struct bpf_link *link, struct bpf_map *new_map,
     struct bpf_map *old_map);
 __poll_t (*poll)(struct file *file, struct poll_table_struct *pts);
};

struct bpf_tramp_link {
 struct bpf_link link;
 struct hlist_node tramp_hlist;
 u64 cookie;
};

struct bpf_shim_tramp_link {
 struct bpf_tramp_link link;
 struct bpf_trampoline *trampoline;
};

struct bpf_tracing_link {
 struct bpf_tramp_link link;
 struct bpf_trampoline *trampoline;
 struct bpf_prog *tgt_prog;
};

struct bpf_raw_tp_link {
 struct bpf_link link;
 struct bpf_raw_event_map *btp;
 u64 cookie;
};

struct bpf_link_primer {
 struct bpf_link *link;
 struct file *file;
 int fd;
 u32 id;
};

struct bpf_mount_opts {
 kuid_t uid;
 kgid_t gid;
 umode_t mode;

 /* BPF token-related delegation options */
 u64 delegate_cmds;
 u64 delegate_maps;
 u64 delegate_progs;
 u64 delegate_attachs;
};

struct bpf_token {
 struct work_struct work;
 atomic64_t refcnt;
 struct user_namespace *userns;
 u64 allowed_cmds;
 u64 allowed_maps;
 u64 allowed_progs;
 u64 allowed_attachs;
#ifdef CONFIG_SECURITY
 void *security;
#endif
};

struct bpf_struct_ops_value;
struct btf_member;

#define BPF_STRUCT_OPS_MAX_NR_MEMBERS 64
/**
 * struct bpf_struct_ops - A structure of callbacks allowing a subsystem to
 *    define a BPF_MAP_TYPE_STRUCT_OPS map type composed
 *    of BPF_PROG_TYPE_STRUCT_OPS progs.
 * @verifier_ops: A structure of callbacks that are invoked by the verifier
 *   when determining whether the struct_ops progs in the
 *   struct_ops map are valid.
 * @init: A callback that is invoked a single time, and before any other
 *   callback, to initialize the structure. A nonzero return value means
 *   the subsystem could not be initialized.
 * @check_member: When defined, a callback invoked by the verifier to allow
 *   the subsystem to determine if an entry in the struct_ops map
 *   is valid. A nonzero return value means that the map is
 *   invalid and should be rejected by the verifier.
 * @init_member: A callback that is invoked for each member of the struct_ops
 *  map to allow the subsystem to initialize the member. A nonzero
 *  value means the member could not be initialized. This callback
 *  is exclusive with the @type, @type_id, @value_type, and
 *  @value_id fields.
 * @reg: A callback that is invoked when the struct_ops map has been
 *  initialized and is being attached to. Zero means the struct_ops map
 *  has been successfully registered and is live. A nonzero return value
 *  means the struct_ops map could not be registered.
 * @unreg: A callback that is invoked when the struct_ops map should be
 *    unregistered.
 * @update: A callback that is invoked when the live struct_ops map is being
 *     updated to contain new values. This callback is only invoked when
 *     the struct_ops map is loaded with BPF_F_LINK. If not defined, the
 *     it is assumed that the struct_ops map cannot be updated.
 * @validate: A callback that is invoked after all of the members have been
 *       initialized. This callback should perform static checks on the
 *       map, meaning that it should either fail or succeed
 *       deterministically. A struct_ops map that has been validated may
 *       not necessarily succeed in being registered if the call to @reg
 *       fails. For example, a valid struct_ops map may be loaded, but
 *       then fail to be registered due to there being another active
 *       struct_ops map on the system in the subsystem already. For this
 *       reason, if this callback is not defined, the check is skipped as
 *       the struct_ops map will have final verification performed in
 *       @reg.
 * @type: BTF type.
 * @value_type: Value type.
 * @name: The name of the struct bpf_struct_ops object.
 * @func_models: Func models
 * @type_id: BTF type id.
 * @value_id: BTF value id.
 */

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,
       const struct bpf_prog *prog);
 int (*init_member)(const struct btf_type *t,
      const struct btf_member *member,
      void *kdata, const void *udata);
 int (*reg)(void *kdata, struct bpf_link *link);
 void (*unreg)(void *kdata, struct bpf_link *link);
 int (*update)(void *kdata, void *old_kdata, struct bpf_link *link);
 int (*validate)(void *kdata);
 void *cfi_stubs;
 struct module *owner;
 const char *name;
 struct btf_func_model func_models[BPF_STRUCT_OPS_MAX_NR_MEMBERS];
};

/* Every member of a struct_ops type has an instance even a member is not
 * an operator (function pointer). The "info" field will be assigned to
 * prog->aux->ctx_arg_info of BPF struct_ops programs to provide the
 * argument information required by the verifier to verify the program.
 *
 * btf_ctx_access() will lookup prog->aux->ctx_arg_info to find the
 * corresponding entry for an given argument.
 */

struct bpf_struct_ops_arg_info {
 struct bpf_ctx_arg_aux *info;
 u32 cnt;
};

struct bpf_struct_ops_desc {
 struct bpf_struct_ops *st_ops;

 const struct btf_type *type;
 const struct btf_type *value_type;
 u32 type_id;
 u32 value_id;

 /* Collection of argument information for each member */
 struct bpf_struct_ops_arg_info *arg_info;
};

enum bpf_struct_ops_state {
 BPF_STRUCT_OPS_STATE_INIT,
 BPF_STRUCT_OPS_STATE_INUSE,
 BPF_STRUCT_OPS_STATE_TOBEFREE,
 BPF_STRUCT_OPS_STATE_READY,
};

struct bpf_struct_ops_common_value {
 refcount_t refcnt;
 enum bpf_struct_ops_state state;
};

#if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL)
/* This macro helps developer to register a struct_ops type and generate
 * type information correctly. Developers should use this macro to register
 * a struct_ops type instead of calling __register_bpf_struct_ops() directly.
 */

#define register_bpf_struct_ops(st_ops, type)    \
 ({        \
  struct bpf_struct_ops_##type {    \
   struct bpf_struct_ops_common_value common; \
   struct type data ____cacheline_aligned_in_smp; \
  };       \
  BTF_TYPE_EMIT(struct bpf_struct_ops_##type);  \
  __register_bpf_struct_ops(st_ops);   \
 })
#define BPF_MODULE_OWNER ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA))
bool bpf_struct_ops_get(const void *kdata);
void bpf_struct_ops_put(const void *kdata);
int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff);
int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key,
           void *value);
int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks,
          struct bpf_tramp_link *link,
          const struct btf_func_model *model,
          void *stub_func,
          void **image, u32 *image_off,
          bool allow_alloc);
void bpf_struct_ops_image_free(void *image);
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);
}
int bpf_struct_ops_link_create(union bpf_attr *attr);

#ifdef CONFIG_NET
/* Define it here to avoid the use of forward declaration */
struct bpf_dummy_ops_state {
 int val;
};

struct bpf_dummy_ops {
 int (*test_1)(struct bpf_dummy_ops_state *cb);
 int (*test_2)(struct bpf_dummy_ops_state *cb, int a1, unsigned short a2,
        char a3, unsigned long a4);
 int (*test_sleepable)(struct bpf_dummy_ops_state *cb);
};

int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr,
       union bpf_attr __user *uattr);
#endif
int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
        struct btf *btf,
        struct bpf_verifier_log *log);
void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struct bpf_map *map);
void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_ops_desc);
#else
#define register_bpf_struct_ops(st_ops, type) ({ (void *)(st_ops); 0; })
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_supported(const struct bpf_struct_ops *st_ops, u32 moff)
{
--> --------------------

--> maximum size reached

--> --------------------

96%


¤ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.