Skip to content

Commit d7233d5

Browse files
committed
[FAB-3450] Prevent panic on msg signing
Currently, the gossip code panics if it's unable to sign a message or to marshal it bytes, because the assumption was that if the signing failed then something is terrible wrong with the peer and it's not recoverable If turning a message into bytes fails, it's because of something not recoverable too. However, a user posted a stack trace in which gossip tried constructing a message that its envelope has a payload of 2GB. Now, the cause for a creation of such a message was fixed but in theory we may somehow have a situation where a large message is constructed. In order to prevent these kind of problems, and the crash of the peer, we need to make the Signer return an error instead of panicking. Change-Id: Ife8f4e137c92c167dadc7bbe1bcdf45f93b2b38e Signed-off-by: Yacov Manevich <[email protected]>
1 parent 5edd65d commit d7233d5

19 files changed

+309
-167
lines changed

gossip/comm/comm_impl.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,10 @@ func (c *commImpl) authenticateRemotePeer(stream stream) (*proto.ConnectionInfo,
433433
return nil, errors.New("No TLS certificate")
434434
}
435435

436-
cMsg = c.createConnectionMsg(c.PKIID, c.selfCertHash, c.peerIdentity, signer)
436+
cMsg, err = c.createConnectionMsg(c.PKIID, c.selfCertHash, c.peerIdentity, signer)
437+
if err != nil {
438+
return nil, err
439+
}
437440

438441
c.logger.Debug("Sending", cMsg, "to", remoteAddress)
439442
stream.Send(cMsg.Envelope)
@@ -580,7 +583,7 @@ func readWithTimeout(stream interface{}, timeout time.Duration, address string)
580583
}
581584
}
582585

583-
func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, certHash []byte, cert api.PeerIdentityType, signer proto.Signer) *proto.SignedGossipMessage {
586+
func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, certHash []byte, cert api.PeerIdentityType, signer proto.Signer) (*proto.SignedGossipMessage, error) {
584587
m := &proto.GossipMessage{
585588
Tag: proto.GossipMessage_EMPTY,
586589
Nonce: 0,
@@ -595,8 +598,8 @@ func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, certHash []byte,
595598
sMsg := &proto.SignedGossipMessage{
596599
GossipMessage: m,
597600
}
598-
sMsg.Sign(signer)
599-
return sMsg
601+
_, err := sMsg.Sign(signer)
602+
return sMsg, err
600603
}
601604

602605
type stream interface {

gossip/comm/comm_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func handshaker(endpoint string, comm Comm, t *testing.T, connMutator msgMutator
156156

157157
pkiID := common.PKIidType(endpoint)
158158
assert.NoError(t, err, "%v", err)
159-
msg := c.createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) {
159+
msg, _ := c.createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) {
160160
mac := hmac.New(sha256.New, hmacKey)
161161
mac.Write(msg)
162162
return mac.Sum(nil), nil
@@ -423,7 +423,7 @@ func TestCloseConn(t *testing.T) {
423423
assert.NoError(t, err, "%v", err)
424424
c := &commImpl{}
425425
tlsCertHash := certHashFromRawCert(tlsCfg.Certificates[0].Certificate[0])
426-
connMsg := c.createConnectionMsg(common.PKIidType("pkiID"), tlsCertHash, api.PeerIdentityType("pkiID"), func(msg []byte) ([]byte, error) {
426+
connMsg, _ := c.createConnectionMsg(common.PKIidType("pkiID"), tlsCertHash, api.PeerIdentityType("pkiID"), func(msg []byte) ([]byte, error) {
427427
mac := hmac.New(sha256.New, hmacKey)
428428
mac.Write(msg)
429429
return mac.Sum(nil), nil
@@ -711,13 +711,14 @@ func TestPresumedDead(t *testing.T) {
711711
}
712712

713713
func createGossipMsg() *proto.SignedGossipMessage {
714-
return (&proto.GossipMessage{
714+
msg, _ := (&proto.GossipMessage{
715715
Tag: proto.GossipMessage_EMPTY,
716716
Nonce: uint64(rand.Int()),
717717
Content: &proto.GossipMessage_DataMsg{
718718
DataMsg: &proto.DataMessage{},
719719
},
720720
}).NoopSign()
721+
return msg
721722
}
722723

723724
func remotePeer(port int) *RemotePeer {

gossip/comm/mock/mock_comm.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ func NewCommMock(id string, members map[string]*socketMock) comm.Comm {
8585

8686
// Respond sends a GossipMessage to the origin from which this ReceivedMessage was sent from
8787
func (packet *packetMock) Respond(msg *proto.GossipMessage) {
88+
sMsg, _ := msg.NoopSign()
8889
packet.src.socket <- &packetMock{
8990
src: packet.dst,
9091
dst: packet.src,
91-
msg: msg.NoopSign(),
92+
msg: sMsg,
9293
}
9394
}
9495

gossip/comm/mock/mock_comm_test.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,13 @@ func TestMockComm(t *testing.T) {
4444
comm2 := NewCommMock(second.endpoint, members)
4545
defer comm2.Stop()
4646

47-
comm2.Send((&proto.GossipMessage{
47+
sMsg, _ := (&proto.GossipMessage{
4848
Content: &proto.GossipMessage_StateRequest{&proto.RemoteStateRequest{
4949
StartSeqNum: 1,
5050
EndSeqNum: 3,
5151
}},
52-
}).NoopSign(), &comm.RemotePeer{"first", common.PKIidType("first")})
52+
}).NoopSign()
53+
comm2.Send(sMsg, &comm.RemotePeer{"first", common.PKIidType("first")})
5354

5455
msg := <-msgCh
5556

@@ -73,15 +74,16 @@ func TestMockComm_PingPong(t *testing.T) {
7374
rcvChA := peerA.Accept(all)
7475
rcvChB := peerB.Accept(all)
7576

76-
peerA.Send((&proto.GossipMessage{
77+
sMsg, _ := (&proto.GossipMessage{
7778
Content: &proto.GossipMessage_DataMsg{
7879
&proto.DataMessage{
7980
&proto.Payload{
8081
SeqNum: 1,
8182
Data: []byte("Ping"),
8283
},
8384
}},
84-
}).NoopSign(), &comm.RemotePeer{"peerB", common.PKIidType("peerB")})
85+
}).NoopSign()
86+
peerA.Send(sMsg, &comm.RemotePeer{"peerB", common.PKIidType("peerB")})
8587

8688
msg := <-rcvChB
8789
dataMsg := msg.GetGossipMessage().GetDataMsg()

gossip/comm/msg.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@ func (m *ReceivedMessageImpl) GetSourceEnvelope() *proto.Envelope {
3838

3939
// Respond sends a msg to the source that sent the ReceivedMessageImpl
4040
func (m *ReceivedMessageImpl) Respond(msg *proto.GossipMessage) {
41-
m.conn.send(msg.NoopSign(), func(e error) {})
41+
sMsg, err := msg.NoopSign()
42+
if err != nil {
43+
m.conn.logger.Error("Failed creating SignedGossipMessage:", err)
44+
return
45+
}
46+
m.conn.send(sMsg, func(e error) {})
4247
}
4348

4449
// GetGossipMessage returns the inner GossipMessage

gossip/discovery/discovery_impl.go

+47-21
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,17 @@ func (d *gossipDiscoveryImpl) Connect(member NetworkMember, id identifier) {
172172
Endpoint: member.Endpoint,
173173
PKIid: id.ID,
174174
}
175-
req := d.createMembershipRequest(id.SelfOrg).NoopSign()
175+
req, err := d.createMembershipRequest(id.SelfOrg).NoopSign()
176+
if err != nil {
177+
d.logger.Warning("Failed creating SignedGossipMessage:", err)
178+
continue
179+
}
176180
req.Nonce = util.RandomUInt64()
177-
req.NoopSign()
181+
req, err = req.NoopSign()
182+
if err != nil {
183+
d.logger.Warning("Failed adding NONCE to SignedGossipMessage", err)
184+
continue
185+
}
178186
go d.sendUntilAcked(peer, req)
179187
return
180188
}
@@ -221,19 +229,16 @@ func (d *gossipDiscoveryImpl) sendUntilAcked(peer *NetworkMember, message *proto
221229
}
222230
}
223231

224-
func (d *gossipDiscoveryImpl) somePeerIsKnown() bool {
225-
d.lock.RLock()
226-
defer d.lock.RUnlock()
227-
return len(d.aliveLastTS) != 0
228-
}
229-
230232
func (d *gossipDiscoveryImpl) InitiateSync(peerNum int) {
231233
if d.toDie() {
232234
return
233235
}
234236
var peers2SendTo []*NetworkMember
235-
memReq := d.createMembershipRequest(true).NoopSign()
236-
237+
memReq, err := d.createMembershipRequest(true).NoopSign()
238+
if err != nil {
239+
d.logger.Warning("Failed creating SignedGossipMessage:", err)
240+
return
241+
}
237242
d.lock.RLock()
238243

239244
n := d.aliveMembership.Size()
@@ -404,7 +409,11 @@ func (d *gossipDiscoveryImpl) sendMemResponse(targetMember *proto.Member, intern
404409
InternalEndpoint: internalEndpoint,
405410
}
406411

407-
memResp := d.createMembershipResponse(targetPeer)
412+
aliveMsg := d.createAliveMessage(true)
413+
if aliveMsg == nil {
414+
return
415+
}
416+
memResp := d.createMembershipResponse(aliveMsg, targetPeer)
408417
if memResp == nil {
409418
errMsg := `Got a membership request from a peer that shouldn't have sent one: %v, closing connection to the peer as a result.`
410419
d.logger.Warningf(errMsg, targetMember)
@@ -414,18 +423,22 @@ func (d *gossipDiscoveryImpl) sendMemResponse(targetMember *proto.Member, intern
414423

415424
defer d.logger.Debug("Exiting, replying with", memResp)
416425

417-
d.comm.SendToPeer(targetPeer, (&proto.GossipMessage{
426+
msg, err := (&proto.GossipMessage{
418427
Tag: proto.GossipMessage_EMPTY,
419428
Nonce: nonce,
420429
Content: &proto.GossipMessage_MemRes{
421430
MemRes: memResp,
422431
},
423-
}).NoopSign())
432+
}).NoopSign()
433+
if err != nil {
434+
d.logger.Warning("Failed creating SignedGossipMessage:", err)
435+
return
436+
}
437+
d.comm.SendToPeer(targetPeer, msg)
424438
}
425439

426-
func (d *gossipDiscoveryImpl) createMembershipResponse(targetMember *NetworkMember) *proto.MembershipResponse {
440+
func (d *gossipDiscoveryImpl) createMembershipResponse(aliveMsg *proto.SignedGossipMessage, targetMember *NetworkMember) *proto.MembershipResponse {
427441
shouldBeDisclosed, omitConcealedFields := d.disclosurePolicy(targetMember)
428-
aliveMsg := d.createAliveMessage(true)
429442

430443
if !shouldBeDisclosed(aliveMsg) {
431444
return nil
@@ -594,24 +607,29 @@ func (d *gossipDiscoveryImpl) periodicalReconnectToDead() {
594607
}
595608

596609
func (d *gossipDiscoveryImpl) sendMembershipRequest(member *NetworkMember, includeInternalEndpoint bool) {
597-
d.comm.SendToPeer(member, d.createMembershipRequest(includeInternalEndpoint))
610+
req, err := d.createMembershipRequest(includeInternalEndpoint).NoopSign()
611+
if err != nil {
612+
d.logger.Error("Failed creating SignedGossipMessage:", err)
613+
return
614+
}
615+
d.comm.SendToPeer(member, req)
598616
}
599617

600-
func (d *gossipDiscoveryImpl) createMembershipRequest(includeInternalEndpoint bool) *proto.SignedGossipMessage {
618+
func (d *gossipDiscoveryImpl) createMembershipRequest(includeInternalEndpoint bool) *proto.GossipMessage {
601619
req := &proto.MembershipRequest{
602620
SelfInformation: d.createAliveMessage(includeInternalEndpoint).Envelope,
603621
// TODO: sending the known peers is not secure because the remote peer might shouldn't know
604622
// TODO: about the known peers. I'm deprecating this until a secure mechanism will be implemented.
605623
// TODO: See FAB-2570 for tracking this issue.
606624
Known: [][]byte{},
607625
}
608-
return (&proto.GossipMessage{
626+
return &proto.GossipMessage{
609627
Tag: proto.GossipMessage_EMPTY,
610628
Nonce: uint64(0),
611629
Content: &proto.GossipMessage_MemReq{
612630
MemReq: req,
613631
},
614-
}).NoopSign()
632+
}
615633
}
616634

617635
func (d *gossipDiscoveryImpl) copyLastSeen(lastSeenMap map[string]*timestamp) []NetworkMember {
@@ -693,7 +711,11 @@ func (d *gossipDiscoveryImpl) periodicalSendAlive() {
693711
for !d.toDie() {
694712
d.logger.Debug("Sleeping", getAliveTimeInterval())
695713
time.Sleep(getAliveTimeInterval())
696-
d.comm.Gossip(d.createAliveMessage(true))
714+
msg := d.createAliveMessage(true)
715+
if msg == nil {
716+
return
717+
}
718+
d.comm.Gossip(msg)
697719
}
698720
}
699721

@@ -726,9 +748,13 @@ func (d *gossipDiscoveryImpl) createAliveMessage(includeInternalEndpoint bool) *
726748
},
727749
}
728750

751+
envp := d.crypt.SignMessage(msg2Gossip, internalEndpoint)
752+
if envp == nil {
753+
return nil
754+
}
729755
signedMsg := &proto.SignedGossipMessage{
730756
GossipMessage: msg2Gossip,
731-
Envelope: d.crypt.SignMessage(msg2Gossip, internalEndpoint),
757+
Envelope: envp,
732758
}
733759

734760
if !includeInternalEndpoint {

0 commit comments

Comments
 (0)