Skip to content

Commit 43736ec

Browse files
eddyz87anakryiko
authored andcommitted
bpf: Include verifier memory allocations in memcg statistics
This commit adds __GFP_ACCOUNT flag to verifier induced memory allocations. The intent is to account for all allocations reachable from BPF_PROG_LOAD command, which is needed to track verifier memory consumption in veristat. This includes allocations done in verifier.c, and some allocations in btf.c, functions in log.c do not allocate. There is also a utility function bpf_memcg_flags() which selectively adds GFP_ACCOUNT flag depending on the `cgroup.memory=nobpf` option. As far as I understand [1], the idea is to remove bpf_prog instances and maps from memcg accounting as these objects do not strictly belong to cgroup, hence it should not apply here. (btf_parse_fields() is reachable from both program load and map creation, but allocated record is not persistent as is freed as soon as map_check_btf() exits). [1] https://lore.kernel.org/all/[email protected]/ Signed-off-by: Eduard Zingerman <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent ccefa19 commit 43736ec

File tree

2 files changed

+43
-41
lines changed

2 files changed

+43
-41
lines changed

kernel/bpf/btf.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3443,7 +3443,8 @@ btf_find_graph_root(const struct btf *btf, const struct btf_type *pt,
34433443
node_field_name = strstr(value_type, ":");
34443444
if (!node_field_name)
34453445
return -EINVAL;
3446-
value_type = kstrndup(value_type, node_field_name - value_type, GFP_KERNEL | __GFP_NOWARN);
3446+
value_type = kstrndup(value_type, node_field_name - value_type,
3447+
GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
34473448
if (!value_type)
34483449
return -ENOMEM;
34493450
id = btf_find_by_name_kind(btf, value_type, BTF_KIND_STRUCT);
@@ -3958,7 +3959,7 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
39583959
/* This needs to be kzalloc to zero out padding and unused fields, see
39593960
* comment in btf_record_equal.
39603961
*/
3961-
rec = kzalloc(struct_size(rec, fields, cnt), GFP_KERNEL | __GFP_NOWARN);
3962+
rec = kzalloc(struct_size(rec, fields, cnt), GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
39623963
if (!rec)
39633964
return ERR_PTR(-ENOMEM);
39643965

@@ -9019,15 +9020,15 @@ static struct bpf_cand_cache *populate_cand_cache(struct bpf_cand_cache *cands,
90199020
bpf_free_cands_from_cache(*cc);
90209021
*cc = NULL;
90219022
}
9022-
new_cands = kmemdup(cands, sizeof_cands(cands->cnt), GFP_KERNEL);
9023+
new_cands = kmemdup(cands, sizeof_cands(cands->cnt), GFP_KERNEL_ACCOUNT);
90239024
if (!new_cands) {
90249025
bpf_free_cands(cands);
90259026
return ERR_PTR(-ENOMEM);
90269027
}
90279028
/* strdup the name, since it will stay in cache.
90289029
* the cands->name points to strings in prog's BTF and the prog can be unloaded.
90299030
*/
9030-
new_cands->name = kmemdup_nul(cands->name, cands->name_len, GFP_KERNEL);
9031+
new_cands->name = kmemdup_nul(cands->name, cands->name_len, GFP_KERNEL_ACCOUNT);
90319032
bpf_free_cands(cands);
90329033
if (!new_cands->name) {
90339034
kfree(new_cands);
@@ -9111,7 +9112,7 @@ bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
91119112
continue;
91129113

91139114
/* most of the time there is only one candidate for a given kind+name pair */
9114-
new_cands = kmalloc(sizeof_cands(cands->cnt + 1), GFP_KERNEL);
9115+
new_cands = kmalloc(sizeof_cands(cands->cnt + 1), GFP_KERNEL_ACCOUNT);
91159116
if (!new_cands) {
91169117
bpf_free_cands(cands);
91179118
return ERR_PTR(-ENOMEM);
@@ -9228,7 +9229,7 @@ int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,
92289229
/* ~4k of temp memory necessary to convert LLVM spec like "0:1:0:5"
92299230
* into arrays of btf_ids of struct fields and array indices.
92309231
*/
9231-
specs = kcalloc(3, sizeof(*specs), GFP_KERNEL);
9232+
specs = kcalloc(3, sizeof(*specs), GFP_KERNEL_ACCOUNT);
92329233
if (!specs)
92339234
return -ENOMEM;
92349235

@@ -9253,7 +9254,7 @@ int bpf_core_apply(struct bpf_core_ctx *ctx, const struct bpf_core_relo *relo,
92539254
goto out;
92549255
}
92559256
if (cc->cnt) {
9256-
cands.cands = kcalloc(cc->cnt, sizeof(*cands.cands), GFP_KERNEL);
9257+
cands.cands = kcalloc(cc->cnt, sizeof(*cands.cands), GFP_KERNEL_ACCOUNT);
92579258
if (!cands.cands) {
92589259
err = -ENOMEM;
92599260
goto out;

kernel/bpf/verifier.c

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,7 +1404,7 @@ static void *realloc_array(void *arr, size_t old_n, size_t new_n, size_t size)
14041404
goto out;
14051405

14061406
alloc_size = kmalloc_size_roundup(size_mul(new_n, size));
1407-
new_arr = krealloc(arr, alloc_size, GFP_KERNEL);
1407+
new_arr = krealloc(arr, alloc_size, GFP_KERNEL_ACCOUNT);
14081408
if (!new_arr) {
14091409
kfree(arr);
14101410
return NULL;
@@ -1421,7 +1421,7 @@ static void *realloc_array(void *arr, size_t old_n, size_t new_n, size_t size)
14211421
static int copy_reference_state(struct bpf_verifier_state *dst, const struct bpf_verifier_state *src)
14221422
{
14231423
dst->refs = copy_array(dst->refs, src->refs, src->acquired_refs,
1424-
sizeof(struct bpf_reference_state), GFP_KERNEL);
1424+
sizeof(struct bpf_reference_state), GFP_KERNEL_ACCOUNT);
14251425
if (!dst->refs)
14261426
return -ENOMEM;
14271427

@@ -1440,7 +1440,7 @@ static int copy_stack_state(struct bpf_func_state *dst, const struct bpf_func_st
14401440
size_t n = src->allocated_stack / BPF_REG_SIZE;
14411441

14421442
dst->stack = copy_array(dst->stack, src->stack, n, sizeof(struct bpf_stack_state),
1443-
GFP_KERNEL);
1443+
GFP_KERNEL_ACCOUNT);
14441444
if (!dst->stack)
14451445
return -ENOMEM;
14461446

@@ -1731,7 +1731,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
17311731

17321732
dst_state->jmp_history = copy_array(dst_state->jmp_history, src->jmp_history,
17331733
src->jmp_history_cnt, sizeof(*dst_state->jmp_history),
1734-
GFP_USER);
1734+
GFP_KERNEL_ACCOUNT);
17351735
if (!dst_state->jmp_history)
17361736
return -ENOMEM;
17371737
dst_state->jmp_history_cnt = src->jmp_history_cnt;
@@ -1760,7 +1760,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
17601760
for (i = 0; i <= src->curframe; i++) {
17611761
dst = dst_state->frame[i];
17621762
if (!dst) {
1763-
dst = kzalloc(sizeof(*dst), GFP_KERNEL);
1763+
dst = kzalloc(sizeof(*dst), GFP_KERNEL_ACCOUNT);
17641764
if (!dst)
17651765
return -ENOMEM;
17661766
dst_state->frame[i] = dst;
@@ -1874,7 +1874,7 @@ static struct bpf_scc_visit *scc_visit_alloc(struct bpf_verifier_env *env,
18741874
info = env->scc_info[scc];
18751875
num_visits = info ? info->num_visits : 0;
18761876
new_sz = sizeof(*info) + sizeof(struct bpf_scc_visit) * (num_visits + 1);
1877-
info = kvrealloc(env->scc_info[scc], new_sz, GFP_KERNEL);
1877+
info = kvrealloc(env->scc_info[scc], new_sz, GFP_KERNEL_ACCOUNT);
18781878
if (!info)
18791879
return NULL;
18801880
env->scc_info[scc] = info;
@@ -2095,7 +2095,7 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
20952095
struct bpf_verifier_stack_elem *elem;
20962096
int err;
20972097

2098-
elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL);
2098+
elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL_ACCOUNT);
20992099
if (!elem)
21002100
goto err;
21012101

@@ -2862,7 +2862,7 @@ static struct bpf_verifier_state *push_async_cb(struct bpf_verifier_env *env,
28622862
struct bpf_verifier_stack_elem *elem;
28632863
struct bpf_func_state *frame;
28642864

2865-
elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL);
2865+
elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL_ACCOUNT);
28662866
if (!elem)
28672867
goto err;
28682868

@@ -2885,7 +2885,7 @@ static struct bpf_verifier_state *push_async_cb(struct bpf_verifier_env *env,
28852885
*/
28862886
elem->st.branches = 1;
28872887
elem->st.in_sleepable = is_sleepable;
2888-
frame = kzalloc(sizeof(*frame), GFP_KERNEL);
2888+
frame = kzalloc(sizeof(*frame), GFP_KERNEL_ACCOUNT);
28892889
if (!frame)
28902890
goto err;
28912891
init_func_state(env, frame,
@@ -3237,7 +3237,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
32373237
return -EINVAL;
32383238
}
32393239

3240-
tab = kzalloc(sizeof(*tab), GFP_KERNEL);
3240+
tab = kzalloc(sizeof(*tab), GFP_KERNEL_ACCOUNT);
32413241
if (!tab)
32423242
return -ENOMEM;
32433243
prog_aux->kfunc_tab = tab;
@@ -3253,7 +3253,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
32533253
return 0;
32543254

32553255
if (!btf_tab && offset) {
3256-
btf_tab = kzalloc(sizeof(*btf_tab), GFP_KERNEL);
3256+
btf_tab = kzalloc(sizeof(*btf_tab), GFP_KERNEL_ACCOUNT);
32573257
if (!btf_tab)
32583258
return -ENOMEM;
32593259
prog_aux->kfunc_btf_tab = btf_tab;
@@ -3939,7 +3939,7 @@ static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_st
39393939

39403940
cnt++;
39413941
alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p)));
3942-
p = krealloc(cur->jmp_history, alloc_size, GFP_USER);
3942+
p = krealloc(cur->jmp_history, alloc_size, GFP_KERNEL_ACCOUNT);
39433943
if (!p)
39443944
return -ENOMEM;
39453945
cur->jmp_history = p;
@@ -10356,7 +10356,7 @@ static int setup_func_entry(struct bpf_verifier_env *env, int subprog, int calls
1035610356
}
1035710357

1035810358
caller = state->frame[state->curframe];
10359-
callee = kzalloc(sizeof(*callee), GFP_KERNEL);
10359+
callee = kzalloc(sizeof(*callee), GFP_KERNEL_ACCOUNT);
1036010360
if (!callee)
1036110361
return -ENOMEM;
1036210362
state->frame[state->curframe + 1] = callee;
@@ -17693,17 +17693,18 @@ static int check_cfg(struct bpf_verifier_env *env)
1769317693
int *insn_stack, *insn_state, *insn_postorder;
1769417694
int ex_insn_beg, i, ret = 0;
1769517695

17696-
insn_state = env->cfg.insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
17696+
insn_state = env->cfg.insn_state = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
1769717697
if (!insn_state)
1769817698
return -ENOMEM;
1769917699

17700-
insn_stack = env->cfg.insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
17700+
insn_stack = env->cfg.insn_stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
1770117701
if (!insn_stack) {
1770217702
kvfree(insn_state);
1770317703
return -ENOMEM;
1770417704
}
1770517705

17706-
insn_postorder = env->cfg.insn_postorder = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
17706+
insn_postorder = env->cfg.insn_postorder =
17707+
kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
1770717708
if (!insn_postorder) {
1770817709
kvfree(insn_state);
1770917710
kvfree(insn_stack);
@@ -17837,7 +17838,7 @@ static int check_btf_func_early(struct bpf_verifier_env *env,
1783717838
urecord = make_bpfptr(attr->func_info, uattr.is_kernel);
1783817839
min_size = min_t(u32, krec_size, urec_size);
1783917840

17840-
krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL | __GFP_NOWARN);
17841+
krecord = kvcalloc(nfuncs, krec_size, GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
1784117842
if (!krecord)
1784217843
return -ENOMEM;
1784317844

@@ -17937,7 +17938,7 @@ static int check_btf_func(struct bpf_verifier_env *env,
1793717938
urecord = make_bpfptr(attr->func_info, uattr.is_kernel);
1793817939

1793917940
krecord = prog->aux->func_info;
17940-
info_aux = kcalloc(nfuncs, sizeof(*info_aux), GFP_KERNEL | __GFP_NOWARN);
17941+
info_aux = kcalloc(nfuncs, sizeof(*info_aux), GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
1794117942
if (!info_aux)
1794217943
return -ENOMEM;
1794317944

@@ -18023,7 +18024,7 @@ static int check_btf_line(struct bpf_verifier_env *env,
1802318024
* pass in a smaller bpf_line_info object.
1802418025
*/
1802518026
linfo = kvcalloc(nr_linfo, sizeof(struct bpf_line_info),
18026-
GFP_KERNEL | __GFP_NOWARN);
18027+
GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
1802718028
if (!linfo)
1802818029
return -ENOMEM;
1802918030

@@ -19408,7 +19409,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1940819409
if (loop) {
1940919410
struct bpf_scc_backedge *backedge;
1941019411

19411-
backedge = kzalloc(sizeof(*backedge), GFP_KERNEL);
19412+
backedge = kzalloc(sizeof(*backedge), GFP_KERNEL_ACCOUNT);
1941219413
if (!backedge)
1941319414
return -ENOMEM;
1941419415
err = copy_verifier_state(&backedge->state, cur);
@@ -19472,7 +19473,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1947219473
* When looping the sl->state.branches will be > 0 and this state
1947319474
* will not be considered for equivalence until branches == 0.
1947419475
*/
19475-
new_sl = kzalloc(sizeof(struct bpf_verifier_state_list), GFP_KERNEL);
19476+
new_sl = kzalloc(sizeof(struct bpf_verifier_state_list), GFP_KERNEL_ACCOUNT);
1947619477
if (!new_sl)
1947719478
return -ENOMEM;
1947819479
env->total_states++;
@@ -22976,13 +22977,13 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
2297622977
env->prev_linfo = NULL;
2297722978
env->pass_cnt++;
2297822979

22979-
state = kzalloc(sizeof(struct bpf_verifier_state), GFP_KERNEL);
22980+
state = kzalloc(sizeof(struct bpf_verifier_state), GFP_KERNEL_ACCOUNT);
2298022981
if (!state)
2298122982
return -ENOMEM;
2298222983
state->curframe = 0;
2298322984
state->speculative = false;
2298422985
state->branches = 1;
22985-
state->frame[0] = kzalloc(sizeof(struct bpf_func_state), GFP_KERNEL);
22986+
state->frame[0] = kzalloc(sizeof(struct bpf_func_state), GFP_KERNEL_ACCOUNT);
2298622987
if (!state->frame[0]) {
2298722988
kfree(state);
2298822989
return -ENOMEM;
@@ -23208,7 +23209,7 @@ static void print_verification_stats(struct bpf_verifier_env *env)
2320823209
int bpf_prog_ctx_arg_info_init(struct bpf_prog *prog,
2320923210
const struct bpf_ctx_arg_aux *info, u32 cnt)
2321023211
{
23211-
prog->aux->ctx_arg_info = kmemdup_array(info, cnt, sizeof(*info), GFP_KERNEL);
23212+
prog->aux->ctx_arg_info = kmemdup_array(info, cnt, sizeof(*info), GFP_KERNEL_ACCOUNT);
2321223213
prog->aux->ctx_arg_info_size = cnt;
2321323214

2321423215
return prog->aux->ctx_arg_info ? 0 : -ENOMEM;
@@ -24152,7 +24153,7 @@ static int compute_live_registers(struct bpf_verifier_env *env)
2415224153
* - repeat the computation while {in,out} fields changes for
2415324154
* any instruction.
2415424155
*/
24155-
state = kvcalloc(insn_cnt, sizeof(*state), GFP_KERNEL);
24156+
state = kvcalloc(insn_cnt, sizeof(*state), GFP_KERNEL_ACCOUNT);
2415624157
if (!state) {
2415724158
err = -ENOMEM;
2415824159
goto out;
@@ -24244,10 +24245,10 @@ static int compute_scc(struct bpf_verifier_env *env)
2424424245
* - 'low[t] == n' => smallest preorder number of the vertex reachable from 't' is 'n';
2424524246
* - 'dfs' DFS traversal stack, used to emulate explicit recursion.
2424624247
*/
24247-
stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
24248-
pre = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
24249-
low = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL);
24250-
dfs = kvcalloc(insn_cnt, sizeof(*dfs), GFP_KERNEL);
24248+
stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
24249+
pre = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
24250+
low = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT);
24251+
dfs = kvcalloc(insn_cnt, sizeof(*dfs), GFP_KERNEL_ACCOUNT);
2425124252
if (!stack || !pre || !low || !dfs) {
2425224253
err = -ENOMEM;
2425324254
goto exit;
@@ -24381,7 +24382,7 @@ static int compute_scc(struct bpf_verifier_env *env)
2438124382
dfs_sz--;
2438224383
}
2438324384
}
24384-
env->scc_info = kvcalloc(next_scc_id, sizeof(*env->scc_info), GFP_KERNEL);
24385+
env->scc_info = kvcalloc(next_scc_id, sizeof(*env->scc_info), GFP_KERNEL_ACCOUNT);
2438524386
if (!env->scc_info) {
2438624387
err = -ENOMEM;
2438724388
goto exit;
@@ -24409,7 +24410,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
2440924410
/* 'struct bpf_verifier_env' can be global, but since it's not small,
2441024411
* allocate/free it every time bpf_check() is called
2441124412
*/
24412-
env = kvzalloc(sizeof(struct bpf_verifier_env), GFP_KERNEL);
24413+
env = kvzalloc(sizeof(struct bpf_verifier_env), GFP_KERNEL_ACCOUNT);
2441324414
if (!env)
2441424415
return -ENOMEM;
2441524416

@@ -24472,7 +24473,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
2447224473

2447324474
env->explored_states = kvcalloc(state_htab_size(env),
2447424475
sizeof(struct list_head),
24475-
GFP_USER);
24476+
GFP_KERNEL_ACCOUNT);
2447624477
ret = -ENOMEM;
2447724478
if (!env->explored_states)
2447824479
goto skip_full_check;
@@ -24603,7 +24604,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
2460324604
/* if program passed verifier, update used_maps in bpf_prog_info */
2460424605
env->prog->aux->used_maps = kmalloc_array(env->used_map_cnt,
2460524606
sizeof(env->used_maps[0]),
24606-
GFP_KERNEL);
24607+
GFP_KERNEL_ACCOUNT);
2460724608

2460824609
if (!env->prog->aux->used_maps) {
2460924610
ret = -ENOMEM;
@@ -24618,7 +24619,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
2461824619
/* if program passed verifier, update used_btfs in bpf_prog_aux */
2461924620
env->prog->aux->used_btfs = kmalloc_array(env->used_btf_cnt,
2462024621
sizeof(env->used_btfs[0]),
24621-
GFP_KERNEL);
24622+
GFP_KERNEL_ACCOUNT);
2462224623
if (!env->prog->aux->used_btfs) {
2462324624
ret = -ENOMEM;
2462424625
goto err_release_maps;

0 commit comments

Comments
 (0)