diff --git a/build/build.sh b/build/build.sh index 6de020e..3715631 100644 --- a/build/build.sh +++ b/build/build.sh @@ -12,6 +12,7 @@ OUTPUT=${ROOT}/output BUILD=${ROOT}/build CLIDIR=${ROOT}/cli +DESTROYDIR=${ROOT}/destroy CLISRCNAME="main.c" INSTALLHELPERDIR=${ROOT}/install @@ -25,6 +26,8 @@ RUNTIMESRCNAME="main.go" CLISRCPATH=$(find ${CLIDIR} -name "${CLISRCNAME}") CLISRCDIR=${CLISRCPATH%/${CLISRCNAME}} +DESTROYSRCPATH=$(find ${DESTROYDIR} -name "${CLISRCNAME}") +DESTROYDIR=${DESTROYSRCPATH%/${CLISRCNAME}} INSTALLHELPERSRCPATH=$(find ${INSTALLHELPERDIR} -name "${INSTALLHELPERSRCNAME}") INSTALLHELPERSRCDIR=${INSTALLHELPERSRCPATH%/${INSTALLHELPERSRCNAME}} HOOKSRCPATH=$(find ${HOOKDIR} -name "${HOOKSRCNAME}") @@ -38,6 +41,14 @@ CPUARCH=$(uname -m) function build_bin() { + echo "make destroy" + [ -d "${BUILD}/build/destroy/build" ] && rm -rf ${BUILD}/build/destroy/build + mkdir -p ${BUILD}/build/destroy/build && cd ${BUILD}/build/destroy/build + + cmake ${DESTROYDIR} + make clean + make + echo "make cli" [ -d "${BUILD}/build/cli/build" ] && rm -rf ${BUILD}/build/cli/build mkdir -p ${BUILD}/build/cli/build && cd ${BUILD}/build/cli/build @@ -87,14 +98,14 @@ function build_run_package() cd ${BUILD} mkdir run_pkg - /bin/cp -f {${RUNTIMESRCDIR},${HOOKSRCDIR},${BUILD}/build/helper,${BUILD}/build/cli}/build/ascend-docker* run_pkg + /bin/cp -f {${RUNTIMESRCDIR},${HOOKSRCDIR},${BUILD}/build/helper,${BUILD}/build/cli,${BUILD}/build/destroy}/build/ascend-docker* run_pkg /bin/cp -f scripts/uninstall.sh run_pkg /bin/cp -f scripts/base.list run_pkg /bin/cp -f scripts/base.list_A500 run_pkg /bin/cp -f scripts/base.list_A200 run_pkg FILECNT=$(ls -l run_pkg |grep "^-"|wc -l) echo "prepare package $FILECNT bins" - if [ $FILECNT -ne 8 ]; then + if [ $FILECNT -ne 9 ]; then exit 1 fi /bin/cp -rf ${ROOT}/assets run_pkg diff --git a/build/scripts/run_main.sh b/build/scripts/run_main.sh index d4439bd..768422c 100644 --- a/build/scripts/run_main.sh +++ b/build/scripts/run_main.sh @@ -19,10 +19,12 @@ function install() cp -f ./ascend-docker-hook ${INSTALL_PATH}/ascend-docker-hook cp -f ./ascend-docker-cli ${INSTALL_PATH}/ascend-docker-cli cp -f ./ascend-docker-plugin-install-helper ${INSTALL_PATH}/ascend-docker-plugin-install-helper + cp -f ./ascend-docker-destroy ${INSTALL_PATH}/ascend-docker-destroy chmod 550 ${INSTALL_PATH}/ascend-docker-runtime chmod 550 ${INSTALL_PATH}/ascend-docker-hook chmod 550 ${INSTALL_PATH}/ascend-docker-cli chmod 550 ${INSTALL_PATH}/ascend-docker-plugin-install-helper + chmod 550 ${INSTALL_PATH}/ascend-docker-destroy cp -rf ./assets ${INSTALL_PATH}/assets cp -f ./README.md ${INSTALL_PATH}/README.md @@ -100,12 +102,14 @@ function upgrade() cp -f ./ascend-docker-hook ${INSTALL_PATH}/ascend-docker-hook cp -f ./ascend-docker-cli ${INSTALL_PATH}/ascend-docker-cli cp -f ./ascend-docker-plugin-install-helper ${INSTALL_PATH}/ascend-docker-plugin-install-helper + cp -f ./ascend-docker-destroy ${INSTALL_PATH}/ascend-docker-destroy cp -f ./uninstall.sh ${INSTALL_PATH}/script/uninstall.sh cp -f ./base.list ${ASCEND_RUNTIME_CONFIG_DIR}/base.list chmod 550 ${INSTALL_PATH}/ascend-docker-runtime chmod 550 ${INSTALL_PATH}/ascend-docker-hook chmod 550 ${INSTALL_PATH}/ascend-docker-cli chmod 550 ${INSTALL_PATH}/ascend-docker-plugin-install-helper + chmod 550 ${INSTALL_PATH}/ascend-docker-destroy chmod 500 ${INSTALL_PATH}/script/uninstall.sh chmod 440 ${ASCEND_RUNTIME_CONFIG_DIR}/base.list diff --git a/destroy/src/CMakeLists.txt b/destroy/src/CMakeLists.txt new file mode 100644 index 0000000..1b413ee --- /dev/null +++ b/destroy/src/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.26) +project(ascend-docker-destroy C) +set(CMAKE_C_STANDARD 11) +## The common options using by both c and cxx + +add_compile_options(-fstack-protector-all -D _GNU_SOURCE -Wl,--no-undefined) + +message(STATUS "CMAKE_SHARED_LIBRARY_LINK_C_FLAGS = " ${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS}) +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +include_directories("${PROJECT_SOURCE_DIR}/../../platform/HuaweiSecureC/include") +aux_source_directory(. SRC) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../build/HuaweiSecureC ${CMAKE_CURRENT_SOURCE_DIR}/../../build/HuaweiSecureC) +add_executable(ascend-docker-destroy ${SRC}) +target_compile_options(ascend-docker-destroy PRIVATE -fstack-protector-all -fpie -ldl -D_FORTIFY_SOURCE=2 -O2) +target_link_libraries(ascend-docker-destroy -ldl -pie -Wl,-s,-z,now HuaweiSecureC) diff --git a/destroy/src/main.c b/destroy/src/main.c new file mode 100644 index 0000000..aea8618 --- /dev/null +++ b/destroy/src/main.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: 算力切分数据销毁入口 +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" + +#define DCMI_INIT "dcmi_init" +#define DCMI_SET_DESTROY_VDEVICE "dcmi_set_destroy_vdevice" +#define ROOT_UID 0 +#define DECIMAL 10 +#define DESTROY_PARAMS_NUM 4 +#define PARAMS_SECOND 1 +#define PARAMS_THIRD 2 +#define PARAMS_FOURTH 3 +#define ID_MAX 65535 + +static bool ShowExceptionInfo(const char* exceptionInfo) +{ + (void)fprintf(stderr, exceptionInfo); + (void)fprintf(stderr, "\n"); + return false; +} + +static bool CheckLegality(const char* resolvedPath, const size_t resolvedPathLen, + const unsigned long long maxFileSzieMb, const bool checkOwner) +{ + const unsigned long long maxFileSzieB = maxFileSzieMb * 1024 * 1024; + char buf[PATH_MAX] = {0}; + if (strncpy_s(buf, sizeof(buf), resolvedPath, resolvedPathLen) != EOK) { + return false; + } + struct stat fileStat; + if ((stat(buf, &fileStat) != 0) || + ((S_ISREG(fileStat.st_mode) == 0) && (S_ISDIR(fileStat.st_mode) == 0))) { + return ShowExceptionInfo("resolvedPath does not exist or is not a file!"); + } + if (fileStat.st_size >= maxFileSzieB) { // 文件大小超限 + return ShowExceptionInfo("fileSize out of bounds!"); + } + for (int iLoop = 0; iLoop < PATH_MAX; iLoop++) { + if (checkOwner) { + if ((fileStat.st_uid != ROOT_UID) && (fileStat.st_uid != geteuid())) { // 操作文件owner非root/自己 + return ShowExceptionInfo("Please check the folder owner!"); + } + } + if ((fileStat.st_mode & S_IWOTH) != 0) { // 操作文件对other用户可写 + return ShowExceptionInfo("Please check the write permission!"); + } + if ((strcmp(buf, "/") == 0) || (strstr(buf, "/") == NULL)) { + break; + } + if (strcmp(dirname(buf), ".") == 0) { + break; + } + if (stat(buf, &fileStat) != 0) { + return false; + } + } + return true; +} + +static bool CheckExternalFile(const char* filePath, const size_t filePathLen, + const size_t maxFileSzieMb, const bool checkOwner) +{ + int iLoop; + if ((filePathLen > PATH_MAX) || (filePathLen <= 0)) { // 长度越界 + return ShowExceptionInfo("filePathLen out of bounds!"); + } + if (strstr(filePath, "..") != NULL) { // 存在".." + return ShowExceptionInfo("filePath has an illegal character!"); + } + for (iLoop = 0; iLoop < filePathLen; iLoop++) { + if ((isalnum(filePath[iLoop]) == 0) && (filePath[iLoop] != '.') && (filePath[iLoop] != '_') && + (filePath[iLoop] != '-') && (filePath[iLoop] != '/') && (filePath[iLoop] != '~')) { // 非法字符 + return ShowExceptionInfo("filePath has an illegal character!"); + } + } + char resolvedPath[PATH_MAX] = {0}; + if (realpath(filePath, resolvedPath) == NULL && errno != ENOENT) { + return ShowExceptionInfo("realpath failed!"); + } + if (strstr(resolvedPath, filePath) == NULL) { // 存在软链接 + return ShowExceptionInfo("filePath has a soft link!"); + } + return CheckLegality(resolvedPath, strlen(resolvedPath), maxFileSzieMb, checkOwner); +} + +static bool DeclareDcmiApiAndCheck(void **handle) +{ + *handle = dlopen("libdcmi.so", RTLD_LAZY); + if (*handle == NULL) { + (void)fprintf(stderr, "dlopen failed.\n"); + return false; + } + char pLinkMap[sizeof(struct link_map)] = {0}; + int ret = dlinfo(*handle, RTLD_DI_LINKMAP, &pLinkMap); + if (ret == 0) { + struct link_map* pLink = *(struct link_map**)pLinkMap; + const size_t maxFileSzieMb = 10; // max 10 mb + if (!CheckExternalFile(pLink->l_name, strlen(pLink->l_name), maxFileSzieMb, true)) { + (void)fprintf(stderr, "check sofile failed.\n"); + return false; + } + } else { + (void)fprintf(stderr, "dlinfo sofile failed.\n"); + return false; + } + + return true; +} + +static void DcmiDlAbnormalExit(void **handle, const char* errorInfo) +{ + (void)fprintf(stderr, errorInfo); + (void)fprintf(stderr, "\n"); + if (*handle != NULL) { + dlclose(*handle); + *handle = NULL; + } +} + +static void DcmiDlclose(void **handle) +{ + if (*handle != NULL) { + dlclose(*handle); + *handle = NULL; + } +} + +static int DestroyEntrance(const char *argv[]) +{ + if (argv == NULL) { + return -1; + } + errno = 0; + int cardId = atoi(argv[PARAMS_SECOND]); + if ((errno != 0) || (cardId < 0) || (cardId > ID_MAX)) { + return -1; + } + int deviceId = atoi(argv[PARAMS_THIRD]); + if ((errno != 0) || (deviceId < 0) || (deviceId > ID_MAX)) { + return -1; + } + int vDeviceId = atoi(argv[PARAMS_FOURTH]); + if ((errno != 0) || (vDeviceId < 0) || (vDeviceId > ID_MAX)) { + return -1; + } + void *handle = NULL; + if (!DeclareDcmiApiAndCheck(&handle)) { + (void)fprintf(stderr, "Declare dcmi failed.\n"); + return -1; + } + int (*dcmi_init)(void) = NULL; + int (*dcmi_set_destroy_vdevice)(int, int, int) = NULL; + dcmi_init = dlsym(handle, DCMI_INIT); + if (dcmi_init == NULL) { + DcmiDlAbnormalExit(&handle, "DeclareDlApi failed"); + return -1; + } + dcmi_set_destroy_vdevice = dlsym(handle, DCMI_SET_DESTROY_VDEVICE); + if (dcmi_set_destroy_vdevice == NULL) { + DcmiDlAbnormalExit(&handle, "DeclareDlApi failed"); + return -1; + } + int ret = dcmi_init(); + if (ret != 0) { + (void)fprintf(stderr, "dcmi_init failed, ret = %d\n", ret); + DcmiDlclose(&handle); + return -1; + } + ret = dcmi_set_destroy_vdevice(cardId, deviceId, vDeviceId); + if (ret != 0) { + (void)fprintf(stderr, "dcmi_set_destroy_vdevice failed, ret = %d\n", ret); + DcmiDlclose(&handle); + return -1; + } + DcmiDlclose(&handle); + return ret; +} + +static bool EntryCheck(const int argc, const char *argv[]) +{ + if (argc != DESTROY_PARAMS_NUM) { + (void)fprintf(stderr, "destroy params namber error.\n"); + return false; + } + for (int iLoop = 1; iLoop < argc; iLoop++) { + for (size_t jLoop = 0; jLoop < strlen(argv[iLoop]); jLoop++) { + if (isdigit(argv[iLoop][jLoop]) == 0) { + return false; + } + } + } + return true; +} + +int main(const int argc, const char *argv[]) +{ + if (!EntryCheck(argc, argv)) { + (void)fprintf(stderr, "destroy params value error.\n"); + return -1; + } + + return DestroyEntrance(argv); +} \ No newline at end of file