Skip to content

Commit fd978bf

Browse files
joestringerborkmann
authored andcommitted
bpf: Add reference tracking to verifier
Allow helper functions to acquire a reference and return it into a register. Specific pointer types such as the PTR_TO_SOCKET will implicitly represent such a reference. The verifier must ensure that these references are released exactly once in each path through the program. To achieve this, this commit assigns an id to the pointer and tracks it in the 'bpf_func_state', then when the function or program exits, verifies that all of the acquired references have been freed. When the pointer is passed to a function that frees the reference, it is removed from the 'bpf_func_state` and all existing copies of the pointer in registers are marked invalid. Signed-off-by: Joe Stringer <joe@wand.net.nz> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent 84dbf35 commit fd978bf

File tree

2 files changed

+308
-22
lines changed

2 files changed

+308
-22
lines changed

include/linux/bpf_verifier.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ struct bpf_stack_state {
104104
u8 slot_type[BPF_REG_SIZE];
105105
};
106106

107+
struct bpf_reference_state {
108+
/* Track each reference created with a unique id, even if the same
109+
* instruction creates the reference multiple times (eg, via CALL).
110+
*/
111+
int id;
112+
/* Instruction where the allocation of this reference occurred. This
113+
* is used purely to inform the user of a reference leak.
114+
*/
115+
int insn_idx;
116+
};
117+
107118
/* state of the program:
108119
* type of all registers and stack info
109120
*/
@@ -121,7 +132,9 @@ struct bpf_func_state {
121132
*/
122133
u32 subprogno;
123134

124-
/* should be second to last. See copy_func_state() */
135+
/* The following fields should be last. See copy_func_state() */
136+
int acquired_refs;
137+
struct bpf_reference_state *refs;
125138
int allocated_stack;
126139
struct bpf_stack_state *stack;
127140
};
@@ -217,11 +230,16 @@ __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
217230
__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,
218231
const char *fmt, ...);
219232

220-
static inline struct bpf_reg_state *cur_regs(struct bpf_verifier_env *env)
233+
static inline struct bpf_func_state *cur_func(struct bpf_verifier_env *env)
221234
{
222235
struct bpf_verifier_state *cur = env->cur_state;
223236

224-
return cur->frame[cur->curframe]->regs;
237+
return cur->frame[cur->curframe];
238+
}
239+
240+
static inline struct bpf_reg_state *cur_regs(struct bpf_verifier_env *env)
241+
{
242+
return cur_func(env)->regs;
225243
}
226244

227245
int bpf_prog_offload_verifier_prep(struct bpf_verifier_env *env);

0 commit comments

Comments
 (0)