On Tue, Jan 12, 2021 at 5:32 PM Yonghong Song <yhs@xxxxxx> wrote: > > > > On 1/11/21 3:45 PM, Song Liu wrote: > > > > > >> On Jan 11, 2021, at 1:58 PM, Martin Lau <kafai@xxxxxx> wrote: > >> > >> On Mon, Jan 11, 2021 at 10:35:43PM +0100, KP Singh wrote: > >>> On Mon, Jan 11, 2021 at 7:57 PM Martin KaFai Lau <kafai@xxxxxx> wrote: > >>>> > >>>> On Fri, Jan 08, 2021 at 03:19:47PM -0800, Song Liu wrote: > >>>> > >>>> [ ... ] > >>>> > >>>>> diff --git a/kernel/bpf/bpf_local_storage.c b/kernel/bpf/bpf_local_storage.c > >>>>> index dd5aedee99e73..9bd47ad2b26f1 100644 > >>>>> --- a/kernel/bpf/bpf_local_storage.c > >>>>> +++ b/kernel/bpf/bpf_local_storage.c [...] > >>>>> +#include <linux/bpf.h> > >>>>> > >>>>> #include <asm/pgalloc.h> > >>>>> #include <linux/uaccess.h> > >>>>> @@ -734,6 +735,7 @@ void __put_task_struct(struct task_struct *tsk) > >>>>> cgroup_free(tsk); > >>>>> task_numa_free(tsk, true); > >>>>> security_task_free(tsk); > >>>>> + bpf_task_storage_free(tsk); > >>>>> exit_creds(tsk); > >>>> If exit_creds() is traced by a bpf and this bpf is doing > >>>> bpf_task_storage_get(..., BPF_LOCAL_STORAGE_GET_F_CREATE), > >>>> new task storage will be created after bpf_task_storage_free(). > >>>> > >>>> I recalled there was an earlier discussion with KP and KP mentioned > >>>> BPF_LSM will not be called with a task that is going away. > >>>> It seems enabling bpf task storage in bpf tracing will break > >>>> this assumption and needs to be addressed? > >>> > >>> For tracing programs, I think we will need an allow list where > >>> task local storage can be used. > >> Instead of whitelist, can refcount_inc_not_zero(&tsk->usage) be used? > > > > I think we can put refcount_inc_not_zero() in bpf_task_storage_get, like: > > > > diff --git i/kernel/bpf/bpf_task_storage.c w/kernel/bpf/bpf_task_storage.c > > index f654b56907b69..93d01b0a010e6 100644 > > --- i/kernel/bpf/bpf_task_storage.c > > +++ w/kernel/bpf/bpf_task_storage.c > > @@ -216,6 +216,9 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *, > > * by an RCU read-side critical section. > > */ > > if (flags & BPF_LOCAL_STORAGE_GET_F_CREATE) { > > + if (!refcount_inc_not_zero(&task->usage)) > > + return -EBUSY; > > + > > sdata = bpf_local_storage_update( > > task, (struct bpf_local_storage_map *)map, value, > > BPF_NOEXIST); > > > > But where shall we add the refcount_dec()? IIUC, we cannot add it to > > __put_task_struct(). > > Maybe put_task_struct()? Yeah, something like, or if you find a more elegant alternative :) --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -107,13 +107,20 @@ extern void __put_task_struct(struct task_struct *t); static inline void put_task_struct(struct task_struct *t) { - if (refcount_dec_and_test(&t->usage)) + + if (rcu_access_pointer(t->bpf_storage)) { + if (refcount_sub_and_test(2, &t->usage)) + __put_task_struct(t); + } else if (refcount_dec_and_test(&t->usage)) __put_task_struct(t); } static inline void put_task_struct_many(struct task_struct *t, int nr) { - if (refcount_sub_and_test(nr, &t->usage)) + if (rcu_access_pointer(t->bpf_storage)) { + if (refcount_sub_and_test(nr + 1, &t->usage)) + __put_task_struct(t); + } else if (refcount_sub_and_test(nr, &t->usage)) __put_task_struct(t); } I may be missing something but shouldn't bpf_storage be an __rcu member like we have for sk_bpf_storage? #ifdef CONFIG_BPF_SYSCALL struct bpf_local_storage __rcu *sk_bpf_storage; #endif > > > Thanks, > > Song > >