add JIT permission

Signed-off-by: wangfeng <wangfeng277@huawei.com>
This commit is contained in:
wangfeng 2024-11-02 15:40:26 +08:00
parent 16aace03a1
commit c9de611063
10 changed files with 319 additions and 137 deletions

View File

@ -65,28 +65,6 @@ void exit(int code)
}
#endif
#ifdef USE_ENCAPS
#include <sys/ioctl.h>
#define OH_ENCAPS_PROC_TYPE_BASE 0x18
#define OH_ENCAPS_MAGIC 'E'
#define OH_PROC_APP 4
#define SET_PROC_TYPE_CMD _IOW(OH_ENCAPS_MAGIC, OH_ENCAPS_PROC_TYPE_BASE, uint32_t)
static void SetEncapsFlag(int fdEncaps, uint32_t flag)
{
if (fdEncaps < -1) {
APPSPAWN_LOGE("AppSpawnChild SetEncapsFlag failed, fdEncaps < -1");
return;
}
int ret = ioctl(fdEncaps, SET_PROC_TYPE_CMD, &flag);
if (ret != 0) {
APPSPAWN_LOGE("AppSpawnChild SetEncapsFlag failed");
}
close(fdEncaps);
}
#endif
int AppSpawnChild(AppSpawnContent *content, AppSpawnClient *client)
{
APPSPAWN_CHECK(content != NULL && client != NULL, return -1, "Invalid arg for appspawn child");
@ -106,9 +84,7 @@ int AppSpawnChild(AppSpawnContent *content, AppSpawnClient *client)
}
APPSPAWN_LOGW("AppSpawnChild cold start fail %{public}u", client->id);
}
#ifdef USE_ENCAPS
SetEncapsFlag(content->fdEncaps, OH_PROC_APP);
#endif
StartAppspawnTrace("AppSpawnExecuteSpawningHook");
ret = AppSpawnExecuteSpawningHook(content, client);
FinishAppspawnTrace();

View File

@ -62,9 +62,6 @@ typedef struct AppSpawnContent {
uint32_t sandboxNsFlags;
int wdgOpened;
bool isLinux;
#ifdef USE_ENCAPS
int fdEncaps;
#endif
int sandboxType;
RunMode mode;
#ifndef OHOS_LITE

View File

@ -276,6 +276,7 @@ int AppSpawnClientAddPermission(AppSpawnClientHandle handle, AppSpawnReqMsgHandl
#define MSG_EXT_NAME_PROCESS_TYPE "ProcessType"
#define MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX "MaxChildProcess"
#define MSG_EXT_NAME_APP_FD "AppFd"
#define MSG_EXT_NAME_JIT_PERMISSIONS "JITPermissions"
int AppSpawnReqMsgAddExtInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const uint8_t *value, uint32_t valueLen);

View File

@ -22,6 +22,9 @@ ohos_shared_library("appspawn_common") {
"appspawn_namespace.c",
"appspawn_silk.c",
]
if (appspawn_use_encaps == true) {
sources += [ "appspawn_encaps.c" ]
}
if (is_debug || build_variant == "root") {
sources += [ "appspawn_begetctl.c" ]
}

View File

@ -46,7 +46,6 @@
#include "init_param.h"
#include "parameter.h"
#include "securec.h"
#include "cJSON.h"
#ifdef CODE_SIGNATURE_ENABLE // for xpm
#include "code_sign_attr_utils.h"
@ -392,76 +391,6 @@ static void SpawnLoadSilk(const AppSpawnMgr *content, const AppSpawningCtx *prop
LoadSilkLibrary(processName);
}
#define APP_PIDS_MAX_ENCAPS "encaps"
#define APP_PIDS_MAX_OHOS_ENCAPS_COUNT_KEY "ohos.encaps.count"
#define APP_PIDS_MAX_OHOS_ENCAPS_FORK_KEY "ohos.encaps.fork.count"
#define APP_PIDS_MAX_OHOS_ENCAPS_COUNT_VALUE 1
#define MSG_EXT_NAME_MAX_DECIMAL 10
#define ASSICN_ENCAPS_CMD _IOW('E', 0x1A, char *)
static int SpawnSetEncaps(AppSpawnMgr *content, AppSpawningCtx *property)
{
int ret = 0;
char *pidMaxStr = NULL;
uint32_t len = 0;
pidMaxStr = GetAppPropertyExt(property, MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX, &len);
APPSPAWN_CHECK_ONLY_EXPER(pidMaxStr != NULL, return ret);
uint32_t max = 0;
if (len != 0) {
char *endPtr = NULL;
max = strtoul(pidMaxStr, &endPtr, MSG_EXT_NAME_MAX_DECIMAL);
if (endPtr == pidMaxStr || *endPtr != '\0') {
APPSPAWN_LOGE("pidMaxStr: %{public}s Data errors", endPtr);
return ret;
}
}
cJSON *encaps = cJSON_CreateObject();
APPSPAWN_CHECK(encaps != NULL, return ret, "Failed to create encaps json object");
cJSON *addGinseng = cJSON_CreateObject();
if (addGinseng == NULL) {
cJSON_Delete(encaps);
encaps = NULL;
APPSPAWN_LOGE("Failed to create addGinseng json object");
return ret;
}
cJSON_AddNumberToObject(encaps, APP_PIDS_MAX_OHOS_ENCAPS_COUNT_KEY,
APP_PIDS_MAX_OHOS_ENCAPS_COUNT_VALUE);
cJSON_AddNumberToObject(encaps, APP_PIDS_MAX_OHOS_ENCAPS_FORK_KEY, max);
cJSON_AddItemToObject(addGinseng, APP_PIDS_MAX_ENCAPS, encaps);
char *maxPid = cJSON_PrintUnformatted(addGinseng);
int fd = 0;
fd = open("dev/encaps", O_RDWR);
if (fd < 0) {
APPSPAWN_LOGW("Failed to open encaps fd for bundleName:%{public}s errno:%{public}d",
GetBundleName(property), errno);
goto EXIT;
}
ret = ioctl(fd, ASSICN_ENCAPS_CMD, maxPid);
APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Encaps the setup failed ret:%{public}d fd:%{public}d maxPid: %{public}s",
ret, fd, maxPid);
close(fd);
EXIT:
free(maxPid);
maxPid = NULL;
cJSON_Delete(addGinseng);
encaps = NULL;
addGinseng = NULL;
return ret;
}
static int SpawnSetCommonProperties(AppSpawnMgr *content, AppSpawningCtx *property)
{
if (IsNWebSpawnMode(content)) {
return 0;
}
uint32_t len = 0;
char *processType = (char *)(GetAppSpawnMsgExtInfo(property->message, MSG_EXT_NAME_PROCESS_TYPE, &len));
if (processType != NULL && strcmp(processType, "gpu") == 0) {
return 0;
}
int ret = SpawnSetEncaps(content, property);
return ret;
}
static int SpawnSetProperties(AppSpawnMgr *content, AppSpawningCtx *property)
{
APPSPAWN_LOGV("Spawning: set child property");
@ -615,7 +544,6 @@ MODULE_CONSTRUCTOR(void)
AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv);
AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv);
AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnSetIntPermission);
AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_COMMON, SpawnSetCommonProperties);
AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties);
AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete);
AddAppSpawnHook(STAGE_PARENT_POST_FORK, HOOK_PRIO_HIGHEST, CloseFdArgs);

View File

@ -0,0 +1,304 @@
/*
* Copyright (c) 2024 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.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "securec.h"
#include "cJSON.h"
#include "appspawn_adapter.h"
#include "appspawn_hook.h"
#include "appspawn_manager.h"
#include "appspawn_utils.h"
#define APP_ENCAPS "encaps"
#define APP_OHOS_ENCAPS_COUNT_KEY "ohos.encaps.count"
#define APP_OHOS_ENCAPS_FORK_KEY "ohos.encaps.fork.count"
#define MSG_EXT_NAME_MAX_DECIMAL 10
#define OH_APP_MAX_PIDS_NUM 512
#define OH_ENCAPS_PROC_TYPE_BASE 0x18
#define OH_ENCAPS_PERMISSION_TYPE_BASE 0x1A
#define OH_ENCAPS_MAGIC 'E'
#define OH_PROC_HAP 4
#define OH_ENCAPS_DEFAULT_FLAG 0
#define OH_ENCAPS_DEFAULT_STR ""
#define SET_ENCAPS_PROC_TYPE_CMD _IOW(OH_ENCAPS_MAGIC, OH_ENCAPS_PROC_TYPE_BASE, uint32_t)
#define SET_ENCAPS_PERMISSION_TYPE_CMD _IOW(OH_ENCAPS_MAGIC, OH_ENCAPS_PERMISSION_TYPE_BASE, char *)
typedef enum {
ENCAPS_PROC_TYPE_MODE, // enable the encaps attribute of a process
ENCAPS_PERMISSION_TYPE_MODE, // set the encaps permission of a process
ENCAPS_MAX_TYPE_MODE
} AppSpawnEncapsBaseType;
static int OpenEncapsFile(void)
{
int fd = 0;
fd = open("dev/encaps", O_RDWR);
if (fd < 0) {
APPSPAWN_LOGW("Failed to open encaps file errno: %{public}d", errno);
}
return fd;
}
static int WriteEncapsInfo(int fd, AppSpawnEncapsBaseType encapsType, const char *encapsInfo, uint32_t flag)
{
if (encapsInfo == NULL) {
return APPSPAWN_ARG_INVALID;
}
APPSPAWN_LOGV("root object: %{public}s", encapsInfo);
int ret = 0;
switch (encapsType) {
case ENCAPS_MAX_TYPE_MODE:
ret = ioctl(fd, SET_ENCAPS_PROC_TYPE_CMD, &flag);
break;
case ENCAPS_PERMISSION_TYPE_MODE:
ret = ioctl(fd, SET_ENCAPS_PERMISSION_TYPE_CMD, encapsInfo);
break;
default:
break;
}
if (ret != 0) {
APPSPAWN_LOGE("Encaps the setup failed ret: %{public}d fd: %{public}d maxPid: %{public}s", ret, fd, encapsInfo);
return ret;
}
return 0;
}
APPSPAWN_STATIC int EnableEncapsForProc(int encapsFileFd)
{
uint32_t flag = OH_PROC_APP;
return WriteEncapsInfo(encapsFileFd, ENCAPS_PROC_TYPE_MODE, OH_ENCAPS_DEFAULT_STR, flag);
}
static uint32_t SpawnGetMaxPids(AppSpawnMgr *content, AppSpawningCtx *property)
{
uint32_t len = 0;
char *pidMaxStr = GetAppPropertyExt(property, MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX, &len);
APPSPAWN_CHECK_ONLY_EXPER(pidMaxStr != NULL, return 0);
uint32_t maxNum = 0;
// string convert to value
if (len != 0) {
char *endPtr = NULL;
maxNum = strtoul(pidMaxStr, &endPtr, MSG_EXT_NAME_MAX_DECIMAL);
if (endPtr == pidMaxStr || *endPtr != '\0') {
APPSPAWN_LOGW("Failed to convert a character string to a value.(ignore), endPtr: %{public}s", endPtr);
return 0;
}
return maxNum;
}
return 0;
}
/* set ohos.encaps.fork.count to encaps */
static int SpawnSetMaxPids(AppSpawnMgr *content, AppSpawningCtx *property, cJSON *encaps)
{
uint32_t maxPidCount = SpawnGetMaxPids(content, property);
if (maxPidCount == 0 || maxPidCount > OH_APP_MAX_PIDS_NUM) {
APPSPAWN_LOGV("Don't need to set pid max count. Use default pid max");
return APPSPAWN_PIDMGR_DEFAULT_PID_MAX;
}
if (cJSON_AddNumberToObject(encaps, APP_OHOS_ENCAPS_COUNT_KEY, maxPidCount) == NULL) {
APPSPAWN_LOGV("Add number to object failed.(ignore)");
return APPSPAWN_PIDMGR_DEFAULT_PID_MAX;
}
return 0;
}
static inline cJSON *GetJsonObjFromExtInfo(const AppSpawningCtx *property, const char *name)
{
uint32_t size = 0;
char *extInfo = (char *)(GetAppSpawnMsgExtInfo(property->message, name, &size));
if (size == 0 || extInfo == NULL) {
return NULL;
}
APPSPAWN_LOGV("Get json name %{public}s value %{public}s", name, extInfo);
cJSON *extInfoJson = cJSON_Parse(extInfo); // need to free
APPSPAWN_CHECK(extInfoJson != NULL, return NULL, "Invalid ext info %{public}s for %{public}s", extInfo, name);
return extInfoJson;
}
static int AddJITPermissionToEncaps(cJSON *extInfoJson, cJSON *encaps, uint32_t *permissionCount)
{
// Get ohos.encaps.count
cJSON *countJson = cJSON_GetObjectItem(extInfoJson, "ohos.encaps.count");
int encapsCount = 0;
if (cJSON_IsNumber(countJson)) {
encapsCount = countJson->valueint;
}
// Check input count and permissions size
cJSON *permissions = cJSON_GetObjectItemCaseSensitive(extInfoJson, "permissions");
int count = cJSON_GetArraySize(permissions);
if (encapsCount != count) {
APPSPAWN_LOGE("Invalid args, encaps count: %{public}d, permission count: %{public}d", encapsCount, count);
return APPSPAWN_ARG_INVALID;
}
// If permissionName is obtained, it needs to be written in the format of ["permissionName: "true""] in the encaps
for (int i = 0; i < count; i++) {
char *permissionName = cJSON_GetStringValue(cJSON_GetArrayItem(permissions, i));
if (cJSON_AddStringToObject(encaps, permissionName, "true") == NULL) {
APPSPAWN_LOGV("Add permission to object failed.(ignore)");
return APPSPAWN_ERROR_UTILS_ADD_JSON_FAIL;
}
}
*permissionCount += count;
return 0;
}
static int SpawnSetJITPermissions(AppSpawnMgr *content, AppSpawningCtx *property, cJSON *encaps, uint32_t *count)
{
cJSON *extInfoJson = GetJsonObjFromExtInfo(property, MSG_EXT_NAME_JIT_PERMISSIONS);
if (extInfoJson == NULL) {
return APPSPAWN_ARG_INVALID;
}
int ret = AddJITPermissionToEncaps(extInfoJson, encaps, count);
if (ret != 0) {
APPSPAWN_LOGW("Add permission to object failed.(ignore), ret: %{public}d", ret);
}
cJSON_Delete(extInfoJson);
return ret;
}
static int AddMembersToEncaps(AppSpawnMgr *content, AppSpawningCtx *property, CJSON *encaps)
{
uint32_t encapsPermissionCount = 0;
// need set ohos.encaps.count to encaps firstly
if (cJSON_AddNumberToObject(encaps, APP_OHOS_ENCAPS_COUNT_KEY, encapsPermissionCount) == NULL) {
APPSPAWN_LOGV("Set ohos.encaps.count to object failed.(ignore)");
return APPSPAWN_ERROR_UTILS_ADD_JSON_FAIL;
}
int ret = SpawnSetMaxPids(content, property, encaps);
if (ret != 0) {
APPSPAWN_LOGV("Can't set max pids to encaps object.(ignore), ret: %{public}d", ret);
} else {
encapsPermissionCount += 1;
}
uint32_t count = 0;
ret = SpawnSetJITPermissions(content, property, encaps, &count);
if (ret != 0) {
APPSPAWN_LOGV("Can't set JIT permission to encaps object.(ignore), ret: %{public}d", ret);
} else {
encapsPermissionCount += count;
}
if (encapsPermissionCount == 0) {
return APPSPAWN_ERROR_UTILS_ADD_JSON_FAIL; // Don't need set permission
}
cJSON *encapsCountItem = cJSON_GetObjectItem(encaps, APP_OHOS_ENCAPS_COUNT_KEY);
if (encapsCountItem != NULL) {
cJSON_SetNumberValue(encapsCountItem, encapsPermissionCount);
}
return 0;
}
static int SpawnBuildEncaps(AppSpawnMgr *content, AppSpawningCtx *property, char **encapsInfoStr)
{
// Create root object
cJSON *root = cJSON_CreateObject();
if (root == NULL) {
return APPSPAWN_ERROR_UTILS_CREATE_JSON_FAIL;
}
// Create encaps object
cJSON *encaps = cJSON_CreateObject();
if (encaps == NULL) {
cJSON_Delete(root);
return APPSPAWN_ERROR_UTILS_CREATE_JSON_FAIL;
}
int ret = AddMembersToEncaps(content, property, encaps);
if (ret != 0) {
APPSPAWN_LOGW("Add members to encaps object failed.(ignore), ret: %{public}d", ret);
cJSON_Delete(root);
cJSON_Delete(encaps);
return ret;
}
if (cJSON_AddItemToObject(root, APP_ENCAPS, encaps) != true) { // add encaps object to root
cJSON_Delete(root);
cJSON_Delete(encaps);
APPSPAWN_LOGW("Add encaps object to root failed.(ignore)");
return APPSPAWN_ERROR_UTILS_ADD_JSON_FAIL;
}
*encapsInfoStr = cJSON_PrintUnformatted(root); // need to free
if (*encapsInfoStr == NULL) {
cJSON_Delete(root);
return APPSPAWN_ERROR_UTILS_DECODE_JSON_FAIL;
}
cJSON_Delete(root);
return 0;
}
APPSPAWN_STATIC int SpawnSetEncapsPermissions(AppSpawnMgr *content, AppSpawningCtx *property)
{
if (content == NULL || property == NULL) {
return APPSPAWN_ARG_INVALID;
}
// The trustlist is used to control not appspawn
if (!IsAppSpawnMode(content)) {
return 0;
}
int encapsFileFd = OpenEncapsFile();
if (encapsFileFd <= 0) {
return 0; // Not support encaps ability
}
int ret = EnableEncapsForProc(encapsFileFd);
if (ret != 0) {
return 0; // Can't enable encaps ability
}
char *encapsInfoStr = NULL;
ret = SpawnBuildEncaps(content, property, &encapsInfoStr);
if (ret != 0) {
APPSPAWN_LOGW("Build encaps object failed, ret: %{public}d", ret);
return 0; // Can't set permission encpas ability
}
(void)WriteEncapsInfo(encapsFileFd, ENCAPS_PERMISSION_TYPE_MODE, encapsInfoStr, OH_ENCAPS_DEFAULT_FLAG);
if (encapsInfoStr != NULL) {
free(encapsInfoStr);
}
close(encapsFileFd);
return 0;
}
MODULE_CONSTRUCTOR(void)
{
AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_COMMON, SpawnSetEncapsPermissions);
}

View File

@ -183,6 +183,12 @@ APPSPAWN_INLINE int IsSpawnServer(const AppSpawnMgr *content)
return (content != NULL) && (content->servicePid == getpid());
}
APPSPAWN_INLINE int IsAppSpawnMode(const AppSpawnMgr *content)
{
return (content != NULL) &&
(content->content.mode == MODE_FOR_APP_SPAWN || content->content.mode == MODE_FOR_APP_COLD_RUN);
}
APPSPAWN_INLINE int IsNWebSpawnMode(const AppSpawnMgr *content)
{
return (content != NULL) &&

View File

@ -46,9 +46,6 @@
#ifdef APPSPAWN_HISYSEVENT
#include "appspawn_hisysevent.h"
#endif
#ifdef USE_ENCAPS
#include <sys/ioctl.h>
#endif
#define PARAM_BUFFER_SIZE 10
#define PATH_SIZE 256
#define FD_PATH_SIZE 128
@ -64,26 +61,6 @@ static void WaitChildDied(pid_t pid);
static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen);
static void ProcessRecvMsg(AppSpawnConnection *connection, AppSpawnMsgNode *message);
#ifdef USE_ENCAPS
static int OpenDevEncaps(void)
{
int fd = open("/dev/encaps", O_RDWR);
if (fd < 0) {
APPSPAWN_LOGE("AppSpawnChild SetEncapsFlag open failed");
return -1;
}
return fd;
}
static void CloseDevEncaps(int fd)
{
if (fd < 0) {
return;
}
close(fd);
}
#endif
// FD_CLOEXEC
static inline void SetFdCtrl(int fd, int opt)
{
@ -1056,9 +1033,6 @@ void AppSpawnDestroyContent(AppSpawnContent *content)
close(content->parentToChildFd[1]);
}
AppSpawnMgr *appSpawnContent = (AppSpawnMgr *)content;
#ifdef USE_ENCAPS
CloseDevEncaps(appSpawnContent->content.fdEncaps);
#endif
if (appSpawnContent->sigHandler != NULL && appSpawnContent->servicePid == getpid()) {
LE_CloseSignalTask(LE_GetDefaultLoop(), appSpawnContent->sigHandler);
}
@ -1208,9 +1182,6 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[])
(void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM);
}
#ifdef USE_ENCAPS
appSpawnContent->content.fdEncaps = OpenDevEncaps();
#endif
LE_RunLoop(LE_GetDefaultLoop());
APPSPAWN_LOGI("AppSpawnRun exit mode: %{public}d ", content->mode);

View File

@ -114,6 +114,10 @@ ohos_unittest("AppSpawn_ut") {
"${appspawn_path}/modules/sandbox/sandbox_manager.c",
]
if (appspawn_use_encaps == true) {
sources += [ "${appspawn_path}/modules/common/appspawn_encaps.c" ]
}
# add stub
include_dirs += [ "${appspawn_path}/test/mock" ]
sources += [

View File

@ -655,10 +655,6 @@ HWTEST_F(AppSpawnSandboxCoverageTest, DumpCurrentDir_7, TestSize.Level0)
EXPECT_NE(strstr(buffer, "Current path test_dir/sub_dir"), nullptr);
}
=======
<<<<<<< Updated upstream
=======
// 测试用例
HWTEST_F(AppSpawnSandboxCoverageTest, IsDeveloperModeOpen_01, TestSize.Level0)
{
@ -737,8 +733,4 @@ HWTEST_F(AppSpawnSandboxCoverageTest, GetSpawnTimeout_06, TestSize.Level0)
mockReturnValue = 1; // 模拟成功返回
EXPECT_EQ(GetSpawnTimeout(10), 20); // 期待返回 20
}
>>>>>>> Stashed changes
>>>>>>> Stashed changes
} // namespace OHOS