Skip to content

Commit 1c3cc3e

Browse files
author
Jason Yellick
committed
[FAB-4479] Fix theoretical orderer crashes
Although the orderer makes every effort to validate all user provided data, especially when processing configuration updates, there is a very large attack surface where a specially crafted message might be able to trigger a programming error like a nil pointer derference, crashing the orderer. Because the client threads for Broadcast and Deliver never have any direct affect on world state (ie writing to the ledger, or updating configuration), they may safely panic at any point without worry of corrupting the orderer state. Since these threads may panic without adversely affecting the orderer, these panics should be recovered and logged, instead of being allowed to crash the whole ordering process. This CR adds a recover to the top level Broadcast/Deliver functions which logs the stack trace at a Critical level, before closing the connection. Change-Id: I0ece5b4749648dd9a478ba814c081049bde55c6d Signed-off-by: Jason Yellick <[email protected]>
1 parent 85ef083 commit 1c3cc3e

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

orderer/server.go

+14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"github.com/hyperledger/fabric/orderer/configupdate"
2424
"github.com/hyperledger/fabric/orderer/multichain"
2525
ab "github.com/hyperledger/fabric/protos/orderer"
26+
27+
"runtime/debug"
2628
)
2729

2830
type configUpdateSupport struct {
@@ -70,11 +72,23 @@ func NewServer(ml multichain.Manager, signer crypto.LocalSigner) ab.AtomicBroadc
7072
// Broadcast receives a stream of messages from a client for ordering
7173
func (s *server) Broadcast(srv ab.AtomicBroadcast_BroadcastServer) error {
7274
logger.Debugf("Starting new Broadcast handler")
75+
defer func() {
76+
if r := recover(); r != nil {
77+
logger.Criticalf("Broadcast client triggered panic: %s\n%s", r, debug.Stack())
78+
}
79+
logger.Debugf("Closing Broadcast stream")
80+
}()
7381
return s.bh.Handle(srv)
7482
}
7583

7684
// Deliver sends a stream of blocks to a client after ordering
7785
func (s *server) Deliver(srv ab.AtomicBroadcast_DeliverServer) error {
7886
logger.Debugf("Starting new Deliver handler")
87+
defer func() {
88+
if r := recover(); r != nil {
89+
logger.Criticalf("Deliver client triggered panic: %s\n%s", r, debug.Stack())
90+
}
91+
logger.Debugf("Closing Deliver stream")
92+
}()
7993
return s.dh.Handle(srv)
8094
}

orderer/server_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"testing"
21+
)
22+
23+
func TestBroadcastNoPanic(t *testing.T) {
24+
// Defer recovers from the panic
25+
_ = (&server{}).Broadcast(nil)
26+
}
27+
28+
func TestDeliverNoPanic(t *testing.T) {
29+
// Defer recovers from the panic
30+
_ = (&server{}).Deliver(nil)
31+
}

0 commit comments

Comments
 (0)