Commit 7dd34d7
bpf: Fix a sdiv overflow issue
Zac Ecob reported a problem where a bpf program may cause kernel crash due
to the following error:
Oops: divide error: 0000 [#1] PREEMPT SMP KASAN PTI
The failure is due to the below signed divide:
LLONG_MIN/-1 where LLONG_MIN equals to -9,223,372,036,854,775,808.
LLONG_MIN/-1 is supposed to give a positive number 9,223,372,036,854,775,808,
but it is impossible since for 64-bit system, the maximum positive
number is 9,223,372,036,854,775,807. On x86_64, LLONG_MIN/-1 will
cause a kernel exception. On arm64, the result for LLONG_MIN/-1 is
LLONG_MIN.
Further investigation found all the following sdiv/smod cases may trigger
an exception when bpf program is running on x86_64 platform:
- LLONG_MIN/-1 for 64bit operation
- INT_MIN/-1 for 32bit operation
- LLONG_MIN%-1 for 64bit operation
- INT_MIN%-1 for 32bit operation
where -1 can be an immediate or in a register.
On arm64, there are no exceptions:
- LLONG_MIN/-1 = LLONG_MIN
- INT_MIN/-1 = INT_MIN
- LLONG_MIN%-1 = 0
- INT_MIN%-1 = 0
where -1 can be an immediate or in a register.
Insn patching is needed to handle the above cases and the patched codes
produced results aligned with above arm64 result. The below are pseudo
codes to handle sdiv/smod exceptions including both divisor -1 and divisor 0
and the divisor is stored in a register.
sdiv:
tmp = rX
tmp += 1 /* [-1, 0] -> [0, 1]
if tmp >(unsigned) 1 goto L2
if tmp == 0 goto L1
rY = 0
L1:
rY = -rY;
goto L3
L2:
rY /= rX
L3:
smod:
tmp = rX
tmp += 1 /* [-1, 0] -> [0, 1]
if tmp >(unsigned) 1 goto L1
if tmp == 1 (is64 ? goto L2 : goto L3)
rY = 0;
goto L2
L1:
rY %= rX
L2:
goto L4 // only when !is64
L3:
wY = wY // only when !is64
L4:
[1] https://lore.kernel.org/bpf/tPJLTEh7S_DxFEqAI2Ji5MBSoZVg7_G-Py2iaZpAaWtM961fFTWtsnlzwvTbzBzaUzwQAoNATXKUlt0LZOFgnDcIyKCswAnAGdUF3LBrhGQ=@protonmail.com/
Reported-by: Zac Ecob <[email protected]>
Signed-off-by: Yonghong Song <[email protected]>
Acked-by: Andrii Nakryiko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>1 parent ea02a94 commit 7dd34d7
1 file changed
+89
-4
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20499 | 20499 | | |
20500 | 20500 | | |
20501 | 20501 | | |
20502 | | - | |
| 20502 | + | |
| 20503 | + | |
| 20504 | + | |
| 20505 | + | |
| 20506 | + | |
| 20507 | + | |
| 20508 | + | |
| 20509 | + | |
| 20510 | + | |
| 20511 | + | |
| 20512 | + | |
| 20513 | + | |
| 20514 | + | |
| 20515 | + | |
| 20516 | + | |
| 20517 | + | |
| 20518 | + | |
| 20519 | + | |
| 20520 | + | |
| 20521 | + | |
| 20522 | + | |
| 20523 | + | |
| 20524 | + | |
| 20525 | + | |
| 20526 | + | |
| 20527 | + | |
| 20528 | + | |
| 20529 | + | |
| 20530 | + | |
| 20531 | + | |
| 20532 | + | |
| 20533 | + | |
20503 | 20534 | | |
20504 | 20535 | | |
20505 | 20536 | | |
20506 | 20537 | | |
20507 | 20538 | | |
20508 | 20539 | | |
| 20540 | + | |
| 20541 | + | |
20509 | 20542 | | |
20510 | 20543 | | |
20511 | 20544 | | |
| |||
20525 | 20558 | | |
20526 | 20559 | | |
20527 | 20560 | | |
| 20561 | + | |
| 20562 | + | |
| 20563 | + | |
| 20564 | + | |
| 20565 | + | |
| 20566 | + | |
| 20567 | + | |
| 20568 | + | |
| 20569 | + | |
| 20570 | + | |
| 20571 | + | |
| 20572 | + | |
| 20573 | + | |
| 20574 | + | |
| 20575 | + | |
| 20576 | + | |
| 20577 | + | |
| 20578 | + | |
| 20579 | + | |
| 20580 | + | |
| 20581 | + | |
| 20582 | + | |
| 20583 | + | |
| 20584 | + | |
| 20585 | + | |
| 20586 | + | |
| 20587 | + | |
| 20588 | + | |
| 20589 | + | |
| 20590 | + | |
| 20591 | + | |
| 20592 | + | |
| 20593 | + | |
| 20594 | + | |
| 20595 | + | |
| 20596 | + | |
| 20597 | + | |
| 20598 | + | |
| 20599 | + | |
| 20600 | + | |
| 20601 | + | |
| 20602 | + | |
| 20603 | + | |
| 20604 | + | |
20528 | 20605 | | |
20529 | | - | |
20530 | | - | |
20531 | | - | |
| 20606 | + | |
| 20607 | + | |
| 20608 | + | |
| 20609 | + | |
| 20610 | + | |
| 20611 | + | |
| 20612 | + | |
| 20613 | + | |
| 20614 | + | |
| 20615 | + | |
| 20616 | + | |
20532 | 20617 | | |
20533 | 20618 | | |
20534 | 20619 | | |
| |||
0 commit comments