mbox series

[SRU,M/F,0/1] CVE-2024-26589

Message ID 20240314194617.42266-1-bethany.jamison@canonical.com
Headers show
Series CVE-2024-26589 | expand

Message

Bethany Jamison March 14, 2024, 7:46 p.m. UTC
[Impact]

 In the Linux kernel, the following vulnerability has been resolved:

 bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS

 For PTR_TO_FLOW_KEYS, check_flow_keys_access() only uses fixed off
 for validation. However, variable offset ptr alu is not prohibited
 for this ptr kind. So the variable offset is not checked.

 The following prog is accepted:

   func#0 @0
   0: R1=ctx() R10=fp0
   0: (bf) r6 = r1                       ; R1=ctx() R6_w=ctx()
   1: (79) r7 = *(u64 *)(r6 +144)        ; R6_w=ctx() R7_w=flow_keys()
   2: (b7) r8 = 1024                     ; R8_w=1024
   3: (37) r8 /= 1                       ; R8_w=scalar()
   4: (57) r8 &= 1024                    ; R8_w=scalar(smin=smin32=0,
   smax=umax=smax32=umax32=1024,var_off=(0x0; 0x400))
   5: (0f) r7 += r8
   mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
   mark_precise: frame0: regs=r8 stack= before 4: (57) r8 &= 1024
   mark_precise: frame0: regs=r8 stack= before 3: (37) r8 /= 1
   mark_precise: frame0: regs=r8 stack= before 2: (b7) r8 = 1024
   6: R7_w=flow_keys(smin=smin32=0,smax=umax=smax32=umax32=1024,var_off
   =(0x0; 0x400)) R8_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=1024,
   var_off=(0x0; 0x400))
   6: (79) r0 = *(u64 *)(r7 +0)          ; R0_w=scalar()
   7: (95) exit

 This prog loads flow_keys to r7, and adds the variable offset r8
 to r7, and finally causes out-of-bounds access:

   BUG: unable to handle page fault for address: ffffc90014c80038
   [...]
   Call Trace:
    <TASK>
    bpf_dispatcher_nop_func include/linux/bpf.h:1231 [inline]
    __bpf_prog_run include/linux/filter.h:651 [inline]
    bpf_prog_run include/linux/filter.h:658 [inline]
    bpf_prog_run_pin_on_cpu include/linux/filter.h:675 [inline]
    bpf_flow_dissect+0x15f/0x350 net/core/flow_dissector.c:991
    bpf_prog_test_run_flow_dissector+0x39d/0x620 net/bpf/test_run.c:1359
    bpf_prog_test_run kernel/bpf/syscall.c:4107 [inline]
    __sys_bpf+0xf8f/0x4560 kernel/bpf/syscall.c:5475
    __do_sys_bpf kernel/bpf/syscall.c:5561 [inline]
    __se_sys_bpf kernel/bpf/syscall.c:5559 [inline]
    __x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:5559
    do_syscall_x64 arch/x86/entry/common.c:52 [inline]
    do_syscall_64+0x3f/0x110 arch/x86/entry/common.c:83
    entry_SYSCALL_64_after_hwframe+0x63/0x6b

 Fix this by rejecting ptr alu with variable offset on flow_keys.
 Applying the patch rejects the program with "R7 pointer arithmetic
 on flow_keys prohibited".

[Fix]

Mantic: Clean cherry-pick.
Focal: Backport - Upstream moved a case statement out of the 
'switch (ptr_reg->type)' switch block to an if block right before the
switch. Functionally, it doesn't matter if that code exists before or
at the beginning of the switch block as the logic isn't affected. Focal
keeps the case statement inside the switch statement and cherry-picking
my way to merge upstream and Focal wasn't feasible. I kept Focal as is and 
added the change from the fix commit (an additional case statement inside 
the 'switch (ptr_reg->type' switch block).

[Test Case]

Compile and boot tested.

[Where problems could occur]

This will affect those who use bpf, this has some risk of 
regression because of the manual backporting that was requried.

Hao Sun (1):
  bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS

 kernel/bpf/verifier.c | 4 ++++
 1 file changed, 4 insertions(+)

Comments

Stefan Bader March 15, 2024, 9:10 a.m. UTC | #1
On 14.03.24 20:46, Bethany Jamison wrote:
> [Impact]
> 
>   In the Linux kernel, the following vulnerability has been resolved:
> 
>   bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
> 
>   For PTR_TO_FLOW_KEYS, check_flow_keys_access() only uses fixed off
>   for validation. However, variable offset ptr alu is not prohibited
>   for this ptr kind. So the variable offset is not checked.
> 
>   The following prog is accepted:
> 
>     func#0 @0
>     0: R1=ctx() R10=fp0
>     0: (bf) r6 = r1                       ; R1=ctx() R6_w=ctx()
>     1: (79) r7 = *(u64 *)(r6 +144)        ; R6_w=ctx() R7_w=flow_keys()
>     2: (b7) r8 = 1024                     ; R8_w=1024
>     3: (37) r8 /= 1                       ; R8_w=scalar()
>     4: (57) r8 &= 1024                    ; R8_w=scalar(smin=smin32=0,
>     smax=umax=smax32=umax32=1024,var_off=(0x0; 0x400))
>     5: (0f) r7 += r8
>     mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
>     mark_precise: frame0: regs=r8 stack= before 4: (57) r8 &= 1024
>     mark_precise: frame0: regs=r8 stack= before 3: (37) r8 /= 1
>     mark_precise: frame0: regs=r8 stack= before 2: (b7) r8 = 1024
>     6: R7_w=flow_keys(smin=smin32=0,smax=umax=smax32=umax32=1024,var_off
>     =(0x0; 0x400)) R8_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=1024,
>     var_off=(0x0; 0x400))
>     6: (79) r0 = *(u64 *)(r7 +0)          ; R0_w=scalar()
>     7: (95) exit
> 
>   This prog loads flow_keys to r7, and adds the variable offset r8
>   to r7, and finally causes out-of-bounds access:
> 
>     BUG: unable to handle page fault for address: ffffc90014c80038
>     [...]
>     Call Trace:
>      <TASK>
>      bpf_dispatcher_nop_func include/linux/bpf.h:1231 [inline]
>      __bpf_prog_run include/linux/filter.h:651 [inline]
>      bpf_prog_run include/linux/filter.h:658 [inline]
>      bpf_prog_run_pin_on_cpu include/linux/filter.h:675 [inline]
>      bpf_flow_dissect+0x15f/0x350 net/core/flow_dissector.c:991
>      bpf_prog_test_run_flow_dissector+0x39d/0x620 net/bpf/test_run.c:1359
>      bpf_prog_test_run kernel/bpf/syscall.c:4107 [inline]
>      __sys_bpf+0xf8f/0x4560 kernel/bpf/syscall.c:5475
>      __do_sys_bpf kernel/bpf/syscall.c:5561 [inline]
>      __se_sys_bpf kernel/bpf/syscall.c:5559 [inline]
>      __x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:5559
>      do_syscall_x64 arch/x86/entry/common.c:52 [inline]
>      do_syscall_64+0x3f/0x110 arch/x86/entry/common.c:83
>      entry_SYSCALL_64_after_hwframe+0x63/0x6b
> 
>   Fix this by rejecting ptr alu with variable offset on flow_keys.
>   Applying the patch rejects the program with "R7 pointer arithmetic
>   on flow_keys prohibited".
> 
> [Fix]
> 
> Mantic: Clean cherry-pick.
> Focal: Backport - Upstream moved a case statement out of the
> 'switch (ptr_reg->type)' switch block to an if block right before the
> switch. Functionally, it doesn't matter if that code exists before or
> at the beginning of the switch block as the logic isn't affected. Focal
> keeps the case statement inside the switch statement and cherry-picking
> my way to merge upstream and Focal wasn't feasible. I kept Focal as is and
> added the change from the fix commit (an additional case statement inside
> the 'switch (ptr_reg->type' switch block).

This does not mention Jammy which could be simply because it got already 
there via stable. But it helps a lot to mention it when submitting. 
Because affecting every kernel in a range is more normal.

> 
> [Test Case]
> 
> Compile and boot tested.
> 
> [Where problems could occur]
> 
> This will affect those who use bpf, this has some risk of
> regression because of the manual backporting that was requried.
> 
> Hao Sun (1):
>    bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
> 
>   kernel/bpf/verifier.c | 4 ++++
>   1 file changed, 4 insertions(+)
> 

Acked-by: Stefan Bader <stefan.bader@canonical.com>
Cengiz Can March 15, 2024, 10:50 a.m. UTC | #2
On 3/14/24 22:46, Bethany Jamison wrote:
> [Impact]
> 
>   In the Linux kernel, the following vulnerability has been resolved:
> 
>   bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
> 
>   For PTR_TO_FLOW_KEYS, check_flow_keys_access() only uses fixed off
>   for validation. However, variable offset ptr alu is not prohibited
>   for this ptr kind. So the variable offset is not checked.
> 
>   The following prog is accepted:
> 
>     func#0 @0
>     0: R1=ctx() R10=fp0
>     0: (bf) r6 = r1                       ; R1=ctx() R6_w=ctx()
>     1: (79) r7 = *(u64 *)(r6 +144)        ; R6_w=ctx() R7_w=flow_keys()
>     2: (b7) r8 = 1024                     ; R8_w=1024
>     3: (37) r8 /= 1                       ; R8_w=scalar()
>     4: (57) r8 &= 1024                    ; R8_w=scalar(smin=smin32=0,
>     smax=umax=smax32=umax32=1024,var_off=(0x0; 0x400))
>     5: (0f) r7 += r8
>     mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
>     mark_precise: frame0: regs=r8 stack= before 4: (57) r8 &= 1024
>     mark_precise: frame0: regs=r8 stack= before 3: (37) r8 /= 1
>     mark_precise: frame0: regs=r8 stack= before 2: (b7) r8 = 1024
>     6: R7_w=flow_keys(smin=smin32=0,smax=umax=smax32=umax32=1024,var_off
>     =(0x0; 0x400)) R8_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=1024,
>     var_off=(0x0; 0x400))
>     6: (79) r0 = *(u64 *)(r7 +0)          ; R0_w=scalar()
>     7: (95) exit
> 
>   This prog loads flow_keys to r7, and adds the variable offset r8
>   to r7, and finally causes out-of-bounds access:
> 
>     BUG: unable to handle page fault for address: ffffc90014c80038
>     [...]
>     Call Trace:
>      <TASK>
>      bpf_dispatcher_nop_func include/linux/bpf.h:1231 [inline]
>      __bpf_prog_run include/linux/filter.h:651 [inline]
>      bpf_prog_run include/linux/filter.h:658 [inline]
>      bpf_prog_run_pin_on_cpu include/linux/filter.h:675 [inline]
>      bpf_flow_dissect+0x15f/0x350 net/core/flow_dissector.c:991
>      bpf_prog_test_run_flow_dissector+0x39d/0x620 net/bpf/test_run.c:1359
>      bpf_prog_test_run kernel/bpf/syscall.c:4107 [inline]
>      __sys_bpf+0xf8f/0x4560 kernel/bpf/syscall.c:5475
>      __do_sys_bpf kernel/bpf/syscall.c:5561 [inline]
>      __se_sys_bpf kernel/bpf/syscall.c:5559 [inline]
>      __x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:5559
>      do_syscall_x64 arch/x86/entry/common.c:52 [inline]
>      do_syscall_64+0x3f/0x110 arch/x86/entry/common.c:83
>      entry_SYSCALL_64_after_hwframe+0x63/0x6b
> 
>   Fix this by rejecting ptr alu with variable offset on flow_keys.
>   Applying the patch rejects the program with "R7 pointer arithmetic
>   on flow_keys prohibited".
> 
> [Fix]
> 
> Mantic: Clean cherry-pick.
> Focal: Backport - Upstream moved a case statement out of the
> 'switch (ptr_reg->type)' switch block to an if block right before the
> switch. Functionally, it doesn't matter if that code exists before or
> at the beginning of the switch block as the logic isn't affected. Focal
> keeps the case statement inside the switch statement and cherry-picking
> my way to merge upstream and Focal wasn't feasible. I kept Focal as is and
> added the change from the fix commit (an additional case statement inside
> the 'switch (ptr_reg->type' switch block).
> 
> [Test Case]
> 
> Compile and boot tested.
> 
> [Where problems could occur]
> 
> This will affect those who use bpf, this has some risk of
> regression because of the manual backporting that was requried.
> 
> Hao Sun (1):
>    bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS

Acked-by: Cengiz Can <cengiz.can@canonical.com>

> 
>   kernel/bpf/verifier.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
Stefan Bader March 15, 2024, 1:55 p.m. UTC | #3
On 14.03.24 20:46, Bethany Jamison wrote:
> [Impact]
> 
>   In the Linux kernel, the following vulnerability has been resolved:
> 
>   bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
> 
>   For PTR_TO_FLOW_KEYS, check_flow_keys_access() only uses fixed off
>   for validation. However, variable offset ptr alu is not prohibited
>   for this ptr kind. So the variable offset is not checked.
> 
>   The following prog is accepted:
> 
>     func#0 @0
>     0: R1=ctx() R10=fp0
>     0: (bf) r6 = r1                       ; R1=ctx() R6_w=ctx()
>     1: (79) r7 = *(u64 *)(r6 +144)        ; R6_w=ctx() R7_w=flow_keys()
>     2: (b7) r8 = 1024                     ; R8_w=1024
>     3: (37) r8 /= 1                       ; R8_w=scalar()
>     4: (57) r8 &= 1024                    ; R8_w=scalar(smin=smin32=0,
>     smax=umax=smax32=umax32=1024,var_off=(0x0; 0x400))
>     5: (0f) r7 += r8
>     mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
>     mark_precise: frame0: regs=r8 stack= before 4: (57) r8 &= 1024
>     mark_precise: frame0: regs=r8 stack= before 3: (37) r8 /= 1
>     mark_precise: frame0: regs=r8 stack= before 2: (b7) r8 = 1024
>     6: R7_w=flow_keys(smin=smin32=0,smax=umax=smax32=umax32=1024,var_off
>     =(0x0; 0x400)) R8_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=1024,
>     var_off=(0x0; 0x400))
>     6: (79) r0 = *(u64 *)(r7 +0)          ; R0_w=scalar()
>     7: (95) exit
> 
>   This prog loads flow_keys to r7, and adds the variable offset r8
>   to r7, and finally causes out-of-bounds access:
> 
>     BUG: unable to handle page fault for address: ffffc90014c80038
>     [...]
>     Call Trace:
>      <TASK>
>      bpf_dispatcher_nop_func include/linux/bpf.h:1231 [inline]
>      __bpf_prog_run include/linux/filter.h:651 [inline]
>      bpf_prog_run include/linux/filter.h:658 [inline]
>      bpf_prog_run_pin_on_cpu include/linux/filter.h:675 [inline]
>      bpf_flow_dissect+0x15f/0x350 net/core/flow_dissector.c:991
>      bpf_prog_test_run_flow_dissector+0x39d/0x620 net/bpf/test_run.c:1359
>      bpf_prog_test_run kernel/bpf/syscall.c:4107 [inline]
>      __sys_bpf+0xf8f/0x4560 kernel/bpf/syscall.c:5475
>      __do_sys_bpf kernel/bpf/syscall.c:5561 [inline]
>      __se_sys_bpf kernel/bpf/syscall.c:5559 [inline]
>      __x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:5559
>      do_syscall_x64 arch/x86/entry/common.c:52 [inline]
>      do_syscall_64+0x3f/0x110 arch/x86/entry/common.c:83
>      entry_SYSCALL_64_after_hwframe+0x63/0x6b
> 
>   Fix this by rejecting ptr alu with variable offset on flow_keys.
>   Applying the patch rejects the program with "R7 pointer arithmetic
>   on flow_keys prohibited".
> 
> [Fix]
> 
> Mantic: Clean cherry-pick.
> Focal: Backport - Upstream moved a case statement out of the
> 'switch (ptr_reg->type)' switch block to an if block right before the
> switch. Functionally, it doesn't matter if that code exists before or
> at the beginning of the switch block as the logic isn't affected. Focal
> keeps the case statement inside the switch statement and cherry-picking
> my way to merge upstream and Focal wasn't feasible. I kept Focal as is and
> added the change from the fix commit (an additional case statement inside
> the 'switch (ptr_reg->type' switch block).
> 
> [Test Case]
> 
> Compile and boot tested.
> 
> [Where problems could occur]
> 
> This will affect those who use bpf, this has some risk of
> regression because of the manual backporting that was requried.
> 
> Hao Sun (1):
>    bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
> 
>   kernel/bpf/verifier.c | 4 ++++
>   1 file changed, 4 insertions(+)
> 

Applied to focal:linux/master-next. For Mantic this was already applied 
as part of "upstream stable patchset 2024-03-07". I just added the CVE 
number to the commit. Thanks.

-Stefan