Skip to content

Commit 4cf1bc1

Browse files
sinkapAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: Implement task local storage
Similar to bpf_local_storage for sockets and inodes add local storage for task_struct. The life-cycle of storage is managed with the life-cycle of the task_struct. i.e. the storage is destroyed along with the owning task with a callback to the bpf_task_storage_free from the task_free LSM hook. The BPF LSM allocates an __rcu pointer to the bpf_local_storage in the security blob which are now stackable and can co-exist with other LSMs. The userspace map operations can be done by using a pid fd as a key passed to the lookup, update and delete operations. Signed-off-by: KP Singh <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Song Liu <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 9e7a4d9 commit 4cf1bc1

File tree

10 files changed

+436
-1
lines changed

10 files changed

+436
-1
lines changed

include/linux/bpf_lsm.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#ifndef _LINUX_BPF_LSM_H
88
#define _LINUX_BPF_LSM_H
99

10+
#include <linux/sched.h>
1011
#include <linux/bpf.h>
1112
#include <linux/lsm_hooks.h>
1213

@@ -35,9 +36,21 @@ static inline struct bpf_storage_blob *bpf_inode(
3536
return inode->i_security + bpf_lsm_blob_sizes.lbs_inode;
3637
}
3738

39+
static inline struct bpf_storage_blob *bpf_task(
40+
const struct task_struct *task)
41+
{
42+
if (unlikely(!task->security))
43+
return NULL;
44+
45+
return task->security + bpf_lsm_blob_sizes.lbs_task;
46+
}
47+
3848
extern const struct bpf_func_proto bpf_inode_storage_get_proto;
3949
extern const struct bpf_func_proto bpf_inode_storage_delete_proto;
50+
extern const struct bpf_func_proto bpf_task_storage_get_proto;
51+
extern const struct bpf_func_proto bpf_task_storage_delete_proto;
4052
void bpf_inode_storage_free(struct inode *inode);
53+
void bpf_task_storage_free(struct task_struct *task);
4154

4255
#else /* !CONFIG_BPF_LSM */
4356

@@ -53,10 +66,20 @@ static inline struct bpf_storage_blob *bpf_inode(
5366
return NULL;
5467
}
5568

69+
static inline struct bpf_storage_blob *bpf_task(
70+
const struct task_struct *task)
71+
{
72+
return NULL;
73+
}
74+
5675
static inline void bpf_inode_storage_free(struct inode *inode)
5776
{
5877
}
5978

79+
static inline void bpf_task_storage_free(struct task_struct *task)
80+
{
81+
}
82+
6083
#endif /* CONFIG_BPF_LSM */
6184

6285
#endif /* _LINUX_BPF_LSM_H */

include/linux/bpf_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops)
109109
#endif
110110
#ifdef CONFIG_BPF_LSM
111111
BPF_MAP_TYPE(BPF_MAP_TYPE_INODE_STORAGE, inode_storage_map_ops)
112+
BPF_MAP_TYPE(BPF_MAP_TYPE_TASK_STORAGE, task_storage_map_ops)
112113
#endif
113114
BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops)
114115
#if defined(CONFIG_XDP_SOCKETS)

include/uapi/linux/bpf.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ enum bpf_map_type {
157157
BPF_MAP_TYPE_STRUCT_OPS,
158158
BPF_MAP_TYPE_RINGBUF,
159159
BPF_MAP_TYPE_INODE_STORAGE,
160+
BPF_MAP_TYPE_TASK_STORAGE,
160161
};
161162

162163
/* Note that tracing related programs such as
@@ -3742,6 +3743,42 @@ union bpf_attr {
37423743
* Return
37433744
* The helper returns **TC_ACT_REDIRECT** on success or
37443745
* **TC_ACT_SHOT** on error.
3746+
*
3747+
* void *bpf_task_storage_get(struct bpf_map *map, struct task_struct *task, void *value, u64 flags)
3748+
* Description
3749+
* Get a bpf_local_storage from the *task*.
3750+
*
3751+
* Logically, it could be thought of as getting the value from
3752+
* a *map* with *task* as the **key**. From this
3753+
* perspective, the usage is not much different from
3754+
* **bpf_map_lookup_elem**\ (*map*, **&**\ *task*) except this
3755+
* helper enforces the key must be an task_struct and the map must also
3756+
* be a **BPF_MAP_TYPE_TASK_STORAGE**.
3757+
*
3758+
* Underneath, the value is stored locally at *task* instead of
3759+
* the *map*. The *map* is used as the bpf-local-storage
3760+
* "type". The bpf-local-storage "type" (i.e. the *map*) is
3761+
* searched against all bpf_local_storage residing at *task*.
3762+
*
3763+
* An optional *flags* (**BPF_LOCAL_STORAGE_GET_F_CREATE**) can be
3764+
* used such that a new bpf_local_storage will be
3765+
* created if one does not exist. *value* can be used
3766+
* together with **BPF_LOCAL_STORAGE_GET_F_CREATE** to specify
3767+
* the initial value of a bpf_local_storage. If *value* is
3768+
* **NULL**, the new bpf_local_storage will be zero initialized.
3769+
* Return
3770+
* A bpf_local_storage pointer is returned on success.
3771+
*
3772+
* **NULL** if not found or there was an error in adding
3773+
* a new bpf_local_storage.
3774+
*
3775+
* long bpf_task_storage_delete(struct bpf_map *map, struct task_struct *task)
3776+
* Description
3777+
* Delete a bpf_local_storage from a *task*.
3778+
* Return
3779+
* 0 on success.
3780+
*
3781+
* **-ENOENT** if the bpf_local_storage cannot be found.
37453782
*/
37463783
#define __BPF_FUNC_MAPPER(FN) \
37473784
FN(unspec), \
@@ -3900,6 +3937,8 @@ union bpf_attr {
39003937
FN(bpf_per_cpu_ptr), \
39013938
FN(bpf_this_cpu_ptr), \
39023939
FN(redirect_peer), \
3940+
FN(task_storage_get), \
3941+
FN(task_storage_delete), \
39033942
/* */
39043943

39053944
/* integer value in 'imm' field of BPF_CALL instruction selects which helper

kernel/bpf/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_i
66
obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
77
obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o
88
obj-${CONFIG_BPF_LSM} += bpf_inode_storage.o
9+
obj-${CONFIG_BPF_LSM} += bpf_task_storage.o
910
obj-$(CONFIG_BPF_SYSCALL) += disasm.o
1011
obj-$(CONFIG_BPF_JIT) += trampoline.o
1112
obj-$(CONFIG_BPF_SYSCALL) += btf.o

kernel/bpf/bpf_lsm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6363
return &bpf_spin_lock_proto;
6464
case BPF_FUNC_spin_unlock:
6565
return &bpf_spin_unlock_proto;
66+
case BPF_FUNC_task_storage_get:
67+
return &bpf_task_storage_get_proto;
68+
case BPF_FUNC_task_storage_delete:
69+
return &bpf_task_storage_delete_proto;
6670
default:
6771
return tracing_prog_func_proto(func_id, prog);
6872
}

0 commit comments

Comments
 (0)