Skip to content

Commit a3efa2c

Browse files
committed
[FAB-2997] don't invoke some scc thru proposals
This is the first of three fixes required for FAB-2997 (described in the discussion for that jira item). In this change set we prevent security-sensitive system chaincodes (such as escc or vscc) from being invoked from the outside through proposals sent to the peer. A flag has been added to the system chaincode struct to keep track of whether a system chaincode can be invoked this way or not. A second flag was added to keep track of whether the system chaincode can be invoked using a cc2cc invocation. This flag will be used in the second change set related to this jira item. Change-Id: Iaf05217fcf7247f61fddb4a16afb0908c9735efc Signed-off-by: Alessandro Sorniotti <[email protected]>
1 parent 7f336b9 commit a3efa2c

File tree

4 files changed

+65
-15
lines changed

4 files changed

+65
-15
lines changed

core/endorser/endorser.go

+8
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,14 @@ func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedPro
313313
return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err
314314
}
315315

316+
// block invocations to security-sensitive system chaincodes
317+
if syscc.IsSysCCAndNotInvokable(hdrExt.ChaincodeId.Name) {
318+
endorserLogger.Errorf("ProcessProposal error: an attempt was made by %#v to invoke system chaincode %s",
319+
shdr.Creator, hdrExt.ChaincodeId.Name)
320+
err = fmt.Errorf("Chaincode %s cannot be invoked through a proposal", hdrExt.ChaincodeId.Name)
321+
return &pb.ProposalResponse{Response: &pb.Response{Status: 500, Message: err.Error()}}, err
322+
}
323+
316324
chainID := chdr.ChannelId
317325

318326
// Check for uniqueness of prop.TxID with ledger

core/endorser/endorser_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,21 @@ func TestAdminACLFail(t *testing.T) {
623623
chaincode.GetChain().Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: chaincodeID}})
624624
}
625625

626+
// TestInvokeSccFail makes sure that invoking a system chaincode fails
627+
func TestInvokeSccFail(t *testing.T) {
628+
chainID := util.GetTestChainID()
629+
630+
chaincodeID := &pb.ChaincodeID{Name: "escc"}
631+
args := util.ToChaincodeArgs("someFunc", "someArg")
632+
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: chaincodeID, Input: &pb.ChaincodeInput{Args: args}}
633+
_, _, _, _, err := invoke(chainID, spec)
634+
if err == nil {
635+
t.Logf("Invoking escc should have failed!")
636+
t.Fail()
637+
return
638+
}
639+
}
640+
626641
func newTempDir() string {
627642
tempDir, err := ioutil.TempDir("", "fabric-")
628643
if err != nil {

core/scc/importsysccs.go

+31-15
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,20 @@ import (
2828
//see systemchaincode_test.go for an example using "sample_syscc"
2929
var systemChaincodes = []*SystemChaincode{
3030
{
31-
Enabled: true,
32-
Name: "cscc",
33-
Path: "github.com/hyperledger/fabric/core/scc/cscc",
34-
InitArgs: [][]byte{[]byte("")},
35-
Chaincode: &cscc.PeerConfiger{},
31+
Enabled: true,
32+
Name: "cscc",
33+
Path: "github.com/hyperledger/fabric/core/scc/cscc",
34+
InitArgs: [][]byte{[]byte("")},
35+
Chaincode: &cscc.PeerConfiger{},
36+
InvokableExternal: true, // cscc is invoked to join a channel
3637
},
3738
{
38-
Enabled: true,
39-
Name: "lscc",
40-
Path: "github.com/hyperledger/fabric/core/scc/lscc",
41-
InitArgs: [][]byte{[]byte("")},
42-
Chaincode: &lscc.LifeCycleSysCC{},
39+
Enabled: true,
40+
Name: "lscc",
41+
Path: "github.com/hyperledger/fabric/core/scc/lscc",
42+
InitArgs: [][]byte{[]byte("")},
43+
Chaincode: &lscc.LifeCycleSysCC{},
44+
InvokableExternal: true, // lccc is invoked to deploy new chaincodes
4345
},
4446
{
4547
Enabled: true,
@@ -56,11 +58,13 @@ var systemChaincodes = []*SystemChaincode{
5658
Chaincode: &vscc.ValidatorOneValidSignature{},
5759
},
5860
{
59-
Enabled: true,
60-
Name: "qscc",
61-
Path: "github.com/hyperledger/fabric/core/chaincode/qscc",
62-
InitArgs: [][]byte{[]byte("")},
63-
Chaincode: &qscc.LedgerQuerier{},
61+
Enabled: true,
62+
Name: "qscc",
63+
Path: "github.com/hyperledger/fabric/core/chaincode/qscc",
64+
InitArgs: [][]byte{[]byte("")},
65+
Chaincode: &qscc.LedgerQuerier{},
66+
InvokableExternal: true, // qscc can be invoked to retrieve blocks
67+
InvokableCC2CC: true, // qscc can be invoked to retrieve blocks also by a cc
6468
},
6569
}
6670

@@ -100,6 +104,18 @@ func IsSysCC(name string) bool {
100104
return false
101105
}
102106

107+
// IsSysCCAndNotInvokable returns true if the chaincode
108+
// is a system chaincode and *CANNOT* be invoked through
109+
// a proposal to this peer
110+
func IsSysCCAndNotInvokable(name string) bool {
111+
for _, sysCC := range systemChaincodes {
112+
if sysCC.Name == name {
113+
return !sysCC.InvokableExternal
114+
}
115+
}
116+
return false
117+
}
118+
103119
// MockRegisterSysCCs is used only for testing
104120
// This is needed to break import cycle
105121
func MockRegisterSysCCs(mockSysCCs []*SystemChaincode) []*SystemChaincode {

core/scc/sysccapi.go

+11
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ type SystemChaincode struct {
5454

5555
// Chaincode is the actual chaincode object
5656
Chaincode shim.Chaincode
57+
58+
// InvokableExternal keeps track of whether
59+
// this system chaincode can be invoked
60+
// through a proposal sent to this peer
61+
InvokableExternal bool
62+
63+
// InvokableCC2CC keeps track of whether
64+
// this system chaincode can be invoked
65+
// by way of a chaincode-to-chaincode
66+
// invocation
67+
InvokableCC2CC bool
5768
}
5869

5970
// RegisterSysCC registers the given system chaincode with the peer

0 commit comments

Comments
 (0)