Skip to content

Commit f1f7714

Browse files
borkmanndavem330
authored andcommitted
bpf: rework prog_digest into prog_tag
Commit 7bd509e ("bpf: add prog_digest and expose it via fdinfo/netlink") was recently discussed, partially due to admittedly suboptimal name of "prog_digest" in combination with sha1 hash usage, thus inevitably and rightfully concerns about its security in terms of collision resistance were raised with regards to use-cases. The intended use cases are for debugging resp. introspection only for providing a stable "tag" over the instruction sequence that both kernel and user space can calculate independently. It's not usable at all for making a security relevant decision. So collisions where two different instruction sequences generate the same tag can happen, but ideally at a rather low rate. The "tag" will be dumped in hex and is short enough to introspect in tracepoints or kallsyms output along with other data such as stack trace, etc. Thus, this patch performs a rename into prog_tag and truncates the tag to a short output (64 bits) to make it obvious it's not collision-free. Should in future a hash or facility be needed with a security relevant focus, then we can think about requirements, constraints, etc that would fit to that situation. For now, rework the exposed parts for the current use cases as long as nothing has been released yet. Tested on x86_64 and s390x. Fixes: 7bd509e ("bpf: add prog_digest and expose it via fdinfo/netlink") Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Cc: Andy Lutomirski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 57d5f64 commit f1f7714

File tree

9 files changed

+24
-21
lines changed

9 files changed

+24
-21
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5);
216216
u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
217217

218218
bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp);
219-
int bpf_prog_calc_digest(struct bpf_prog *fp);
219+
int bpf_prog_calc_tag(struct bpf_prog *fp);
220220

221221
const struct bpf_func_proto *bpf_get_trace_printk_proto(void);
222222

include/linux/filter.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ struct bpf_prog_aux;
5757
/* BPF program can access up to 512 bytes of stack space. */
5858
#define MAX_BPF_STACK 512
5959

60+
#define BPF_TAG_SIZE 8
61+
6062
/* Helper macros for filter block array initializers. */
6163

6264
/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
@@ -408,7 +410,7 @@ struct bpf_prog {
408410
kmemcheck_bitfield_end(meta);
409411
enum bpf_prog_type type; /* Type of BPF program */
410412
u32 len; /* Number of filter blocks */
411-
u32 digest[SHA_DIGEST_WORDS]; /* Program digest */
413+
u8 tag[BPF_TAG_SIZE];
412414
struct bpf_prog_aux *aux; /* Auxiliary fields */
413415
struct sock_fprog_kern *orig_prog; /* Original BPF program */
414416
unsigned int (*bpf_func)(const void *ctx,
@@ -519,7 +521,7 @@ static inline u32 bpf_prog_insn_size(const struct bpf_prog *prog)
519521
return prog->len * sizeof(struct bpf_insn);
520522
}
521523

522-
static inline u32 bpf_prog_digest_scratch_size(const struct bpf_prog *prog)
524+
static inline u32 bpf_prog_tag_scratch_size(const struct bpf_prog *prog)
523525
{
524526
return round_up(bpf_prog_insn_size(prog) +
525527
sizeof(__be64) + 1, SHA_MESSAGE_BYTES);

include/uapi/linux/pkt_cls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ enum {
397397
TCA_BPF_NAME,
398398
TCA_BPF_FLAGS,
399399
TCA_BPF_FLAGS_GEN,
400-
TCA_BPF_DIGEST,
400+
TCA_BPF_TAG,
401401
__TCA_BPF_MAX,
402402
};
403403

include/uapi/linux/tc_act/tc_bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ enum {
2727
TCA_ACT_BPF_FD,
2828
TCA_ACT_BPF_NAME,
2929
TCA_ACT_BPF_PAD,
30-
TCA_ACT_BPF_DIGEST,
30+
TCA_ACT_BPF_TAG,
3131
__TCA_ACT_BPF_MAX,
3232
};
3333
#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)

kernel/bpf/core.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,11 @@ void __bpf_prog_free(struct bpf_prog *fp)
146146
vfree(fp);
147147
}
148148

149-
int bpf_prog_calc_digest(struct bpf_prog *fp)
149+
int bpf_prog_calc_tag(struct bpf_prog *fp)
150150
{
151151
const u32 bits_offset = SHA_MESSAGE_BYTES - sizeof(__be64);
152-
u32 raw_size = bpf_prog_digest_scratch_size(fp);
152+
u32 raw_size = bpf_prog_tag_scratch_size(fp);
153+
u32 digest[SHA_DIGEST_WORDS];
153154
u32 ws[SHA_WORKSPACE_WORDS];
154155
u32 i, bsize, psize, blocks;
155156
struct bpf_insn *dst;
@@ -162,7 +163,7 @@ int bpf_prog_calc_digest(struct bpf_prog *fp)
162163
if (!raw)
163164
return -ENOMEM;
164165

165-
sha_init(fp->digest);
166+
sha_init(digest);
166167
memset(ws, 0, sizeof(ws));
167168

168169
/* We need to take out the map fd for the digest calculation
@@ -204,13 +205,14 @@ int bpf_prog_calc_digest(struct bpf_prog *fp)
204205
*bits = cpu_to_be64((psize - 1) << 3);
205206

206207
while (blocks--) {
207-
sha_transform(fp->digest, todo, ws);
208+
sha_transform(digest, todo, ws);
208209
todo += SHA_MESSAGE_BYTES;
209210
}
210211

211-
result = (__force __be32 *)fp->digest;
212+
result = (__force __be32 *)digest;
212213
for (i = 0; i < SHA_DIGEST_WORDS; i++)
213-
result[i] = cpu_to_be32(fp->digest[i]);
214+
result[i] = cpu_to_be32(digest[i]);
215+
memcpy(fp->tag, result, sizeof(fp->tag));
214216

215217
vfree(raw);
216218
return 0;

kernel/bpf/syscall.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -688,17 +688,17 @@ static int bpf_prog_release(struct inode *inode, struct file *filp)
688688
static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
689689
{
690690
const struct bpf_prog *prog = filp->private_data;
691-
char prog_digest[sizeof(prog->digest) * 2 + 1] = { };
691+
char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
692692

693-
bin2hex(prog_digest, prog->digest, sizeof(prog->digest));
693+
bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
694694
seq_printf(m,
695695
"prog_type:\t%u\n"
696696
"prog_jited:\t%u\n"
697-
"prog_digest:\t%s\n"
697+
"prog_tag:\t%s\n"
698698
"memlock:\t%llu\n",
699699
prog->type,
700700
prog->jited,
701-
prog_digest,
701+
prog_tag,
702702
prog->pages * 1ULL << PAGE_SHIFT);
703703
}
704704
#endif

kernel/bpf/verifier.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2936,7 +2936,7 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
29362936
int insn_cnt = env->prog->len;
29372937
int i, j, err;
29382938

2939-
err = bpf_prog_calc_digest(env->prog);
2939+
err = bpf_prog_calc_tag(env->prog);
29402940
if (err)
29412941
return err;
29422942

net/sched/act_bpf.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,11 @@ static int tcf_bpf_dump_ebpf_info(const struct tcf_bpf *prog,
123123
nla_put_string(skb, TCA_ACT_BPF_NAME, prog->bpf_name))
124124
return -EMSGSIZE;
125125

126-
nla = nla_reserve(skb, TCA_ACT_BPF_DIGEST,
127-
sizeof(prog->filter->digest));
126+
nla = nla_reserve(skb, TCA_ACT_BPF_TAG, sizeof(prog->filter->tag));
128127
if (nla == NULL)
129128
return -EMSGSIZE;
130129

131-
memcpy(nla_data(nla), prog->filter->digest, nla_len(nla));
130+
memcpy(nla_data(nla), prog->filter->tag, nla_len(nla));
132131

133132
return 0;
134133
}

net/sched/cls_bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,11 +555,11 @@ static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog,
555555
nla_put_string(skb, TCA_BPF_NAME, prog->bpf_name))
556556
return -EMSGSIZE;
557557

558-
nla = nla_reserve(skb, TCA_BPF_DIGEST, sizeof(prog->filter->digest));
558+
nla = nla_reserve(skb, TCA_BPF_TAG, sizeof(prog->filter->tag));
559559
if (nla == NULL)
560560
return -EMSGSIZE;
561561

562-
memcpy(nla_data(nla), prog->filter->digest, nla_len(nla));
562+
memcpy(nla_data(nla), prog->filter->tag, nla_len(nla));
563563

564564
return 0;
565565
}

0 commit comments

Comments
 (0)