Yyhspm
2a89ce74创建于 28 天前历史提交
/*
 * 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.
 */

#ifndef APPSPAWN_MANAGER_H
#define APPSPAWN_MANAGER_H

#include <limits.h>
#include <stdbool.h>
#include <unistd.h>

#include "appspawn.h"
#include "appspawn_hook.h"
#include "appspawn_msg.h"
#include "appspawn_server.h"
#include "appspawn_utils.h"
#include "appspawn_fd_manager.h"  // Spawning FD type definitions and management APIs
#include "list.h"
#include "loop_event.h"
#ifdef APPSPAWN_HISYSEVENT
#include "hisysevent_adapter.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#define MODE_ID_INDEX 1
#define MODE_VALUE_INDEX 2
#define FD_ID_INDEX 3
#define FD_VALUE_INDEX 4
#define FLAGS_VALUE_INDEX 5
#define SHM_SIZE_INDEX 6
#define PARAM_ID_INDEX 7
#define PARAM_VALUE_INDEX 8
#define CLIENT_ID_INDEX 9
#define ARG_NULL 10

#define MAX_DIED_PROCESS_COUNT 5

#define INVALID_OFFSET 0xffffffff

#define APP_STATE_IDLE 1
#define APP_STATE_SPAWNING 2
#define APPSPAWN_MAX_TIME 3000000
#define UUID_MAX_LEN 37
#define PATH_MAX_LEN 256

#define APPSPAWN_INLINE __attribute__((always_inline)) inline

typedef struct AppSpawnContent AppSpawnContent;
typedef struct AppSpawnClient AppSpawnClient;
typedef struct TagAppSpawnConnection AppSpawnConnection;

typedef struct TagAppSpawnMsgNode {
    AppSpawnConnection *connection;
    AppSpawnMsg msgHeader;
    uint32_t tlvCount;
    uint32_t *tlvOffset;  // 记录属性的在msg中的偏移,不完全拷贝试消息完整
    uint8_t *buffer;
} AppSpawnMsgNode;

typedef struct {
    int32_t fd[2];  // 2 fd count
    WatcherHandle watcherHandle;
    WatcherHandle pidFdWatcherHandle;
    TimerHandle timer;
    char *childMsg;
    uint32_t msgSize;
    char *coldRunPath;
} AppSpawnForkCtx;

typedef struct TagAppSpawningCtx {
    AppSpawnClient client;
    struct ListNode node;
    AppSpawnForkCtx forkCtx;
    AppSpawnMsgNode *message;
    bool isPrefork;
    pid_t pid;
    int state;
    struct timespec spawnStart;
    bool allowDumpable;
    uint64_t checkPointId;        // Image process index ID
    uint8_t spmRefAdded;          // Bitmap: which SPM refcounts have been incremented
                                  //   bit0 (0x01): tokenid refcount
                                  //   bit1 (0x02): uid refcount
    bool lockBundleRefAdded;  // Flag: whether AddLockBundleRef has been called for _preunlock directory
    char *lockPath;           // Sandbox root path for _preunlock directory (set by MountDirToShared)
} AppSpawningCtx;

typedef struct TagAppSpawnedProcess {
    struct ListNode node;
    uid_t uid;
    pid_t pid;
    uint32_t max;
    int exitStatus;
    struct timespec spawnStart;
    struct timespec spawnEnd;
#ifdef DEBUG_BEGETCTL_BOOT
    AppSpawnMsgNode *message;
#endif
    bool isDebuggable;
    uint32_t appIndex;
    bool lockBundleRefAdded;  // Flag: whether AddLockBundleRef has been called for _preunlock directory
    char *lockPath;  // Sandbox root path for _preunlock directory management
    uint64_t tokenid;  // Token ID from message (for SPM refcount management)
    uint8_t spmRefAdded;  // Bitmap: which SPM refcounts have been incremented
                          //   bit0 (0x01): tokenid refcount
                          //   bit1 (0x02): uid refcount
    char name[0];
} AppSpawnedProcess;

/**
 * @brief Appspawn receives the request for starting an application from the client,
 *        and saves the image process information.
 * @param node Linked list head node.
 * @param uid User Id of the application process.
 * @param exitStatus Image process exit status.
 * @param appIndex AppIndex information of the application
 * @param checkPointId Check point id of the application image process.
 * @param name Hap name
 */
typedef struct {
    struct ListNode node;
    uid_t uid;
    int exitStatus;
    uint32_t appIndex;
    uint64_t checkPointId;
    char name[0];
} AppSpawnedCheckPointProcesses;

typedef struct SpawnTime {
    int minAppspawnTime;
    int maxAppspawnTime;
} SpawnTime;

typedef struct TagPathBuffer {
    uint32_t pathLen;
    char path[PATH_MAX_LEN];
} PathBuffer;

typedef struct TagDataGroupCtx {
    struct ListNode node;
    int gid;
    char dataGroupUuid[UUID_MAX_LEN];
    PathBuffer srcPath;
    PathBuffer destPath;
} DataGroupCtx;

typedef struct TagAppSpawnMgr {
    AppSpawnContent content;
    struct timespec perLoadStart;
    struct timespec perLoadEnd;
    struct SpawnTime spawnTime;
    uint32_t diedAppCount;
    uint32_t flags;
    pid_t servicePid;
    TaskHandle server;
    SignalHandle sigHandler;
    struct ListNode appQueue;           // save spawned app pid and name
    struct ListNode diedQueue;          // save died app pid and name
    struct ListNode appSpawnQueue;      // save spawning app pid and name
    struct ListNode extData;
    struct ListNode dataGroupCtxQueue;
    struct ListNode checkPointIdQueue;  // Image boot process queue
    struct ListNode spawningFdsQueue;
#ifdef APPSPAWN_HISYSEVENT
    AppSpawnHisyseventInfo *hisyseventInfo;
#endif
} AppSpawnMgr;

/**
 * @brief App Spawn Mgr object op
 *
 */
AppSpawnMgr *CreateAppSpawnMgr(int mode);
AppSpawnMgr *GetAppSpawnMgr(void);
void DeleteAppSpawnMgr(AppSpawnMgr *mgr);
AppSpawnContent *GetAppSpawnContent(void);

/**
 * @brief 孵化成功后进程或者app实例的操作
 *
 */
typedef void (*AppTraversal)(const AppSpawnMgr *mgr, AppSpawnedProcess *appInfo, void *data);
void TraversalSpawnedProcess(AppTraversal traversal, void *data);
AppSpawnedProcess *AddSpawnedProcess(pid_t pid, const char *processName, uint32_t appIndex,
    bool isDebuggable, uint64_t tokenid);
AppSpawnedProcess *GetSpawnedProcess(pid_t pid);
AppSpawnedProcess *GetSpawnedProcessByName(const char *name);
void TerminateSpawnedProcess(AppSpawnedProcess *node);

/**
 * @brief 孵化过程中的ctx对象的操作
 *
 */
typedef void (*ProcessTraversal)(const AppSpawnMgr *mgr, AppSpawningCtx *ctx, void *data);
void AppSpawningCtxTraversal(ProcessTraversal traversal, void *data);
AppSpawningCtx *GetAppSpawningCtxByPid(pid_t pid);
AppSpawningCtx *CreateAppSpawningCtx();
void DeleteAppSpawningCtx(AppSpawningCtx *property);
int KillAndWaitStatus(pid_t pid, int sig, int *exitStatus);

/**
 * @brief 消息解析、处理
 *
 */
void ProcessAppSpawnDumpMsg(const AppSpawnMsgNode *message);
int ProcessTerminationStatusMsg(const AppSpawnMsgNode *message, AppSpawnResult *result);

AppSpawnMsgNode *CreateAppSpawnMsg(void);
void DeleteAppSpawnMsg(AppSpawnMsgNode **msgNode);
int CheckAppSpawnMsg(const AppSpawnMsgNode *message);
int DecodeAppSpawnMsg(AppSpawnMsgNode *message);
int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen,
    AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder);
AppSpawnMsgNode *RebuildAppSpawnMsgNode(AppSpawnMsgNode *message, AppSpawnedProcess *appInfo);

/**
 * @brief 消息内容操作接口
 *
 */
void DumpAppSpawnMsg(const AppSpawnMsgNode *message);
void *GetAppSpawnMsgInfo(const AppSpawnMsgNode *message, int type);
void *GetAppSpawnMsgExtInfo(const AppSpawnMsgNode *message, const char *name, uint32_t *len);
int CheckAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index);
int SetAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index);
int CheckAppSpawnMsgFlagsSet(const AppSpawnMsgFlags *msgFlags, uint32_t flagIndex);

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) &&
        (content->content.mode == MODE_FOR_NWEB_SPAWN || content->content.mode == MODE_FOR_NWEB_COLD_RUN);
}

APPSPAWN_INLINE int IsCJSpawnMode(const AppSpawnMgr *content)
{
    return (content != NULL) &&
        (content->content.mode == MODE_FOR_CJAPP_SPAWN || content->content.mode == MODE_FOR_CJAPP_COLD_RUN);
}

APPSPAWN_INLINE int IsNativeSpawnMode(const AppSpawnMgr *content)
{
    return (content != NULL) &&
        (content->content.mode == MODE_FOR_NATIVE_SPAWN || content->content.mode == MODE_FOR_NATIVE_COLD_RUN);
}

APPSPAWN_INLINE int IsHybridSpawnMode(const AppSpawnMgr *content)
{
    return (content != NULL) &&
        (content->content.mode == MODE_FOR_HYBRID_SPAWN || content->content.mode == MODE_FOR_HYBRID_COLD_RUN);
}

APPSPAWN_INLINE int IsColdRunMode(const AppSpawnMgr *content)
{
    return (content != NULL) && (content->content.mode == MODE_FOR_APP_COLD_RUN ||
        content->content.mode == MODE_FOR_NWEB_COLD_RUN || content->content.mode == MODE_FOR_HYBRID_COLD_RUN ||
        content->content.mode == MODE_FOR_CJAPP_COLD_RUN || content->content.mode == MODE_FOR_NATIVE_COLD_RUN);
}

APPSPAWN_INLINE int IsDeveloperModeOn(const AppSpawningCtx *property)
{
#ifdef SUPPORT_LOCAL_DEBUGGER
    return true;
#endif
    return (property != NULL && ((property->client.flags & APP_DEVELOPER_MODE) == APP_DEVELOPER_MODE));
}

APPSPAWN_INLINE int IsJitFortModeOn(const AppSpawningCtx *property)
{
    return (property != NULL && ((property->client.flags & APP_JITFORT_MODE) == APP_JITFORT_MODE));
}

APPSPAWN_INLINE int GetAppSpawnMsgType(const AppSpawningCtx *appProperty)
{
    return (appProperty != NULL && appProperty->message != NULL) ?
        appProperty->message->msgHeader.msgType : MAX_TYPE_INVALID;
}

APPSPAWN_INLINE const char *GetProcessName(const AppSpawningCtx *property)
{
    if (property == NULL || property->message == NULL) {
        return NULL;
    }
    return property->message->msgHeader.processName;
}

APPSPAWN_INLINE const char *GetBundleName(const AppSpawningCtx *property)
{
    if (property == NULL || property->message == NULL) {
        return NULL;
    }
    AppSpawnMsgBundleInfo *info = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(property->message, TLV_BUNDLE_INFO);
    if (info != NULL) {
        return info->bundleName;
    }
    return NULL;
}

APPSPAWN_INLINE void *GetAppProperty(const AppSpawningCtx *property, uint32_t type)
{
    APPSPAWN_CHECK(property != NULL && property->message != NULL,
        return NULL, "Invalid property for type %{public}u", type);
    return GetAppSpawnMsgInfo(property->message, type);
}

APPSPAWN_INLINE void *GetAppPropertyExt(const AppSpawningCtx *property, const char *name, uint32_t *len)
{
    APPSPAWN_CHECK(name != NULL, return NULL, "Invalid name ");
    APPSPAWN_CHECK(property != NULL && property->message != NULL,
        return NULL, "Invalid property for name %{public}s", name);
    return GetAppSpawnMsgExtInfo(property->message, name, len);
}

APPSPAWN_INLINE int CheckAppMsgFlagsSet(const AppSpawningCtx *property, uint32_t index)
{
    APPSPAWN_CHECK(property != NULL && property->message != NULL,
        return 0, "Invalid property for name %{public}u", TLV_MSG_FLAGS);
    return CheckAppSpawnMsgFlag(property->message, TLV_MSG_FLAGS, index);
}

APPSPAWN_INLINE int CheckAppPermissionFlagSet(const AppSpawningCtx *property, uint32_t index)
{
    APPSPAWN_CHECK(property != NULL && property->message != NULL,
        return 0, "Invalid property for name %{public}u", TLV_PERMISSION);
    return CheckAppSpawnMsgFlag(property->message, TLV_PERMISSION, index);
}

APPSPAWN_INLINE int SetAppPermissionFlags(const AppSpawningCtx *property, uint32_t index)
{
    APPSPAWN_CHECK(property != NULL && property->message != NULL,
        return -1, "Invalid property for name %{public}u", TLV_PERMISSION);
    return SetAppSpawnMsgFlag(property->message, TLV_PERMISSION, index);
}

APPSPAWN_INLINE int IsIsolatedNativeSpawnMode(const AppSpawnMgr *content, const AppSpawningCtx *property)
{
    return (content != NULL) && (content->content.mode == MODE_FOR_NATIVE_SPAWN) &&
        CheckAppMsgFlagsSet(property, APP_FLAGS_ISOLATED_SANDBOX_TYPE);
}

#ifdef __cplusplus
}
#endif
#endif  // APPSPAWN_MANAGER_H