linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] bpf: btf: Fix a missing-check bug
@ 2018-10-19 22:29 Wenwen Wang
  2018-10-22 15:40 ` Martin Lau
  2018-10-22 15:57 ` Y Song
  0 siblings, 2 replies; 5+ messages in thread
From: Wenwen Wang @ 2018-10-19 22:29 UTC (permalink / raw)
  To: Wenwen Wang
  Cc: Kangjie Lu, Alexei Starovoitov, Daniel Borkmann,
	open list:BPF (Safe dynamic programs and tools),
	open list:BPF (Safe dynamic programs and tools)

In btf_parse(), the header of the user-space btf data 'btf_data' is firstly
parsed and verified through btf_parse_hdr(). In btf_parse_hdr(), the header
is copied from user-space 'btf_data' to kernel-space 'btf->hdr' and then
verified. If no error happens during the verification process, the whole
data of 'btf_data', including the header, is then copied to 'data' in
btf_parse(). It is obvious that the header is copied twice here. More
importantly, no check is enforced after the second copy to make sure the
headers obtained in these two copies are same. Given that 'btf_data'
resides in the user space, a malicious user can race to modify the header
between these two copies. By doing so, the user can inject inconsistent
data, which can cause undefined behavior of the kernel and introduce
potential security risk.

To avoid the above issue, this patch rewrites the header after the second
copy, using 'btf->hdr', which is obtained in the first copy.

Signed-off-by: Wenwen Wang <wang6495@umn.edu>
---
 kernel/bpf/btf.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 138f030..2a85f91 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -2202,6 +2202,9 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,
 		goto errout;
 	}
 
+	memcpy(data, &btf->hdr,
+		min_t(u32, btf->hdr.hdr_len, sizeof(btf->hdr)));
+
 	err = btf_parse_str_sec(env);
 	if (err)
 		goto errout;
-- 
2.7.4


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

* Re: [PATCH] bpf: btf: Fix a missing-check bug
  2018-10-19 22:29 [PATCH] bpf: btf: Fix a missing-check bug Wenwen Wang
@ 2018-10-22 15:40 ` Martin Lau
  2018-10-22 15:57 ` Y Song
  1 sibling, 0 replies; 5+ messages in thread
From: Martin Lau @ 2018-10-22 15:40 UTC (permalink / raw)
  To: Wenwen Wang
  Cc: Kangjie Lu, Alexei Starovoitov, Daniel Borkmann,
	open list:BPF (Safe dynamic programs and tools),
	open list:BPF (Safe dynamic programs and tools)

On Fri, Oct 19, 2018 at 05:29:51PM -0500, Wenwen Wang wrote:
> In btf_parse(), the header of the user-space btf data 'btf_data' is firstly
> parsed and verified through btf_parse_hdr(). In btf_parse_hdr(), the header
> is copied from user-space 'btf_data' to kernel-space 'btf->hdr' and then
> verified. If no error happens during the verification process, the whole
> data of 'btf_data', including the header, is then copied to 'data' in
> btf_parse(). It is obvious that the header is copied twice here. More
> importantly, no check is enforced after the second copy to make sure the
> headers obtained in these two copies are same. Given that 'btf_data'
> resides in the user space, a malicious user can race to modify the header
> between these two copies. By doing so, the user can inject inconsistent
> data, which can cause undefined behavior of the kernel and introduce
> potential security risk.
> 
> To avoid the above issue, this patch rewrites the header after the second
> copy, using 'btf->hdr', which is obtained in the first copy.
Acked-by: Martin KaFai Lau <kafai@fb.com>

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

* Re: [PATCH] bpf: btf: Fix a missing-check bug
  2018-10-19 22:29 [PATCH] bpf: btf: Fix a missing-check bug Wenwen Wang
  2018-10-22 15:40 ` Martin Lau
@ 2018-10-22 15:57 ` Y Song
  2018-10-24  9:16   ` Daniel Borkmann
  1 sibling, 1 reply; 5+ messages in thread
From: Y Song @ 2018-10-22 15:57 UTC (permalink / raw)
  To: wang6495; +Cc: kjlu, Alexei Starovoitov, Daniel Borkmann, netdev, LKML

On Fri, Oct 19, 2018 at 3:30 PM Wenwen Wang <wang6495@umn.edu> wrote:
>
> In btf_parse(), the header of the user-space btf data 'btf_data' is firstly
> parsed and verified through btf_parse_hdr(). In btf_parse_hdr(), the header
> is copied from user-space 'btf_data' to kernel-space 'btf->hdr' and then
> verified. If no error happens during the verification process, the whole
> data of 'btf_data', including the header, is then copied to 'data' in
> btf_parse(). It is obvious that the header is copied twice here. More
> importantly, no check is enforced after the second copy to make sure the
> headers obtained in these two copies are same. Given that 'btf_data'
> resides in the user space, a malicious user can race to modify the header
> between these two copies. By doing so, the user can inject inconsistent
> data, which can cause undefined behavior of the kernel and introduce
> potential security risk.
>
> To avoid the above issue, this patch rewrites the header after the second
> copy, using 'btf->hdr', which is obtained in the first copy.
>
> Signed-off-by: Wenwen Wang <wang6495@umn.edu>
> ---
>  kernel/bpf/btf.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 138f030..2a85f91 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -2202,6 +2202,9 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,
>                 goto errout;
>         }
>
> +       memcpy(data, &btf->hdr,
> +               min_t(u32, btf->hdr.hdr_len, sizeof(btf->hdr)));

Could you restructure the code to memcpy the header followed by copying
the rest of btf_data with copy_from_user? This way, each byte is only
copied once.
Could you add some comments right before memcpy so later people will know
why we implement this way?

> +
>         err = btf_parse_str_sec(env);
>         if (err)
>                 goto errout;
> --
> 2.7.4
>

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

* Re: [PATCH] bpf: btf: Fix a missing-check bug
  2018-10-22 15:57 ` Y Song
@ 2018-10-24  9:16   ` Daniel Borkmann
  2018-10-24 11:36     ` Wenwen Wang
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel Borkmann @ 2018-10-24  9:16 UTC (permalink / raw)
  To: Y Song, wang6495; +Cc: kjlu, Alexei Starovoitov, netdev, LKML

Hi Wenwen,

On 10/22/2018 05:57 PM, Y Song wrote:
> On Fri, Oct 19, 2018 at 3:30 PM Wenwen Wang <wang6495@umn.edu> wrote:
>>
>> In btf_parse(), the header of the user-space btf data 'btf_data' is firstly
>> parsed and verified through btf_parse_hdr(). In btf_parse_hdr(), the header
>> is copied from user-space 'btf_data' to kernel-space 'btf->hdr' and then
>> verified. If no error happens during the verification process, the whole
>> data of 'btf_data', including the header, is then copied to 'data' in
>> btf_parse(). It is obvious that the header is copied twice here. More
>> importantly, no check is enforced after the second copy to make sure the
>> headers obtained in these two copies are same. Given that 'btf_data'
>> resides in the user space, a malicious user can race to modify the header
>> between these two copies. By doing so, the user can inject inconsistent
>> data, which can cause undefined behavior of the kernel and introduce
>> potential security risk.
>>
>> To avoid the above issue, this patch rewrites the header after the second
>> copy, using 'btf->hdr', which is obtained in the first copy.
>>
>> Signed-off-by: Wenwen Wang <wang6495@umn.edu>
>> ---
>>  kernel/bpf/btf.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index 138f030..2a85f91 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
>> @@ -2202,6 +2202,9 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,
>>                 goto errout;
>>         }
>>
>> +       memcpy(data, &btf->hdr,
>> +               min_t(u32, btf->hdr.hdr_len, sizeof(btf->hdr)));
> 
> Could you restructure the code to memcpy the header followed by copying
> the rest of btf_data with copy_from_user? This way, each byte is only
> copied once.
> Could you add some comments right before memcpy so later people will know
> why we implement this way?

Thanks for the fix! Agree with Yonghong that we should rework this a bit, so
please respin a v2 with the feedback addressed, thanks.

>> +
>>         err = btf_parse_str_sec(env);
>>         if (err)
>>                 goto errout;
>> --
>> 2.7.4
>>


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

* Re: [PATCH] bpf: btf: Fix a missing-check bug
  2018-10-24  9:16   ` Daniel Borkmann
@ 2018-10-24 11:36     ` Wenwen Wang
  0 siblings, 0 replies; 5+ messages in thread
From: Wenwen Wang @ 2018-10-24 11:36 UTC (permalink / raw)
  To: daniel
  Cc: ys114321, Kangjie Lu, ast, open list:NETWORKING [GENERAL],
	open list, Wenwen Wang

On Wed, Oct 24, 2018 at 4:39 AM Daniel Borkmann <daniel@iogearbox.net> wrote:
>
> Hi Wenwen,
>
> On 10/22/2018 05:57 PM, Y Song wrote:
> > On Fri, Oct 19, 2018 at 3:30 PM Wenwen Wang <wang6495@umn.edu> wrote:
> >>
> >> In btf_parse(), the header of the user-space btf data 'btf_data' is firstly
> >> parsed and verified through btf_parse_hdr(). In btf_parse_hdr(), the header
> >> is copied from user-space 'btf_data' to kernel-space 'btf->hdr' and then
> >> verified. If no error happens during the verification process, the whole
> >> data of 'btf_data', including the header, is then copied to 'data' in
> >> btf_parse(). It is obvious that the header is copied twice here. More
> >> importantly, no check is enforced after the second copy to make sure the
> >> headers obtained in these two copies are same. Given that 'btf_data'
> >> resides in the user space, a malicious user can race to modify the header
> >> between these two copies. By doing so, the user can inject inconsistent
> >> data, which can cause undefined behavior of the kernel and introduce
> >> potential security risk.
> >>
> >> To avoid the above issue, this patch rewrites the header after the second
> >> copy, using 'btf->hdr', which is obtained in the first copy.
> >>
> >> Signed-off-by: Wenwen Wang <wang6495@umn.edu>
> >> ---
> >>  kernel/bpf/btf.c | 3 +++
> >>  1 file changed, 3 insertions(+)
> >>
> >> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> >> index 138f030..2a85f91 100644
> >> --- a/kernel/bpf/btf.c
> >> +++ b/kernel/bpf/btf.c
> >> @@ -2202,6 +2202,9 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,
> >>                 goto errout;
> >>         }
> >>
> >> +       memcpy(data, &btf->hdr,
> >> +               min_t(u32, btf->hdr.hdr_len, sizeof(btf->hdr)));
> >
> > Could you restructure the code to memcpy the header followed by copying
> > the rest of btf_data with copy_from_user? This way, each byte is only
> > copied once.
> > Could you add some comments right before memcpy so later people will know
> > why we implement this way?
>
> Thanks for the fix! Agree with Yonghong that we should rework this a bit, so
> please respin a v2 with the feedback addressed, thanks.

Hi Yonghong and Daniel,

Thanks for your suggestions! No problem, I will work on the v2 and
resubmit the patch.

Wenwen

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

end of thread, other threads:[~2018-10-24 11:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-19 22:29 [PATCH] bpf: btf: Fix a missing-check bug Wenwen Wang
2018-10-22 15:40 ` Martin Lau
2018-10-22 15:57 ` Y Song
2018-10-24  9:16   ` Daniel Borkmann
2018-10-24 11:36     ` Wenwen Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).