跨应用共享库启动适配

Change-Id: Ifa280ba0d5718cab303ab23493567a9d689032cb
Signed-off-by: yml <yangmingliang9@huawei.com>
This commit is contained in:
yangmingliang 2022-12-13 17:55:27 +08:00
parent 1c6b45d91d
commit fb05033a99
10 changed files with 650 additions and 9 deletions

View File

@ -59,6 +59,11 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
appProperty->property.cloneFlags = client->cloneFlags;
int ret = SandboxUtils::SetAppSandboxProperty(&appProperty->property);
// free HspList
if (appProperty->property.hspList.data != nullptr) {
free(appProperty->property.hspList.data);
appProperty->property.hspList = {};
}
// for module test do not create sandbox
if (strncmp(appProperty->property.bundleName,
MODULE_TEST_BUNDLE_NAME.c_str(), MODULE_TEST_BUNDLE_NAME.size()) == 0) {

View File

@ -16,6 +16,8 @@
#include "appspawn_socket.h"
#include <sys/socket.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <cerrno>
#include "appspawn_server.h"
@ -79,7 +81,9 @@ int AppSpawnSocket::CreateSocket()
int socketFd = socket(AF_UNIX, SOCK_STREAM, 0); // SOCK_SEQPACKET
APPSPAWN_CHECK(socketFd >= 0, return -errno, "Failed to create socket: %d", errno);
APPSPAWN_LOGV("Created socket with fd %d", socketFd);
int flag = 1;
int ret = setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
APPSPAWN_LOGV("Created socket with fd %d, setsockopt %d", socketFd, ret);
return socketFd;
}
@ -87,6 +91,8 @@ void AppSpawnSocket::CloseSocket(int &socketFd)
{
if (socketFd >= 0) {
APPSPAWN_LOGV("Closed socket with fd %d", socketFd);
int flag = 0;
setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
close(socketFd);
socketFd = -1;
}

View File

@ -63,6 +63,12 @@ typedef enum AppOperateType_ {
#define FDLEN2 2
#define FD_INIT_VALUE 0
typedef struct HspList_ {
uint32_t totalLength;
uint32_t savedLength;
char* data;
} HspList;
typedef struct AppParameter_ {
uint32_t cloneFlags;
uint32_t uid; // the UNIX uid that the child process setuid() to after fork()
@ -86,6 +92,7 @@ typedef struct AppParameter_ {
uint8_t reserved1;
uint8_t reserved2;
#endif
HspList hspList; // list of cross-app hsp (Harmony Shared Package) to mount onto app sandbox
} AppParameter;
#ifdef __cplusplus

View File

@ -228,7 +228,7 @@ static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClie
return 0;
}
static void Free(char **argv)
static void Free(char **argv, HspList *hspList)
{
argv[0] = NULL;
for (int i = 0; i < NULL_INDEX; i++) {
@ -238,6 +238,12 @@ static void Free(char **argv)
}
}
free(argv);
if (hspList != NULL) {
hspList->totalLength = 0;
hspList->savedLength = 0;
hspList->data = NULL;
}
}
#ifdef ASAN_DETECTOR
@ -310,6 +316,12 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client
appProperty->accessTokenId, appProperty->apl, appProperty->renderCmd);
APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format processName");
startLen += len;
len = sprintf_s(buffer, sizeof(buffer), "%u", appProperty->hspList.totalLength);
APPSPAWN_CHECK(len > 0 && len < sizeof(buffer), break, "Invalid hspList.totalLength");
argv[HSP_LIST_LEN_INDEX] = strdup(buffer);
argv[HSP_LIST_INDEX] = appProperty->hspList.data;
ret = 0;
} while (0);
@ -324,7 +336,7 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client
APPSPAWN_LOGE("Failed to execv, errno = %d", errno);
}
}
Free(argv);
Free(argv, &appProperty->hspList);
return ret;
}
@ -387,6 +399,22 @@ int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *cl
ret = strcpy_s(client->property.renderCmd, sizeof(client->property.renderCmd), start);
APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy renderCmd");
if (argc > HSP_LIST_LEN_INDEX) {
APPSPAWN_CHECK(argv[HSP_LIST_LEN_INDEX] != NULL, return -1, "Invalid HspList length");
client->property.hspList.totalLength = atoi(argv[HSP_LIST_LEN_INDEX]);
} else {
client->property.hspList.totalLength = 0;
}
client->property.hspList.data = NULL;
if (client->property.hspList.totalLength > 0) {
APPSPAWN_CHECK(argc > HSP_LIST_INDEX && argv[HSP_LIST_INDEX] != NULL, return -1, "Invalid argv for HspList");
client->property.hspList.data = malloc(client->property.hspList.totalLength);
APPSPAWN_CHECK(client->property.hspList.data != NULL, return -1, "Failed to malloc hspList.data");
ret = strcpy_s(client->property.hspList.data, client->property.hspList.totalLength, argv[HSP_LIST_INDEX]);
APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy hspList.data");
}
return 0;
}

View File

@ -321,16 +321,88 @@ static void SetInternetPermission(AppSpawnClientExt *appProperty)
}
}
static void FreeHspList(AppSpawnClientExt *client)
{
if (client != NULL && client->property.hspList.data != NULL) {
free(client->property.hspList.data);
client->property.hspList.totalLength = 0;
client->property.hspList.savedLength = 0;
client->property.hspList.data = NULL;
}
}
APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client,
const uint8_t *buffer, uint32_t buffLen)
{
APPSPAWN_LOGI("ReceiveRequestData: buffLen=%u", buffLen);
APPSPAWN_CHECK(buffer != NULL && buffLen > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
return false, "ReceiveRequestData: Invalid buff");
// 1. receive AppParamter
if (client->property.hspList.totalLength == 0) {
APPSPAWN_CHECK(buffLen >= sizeof(client->property), LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
return false, "ReceiveRequestData: Invalid buffLen %u", buffLen);
int ret = memcpy_s(&client->property, sizeof(client->property), buffer, sizeof(client->property));
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
return false, "ReceiveRequestData: memcpy failed %d:%u", ret, buffLen);
// reset hspList
client->property.hspList.savedLength = 0;
client->property.hspList.data = NULL;
// update buffer
buffer += sizeof(client->property);
buffLen -= sizeof(client->property);
}
// 2. check whether hspList exist
if (client->property.hspList.totalLength == 0) { // no hspList
APPSPAWN_LOGI("ReceiveRequestData: no hspList");
return true;
} else if (buffLen == 0) {
APPSPAWN_LOGI("ReceiveRequestData: waiting for hspList");
return false;
}
// 3. save HspList
HspList *hspList = &client->property.hspList;
if (hspList->savedLength == 0) {
hspList->data = (char *)malloc(hspList->totalLength);
APPSPAWN_CHECK(hspList->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
FreeHspList(client); return false, "ReceiveRequestData: malloc hspList failed");
}
uint32_t saved = hspList->savedLength;
uint32_t total = hspList->totalLength;
char *data = hspList->data;
APPSPAWN_LOGI("ReceiveRequestData: receiving hspList: (%u saved + %u incoming) / %u total", saved, buffLen, total);
APPSPAWN_CHECK((total - saved) >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
FreeHspList(client); return false, "ReceiveRequestData: too many data for hspList %u ", buffLen);
int ret = memcpy_s(data + saved, buffLen, buffer, buffLen);
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); FreeHspList(client);
return false, "ReceiveRequestData: memcpy hspList failed");
hspList->savedLength += buffLen;
if (hspList->savedLength < hspList->totalLength) {
return false;
}
hspList->data[hspList->totalLength - 1] = 0;
return true;
}
static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
{
APPSPAWN_CHECK(buffer != NULL && buffLen >= sizeof(AppParameter), LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
return, "Invalid buffLen %u", buffLen);
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle);
APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
return, "alloc client Failed");
int ret = memcpy_s(&appProperty->property, sizeof(appProperty->property), buffer, buffLen);
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); return, "Invalid buffLen %u", buffLen);
if (!ReceiveRequestData(taskHandle, appProperty, buffer, buffLen)) {
return;
}
#ifdef NWEB_SPAWN
// get render process termination status, only nwebspawn need this logic.
@ -341,7 +413,7 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
#endif
APPSPAWN_CHECK(appProperty->property.gidCount <= APP_MAX_GIDS && strlen(appProperty->property.processName) > 0,
LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
LE_CloseTask(LE_GetDefaultLoop(), taskHandle); FreeHspList(appProperty);
return, "Invalid property %u", appProperty->property.gidCount);
// special handle bundle name medialibrary and scanner
HandleSpecial(appProperty);
@ -356,6 +428,7 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
if (pipe(appProperty->fd) == -1) {
APPSPAWN_LOGE("create pipe fail, errno = %d", errno);
LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
FreeHspList(appProperty);
return;
}
@ -383,6 +456,7 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
} else {
SendResponse(appProperty, (char *)&result, sizeof(result));
}
FreeHspList(appProperty);
}
APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags)
@ -418,6 +492,9 @@ APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskH
client->client.flags = 0;
client->setAllowInternet = 0;
client->allowInternet = 1;
client->property.hspList.totalLength = 0;
client->property.hspList.savedLength = 0;
client->property.hspList.data = NULL;
APPSPAWN_LOGI("OnConnection client fd %d Id %d", LE_GetSocketFd(stream), client->client.id);
return stream;
}

View File

@ -41,7 +41,9 @@ extern "C" {
#define START_INDEX 1
#define FD_INDEX 2
#define PARAM_INDEX 3
#define NULL_INDEX 4
#define HSP_LIST_LEN_INDEX 4
#define HSP_LIST_INDEX 5
#define NULL_INDEX 6
#define PARAM_BUFFER_LEN 128
typedef struct {
AppSpawnClient client;

View File

@ -1084,4 +1084,203 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_33, TestSize.Level0)
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path6);
SUCCEED();
}
/**
* @tc.name: App_Spawn_Sandbox_34
* @tc.desc: parse and mount HspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_34, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_34 start";
ClientSocket::AppProperty *m_appProperty = GetAppProperty();
const char *strl1 = "/mnt/sandbox/test.bundle1";
std::string testBundle = strl1;
{ // totalLength is 0
m_appProperty->hspList = {};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_EQ(0, ret);
}
{ // data is nullptr
m_appProperty->hspList = {1, 0, nullptr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_EQ(0, ret);
}
{ // success
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_EQ(0, ret);
}
m_appProperty->hspList = {};
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_34 end";
}
/**
* @tc.name: App_Spawn_Sandbox_35
* @tc.desc: validate json format of HspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_35, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_35 start";
ClientSocket::AppProperty *m_appProperty = GetAppProperty();
const char *strl1 = "/mnt/sandbox/test.bundle1";
std::string testBundle = strl1;
{ // invalid json
char hspListStr[] = "{";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // no bundles
char hspListStr[] = "{ \
\"modules\":[\"module1\", \"module2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // no modules
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // no versions
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // list size not same
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // value type is not arrary
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\": 1001 \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // element type is not string
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\": [1001, 1002] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // element type is not same, string + number
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\": [\"v10001\", 1002] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // element type is not same, number + string
char hspListStr[] = "{ \
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\": [1001, \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
m_appProperty->hspList = {};
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_35 end";
}
/**
* @tc.name: App_Spawn_Sandbox_36
* @tc.desc: validate bundlemodule and version in hspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_36, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_36 start";
ClientSocket::AppProperty *m_appProperty = GetAppProperty();
const char *strl1 = "/mnt/sandbox/test.bundle1";
std::string testBundle = strl1;
{ // empty name
char hspListStr[] = "{ \
\"bundles\":[\"\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // name is .
char hspListStr[] = "{ \
\"bundles\":[\".\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // name is ..
char hspListStr[] = "{ \
\"bundles\":[\"..\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
{ // name contains /
char hspListStr[] = "{ \
\"bundles\":[\"test/bundle1\", \"test.bundle2\"], \
\"modules\":[\"module1\", \"module2\"], \
\"versions\":[\"v10001\", \"v10002\"] \
}";
m_appProperty->hspList = {strlen(hspListStr), 0, hspListStr};
int ret = OHOS::AppSpawn::SandboxUtils::MountAllHsp(m_appProperty, testBundle);
EXPECT_NE(0, ret);
}
m_appProperty->hspList = {};
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_36 end";
}
} // namespace OHOS

View File

@ -43,6 +43,8 @@ using nlohmann::json;
extern "C" {
#endif
TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags);
bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *appProperty,
const uint8_t *buffer, uint32_t buffLen);
void AddAppInfo(pid_t pid, const char *processName);
void ProcessTimer(const TimerHandle taskHandle, void *context);
void SignalHandler(const struct signalfd_siginfo *siginfo);
@ -75,6 +77,15 @@ int32_t TestSetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClie
{
return 0;
}
static void FreeHspList(HspList &hspList)
{
if (hspList.data != nullptr) {
free(hspList.data);
}
hspList = {};
}
/**
* @tc.name: App_Spawn_Standard_002
* @tc.desc: fork app son process and set content.
@ -112,6 +123,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_002, TestSize.Level0)
if (strcpy_s(client->property.renderCmd, APP_RENDER_CMD_MAX_LEN, "xxx") != 0) {
GTEST_LOG_(INFO) << "strcpy_s failed";
}
client->property.hspList = {0, 0, NULL};
AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", longProcName, longProcNameLen, 1);
content->loadExtendLib = LoadExtendLib;
@ -185,6 +197,97 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003, TestSize.Level0)
GTEST_LOG_(INFO) << "App_Spawn_Standard_003 end";
}
/**
* @tc.name: App_Spawn_Standard_003_1
* @tc.desc: Verify set Arg if GetAppSpawnClient succeed, with HspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_1, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_003_1 start";
AppSpawnClientExt client = {};
char arg1[] = "/system/bin/appspawn";
char arg2[] = "cold-start";
char arg3[] = "1";
{
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg5[] = "10";
char arg6[] = "012345678";
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(0, GetAppSpawnClientFromArg(argc, argv, &client));
FreeHspList(client.property.hspList);
}
{ // hsp length is 0
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg5[] = "0";
char* argv[] = {arg1, arg2, arg3, arg4, arg5, nullptr};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(0, GetAppSpawnClientFromArg(argc, argv, &client));
}
{ // hsp length is null
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg6[] = "0123456789";
char* argv[] = {arg1, arg2, arg3, arg4, nullptr, arg6};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
}
{ // hsp length is non-zero, but argc is 5
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg5[] = "10";
char* argv[] = {arg1, arg2, arg3, arg4, arg5};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
}
{ // hsp length is non-zero, but content is null
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg5[] = "10";
char* argv[] = {arg1, arg2, arg3, arg4, arg5, nullptr};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
}
GTEST_LOG_(INFO) << "App_Spawn_Standard_003_1 end";
}
/**
* @tc.name: App_Spawn_Standard_003_2
* @tc.desc: Verify set Arg if GetAppSpawnClient succeed, wrong HspList length
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_2, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_003_2 start";
AppSpawnClientExt client = {};
char arg1[] = "/system/bin/appspawn";
char arg2[] = "cold-start";
char arg3[] = "1";
{ // actual data is shorter than totalLength
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg5[] = "10";
char arg6[] = "01234";
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(0, GetAppSpawnClientFromArg(argc, argv, &client));
FreeHspList(client.property.hspList);
}
{ // actual data is longer than totalLength
char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default";
char arg5[] = "5";
char arg6[] = "0123456789";
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6};
int argc = sizeof(argv)/sizeof(argv[0]);
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
FreeHspList(client.property.hspList);
}
GTEST_LOG_(INFO) << "App_Spawn_Standard_003_2 end";
}
/**
* @tc.name: App_Spawn_Standard_004
* @tc.desc: App cold start.
@ -473,6 +576,170 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_07, TestSize.Level0)
GTEST_LOG_(INFO) << "App_Spawn_Standard_07 end";
}
/**
* @tc.name: App_Spawn_Standard_08
* @tc.desc: verify receive hspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_08, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_08 start";
AppSpawnClientExt client = {};
AppParameter param = {};
{ // buff is null
bool ret = ReceiveRequestData(nullptr, &client, nullptr, sizeof(param));
EXPECT_FALSE(ret);
}
{ // buffLen is 0
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)&param, 0);
EXPECT_FALSE(ret);
}
{ // buffLen < sizeof(AppParameter)
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)&param, sizeof(param) - 1);
EXPECT_FALSE(ret);
}
{ // no HspList
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)&param, sizeof(param));
EXPECT_TRUE(ret);
}
GTEST_LOG_(INFO) << "App_Spawn_Standard_08 end";
}
/**
* @tc.name: App_Spawn_Standard_08_1
* @tc.desc: receive AppParameter and HspList separately
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_08_1, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_1 start";
AppSpawnClientExt client = {};
AppParameter param = {};
// send AppParameter
char hspListStr[] = "01234";
param.hspList = {sizeof(hspListStr), 0, nullptr};
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)&param, sizeof(param));
EXPECT_FALSE(ret);
// send HspList
ret = ReceiveRequestData(nullptr, &client, (uint8_t *)hspListStr, sizeof(hspListStr));
EXPECT_TRUE(ret);
EXPECT_EQ(0, strcmp(hspListStr, client.property.hspList.data));
FreeHspList(client.property.hspList);
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_1 end";
}
/**
* @tc.name: App_Spawn_Standard_08_2
* @tc.desc: receive AppParameter and HspList together
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_08_2, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_2 start";
AppSpawnClientExt client = {};
AppParameter param = {};
// put AppParameter and HspList together
char hspListStr[] = "01234";
char buff[sizeof(param) + sizeof(hspListStr)];
param.hspList = {sizeof(hspListStr), 0, nullptr};
int res = memcpy_s(buff, sizeof(param), (void *)&param, sizeof(param));
EXPECT_EQ(0, res);
res = memcpy_s(buff + sizeof(param), sizeof(hspListStr), (void *)hspListStr, sizeof(hspListStr));
EXPECT_EQ(0, res);
// send
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)buff, sizeof(buff));
EXPECT_TRUE(ret);
EXPECT_EQ(0, strcmp(hspListStr, client.property.hspList.data));
FreeHspList(client.property.hspList);
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_2 end";
}
/**
* @tc.name: App_Spawn_Standard_08_3
* @tc.desc: receive AppParameter and part of HspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_08_3, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_3 start";
AppSpawnClientExt client = {};
AppParameter param = {};
const uint32_t splitLen = 3;
// put AppParameter and part of HspList together
char hspListStr[] = "0123456789";
char buff[sizeof(param) + splitLen];
param.hspList = {sizeof(hspListStr), 0, hspListStr};
int res = memcpy_s(buff, sizeof(param), (void *)&param, sizeof(param));
EXPECT_EQ(0, res);
res = memcpy_s(buff + sizeof(param), splitLen, (void *)hspListStr, splitLen);
EXPECT_EQ(0, res);
// send AppParameter and part of HspList
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)buff, sizeof(buff));
EXPECT_FALSE(ret);
// send left HspList
ret = ReceiveRequestData(nullptr, &client, (uint8_t *)hspListStr + splitLen, sizeof(hspListStr) - splitLen);
EXPECT_TRUE(ret);
EXPECT_EQ(0, strcmp(hspListStr, client.property.hspList.data));
FreeHspList(client.property.hspList);
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_3 end";
}
/**
* @tc.name: App_Spawn_Standard_08_4
* @tc.desc: receive AppParameter and splited HspList
* @tc.type: FUNC
* @tc.require:issueI6798L
* @tc.author:
*/
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_08_4, TestSize.Level0)
{
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_4 start";
AppSpawnClientExt client = {};
AppParameter param = {};
const uint32_t splitLen = 3;
uint32_t sentLen = 0;
// send AppParameter
char hspListStr[] = "0123456789";
param.hspList = {sizeof(hspListStr), 0, nullptr};
bool ret = ReceiveRequestData(nullptr, &client, (uint8_t *)&param, sizeof(param));
EXPECT_FALSE(ret);
// send splited HspList
ret = ReceiveRequestData(nullptr, &client, (uint8_t *)hspListStr + sentLen, splitLen);
sentLen += splitLen;
EXPECT_FALSE(ret);
ret = ReceiveRequestData(nullptr, &client, (uint8_t *)hspListStr + sentLen, splitLen);
sentLen += splitLen;
EXPECT_FALSE(ret);
ret = ReceiveRequestData(nullptr, &client, (uint8_t *)hspListStr + sentLen, sizeof(hspListStr) - sentLen);
EXPECT_TRUE(ret);
EXPECT_EQ(0, strcmp(hspListStr, client.property.hspList.data));
FreeHspList(client.property.hspList);
GTEST_LOG_(INFO) << "App_Spawn_Standard_08_4 end";
}
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_ReportEvent, TestSize.Level0)
{
ReportProcessExitInfo(nullptr, 100, 100, 0);

View File

@ -54,6 +54,7 @@ private:
static int32_t SetPrivateAppSandboxProperty(const ClientSocket::AppProperty *appProperty);
static int32_t SetCommonAppSandboxProperty(const ClientSocket::AppProperty *appProperty,
std::string &sandboxPackagePath);
static int32_t MountAllHsp(const ClientSocket::AppProperty *appProperty, std::string &sandboxPackagePath);
static int32_t DoSandboxRootFolderCreateAdapt(std::string &sandboxPackagePath);
static int32_t DoSandboxRootFolderCreate(const ClientSocket::AppProperty *appProperty,
std::string &sandboxPackagePath);

View File

@ -50,6 +50,7 @@ namespace {
constexpr std::string_view APL_SYSTEM_BASIC("system_basic");
const std::string g_packageItems[] = {{"cache"}, {"files"}, {"temp"}, {"preferences"}, {"haps"}};
const std::string g_physicalAppInstallPath = "/data/app/el1/bundle/public/";
const std::string g_sandboxHspInstallPath = "/data/storage/el1/bundle/";
const std::string g_sandBoxAppInstallPath = "/data/accounts/account_0/applications/";
const std::string g_dataBundles = "/data/bundles/";
const std::string g_userId = "<currentUserId>";
@ -60,6 +61,9 @@ namespace {
const std::string g_sbxSwitchCheck = "ON";
const std::string g_dlpBundleName = "com.ohos.dlpmanager";
const std::string g_internal = "__internal__";
const std::string g_hspList_key_bundles = "bundles";
const std::string g_hspList_key_modules = "modules";
const std::string g_hspList_key_versions = "versions";
const char *g_actionStatuc = "check-action-status";
const char *g_accountPrefix = "/account/data/";
const char *g_accountNonPrefix = "/non_account/data/";
@ -779,6 +783,9 @@ int32_t SandboxUtils::SetCommonAppSandboxProperty(const ClientSocket::AppPropert
ret = SetCommonAppSandboxProperty_(appProperty, productConfig);
APPSPAWN_CHECK(ret == 0, return ret, "parse product config for common failed, %s", sandboxPackagePath.c_str());
ret = MountAllHsp(appProperty, sandboxPackagePath);
APPSPAWN_CHECK(ret == 0, return ret, "mount hspList failed, %s", sandboxPackagePath.c_str());
if (strcmp(appProperty->apl, APL_SYSTEM_BASIC.data()) == 0 ||
strcmp(appProperty->apl, APL_SYSTEM_CORE.data()) == 0) {
// need permission check for system app here
@ -790,6 +797,48 @@ int32_t SandboxUtils::SetCommonAppSandboxProperty(const ClientSocket::AppPropert
return 0;
}
static inline bool CheckPath(const std::string& name)
{
return !name.empty() && name != "." && name != ".." && name.find("/") == std::string::npos;
}
int32_t SandboxUtils::MountAllHsp(const ClientSocket::AppProperty *appProperty, std::string &sandboxPackagePath)
{
int ret = 0;
if (appProperty->hspList.totalLength == 0 || appProperty->hspList.data == nullptr) {
return ret;
}
nlohmann::json hsps = nlohmann::json::parse(appProperty->hspList.data, nullptr, false);
APPSPAWN_CHECK(!hsps.is_discarded() && hsps.contains(g_hspList_key_bundles) && hsps.contains(g_hspList_key_modules)
&& hsps.contains(g_hspList_key_versions), return -1, "MountAllHsp: json parse failed");
nlohmann::json& bundles = hsps[g_hspList_key_bundles];
nlohmann::json& modules = hsps[g_hspList_key_modules];
nlohmann::json& versions = hsps[g_hspList_key_versions];
APPSPAWN_CHECK(bundles.is_array() && modules.is_array() && versions.is_array() && bundles.size() == modules.size()
&& bundles.size() == versions.size(), return -1, "MountAllHsp: value is not arrary or sizes are not same");
APPSPAWN_LOGI("MountAllHsp: app = %s, cnt = %u", appProperty->bundleName, bundles.size());
for (uint32_t i = 0; i < bundles.size(); i++) {
// elements in json arrary can be different type
APPSPAWN_CHECK(bundles[i].is_string() && modules[i].is_string() && versions[i].is_string(),
return -1, "MountAllHsp: element type error");
std::string libBundleName = bundles[i];
std::string libModuleName = modules[i];
std::string libVersion = versions[i];
APPSPAWN_CHECK(CheckPath(libBundleName) && CheckPath(libModuleName) && CheckPath(libVersion),
return -1, "MountAllHsp: path error");
std::string libPhysicalPath = g_physicalAppInstallPath + libBundleName + "/" + libVersion + "/" + libModuleName;
std::string mntPath = sandboxPackagePath + g_sandboxHspInstallPath + libBundleName + "/" + libModuleName;
ret = DoAppSandboxMountOnce(libPhysicalPath.c_str(), mntPath.c_str(), "", BASIC_MOUNT_FLAGS, nullptr);
APPSPAWN_CHECK(ret == 0, return ret, "mount library failed %d", ret);
}
return ret;
}
int32_t SandboxUtils::DoSandboxRootFolderCreateAdapt(std::string &sandboxPackagePath)
{
#ifndef APPSPAWN_TEST