未验证 提交 5e15e94f 编写于 作者: O openharmony_ci 提交者: Gitee

!1195 seccomp模块进程内存映射空间优化

Merge pull request !1195 from 夏不白/seccomp_so
...@@ -26,16 +26,14 @@ if (defined(build_seccomp) && build_seccomp) { ...@@ -26,16 +26,14 @@ if (defined(build_seccomp) && build_seccomp) {
include_dirs = [ include_dirs = [
"//base/startup/init/interfaces/innerkits/include", "//base/startup/init/interfaces/innerkits/include",
"//base/startup/init/services/modules/seccomp",
"//base/startup/init/services/modules", "//base/startup/init/services/modules",
"//base/startup/init/services/log", "//base/startup/init/services/log",
"//third_party/bounds_checking_function/include",
] ]
deps = [ deps = [
"//base/startup/init/interfaces/innerkits:libbegetutil", "//base/startup/init/interfaces/innerkits:libbegetutil",
"//base/startup/init/services/modules/seccomp:app_filter", "//third_party/bounds_checking_function:libsec_shared",
"//base/startup/init/services/modules/seccomp:appspawn_filter",
"//base/startup/init/services/modules/seccomp:nwebspawn_filter",
] ]
license_file = "//base/startup/init/LICENSE" license_file = "//base/startup/init/LICENSE"
...@@ -43,10 +41,7 @@ if (defined(build_seccomp) && build_seccomp) { ...@@ -43,10 +41,7 @@ if (defined(build_seccomp) && build_seccomp) {
part_name = "init" part_name = "init"
install_enable = true install_enable = true
install_images = [ install_images = [ "system" ]
"system",
"updater",
]
} }
} else { } else {
group("seccomp") { group("seccomp") {
......
...@@ -25,14 +25,12 @@ extern "C" { ...@@ -25,14 +25,12 @@ extern "C" {
#endif #endif
#endif #endif
typedef enum { #define SYSTEM_NAME "system"
SYSTEM, #define APPSPAWN_NAME "appspawn"
APPSPAWN, #define NWEBSPAWN_NAME "nwebspawn"
APP, #define APP_NAME "app"
NWEBSPAWN,
} PolicyType;
bool SetSeccompPolicy(PolicyType policy); bool SetSeccompPolicyWithName(const char *filterName);
#ifdef __cplusplus #ifdef __cplusplus
#if __cplusplus #if __cplusplus
......
...@@ -36,7 +36,7 @@ group("modulesgroup") { ...@@ -36,7 +36,7 @@ group("modulesgroup") {
"reboot:rebootmodule", "reboot:rebootmodule",
] ]
if (build_seccomp) { if (build_seccomp) {
deps += [ "seccomp:seccomp_module" ] deps += [ "seccomp:seccomp_filter" ]
} }
if (build_selinux) { if (build_selinux) {
deps += [ "selinux:selinuxadp" ] deps += [ "selinux:selinuxadp" ]
......
...@@ -77,16 +77,11 @@ ohos_prebuilt_seccomp("system_filter") { ...@@ -77,16 +77,11 @@ ohos_prebuilt_seccomp("system_filter") {
} }
filtername = "g_systemSeccompFilter" filtername = "g_systemSeccompFilter"
include_dirs = [ "." ]
part_name = INIT_PART part_name = INIT_PART
subsystem_name = "startup" subsystem_name = "startup"
install_enable = true install_enable = true
install_images = [ install_images = [ "system" ]
"system",
"ramdisk",
"updater",
]
} }
ohos_prebuilt_seccomp("appspawn_filter") { ohos_prebuilt_seccomp("appspawn_filter") {
...@@ -102,7 +97,6 @@ ohos_prebuilt_seccomp("appspawn_filter") { ...@@ -102,7 +97,6 @@ ohos_prebuilt_seccomp("appspawn_filter") {
} }
filtername = "g_appspawnSeccompFilter" filtername = "g_appspawnSeccompFilter"
include_dirs = [ "." ]
part_name = INIT_PART part_name = INIT_PART
subsystem_name = "startup" subsystem_name = "startup"
...@@ -118,7 +112,6 @@ ohos_prebuilt_seccomp("nwebspawn_filter") { ...@@ -118,7 +112,6 @@ ohos_prebuilt_seccomp("nwebspawn_filter") {
} }
filtername = "g_nwebspawnSeccompFilter" filtername = "g_nwebspawnSeccompFilter"
include_dirs = [ "." ]
part_name = INIT_PART part_name = INIT_PART
subsystem_name = "startup" subsystem_name = "startup"
...@@ -139,7 +132,6 @@ ohos_prebuilt_seccomp("app_filter") { ...@@ -139,7 +132,6 @@ ohos_prebuilt_seccomp("app_filter") {
} }
filtername = "g_appSeccompFilter" filtername = "g_appSeccompFilter"
include_dirs = [ "." ]
part_name = INIT_PART part_name = INIT_PART
subsystem_name = "startup" subsystem_name = "startup"
...@@ -147,46 +139,30 @@ ohos_prebuilt_seccomp("app_filter") { ...@@ -147,46 +139,30 @@ ohos_prebuilt_seccomp("app_filter") {
install_images = [ "system" ] install_images = [ "system" ]
} }
ohos_shared_library("seccomp_module") { config("libseccomp_static_config") {
sources = [ "seccomp_policy.c" ]
include_dirs = [ include_dirs = [
"//base/startup/init/services/modules", "//base/startup/init/services/modules",
"//base/startup/init/interfaces/innerkits/include",
"//base/startup/init/interfaces/innerkits/seccomp/include", "//base/startup/init/interfaces/innerkits/seccomp/include",
"//base/startup/init/services/modules/seccomp", "//third_party/bounds_checking_function/include",
] ]
}
deps = [ ohos_source_set("libseccomp_static") {
":system_filter", sources = [
"//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine", "seccomp_policy.c",
"seccomp_policy_static.c",
] ]
public_configs = [
cflags = [ "-DSECCOMP_PLUGIN" ] ":libseccomp_static_config",
"//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config",
part_name = "init"
if (target_cpu == "arm64") {
module_install_dir = "lib64/init"
} else {
module_install_dir = "lib/init"
}
install_images = [
"system",
"ramdisk",
"updater",
] ]
} }
config("libseccomp_static_config") { group("seccomp_filter") {
include_dirs = [ deps = [
"//base/startup/init/services/modules", ":app_filter",
"//base/startup/init/services/modules/seccomp", ":appspawn_filter",
"//base/startup/init/interfaces/innerkits/seccomp/include", ":nwebspawn_filter",
":system_filter",
] ]
} }
ohos_source_set("libseccomp_static") {
sources = [ "seccomp_policy_static.c" ]
public_configs = [ ":libseccomp_static_config" ]
public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ]
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SECCOMP_FILTERS_H
#define SECCOMP_FILTERS_H
#include <stddef.h>
#include <linux/filter.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
extern const struct sock_filter g_appspawnSeccompFilter[];
extern const size_t g_appspawnSeccompFilterSize;
extern const struct sock_filter g_systemSeccompFilter[];
extern const size_t g_systemSeccompFilterSize;
extern const struct sock_filter g_nwebspawnSeccompFilter[];
extern const size_t g_nwebspawnSeccompFilterSize;
extern const struct sock_filter g_appSeccompFilter[];
extern const size_t g_appSeccompFilterSize;
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // SECCOMP_FILTERS_H
...@@ -14,12 +14,10 @@ ...@@ -14,12 +14,10 @@
*/ */
#include "seccomp_policy.h" #include "seccomp_policy.h"
#include "seccomp_filters.h"
#include "plugin_adapter.h" #include "plugin_adapter.h"
#ifdef SECCOMP_PLUGIN #include "securec.h"
#include "init_module_engine.h"
#endif
#include <dlfcn.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>
...@@ -33,6 +31,14 @@ ...@@ -33,6 +31,14 @@
#define SECCOMP_SET_MODE_FILTER (1) #define SECCOMP_SET_MODE_FILTER (1)
#endif #endif
#ifdef __aarch64__
#define FILTER_LIB_PATH_FORMAT "/system/lib64/lib%s_filter.z.so"
#else
#define FILTER_LIB_PATH_FORMAT "/system/lib/lib%s_filter.z.so"
#endif
#define FILTER_NAME_FORMAT "g_%sSeccompFilter"
#define FILTER_SIZE_STRING "Size"
static bool IsSupportFilterFlag(unsigned int filterFlag) static bool IsSupportFilterFlag(unsigned int filterFlag)
{ {
errno = 0; errno = 0;
...@@ -69,78 +75,41 @@ static bool InstallSeccompPolicy(const struct sock_filter* filter, size_t filter ...@@ -69,78 +75,41 @@ static bool InstallSeccompPolicy(const struct sock_filter* filter, size_t filter
return true; return true;
} }
#ifndef SECCOMP_PLUGIN bool SetSeccompPolicyWithName(const char *filterName)
bool SetSeccompPolicy(PolicyType policy)
{ {
bool ret = false; char filterLibPath[512] = {0};
switch (policy) { char filterVaribleName[512] = {0};
case APPSPAWN: struct sock_filter *filterPtr = NULL;
ret = InstallSeccompPolicy(g_appspawnSeccompFilter, g_appspawnSeccompFilterSize, SECCOMP_FILTER_FLAG_LOG); size_t *filterSize = NULL;
break;
case NWEBSPAWN:
ret = InstallSeccompPolicy(g_nwebspawnSeccompFilter, g_nwebspawnSeccompFilterSize, SECCOMP_FILTER_FLAG_LOG);
break;
case APP:
ret = InstallSeccompPolicy(g_appSeccompFilter, g_appSeccompFilterSize, SECCOMP_FILTER_FLAG_LOG);
break;
default:
ret = false;
}
return ret; int rc = snprintf_s(filterLibPath, sizeof(filterLibPath), \
} strlen(filterName) + strlen(FILTER_LIB_PATH_FORMAT) - strlen("%s"), \
#else FILTER_LIB_PATH_FORMAT, filterName);
static bool SetSystemSeccompPolicy(void) PLUGIN_CHECK(rc != -1, return false, "snprintf_s filterLibPath failed");
{
return InstallSeccompPolicy(g_systemSeccompFilter, g_systemSeccompFilterSize, SECCOMP_FILTER_FLAG_LOG);
}
static int DoSetSeccompPolicyStart(void) rc = snprintf_s(filterVaribleName, sizeof(filterVaribleName), \
{ strlen(filterName) + strlen(FILTER_NAME_FORMAT) - strlen("%s"), \
bool ret = false; FILTER_NAME_FORMAT, filterName);
ret = SetSystemSeccompPolicy(); PLUGIN_CHECK(rc != -1, return false, "snprintf_s faiVribleName failed");
PLUGIN_CHECK(ret == true, return -1, "SetSeccompPolicy failed");
return 0; void *handler = dlopen(filterLibPath, RTLD_LAZY);
} PLUGIN_CHECK(handler != NULL, return false, "dlopen %s failed", filterLibPath);
static int DoSetSeccompPolicyCmd(int id, const char *name, int argc, const char **argv) filterPtr = (struct sock_filter *)dlsym(handler, filterVaribleName);
{ PLUGIN_CHECK(filterPtr != NULL, dlclose(handler);
PLUGIN_LOGI("DoBootchartCmd argc %d %s", argc, name); return false, "dlsym %s failed", filterVaribleName);
PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
if (strcmp(argv[0], "start") == 0) {
return DoSetSeccompPolicyStart();
}
return 0;
}
static int32_t g_executorId = -1; rc = strcat_s(filterVaribleName, strlen(filterVaribleName) + strlen(FILTER_SIZE_STRING) + 1, FILTER_SIZE_STRING);
static int SetSeccompPolicyInit(void) PLUGIN_CHECK(rc == 0, dlclose(handler);
{ return false, "strcat_s filterVaribleName failed");
if (g_executorId == -1) {
g_executorId = AddCmdExecutor("SetSeccompPolicy", DoSetSeccompPolicyCmd);
PLUGIN_LOGI("SetSeccompPolicy executorId %d", g_executorId);
}
return 0;
}
static void SetSeccompPolicyExit(void) filterSize = (size_t *)dlsym(handler, filterVaribleName);
{ PLUGIN_CHECK(filterSize != NULL, dlclose(handler);
PLUGIN_LOGI("SetSeccompPolicy executorId %d", g_executorId); return false, "dlsym %s failed", filterVaribleName);
if (g_executorId != -1) {
RemoveCmdExecutor("SetSeccompPolicy", g_executorId);
}
}
MODULE_CONSTRUCTOR(void) bool ret = InstallSeccompPolicy(filterPtr, *filterSize, SECCOMP_FILTER_FLAG_LOG);
{
PLUGIN_LOGI("DoSetSeccompPolicyStart now ...");
SetSeccompPolicyInit();
}
MODULE_DESTRUCTOR(void) dlclose(handler);
{
PLUGIN_LOGI("DoSetSeccompPolicyStop now ..."); return ret;
SetSeccompPolicyExit();
} }
#endif
...@@ -17,9 +17,6 @@ arm ...@@ -17,9 +17,6 @@ arm
@returnValue @returnValue
KILL_PROCESS KILL_PROCESS
@headFiles
"seccomp_filters.h"
@priority @priority
ioctl ioctl
futex futex
......
...@@ -17,9 +17,6 @@ arm64 ...@@ -17,9 +17,6 @@ arm64
@returnValue @returnValue
KILL_PROCESS KILL_PROCESS
@headFiles
"seccomp_filters.h"
@priority @priority
ioctl ioctl
futex futex
......
...@@ -18,7 +18,6 @@ arm ...@@ -18,7 +18,6 @@ arm
KILL_PROCESS KILL_PROCESS
@headFiles @headFiles
"seccomp_filters.h"
"time.h" "time.h"
"sys/ioctl.h" "sys/ioctl.h"
"linux/futex.h" "linux/futex.h"
......
...@@ -18,7 +18,6 @@ arm64 ...@@ -18,7 +18,6 @@ arm64
KILL_PROCESS KILL_PROCESS
@headFiles @headFiles
"seccomp_filters.h"
"time.h" "time.h"
"sys/ioctl.h" "sys/ioctl.h"
"linux/futex.h" "linux/futex.h"
......
...@@ -20,9 +20,6 @@ KILL_PROCESS ...@@ -20,9 +20,6 @@ KILL_PROCESS
@mode @mode
ONLY_CHECK_ARGS ONLY_CHECK_ARGS
@headFiles
"seccomp_filters.h"
@allowListWithArgs @allowListWithArgs
setresuid32: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS; setresuid32: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS;
setresgid32: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS; setresgid32: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS;
...@@ -19,9 +19,6 @@ KILL_PROCESS ...@@ -19,9 +19,6 @@ KILL_PROCESS
@mode @mode
ONLY_CHECK_ARGS ONLY_CHECK_ARGS
@headFiles
"seccomp_filters.h"
@allowListWithArgs @allowListWithArgs
setresuid: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS; setresuid: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS;
setresgid: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS; setresgid: if arg0 >= 1000 && arg1 >= 1000 && arg2 >= 1000; return ALLOW; else return KILL_PROCESS;
...@@ -17,9 +17,6 @@ arm ...@@ -17,9 +17,6 @@ arm
@returnValue @returnValue
KILL_PROCESS KILL_PROCESS
@headFiles
"seccomp_filters.h"
@allowList @allowList
restart_syscall restart_syscall
exit exit
......
...@@ -17,9 +17,6 @@ arm64 ...@@ -17,9 +17,6 @@ arm64
@returnValue @returnValue
KILL_PROCESS KILL_PROCESS
@headFiles
"seccomp_filters.h"
@allowList @allowList
io_setup io_setup
io_destroy io_destroy
......
...@@ -15,10 +15,32 @@ ...@@ -15,10 +15,32 @@
#include <string.h> #include <string.h>
#include "init_module_engine.h" #include "init_module_engine.h"
#include "plugin_adapter.h" #include "plugin_adapter.h"
#include "seccomp_policy.h"
static int SetSystemSeccompPolicy(int id, const char *name, int argc, const char **argv)
{
PLUGIN_LOGI("SetSystemSeccompPolicy argc %d %s", argc, name);
PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
bool ret = SetSeccompPolicyWithName(SYSTEM_NAME);
PLUGIN_CHECK(ret == true, return -1, "SetSystemSeccompPolicy failed");
return 0;
}
static int32_t g_executorId = -1;
static int SetSeccompPolicyInit(void)
{
if (g_executorId == -1) {
g_executorId = AddCmdExecutor("SetSeccompPolicy", SetSystemSeccompPolicy);
PLUGIN_LOGI("SetSeccompPolicy executorId %d", g_executorId);
}
return 0;
}
static int SeccompHook(const HOOK_INFO *info, void *cookie) static int SeccompHook(const HOOK_INFO *info, void *cookie)
{ {
InitModuleMgrInstall("seccomp_module"); SetSeccompPolicyInit();
PLUGIN_LOGI("seccomp enabled."); PLUGIN_LOGI("seccomp enabled.");
return 0; return 0;
} }
......
...@@ -53,7 +53,7 @@ public: ...@@ -53,7 +53,7 @@ public:
{ {
} }
static pid_t StartChild(PolicyType type, SyscallFunc func) static pid_t StartChild(const char *filterName, SyscallFunc func)
{ {
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0) { if (pid == 0) {
...@@ -61,8 +61,8 @@ public: ...@@ -61,8 +61,8 @@ public:
std::cout << "PR_SET_NO_NEW_PRIVS set fail " << std::endl; std::cout << "PR_SET_NO_NEW_PRIVS set fail " << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (type != SYSTEM && !SetSeccompPolicy(type)) { if (!SetSeccompPolicyWithName(filterName)) {
std::cout << "SetSeccompPolicy set fail type is " << type << std::endl; std::cout << "SetSeccompPolicy set fail fiterName is " << filterName << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -78,7 +78,7 @@ public: ...@@ -78,7 +78,7 @@ public:
return pid; return pid;
} }
static int CheckSyscall(PolicyType type, SyscallFunc func, bool isAllow) static int CheckSyscall(const char *filterName, SyscallFunc func, bool isAllow)
{ {
sigset_t set; sigset_t set;
int status; int status;
...@@ -93,7 +93,7 @@ public: ...@@ -93,7 +93,7 @@ public:
std::cout << "signal failed:" << strerror(errno) << std::endl; std::cout << "signal failed:" << strerror(errno) << std::endl;
} }
pid = StartChild(type, func); pid = StartChild(filterName, func);
if (pid == -1) { if (pid == -1) {
std::cout << "fork failed:" << strerror(errno) << std::endl; std::cout << "fork failed:" << strerror(errno) << std::endl;
return -1; return -1;
...@@ -200,33 +200,33 @@ public: ...@@ -200,33 +200,33 @@ public:
void TestSystemSycall() void TestSystemSycall()
{ {
// system blocklist // system blocklist
int ret = CheckSyscall(SYSTEM, CheckGetMempolicy, false); int ret = CheckSyscall(SYSTEM_NAME, CheckGetMempolicy, false);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
// system allowlist // system allowlist
ret = CheckSyscall(SYSTEM, CheckGetpid, true); ret = CheckSyscall(SYSTEM_NAME, CheckGetpid, true);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
void TestSetUidGidFilter() void TestSetUidGidFilter()
{ {
// system blocklist // system blocklist
int ret = CheckSyscall(APPSPAWN, CheckSetresuidArgsOutOfRange, false); int ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuidArgsOutOfRange, false);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
// system allowlist // system allowlist
ret = CheckSyscall(APPSPAWN, CheckSetresuidArgsInRange, true); ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuidArgsInRange, true);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
void TestAppSycall() void TestAppSycall()
{ {
// app blocklist // app blocklist
int ret = CheckSyscall(APP, CheckSetuid, false); int ret = CheckSyscall(APP_NAME, CheckSetuid, false);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
// app allowlist // app allowlist
ret = CheckSyscall(APP, CheckGetpid, true); ret = CheckSyscall(APP_NAME, CheckGetpid, true);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
#elif defined __arm__ #elif defined __arm__
...@@ -281,33 +281,33 @@ public: ...@@ -281,33 +281,33 @@ public:
void TestSystemSycall() void TestSystemSycall()
{ {
// system blocklist // system blocklist
int ret = CheckSyscall(SYSTEM, CheckGetuid, false); int ret = CheckSyscall(SYSTEM_NAME, CheckGetuid, false);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
// system allowlist // system allowlist
ret = CheckSyscall(SYSTEM, CheckGetuid32, true); ret = CheckSyscall(SYSTEM_NAME, CheckGetuid32, true);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
void TestSetUidGidFilter() void TestSetUidGidFilter()
{ {
// system blocklist // system blocklist
int ret = CheckSyscall(APPSPAWN, CheckSetresuid32ArgsOutOfRange, false); int ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuid32ArgsOutOfRange, false);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
// system allowlist // system allowlist
ret = CheckSyscall(APPSPAWN, CheckSetresuid32ArgsInRange, true); ret = CheckSyscall(APPSPAWN_NAME, CheckSetresuid32ArgsInRange, true);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
void TestAppSycall() void TestAppSycall()
{ {
// app blocklist // app blocklist
int ret = CheckSyscall(APP, CheckSetuid32, false); int ret = CheckSyscall(APP_NAME, CheckSetuid32, false);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
// app allowlist // app allowlist
ret = CheckSyscall(APP, CheckGetuid32, true); ret = CheckSyscall(APP_NAME, CheckGetuid32, true);
EXPECT_EQ(ret, 0); EXPECT_EQ(ret, 0);
} }
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册