From 6b0cd809b6dc9878ea0b26594f4b0925bbba15df Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Thu, 3 Mar 2022 20:39:52 +0800 Subject: [PATCH] init: add sandbox func Signed-off-by: xionglei6 --- bundle.json | 3 +- interfaces/innerkits/sandbox/BUILD.gn | 67 ++ .../innerkits/sandbox/chipset-sandbox.json | 58 ++ .../innerkits/sandbox/include/sandbox.h | 64 ++ .../sandbox/include/sandbox_namespace.h | 36 + interfaces/innerkits/sandbox/sandbox.c | 657 ++++++++++++++++++ .../innerkits/sandbox/sandbox_namespace.c | 91 +++ .../innerkits/sandbox/system-sandbox.json | 74 ++ interfaces/innerkits/socket/BUILD.gn | 1 + services/BUILD.gn | 16 + services/begetctl/BUILD.gn | 6 + services/begetctl/sandbox.cpp | 218 ++++++ services/etc/init.cfg | 5 - services/etc/init.without_two_stages.cfg | 5 - services/etc/param/ohos.para | 1 + services/init/include/init.h | 1 + services/init/init_common_service.c | 9 +- services/init/lite/init.c | 6 + services/init/standard/device.c | 6 + services/init/standard/init.c | 78 ++- services/log/BUILD.gn | 1 + test/unittest/BUILD.gn | 3 + 22 files changed, 1390 insertions(+), 16 deletions(-) create mode 100755 interfaces/innerkits/sandbox/BUILD.gn create mode 100644 interfaces/innerkits/sandbox/chipset-sandbox.json create mode 100644 interfaces/innerkits/sandbox/include/sandbox.h create mode 100644 interfaces/innerkits/sandbox/include/sandbox_namespace.h create mode 100644 interfaces/innerkits/sandbox/sandbox.c create mode 100644 interfaces/innerkits/sandbox/sandbox_namespace.c create mode 100644 interfaces/innerkits/sandbox/system-sandbox.json create mode 100755 services/begetctl/sandbox.cpp diff --git a/bundle.json b/bundle.json index 97b30144..89ae7c00 100644 --- a/bundle.json +++ b/bundle.json @@ -48,7 +48,8 @@ "//base/startup/init_lite/interfaces/innerkits/socket:libsocket", "//base/startup/init_lite/services/loopevent:loopevent", "//base/startup/init_lite/interfaces/innerkits/plugin:libplugin", - "//base/startup/init_lite/device_info:device_info_group" + "//base/startup/init_lite/device_info:device_info_group", + "//base/startup/init_lite/interfaces/innerkits/sandbox:libsandbox" ], "inner_kits": [ { diff --git a/interfaces/innerkits/sandbox/BUILD.gn b/interfaces/innerkits/sandbox/BUILD.gn new file mode 100755 index 00000000..cf8c2fc9 --- /dev/null +++ b/interfaces/innerkits/sandbox/BUILD.gn @@ -0,0 +1,67 @@ +# 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. + +import("//base/startup/init_lite/begetd.gni") +import("//build/ohos.gni") + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ "include/" ] +} + +ohos_shared_library("libsandbox") { + sources = [ + "sandbox.c", + "sandbox_namespace.c", + ] + public_configs = [ ":exported_header_files" ] + include_dirs = [ + "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/services/include", + "//base/startup/init_lite/interfaces/innerkits/include", + "//third_party/cJSON", + ] + defines = [ "INIT_AGENT" ] + deps = [ + "//base/startup/init_lite/services/utils:libinit_utils", + "//third_party/bounds_checking_function:libsec_shared", + "//third_party/cJSON:cjson_static", + ] + + deps += [ "//base/startup/init_lite/services/log:init_log" ] + + part_name = "init" + install_images = [ "system" ] +} + +# For init only +ohos_static_library("libsandbox_static") { + sources = [ + "sandbox.c", + "sandbox_namespace.c", + ] + public_configs = [ ":exported_header_files" ] + include_dirs = [ + "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", + "//base/startup/init_lite/services/include", + "//third_party/cJSON", + ] + deps = [ + "//base/startup/init_lite/services/utils:libinit_utils", + "//third_party/bounds_checking_function:libsec_static", + "//third_party/cJSON:cjson_static", + ] + deps += [ "//base/startup/init_lite/services/log:init_log" ] + part_name = "init" +} diff --git a/interfaces/innerkits/sandbox/chipset-sandbox.json b/interfaces/innerkits/sandbox/chipset-sandbox.json new file mode 100644 index 00000000..3b97c395 --- /dev/null +++ b/interfaces/innerkits/sandbox/chipset-sandbox.json @@ -0,0 +1,58 @@ +{ + "sandbox-root" : "/mnt/sandbox/chipset", + "mount-bind-paths" : [{ + "src-path" : "/system/lib/vndk", + "sandbox-path" : "/system/lib/vndk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/platform-vndk", + "sandbox-path" : "/system/lib/platform-vndk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/ndk", + "sandbox-path" : "/system/lib/ndk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/lib", + "sandbox-path" : "/vendor/lib", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/bin", + "sandbox-path" : "/vendor/bin", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/etc", + "sandbox-path" : "/vendor/etc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/dev", + "sandbox-path" : "/dev", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/proc", + "sandbox-path" : "/proc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/data", + "sandbox-path" : "/data", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/sys", + "sandbox-path" : "/sys", + "sandbox-flags" : [ "bind", "rec", "private" ] + } + ], + "mount-bind-files" : [{ + }], + "symbol-links" : [{ + "target-name" : "/vendor/lib", + "link-name" : "/lib" + }, { + "target-name" : "/vendor/bin", + "link-name" : "/bin" + }, { + "target-name" : "/vendor/etc", + "link-name" : "/etc" + } + ] +} \ No newline at end of file diff --git a/interfaces/innerkits/sandbox/include/sandbox.h b/interfaces/innerkits/sandbox/include/sandbox.h new file mode 100644 index 00000000..4fa96f2b --- /dev/null +++ b/interfaces/innerkits/sandbox/include/sandbox.h @@ -0,0 +1,64 @@ +/* +* 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 BASE_STARTUP_INITLITE_SANDBOX_H +#define BASE_STARTUP_INITLITE_SANDBOX_H + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "init_utils.h" + +typedef struct { + char *source; // source 目录,一般是全局的fs 目录 + char *target; // 沙盒化后的目录 + unsigned long flags; +} mount_t; + +typedef struct MountList { + mount_t *info; + struct MountList *next; +} mountlist_t; + +typedef struct { + char *target; + char *linkName; +} linker_t; + +typedef struct LinkList { + linker_t *info; + struct LinkList *next; +} linklist_t; + +typedef struct { + mountlist_t *mounts; + linklist_t *links; + char *rootPath; // /mnt/sandbox/system|vendor|xxx + char name[MAX_BUFFER_LEN]; // name of sandbox. i.e system, chipset etc. + bool isCreated; // sandbox already created or not + int ns; // namespace +} sandbox_t; + +bool InitSandboxWithName(const char *name); +int PrepareSandbox(const char *name); +int EnterSandbox(const char *name); +void DestroySandbox(const char *name); +int CheckSupportSandbox(void); +void DumpSandboxByName(const char *name); +#ifdef __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/sandbox/include/sandbox_namespace.h b/interfaces/innerkits/sandbox/include/sandbox_namespace.h new file mode 100644 index 00000000..4e398a59 --- /dev/null +++ b/interfaces/innerkits/sandbox/include/sandbox_namespace.h @@ -0,0 +1,36 @@ +/* +* 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 SANDBOX_NAMESPACE_H +#define SANDBOX_NAMESPACE_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int GetNamespaceFd(const char *nsPath); +int UnshareNamespace(int nsType); +int SetNamespce(int nsFd, int nsType); +void InitDefaultNamespace(void); +int EnterDefaultNamespace(void); +void CloseDefaultNamespace(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/sandbox/sandbox.c b/interfaces/innerkits/sandbox/sandbox.c new file mode 100644 index 00000000..e8249137 --- /dev/null +++ b/interfaces/innerkits/sandbox/sandbox.c @@ -0,0 +1,657 @@ +/* +* 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. +*/ + +#include "sandbox.h" + +#include +#include +#include +#include +#include +#include +#include +#include "beget_ext.h" +#include "init_utils.h" +#include "cJSON.h" +#include "sandbox_namespace.h" +#include "securec.h" + +#define SANDBOX_ROOT_TAG "sandbox-root" +#define SANDBOX_MOUNT_PATH_TAG "mount-bind-paths" +#define SANDBOX_MOUNT_FILE_TAG "mount-bind-files" +#define SANDBOX_SOURCE "src-path" +#define SANDBOX_TARGET "sandbox-path" +#define SANDBOX_FLAGS "sandbox-flags" +#define SANDBOX_SYMLINK_TAG "symbol-links" +#define SANDBOX_SYMLINK_TARGET "target-name" +#define SANDBOX_SYMLINK_NAME "link-name" + +#define SANDBOX_SYSTEM_CONFIG_FILE "/system/etc/sandbox/system-sandbox.json" +#define SANDBOX_CHIPSET_CONFIG_FILE "/system/etc/sandbox/chipset-sandbox.json" +#define SANDBOX_PRIVAPP_CONFIG_FILE "/system/etc/sandbox/privapp-sandbox.json" +#define SANDBOX_APP_CONFIG_FILE "/system/etc/sandbox/app-sandbox.json" + +#define SANDBOX_MOUNT_FLAGS_MS_BIND "bind" +#define SANDBOX_MOUNT_FLAGS_MS_PRIVATE "private" +#define SANDBOX_MOUNT_FLAGS_MS_REC "rec" +#define SANDBOX_MOUNT_FLAGS_MS_MOVE "move" + +struct SandboxMountFlags { + const char *flag; + unsigned long value; +}; + +struct SandboxMountFlags g_flags[] = { + { + .flag = "bind", + .value = MS_BIND, + }, + { + .flag = "private", + .value = MS_PRIVATE, + }, + { + .flag = "rec", + .value = MS_REC, + }, + { + .flag = "move", + .value = MS_MOVE, + } +}; + + +static sandbox_t g_systemSandbox; +static sandbox_t g_chipsetSandbox; +static sandbox_t g_privAppSandbox; +static sandbox_t g_appSandbox; + +struct SandboxMap { + const char *name; + sandbox_t *sandbox; + const char *configfile; +}; + +struct SandboxMap g_map[] = { + { + .name = "system", + .sandbox = &g_systemSandbox, + .configfile = SANDBOX_SYSTEM_CONFIG_FILE, + }, + { + .name = "chipset", + .sandbox = &g_chipsetSandbox, + .configfile = SANDBOX_CHIPSET_CONFIG_FILE, + }, + { + .name = "priv-app", + .sandbox = &g_privAppSandbox, + .configfile = SANDBOX_PRIVAPP_CONFIG_FILE, + }, + { + .name = "app", + .sandbox = &g_appSandbox, + .configfile = SANDBOX_APP_CONFIG_FILE, + } +}; + +static unsigned long GetSandboxMountFlags(cJSON *item) +{ + BEGET_ERROR_CHECK(item != NULL, return 0, "Invalid parameter."); + char *str = cJSON_GetStringValue(item); + if (str == NULL) { + return 0; + } + for (size_t i = 0; i < ARRAY_LENGTH(g_flags); i++) { + if (strcmp(str, g_flags[i].flag) == 0) { + return g_flags[i].value; + } + } + return 0; +} + +typedef int (*AddInfoToSandboxCallback)(sandbox_t *sandbox, cJSON *item); + +static int AddMountInfoToSandbox(sandbox_t *sandbox, cJSON *item) +{ + if (sandbox == NULL || item == NULL) { + return -1; + } + mountlist_t *tmpMount = (mountlist_t *)calloc(1, sizeof(mountlist_t)); + BEGET_ERROR_CHECK(tmpMount != NULL, return -1, "Failed calloc err=%d", errno); + tmpMount->info = (mount_t *)calloc(1, sizeof(mount_t)); + BEGET_ERROR_CHECK(tmpMount->info != NULL, return -1, "Failed calloc err=%d", errno); + + char *srcPath = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SOURCE)); + if (srcPath != NULL) { + tmpMount->info->source = strdup(srcPath); + } + char *dstPath = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_TARGET)); + if (dstPath != NULL) { + tmpMount->info->target = strdup(dstPath); + } + cJSON *obj = cJSON_GetObjectItem(item, SANDBOX_FLAGS); + BEGET_ERROR_CHECK(obj != NULL, return -1, "Failed get sandbox-flags."); + int ret = cJSON_IsArray(obj); + BEGET_ERROR_CHECK(ret, return -1, "Failed get sandbox-flags array. "); + int count = cJSON_GetArraySize(obj); + BEGET_ERROR_CHECK(count > 0, return -1, "Failed get sandbox-flags array size."); + for (int i = 0; i < count; i++) { + cJSON *item = cJSON_GetArrayItem(obj, i); + tmpMount->info->flags |= GetSandboxMountFlags(item); + } + + if (sandbox->mounts == NULL) { + sandbox->mounts = tmpMount; + tmpMount->next = NULL; + } else { + tmpMount->next = sandbox->mounts->next; + sandbox->mounts->next = tmpMount; + } + return 0; +} + +static int AddSymbolLinksToSandbox(sandbox_t *sandbox, cJSON *item) +{ + if (sandbox == NULL || item == NULL) { + return -1; + } + linklist_t *tmpLink = (linklist_t *)calloc(1, sizeof(linklist_t)); + BEGET_ERROR_CHECK(tmpLink != NULL, return -1, "Failed calloc err=%d", errno); + tmpLink->info = (linker_t *)calloc(1, sizeof(linker_t)); + BEGET_ERROR_CHECK(tmpLink->info != NULL, return -1, "Failed calloc err=%d", errno); + + char *target = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_TARGET)); + if (target != NULL) { + tmpLink->info->target = strdup(target); + } + char *name = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_NAME)); + if (name != NULL) { + tmpLink->info->linkName = strdup(name); + } + + if (sandbox->links == NULL) { + sandbox->links = tmpLink; + tmpLink->next = NULL; + } else { + tmpLink->next = sandbox->links->next; + sandbox->links->next = tmpLink; + } + return 0; +} + +static int GetSandboxInfo(sandbox_t *sandbox, cJSON *root, const char *itemName) +{ + if (sandbox == NULL || root == NULL || itemName == NULL) { + BEGET_LOGE("Get sandbox mount info with invalid argument"); + return -1; + } + + cJSON *obj = cJSON_GetObjectItem(root, itemName); + if (obj == NULL) { + BEGET_LOGE("Cannot find item \' %s \' in sandbox config", itemName); + return -1; + } + if (!cJSON_IsArray(obj)) { + BEGET_LOGE("%s with invalid type, should be array", itemName); + return -1; + } + + int counts = cJSON_GetArraySize(obj); + if (counts <= 0) { + BEGET_LOGE("%s with invalid content", itemName); + return -1; + } + AddInfoToSandboxCallback func; + if (strcmp(itemName, SANDBOX_MOUNT_PATH_TAG) == 0) { + func = AddMountInfoToSandbox; + } else if (strcmp(itemName, SANDBOX_SYMLINK_TAG) == 0) { + func = AddSymbolLinksToSandbox; + } else { + BEGET_LOGE("Failed %s item name is not support.", itemName); + return -1; + } + for (int i = 0; i < counts; i++) { + cJSON *item = cJSON_GetArrayItem(obj, i); + BEGET_ERROR_CHECK(item != NULL, return -1, "Failed get json array item %d", i); + if (func(sandbox, item) < 0) { + BEGET_LOGE("Failed add info to sandbox."); + return -1; + } + } + return 0; +} + +static int ParseSandboxConfig(sandbox_t *sandbox, const char *sandboxConfig) +{ + if (sandbox == NULL || sandboxConfig == NULL) { + BEGET_LOGE("Parse sandbox config with invalid argument"); + return -1; + } + char *contents = ReadFileToBuf(sandboxConfig); + if (contents == NULL) { + return -1; + } + cJSON *root = cJSON_Parse(contents); + if (root == NULL) { + BEGET_LOGE("Parse sandbox config \' %s \' failed", sandboxConfig); + return -1; + } + cJSON *sandboxRoot = cJSON_GetObjectItem(root, SANDBOX_ROOT_TAG); + if (sandboxRoot == NULL) { + BEGET_LOGE("Cannot find item \' %s \' in sandbox config", SANDBOX_ROOT_TAG); + cJSON_Delete(root); + return -1; + } + char *rootdir = cJSON_GetStringValue(sandboxRoot); + if (rootdir != NULL) { + sandbox->rootPath = strdup(rootdir); + if (sandbox->rootPath == NULL) { + BEGET_LOGE("Get sandbox root path out of memory"); + cJSON_Delete(root); + return -1; + } + } + if (GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_PATH_TAG) < 0) { + cJSON_Delete(root); + return -1; + } + if (GetSandboxInfo(sandbox, root, SANDBOX_SYMLINK_TAG) < 0) { + cJSON_Delete(root); + return -1; + } + cJSON_Delete(root); + return 0; +} + +static struct SandboxMap *GetSandboxMapByName(const char *name) +{ + if (name == NULL) { + BEGET_LOGE("Failed get sandbox map name is NULL."); + return NULL; + } + int len = ARRAY_LENGTH(g_map); + for (int i = 0; i < len; i++) { + if (strcmp(g_map[i].name, name) == 0) { + return &g_map[i]; + } + } + return NULL; +} + +static void InitSandbox(sandbox_t *sandbox, const char *sandboxConfig, const char *name) +{ + if (sandbox == NULL || sandboxConfig == NULL || name == NULL) { + BEGET_LOGE("Init sandbox with invalid arguments"); + return; + } + if (sandbox->isCreated) { + BEGET_LOGE("Sandbox %s has created."); + return; + } + if (UnshareNamespace(CLONE_NEWNS) < 0) { + return; + } + sandbox->ns = GetNamespaceFd("/proc/self/ns/mnt"); + if (sandbox->ns < 0) { + BEGET_LOGE("Failed get sandbox namespace fd."); + return; + } + + if (strcpy_s(sandbox->name, MAX_BUFFER_LEN - 1, name) != 0) { + BEGET_LOGE("Failed to copy sandbox name"); + return; + } + + // parse json config + if (ParseSandboxConfig(sandbox, sandboxConfig) < 0) { + return; + } +} + +static int CheckAndMakeDir(const char *dir, mode_t mode) +{ + if (access(dir, F_OK) == 0) { + BEGET_LOGW("Mount point \' %s \' already exist", dir); + return 0; + } else { + if (errno == ENOENT) { + if (MakeDirRecursive(dir, mode) != 0) { + BEGET_LOGE("Failed MakeDirRecursive %s, err=%d", dir, errno); + return -1; + } + } else { + BEGET_LOGW("Failed to access mount point \' %s \', err = %d", dir, errno); + return -1; + } + } + return 0; +} + +static int BindMount(const char *source, const char *target, unsigned long flags) +{ + if (source == NULL || target == NULL) { + BEGET_LOGE("Mount with invalid arguments"); + errno = EINVAL; + return -1; + } + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + if (CheckAndMakeDir(target, mode) != 0) { + BEGET_LOGE("Failed make %s dir.", target); + return -1; + } + + if ((flags & MS_BIND) == 0) { + BEGET_LOGW("Not configure bind, must configure bind flag."); + flags |= MS_BIND; + } + + if ((flags & MS_REC) == 0) { + BEGET_LOGW("Not configure rec, must configure rec flag."); + flags |= MS_REC; + } + + // do mount + if (mount(source, target, NULL, flags, NULL) != 0) { + BEGET_LOGE("Failed to bind mount \' %s \' to \' %s \', err = %d", source, target, errno); + return -1; + } + + return 0; +} + +static bool IsValidSandbox(sandbox_t *sandbox) +{ + if (sandbox == NULL) { + BEGET_LOGE("preparing sandbox with invalid argument"); + return false; + } + + if (sandbox->rootPath == NULL) { + return false; + } + + if (sandbox->mounts == NULL) { + return false; + } + return true; +} + +static int MountSandboxInfo(const mountlist_t *mounts, const char *rootPath) +{ + if (mounts == NULL) { + return -1; + } + if (mounts->info == NULL) { + return -1; + } + while (mounts != NULL) { + mount_t *mount = mounts->info; + char *source = mount->source; + char target[PATH_MAX] = {}; + if (snprintf_s(target, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, mount->target) < 0) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return -1; + } + int rc = BindMount(source, target, mount->flags); + BEGET_ERROR_CHECK(rc == 0, return -1, "Failed bind mount %s to %s.", source, target); + mounts = mounts->next; + } + return 0; +} + +static int LinkSandboxInfo(const linklist_t *links, const char *rootPath) +{ + if (links == NULL) { + return -1; + } + if (links->info == NULL) { + return -1; + } + while (links != NULL) { + linker_t *link = links->info; + char linkName[PATH_MAX] = {0}; + if (snprintf_s(linkName, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, link->linkName) < 0) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return -1; + } + int rc = symlink(link->target, linkName); + if (rc != 0) { + if (errno == EEXIST) { + BEGET_LOGE("symbol link name \' %s \' already exist", linkName); + } else { + BEGET_LOGE("Failed to link \' %s \' to \' %s \', err = %d", link->target, linkName, errno); + return -1; + } + } + links = links->next; + } + return 0; +} + +int PrepareSandbox(const char *name) +{ + BEGET_ERROR_CHECK(name != NULL, return -1, "Prepare sandbox name is NULL."); + BEGET_ERROR_CHECK(getuid() == 0, return -1, "Current process uid is not root, exit."); + struct SandboxMap *map = GetSandboxMapByName(name); + BEGET_ERROR_CHECK(map != NULL, return -1, "Failed get sandbox map by name %s.", name); + sandbox_t *sandbox = map->sandbox; + BEGET_CHECK(IsValidSandbox(sandbox) == true, return -1); + BEGET_INFO_CHECK(sandbox->isCreated == false, return 0, "Sandbox %s already created", sandbox->name); + BEGET_CHECK(sandbox->rootPath != NULL, return -1); + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + BEGET_ERROR_CHECK(CheckAndMakeDir(sandbox->rootPath, mode) == 0, return -1, "Failed root %s.", sandbox->rootPath); + int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL); + BEGET_ERROR_CHECK(rc == 0, return -1, "Failed set mount slave err = %d", errno); + rc = BindMount(sandbox->rootPath, sandbox->rootPath, MS_BIND | MS_REC); + BEGET_ERROR_CHECK(rc == 0, return -1, "Failed to mount rootpath bind err = %d", errno); + + // 1) walk through all mounts and do bind mount + rc = MountSandboxInfo(sandbox->mounts, sandbox->rootPath); + if (rc < 0) { + return -1; + } + + // 2) walk through all links and do symbol link + rc = LinkSandboxInfo(sandbox->links, sandbox->rootPath); + if (rc < 0) { + return -1; + } + + BEGET_ERROR_CHECK(chdir(sandbox->rootPath) == 0, return -1, "Change to %s, err = %d", sandbox->rootPath, errno); + BEGET_ERROR_CHECK(syscall(SYS_pivot_root, sandbox->rootPath, sandbox->rootPath) == 0, return -1, + "Failed system call pivot root, err=%d", errno); + BEGET_ERROR_CHECK(umount2(".", MNT_DETACH) == 0, return -1, "Failed umount2 MNT_DETACH, err=%d", errno); + sandbox->isCreated = true; + return 0; +} + +static void FreeLink(linker_t *link) +{ + if (link == NULL) { + return; + } + + if (link->linkName != NULL) { + free(link->linkName); + link->linkName = NULL; + } + + if (link->target != NULL) { + free(link->target); + link->target = NULL; + } +} + +static void FreeLinks(linklist_t *links) +{ + if (links == NULL) { + return; + } + + linklist_t *tmp = links; + while (tmp != NULL) { + linklist_t *next = tmp ->next; + FreeLink(tmp->info); + free(tmp); + tmp = next; + } +} + +static void FreeMount(mount_t *mount) +{ + if (mount == NULL) { + return; + } + + if (mount->source != NULL) { + free(mount->source); + mount->source = NULL; + } + + if (mount->target != NULL) { + free(mount->target); + mount->target = NULL; + } +} + +static void FreeMounts(mountlist_t *mounts) +{ + if (mounts == NULL) { + return; + } + + mountlist_t *tmp = mounts; + while (tmp != NULL) { + mountlist_t *next = tmp ->next; + FreeMount(tmp->info); + free(tmp); + tmp = next; + } +} + +bool InitSandboxWithName(const char *name) +{ + bool isFound = false; + if (name == NULL) { + BEGET_LOGE("Init sandbox name is NULL."); + return isFound; + } + struct SandboxMap *map = GetSandboxMapByName(name); + if (map != NULL) { + InitSandbox(map->sandbox, map->configfile, name); + isFound = true; + } + + if (!isFound) { + BEGET_LOGE("Cannot find sandbox with name %s.", name); + } + return isFound; +} + +void DestroySandbox(const char *name) +{ + if (name == NULL) { + BEGET_LOGE("Destroy sandbox name is NULL."); + return; + } + struct SandboxMap *map = GetSandboxMapByName(name); + if (map == NULL) { + BEGET_LOGE("Failed get sandbox map by name %s.", name); + return; + } + sandbox_t *sandbox = map->sandbox; + + if (sandbox == NULL) { + return; + } + + if (sandbox->rootPath != NULL) { + free(sandbox->rootPath); + sandbox->rootPath = NULL; + } + FreeLinks(sandbox->links); + FreeMounts(sandbox->mounts); + if (sandbox->ns > 0) { + (void)close(sandbox->ns); + } + sandbox->isCreated = false; + return; +} + +int EnterSandbox(const char *name) +{ + if (name == NULL) { + BEGET_LOGE("Destroy sandbox name is NULL."); + return -1; + } + struct SandboxMap *map = GetSandboxMapByName(name); + if (map == NULL) { + BEGET_LOGE("Failed get sandbox map by name %s.", name); + return -1; + } + sandbox_t *sandbox = map->sandbox; + + if (sandbox == NULL) { + return -1; + } + if (sandbox->isCreated == false) { + BEGET_LOGE("Sandbox has not created."); + return -1; + } + if (sandbox->ns > 0) { + if (SetNamespce(sandbox->ns, CLONE_NEWNS) < 0) { + BEGET_LOGE("Failed set namespace CLONE_NEWNS, err=%d.", errno); + return -1; + } + } else { + BEGET_LOGE("System sandbox namespace fd is error."); + return -1; + } + return 0; +} + +void DumpSandboxByName(const char *name) +{ + if (name == NULL) { + BEGET_LOGE("Init sandbox name is NULL."); + return; + } + struct SandboxMap *map = GetSandboxMapByName(name); + if (map == NULL) { + return; + } + BEGET_LOGI("Sandbox Map name: %s.", map->name); + BEGET_LOGI("Sandbox Map config file: %s.", map->configfile); + BEGET_LOGI("Sandbox name: %s.", map->sandbox->name); + BEGET_LOGI("Sandbox rootPath: %s.", map->sandbox->rootPath); + BEGET_LOGI("Sandbox mounts info:"); + mountlist_t *mounts = map->sandbox->mounts; + while (mounts != NULL) { + mount_t *mount = mounts->info; + BEGET_LOGI("Sandbox mounts list source: %s", mount->source); + BEGET_LOGI("Sandbox mounts list target: %s", mount->target); + mounts = mounts->next; + } + BEGET_LOGI("Sandbox links info:"); + linklist_t *links = map->sandbox->links; + while (links != NULL) { + linker_t *link = links->info; + BEGET_LOGI("Sandbox links list source: %s", link->target); + BEGET_LOGI("Sandbox links list target: %s", link->linkName); + links = links->next; + } + return; +} diff --git a/interfaces/innerkits/sandbox/sandbox_namespace.c b/interfaces/innerkits/sandbox/sandbox_namespace.c new file mode 100644 index 00000000..071f1298 --- /dev/null +++ b/interfaces/innerkits/sandbox/sandbox_namespace.c @@ -0,0 +1,91 @@ +/* +* 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. +*/ + +#include +#include +#include +#include +#include +#include +#include "beget_ext.h" + +static int g_defaultNs; + +int GetNamespaceFd(const char *nsPath) +{ + if (nsPath == NULL) { + return -1; + } + int ns = open(nsPath, O_RDONLY | O_CLOEXEC); + if (ns < 0) { + BEGET_LOGE("Failed unshare namespace, err=%d", errno); + return -1; + } + return ns; +} + +int UnshareNamespace(int nsType) +{ + if (nsType == CLONE_NEWNS) { + if (unshare(nsType) < 0) { + BEGET_LOGE("Failed unshare namespace, err=%d", errno); + return -1; + } else { + return 0; + } + } else { + BEGET_LOGE("Failed unshare, type is not support"); + return -1; + } +} + +int SetNamespce(int nsFd, int nsType) +{ + if (nsFd < 0) { + BEGET_LOGE("Failed get namespace fd"); + return -1; + } + if (nsType != CLONE_NEWNS) { + BEGET_LOGE("Failed get namespace type"); + return -1; + } + return setns(nsFd, nsType); +} + +void InitDefaultNamespace(void) +{ + if (g_defaultNs > 0) { + (void)close(g_defaultNs); + } + g_defaultNs = GetNamespaceFd("/proc/self/ns/mnt"); + return; +} + +int EnterDefaultNamespace(void) +{ + if (g_defaultNs < 0) { + return -1; + } + return SetNamespce(g_defaultNs, CLONE_NEWNS); +} + +void CloseDefaultNamespace(void) +{ + if (g_defaultNs > 0) { + (void)close(g_defaultNs); + g_defaultNs = -1; + } + return; +} diff --git a/interfaces/innerkits/sandbox/system-sandbox.json b/interfaces/innerkits/sandbox/system-sandbox.json new file mode 100644 index 00000000..0a55be15 --- /dev/null +++ b/interfaces/innerkits/sandbox/system-sandbox.json @@ -0,0 +1,74 @@ +{ + "sandbox-root" : "/mnt/sandbox/system", + "mount-bind-paths" : [{ + "src-path" : "/system/bin", + "sandbox-path" : "/system/bin", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/etc", + "sandbox-path" : "/system/etc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib", + "sandbox-path" : "/system/lib", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/profile", + "sandbox-path" : "/system/profile", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/app", + "sandbox-path" : "/system/app", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/fonts", + "sandbox-path" : "/system/fonts", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor", + "sandbox-path" : "/vendor", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/dev", + "sandbox-path" : "/dev", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/proc", + "sandbox-path" : "/proc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/data", + "sandbox-path" : "/data", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/sys", + "sandbox-path" : "/sys", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/config", + "sandbox-path" : "/config", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/mnt", + "sandbox-path" : "/mnt", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/storage", + "sandbox-path" : "/storage", + "sandbox-flags" : [ "bind", "rec", "private" ] + } + ], + "mount-bind-files" : [{ + }], + "symbol-links" : [{ + "target-name" : "/system/lib", + "link-name" : "/lib" + }, { + "target-name" : "/system/bin", + "link-name" : "/bin" + }, { + "target-name" : "/system/etc", + "link-name" : "/etc" + } + ] +} \ No newline at end of file diff --git a/interfaces/innerkits/socket/BUILD.gn b/interfaces/innerkits/socket/BUILD.gn index f5fc3e9d..619230d4 100644 --- a/interfaces/innerkits/socket/BUILD.gn +++ b/interfaces/innerkits/socket/BUILD.gn @@ -49,5 +49,6 @@ if (defined(ohos_lite)) { "system", "updater", ] + relative_install_dir = "platform-vndk" } } diff --git a/services/BUILD.gn b/services/BUILD.gn index f0ffcb11..9420c6b9 100755 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -125,6 +125,7 @@ if (defined(ohos_lite)) { include_dirs = [ "//base/security/access_token/interfaces/innerkits/token_setproc/include", "//base/security/access_token/interfaces/innerkits/nativetoken/include", + "//base/startup/init_lite/interfaces/innerkits/sandbox/include", "//base/startup/init_lite/services/include/param", "//base/startup/init_lite/services/include", "//base/startup/init_lite/services/init/include", @@ -141,6 +142,7 @@ if (defined(ohos_lite)) { "//base/security/access_token/interfaces/innerkits/nativetoken:libnativetoken", "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", "//base/startup/init_lite/interfaces/innerkits:libfsmanager_static", + "//base/startup/init_lite/interfaces/innerkits/sandbox:libsandbox_static", "//base/startup/init_lite/services/log:init_log", "//base/startup/init_lite/services/loopevent:loopevent", "//base/startup/init_lite/services/param:param_service", @@ -301,10 +303,23 @@ if (defined(ohos_lite)) { part_name = "init" } + ohos_prebuilt_etc("system-sandbox.json") { + source = "//base/startup/init_lite/interfaces/innerkits/sandbox/system-sandbox.json" + part_name = "init" + module_install_dir = "etc/sandbox" + } + + ohos_prebuilt_etc("chipset-sandbox.json") { + source = "//base/startup/init_lite/interfaces/innerkits/sandbox/chipset-sandbox.json" + part_name = "init" + module_install_dir = "etc/sandbox" + } + group("init_etc") { deps = [ ":boot.group", ":charing.group", + ":chipset-sandbox.json", ":group", ":init.cfg", ":init.usb.cfg", @@ -315,6 +330,7 @@ if (defined(ohos_lite)) { ":plugin_modules", ":syscap.json", ":syscap.para", + ":system-sandbox.json", ":systemcapability.json", ] } diff --git a/services/begetctl/BUILD.gn b/services/begetctl/BUILD.gn index d9c10628..3d9e619d 100755 --- a/services/begetctl/BUILD.gn +++ b/services/begetctl/BUILD.gn @@ -20,6 +20,7 @@ ohos_executable("begetctl") { "main.c", "misc_daemon.cpp", "param_cmd.c", + "sandbox.cpp", "service_control.c", "shell/shell_bas.c", ] @@ -41,12 +42,16 @@ ohos_executable("begetctl") { "//base/startup/init_lite/services/param/include", "//base/startup/init_lite/services/loopevent/include", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/sandbox/include", + "//utils/native/base/include", ] deps = [ "//base/startup/init_lite/interfaces/innerkits:libbegetutil", + "//base/startup/init_lite/interfaces/innerkits/sandbox:libsandbox_static", "//base/startup/init_lite/services/log:agent_log", "//base/startup/init_lite/services/param:param_client", "//third_party/bounds_checking_function:libsec_static", + "//utils/native/base:utils", ] if (param_test) { @@ -72,6 +77,7 @@ ohos_executable("begetctl") { "stop_service", "service", "param", + "sandbox", ] install_images = [ "system" ] diff --git a/services/begetctl/sandbox.cpp b/services/begetctl/sandbox.cpp new file mode 100755 index 00000000..74d4c2bd --- /dev/null +++ b/services/begetctl/sandbox.cpp @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "begetctl.h" +#include "init_utils.h" +#include "sandbox.h" +#include "sandbox_namespace.h" +#include "string_ex.h" + +using namespace OHOS; +struct option g_options[] = { + { "config_file", required_argument, nullptr, 'c' }, + { "sandbox_name", required_argument, nullptr, 's' }, + { "process_name", required_argument, nullptr, 'p' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 }, +}; + +static void Usage() +{ + std::cout << "sandbox -c, --config_file=sandbox config file \"config file with json format\"" << std::endl; + std::cout << "sandbox -s, --sandbox_name=sandbox name \"Sandbox name, system, chipset etc.\"" << std::endl; + std::cout << "sandbox -p, --process=process name \"sh, hdcd, hdf_devhost, etc.\"" << std::endl; + std::cout << "sandbox -h, --help \"Show help\"" << std::endl; + exit(0); +} + +static std::string SearchConfigBySandboxName(const std::string &sandboxName) +{ + std::map sandboxConfigMap = { + {"system", "/system/etc/system-sandbox.json"}, + {"chipset", "/system/etc/chipset-sandbox.json"}, + {"priv-app", "/system/etc/priv-app-sandbox.json"}, + {"app", "/system/etc/app-sandbox.json"}, + }; + auto it = sandboxConfigMap.find(sandboxName); + if (it == sandboxConfigMap.end()) { + return ""; + } else { + return it->second; + } +} + +static void RunSandbox(const std::string &configFile, const std::string &name) +{ + std::string config {}; + std::string sandboxName {}; + if (!name.empty()) { + config = SearchConfigBySandboxName(name); + sandboxName = name; + } else { + // Without sandbox name, give one. + sandboxName = "sandbox_test"; + } + + if (config.empty()) { + std::cout << "No sandbox name " << sandboxName << "or config file specified!" << std::endl; + return; + } + InitDefaultNamespace(); + if (!InitSandboxWithName(sandboxName.c_str())) { + std::cout << "Init sandbox failed." << std::endl; + return; + } + + DumpSandboxByName(sandboxName.c_str()); + if (PrepareSandbox(sandboxName.c_str()) != 0) { + std::cout << "Prepare sandbox failed." << std::endl; + return; + } + EnterDefaultNamespace(); + CloseDefaultNamespace(); + EnterSandbox(sandboxName.c_str()); + return; +} + +static void EnterShell() +{ + char *argv[] = { (char *)"sh", NULL }; + char *envp[] = { nullptr }; + if (execve("/system/bin/sh", argv, envp) != 0) { + std::cout << "execve sh failed! err = "<< errno << std::endl; + } + return; +} + +static const int MAX_PROCESS_ARGC = 8; +static void EnterExec(const std::string &processName) +{ + if (processName.empty()) { + std::cout << "process name is nullptr." << std::endl; + return; + } + std::string tmpName = processName; + std::vector vtr; + const std::string sep = " "; + OHOS::SplitStr(tmpName, sep, vtr, true, false); + + if ((vtr.size() > MAX_PROCESS_ARGC) || (vtr.size() <= 0)) { + std::cout << "Service parameters is error." << std::endl; + return; + } + char *argv[MAX_PROCESS_ARGC] = {}; + std::vector::iterator it; + int i = 0; + for (it = vtr.begin(); it != vtr.end(); it++) { + argv[i] = (char *)(*it).c_str(); + std::cout << std::string(argv[i]) << std::endl; + i++; + } + argv[i] = NULL; + char *envp[] = { NULL }; + if (execve(argv[0], argv, envp) != 0) { + std::cout << "execve:" << argv[0] << "failed! err = "<< errno << std::endl; + } + return; +} + +static void RunCmd(const std::string &configFile, const std::string &sandboxName, const std::string &processName) +{ + if (!sandboxName.empty() && processName.empty()) { + RunSandbox(configFile, sandboxName); + EnterShell(); + } else if (!sandboxName.empty() && !processName.empty()) { + RunSandbox(configFile, sandboxName); + EnterExec(processName); + } else if (sandboxName.empty() && !processName.empty()) { + std::cout << "process name:" << processName << std::endl; + RunSandbox(configFile, std::string("system")); + EnterExec(processName); + } else { + Usage(); + } +} + +static int main_cmd(BShellHandle shell, int argc, char **argv) +{ + int rc = -1; + int optIndex = -1; + std::string configFile {}; + std::string sandboxName {}; + std::string processName {}; + while ((rc = getopt_long(argc, argv, "c:s:p:h", g_options, &optIndex)) != -1) { + switch (rc) { + case 0: { + std::string optionName = g_options[optIndex].name; + if (optionName == "config_file") { + configFile = optarg; + } else if (optionName == "help") { + Usage(); + } else if (optionName == "sandbox_name") { + sandboxName = optarg; + } else if (optionName == "process_name") { + processName = optarg; + } + break; + } + case 'c': + configFile = optarg; + break; + case 'h': + Usage(); + break; + case 's': + sandboxName = optarg; + break; + case 'p': + std::cout << "1111 process name:" << optarg << std::endl; + processName = optarg; + break; + case '?': + std::cout << "Invalid arugment\n"; + break; + default: + std::cout << "Invalid arugment\n"; + break; + } + } + RunCmd(configFile, sandboxName, processName); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + CmdInfo infos[] = { + { + (char *)"sandbox", main_cmd, (char *)"sandbox debug tool", + (char *)"sandbox -s, --sandbox=system, chipset, priv-app, or app", + NULL + } + }; + for (size_t i = 0; i < ARRAY_LENGTH(infos); i++) { + BShellEnvRegitsterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/services/etc/init.cfg b/services/etc/init.cfg index 18cf6857..6d88faae 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -15,8 +15,6 @@ "mkdir /dev/memcg/system 0550 system system", "start ueventd", "start watchdog_service", - "mkdir /data", - "mount_fstab /vendor/etc/fstab.${ohos.boot.hardware}", "chown system system /data", "chmod 0771 /data", "mkdir /data/service 0711 root root", @@ -64,11 +62,9 @@ "write /dev/blkio/background/blkio.weight 500", "write /dev/blkio/blkio.group_idle 0", "write /dev/blkio/background/blkio.group_idle 0", - "mount configfs none /config nodev noexec nosuid", "chmod 0770 /config/sdcardfs", "chown system package_info /config/sdcardfs", "symlink /storage/self/primary /sdcard", - "mkdir /mnt/sandbox 0711 root root", "write /proc/sys/kernel/panic_on_oops 1", "write /proc/sys/kernel/hung_task_timeout_secs 0", "write /proc/cpu/alignment 4", @@ -221,7 +217,6 @@ "mkdir /data/service/el2/0/hmdfs 0711 system system", "mkdir /data/chipset/el1/0 0711 root root", "mkdir /data/chipset/el2/0 0711 root root", - "mount tmpfs tmpfs /storage nodev noexec nosuid mode=0755,uid=0,gid=0", "mkdir /storage/media 0711 root root", "mkdir /data/bootchart 0755 shell shell", "mkdir /data/app-staging 0750 system system", diff --git a/services/etc/init.without_two_stages.cfg b/services/etc/init.without_two_stages.cfg index 7b2f272b..4a0e1beb 100755 --- a/services/etc/init.without_two_stages.cfg +++ b/services/etc/init.without_two_stages.cfg @@ -16,9 +16,6 @@ "mkdir /dev/memcg/system 0550 system system", "start ueventd", "start watchdog_service", - "mkdir /data", - "mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor /vendor wait rdonly barrier=1", - "mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/userdata /data wait nosuid nodev noatime barrier=1,data=ordered,noauto_da_alloc", "chown system system /data", "chmod 0771 /data", "mkdir /data/service 0711 root root", @@ -64,11 +61,9 @@ "write /dev/blkio/background/blkio.weight 500", "write /dev/blkio/blkio.group_idle 0", "write /dev/blkio/background/blkio.group_idle 0", - "mount configfs none /config nodev noexec nosuid", "chmod 0770 /config/sdcardfs", "chown system package_info /config/sdcardfs", "symlink /storage/self/primary /sdcard", - "mkdir /mnt/sandbox 0711 root root", "write /proc/sys/kernel/panic_on_oops 1", "write /proc/sys/kernel/hung_task_timeout_secs 0", "write /proc/cpu/alignment 4", diff --git a/services/etc/param/ohos.para b/services/etc/param/ohos.para index 9cee5606..8a90330f 100755 --- a/services/etc/param/ohos.para +++ b/services/etc/param/ohos.para @@ -37,3 +37,4 @@ const.build.characteristics=default const.product.model=ohos const.product.name="OpenHarmony 2.0 Canary" persist.sys.usb.config=hdc +const.sandbox=enable diff --git a/services/init/include/init.h b/services/init/include/init.h index b7f5e913..caf3b71a 100755 --- a/services/init/include/init.h +++ b/services/init/include/init.h @@ -43,6 +43,7 @@ void SystemExecuteRcs(void); void ReadConfig(void); void SignalInit(void); +int SetServiceEnterSandbox(const char *path); #ifdef __cplusplus #if __cplusplus diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index 61fc595e..80ea418e 100755 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -280,8 +280,10 @@ int ServiceStart(Service *service) } int pid = fork(); if (pid == 0) { - INIT_CHECK_ONLY_ELOG(SetAccessToken(service) == SERVICE_SUCCESS, - "set access token failed for service %s", service->name); + INIT_CHECK_ONLY_ELOG(SetServiceEnterSandbox(service->pathArgs.argv[0]) == SERVICE_SUCCESS, + "Failed %s sandbox.", service->name); + + INIT_CHECK_ONLY_ELOG(SetAccessToken(service) == SERVICE_SUCCESS, "access token failed %s", service->name); // deal start job if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) { DoJobNow(service->serviceJobs.jobsName[JOB_ON_START]); @@ -290,8 +292,7 @@ int ServiceStart(Service *service) ClearEnvironment(); if (!IsOnDemandService(service)) { - int ret = CreateServiceSocket(service); - INIT_ERROR_CHECK(ret >= 0, return SERVICE_FAILURE, + INIT_ERROR_CHECK(CreateServiceSocket(service) >= 0, return SERVICE_FAILURE, "service %s exit! create socket failed!", service->name); } diff --git a/services/init/lite/init.c b/services/init/lite/init.c index b710f495..b170efa0 100755 --- a/services/init/lite/init.c +++ b/services/init/lite/init.c @@ -82,3 +82,9 @@ void SystemRun(void) { LE_RunLoop(LE_GetDefaultLoop()); } + +int SetServiceEnterSandbox(const char *path) +{ + UNUSED(path); + return -1; +} diff --git a/services/init/standard/device.c b/services/init/standard/device.c index bac801fc..3152cf7d 100755 --- a/services/init/standard/device.c +++ b/services/init/standard/device.c @@ -47,6 +47,12 @@ void MountBasicFs(void) if (mount("tmpfs", "/mnt", "tmpfs", MS_NOSUID, "mode=0755") != 0) { INIT_LOGE("Mount tmpfs failed. %s", strerror(errno)); } + if (mount("tmpfs", "/storage", "tmpfs", MS_NOEXEC | MS_NODEV| MS_NOSUID, "mode=0755") != 0) { + INIT_LOGE("Mount storage failed. %s", strerror(errno)); + } + if (mount("none", "/config", "configfs", MS_NOEXEC | MS_NODEV| MS_NOSUID, "mode=0755") != 0) { + INIT_LOGE("Mount configfs failed. %s", strerror(errno)); + } if (mkdir("/dev/pts", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { INIT_LOGE("mkdir /dev/pts failed. %s", strerror(errno)); } diff --git a/services/init/standard/init.c b/services/init/standard/init.c index e66b4df1..5f789162 100755 --- a/services/init/standard/init.c +++ b/services/init/standard/init.c @@ -38,11 +38,15 @@ #include "ueventd.h" #include "ueventd_socket.h" #include "fd_holder_internal.h" +#include "sandbox.h" +#include "sandbox_namespace.h" #ifdef WITH_SELINUX #include #include #endif // WITH_SELINUX +static bool g_enableSandbox; + static int FdHolderSockInit(void) { int sock = -1; @@ -88,6 +92,28 @@ static int FdHolderSockInit(void) return sock; } +static void RegisterSandbox(const char *sandbox) +{ + if (sandbox == NULL) { + INIT_LOGE("Invaild parameters."); + return; + } + InitDefaultNamespace(); + if (!InitSandboxWithName(sandbox)) { + INIT_LOGE("Failed init sandbox with name %s.", sandbox); + } + + // DumpSandboxByName(sandbox); + if (PrepareSandbox(sandbox) != 0) { + INIT_LOGE("Failed prepare sandbox %s.", sandbox); + DestroySandbox(sandbox); + } + if (EnterDefaultNamespace() < 0) { + INIT_LOGE("Fail set default namespace."); + } + CloseDefaultNamespace(); +} + void SystemInit(void) { SignalInit(); @@ -98,6 +124,8 @@ void SystemInit(void) if (sock >= 0) { RegisterFdHoldWatcher(sock); } + RegisterSandbox("system"); + RegisterSandbox("chipset"); } static void EnableDevKmsg(void) @@ -267,6 +295,24 @@ static int SystemDump(int id, const char *name, int argc, const char **argv) } #endif +static void IsEnableSandbox(void) +{ + const char *name = "const.sandbox"; + char value[MAX_BUFFER_LEN] = {0}; + unsigned int len = MAX_BUFFER_LEN; + if (SystemReadParam(name, value, &len) != 0) { + INIT_LOGE("Failed read param."); + g_enableSandbox = false; + } + if (strcmp(value, "enable") == 0) { + INIT_LOGI("Support sandbox."); + g_enableSandbox = true; + } else { + INIT_LOGI("Not support sandbox."); + g_enableSandbox = false; + } +} + void SystemConfig(void) { InitServiceSpace(); @@ -293,7 +339,7 @@ void SystemConfig(void) AddCmdExecutor("display", SystemDump); (void)AddCompleteJob("param:ohos.servicectrl.display", "ohos.servicectrl.display=*", "display system"); #endif - + IsEnableSandbox(); // execute init PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init")); PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init")); @@ -304,3 +350,33 @@ void SystemRun(void) { StartParamService(); } + +int SetServiceEnterSandbox(const char *path) +{ + if (g_enableSandbox == false) { + return -1; + } + INIT_ERROR_CHECK(path != NULL, return -1, "Service path is null."); + if (strstr(path, "/system/bin") != NULL) { + if (strcmp(path, "/system/bin/sh") == 0) { + INIT_LOGI("Console cannot enter sandbox."); + } else if (strcmp(path, "/system/bin/hdcd") == 0) { + INIT_LOGI("Hdcd cannot enter sandbox."); + } else if (strcmp(path, "/system/bin/appspawn") == 0) { + INIT_LOGI("Appspawn cannot enter sandbox."); + } else if (strcmp(path, "/system/bin/ueventd") == 0) { + INIT_LOGI("Ueventd cannot enter sandbox."); + } else if (strcmp(path, "/system/bin/hilogd") == 0) { + INIT_LOGI("Hilogd cannot enter sandbox."); + } else { + INIT_ERROR_CHECK(EnterSandbox("system") == 0, return -1, + "Service %s failed enter sandbox system.", path); + } + } else if (strstr(path, "/vendor/bin") != NULL) { + INIT_ERROR_CHECK(EnterSandbox("system") == 0, return -1, + "Service %s failed enter sandbox system.", path); + } else { + INIT_LOGE("Service path %s is not support sandbox", path); + } + return 0; +} diff --git a/services/log/BUILD.gn b/services/log/BUILD.gn index ba3f7403..b8e404af 100755 --- a/services/log/BUILD.gn +++ b/services/log/BUILD.gn @@ -40,6 +40,7 @@ if (defined(ohos_lite)) { "system", "updater", ] + relative_install_dir = "platform-vndk" install_enable = true part_name = "init" subsystem_name = "startup" diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 64fc776d..d48273cd 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -38,6 +38,8 @@ ohos_unittest("init_ut") { "//base/startup/init_lite/interfaces/innerkits/fs_manager/fstab_mount.c", "//base/startup/init_lite/interfaces/innerkits/plugin/init_plugin.c", "//base/startup/init_lite/interfaces/innerkits/reboot/init_reboot_innerkits.c", + "//base/startup/init_lite/interfaces/innerkits/sandbox/sandbox.c", + "//base/startup/init_lite/interfaces/innerkits/sandbox/sandbox_namespace.c", "//base/startup/init_lite/interfaces/innerkits/socket/init_socket.c", "//base/startup/init_lite/services/begetctl/param_cmd.c", "//base/startup/init_lite/services/begetctl/shell/shell_bas.c", @@ -168,6 +170,7 @@ ohos_unittest("init_ut") { "//third_party/cJSON", "//base/security/access_token/interfaces/innerkits/token_setproc/include", "//base/security/access_token/interfaces/innerkits/nativetoken/include", + "//base/startup/init_lite/interfaces/innerkits/sandbox/include", ] deps = [ -- GitLab