History

bpf: Remove gfp_flags plumbing from bpf_local_storage_update()

Remove the check that rejects sleepable BPF programs from doing BPF_ANY/BPF_EXIST updates on local storage. This restriction was added in commit b00fa38a9c1c ("bpf: Enable non-atomic allocations in local storage") because kzalloc(GFP_KERNEL) could sleep inside local_storage->lock. This is no longer a concern: all local storage allocations now use kmalloc_nolock() which never sleeps. In addition, since kmalloc_nolock() only accepts __GFP_ACCOUNT, __GFP_ZERO and __GFP_NO_OBJ_EXT, the gfp_flags parameter plumbing from bpf_*_storage_get() to bpf_local_storage_update() becomes dead code. Remove gfp_flags from bpf_selem_alloc(), bpf_local_storage_alloc() and bpf_local_storage_update(). Drop the hidden 5th argument from bpf_*_storage_get helpers, and remove the verifier patching that injected GFP_KERNEL/GFP_ATOMIC into the fifth argument.

Amery Hung committed 7 months ago

Commit 136deea1 parent 5063e777 files · +30 −67Browse files

Showing the changes to kernel (5 of 7 files). Show all

Unified · Split

5 files
  1. kernel/bpf/bpf_cgrp_storage.c +4 −5
  2. kernel/bpf/bpf_inode_storage.c +4 −5
  3. kernel/bpf/bpf_local_storage.c +6 −10
  4. kernel/bpf/bpf_task_storage.c +4 −5
  5. kernel/bpf/verifier.c +0 −26
kernel/bpf/bpf_cgrp_storage.c+4−5
@@ -76,7 +76,7 @@ static long bpf_cgrp_storage_update_elem(struct bpf_map *map, void *key, · 75 unmodified lines
7676 return PTR_ERR(cgroup);
7777
7878 sdata = bpf_local_storage_update(cgroup, (struct bpf_local_storage_map *)map,
79− value, map_flags, false, GFP_ATOMIC);
79+ value, map_flags, false);
8080 cgroup_put(cgroup);
8181 return PTR_ERR_OR_ZERO(sdata);
8282 }
@@ -122,9 +122,8 @@ static void cgroup_storage_map_free(struct bpf_map *map) · 39 unmodified lines
122122 bpf_local_storage_map_free(map, &cgroup_cache);
123123 }
124124
125−/* *gfp_flags* is a hidden argument provided by the verifier */
126−BPF_CALL_5(bpf_cgrp_storage_get, struct bpf_map *, map, struct cgroup *, cgroup,
127− void *, value, u64, flags, gfp_t, gfp_flags)
125+BPF_CALL_4(bpf_cgrp_storage_get, struct bpf_map *, map, struct cgroup *, cgroup,
126+ void *, value, u64, flags)
128127 {
129128 struct bpf_local_storage_data *sdata;
130129
@@ -143,7 +142,7 @@ BPF_CALL_5(bpf_cgrp_storage_get, struct bpf_map *, map, struct cgroup *, cgroup, · 12 unmodified lines
143142 if (!percpu_ref_is_dying(&cgroup->self.refcnt) &&
144143 (flags & BPF_LOCAL_STORAGE_GET_F_CREATE))
145144 sdata = bpf_local_storage_update(cgroup, (struct bpf_local_storage_map *)map,
146− value, BPF_NOEXIST, false, gfp_flags);
145+ value, BPF_NOEXIST, false);
147146
148147 out:
149148 return IS_ERR_OR_NULL(sdata) ? (unsigned long)NULL : (unsigned long)sdata->data;
kernel/bpf/bpf_inode_storage.c+4−5
@@ -98,7 +98,7 @@ static long bpf_fd_inode_storage_update_elem(struct bpf_map *map, void *key, · 97 unmodified lines
9898
9999 sdata = bpf_local_storage_update(file_inode(fd_file(f)),
100100 (struct bpf_local_storage_map *)map,
101− value, map_flags, false, GFP_ATOMIC);
101+ value, map_flags, false);
102102 return PTR_ERR_OR_ZERO(sdata);
103103 }
104104
@@ -122,9 +122,8 @@ static long bpf_fd_inode_storage_delete_elem(struct bpf_map *map, void *key) · 17 unmodified lines
122122 return inode_storage_delete(file_inode(fd_file(f)), map);
123123 }
124124
125−/* *gfp_flags* is a hidden argument provided by the verifier */
126−BPF_CALL_5(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
127− void *, value, u64, flags, gfp_t, gfp_flags)
125+BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
126+ void *, value, u64, flags)
128127 {
129128 struct bpf_local_storage_data *sdata;
130129
@@ -150,7 +149,7 @@ BPF_CALL_5(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode, · 19 unmodified lines
150149 if (flags & BPF_LOCAL_STORAGE_GET_F_CREATE) {
151150 sdata = bpf_local_storage_update(
152151 inode, (struct bpf_local_storage_map *)map, value,
153− BPF_NOEXIST, false, gfp_flags);
152+ BPF_NOEXIST, false);
154153 return IS_ERR(sdata) ? (unsigned long)NULL :
155154 (unsigned long)sdata->data;
156155 }
kernel/bpf/bpf_local_storage.c+6−10
@@ -68,7 +68,7 @@ static bool selem_linked_to_map(const struct bpf_local_storage_elem *selem) · 67 unmodified lines
6868
6969 struct bpf_local_storage_elem *
7070 bpf_selem_alloc(struct bpf_local_storage_map *smap, void *owner,
71− void *value, bool swap_uptrs, gfp_t gfp_flags)
71+ void *value, bool swap_uptrs)
7272 {
7373 struct bpf_local_storage_elem *selem;
7474
@@ -475,8 +475,7 @@ static int check_flags(const struct bpf_local_storage_data *old_sdata, · 400 unmodified lines
475475
476476 int bpf_local_storage_alloc(void *owner,
477477 struct bpf_local_storage_map *smap,
478− struct bpf_local_storage_elem *first_selem,
479− gfp_t gfp_flags)
478+ struct bpf_local_storage_elem *first_selem)
480479 {
481480 struct bpf_local_storage *prev_storage, *storage;
482481 struct bpf_local_storage **owner_storage_ptr;
@@ -546,7 +545,7 @@ uncharge: · 63 unmodified lines
546545 */
547546 struct bpf_local_storage_data *
548547 bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap,
549− void *value, u64 map_flags, bool swap_uptrs, gfp_t gfp_flags)
548+ void *value, u64 map_flags, bool swap_uptrs)
550549 {
551550 struct bpf_local_storage_data *old_sdata = NULL;
552551 struct bpf_local_storage_elem *alloc_selem, *selem = NULL;
@@ -563,9 +562,6 @@ bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap, · 10 unmodified lines
563562 !btf_record_has_field(smap->map.record, BPF_SPIN_LOCK)))
564563 return ERR_PTR(-EINVAL);
565564
566− if (gfp_flags == GFP_KERNEL && (map_flags & ~BPF_F_LOCK) != BPF_NOEXIST)
567− return ERR_PTR(-EINVAL);
568−
569565 local_storage = rcu_dereference_check(*owner_storage(smap, owner),
570566 bpf_rcu_lock_held());
571567 if (!local_storage || hlist_empty(&local_storage->list)) {
@@ -574,11 +570,11 @@ bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap, · 2 unmodified lines
574570 if (err)
575571 return ERR_PTR(err);
576572
577− selem = bpf_selem_alloc(smap, owner, value, swap_uptrs, gfp_flags);
573+ selem = bpf_selem_alloc(smap, owner, value, swap_uptrs);
578574 if (!selem)
579575 return ERR_PTR(-ENOMEM);
580576
581− err = bpf_local_storage_alloc(owner, smap, selem, gfp_flags);
577+ err = bpf_local_storage_alloc(owner, smap, selem);
582578 if (err) {
583579 bpf_selem_free(selem, true);
584580 mem_uncharge(smap, owner, smap->elem_size);
@@ -608,7 +604,7 @@ bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap, · 23 unmodified lines
608604 /* A lookup has just been done before and concluded a new selem is
609605 * needed. The chance of an unnecessary alloc is unlikely.
610606 */
611− alloc_selem = selem = bpf_selem_alloc(smap, owner, value, swap_uptrs, gfp_flags);
607+ alloc_selem = selem = bpf_selem_alloc(smap, owner, value, swap_uptrs);
612608 if (!alloc_selem)
613609 return ERR_PTR(-ENOMEM);
614610
kernel/bpf/bpf_task_storage.c+4−5
@@ -118,7 +118,7 @@ static long bpf_pid_task_storage_update_elem(struct bpf_map *map, void *key, · 117 unmodified lines
118118
119119 sdata = bpf_local_storage_update(
120120 task, (struct bpf_local_storage_map *)map, value, map_flags,
121− true, GFP_ATOMIC);
121+ true);
122122
123123 err = PTR_ERR_OR_ZERO(sdata);
124124 out:
@@ -165,9 +165,8 @@ out: · 40 unmodified lines
165165 return err;
166166 }
167167
168−/* *gfp_flags* is a hidden argument provided by the verifier */
169−BPF_CALL_5(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
170− task, void *, value, u64, flags, gfp_t, gfp_flags)
168+BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
169+ task, void *, value, u64, flags)
171170 {
172171 struct bpf_local_storage_data *sdata;
173172
@@ -184,7 +183,7 @@ BPF_CALL_5(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *, · 10 unmodified lines
184183 (flags & BPF_LOCAL_STORAGE_GET_F_CREATE)) {
185184 sdata = bpf_local_storage_update(
186185 task, (struct bpf_local_storage_map *)map, value,
187− BPF_NOEXIST, false, gfp_flags);
186+ BPF_NOEXIST, false);
188187 return IS_ERR(sdata) ? (unsigned long)NULL : (unsigned long)sdata->data;
189188 }
190189
kernel/bpf/verifier.c+0−26
@@ -589,14 +589,6 @@ static bool is_may_goto_insn_at(struct bpf_verifier_env *env, int insn_idx) · 588 unmodified lines
589589 return bpf_is_may_goto_insn(&env->prog->insnsi[insn_idx]);
590590 }
591591
592−static bool is_storage_get_function(enum bpf_func_id func_id)
593−{
594− return func_id == BPF_FUNC_sk_storage_get ||
595− func_id == BPF_FUNC_inode_storage_get ||
596− func_id == BPF_FUNC_task_storage_get ||
597− func_id == BPF_FUNC_cgrp_storage_get;
598−}
599−
600592 static bool helper_multiple_ref_obj_use(enum bpf_func_id func_id,
601593 const struct bpf_map *map)
602594 {
@@ -24429,24 +24421,6 @@ static int do_misc_fixups(struct bpf_verifier_env *env) · 23826 unmodified lines
2442924421 goto patch_call_imm;
2443024422 }
2443124423
24432− if (is_storage_get_function(insn->imm)) {
24433− if (env->insn_aux_data[i + delta].non_sleepable)
24434− insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_ATOMIC);
24435− else
24436− insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_KERNEL);
24437− insn_buf[1] = *insn;
24438− cnt = 2;
24439−
24440− new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
24441− if (!new_prog)
24442− return -ENOMEM;
24443−
24444− delta += cnt - 1;
24445− env->prog = prog = new_prog;
24446− insn = new_prog->insnsi + i + delta;
24447− goto patch_call_imm;
24448− }
24449−
2445024424 /* bpf_per_cpu_ptr() and bpf_this_cpu_ptr() */
2445124425 if (env->insn_aux_data[i + delta].call_with_percpu_alloc_ptr) {
2445224426 /* patch with 'r1 = *(u64 *)(r1 + 0)' since for percpu data,