Skip to content

Commit cd33943

Browse files
rgushchinborkmann
authored andcommitted
bpf: introduce the bpf_get_local_storage() helper function
The bpf_get_local_storage() helper function is used to get a pointer to the bpf local storage from a bpf program. It takes a pointer to a storage map and flags as arguments. Right now it accepts only cgroup storage maps, and flags argument has to be 0. Further it can be extended to support other types of local storage: e.g. thread local storage etc. Signed-off-by: Roman Gushchin <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Daniel Borkmann <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 7b5dd2b commit cd33943

File tree

7 files changed

+85
-2
lines changed

7 files changed

+85
-2
lines changed

include/linux/bpf.h

+2
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,8 @@ extern const struct bpf_func_proto bpf_sock_map_update_proto;
788788
extern const struct bpf_func_proto bpf_sock_hash_update_proto;
789789
extern const struct bpf_func_proto bpf_get_current_cgroup_id_proto;
790790

791+
extern const struct bpf_func_proto bpf_get_local_storage_proto;
792+
791793
/* Shared helpers among cBPF and eBPF. */
792794
void bpf_user_rnd_init_once(void);
793795
u64 bpf_user_rnd_u32(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);

include/uapi/linux/bpf.h

+20-1
Original file line numberDiff line numberDiff line change
@@ -2095,6 +2095,24 @@ union bpf_attr {
20952095
* Return
20962096
* A 64-bit integer containing the current cgroup id based
20972097
* on the cgroup within which the current task is running.
2098+
*
2099+
* void* get_local_storage(void *map, u64 flags)
2100+
* Description
2101+
* Get the pointer to the local storage area.
2102+
* The type and the size of the local storage is defined
2103+
* by the *map* argument.
2104+
* The *flags* meaning is specific for each map type,
2105+
* and has to be 0 for cgroup local storage.
2106+
*
2107+
* Depending on the bpf program type, a local storage area
2108+
* can be shared between multiple instances of the bpf program,
2109+
* running simultaneously.
2110+
*
2111+
* A user should care about the synchronization by himself.
2112+
* For example, by using the BPF_STX_XADD instruction to alter
2113+
* the shared data.
2114+
* Return
2115+
* Pointer to the local storage area.
20982116
*/
20992117
#define __BPF_FUNC_MAPPER(FN) \
21002118
FN(unspec), \
@@ -2177,7 +2195,8 @@ union bpf_attr {
21772195
FN(rc_repeat), \
21782196
FN(rc_keydown), \
21792197
FN(skb_cgroup_id), \
2180-
FN(get_current_cgroup_id),
2198+
FN(get_current_cgroup_id), \
2199+
FN(get_local_storage),
21812200

21822201
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
21832202
* function eBPF program intends to call

kernel/bpf/cgroup.c

+2
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,8 @@ cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
684684
return &bpf_map_delete_elem_proto;
685685
case BPF_FUNC_get_current_uid_gid:
686686
return &bpf_get_current_uid_gid_proto;
687+
case BPF_FUNC_get_local_storage:
688+
return &bpf_get_local_storage_proto;
687689
case BPF_FUNC_trace_printk:
688690
if (capable(CAP_SYS_ADMIN))
689691
return bpf_get_trace_printk_proto();

kernel/bpf/core.c

+1
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,7 @@ const struct bpf_func_proto bpf_get_current_comm_proto __weak;
17951795
const struct bpf_func_proto bpf_sock_map_update_proto __weak;
17961796
const struct bpf_func_proto bpf_sock_hash_update_proto __weak;
17971797
const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak;
1798+
const struct bpf_func_proto bpf_get_local_storage_proto __weak;
17981799

17991800
const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
18001801
{

kernel/bpf/helpers.c

+20
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,24 @@ const struct bpf_func_proto bpf_get_current_cgroup_id_proto = {
193193
.gpl_only = false,
194194
.ret_type = RET_INTEGER,
195195
};
196+
197+
DECLARE_PER_CPU(void*, bpf_cgroup_storage);
198+
199+
BPF_CALL_2(bpf_get_local_storage, struct bpf_map *, map, u64, flags)
200+
{
201+
/* map and flags arguments are not used now,
202+
* but provide an ability to extend the API
203+
* for other types of local storages.
204+
* verifier checks that their values are correct.
205+
*/
206+
return (unsigned long) this_cpu_read(bpf_cgroup_storage);
207+
}
208+
209+
const struct bpf_func_proto bpf_get_local_storage_proto = {
210+
.func = bpf_get_local_storage,
211+
.gpl_only = false,
212+
.ret_type = RET_PTR_TO_MAP_VALUE,
213+
.arg1_type = ARG_CONST_MAP_PTR,
214+
.arg2_type = ARG_ANYTHING,
215+
};
196216
#endif

kernel/bpf/verifier.c

+18
Original file line numberDiff line numberDiff line change
@@ -2127,6 +2127,10 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
21272127
func_id != BPF_FUNC_current_task_under_cgroup)
21282128
goto error;
21292129
break;
2130+
case BPF_MAP_TYPE_CGROUP_STORAGE:
2131+
if (func_id != BPF_FUNC_get_local_storage)
2132+
goto error;
2133+
break;
21302134
/* devmap returns a pointer to a live net_device ifindex that we cannot
21312135
* allow to be modified from bpf side. So do not allow lookup elements
21322136
* for now.
@@ -2209,6 +2213,10 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
22092213
if (map->map_type != BPF_MAP_TYPE_SOCKHASH)
22102214
goto error;
22112215
break;
2216+
case BPF_FUNC_get_local_storage:
2217+
if (map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE)
2218+
goto error;
2219+
break;
22122220
default:
22132221
break;
22142222
}
@@ -2533,6 +2541,16 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
25332541
}
25342542

25352543
regs = cur_regs(env);
2544+
2545+
/* check that flags argument in get_local_storage(map, flags) is 0,
2546+
* this is required because get_local_storage() can't return an error.
2547+
*/
2548+
if (func_id == BPF_FUNC_get_local_storage &&
2549+
!register_is_null(&regs[BPF_REG_2])) {
2550+
verbose(env, "get_local_storage() doesn't support non-zero flags\n");
2551+
return -EINVAL;
2552+
}
2553+
25362554
/* reset caller saved regs */
25372555
for (i = 0; i < CALLER_SAVED_REGS; i++) {
25382556
mark_reg_not_init(env, regs, caller_saved[i]);

net/core/filter.c

+22-1
Original file line numberDiff line numberDiff line change
@@ -4820,6 +4820,8 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
48204820
*/
48214821
case BPF_FUNC_get_current_uid_gid:
48224822
return &bpf_get_current_uid_gid_proto;
4823+
case BPF_FUNC_get_local_storage:
4824+
return &bpf_get_local_storage_proto;
48234825
default:
48244826
return bpf_base_func_proto(func_id);
48254827
}
@@ -4844,6 +4846,8 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
48444846
}
48454847
case BPF_FUNC_get_socket_cookie:
48464848
return &bpf_get_socket_cookie_sock_addr_proto;
4849+
case BPF_FUNC_get_local_storage:
4850+
return &bpf_get_local_storage_proto;
48474851
default:
48484852
return bpf_base_func_proto(func_id);
48494853
}
@@ -4866,6 +4870,17 @@ sk_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
48664870
}
48674871
}
48684872

4873+
static const struct bpf_func_proto *
4874+
cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
4875+
{
4876+
switch (func_id) {
4877+
case BPF_FUNC_get_local_storage:
4878+
return &bpf_get_local_storage_proto;
4879+
default:
4880+
return sk_filter_func_proto(func_id, prog);
4881+
}
4882+
}
4883+
48694884
static const struct bpf_func_proto *
48704885
tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
48714886
{
@@ -4988,6 +5003,8 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
49885003
return &bpf_sock_hash_update_proto;
49895004
case BPF_FUNC_get_socket_cookie:
49905005
return &bpf_get_socket_cookie_sock_ops_proto;
5006+
case BPF_FUNC_get_local_storage:
5007+
return &bpf_get_local_storage_proto;
49915008
default:
49925009
return bpf_base_func_proto(func_id);
49935010
}
@@ -5007,6 +5024,8 @@ sk_msg_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
50075024
return &bpf_msg_cork_bytes_proto;
50085025
case BPF_FUNC_msg_pull_data:
50095026
return &bpf_msg_pull_data_proto;
5027+
case BPF_FUNC_get_local_storage:
5028+
return &bpf_get_local_storage_proto;
50105029
default:
50115030
return bpf_base_func_proto(func_id);
50125031
}
@@ -5034,6 +5053,8 @@ sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
50345053
return &bpf_sk_redirect_map_proto;
50355054
case BPF_FUNC_sk_redirect_hash:
50365055
return &bpf_sk_redirect_hash_proto;
5056+
case BPF_FUNC_get_local_storage:
5057+
return &bpf_get_local_storage_proto;
50375058
default:
50385059
return bpf_base_func_proto(func_id);
50395060
}
@@ -6838,7 +6859,7 @@ const struct bpf_prog_ops xdp_prog_ops = {
68386859
};
68396860

68406861
const struct bpf_verifier_ops cg_skb_verifier_ops = {
6841-
.get_func_proto = sk_filter_func_proto,
6862+
.get_func_proto = cg_skb_func_proto,
68426863
.is_valid_access = sk_filter_is_valid_access,
68436864
.convert_ctx_access = bpf_convert_ctx_access,
68446865
};

0 commit comments

Comments
 (0)