mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
@ 2017-10-16 22:10 Alexei Starovoitov
  2017-10-16 22:19 ` Daniel Borkmann
  0 siblings, 1 reply; 7+ messages in thread
From: Alexei Starovoitov @ 2017-10-16 22:10 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Daniel Borkmann, netdev, linux-kernel, Alexei Starovoitov

On Mon, Oct 16, 2017 at 2:10 PM, Richard Weinberger <richard@nod.at> wrote:
> Am Montag, 16. Oktober 2017, 23:02:06 CEST schrieb Daniel Borkmann:
>> On 10/16/2017 10:55 PM, Richard Weinberger wrote:
>> > Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
>> >>>           struct task_struct *task = current;
>> >>>
>> >>> + task_lock(task);
>> >>>
>> >>>           strncpy(buf, task->comm, size);
>> >>>
>> >>> + task_unlock(task);
>> >>
>> >> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
>> >> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
>> >> bpf_get_current_comm() taking the lock again ...
>> >
>> > Yes, but doesn't the same apply to the use case when I attach to strncpy()
>> > and run bpf_get_current_comm()?
>>
>> You mean due to recursion? In that case trace_call_bpf() would bail out
>> due to the bpf_prog_active counter.
>
> Ah, that's true.
> So, when someone wants to use bpf_get_current_comm() while tracing task_lock,
> we have a problem. I agree.
> On the other hand, without locking the function may return wrong results.

it will surely race with somebody else setting task comm and it's fine.
all of bpf tracing is read-only, so locks are only allowed inside bpf core
bits like maps. Taking core locks like task_lock() is quite scary.
bpf scripts rely on bpf_probe_read() of all sorts of kernel fields
so reading comm here w/o lock is fine.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
  2017-10-16 22:10 [PATCH 3/3] bpf: Make sure that ->comm does not change under us Alexei Starovoitov
@ 2017-10-16 22:19 ` Daniel Borkmann
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Borkmann @ 2017-10-16 22:19 UTC (permalink / raw)
  To: Alexei Starovoitov, Richard Weinberger
  Cc: netdev, linux-kernel, Alexei Starovoitov

On 10/17/2017 12:10 AM, Alexei Starovoitov wrote:
> On Mon, Oct 16, 2017 at 2:10 PM, Richard Weinberger <richard@nod.at> wrote:
>> Am Montag, 16. Oktober 2017, 23:02:06 CEST schrieb Daniel Borkmann:
>>> On 10/16/2017 10:55 PM, Richard Weinberger wrote:
>>>> Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
>>>>>>            struct task_struct *task = current;
>>>>>>
>>>>>> + task_lock(task);
>>>>>>
>>>>>>            strncpy(buf, task->comm, size);
>>>>>>
>>>>>> + task_unlock(task);
>>>>>
>>>>> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
>>>>> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
>>>>> bpf_get_current_comm() taking the lock again ...
>>>>
>>>> Yes, but doesn't the same apply to the use case when I attach to strncpy()
>>>> and run bpf_get_current_comm()?
>>>
>>> You mean due to recursion? In that case trace_call_bpf() would bail out
>>> due to the bpf_prog_active counter.
>>
>> Ah, that's true.
>> So, when someone wants to use bpf_get_current_comm() while tracing task_lock,
>> we have a problem. I agree.
>> On the other hand, without locking the function may return wrong results.
>
> it will surely race with somebody else setting task comm and it's fine.
> all of bpf tracing is read-only, so locks are only allowed inside bpf core
> bits like maps. Taking core locks like task_lock() is quite scary.
> bpf scripts rely on bpf_probe_read() of all sorts of kernel fields
> so reading comm here w/o lock is fine.

Yeah, and perf_event_comm() -> perf_event_comm_event() out of __set_task_comm()
is having same approach wrt comm read-out.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
  2017-10-16 21:02       ` Daniel Borkmann
@ 2017-10-16 21:10         ` Richard Weinberger
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Weinberger @ 2017-10-16 21:10 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: netdev, linux-kernel, ast

Am Montag, 16. Oktober 2017, 23:02:06 CEST schrieb Daniel Borkmann:
> On 10/16/2017 10:55 PM, Richard Weinberger wrote:
> > Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
> >>>    	struct task_struct *task = current;
> >>> 
> >>> +	task_lock(task);
> >>> 
> >>>    	strncpy(buf, task->comm, size);
> >>> 
> >>> +	task_unlock(task);
> >> 
> >> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
> >> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
> >> bpf_get_current_comm() taking the lock again ...
> > 
> > Yes, but doesn't the same apply to the use case when I attach to strncpy()
> > and run bpf_get_current_comm()?
> 
> You mean due to recursion? In that case trace_call_bpf() would bail out
> due to the bpf_prog_active counter.

Ah, that's true.
So, when someone wants to use bpf_get_current_comm() while tracing task_lock,
we have a problem. I agree.
On the other hand, without locking the function may return wrong results.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
  2017-10-16 20:55     ` Richard Weinberger
@ 2017-10-16 21:02       ` Daniel Borkmann
  2017-10-16 21:10         ` Richard Weinberger
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Borkmann @ 2017-10-16 21:02 UTC (permalink / raw)
  To: Richard Weinberger; +Cc: netdev, linux-kernel, ast

On 10/16/2017 10:55 PM, Richard Weinberger wrote:
> Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
>>>    	struct task_struct *task = current;
>>>
>>> +	task_lock(task);
>>>
>>>    	strncpy(buf, task->comm, size);
>>>
>>> +	task_unlock(task);
>>
>> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
>> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
>> bpf_get_current_comm() taking the lock again ...
>
> Yes, but doesn't the same apply to the use case when I attach to strncpy()
> and run bpf_get_current_comm()?

You mean due to recursion? In that case trace_call_bpf() would bail out
due to the bpf_prog_active counter.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
  2017-10-16 20:50   ` Daniel Borkmann
@ 2017-10-16 20:55     ` Richard Weinberger
  2017-10-16 21:02       ` Daniel Borkmann
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Weinberger @ 2017-10-16 20:55 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: netdev, linux-kernel, ast

Am Montag, 16. Oktober 2017, 22:50:43 CEST schrieb Daniel Borkmann:
> >   	struct task_struct *task = current;
> > 
> > +	task_lock(task);
> > 
> >   	strncpy(buf, task->comm, size);
> > 
> > +	task_unlock(task);
> 
> Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
> to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
> bpf_get_current_comm() taking the lock again ...

Yes, but doesn't the same apply to the use case when I attach to strncpy()
and run bpf_get_current_comm()?

Thanks,
//richard

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
  2017-10-16 18:18 ` [PATCH 3/3] bpf: Make sure that ->comm does not change under us Richard Weinberger
@ 2017-10-16 20:50   ` Daniel Borkmann
  2017-10-16 20:55     ` Richard Weinberger
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Borkmann @ 2017-10-16 20:50 UTC (permalink / raw)
  To: Richard Weinberger, netdev; +Cc: linux-kernel, ast

On 10/16/2017 08:18 PM, Richard Weinberger wrote:
> Sadly we cannot use get_task_comm() since bpf_get_current_comm()
> allows truncation.
>
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>   kernel/bpf/helpers.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 511c9d522cfc..4b042b24524d 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -18,6 +18,7 @@
>   #include <linux/sched.h>
>   #include <linux/uidgid.h>
>   #include <linux/filter.h>
> +#include <linux/sched/task.h>
>
>   /* If kernel subsystem is allowing eBPF programs to call this function,
>    * inside its own verifier_ops->get_func_proto() callback it should return
> @@ -149,7 +150,9 @@ BPF_CALL_2(bpf_get_current_comm, char *, buf, u32, size)
>   {
>   	struct task_struct *task = current;
>
> +	task_lock(task);
>   	strncpy(buf, task->comm, size);
> +	task_unlock(task);

Wouldn't this potentially lead to a deadlock? E.g. you attach yourself
to task_lock() / spin_lock() / etc, and then the BPF prog triggers the
bpf_get_current_comm() taking the lock again ...

>   	/* Verifier guarantees that size > 0. For task->comm exceeding
>   	 * size, guarantee that buf is %NUL-terminated. Unconditionally
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/3] bpf: Make sure that ->comm does not change under us.
  2017-10-16 18:18 [PATCH 1/3] bpf: Don't check for current being NULL Richard Weinberger
@ 2017-10-16 18:18 ` Richard Weinberger
  2017-10-16 20:50   ` Daniel Borkmann
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Weinberger @ 2017-10-16 18:18 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, daniel, ast, Richard Weinberger

Sadly we cannot use get_task_comm() since bpf_get_current_comm()
allows truncation.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 kernel/bpf/helpers.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 511c9d522cfc..4b042b24524d 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/uidgid.h>
 #include <linux/filter.h>
+#include <linux/sched/task.h>
 
 /* If kernel subsystem is allowing eBPF programs to call this function,
  * inside its own verifier_ops->get_func_proto() callback it should return
@@ -149,7 +150,9 @@ BPF_CALL_2(bpf_get_current_comm, char *, buf, u32, size)
 {
 	struct task_struct *task = current;
 
+	task_lock(task);
 	strncpy(buf, task->comm, size);
+	task_unlock(task);
 
 	/* Verifier guarantees that size > 0. For task->comm exceeding
 	 * size, guarantee that buf is %NUL-terminated. Unconditionally
-- 
2.13.6

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-10-16 22:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-16 22:10 [PATCH 3/3] bpf: Make sure that ->comm does not change under us Alexei Starovoitov
2017-10-16 22:19 ` Daniel Borkmann
  -- strict thread matches above, loose matches on Subject: below --
2017-10-16 18:18 [PATCH 1/3] bpf: Don't check for current being NULL Richard Weinberger
2017-10-16 18:18 ` [PATCH 3/3] bpf: Make sure that ->comm does not change under us Richard Weinberger
2017-10-16 20:50   ` Daniel Borkmann
2017-10-16 20:55     ` Richard Weinberger
2017-10-16 21:02       ` Daniel Borkmann
2017-10-16 21:10         ` Richard Weinberger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®