Panic on txn with value > 21mill in ChannelMonitor::block_connected 2020-01-fuzz-mega-value
authorMatt Corallo <git@bluematt.me>
Sun, 19 Jan 2020 21:03:25 +0000 (16:03 -0500)
committerMatt Corallo <git@bluematt.me>
Sun, 19 Jan 2020 21:13:47 +0000 (16:13 -0500)
full_stack_target found a crash where we may overflow ruring fee
calculation if a transaction appears on-chain with massive value
available for us to claim. Since these transactions are clearly
bogus, we shouldn't allow full_stack_target to connect them, but
we also improve the error generated by explicitly panicing on them.

fuzz/src/full_stack.rs
lightning/src/ln/channelmonitor.rs

index 19dc28042636aaf3c33c3bdedee14c52848b712e..5aa6d94ed81f47d796206673e02e96a23833a636 100644 (file)
@@ -485,6 +485,12 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                } else {
                                        let txres: Result<Transaction, _> = deserialize(get_slice!(txlen));
                                        if let Ok(tx) = txres {
+                                               let mut output_val = 0;
+                                               for out in tx.output.iter() {
+                                                       if out.value > 21_000_000_0000_0000 { return; }
+                                                       output_val += out.value;
+                                                       if output_val > 21_000_000_0000_0000 { return; }
+                                               }
                                                loss_detector.connect_block(&[tx]);
                                        } else {
                                                return;
index 70f11405d0cb8399beb1c540acbe84ff20955982..c96c30cbeee448f0c8067eef0561b51b3a8b0455 100644 (file)
@@ -2334,6 +2334,15 @@ impl ChannelMonitor {
        }
 
        fn block_connected(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &Sha256dHash, broadcaster: &BroadcasterInterface, fee_estimator: &FeeEstimator)-> (Vec<(Sha256dHash, Vec<TxOut>)>, Vec<SpendableOutputDescriptor>, Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)>) {
+               for tx in txn_matched {
+                       let mut output_val = 0;
+                       for out in tx.output.iter() {
+                               if out.value > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); }
+                               output_val += out.value;
+                               if output_val > 21_000_000_0000_0000 { panic!("Value-overflowing transaction provided to block connected"); }
+                       }
+               }
+
                log_trace!(self, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len());
                let mut watch_outputs = Vec::new();
                let mut spendable_outputs = Vec::new();