Match-id-0354e63b9bb8c86b7d8b9f14eba3884b6a7da21c

This commit is contained in:
BianTanggui
2022-03-28 17:11:41 +08:00
parent 208f625fdd
commit cdbf958c5b
11 changed files with 165 additions and 60 deletions

View File

@@ -21,6 +21,7 @@
#define BUF_SIZE 1024
#define MAX_DEVICE_NR 1024
#define MAX_MOUNT_NR 512
#define WHITE_LIST_NUM 4
#define ROOT_UID 0

View File

@@ -12,6 +12,7 @@
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include "securec.h"
#include "basic.h"
@@ -51,6 +52,12 @@ static bool DevicesCmdArgParser(struct CmdArgs *args, const char *arg)
Logger("args, arg pointer is null!", LEVEL_ERROR, SCREEN_YES);
return false;
}
for (size_t iLoop = 0; iLoop < strlen(arg); iLoop++) {
if ((isdigit(arg[iLoop]) == 0) && (arg[iLoop] != ',')) {
Logger("failed to check devices.", LEVEL_ERROR, SCREEN_YES);
return false;
}
}
errno_t err = strcpy_s(args->devices, BUF_SIZE, arg);
if (err != EOK) {
@@ -63,27 +70,71 @@ static bool DevicesCmdArgParser(struct CmdArgs *args, const char *arg)
static bool PidCmdArgParser(struct CmdArgs *args, const char *arg)
{
char buff[PATH_MAX] = {0};
if (args == NULL || arg == NULL) {
Logger("args, arg pointer is null!", LEVEL_ERROR, SCREEN_YES);
return false;
}
errno = 0;
args->pid = strtol(optarg, NULL, DECIMAL);
const char* pidMax = "/proc/sys/kernel/pid_max";
const size_t maxFileSzieMb = 10; // max 10MB
if (!CheckExternalFile(pidMax, strlen(pidMax), maxFileSzieMb, true)) {
Logger("failed to check pid_max path.", LEVEL_ERROR, SCREEN_YES);
return false;
}
FILE* pFile = NULL;
pFile = fopen(pidMax, "r");
if ((pFile == NULL) || (fgets(buff, PATH_MAX, pFile) == NULL)) {
Logger("failed to get pid_max buff.", LEVEL_ERROR, SCREEN_YES);
return false;
}
(void)fclose(pFile);
if ((strlen(buff) > 0) && (buff[strlen(buff) -1] == '\n')) {
buff[strlen(buff) -1] = '\0';
}
for (size_t iLoop = 0; iLoop < strlen(buff); iLoop++) {
if (isdigit(buff[iLoop]) == 0) {
Logger("failed to get pid_max value.", LEVEL_ERROR, SCREEN_YES);
return false;
}
}
if ((args->pid < 0) || (args->pid >= strtol(buff, NULL, DECIMAL))) {
Logger("The PID out of bounds.", LEVEL_ERROR, SCREEN_YES);
return false;
}
if (errno != 0) {
char* str = FormatLogMessage("failed to convert pid string from cmd args, pid string: %s.", arg);
Logger(str, LEVEL_ERROR, SCREEN_YES);
free(str);
return false;
}
if (args->pid <= 0) {
char* str = FormatLogMessage("invalid pid %d.", args->pid);
Logger(str, LEVEL_ERROR, SCREEN_YES);
free(str);
return false;
return true;
}
static bool CheckFileLegality(const char* filePath, const size_t filePathLen,
const size_t maxFileSzieMb)
{
if ((filePathLen > PATH_MAX) || (filePathLen <= 0)) { // 长度越界
Logger("filePathLen out of bounds!", LEVEL_ERROR, SCREEN_YES);
return false;
}
for (size_t iLoop = 0; iLoop < filePathLen; iLoop++) {
if (!IsValidChar(filePath[iLoop])) { // 非法字符
Logger("filePath has an illegal character!", LEVEL_ERROR, SCREEN_YES);
return false;
}
}
char resolvedPath[PATH_MAX] = {0};
if (realpath(filePath, resolvedPath) == NULL && errno != ENOENT) {
Logger("realpath failed!", LEVEL_ERROR, SCREEN_YES);
return false;
}
if (strstr(resolvedPath, filePath) == NULL) { // 存在软链接
Logger("filePath has a soft link!", LEVEL_ERROR, SCREEN_YES);
return false;
}
return true;
}
@@ -99,6 +150,11 @@ static bool RootfsCmdArgParser(struct CmdArgs *args, const char *arg)
Logger("failed to get rootfs path from cmd args", LEVEL_ERROR, SCREEN_YES);
return false;
}
const size_t maxFileSzieMb = 50; // max 50MB
if (!CheckFileLegality(args->rootfs, strlen(args->rootfs), maxFileSzieMb)) {
Logger("failed to check rootf.", LEVEL_ERROR, SCREEN_YES);
return false;
}
return true;
}
@@ -116,6 +172,35 @@ static bool OptionsCmdArgParser(struct CmdArgs *args, const char *arg)
return false;
}
if ((strcmp(args->options, "NODRV,VIRTUAL") != 0) &&
(strcmp(args->options, "NODRV") != 0) &&
(strcmp(args->options, "VIRTUAL") != 0)) {
Logger("Whitelist check failed.", LEVEL_ERROR, SCREEN_YES);
return false;
}
return true;
}
static bool CheckWhiteList(const char* fileName)
{
bool fileExists = false;
const char mountWhiteList[WHITE_LIST_NUM][PATH_MAX] = {{"/usr/local/Ascend/driver/lib64"},
{"/usr/local/Ascend/driver/include"},
{"/usr/local/dcmi"},
{"/usr/local/bin/npu-smi"}};
for (size_t iLoop = 0; iLoop < WHITE_LIST_NUM; iLoop++) {
if (strcmp(mountWhiteList[iLoop], fileName) == 0) {
fileExists = true;
}
}
if (!fileExists) {
char* str = FormatLogMessage("failed to check whiteList value: %s.", fileName);
Logger(str, LEVEL_ERROR, SCREEN_YES);
free(str);
return false;
}
return true;
}
@@ -142,7 +227,15 @@ static bool MountFileCmdArgParser(struct CmdArgs *args, const char *arg)
return false;
}
return true;
const size_t maxFileSzieMb = 50; // max 50MB
if (!CheckFileLegality(dst, strlen(dst), maxFileSzieMb)) {
char* str = FormatLogMessage("failed to check files: %s", dst);
Logger(str, LEVEL_ERROR, SCREEN_YES);
free(str);
return false;
}
return CheckWhiteList(dst) ? true : false;
}
static bool MountDirCmdArgParser(struct CmdArgs *args, const char *arg)
@@ -167,8 +260,13 @@ static bool MountDirCmdArgParser(struct CmdArgs *args, const char *arg)
free(str);
return false;
}
const size_t maxFileSzieMb = 50; // max 50MB
if (!CheckFileLegality(dst, strlen(dst), maxFileSzieMb)) {
Logger("failed to check dir.", LEVEL_ERROR, SCREEN_YES);
return false;
}
return true;
return CheckWhiteList(dst) ? true : false;
}
#define NUM_OF_CMD_ARGS 6

View File

@@ -31,10 +31,9 @@ int Mount(const char *src, const char *dst)
((S_ISREG(fileStat.st_mode) != 0) || (S_ISDIR(fileStat.st_mode) != 0))) { // 只校验文件和目录
const size_t maxFileSzieMb = 10 * 1024; // max 10 G
if (!CheckExternalFile(src, strlen(src), maxFileSzieMb, false)) {
char* str = FormatLogMessage("failed to mount src hehe:%s.", src);
char* str = FormatLogMessage("failed to Check src: %s.", src);
Logger(str, LEVEL_ERROR, SCREEN_YES);
free(str);
Logger("failed to Check src.", LEVEL_ERROR, SCREEN_YES);
return -1;
}
}

View File

@@ -223,19 +223,30 @@ static bool CheckLegality(const char* resolvedPath, const size_t resolvedPathLen
return true;
}
bool IsValidChar(const char c)
{
if (isalnum(c) != 0) {
return true;
}
// ._-/~为合法字符
if ((c == '.') || (c == '_') ||
(c == '-') || (c == '/') || (c == '~')) {
return true;
}
return false;
}
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] != '~')) { // 非法字符
for (size_t iLoop = 0; iLoop < filePathLen; iLoop++) {
if (!IsValidChar(filePath[iLoop])) { // 非法字符
return ShowExceptionInfo("filePath has an illegal character!");
}
}

View File

@@ -22,6 +22,7 @@ int CheckDirExists(const char *dir);
int GetParentPathStr(const char *path, char *parent, size_t bufSize);
int MakeDirWithParent(const char *path, mode_t mode);
int MakeMountPoints(const char *path, mode_t mode);
bool IsValidChar(const char c);
bool CheckExternalFile(const char* filePath, const size_t filePathLen,
const size_t maxFileSzieMb, const bool checkOwner);

View File

@@ -841,21 +841,6 @@ TEST(SetupCgroup, StatusThree)
EXPECT_EQ(-1, ret);
}
TEST(SetupCgroup, StatusFour)
{
MOCKER(SetupDriverCgroup).stubs().will(invoke(Stub_SetupDriverCgroup_Success));
MOCKER(SetupDeviceCgroup).stubs().will(invoke(Stub_SetupDeviceCgroup_Success));
struct ParsedConfig config;
(void)strcpy_s(config.rootfs, sizeof(config.rootfs), "/home");
config.devices[0] = 1;
config.devices[1] = 2;
config.devicesNr = 2;
(void)strcpy_s(config.cgroupPath, sizeof(config.cgroupPath), "devices.allow");
int ret = SetupCgroup(&config);
GlobalMockObject::verify();
EXPECT_EQ(0, ret);
}
TEST(SetupContainer, StatusOne)
{
struct CmdArgs args;

View File

@@ -193,7 +193,7 @@ var getContainerConfig = func() (*containerConfig, error) {
}
configPath := path.Join(state.Bundle, "config.json")
if _, err := mindxcheckutils.FileChecker(configPath, false, false, 0); err != nil {
if _, err := mindxcheckutils.FileChecker(configPath, false, false, true, 0); err != nil {
return nil, err
}
@@ -239,7 +239,7 @@ func readMountConfig(dir string, name string) ([]string, []string, error) {
}
fileInfo, err := os.Stat(baseConfigFilePath)
if _, err := mindxcheckutils.FileChecker(baseConfigFilePath, false, true, 0); err != nil {
if _, err := mindxcheckutils.FileChecker(baseConfigFilePath, false, true, false, 0); err != nil {
return nil, nil, err
}
if err != nil {
@@ -346,7 +346,7 @@ func doPrestartHook() error {
if _, err = os.Stat(cliPath); err != nil {
return fmt.Errorf("cannot find ascend-docker-cli executable file at %s: %v", cliPath, err)
}
if _, err := mindxcheckutils.FileChecker(cliPath, false, true, 0); err != nil {
if _, err := mindxcheckutils.FileChecker(cliPath, false, true, false, 0); err != nil {
return err
}

View File

@@ -326,19 +326,30 @@ static bool CheckLegality(const char* resolvedPath, const size_t resolvedPathLen
return true;
}
static bool IsValidChar(const char c)
{
if (isalnum(c) != 0) {
return true;
}
// ._-/~为合法字符
if ((c == '.') || (c == '_') ||
(c == '-') || (c == '/') || (c == '~')) {
return true;
}
return false;
}
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] != '~')) { // 非法字符
for (size_t iLoop = 0; iLoop < filePathLen; iLoop++) {
if (!IsValidChar(filePath[iLoop])) { // 非法字符
return ShowExceptionInfo("filePath has an illegal character!");
}
}

View File

@@ -1,8 +1,7 @@
// Package mindxcheckutils is a check utils package
/**
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved.
*/
// Package mindxcheckutils is a check utils package
package mindxcheckutils
import (
@@ -14,7 +13,7 @@ import (
)
// FileChecker check if a file/dir is safe to use
func FileChecker(path string, allowDir, checkParent bool, deep int) (bool, error) {
func FileChecker(path string, allowDir, checkParent, allowLink bool, deep int) (bool, error) {
const maxDepth, groupWriteIndex, otherWriteIndex, permLength int = 99, 5, 8, 10
if deep > maxDepth {
return false, fmt.Errorf("over maxDepth %v", maxDepth)
@@ -26,7 +25,7 @@ func FileChecker(path string, allowDir, checkParent bool, deep int) (bool, error
if err != nil {
return false, fmt.Errorf("get abs path failed %v", err)
}
fileInfo, ok, err := normalFileCheck(filePath, allowDir)
fileInfo, ok, err := normalFileCheck(filePath, allowDir, allowLink)
if err != nil {
return ok, err
}
@@ -52,14 +51,14 @@ func FileChecker(path string, allowDir, checkParent bool, deep int) (bool, error
return false, fmt.Errorf("owner not right %v %v", filePath, uid)
}
if filePath != "/" && checkParent {
return FileChecker(filepath.Dir(filePath), true, true, deep+1)
return FileChecker(filepath.Dir(filePath), true, true, allowLink, deep+1)
}
return true, nil
}
func normalFileCheck(filePath string, allowDir bool) (os.FileInfo, bool, error) {
func normalFileCheck(filePath string, allowDir bool, allowLink bool) (os.FileInfo, bool, error) {
realPath, err := filepath.EvalSymlinks(filePath)
if err != nil || realPath != filePath {
if err != nil || (realPath != filePath && !allowLink) {
return nil, false, fmt.Errorf("symlinks or not existed, failed %v, %v", filePath, err)
}
fileInfo, err := os.Stat(filePath)

View File

@@ -1,8 +1,7 @@
/*
// Package mindxcheckutils is a check utils package
/**
* Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved.
*/
// Package mindxcheckutils is a check utils package
package mindxcheckutils
import (
@@ -19,27 +18,27 @@ func TestNormalFileCheckRegularFile(t *testing.T) {
t.Fatalf("create symlink failed %q: %s", filePath, err)
}
if _, _, err = normalFileCheck(tmpDir, true); err != nil {
if _, _, err = normalFileCheck(tmpDir, true, false); err != nil {
t.Fatalf("check allow dir failed %q: %s", tmpDir+"/__test__", err)
}
if _, _, err = normalFileCheck(tmpDir, false); !strings.Contains(err.Error(), "not regular file") {
if _, _, err = normalFileCheck(tmpDir, false, false); !strings.Contains(err.Error(), "not regular file") {
t.Fatalf("check not allow dir failed %q: %s", tmpDir+"/__test__", err)
}
if _, _, err = normalFileCheck("/dev/zero", true); !strings.Contains(err.Error(), "not regular file/dir") {
if _, _, err = normalFileCheck("/dev/zero", true, false); !strings.Contains(err.Error(), "not regular file/dir") {
t.Fatalf("check /dev/zero failed %q: %s", tmpDir+"/__test__", err)
}
if _, _, err = normalFileCheck(tmpDir+"/syslink", false); !strings.Contains(err.Error(), "symlinks") {
if _, _, err = normalFileCheck(tmpDir+"/syslink", false, false); !strings.Contains(err.Error(), "symlinks") {
t.Fatalf("check symlinks failed %q: %s", tmpDir+"/syslink", err)
}
if _, _, err = normalFileCheck(filePath, false); err != nil {
if _, _, err = normalFileCheck(filePath, false, false); err != nil {
t.Fatalf("check failed %q: %s", filePath, err)
}
if _, _, err = normalFileCheck(tmpDir+"/notexisted", false); !strings.Contains(err.Error(), "not existed") {
if _, _, err = normalFileCheck(tmpDir+"/notexisted", false, false); !strings.Contains(err.Error(), "not existed") {
t.Fatalf("check symlinks failed %q: %s", tmpDir+"/syslink", err)
}
}
@@ -52,15 +51,16 @@ func TestFileCheckRegularFile(t *testing.T) {
t.Fatalf("create symlink failed %q: %s", filePath, err)
}
if _, err = FileChecker(tmpDir, true, false, 0); err != nil {
if _, err = FileChecker(tmpDir, true, false, false, 0); err != nil {
t.Fatalf("check allow dir failed %q: %s", tmpDir+"/__test__", err)
}
if _, err = FileChecker(tmpDir, false, false, 0); err != nil && !strings.Contains(err.Error(), "not regular file") {
if _, err = FileChecker(tmpDir, false, false, false, 0); err != nil &&
!strings.Contains(err.Error(), "not regular file") {
t.Fatalf("check not allow dir failed %q: %s", tmpDir+"/__test__", err)
}
if _, err = FileChecker("/dev/zero", true, false, 0); err != nil &&
if _, err = FileChecker("/dev/zero", true, false, false, 0); err != nil &&
!strings.Contains(err.Error(), "not regular file/dir") {
t.Fatalf("check /dev/zero failed %q: %s", tmpDir+"/__test__", err)
}

View File

@@ -65,7 +65,7 @@ var execRunc = func() error {
return fmt.Errorf("failed to find the path of runc: %v", err)
}
}
if _, err := mindxcheckutils.FileChecker(runcPath, false, true, 0); err != nil {
if _, err := mindxcheckutils.FileChecker(runcPath, false, true, false, 0); err != nil {
return err
}
@@ -83,7 +83,7 @@ func addHook(spec *specs.Spec) error {
}
hookCliPath = path.Join(path.Dir(currentExecPath), hookCli)
if _, err := mindxcheckutils.FileChecker(hookCliPath, false, true, 0); err != nil {
if _, err := mindxcheckutils.FileChecker(hookCliPath, false, true, false, 0); err != nil {
return err
}
if _, err = os.Stat(hookCliPath); err != nil {
@@ -114,7 +114,7 @@ func modifySpecFile(path string) error {
if err != nil {
return fmt.Errorf("spec file doesnt exist %s: %v", path, err)
}
if _, err := mindxcheckutils.FileChecker(path, false, true, 0); err != nil {
if _, err := mindxcheckutils.FileChecker(path, false, true, true, 0); err != nil {
return err
}