Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5397b31b authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bpf-prog-digest'



Daniel Borkmann says:

====================
Minor BPF cleanups and digest

First two patches are minor cleanups, and the third one adds
a prog digest. For details, please see individual patches.
After this one, I have a set with tracepoint support that makes
use of this facility as well.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 70f23a80 7bd509e3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5);
u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);

bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp);
void bpf_prog_calc_digest(struct bpf_prog *fp);

const struct bpf_func_proto *bpf_get_trace_printk_proto(void);

+6 −1
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/capability.h>
#include <linux/cryptohash.h>

#include <net/sch_generic.h>

@@ -56,6 +57,9 @@ struct bpf_prog_aux;
/* BPF program can access up to 512 bytes of stack space. */
#define MAX_BPF_STACK	512

/* Maximum BPF program size in bytes. */
#define MAX_BPF_SIZE	(BPF_MAXINSNS * sizeof(struct bpf_insn))

/* Helper macros for filter block array initializers. */

/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
@@ -404,8 +408,9 @@ struct bpf_prog {
				cb_access:1,	/* Is control block accessed? */
				dst_needed:1;	/* Do we need dst entry? */
	kmemcheck_bitfield_end(meta);
	u32			len;		/* Number of filter blocks */
	enum bpf_prog_type	type;		/* Type of BPF program */
	u32			len;		/* Number of filter blocks */
	u32			digest[SHA_DIGEST_WORDS]; /* Program digest */
	struct bpf_prog_aux	*aux;		/* Auxiliary fields */
	struct sock_fprog_kern	*orig_prog;	/* Original BPF program */
	unsigned int		(*bpf_func)(const void *ctx,
+1 −0
Original line number Diff line number Diff line
@@ -397,6 +397,7 @@ enum {
	TCA_BPF_NAME,
	TCA_BPF_FLAGS,
	TCA_BPF_FLAGS_GEN,
	TCA_BPF_DIGEST,
	__TCA_BPF_MAX,
};

+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ enum {
	TCA_ACT_BPF_FD,
	TCA_ACT_BPF_NAME,
	TCA_ACT_BPF_PAD,
	TCA_ACT_BPF_DIGEST,
	__TCA_ACT_BPF_MAX,
};
#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
+65 −0
Original line number Diff line number Diff line
@@ -136,6 +136,71 @@ void __bpf_prog_free(struct bpf_prog *fp)
	vfree(fp);
}

#define SHA_BPF_RAW_SIZE						\
	round_up(MAX_BPF_SIZE + sizeof(__be64) + 1, SHA_MESSAGE_BYTES)

/* Called under verifier mutex. */
void bpf_prog_calc_digest(struct bpf_prog *fp)
{
	const u32 bits_offset = SHA_MESSAGE_BYTES - sizeof(__be64);
	static u32 ws[SHA_WORKSPACE_WORDS];
	static u8 raw[SHA_BPF_RAW_SIZE];
	struct bpf_insn *dst = (void *)raw;
	u32 i, bsize, psize, blocks;
	bool was_ld_map;
	u8 *todo = raw;
	__be32 *result;
	__be64 *bits;

	sha_init(fp->digest);
	memset(ws, 0, sizeof(ws));

	/* We need to take out the map fd for the digest calculation
	 * since they are unstable from user space side.
	 */
	for (i = 0, was_ld_map = false; i < fp->len; i++) {
		dst[i] = fp->insnsi[i];
		if (!was_ld_map &&
		    dst[i].code == (BPF_LD | BPF_IMM | BPF_DW) &&
		    dst[i].src_reg == BPF_PSEUDO_MAP_FD) {
			was_ld_map = true;
			dst[i].imm = 0;
		} else if (was_ld_map &&
			   dst[i].code == 0 &&
			   dst[i].dst_reg == 0 &&
			   dst[i].src_reg == 0 &&
			   dst[i].off == 0) {
			was_ld_map = false;
			dst[i].imm = 0;
		} else {
			was_ld_map = false;
		}
	}

	psize = fp->len * sizeof(struct bpf_insn);
	memset(&raw[psize], 0, sizeof(raw) - psize);
	raw[psize++] = 0x80;

	bsize  = round_up(psize, SHA_MESSAGE_BYTES);
	blocks = bsize / SHA_MESSAGE_BYTES;
	if (bsize - psize >= sizeof(__be64)) {
		bits = (__be64 *)(todo + bsize - sizeof(__be64));
	} else {
		bits = (__be64 *)(todo + bsize + bits_offset);
		blocks++;
	}
	*bits = cpu_to_be64((psize - 1) << 3);

	while (blocks--) {
		sha_transform(fp->digest, todo, ws);
		todo += SHA_MESSAGE_BYTES;
	}

	result = (__force __be32 *)fp->digest;
	for (i = 0; i < SHA_DIGEST_WORDS; i++)
		result[i] = cpu_to_be32(fp->digest[i]);
}

static bool bpf_is_jmp_and_has_target(const struct bpf_insn *insn)
{
	return BPF_CLASS(insn->code) == BPF_JMP  &&
Loading