From 1b1e24ce053a7548e9997b3c9725811ff83e7fb2 Mon Sep 17 00:00:00 2001 From: Alessandro Sorniotti Date: Thu, 1 Jun 2017 17:43:42 +0200 Subject: [PATCH] [FAB-3892] check correctness of policy on cc2cc The purpose of this change set is that for each cc2cc invocation, we check that the instantiated chaincode matches the installed one (if any) in terms of its instantiation policy, just to avoid repercussions from any rogue instantiation of a chaincode. Change-Id: I67368d1ef918edd6f6b92bf2cf4b99ea8eeb4e4b Signed-off-by: Alessandro Sorniotti --- core/chaincode/handler.go | 6 +++++ core/common/ccprovider/ccprovider.go | 33 ++++++++++++++++++++++++++++ core/endorser/endorser.go | 27 ++--------------------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/core/chaincode/handler.go b/core/chaincode/handler.go index 74d21abc773..4338786ba08 100644 --- a/core/chaincode/handler.go +++ b/core/chaincode/handler.go @@ -1262,6 +1262,12 @@ func (handler *Handler) enterBusyState(e *fsm.Event, state string) { errHandler([]byte(err.Error()), "[%s]Failed to get chaincoed data (%s) for invoked chaincode. Sending %s", shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR) return } + + err = ccprovider.CheckInsantiationPolicy(calledCcIns.ChaincodeName, cd.Version, cd) + if err != nil { + errHandler([]byte(err.Error()), "[%s]CheckInsantiationPolicy, error %s. Sending %s", shorttxid(msg.Txid), err, pb.ChaincodeMessage_ERROR) + return + } } else { //this is a system cc, just call it directly cd = &ccprovider.ChaincodeData{Name: calledCcIns.ChaincodeName, Version: util.GetSysCCVersion()} diff --git a/core/common/ccprovider/ccprovider.go b/core/common/ccprovider/ccprovider.go index f18aa80e866..1155bd263dd 100644 --- a/core/common/ccprovider/ccprovider.go +++ b/core/common/ccprovider/ccprovider.go @@ -26,6 +26,8 @@ import ( "github.com/golang/protobuf/proto" + "bytes" + "github.com/hyperledger/fabric/common/flogging" "github.com/hyperledger/fabric/core/ledger" pb "github.com/hyperledger/fabric/protos/peer" @@ -217,6 +219,37 @@ func PutChaincodeIntoFS(depSpec *pb.ChaincodeDeploymentSpec) error { } } +func CheckInsantiationPolicy(name, version string, cdLedger *ChaincodeData) error { + // we retrieve info about this chaincode from the file system + ccpack, err := GetChaincodeFromFS(name, version) + if err != nil { + return fmt.Errorf("Chaincode data for cc %s/%s was not found, error %s", name, version, err) + } + + // ccpack is guaranteed to be non-nil + cdLocalFS := ccpack.GetChaincodeData() + + // we have the info from the fs, check that the policy + // matches the one on the file system if one was specified; + // this check is required because the admin of this peer + // might have specified instantiation policies for their + // chaincode, for example to make sure that the chaincode + // is only instantiated on certain channels; a malicious + // peer on the other hand might have created a deploy + // transaction that attempts to bypass the instantiation + // policy. This check is there to ensure that this will not + // happen, i.e. that the peer will refuse to invoke the + // chaincode under these conditions. More info on + // https://jira.hyperledger.org/browse/FAB-3156 + if cdLocalFS.InstantiationPolicy != nil { + if !bytes.Equal(cdLocalFS.InstantiationPolicy, cdLedger.InstantiationPolicy) { + return fmt.Errorf("Instantiation policy mismatch for cc %s/%s", name, version) + } + } + + return nil +} + // GetCCPackage tries each known package implementation one by one // till the right package is found func GetCCPackage(buf []byte) (CCPackage, error) { diff --git a/core/endorser/endorser.go b/core/endorser/endorser.go index b4ae6a16d73..2f779002e6c 100644 --- a/core/endorser/endorser.go +++ b/core/endorser/endorser.go @@ -15,8 +15,6 @@ import ( "errors" - "bytes" - "github.com/hyperledger/fabric/common/policies" "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/core/chaincode" @@ -234,30 +232,9 @@ func (e *Endorser) simulateProposal(ctx context.Context, chainID string, txid st } version = cdLedger.Version - // we retrieve info about this chaincode from the file system - ccpack, err := ccprovider.GetChaincodeFromFS(cid.Name, version) + err = ccprovider.CheckInsantiationPolicy(cid.Name, version, cdLedger) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("chaincode %s/%s not found on the file system, error %s", cid.Name, version, err) - } - // ccpack is guaranteed to be non-nil - cdLocalFS := ccpack.GetChaincodeData() - - // we have the info from the fs, check that the policy - // matches the one on the file system if one was specified; - // this check is required because the admin of this peer - // might have specified instantiation policies for their - // chaincode, for example to make sure that the chaincode - // is only instantiated on certain channels; a malicious - // peer on the other hand might have created a deploy - // transaction that attempts to bypass the instantiation - // policy. This check is there to ensure that this will not - // happen, i.e. that the peer will refuse to invoke the - // chaincode under these conditions. More info on - // https://jira.hyperledger.org/browse/FAB-3156 - if cdLocalFS.InstantiationPolicy != nil { - if !bytes.Equal(cdLocalFS.InstantiationPolicy, cdLedger.InstantiationPolicy) { - return nil, nil, nil, nil, fmt.Errorf("instantiation policy mismatch for cc %s/%s", cid.Name, version) - } + return nil, nil, nil, nil, err } } else { version = util.GetSysCCVersion()