diff mbox series

[RFC,bpf-next,11/13] treewide: bpf: Export symbols used by verifier

Message ID 5b3433d942eaecdbcc92876c9ed8b7d17f7e1086.1744169424.git.dxu@dxuuu.xyz
State New
Headers show
Series bpf: Introduce modular verifier | expand

Commit Message

Daniel Xu April 9, 2025, 3:34 a.m. UTC
This commit EXPORT_SYMBOL_GPL()'s all the unresolved symbols from verifier.o.
This is necessary to support loads and reloads of the verifier at
runtime.

The list of symbols was generated using:

    nm -u kernel/bpf/verifier.o | grep -ve "__asan\|__ubsan\|__kasan" | awk '{print $2}'

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
 arch/x86/net/bpf_jit_comp.c |  2 ++
 drivers/media/rc/bpf-lirc.c |  1 +
 fs/bpf_fs_kfuncs.c          |  4 ++++
 kernel/bpf/bpf_iter.c       |  1 +
 kernel/bpf/bpf_lsm.c        |  5 +++++
 kernel/bpf/bpf_struct_ops.c |  2 ++
 kernel/bpf/btf.c            | 40 +++++++++++++++++++++++++++++++++++++
 kernel/bpf/cgroup.c         |  4 ++++
 kernel/bpf/core.c           | 29 +++++++++++++++++++++++++++
 kernel/bpf/disasm.c         |  4 ++++
 kernel/bpf/helpers.c        |  2 ++
 kernel/bpf/local_storage.c  |  2 ++
 kernel/bpf/log.c            | 12 +++++++++++
 kernel/bpf/map_iter.c       |  1 +
 kernel/bpf/memalloc.c       |  3 +++
 kernel/bpf/offload.c        | 10 ++++++++++
 kernel/bpf/syscall.c        |  7 +++++++
 kernel/bpf/tnum.c           | 20 +++++++++++++++++++
 kernel/bpf/token.c          |  1 +
 kernel/bpf/trampoline.c     |  5 +++++
 kernel/events/callchain.c   |  3 +++
 kernel/trace/bpf_trace.c    |  9 +++++++++
 lib/error-inject.c          |  2 ++
 net/core/filter.c           | 26 ++++++++++++++++++++++++
 net/core/xdp.c              |  2 ++
 net/netfilter/nf_bpf_link.c |  1 +
 26 files changed, 198 insertions(+)

Comments

Alexei Starovoitov April 21, 2025, 4:13 p.m. UTC | #1
On Tue, Apr 8, 2025 at 8:35 PM Daniel Xu <dxu@dxuuu.xyz> wrote:
>
> This commit EXPORT_SYMBOL_GPL()'s all the unresolved symbols from verifier.o.
> This is necessary to support loads and reloads of the verifier at
> runtime.
>
> The list of symbols was generated using:
>
>     nm -u kernel/bpf/verifier.o | grep -ve "__asan\|__ubsan\|__kasan" | awk '{print $2}'
>
> Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
> ---
>  arch/x86/net/bpf_jit_comp.c |  2 ++
>  drivers/media/rc/bpf-lirc.c |  1 +
>  fs/bpf_fs_kfuncs.c          |  4 ++++
>  kernel/bpf/bpf_iter.c       |  1 +
>  kernel/bpf/bpf_lsm.c        |  5 +++++
>  kernel/bpf/bpf_struct_ops.c |  2 ++
>  kernel/bpf/btf.c            | 40 +++++++++++++++++++++++++++++++++++++
>  kernel/bpf/cgroup.c         |  4 ++++
>  kernel/bpf/core.c           | 29 +++++++++++++++++++++++++++
>  kernel/bpf/disasm.c         |  4 ++++
>  kernel/bpf/helpers.c        |  2 ++
>  kernel/bpf/local_storage.c  |  2 ++
>  kernel/bpf/log.c            | 12 +++++++++++
>  kernel/bpf/map_iter.c       |  1 +
>  kernel/bpf/memalloc.c       |  3 +++
>  kernel/bpf/offload.c        | 10 ++++++++++
>  kernel/bpf/syscall.c        |  7 +++++++
>  kernel/bpf/tnum.c           | 20 +++++++++++++++++++
>  kernel/bpf/token.c          |  1 +
>  kernel/bpf/trampoline.c     |  5 +++++
>  kernel/events/callchain.c   |  3 +++
>  kernel/trace/bpf_trace.c    |  9 +++++++++
>  lib/error-inject.c          |  2 ++
>  net/core/filter.c           | 26 ++++++++++++++++++++++++
>  net/core/xdp.c              |  2 ++
>  net/netfilter/nf_bpf_link.c |  1 +
>  26 files changed, 198 insertions(+)

Patches 1-10 look ok. Moving the code around and few targeted
exports are fine,
but this patch goes too far.
At least btf.c, log.c, tnum.c and may be others should be a part
of the module.
Then check_sock_access() can be refactored into callbacks
to avoid exports in filter.c
We can approach it from the pov of minimizing exports,
but such steps won't give us clarity on how portable such
modular verifier will be.
Other questions to answer is whether maps should be in the module too.
Modules can provide their kfuncs already, so existing kfuncs
can stay where they are.

Namespacing into "bpf_internal" as Stanislav suggested is
a good thing too with a warning somewhere in Documentation/bpf/
that these must only be used by the verifier.
diff mbox series

Patch

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 9e5fe2ba858f..1319e9e47540 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3704,6 +3704,7 @@  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 					   tmp : orig_prog);
 	return prog;
 }
+EXPORT_SYMBOL_GPL(bpf_int_jit_compile);
 
 bool bpf_jit_supports_kfunc_call(void)
 {
@@ -3762,6 +3763,7 @@  void bpf_jit_free(struct bpf_prog *prog)
 
 	bpf_prog_unlock_free(prog);
 }
+EXPORT_SYMBOL_GPL(bpf_jit_free);
 
 bool bpf_jit_supports_exceptions(void)
 {
diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c
index 2f7564f26445..c9d421c3ee6f 100644
--- a/drivers/media/rc/bpf-lirc.c
+++ b/drivers/media/rc/bpf-lirc.c
@@ -131,6 +131,7 @@  const struct bpf_verifier_ops lirc_mode2_verifier_ops = {
 	.get_func_proto  = lirc_mode2_func_proto,
 	.is_valid_access = lirc_mode2_is_valid_access
 };
+EXPORT_SYMBOL_GPL(lirc_mode2_verifier_ops);
 
 #define BPF_MAX_PROGS 64
 
diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c
index 08412532db1b..55ee6e79de3c 100644
--- a/fs/bpf_fs_kfuncs.c
+++ b/fs/bpf_fs_kfuncs.c
@@ -6,6 +6,7 @@ 
 #include <linux/btf.h>
 #include <linux/btf_ids.h>
 #include <linux/dcache.h>
+#include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/fsnotify.h>
 #include <linux/file.h>
@@ -231,6 +232,7 @@  int bpf_set_dentry_xattr_locked(struct dentry *dentry, const char *name__str,
 	}
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_set_dentry_xattr_locked);
 
 /**
  * bpf_remove_dentry_xattr_locked - remove a xattr of a dentry
@@ -266,6 +268,7 @@  int bpf_remove_dentry_xattr_locked(struct dentry *dentry, const char *name__str)
 	}
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_remove_dentry_xattr_locked);
 
 __bpf_kfunc_start_defs();
 
@@ -373,6 +376,7 @@  bool bpf_lsm_has_d_inode_locked(const struct bpf_prog *prog)
 {
 	return btf_id_set_contains(&d_inode_locked_hooks, prog->aux->attach_btf_id);
 }
+EXPORT_SYMBOL_GPL(bpf_lsm_has_d_inode_locked);
 
 static const struct btf_kfunc_id_set bpf_fs_kfunc_set = {
 	.owner = THIS_MODULE,
diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c
index 380e9a7cac75..2e015b08c6cc 100644
--- a/kernel/bpf/bpf_iter.c
+++ b/kernel/bpf/bpf_iter.c
@@ -366,6 +366,7 @@  int bpf_iter_prog_supported(struct bpf_prog *prog)
 	return bpf_prog_ctx_arg_info_init(prog, tinfo->reg_info->ctx_arg_info,
 					  tinfo->reg_info->ctx_arg_info_size);
 }
+EXPORT_SYMBOL_GPL(bpf_iter_prog_supported);
 
 const struct bpf_func_proto *
 bpf_iter_get_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index 0a59df1c550a..417790c4b0f7 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -8,6 +8,7 @@ 
 #include <linux/bpf.h>
 #include <linux/btf.h>
 #include <linux/binfmts.h>
+#include <linux/export.h>
 #include <linux/lsm_hooks.h>
 #include <linux/bpf_lsm.h>
 #include <linux/kallsyms.h>
@@ -137,6 +138,7 @@  int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_lsm_verify_prog);
 
 /* Mask for all the currently supported BPRM option flags */
 #define BPF_F_BRPM_OPTS_MASK	BPF_F_BPRM_SECUREEXEC
@@ -399,6 +401,7 @@  bool bpf_lsm_is_sleepable_hook(u32 btf_id)
 {
 	return btf_id_set_contains(&sleepable_lsm_hooks, btf_id);
 }
+EXPORT_SYMBOL_GPL(bpf_lsm_is_sleepable_hook);
 
 bool bpf_lsm_is_trusted(const struct bpf_prog *prog)
 {
@@ -412,6 +415,7 @@  const struct bpf_verifier_ops lsm_verifier_ops = {
 	.get_func_proto = bpf_lsm_func_proto,
 	.is_valid_access = btf_ctx_access,
 };
+EXPORT_SYMBOL_GPL(lsm_verifier_ops);
 
 /* hooks return 0 or 1 */
 BTF_SET_START(bool_lsm_hooks)
@@ -445,3 +449,4 @@  int bpf_lsm_get_retval_range(const struct bpf_prog *prog,
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_lsm_get_retval_range);
diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
index db13ee70d94d..10abed11082e 100644
--- a/kernel/bpf/bpf_struct_ops.c
+++ b/kernel/bpf/bpf_struct_ops.c
@@ -68,6 +68,7 @@  static DEFINE_MUTEX(update_mutex);
 
 const struct bpf_verifier_ops bpf_struct_ops_verifier_ops = {
 };
+EXPORT_SYMBOL_GPL(bpf_struct_ops_verifier_ops);
 
 const struct bpf_prog_ops bpf_struct_ops_prog_ops = {
 #ifdef CONFIG_NET
@@ -327,6 +328,7 @@  int bpf_struct_ops_supported(const struct bpf_struct_ops *st_ops, u32 moff)
 
 	return func_ptr ? 0 : -ENOTSUPP;
 }
+EXPORT_SYMBOL_GPL(bpf_struct_ops_supported);
 
 int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
 			     struct btf *btf,
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 5b38c90e1184..91cc0fcd29e9 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -9,6 +9,7 @@ 
 #include <linux/compiler.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/anon_inodes.h>
 #include <linux/file.h>
@@ -347,6 +348,7 @@  const char *btf_type_str(const struct btf_type *t)
 {
 	return btf_kind_str[BTF_INFO_KIND(t->info)];
 }
+EXPORT_SYMBOL_GPL(btf_type_str);
 
 /* Chunk size we use in safe copy of data to be shown. */
 #define BTF_SHOW_OBJ_SAFE_SIZE		32
@@ -497,6 +499,7 @@  bool btf_type_is_void(const struct btf_type *t)
 {
 	return t == &btf_void;
 }
+EXPORT_SYMBOL_GPL(btf_type_is_void);
 
 static bool btf_type_is_datasec(const struct btf_type *t)
 {
@@ -542,6 +545,7 @@  u32 btf_nr_types(const struct btf *btf)
 
 	return total;
 }
+EXPORT_SYMBOL_GPL(btf_nr_types);
 
 s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind)
 {
@@ -562,6 +566,7 @@  s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind)
 
 	return -ENOENT;
 }
+EXPORT_SYMBOL_GPL(btf_find_by_name_kind);
 
 struct btf *bpf_get_btf_vmlinux(void)
 {
@@ -635,6 +640,7 @@  const struct btf_type *btf_type_skip_modifiers(const struct btf *btf,
 
 	return t;
 }
+EXPORT_SYMBOL_GPL(btf_type_skip_modifiers);
 
 const struct btf_type *btf_type_resolve_ptr(const struct btf *btf,
 					    u32 id, u32 *res_id)
@@ -647,6 +653,7 @@  const struct btf_type *btf_type_resolve_ptr(const struct btf *btf,
 
 	return btf_type_skip_modifiers(btf, t->type, res_id);
 }
+EXPORT_SYMBOL_GPL(btf_type_resolve_ptr);
 
 const struct btf_type *btf_type_resolve_func_ptr(const struct btf *btf,
 						 u32 id, u32 *res_id)
@@ -659,6 +666,7 @@  const struct btf_type *btf_type_resolve_func_ptr(const struct btf *btf,
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(btf_type_resolve_func_ptr);
 
 /* Types that act only as a source, not sink or intermediate
  * type when resolving.
@@ -855,6 +863,7 @@  const char *btf_name_by_offset(const struct btf *btf, u32 offset)
 {
 	return btf_str_by_offset(btf, offset);
 }
+EXPORT_SYMBOL_GPL(btf_name_by_offset);
 
 const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id)
 {
@@ -1760,11 +1769,13 @@  const char *btf_get_name(const struct btf *btf)
 {
 	return btf->name;
 }
+EXPORT_SYMBOL_GPL(btf_get_name);
 
 void btf_get(struct btf *btf)
 {
 	refcount_inc(&btf->refcnt);
 }
+EXPORT_SYMBOL_GPL(btf_get);
 
 void btf_put(struct btf *btf)
 {
@@ -1773,6 +1784,7 @@  void btf_put(struct btf *btf)
 		call_rcu(&btf->rcu, btf_free_rcu);
 	}
 }
+EXPORT_SYMBOL_GPL(btf_put);
 
 struct btf *btf_base_btf(const struct btf *btf)
 {
@@ -2018,6 +2030,7 @@  btf_resolve_size(const struct btf *btf, const struct btf_type *type,
 {
 	return __btf_resolve_size(btf, type, type_size, NULL, NULL, NULL, NULL);
 }
+EXPORT_SYMBOL_GPL(btf_resolve_size);
 
 static u32 btf_resolved_type_id(const struct btf *btf, u32 type_id)
 {
@@ -3433,6 +3446,7 @@  const char *btf_find_decl_tag_value(const struct btf *btf, const struct btf_type
 
 	return value;
 }
+EXPORT_SYMBOL_GPL(btf_find_decl_tag_value);
 
 static int
 btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
@@ -5701,6 +5715,7 @@  struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id)
 		return NULL;
 	return bsearch(&btf_id, tab->types, tab->cnt, sizeof(tab->types[0]), btf_id_cmp_func);
 }
+EXPORT_SYMBOL_GPL(btf_find_struct_meta);
 
 static int btf_check_type_tags(struct btf_verifier_env *env,
 			       struct btf *btf, int start_id)
@@ -5946,6 +5961,7 @@  bool btf_is_projection_of(const char *pname, const char *tname)
 		return true;
 	return false;
 }
+EXPORT_SYMBOL_GPL(btf_is_projection_of);
 
 bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
 			  const struct btf_type *t, enum bpf_prog_type prog_type,
@@ -6023,6 +6039,7 @@  bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
 	}
 	return true;
 }
+EXPORT_SYMBOL_GPL(btf_is_prog_ctx_type);
 
 /* forward declarations for arch-specific underlying types of
  * bpf_user_pt_regs_t; this avoids the need for arch-specific #ifdef
@@ -6197,6 +6214,7 @@  int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_ty
 
 	return kctx_type_id;
 }
+EXPORT_SYMBOL_GPL(get_kern_ctx_btf_id);
 
 BTF_ID_LIST(bpf_ctx_convert_btf_id)
 BTF_ID(struct, bpf_ctx_convert)
@@ -6280,6 +6298,7 @@  struct btf *btf_parse_vmlinux(void)
 	btf_verifier_env_free(env);
 	return btf;
 }
+EXPORT_SYMBOL_GPL(btf_parse_vmlinux);
 
 /* If .BTF_ids section was created with distilled base BTF, both base and
  * split BTF ids will need to be mapped to actual base/split ids for
@@ -7257,6 +7276,7 @@  int btf_struct_access(struct bpf_verifier_log *log,
 
 	return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(btf_struct_access);
 
 /* Check that two BTF types, each specified as an BTF object + id, are exactly
  * the same. Trivial ID check is not enough due to module BTFs, because we can
@@ -7272,6 +7292,7 @@  bool btf_types_are_same(const struct btf *btf1, u32 id1,
 		return true;
 	return btf_type_by_id(btf1, id1) == btf_type_by_id(btf2, id2);
 }
+EXPORT_SYMBOL_GPL(btf_types_are_same);
 
 bool btf_struct_ids_match(struct bpf_verifier_log *log,
 			  const struct btf *btf, u32 id, int off,
@@ -7311,6 +7332,7 @@  bool btf_struct_ids_match(struct bpf_verifier_log *log,
 
 	return true;
 }
+EXPORT_SYMBOL_GPL(btf_struct_ids_match);
 
 static int __get_type_size(struct btf *btf, u32 btf_id,
 			   const struct btf_type **ret_type)
@@ -7417,6 +7439,7 @@  int btf_distill_func_proto(struct bpf_verifier_log *log,
 	m->nr_args = nargs;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(btf_distill_func_proto);
 
 /* Compare BTFs of two functions assuming only scalars and pointers to context.
  * t1 points to BTF_KIND_FUNC in btf1
@@ -7559,6 +7582,7 @@  int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *pr
 
 	return btf_check_func_type_match(log, btf1, t1, btf2, t2);
 }
+EXPORT_SYMBOL_GPL(btf_check_type_match);
 
 static bool btf_is_dynptr_ptr(const struct btf *btf, const struct btf_type *t)
 {
@@ -7872,6 +7896,7 @@  int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(btf_prepare_func_args);
 
 static void btf_type_show(const struct btf *btf, u32 type_id, void *obj,
 			  struct btf_show *show)
@@ -7983,6 +8008,7 @@  const struct file_operations btf_fops = {
 #endif
 	.release	= btf_release,
 };
+EXPORT_SYMBOL_GPL(btf_fops);
 
 static int __btf_new_fd(struct btf *btf)
 {
@@ -8028,6 +8054,7 @@  struct btf *btf_get_by_fd(int fd)
 
 	return btf;
 }
+EXPORT_SYMBOL_GPL(btf_get_by_fd);
 
 int btf_get_info_by_fd(const struct btf *btf,
 		       const union bpf_attr *attr,
@@ -8114,16 +8141,19 @@  u32 btf_obj_id(const struct btf *btf)
 {
 	return btf->id;
 }
+EXPORT_SYMBOL_GPL(btf_obj_id);
 
 bool btf_is_kernel(const struct btf *btf)
 {
 	return btf->kernel_btf;
 }
+EXPORT_SYMBOL_GPL(btf_is_kernel);
 
 bool btf_is_module(const struct btf *btf)
 {
 	return btf->kernel_btf && strcmp(btf->name, "vmlinux") != 0;
 }
+EXPORT_SYMBOL_GPL(btf_is_module);
 
 enum {
 	BTF_MODULE_F_LIVE = (1 << 0),
@@ -8289,6 +8319,7 @@  struct module *btf_try_get_module(const struct btf *btf)
 
 	return res;
 }
+EXPORT_SYMBOL_GPL(btf_try_get_module);
 
 /* Returns struct btf corresponding to the struct module.
  * This function can return NULL or ERR_PTR.
@@ -8374,6 +8405,7 @@  BTF_ID_LIST_GLOBAL(btf_tracing_ids, MAX_BTF_TRACING_TYPE)
 #define BTF_TRACING_TYPE(name, type) BTF_ID(struct, type)
 BTF_TRACING_TYPE_xxx
 #undef BTF_TRACING_TYPE
+EXPORT_SYMBOL_GPL(btf_tracing_ids);
 
 /* Validate well-formedness of iter argument type.
  * On success, return positive BTF ID of iter state's STRUCT type.
@@ -8403,6 +8435,7 @@  int btf_check_iter_arg(struct btf *btf, const struct btf_type *func, int arg_idx
 
 	return btf_id;
 }
+EXPORT_SYMBOL_GPL(btf_check_iter_arg);
 
 static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
 				 const struct btf_type *func, u32 func_flags)
@@ -8708,12 +8741,14 @@  u32 *btf_kfunc_id_set_contains(const struct btf *btf,
 	hook = bpf_prog_type_to_kfunc_hook(prog_type);
 	return __btf_kfunc_id_set_contains(btf, hook, kfunc_btf_id, prog);
 }
+EXPORT_SYMBOL_GPL(btf_kfunc_id_set_contains);
 
 u32 *btf_kfunc_is_modify_return(const struct btf *btf, u32 kfunc_btf_id,
 				const struct bpf_prog *prog)
 {
 	return __btf_kfunc_id_set_contains(btf, BTF_KFUNC_HOOK_FMODRET, kfunc_btf_id, prog);
 }
+EXPORT_SYMBOL_GPL(btf_kfunc_is_modify_return);
 
 static int __register_btf_kfunc_id_set(enum btf_kfunc_hook hook,
 				       const struct btf_kfunc_id_set *kset)
@@ -9311,6 +9346,7 @@  int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,
 	}
 	return err;
 }
+EXPORT_SYMBOL_GPL(bpf_core_apply);
 
 bool btf_nested_type_is_trusted(struct bpf_verifier_log *log,
 				const struct bpf_reg_state *reg,
@@ -9358,6 +9394,7 @@  bool btf_nested_type_is_trusted(struct bpf_verifier_log *log,
 
 	return false;
 }
+EXPORT_SYMBOL_GPL(btf_nested_type_is_trusted);
 
 bool btf_type_ids_nocast_alias(struct bpf_verifier_log *log,
 			       const struct btf *reg_btf, u32 reg_id,
@@ -9413,6 +9450,7 @@  bool btf_type_ids_nocast_alias(struct bpf_verifier_log *log,
 
 	return !strncmp(reg_name, arg_name, cmp_len);
 }
+EXPORT_SYMBOL_GPL(btf_type_ids_nocast_alias);
 
 #ifdef CONFIG_BPF_JIT
 static int
@@ -9502,6 +9540,7 @@  bpf_struct_ops_find(struct btf *btf, u32 type_id)
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(bpf_struct_ops_find);
 
 int __register_bpf_struct_ops(struct bpf_struct_ops *st_ops)
 {
@@ -9551,3 +9590,4 @@  bool btf_param_match_suffix(const struct btf *btf,
 	param_name += len - suffix_len;
 	return !strncmp(param_name, suffix, suffix_len);
 }
+EXPORT_SYMBOL_GPL(btf_param_match_suffix);
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 84f58f3d028a..3168389a2972 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -8,6 +8,7 @@ 
 #include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/cgroup.h>
+#include <linux/export.h>
 #include <linux/filter.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
@@ -1702,6 +1703,7 @@  const struct bpf_verifier_ops cg_dev_verifier_ops = {
 	.get_func_proto		= cgroup_dev_func_proto,
 	.is_valid_access	= cgroup_dev_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(cg_dev_verifier_ops);
 
 /**
  * __cgroup_bpf_run_filter_sysctl - Run a program on sysctl
@@ -2322,6 +2324,7 @@  const struct bpf_verifier_ops cg_sysctl_verifier_ops = {
 	.is_valid_access	= sysctl_is_valid_access,
 	.convert_ctx_access	= sysctl_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(cg_sysctl_verifier_ops);
 
 const struct bpf_prog_ops cg_sysctl_prog_ops = {
 };
@@ -2550,6 +2553,7 @@  const struct bpf_verifier_ops cg_sockopt_verifier_ops = {
 	.convert_ctx_access	= cg_sockopt_convert_ctx_access,
 	.gen_prologue		= cg_sockopt_get_prologue,
 };
+EXPORT_SYMBOL_GPL(cg_sockopt_verifier_ops);
 
 const struct bpf_prog_ops cg_sockopt_prog_ops = {
 };
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 13301a668fe0..6c8bb4cdac0f 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -69,6 +69,7 @@ 
 
 struct bpf_mem_alloc bpf_global_ma;
 bool bpf_global_ma_set;
+EXPORT_SYMBOL_GPL(bpf_global_ma_set);
 
 struct bpf_mem_alloc bpf_global_percpu_ma;
 EXPORT_SYMBOL_GPL(bpf_global_percpu_ma);
@@ -510,6 +511,7 @@  struct bpf_prog *bpf_prog_alloc_no_stats(unsigned int size, gfp_t gfp_extra_flag
 
 	return fp;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_alloc_no_stats);
 
 struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags)
 {
@@ -552,6 +554,7 @@  int bpf_prog_alloc_jited_linfo(struct bpf_prog *prog)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_alloc_jited_linfo);
 
 void bpf_prog_jit_attempt_done(struct bpf_prog *prog)
 {
@@ -564,6 +567,7 @@  void bpf_prog_jit_attempt_done(struct bpf_prog *prog)
 	kfree(prog->aux->kfunc_tab);
 	prog->aux->kfunc_tab = NULL;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_jit_attempt_done);
 
 /* The jit engine is responsible to provide an array
  * for insn_off to the jited_off mapping (insn_to_jit_off).
@@ -733,6 +737,7 @@  int bpf_prog_calc_tag(struct bpf_prog *fp)
 	vfree(raw);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_calc_tag);
 
 static int bpf_adj_delta_to_imm(struct bpf_insn *insn, u32 pos, s32 end_old,
 				s32 end_new, s32 curr, const bool probe_pass)
@@ -910,6 +915,7 @@  struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
 
 	return prog_adj;
 }
+EXPORT_SYMBOL_GPL(bpf_patch_insn_single);
 
 int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
 {
@@ -926,6 +932,7 @@  int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
 	WARN_ON_ONCE(err);
 	return err;
 }
+EXPORT_SYMBOL_GPL(bpf_remove_insns);
 
 static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
 {
@@ -1093,6 +1100,7 @@  void bpf_prog_kallsyms_add(struct bpf_prog *fp)
 	bpf_ksym_add(&fp->aux->ksym_prefix);
 #endif
 }
+EXPORT_SYMBOL_GPL(bpf_prog_kallsyms_add);
 
 void bpf_prog_kallsyms_del(struct bpf_prog *fp)
 {
@@ -1238,6 +1246,7 @@  int bpf_jit_add_poke_descriptor(struct bpf_prog *prog,
 
 	return slot;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_add_poke_descriptor);
 
 /*
  * BPF program pack allocator.
@@ -2129,6 +2138,7 @@  bool bpf_opcode_in_insntable(u8 code)
 #undef BPF_INSN_2_TBL
 	return public_insntable[code];
 }
+EXPORT_SYMBOL_GPL(bpf_opcode_in_insntable);
 
 #ifndef CONFIG_BPF_JIT_ALWAYS_ON
 /**
@@ -3237,6 +3247,7 @@  void __bpf_free_used_maps(struct bpf_prog_aux *aux,
 		bpf_map_put(map);
 	}
 }
+EXPORT_SYMBOL_GPL(__bpf_free_used_maps);
 
 static void bpf_free_used_maps(struct bpf_prog_aux *aux)
 {
@@ -3258,6 +3269,7 @@  void __bpf_free_used_btfs(struct btf_mod_pair *used_btfs, u32 len)
 	}
 #endif
 }
+EXPORT_SYMBOL_GPL(__bpf_free_used_btfs);
 
 static void bpf_free_used_btfs(struct bpf_prog_aux *aux)
 {
@@ -3336,6 +3348,7 @@  void bpf_user_rnd_init_once(void)
 {
 	prandom_init_once(&bpf_user_rnd_state);
 }
+EXPORT_SYMBOL_GPL(bpf_user_rnd_init_once);
 
 BPF_CALL_0(bpf_user_rnd_u32)
 {
@@ -3445,6 +3458,7 @@  bool __weak bpf_helper_changes_pkt_data(enum bpf_func_id func_id)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_helper_changes_pkt_data);
 
 /* Return TRUE if the JIT backend wants verifier to enable sub-register usage
  * analysis code and wants explicit zero extension inserted by verifier.
@@ -3458,6 +3472,7 @@  bool __weak bpf_jit_needs_zext(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_needs_zext);
 
 /* Return true if the JIT inlines the call to the helper corresponding to
  * the imm.
@@ -3469,37 +3484,44 @@  bool __weak bpf_jit_inlines_helper_call(s32 imm)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_inlines_helper_call);
 
 /* Return TRUE if the JIT backend supports mixing bpf2bpf and tailcalls. */
 bool __weak bpf_jit_supports_subprog_tailcalls(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_subprog_tailcalls);
 
 bool __weak bpf_jit_supports_percpu_insn(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_percpu_insn);
 
 bool __weak bpf_jit_supports_kfunc_call(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_kfunc_call);
 
 bool __weak bpf_jit_supports_far_kfunc_call(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_far_kfunc_call);
 
 bool __weak bpf_jit_supports_arena(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_arena);
 
 bool __weak bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_insn);
 
 u64 __weak bpf_arch_uaddress_limit(void)
 {
@@ -3509,6 +3531,7 @@  u64 __weak bpf_arch_uaddress_limit(void)
 	return 0;
 #endif
 }
+EXPORT_SYMBOL_GPL(bpf_arch_uaddress_limit);
 
 /* Return TRUE if the JIT backend satisfies the following two conditions:
  * 1) JIT backend supports atomic_xchg() on pointer-sized words.
@@ -3519,6 +3542,7 @@  bool __weak bpf_jit_supports_ptr_xchg(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_ptr_xchg);
 
 /* To execute LD_ABS/LD_IND instructions __bpf_prog_run() may call
  * skb_copy_bits(), so provide a weak definition of it for NET-less config.
@@ -3549,11 +3573,13 @@  bool __weak bpf_jit_supports_exceptions(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_exceptions);
 
 bool __weak bpf_jit_supports_private_stack(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_private_stack);
 
 void __weak arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie)
 {
@@ -3563,11 +3589,13 @@  bool __weak bpf_jit_supports_timed_may_goto(void)
 {
 	return false;
 }
+EXPORT_SYMBOL_GPL(bpf_jit_supports_timed_may_goto);
 
 u64 __weak arch_bpf_timed_may_goto(void)
 {
 	return 0;
 }
+EXPORT_SYMBOL_GPL(arch_bpf_timed_may_goto);
 
 u64 bpf_check_timed_may_goto(struct bpf_timed_may_goto *p)
 {
@@ -3591,6 +3619,7 @@  __weak u64 bpf_arena_get_user_vm_start(struct bpf_arena *arena)
 {
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_arena_get_user_vm_start);
 __weak u64 bpf_arena_get_kern_vm_start(struct bpf_arena *arena)
 {
 	return 0;
diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c
index 20883c6b1546..ab441a6b8b54 100644
--- a/kernel/bpf/disasm.c
+++ b/kernel/bpf/disasm.c
@@ -4,6 +4,7 @@ 
  */
 
 #include <linux/bpf.h>
+#include <linux/export.h>
 
 #include "disasm.h"
 
@@ -58,6 +59,7 @@  const char *func_id_name(int id)
 	else
 		return "unknown";
 }
+EXPORT_SYMBOL_GPL(func_id_name);
 
 const char *const bpf_class_string[8] = {
 	[BPF_LD]    = "ld",
@@ -86,6 +88,7 @@  const char *const bpf_alu_string[16] = {
 	[BPF_ARSH >> 4] = "s>>=",
 	[BPF_END >> 4]  = "endian",
 };
+EXPORT_SYMBOL_GPL(bpf_alu_string);
 
 static const char *const bpf_alu_sign_string[16] = {
 	[BPF_DIV >> 4]  = "s/=",
@@ -388,3 +391,4 @@  void print_bpf_insn(const struct bpf_insn_cbs *cbs,
 			insn->code, bpf_class_string[class]);
 	}
 }
+EXPORT_SYMBOL_GPL(print_bpf_insn);
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index e3a2662f4e33..46816949b78f 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -5,6 +5,7 @@ 
 #include <linux/btf.h>
 #include <linux/bpf-cgroup.h>
 #include <linux/cgroup.h>
+#include <linux/export.h>
 #include <linux/rcupdate.h>
 #include <linux/random.h>
 #include <linux/smp.h>
@@ -1041,6 +1042,7 @@  int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args,
 		bpf_bprintf_cleanup(data);
 	return err;
 }
+EXPORT_SYMBOL_GPL(bpf_bprintf_prepare);
 
 BPF_CALL_5(bpf_snprintf, char *, str, u32, str_size, char *, fmt,
 	   const void *, args, u32, data_len)
diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 3969eb0382af..1743d1f434fc 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -4,6 +4,7 @@ 
 #include <linux/bpf_local_storage.h>
 #include <linux/btf.h>
 #include <linux/bug.h>
+#include <linux/export.h>
 #include <linux/filter.h>
 #include <linux/mm.h>
 #include <linux/rbtree.h>
@@ -478,6 +479,7 @@  int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *_map)
 	aux->cgroup_storage[stype] = _map;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_cgroup_storage_assign);
 
 static size_t bpf_cgroup_storage_calculate_size(struct bpf_map *map, u32 *pages)
 {
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index 38050f4ee400..0ed4e0b89fdf 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -8,6 +8,7 @@ 
 #include <linux/types.h>
 #include <linux/bpf.h>
 #include <linux/bpf_verifier.h>
+#include <linux/export.h>
 #include <linux/math64.h>
 #include <linux/string.h>
 
@@ -41,6 +42,7 @@  int bpf_vlog_init(struct bpf_verifier_log *log, u32 log_level,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_vlog_init);
 
 static void bpf_vlog_update_len_max(struct bpf_verifier_log *log, u32 add_len)
 {
@@ -145,6 +147,7 @@  void bpf_verifier_vlog(struct bpf_verifier_log *log, const char *fmt,
 fail:
 	log->ubuf = NULL;
 }
+EXPORT_SYMBOL_GPL(bpf_verifier_vlog);
 
 void bpf_vlog_reset(struct bpf_verifier_log *log, u64 new_pos)
 {
@@ -176,6 +179,7 @@  void bpf_vlog_reset(struct bpf_verifier_log *log, u64 new_pos)
 	if (pos < log->len_total && put_user(zero, log->ubuf + pos))
 		log->ubuf = NULL;
 }
+EXPORT_SYMBOL_GPL(bpf_vlog_reset);
 
 static void bpf_vlog_reverse_kbuf(char *buf, int len)
 {
@@ -296,6 +300,7 @@  int bpf_vlog_finalize(struct bpf_verifier_log *log, u32 *log_size_actual)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_vlog_finalize);
 
 /* log_level controls verbosity level of eBPF verifier.
  * bpf_verifier_log_write() is used to dump the verification trace to the log,
@@ -426,6 +431,7 @@  __printf(3, 4) void verbose_linfo(struct bpf_verifier_env *env,
 
 	env->prev_linfo = linfo;
 }
+EXPORT_SYMBOL_GPL(verbose_linfo);
 
 static const char *btf_type_name(const struct btf *btf, u32 id)
 {
@@ -486,6 +492,7 @@  const char *reg_type_str(struct bpf_verifier_env *env, enum bpf_reg_type type)
 		 prefix, str[base_type(type)], postfix);
 	return env->tmp_str_buf;
 }
+EXPORT_SYMBOL_GPL(reg_type_str);
 
 const char *dynptr_type_str(enum bpf_dynptr_type type)
 {
@@ -505,6 +512,7 @@  const char *dynptr_type_str(enum bpf_dynptr_type type)
 		return "<unknown>";
 	}
 }
+EXPORT_SYMBOL_GPL(dynptr_type_str);
 
 const char *iter_type_str(const struct btf *btf, u32 btf_id)
 {
@@ -514,6 +522,7 @@  const char *iter_type_str(const struct btf *btf, u32 btf_id)
 	/* we already validated that type is valid and has conforming name */
 	return btf_type_name(btf, btf_id) + sizeof(ITER_PREFIX) - 1;
 }
+EXPORT_SYMBOL_GPL(iter_type_str);
 
 const char *iter_state_str(enum bpf_iter_state state)
 {
@@ -529,6 +538,7 @@  const char *iter_state_str(enum bpf_iter_state state)
 		return "<unknown>";
 	}
 }
+EXPORT_SYMBOL_GPL(iter_state_str);
 
 static char slot_type_char[] = {
 	[STACK_INVALID]	= '?',
@@ -859,6 +869,7 @@  void print_verifier_state(struct bpf_verifier_env *env, const struct bpf_verifie
 	if (!print_all)
 		mark_verifier_state_clean(env);
 }
+EXPORT_SYMBOL_GPL(print_verifier_state);
 
 static inline u32 vlog_alignment(u32 pos)
 {
@@ -878,3 +889,4 @@  void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
 	}
 	print_verifier_state(env, vstate, frameno, false);
 }
+EXPORT_SYMBOL_GPL(print_insn_state);
diff --git a/kernel/bpf/map_iter.c b/kernel/bpf/map_iter.c
index 9575314f40a6..e6c3142b9e91 100644
--- a/kernel/bpf/map_iter.c
+++ b/kernel/bpf/map_iter.c
@@ -79,6 +79,7 @@  static const struct seq_operations bpf_map_seq_ops = {
 };
 
 BTF_ID_LIST_GLOBAL_SINGLE(btf_bpf_map_id, struct, bpf_map)
+EXPORT_SYMBOL_GPL(btf_bpf_map_id);
 
 static const struct bpf_iter_seq_info bpf_map_seq_info = {
 	.seq_ops		= &bpf_map_seq_ops,
diff --git a/kernel/bpf/memalloc.c b/kernel/bpf/memalloc.c
index 889374722d0a..a35079962965 100644
--- a/kernel/bpf/memalloc.c
+++ b/kernel/bpf/memalloc.c
@@ -3,6 +3,7 @@ 
 #include <linux/mm.h>
 #include <linux/llist.h>
 #include <linux/bpf.h>
+#include <linux/export.h>
 #include <linux/irq_work.h>
 #include <linux/bpf_mem_alloc.h>
 #include <linux/memcontrol.h>
@@ -587,6 +588,7 @@  int bpf_mem_alloc_percpu_init(struct bpf_mem_alloc *ma, struct obj_cgroup *objcg
 	ma->percpu = true;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_mem_alloc_percpu_init);
 
 int bpf_mem_alloc_percpu_unit_init(struct bpf_mem_alloc *ma, int size)
 {
@@ -623,6 +625,7 @@  int bpf_mem_alloc_percpu_unit_init(struct bpf_mem_alloc *ma, int size)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_mem_alloc_percpu_unit_init);
 
 static void drain_mem_cache(struct bpf_mem_cache *c)
 {
diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c
index 42ae8d595c2c..e20d0e9f5fed 100644
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@ -16,6 +16,7 @@ 
 #include <linux/bpf.h>
 #include <linux/bpf_verifier.h>
 #include <linux/bug.h>
+#include <linux/export.h>
 #include <linux/kdev_t.h>
 #include <linux/list.h>
 #include <linux/lockdep.h>
@@ -309,6 +310,7 @@  int bpf_prog_offload_verifier_prep(struct bpf_prog *prog)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_offload_verifier_prep);
 
 int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env,
 				 int insn_idx, int prev_insn_idx)
@@ -325,6 +327,7 @@  int bpf_prog_offload_verify_insn(struct bpf_verifier_env *env,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_offload_verify_insn);
 
 int bpf_prog_offload_finalize(struct bpf_verifier_env *env)
 {
@@ -343,6 +346,7 @@  int bpf_prog_offload_finalize(struct bpf_verifier_env *env)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_offload_finalize);
 
 void
 bpf_prog_offload_replace_insn(struct bpf_verifier_env *env, u32 off,
@@ -362,6 +366,7 @@  bpf_prog_offload_replace_insn(struct bpf_verifier_env *env, u32 off,
 	}
 	up_read(&bpf_devs_lock);
 }
+EXPORT_SYMBOL_GPL(bpf_prog_offload_replace_insn);
 
 void
 bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt)
@@ -378,6 +383,7 @@  bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt)
 	}
 	up_read(&bpf_devs_lock);
 }
+EXPORT_SYMBOL_GPL(bpf_prog_offload_remove_insns);
 
 void bpf_prog_dev_bound_destroy(struct bpf_prog *prog)
 {
@@ -744,6 +750,7 @@  bool bpf_prog_dev_bound_match(const struct bpf_prog *lhs, const struct bpf_prog
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_prog_dev_bound_match);
 
 bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map)
 {
@@ -760,6 +767,7 @@  bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bpf_offload_prog_map_match);
 
 int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
 				    struct net_device *netdev)
@@ -840,6 +848,7 @@  int bpf_dev_bound_kfunc_check(struct bpf_verifier_log *log,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_dev_bound_kfunc_check);
 
 void *bpf_dev_bound_resolve_kfunc(struct bpf_prog *prog, u32 func_id)
 {
@@ -869,6 +878,7 @@  void *bpf_dev_bound_resolve_kfunc(struct bpf_prog *prog, u32 func_id)
 
 	return p;
 }
+EXPORT_SYMBOL_GPL(bpf_dev_bound_resolve_kfunc);
 
 static int __init bpf_offload_init(void)
 {
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 9794446bc8c6..2ef55503ba32 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -8,6 +8,7 @@ 
 #include <linux/bpf_verifier.h>
 #include <linux/bsearch.h>
 #include <linux/btf.h>
+#include <linux/export.h>
 #include <linux/syscalls.h>
 #include <linux/slab.h>
 #include <linux/sched/signal.h>
@@ -104,6 +105,7 @@  int bpf_check_uarg_tail_zero(bpfptr_t uaddr,
 		return res;
 	return res ? 0 : -E2BIG;
 }
+EXPORT_SYMBOL_GPL(bpf_check_uarg_tail_zero);
 
 const struct bpf_map_ops bpf_map_offload_ops = {
 	.map_meta_equal = bpf_map_meta_equal,
@@ -112,6 +114,7 @@  const struct bpf_map_ops bpf_map_offload_ops = {
 	.map_check_btf = map_check_no_btf,
 	.map_mem_usage = bpf_map_offload_map_mem_usage,
 };
+EXPORT_SYMBOL_GPL(bpf_map_offload_ops);
 
 static void bpf_map_write_active_inc(struct bpf_map *map)
 {
@@ -127,6 +130,7 @@  bool bpf_map_write_active(const struct bpf_map *map)
 {
 	return atomic64_read(&map->writecnt) != 0;
 }
+EXPORT_SYMBOL_GPL(bpf_map_write_active);
 
 static u32 bpf_map_value_size(const struct bpf_map *map)
 {
@@ -642,6 +646,7 @@  struct btf_field *btf_record_find(const struct btf_record *rec, u32 offset,
 		return NULL;
 	return field;
 }
+EXPORT_SYMBOL_GPL(btf_record_find);
 
 void btf_record_free(struct btf_record *rec)
 {
@@ -1145,6 +1150,7 @@  const struct file_operations bpf_map_fops = {
 	.poll		= bpf_map_poll,
 	.get_unmapped_area = bpf_get_unmapped_area,
 };
+EXPORT_SYMBOL_GPL(bpf_map_fops);
 
 int bpf_map_new_fd(struct bpf_map *map, int flags)
 {
@@ -6103,6 +6109,7 @@  const struct bpf_verifier_ops bpf_syscall_verifier_ops = {
 	.get_func_proto  = syscall_prog_func_proto,
 	.is_valid_access = syscall_prog_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(bpf_syscall_verifier_ops);
 
 const struct bpf_prog_ops bpf_syscall_prog_ops = {
 	.test_run = bpf_prog_test_run_syscall,
diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c
index 9dbc31b25e3d..2f815447ace7 100644
--- a/kernel/bpf/tnum.c
+++ b/kernel/bpf/tnum.c
@@ -12,11 +12,13 @@ 
 #define TNUM(_v, _m)	(struct tnum){.value = _v, .mask = _m}
 /* A completely unknown value */
 const struct tnum tnum_unknown = { .value = 0, .mask = -1 };
+EXPORT_SYMBOL_GPL(tnum_unknown);
 
 struct tnum tnum_const(u64 value)
 {
 	return TNUM(value, 0);
 }
+EXPORT_SYMBOL_GPL(tnum_const);
 
 struct tnum tnum_range(u64 min, u64 max)
 {
@@ -33,16 +35,19 @@  struct tnum tnum_range(u64 min, u64 max)
 	delta = (1ULL << bits) - 1;
 	return TNUM(min & ~delta, delta);
 }
+EXPORT_SYMBOL_GPL(tnum_range);
 
 struct tnum tnum_lshift(struct tnum a, u8 shift)
 {
 	return TNUM(a.value << shift, a.mask << shift);
 }
+EXPORT_SYMBOL_GPL(tnum_lshift);
 
 struct tnum tnum_rshift(struct tnum a, u8 shift)
 {
 	return TNUM(a.value >> shift, a.mask >> shift);
 }
+EXPORT_SYMBOL_GPL(tnum_rshift);
 
 struct tnum tnum_arshift(struct tnum a, u8 min_shift, u8 insn_bitness)
 {
@@ -58,6 +63,7 @@  struct tnum tnum_arshift(struct tnum a, u8 min_shift, u8 insn_bitness)
 		return TNUM((s64)a.value >> min_shift,
 			    (s64)a.mask  >> min_shift);
 }
+EXPORT_SYMBOL_GPL(tnum_arshift);
 
 struct tnum tnum_add(struct tnum a, struct tnum b)
 {
@@ -70,6 +76,7 @@  struct tnum tnum_add(struct tnum a, struct tnum b)
 	mu = chi | a.mask | b.mask;
 	return TNUM(sv & ~mu, mu);
 }
+EXPORT_SYMBOL_GPL(tnum_add);
 
 struct tnum tnum_sub(struct tnum a, struct tnum b)
 {
@@ -82,6 +89,7 @@  struct tnum tnum_sub(struct tnum a, struct tnum b)
 	mu = chi | a.mask | b.mask;
 	return TNUM(dv & ~mu, mu);
 }
+EXPORT_SYMBOL_GPL(tnum_sub);
 
 struct tnum tnum_and(struct tnum a, struct tnum b)
 {
@@ -92,6 +100,7 @@  struct tnum tnum_and(struct tnum a, struct tnum b)
 	v = a.value & b.value;
 	return TNUM(v, alpha & beta & ~v);
 }
+EXPORT_SYMBOL_GPL(tnum_and);
 
 struct tnum tnum_or(struct tnum a, struct tnum b)
 {
@@ -101,6 +110,7 @@  struct tnum tnum_or(struct tnum a, struct tnum b)
 	mu = a.mask | b.mask;
 	return TNUM(v, mu & ~v);
 }
+EXPORT_SYMBOL_GPL(tnum_or);
 
 struct tnum tnum_xor(struct tnum a, struct tnum b)
 {
@@ -110,6 +120,7 @@  struct tnum tnum_xor(struct tnum a, struct tnum b)
 	mu = a.mask | b.mask;
 	return TNUM(v & ~mu, mu);
 }
+EXPORT_SYMBOL_GPL(tnum_xor);
 
 /* Generate partial products by multiplying each bit in the multiplier (tnum a)
  * with the multiplicand (tnum b), and add the partial products after
@@ -137,6 +148,7 @@  struct tnum tnum_mul(struct tnum a, struct tnum b)
 	}
 	return tnum_add(TNUM(acc_v, 0), acc_m);
 }
+EXPORT_SYMBOL_GPL(tnum_mul);
 
 /* Note that if a and b disagree - i.e. one has a 'known 1' where the other has
  * a 'known 0' - this will return a 'known 1' for that bit.
@@ -149,6 +161,7 @@  struct tnum tnum_intersect(struct tnum a, struct tnum b)
 	mu = a.mask & b.mask;
 	return TNUM(v & ~mu, mu);
 }
+EXPORT_SYMBOL_GPL(tnum_intersect);
 
 struct tnum tnum_cast(struct tnum a, u8 size)
 {
@@ -156,6 +169,7 @@  struct tnum tnum_cast(struct tnum a, u8 size)
 	a.mask &= (1ULL << (size * 8)) - 1;
 	return a;
 }
+EXPORT_SYMBOL_GPL(tnum_cast);
 
 bool tnum_is_aligned(struct tnum a, u64 size)
 {
@@ -163,6 +177,7 @@  bool tnum_is_aligned(struct tnum a, u64 size)
 		return true;
 	return !((a.value | a.mask) & (size - 1));
 }
+EXPORT_SYMBOL_GPL(tnum_is_aligned);
 
 bool tnum_in(struct tnum a, struct tnum b)
 {
@@ -171,6 +186,7 @@  bool tnum_in(struct tnum a, struct tnum b)
 	b.value &= ~a.mask;
 	return a.value == b.value;
 }
+EXPORT_SYMBOL_GPL(tnum_in);
 
 int tnum_sbin(char *str, size_t size, struct tnum a)
 {
@@ -196,18 +212,22 @@  struct tnum tnum_subreg(struct tnum a)
 {
 	return tnum_cast(a, 4);
 }
+EXPORT_SYMBOL_GPL(tnum_subreg);
 
 struct tnum tnum_clear_subreg(struct tnum a)
 {
 	return tnum_lshift(tnum_rshift(a, 32), 32);
 }
+EXPORT_SYMBOL_GPL(tnum_clear_subreg);
 
 struct tnum tnum_with_subreg(struct tnum reg, struct tnum subreg)
 {
 	return tnum_or(tnum_clear_subreg(reg), tnum_subreg(subreg));
 }
+EXPORT_SYMBOL_GPL(tnum_with_subreg);
 
 struct tnum tnum_const_subreg(struct tnum a, u32 value)
 {
 	return tnum_with_subreg(a, tnum_const(value));
 }
+EXPORT_SYMBOL_GPL(tnum_const_subreg);
diff --git a/kernel/bpf/token.c b/kernel/bpf/token.c
index 26057aa13503..76936e8cf5af 100644
--- a/kernel/bpf/token.c
+++ b/kernel/bpf/token.c
@@ -25,6 +25,7 @@  bool bpf_token_capable(const struct bpf_token *token, int cap)
 		return false;
 	return true;
 }
+EXPORT_SYMBOL_GPL(bpf_token_capable);
 
 void bpf_token_inc(struct bpf_token *token)
 {
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index c4b1a98ff726..0ec41c025996 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -2,6 +2,7 @@ 
 /* Copyright (c) 2019 Facebook */
 #include <linux/hash.h>
 #include <linux/bpf.h>
+#include <linux/export.h>
 #include <linux/filter.h>
 #include <linux/ftrace.h>
 #include <linux/rbtree_latch.h>
@@ -17,6 +18,8 @@ 
 /* dummy _ops. The verifier will operate on target program's ops. */
 const struct bpf_verifier_ops bpf_extension_verifier_ops = {
 };
+EXPORT_SYMBOL_GPL(bpf_extension_verifier_ops);
+
 const struct bpf_prog_ops bpf_extension_prog_ops = {
 };
 
@@ -114,6 +117,7 @@  bool bpf_prog_has_trampoline(const struct bpf_prog *prog)
 		 eatype == BPF_MODIFY_RETURN)) ||
 		(ptype == BPF_PROG_TYPE_LSM && eatype == BPF_LSM_MAC);
 }
+EXPORT_SYMBOL_GPL(bpf_prog_has_trampoline);
 
 void bpf_image_ksym_init(void *data, unsigned int size, struct bpf_ksym *ksym)
 {
@@ -836,6 +840,7 @@  struct bpf_trampoline *bpf_trampoline_get(u64 key,
 	mutex_unlock(&tr->mutex);
 	return tr;
 }
+EXPORT_SYMBOL_GPL(bpf_trampoline_get);
 
 void bpf_trampoline_put(struct bpf_trampoline *tr)
 {
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index 6c83ad674d01..5b19c4ed0c92 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -21,6 +21,8 @@  struct callchain_cpus_entries {
 };
 
 int sysctl_perf_event_max_stack __read_mostly = PERF_MAX_STACK_DEPTH;
+EXPORT_SYMBOL_GPL(sysctl_perf_event_max_stack);
+
 int sysctl_perf_event_max_contexts_per_stack __read_mostly = PERF_MAX_CONTEXTS_PER_STACK;
 static const int six_hundred_forty_kb = 640 * 1024;
 
@@ -142,6 +144,7 @@  int get_callchain_buffers(int event_max_stack)
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(get_callchain_buffers);
 
 void put_callchain_buffers(void)
 {
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 187dc37d61d4..fd9c5903605c 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -9,6 +9,7 @@ 
 #include <linux/bpf_verifier.h>
 #include <linux/bpf_perf_event.h>
 #include <linux/btf.h>
+#include <linux/export.h>
 #include <linux/filter.h>
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
@@ -1645,6 +1646,7 @@  const struct bpf_verifier_ops kprobe_verifier_ops = {
 	.get_func_proto  = kprobe_prog_func_proto,
 	.is_valid_access = kprobe_prog_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(kprobe_verifier_ops);
 
 const struct bpf_prog_ops kprobe_prog_ops = {
 };
@@ -1751,6 +1753,7 @@  const struct bpf_verifier_ops tracepoint_verifier_ops = {
 	.get_func_proto  = tp_prog_func_proto,
 	.is_valid_access = tp_prog_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(tracepoint_verifier_ops);
 
 const struct bpf_prog_ops tracepoint_prog_ops = {
 };
@@ -2067,6 +2070,7 @@  const struct bpf_verifier_ops raw_tracepoint_verifier_ops = {
 	.get_func_proto  = raw_tp_prog_func_proto,
 	.is_valid_access = raw_tp_prog_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(raw_tracepoint_verifier_ops);
 
 const struct bpf_prog_ops raw_tracepoint_prog_ops = {
 #ifdef CONFIG_NET
@@ -2078,6 +2082,7 @@  const struct bpf_verifier_ops tracing_verifier_ops = {
 	.get_func_proto  = tracing_prog_func_proto,
 	.is_valid_access = tracing_prog_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(tracing_verifier_ops);
 
 const struct bpf_prog_ops tracing_prog_ops = {
 	.test_run = bpf_prog_test_run_tracing,
@@ -2100,6 +2105,7 @@  const struct bpf_verifier_ops raw_tracepoint_writable_verifier_ops = {
 	.get_func_proto  = raw_tp_prog_func_proto,
 	.is_valid_access = raw_tp_writable_prog_is_valid_access,
 };
+EXPORT_SYMBOL_GPL(raw_tracepoint_writable_verifier_ops);
 
 const struct bpf_prog_ops raw_tracepoint_writable_prog_ops = {
 };
@@ -2183,6 +2189,7 @@  const struct bpf_verifier_ops perf_event_verifier_ops = {
 	.is_valid_access	= pe_prog_is_valid_access,
 	.convert_ctx_access	= pe_prog_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(perf_event_verifier_ops);
 
 const struct bpf_prog_ops perf_event_prog_ops = {
 };
@@ -2333,6 +2340,7 @@  struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name)
 
 	return bpf_get_raw_tracepoint_module(name);
 }
+EXPORT_SYMBOL_GPL(bpf_get_raw_tracepoint);
 
 void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)
 {
@@ -2342,6 +2350,7 @@  void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)
 	mod = __module_address((unsigned long)btp);
 	module_put(mod);
 }
+EXPORT_SYMBOL_GPL(bpf_put_raw_tracepoint);
 
 static __always_inline
 void __bpf_trace_run(struct bpf_raw_tp_link *link, u64 *args)
diff --git a/lib/error-inject.c b/lib/error-inject.c
index 887acd9a6ea6..10312e487843 100644
--- a/lib/error-inject.c
+++ b/lib/error-inject.c
@@ -2,6 +2,7 @@ 
 // error-inject.c: Function-level error injection table
 #include <linux/error-injection.h>
 #include <linux/debugfs.h>
+#include <linux/export.h>
 #include <linux/kallsyms.h>
 #include <linux/kprobes.h>
 #include <linux/module.h>
@@ -36,6 +37,7 @@  bool within_error_injection_list(unsigned long addr)
 	mutex_unlock(&ei_mutex);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(within_error_injection_list);
 
 int get_injectable_error_type(unsigned long addr)
 {
diff --git a/net/core/filter.c b/net/core/filter.c
index bc6828761a47..5c4908fd6bf8 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -30,6 +30,7 @@ 
 #include <linux/netdevice.h>
 #include <linux/if_packet.h>
 #include <linux/if_arp.h>
+#include <linux/export.h>
 #include <linux/gfp.h>
 #include <net/inet_common.h>
 #include <net/ip.h>
@@ -7194,6 +7195,7 @@  bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
 		return size == sizeof(__u32);
 	}
 }
+EXPORT_SYMBOL_GPL(bpf_tcp_sock_is_valid_access);
 
 u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 				    const struct bpf_insn *si,
@@ -7317,6 +7319,7 @@  u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
 	return insn - insn_buf;
 }
+EXPORT_SYMBOL_GPL(bpf_tcp_sock_convert_ctx_access);
 
 BPF_CALL_1(bpf_tcp_sock, struct sock *, sk)
 {
@@ -7388,6 +7391,7 @@  bool bpf_xdp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
 		return size == sizeof(__u32);
 	}
 }
+EXPORT_SYMBOL_GPL(bpf_xdp_sock_is_valid_access);
 
 u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
 				    const struct bpf_insn *si,
@@ -7413,6 +7417,7 @@  u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
 
 	return insn - insn_buf;
 }
+EXPORT_SYMBOL_GPL(bpf_xdp_sock_convert_ctx_access);
 
 static const struct bpf_func_proto bpf_skb_ecn_set_ce_proto = {
 	.func           = bpf_skb_ecn_set_ce,
@@ -8879,6 +8884,7 @@  bool bpf_sock_common_is_valid_access(int off, int size,
 		return bpf_sock_is_valid_access(off, size, type, info);
 	}
 }
+EXPORT_SYMBOL_GPL(bpf_sock_common_is_valid_access);
 
 bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
 			      struct bpf_insn_access_aux *info)
@@ -8916,6 +8922,7 @@  bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
 
 	return size == size_default;
 }
+EXPORT_SYMBOL_GPL(bpf_sock_is_valid_access);
 
 static bool sock_filter_is_valid_access(int off, int size,
 					enum bpf_access_type type,
@@ -10156,6 +10163,7 @@  u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
 
 	return insn - insn_buf;
 }
+EXPORT_SYMBOL_GPL(bpf_sock_convert_ctx_access);
 
 static u32 tc_cls_act_convert_ctx_access(enum bpf_access_type type,
 					 const struct bpf_insn *si,
@@ -11075,6 +11083,7 @@  const struct bpf_verifier_ops sk_filter_verifier_ops = {
 	.convert_ctx_access	= bpf_convert_ctx_access,
 	.gen_ld_abs		= bpf_gen_ld_abs,
 };
+EXPORT_SYMBOL_GPL(sk_filter_verifier_ops);
 
 const struct bpf_prog_ops sk_filter_prog_ops = {
 	.test_run		= bpf_prog_test_run_skb,
@@ -11088,6 +11097,7 @@  const struct bpf_verifier_ops tc_cls_act_verifier_ops = {
 	.gen_ld_abs		= bpf_gen_ld_abs,
 	.btf_struct_access	= tc_cls_act_btf_struct_access,
 };
+EXPORT_SYMBOL_GPL(tc_cls_act_verifier_ops);
 
 const struct bpf_prog_ops tc_cls_act_prog_ops = {
 	.test_run		= bpf_prog_test_run_skb,
@@ -11100,6 +11110,7 @@  const struct bpf_verifier_ops xdp_verifier_ops = {
 	.gen_prologue		= bpf_noop_prologue,
 	.btf_struct_access	= xdp_btf_struct_access,
 };
+EXPORT_SYMBOL_GPL(xdp_verifier_ops);
 
 const struct bpf_prog_ops xdp_prog_ops = {
 	.test_run		= bpf_prog_test_run_xdp,
@@ -11110,6 +11121,7 @@  const struct bpf_verifier_ops cg_skb_verifier_ops = {
 	.is_valid_access	= cg_skb_is_valid_access,
 	.convert_ctx_access	= bpf_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(cg_skb_verifier_ops);
 
 const struct bpf_prog_ops cg_skb_prog_ops = {
 	.test_run		= bpf_prog_test_run_skb,
@@ -11120,6 +11132,7 @@  const struct bpf_verifier_ops lwt_in_verifier_ops = {
 	.is_valid_access	= lwt_is_valid_access,
 	.convert_ctx_access	= bpf_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(lwt_in_verifier_ops);
 
 const struct bpf_prog_ops lwt_in_prog_ops = {
 	.test_run		= bpf_prog_test_run_skb,
@@ -11130,6 +11143,7 @@  const struct bpf_verifier_ops lwt_out_verifier_ops = {
 	.is_valid_access	= lwt_is_valid_access,
 	.convert_ctx_access	= bpf_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(lwt_out_verifier_ops);
 
 const struct bpf_prog_ops lwt_out_prog_ops = {
 	.test_run		= bpf_prog_test_run_skb,
@@ -11141,6 +11155,7 @@  const struct bpf_verifier_ops lwt_xmit_verifier_ops = {
 	.convert_ctx_access	= bpf_convert_ctx_access,
 	.gen_prologue		= tc_cls_act_prologue,
 };
+EXPORT_SYMBOL_GPL(lwt_xmit_verifier_ops);
 
 const struct bpf_prog_ops lwt_xmit_prog_ops = {
 	.test_run		= bpf_prog_test_run_skb,
@@ -11151,6 +11166,7 @@  const struct bpf_verifier_ops lwt_seg6local_verifier_ops = {
 	.is_valid_access	= lwt_is_valid_access,
 	.convert_ctx_access	= bpf_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(lwt_seg6local_verifier_ops);
 
 const struct bpf_prog_ops lwt_seg6local_prog_ops = {
 };
@@ -11160,6 +11176,7 @@  const struct bpf_verifier_ops cg_sock_verifier_ops = {
 	.is_valid_access	= sock_filter_is_valid_access,
 	.convert_ctx_access	= bpf_sock_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(cg_sock_verifier_ops);
 
 const struct bpf_prog_ops cg_sock_prog_ops = {
 };
@@ -11169,6 +11186,7 @@  const struct bpf_verifier_ops cg_sock_addr_verifier_ops = {
 	.is_valid_access	= sock_addr_is_valid_access,
 	.convert_ctx_access	= sock_addr_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(cg_sock_addr_verifier_ops);
 
 const struct bpf_prog_ops cg_sock_addr_prog_ops = {
 };
@@ -11178,6 +11196,7 @@  const struct bpf_verifier_ops sock_ops_verifier_ops = {
 	.is_valid_access	= sock_ops_is_valid_access,
 	.convert_ctx_access	= sock_ops_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(sock_ops_verifier_ops);
 
 const struct bpf_prog_ops sock_ops_prog_ops = {
 };
@@ -11188,6 +11207,7 @@  const struct bpf_verifier_ops sk_skb_verifier_ops = {
 	.convert_ctx_access	= sk_skb_convert_ctx_access,
 	.gen_prologue		= sk_skb_prologue,
 };
+EXPORT_SYMBOL_GPL(sk_skb_verifier_ops);
 
 const struct bpf_prog_ops sk_skb_prog_ops = {
 };
@@ -11198,6 +11218,7 @@  const struct bpf_verifier_ops sk_msg_verifier_ops = {
 	.convert_ctx_access	= sk_msg_convert_ctx_access,
 	.gen_prologue		= bpf_noop_prologue,
 };
+EXPORT_SYMBOL_GPL(sk_msg_verifier_ops);
 
 const struct bpf_prog_ops sk_msg_prog_ops = {
 };
@@ -11207,6 +11228,7 @@  const struct bpf_verifier_ops flow_dissector_verifier_ops = {
 	.is_valid_access	= flow_dissector_is_valid_access,
 	.convert_ctx_access	= flow_dissector_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(flow_dissector_verifier_ops);
 
 const struct bpf_prog_ops flow_dissector_prog_ops = {
 	.test_run		= bpf_prog_test_run_flow_dissector,
@@ -11547,6 +11569,7 @@  const struct bpf_verifier_ops sk_reuseport_verifier_ops = {
 	.is_valid_access	= sk_reuseport_is_valid_access,
 	.convert_ctx_access	= sk_reuseport_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(sk_reuseport_verifier_ops);
 
 const struct bpf_prog_ops sk_reuseport_prog_ops = {
 };
@@ -11759,6 +11782,7 @@  const struct bpf_verifier_ops sk_lookup_verifier_ops = {
 	.is_valid_access	= sk_lookup_is_valid_access,
 	.convert_ctx_access	= sk_lookup_convert_ctx_access,
 };
+EXPORT_SYMBOL_GPL(sk_lookup_verifier_ops);
 
 #endif /* CONFIG_INET */
 
@@ -11773,6 +11797,7 @@  BTF_ID_LIST_GLOBAL(btf_sock_ids, MAX_BTF_SOCK_TYPE)
 #define BTF_SOCK_TYPE(name, type) BTF_ID(struct, type)
 BTF_SOCK_TYPE_xxx
 #undef BTF_SOCK_TYPE
+EXPORT_SYMBOL_GPL(btf_sock_ids);
 
 BPF_CALL_1(bpf_skc_to_tcp6_sock, struct sock *, sk)
 {
@@ -12161,6 +12186,7 @@  int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(bpf_dynptr_from_skb_rdonly);
 
 BTF_KFUNCS_START(bpf_kfunc_check_set_skb)
 BTF_ID_FLAGS(func, bpf_dynptr_from_skb, KF_TRUSTED_ARGS)
diff --git a/net/core/xdp.c b/net/core/xdp.c
index f86eedad586a..a0deb63420a2 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -6,6 +6,7 @@ 
 #include <linux/bpf.h>
 #include <linux/btf.h>
 #include <linux/btf_ids.h>
+#include <linux/export.h>
 #include <linux/filter.h>
 #include <linux/types.h>
 #include <linux/mm.h>
@@ -984,6 +985,7 @@  bool bpf_dev_bound_kfunc_id(u32 btf_id)
 {
 	return btf_id_set8_contains(&xdp_metadata_kfunc_ids, btf_id);
 }
+EXPORT_SYMBOL_GPL(bpf_dev_bound_kfunc_id);
 
 static int __init xdp_metadata_init(void)
 {
diff --git a/net/netfilter/nf_bpf_link.c b/net/netfilter/nf_bpf_link.c
index 06b084844700..0e714fb36dd7 100644
--- a/net/netfilter/nf_bpf_link.c
+++ b/net/netfilter/nf_bpf_link.c
@@ -326,3 +326,4 @@  const struct bpf_verifier_ops netfilter_verifier_ops = {
 	.is_valid_access	= nf_is_valid_access,
 	.get_func_proto		= bpf_nf_func_proto,
 };
+EXPORT_SYMBOL_GPL(netfilter_verifier_ops);