Commit 4ff57471 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'bpf-support-dumping-kfunc-prototypes-from-btf'

Daniel Xu says:

====================
bpf: Support dumping kfunc prototypes from BTF

This patchset enables both detecting as well as dumping compilable
prototypes for kfuncs.

The first commit instructs pahole to DECL_TAG kfuncs when available.
This requires v1.27 which was released on 6/11/24. With it, users will
be able to look at BTF inside vmlinux (or modules) and check if the
kfunc they want is available.

The final commit teaches bpftool how to dump kfunc prototypes. This
is done for developer convenience.

The rest of the commits are fixups to enable selftests to use the
newly dumped kfunc prototypes. With these, selftests will regularly
exercise the newly added codepaths.

Tested with and without the required pahole changes:

  * https://github.com/kernel-patches/bpf/pull/7186
  * https://github.com/kernel-patches/bpf/pull/7187

=== Changelog ===
From v4:
* Change bpf_session_cookie() return type
* Only fixup used fentry test kfunc prototypes
* Extract out projection detection into shared btf_is_projection_of()
* Fix kernel test robot build warnings about doc comments

From v3:
* Teach selftests to use dumped prototypes

From v2:
* Update Makefile.btf with pahole flag
* More error checking
* Output formatting changes
* Drop already-merged commit

From v1:
* Add __weak annotation
* Use btf_dump for kfunc prototypes
* Update kernel bpf_rdonly_cast() signature
====================

Link: https://lore.kernel.org/r/cover.1718207789.git.dxu@dxuuu.xyz


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 98b303c9 770abbb5
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -111,14 +111,15 @@ __bpf_kfunc_start_defs();
/**
 * bpf_get_fsverity_digest: read fsverity digest of file
 * @file: file to get digest from
 * @digest_ptr: (out) dynptr for struct fsverity_digest
 * @digest_p: (out) dynptr for struct fsverity_digest
 *
 * Read fsverity_digest of *file* into *digest_ptr*.
 *
 * Return: 0 on success, a negative value on error.
 */
__bpf_kfunc int bpf_get_fsverity_digest(struct file *file, struct bpf_dynptr_kern *digest_ptr)
__bpf_kfunc int bpf_get_fsverity_digest(struct file *file, struct bpf_dynptr *digest_p)
{
	struct bpf_dynptr_kern *digest_ptr = (struct bpf_dynptr_kern *)digest_p;
	const struct inode *inode = file_inode(file);
	u32 dynptr_sz = __bpf_dynptr_size(digest_ptr);
	struct fsverity_digest *arg;
+4 −4
Original line number Diff line number Diff line
@@ -3265,8 +3265,8 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
				struct bpf_insn *insn_buf,
				struct bpf_prog *prog,
				u32 *target_size);
int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
			       struct bpf_dynptr_kern *ptr);
int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
			       struct bpf_dynptr *ptr);
#else
static inline bool bpf_sock_common_is_valid_access(int off, int size,
						   enum bpf_access_type type,
@@ -3288,8 +3288,8 @@ static inline u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
{
	return 0;
}
static inline int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
					     struct bpf_dynptr_kern *ptr)
static inline int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags,
					     struct bpf_dynptr *ptr)
{
	return -EOPNOTSUPP;
}
+1 −0
Original line number Diff line number Diff line
@@ -531,6 +531,7 @@ s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id);
int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_cnt,
				struct module *owner);
struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id);
bool btf_is_projection_of(const char *pname, const char *tname);
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,
			   int arg);
+10 −3
Original line number Diff line number Diff line
@@ -5820,6 +5820,15 @@ static int find_kern_ctx_type_id(enum bpf_prog_type prog_type)
	return ctx_type->type;
}

bool btf_is_projection_of(const char *pname, const char *tname)
{
	if (strcmp(pname, "__sk_buff") == 0 && strcmp(tname, "sk_buff") == 0)
		return true;
	if (strcmp(pname, "xdp_md") == 0 && strcmp(tname, "xdp_buff") == 0)
		return true;
	return false;
}

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,
			  int arg)
@@ -5882,9 +5891,7 @@ bool btf_is_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
	 * int socket_filter_bpf_prog(struct __sk_buff *skb)
	 * { // no fields of skb are ever used }
	 */
	if (strcmp(ctx_tname, "__sk_buff") == 0 && strcmp(tname, "sk_buff") == 0)
		return true;
	if (strcmp(ctx_tname, "xdp_md") == 0 && strcmp(tname, "xdp_buff") == 0)
	if (btf_is_projection_of(ctx_tname, tname))
		return true;
	if (strcmp(ctx_tname, tname)) {
		/* bpf_user_pt_regs_t is a typedef, so resolve it to
+16 −8
Original line number Diff line number Diff line
@@ -311,11 +311,15 @@ static int bpf_crypto_crypt(const struct bpf_crypto_ctx *ctx,
 * Decrypts provided buffer using IV data and the crypto context. Crypto context must be configured.
 */
__bpf_kfunc int bpf_crypto_decrypt(struct bpf_crypto_ctx *ctx,
				   const struct bpf_dynptr_kern *src,
				   const struct bpf_dynptr_kern *dst,
				   const struct bpf_dynptr_kern *siv)
				   const struct bpf_dynptr *src,
				   const struct bpf_dynptr *dst,
				   const struct bpf_dynptr *siv)
{
	return bpf_crypto_crypt(ctx, src, dst, siv, true);
	const struct bpf_dynptr_kern *src_kern = (struct bpf_dynptr_kern *)src;
	const struct bpf_dynptr_kern *dst_kern = (struct bpf_dynptr_kern *)dst;
	const struct bpf_dynptr_kern *siv_kern = (struct bpf_dynptr_kern *)siv;

	return bpf_crypto_crypt(ctx, src_kern, dst_kern, siv_kern, true);
}

/**
@@ -328,11 +332,15 @@ __bpf_kfunc int bpf_crypto_decrypt(struct bpf_crypto_ctx *ctx,
 * Encrypts provided buffer using IV data and the crypto context. Crypto context must be configured.
 */
__bpf_kfunc int bpf_crypto_encrypt(struct bpf_crypto_ctx *ctx,
				   const struct bpf_dynptr_kern *src,
				   const struct bpf_dynptr_kern *dst,
				   const struct bpf_dynptr_kern *siv)
				   const struct bpf_dynptr *src,
				   const struct bpf_dynptr *dst,
				   const struct bpf_dynptr *siv)
{
	return bpf_crypto_crypt(ctx, src, dst, siv, false);
	const struct bpf_dynptr_kern *src_kern = (struct bpf_dynptr_kern *)src;
	const struct bpf_dynptr_kern *dst_kern = (struct bpf_dynptr_kern *)dst;
	const struct bpf_dynptr_kern *siv_kern = (struct bpf_dynptr_kern *)siv;

	return bpf_crypto_crypt(ctx, src_kern, dst_kern, siv_kern, false);
}

__bpf_kfunc_end_defs();
Loading