Files
linux/include/linux
Eduard Zingerman 4bf79f9be4 bpf: Track equal scalars history on per-instruction level
Use bpf_verifier_state->jmp_history to track which registers were
updated by find_equal_scalars() (renamed to collect_linked_regs())
when conditional jump was verified. Use recorded information in
backtrack_insn() to propagate precision.

E.g. for the following program:

            while verifying instructions
  1: r1 = r0              |
  2: if r1 < 8  goto ...  | push r0,r1 as linked registers in jmp_history
  3: if r0 > 16 goto ...  | push r0,r1 as linked registers in jmp_history
  4: r2 = r10             |
  5: r2 += r0             v mark_chain_precision(r0)

            while doing mark_chain_precision(r0)
  5: r2 += r0             | mark r0 precise
  4: r2 = r10             |
  3: if r0 > 16 goto ...  | mark r0,r1 as precise
  2: if r1 < 8  goto ...  | mark r0,r1 as precise
  1: r1 = r0              v

Technically, do this as follows:
- Use 10 bits to identify each register that gains range because of
  sync_linked_regs():
  - 3 bits for frame number;
  - 6 bits for register or stack slot number;
  - 1 bit to indicate if register is spilled.
- Use u64 as a vector of 6 such records + 4 bits for vector length.
- Augment struct bpf_jmp_history_entry with a field 'linked_regs'
  representing such vector.
- When doing check_cond_jmp_op() remember up to 6 registers that
  gain range because of sync_linked_regs() in such a vector.
- Don't propagate range information and reset IDs for registers that
  don't fit in 6-value vector.
- Push a pair {instruction index, linked registers vector}
  to bpf_verifier_state->jmp_history.
- When doing backtrack_insn() check if any of recorded linked
  registers is currently marked precise, if so mark all linked
  registers as precise.

This also requires fixes for two test_verifier tests:
- precise: test 1
- precise: test 2

Both tests contain the following instruction sequence:

19: (bf) r2 = r9                      ; R2=scalar(id=3) R9=scalar(id=3)
20: (a5) if r2 < 0x8 goto pc+1        ; R2=scalar(id=3,umin=8)
21: (95) exit
22: (07) r2 += 1                      ; R2_w=scalar(id=3+1,...)
23: (bf) r1 = r10                     ; R1_w=fp0 R10=fp0
24: (07) r1 += -8                     ; R1_w=fp-8
25: (b7) r3 = 0                       ; R3_w=0
26: (85) call bpf_probe_read_kernel#113

The call to bpf_probe_read_kernel() at (26) forces r2 to be precise.
Previously, this forced all registers with same id to become precise
immediately when mark_chain_precision() is called.
After this change, the precision is propagated to registers sharing
same id only when 'if' instruction is backtracked.
Hence verification log for both tests is changed:
regs=r2,r9 -> regs=r2 for instructions 25..20.

Fixes: 904e6ddf41 ("bpf: Use scalar ids in mark_chain_precision()")
Reported-by: Hao Sun <sunhao.th@gmail.com>
Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20240718202357.1746514-2-eddyz87@gmail.com

Closes: https://lore.kernel.org/bpf/CAEf4BzZ0xidVCqB47XnkXcNhkPWF6_nTV7yt+_Lf0kcFEut2Mg@mail.gmail.com/
2024-07-29 12:53:10 -07:00
..
2024-03-19 16:11:42 +01:00
2024-01-18 15:21:00 -08:00
2024-05-27 13:39:51 +02:00
2024-04-24 11:06:26 -07:00
2024-04-25 20:55:49 -07:00
2023-12-20 19:26:32 -05:00
2024-05-02 20:35:57 +02:00
2024-03-11 15:37:23 -07:00
2024-04-29 16:28:07 -07:00
2024-07-03 19:29:59 -07:00
2024-07-08 01:51:05 -06:00
2023-12-15 16:25:55 -08:00
2024-06-24 18:29:20 +02:00
2024-04-23 09:03:37 +09:00
2024-06-11 12:57:49 -05:00
2024-02-20 14:22:55 -05:00
2024-02-20 14:22:51 -05:00
2024-03-12 23:08:29 -07:00
2024-05-27 11:08:31 +02:00
2024-04-15 16:03:24 -04:00
2024-06-28 10:36:45 +02:00
2024-05-19 14:36:17 -07:00
2024-07-03 19:29:52 -07:00
2024-05-27 16:50:03 +02:00
2024-02-28 19:36:39 -08:00
2024-02-14 11:14:40 +01:00
2023-12-20 19:26:31 -05:00
2023-12-20 19:26:31 -05:00
2024-06-24 22:24:56 -07:00
2024-07-03 19:30:23 -07:00
2024-02-17 16:20:41 +01:00
2024-06-05 19:19:26 -07:00
2023-12-20 19:26:30 -05:00
2024-05-03 10:44:42 +01:00
2024-07-10 12:14:54 -07:00
2024-07-10 12:14:54 -07:00
2024-07-08 13:47:27 -04:00
2024-06-24 22:25:02 -07:00
2024-03-26 11:07:20 -07:00
2024-06-28 09:52:05 +02:00
2023-12-20 19:26:31 -05:00
2024-03-13 12:53:53 -07:00
2024-03-13 12:53:53 -07:00
2023-12-20 19:26:31 -05:00
2023-12-20 19:26:31 -05:00
2023-12-20 19:26:30 -05:00
2024-07-10 17:52:47 +02:00
2023-12-20 19:26:32 -05:00
2024-04-02 18:03:32 -07:00
2023-12-27 11:49:56 -05:00
2023-12-20 19:26:31 -05:00
2024-03-08 12:05:10 +01:00
2024-04-03 09:59:38 +01:00
2023-12-20 19:26:32 -05:00
2023-12-20 19:26:32 -05:00
2023-12-20 19:26:32 -05:00
2024-02-15 12:17:28 -05:00
2024-04-09 10:53:44 +02:00
2024-07-02 18:59:33 -07:00
2024-05-04 18:57:21 +02:00
2024-07-10 07:59:03 +02:00
2024-04-08 11:49:02 +01:00
2023-12-20 19:26:31 -05:00
2023-12-08 12:02:37 +01:00
2024-05-06 12:05:00 +02:00
2023-12-20 19:26:30 -05:00
2024-04-07 02:42:36 -04:00
2024-07-04 11:00:31 -04:00
2024-06-24 18:16:44 +01:00
2024-02-09 12:07:48 +00:00
2024-04-25 20:55:48 -07:00