Skip to content

Commit 4c5192f

Browse files
Add crash test for unmarshal_values
- adding a test case that tries submids a malicous key that might cause a null pointer dereferencing in `get_public_state_by_partial_composite_key`, which may crash the enclave Signed-off-by: Marcus Brandenburger <bur@zurich.ibm.com>
1 parent af091b7 commit 4c5192f

File tree

8 files changed

+206
-1
lines changed

8 files changed

+206
-1
lines changed

integration/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ include $(TOP)/build.mk
77

88
all: test
99

10-
test: auction_test echo_test kv_test deployment_test client_sdk_test stress_test ecc_go_test
10+
test: auction_test echo_test kv_test deployment_test client_sdk_test stress_test ecc_go_test crash_test
1111

1212
auction_test:
1313
./auction_test.sh
@@ -29,3 +29,6 @@ stress_test:
2929

3030
ecc_go_test:
3131
$(MAKE) -C go_chaincode
32+
33+
crash_test:
34+
$(MAKE) -C crashtest

integration/crashtest/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
_build/
2+
wallet/
3+
keystore/

integration/crashtest/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
TOP = ../..
4+
include $(TOP)/build.mk
5+
6+
GO_TEST_DIRS=unmarshal_values
7+
8+
test:
9+
$(foreach DIR, $(GO_TEST_DIRS), $(MAKE) -C $(DIR) || exit ;)
10+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required(VERSION 3.5.1)
2+
3+
set(SOURCE_FILES cc.cpp)
4+
5+
include($ENV{FPC_PATH}/ecc_enclave/enclave/CMakeLists-common-app-enclave.txt)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
TOP = ../../..
2+
include $(TOP)/build.mk
3+
4+
TEST_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
5+
BUILD_DIR := ${TEST_DIR}/_build
6+
CC_NAME := "crash"
7+
DOCKER_IMAGE_NAME := fpc/${CC_NAME}
8+
9+
all: build docker test
10+
11+
$(BUILD_DIR):
12+
@if [ ! -d $(BUILD_DIR) ]; then \
13+
mkdir -p $(BUILD_DIR) && \
14+
cd $(BUILD_DIR) && \
15+
cmake ./..; \
16+
fi
17+
18+
build: $(BUILD_DIR)
19+
$(MAKE) --directory=$<
20+
21+
docker: build
22+
if [ "${SGX_MODE}" = "HW" ]; then \
23+
export HW_EXTENSION="-hw" ; \
24+
fi && \
25+
make -C ${FPC_PATH}/ecc CC_NAME=${CC_NAME} DOCKER_IMAGE=${DOCKER_IMAGE_NAME}$${HW_EXTENSION} DOCKER_ENCLAVE_SO_PATH=${BUILD_DIR}/lib all docker \
26+
&& $(DOCKER) tag ${DOCKER_IMAGE_NAME}$${HW_EXTENSION}:$(FPC_VERSION) ${DOCKER_IMAGE_NAME}$${HW_EXTENSION}:latest
27+
28+
test: docker
29+
CC_ID=$(CC_NAME) ./test.sh
30+
31+
clean:
32+
rm -rf $(BUILD_DIR)
33+
34+
35+
36+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <string>
2+
#include "logging.h"
3+
#include "shim.h"
4+
5+
const std::string SEP = ".";
6+
const std::string PREFIX = SEP + "somePrefix" + SEP;
7+
8+
std::string store(std::string auction_name, std::string bidder_name, int value, shim_ctx_ptr_t ctx)
9+
{
10+
std::string new_key(PREFIX + auction_name + SEP + bidder_name + SEP);
11+
put_public_state(new_key.c_str(), (uint8_t*)&value, sizeof(int), ctx);
12+
return "OK";
13+
}
14+
15+
std::string retrieve(std::string auction_name, shim_ctx_ptr_t ctx)
16+
{
17+
std::map<std::string, std::string> values;
18+
std::string bid_composite_key = PREFIX + auction_name + SEP;
19+
get_public_state_by_partial_composite_key(bid_composite_key.c_str(), values, ctx);
20+
return "STILL_ALIVE";
21+
}
22+
23+
int invoke(
24+
uint8_t* response, uint32_t max_response_len, uint32_t* actual_response_len, shim_ctx_ptr_t ctx)
25+
{
26+
LOG_DEBUG("[+] +++ Executing chaincode invocation +++");
27+
28+
std::string function_name;
29+
std::vector<std::string> params;
30+
get_func_and_params(function_name, params, ctx);
31+
std::string result;
32+
33+
if (function_name == "store")
34+
result = store(params[0], params[1], std::stoi(params[2]), ctx);
35+
else if (function_name == "retrieve")
36+
result = retrieve(params[0], ctx);
37+
38+
int neededSize = result.size();
39+
if (max_response_len < neededSize)
40+
{
41+
LOG_DEBUG("[+] Response buffer too small");
42+
*actual_response_len = 0;
43+
return -1;
44+
}
45+
46+
memcpy(response, result.c_str(), neededSize);
47+
*actual_response_len = neededSize;
48+
LOG_DEBUG("[+] Response: %s", result.c_str());
49+
LOG_DEBUG("[+] +++ Executing done +++");
50+
return 0;
51+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env bash
2+
3+
if [[ -z "${FPC_PATH}" ]]; then
4+
echo "Error: FPC_PATH not set"; exit 1
5+
fi
6+
7+
FABRIC_CFG_PATH="${FPC_PATH}/integration/config"
8+
FABRIC_SCRIPTDIR="${FPC_PATH}/fabric/bin/"
9+
10+
. "${FABRIC_SCRIPTDIR}"/lib/common_utils.sh
11+
. "${FABRIC_SCRIPTDIR}"/lib/common_ledger.sh
12+
13+
# this is the path points to FPC chaincode binary
14+
CC_PATH=${FPC_PATH}/integration/crashtest/unmarshal_values/_build/lib/
15+
16+
CC_ID="${CC_ID-crash}"
17+
CC_VER="$(cat "${CC_PATH}"/mrenclave)"
18+
CC_EP="OR('SampleOrg.member')"
19+
CC_SEQ="1"
20+
21+
run_test() {
22+
say "- install chaincode"
23+
PKG="/tmp/${CC_ID}.tar.gz"
24+
${PEER_CMD} lifecycle chaincode package --lang fpc-c --label "${CC_ID}" --path "${CC_PATH}" "${PKG}"
25+
${PEER_CMD} lifecycle chaincode install "${PKG}"
26+
27+
PKG_ID=$(${PEER_CMD} lifecycle chaincode queryinstalled | awk "/Package ID: ${CC_ID}/{print}" | sed -n 's/^Package ID: //; s/, Label:.*$//;p')
28+
29+
${PEER_CMD} lifecycle chaincode approveformyorg -o "${ORDERER_ADDR}" -C "${CHAN_ID}" --package-id "${PKG_ID}" --name "${CC_ID}" --version "${CC_VER}" --sequence ${CC_SEQ} --signature-policy ${CC_EP}
30+
${PEER_CMD} lifecycle chaincode checkcommitreadiness -C "${CHAN_ID}" --name "${CC_ID}" --version "${CC_VER}" --sequence ${CC_SEQ} --signature-policy ${CC_EP}
31+
${PEER_CMD} lifecycle chaincode commit -o "${ORDERER_ADDR}" -C "${CHAN_ID}" --name "${CC_ID}" --version "${CC_VER}" --sequence ${CC_SEQ} --signature-policy ${CC_EP}
32+
33+
${PEER_CMD} lifecycle chaincode initEnclave -o "${ORDERER_ADDR}" --peerAddresses "localhost:7051" --name "${CC_ID}"
34+
35+
say "- interact with the FPC chaincode using our client app"
36+
37+
export CC_ID
38+
export CHAN_ID
39+
try go test -v ./test
40+
}
41+
42+
trap ledger_shutdown EXIT
43+
44+
say "Setup ledger ..."
45+
ledger_init
46+
47+
para
48+
say "Run test ..."
49+
run_test
50+
51+
para
52+
say "Shutdown ledger ..."
53+
ledger_shutdown
54+
55+
yell "Test PASSED"
56+
57+
exit 0
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package test_test
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
fpc "github.com/hyperledger/fabric-private-chaincode/client_sdk/go/pkg/gateway"
8+
"github.com/hyperledger/fabric-private-chaincode/integration/client_sdk/go/utils"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestMustNotCrash(t *testing.T) {
13+
ccID := os.Getenv("CC_ID")
14+
channelID := os.Getenv("CHAN_ID")
15+
assert.NotEmpty(t, ccID)
16+
assert.NotEmpty(t, channelID)
17+
t.Logf("Use channel: %v, chaincode ID: %v", channelID, ccID)
18+
19+
network, err := utils.SetupNetwork(channelID)
20+
assert.NoError(t, err)
21+
contract := fpc.GetContract(network, ccID)
22+
23+
// this bidder name might cause the enclave crashing due to a null dereferencing
24+
// https://github.com/hyperledger/fabric-private-chaincode/blob/88b7c21cc398ed7273d807976f6dffe5e69bd18c/ecc_enclave/enclave/shim.cpp#L195
25+
result, err := contract.SubmitTransaction("store", "auction", "baz\",\"value\":4141},{\"key\":\"aa", "200")
26+
assert.NoError(t, err)
27+
assert.Equal(t, "OK", string(result))
28+
29+
result, err = contract.EvaluateTransaction("retrieve", "auction")
30+
assert.NoError(t, err)
31+
assert.Equal(t, "STILL_ALIVE", string(result))
32+
33+
result, err = contract.SubmitTransaction("store", "auction", "john", "200")
34+
assert.NoError(t, err)
35+
assert.Equal(t, "OK", string(result))
36+
37+
result, err = contract.EvaluateTransaction("retrieve", "auction")
38+
assert.NoError(t, err)
39+
assert.Equal(t, "STILL_ALIVE", string(result))
40+
}

0 commit comments

Comments
 (0)