lightningd: check value overflow for forward amounts - #9411
Conversation
Blinded paths encrypted_recipient_data payment_relay fee_proportional_millionths is a 32 bit unsigned integer. We convert to 64 bits before doing arithmetic operations to avoid integer overflow. **BROKEN** lightningd: FATAL SIGNAL 8 (version v26.06-197-g8c42be3-modded) **BROKEN** lightningd: backtrace: common/daemon.c:46 (send_backtrace) 0x556ac0a6be39 **BROKEN** lightningd: backtrace: common/daemon.c:83 (crashdump) 0x556ac0a6be76 **BROKEN** lightningd: backtrace: ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0 ((null)) 0x7f9c98a31def **BROKEN** lightningd: backtrace: common/onion_decode.c:61 (ceil_div) 0x556ac0a7835d **BROKEN** lightningd: backtrace: common/onion_decode.c:122 (handle_blinded_forward) 0x556ac0a784c4 **BROKEN** lightningd: backtrace: common/onion_decode.c:355 (onion_decode) 0x556ac0a78c39 **BROKEN** lightningd: backtrace: lightningd/peer_htlcs.c:1548 (peer_accepted_htlc) 0x556ac0a087fa **BROKEN** lightningd: backtrace: lightningd/peer_htlcs.c:2648 (peer_got_revoke) 0x556ac0a09e25 **BROKEN** lightningd: backtrace: lightningd/channel_control.c:1624 (channel_msg) 0x556ac09c3e11 **BROKEN** lightningd: backtrace: lightningd/subd.c:562 (sd_msg_read) 0x556ac0a16e2e **BROKEN** lightningd: backtrace: ccan/ccan/io/io.c:60 (next_plan) 0x556ac0aa8fc1 **BROKEN** lightningd: backtrace: ccan/ccan/io/io.c:422 (do_plan) 0x556ac0aa944c **BROKEN** lightningd: backtrace: ccan/ccan/io/io.c:439 (io_ready) 0x556ac0aa9505 **BROKEN** lightningd: backtrace: ccan/ccan/io/poll.c:471 (io_loop) 0x556ac0aaaea3 **BROKEN** lightningd: backtrace: lightningd/io_loop_with_timers.c:22 (io_loop_with_timers) 0x556ac09dea99 **BROKEN** lightningd: backtrace: lightningd/lightningd.c:1518 (main) 0x556ac09e43f7 **BROKEN** lightningd: backtrace: ../sysdeps/nptl/libc_start_call_main.h:58 (__libc_start_call_main) 0x7f9c98a1bca7 **BROKEN** lightningd: backtrace: ../csu/libc-start.c:360 (__libc_start_main_impl) 0x7f9c98a1bd64 **BROKEN** lightningd: backtrace: (null):0 ((null)) 0x556ac09b3120 **BROKEN** lightningd: backtrace: (null):0 ((null)) 0xffffffffffffffff Changelog-Fixed: lightningd: guard for arithmetic operation overflow on onion message request for forward a payment through a blinded path Reported-by: Vincenzo Palazzo (Bitcoin Security Council finding 2026-08-11) Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Andezion
left a comment
There was a problem hiding this comment.
Maybe handle_blinded_forward() can call amount_msat_sub_fee() directly instead of keeping a second, parallel implementation of the same formula??
| /* If these values are crap, that's OK: the HTLC will fail. */ | ||
| p->amt_to_forward = amount_msat(ceil_div((amt - enc->payment_relay->fee_base_msat) * 1000000, | ||
| 1000000 + enc->payment_relay->fee_proportional_millionths)); | ||
| (u64)1000000 + enc->payment_relay->fee_proportional_millionths)); |
There was a problem hiding this comment.
From what i see the same bug still exists in common/amount.c lines 672-673, inside amount_msat_sub_fee():
if (!amount_msat_mul_div(&out, out, 1000000,
1000000 + fee_proportional_millionths))
Maybe we should consider whether amount_msat_mul_div() should just reject div == 0 defensively (return false instead of dividing), since its a general-purpose helper and any future caller could hit the same class of bug
There was a problem hiding this comment.
Good question in general imo is why are we doing bare msat operations outside of the amount.c handlers, which iiuc were explicitly created to avoid issues with overflows?
If there's an issue existing in the amount.c handlers, we should fix that as well.
Blinded paths encrypted_recipient_data payment_relay fee_proportional_millionths is a 32 bit unsigned integer. We convert to 64 bits before doing arithmetic operations to avoid integer overflow.