diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md new file mode 100644 index 0000000000000000000000000000000000000000..f09d98dde9597de75ffcdb237c2b580b8fffa3f9 --- /dev/null +++ b/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -0,0 +1,13 @@ +### 该问题是怎么引起的? + + + +### 重现步骤 + + + +### 报错信息 + + + + diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md new file mode 100644 index 0000000000000000000000000000000000000000..66d4332058d27e3c8ef94919138576d71b524467 --- /dev/null +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -0,0 +1,14 @@ +### 相关的Issue + + +### 原因(目的、解决的问题等) + + +### 描述(做了什么,变更了什么) + + +### 测试用例(新增、改动、可能影响的功能) + + + + diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d77eb00b46ea7be51e1880304711bb13cd887ed6 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,40 @@ +# 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. +import("//base/startup/init/begetd.gni") + +group("init_fwk_group") { + deps = [] + if (init_feature_group_type) { + deps += [ + "device_info:device_info_group", + "interfaces/innerkits:innergroup", + "interfaces/kits:kitsgroup", + "services:startup_init", + "services/begetctl:begetctl_cmd", + "services/loopevent:loopeventgroup", + "services/modules:modulesgroup", + "services/param:parameter", + ] + } +} + +group("init_service_group") { + deps = [] + if (init_feature_group_type) { + deps += [ + "remount:overlayremount", + "ueventd:startup_ueventd", + "watchdog:watchdog", + ] + } +} diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000000000000000000000000000000000..ca34b3697310adc813a04d6dfe3ea95d8a6ef429 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,15 @@ +# 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. + +# any change needs to be reviewed by @liveery +* @liveery @zl_zl @cat @zhouge94 diff --git a/OAT.xml b/OAT.xml index 32f3b5575318c9cec64cf75574b63329d1f320c1..0cfc6f85984101a02c77fe7ebbd15e9adbbacd7a 100644 --- a/OAT.xml +++ b/OAT.xml @@ -22,6 +22,7 @@ + @@ -37,11 +38,13 @@ + + @@ -62,7 +65,8 @@ - + + diff --git a/README.md b/README.md index 4863f350d6263847db330b2d9916e279ffe9e7b6..4ab9187dca06b5d5521718445bd4716abd19f08e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# init\_lite +# init - [Introduction](#section469617221261) - [Directory Structure](#section15884114210197) @@ -8,27 +8,27 @@ ## Introduction -The init\_lite module starts system service processes from the time the kernel loads the first user-space process to the time the first application is started. In addition to loading key system processes, the module needs to configure their permissions during the startup and keep the specified process alive after sub-processes are started. If a process exits abnormally, the module needs to restart it, and to perform system reset for a special process. +The init module starts system service processes from the time the kernel loads the first user-space process to the time the first application is started. In addition to loading key system processes, the module needs to configure their permissions during the startup and keep the specified process alive after sub-processes are started. If a process exits abnormally, the module needs to restart it, and to perform system reset for a special process. ## Directory Structure ``` -base/startup/init_lite/ # init_lite module +base/startup/init/ # init module ├── LICENSE └── services - ├── include # Header files for the init_lite module - ├── src # Source files for the init_lite module - └── test # Source files of the test cases for the init_lite module + ├── include # Header files for the init module + ├── src # Source files for the init module + └── test # Source files of the test cases for the init module └── unittest vendor └──huawei └──camera - └──init_configs # init_lite configuration files (in JSON format, and deployed in /etc/init.cfg after image burning) + └──init_configs # init configuration files (in JSON format, and deployed in /etc/init.cfg after image burning) ``` ## Constraints -Currently, the init\_lite module applies only to small-system devices \(reference memory ≥ 1 MB\), for example, Hi3516D V300 and Hi3518E V300. +Currently, the init module applies only to small-system devices \(reference memory ≥ 1 MB\), for example, Hi3516D V300 and Hi3518E V300. ## Usage @@ -75,6 +75,7 @@ The format and content of the **init.cfg** file are as follows: "path" : "/bin/process1", "uid" : 1, "gid" : 1, + "secon" : "u:r:untrusted_app:s0", "once" : 0, "importance" : 1, "caps" : [0, 1, 2, 5] @@ -83,6 +84,7 @@ The format and content of the **init.cfg** file are as follows: "path" : "/bin/process2", "uid" : 2, "gid" : 2, + "secon" : "u:r:untrusted_app:s0", "once" : 1, "importance" : 0, "caps" : [] @@ -215,6 +217,11 @@ A single job can hold a maximum of 30 commands \(only **start**, **mkdir**, *

Group ID (GID) of the current service process.

+

secon

+ +

Security context of the current service process (no need to set currently).

+ +

once

Whether the current service process is a one-off process.

@@ -248,5 +255,5 @@ A single job can hold a maximum of 30 commands \(only **start**, **mkdir**, * [startup\_bootstrap\_lite](https://gitee.com/openharmony/startup_bootstrap_lite/blob/master/README.md) -**[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README.md)** +**[startup\_init\_lite]** diff --git a/README_zh.md b/README_zh.md index 2caa463d4f9b14ffd6e2523a6aca4f94a715ec11..4efaac39973a170153a6a103c36085eadd63414c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,252 +1,91 @@ -# init组件 - -- [简介](#section469617221261) -- [目录](#section15884114210197) -- [约束](#section12212842173518) -- [使用说明](#section837771600) -- [相关仓](#section641143415335) +# 启动子系统 ## 简介 init组件负责处理从内核加载第一个用户态进程开始,到第一个应用程序启动之间的系统服务进程启动过程。启动恢复子系统除负责加载各系统关键进程之外,还需在启动的同时设置其对应权限,并在子进程启动后对指定进程实行保活(若进程意外退出要重新启动),对于特殊进程意外退出时,启动恢复子系统还要执行系统复位操作。 -## 目录 +## 系统架构 + +**图 1** OHOS启动框架图 +![](figures/init系统架构.png) + +## 目录 +仓目录结构如下: ``` -base/startup/init_lite/ # init组件 -├── LICENSE -└── services - ├── include # init组件头文件目录 - ├── src # init组件源文件目录 - └── test # init组件测试用例源文件目录 - └── unittest -vendor -└──huawei - └──camera - └──init_configs # init配置文件目录(json格式,镜像烧写后部署于/etc/init.cfg) +base/startup/init/ +├── device_info # 提供设备信息的SA服务 +├── initsync # 同步命令(小型系统) +├── interfaces # 对外接口 +├── scripts # 脚本(LiteOS系统使用) +├── services +│   ├── begetctl # 命令集合。提供服务的dump,拉起等一系列命令 +│   ├── etc # init配置文件目录(标准系统) +│   ├── etc_lite # init配置文件目录(小型系统) +│   ├── include # init头文件目录 +│   ├── init # init核心功能源码 +│   │   ├── adapter # 内核适配层 +│   │   ├── include # 头文件目录 +│   │   ├── lite # init核心功能源码(小型系统) +│   │   └── standard # init核心功能源码(标准系统) +│   ├── log # init日志部件。 +│   ├── loopevent # 事件库 +│   │   ├── include # 头文件目录 +│   │   ├── loop # 基于epoll封装的I/O多路复用接口 +│   │   ├── signal # 信号处理接口封装。提供信号的添加,handler注册等功能 +│   │   ├── socket # socket通信接口 +│   │   ├── task # 事件的抽象任务,如signal, timer等事件都要创建对应task +│   │   ├── timer # 定时器接口 +│   │   └── utils # loopevent通用接口 +│   ├── modules # 插件化模块 +│   │   ├── bootchart # bootchart插件化源码 +│   │   ├── bootevent # bootevent插件化源码 +│   │   ├── init_hook # init提供的回调函数 +│   │   ├── reboot # reboot插件化源码 +│   │   ├── seccomp # seccomp插件化源码 +│   │   └── selinux # selinux插件化源码 +│   ├── param # 系统参数部件 +│   └── utils # init通用接口 +├── test # init组件测试用例源文件目录 +├── ueventd # ueventd服务源码 +│   ├── etc # ueventd配置文件目录 +│   ├── include # ueventd头文件目录 +│   ├── lite # ueventd核心功能源码(小型系统) +│   └── standard # ueventd核心功能源码(标准系统) +└── watchdog # 看门狗服务源码 ``` + ## 约束 -目前支持小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300。 +目前支持小型系统设备(参考内存≥1MB),标准系统Hi3516DV300、Hi3518EV300以及RK3568等 -## 使用说明 +## 说明 -init将系统启动分为三个阶段: +详细使用说明参考开发指南: -“pre-init”阶段:启动系统服务之前需要先执行的操作,例如挂载文件系统、创建文件夹、修改权限等 +[启动恢复子系统概述](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-overview.md) -“init”阶段:系统服务启动阶段 +[引导启动配置文件](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-cfg.md) -“post-init”阶段:系统服务启动完后还需要执行的操作 +[jobs管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-jobs.md) -上述每个阶段在配置文件init.cfg中都用一个job表示,每个job都对应一个命令集合,init通过依次执行每个job中的命令来完成系统初始化。job执行顺序:先执行“pre-init”,再执行“init”,最后执行“post-init”,所有job都集中放在init.cfg的jobs数组中。 +[插件](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-plugin.md) -除上述jobs数组之外,init.cfg中还有一个services数组,用于存放所有需要由init进程启动的系统关键服务的服务名、可执行文件路径、权限和其他属性信息。 +[沙盒管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sandbox.md) -配置文件init.cfg位于代码仓库/vendor/hisilicon/hispark\_aries/init\_configs/目录,部署在/etc/下,采用json格式,文件大小目前限制在100KB以内。 +[服务管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-service.md) -配置文件格式和内容说明如下所示: +[系统参数](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sysparam.md) -``` -{ - "jobs" : [{ - "name" : "pre-init", - "cmds" : [ - "mkdir /testdir", - "chmod 0700 /testdir", - "chown 99 99 /testdir", - "mkdir /testdir2", - "mount vfat /dev/mmcblk0p0 /testdir2 noexec nosuid" - ] - }, { - "name" : "init", - "cmds" : [ - "start service1", - "start service2" - ] - }, { - "name" : "post-init", - "cmds" : [] - } - ], - "services" : [{ - "name" : "service1", - "path" : "/bin/process1", - "uid" : 1, - "gid" : 1, - "once" : 0, - "importance" : 1, - "caps" : [0, 1, 2, 5] - }, { - "name" : "service2", - "path" : "/bin/process2", - "uid" : 2, - "gid" : 2, - "once" : 1, - "importance" : 0, - "caps" : [] - } - ] -} -``` +[日志管理](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-log.md) -**表 1** 执行job介绍 - - - - - - - - - - - - - - - - -

job名

-

说明

-

pre-init

-

最先执行的job,如果开发者的进程在启动之前需要首先执行一些操作(例如创建文件夹),可以把操作放到pre-init中先执行。

-

init

-

中间执行的job,例如服务启动。

-

post-init

-

最后被执行的job,如果开发者的进程在启动完成之后需要有一些处理(如驱动初始化后再挂载设备),可以把这类操作放到该job执行。

-
- -单个job最多支持30条命令(当前仅支持start/mkdir/chmod/chown/mount/loadcfg),命令名称和后面的参数(参数长度≤128字节)之间有且只能有一个空格。 - -**表 2** 命令集说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

命令

-

命令格式和示例

-

说明

-

mkdir

-

mkdir 目标文件夹

-

如:mkdir /storage/myDirectory

-

创建文件夹命令,mkdir和目标文件夹之间有且只能有一个空格。

-

chmod

-

chmod 权限 目标

-

如:chmod 0600 /storage/myFile.txt

-

chmod 0750 /storage/myDir

-

修改权限命令,chmod 权限 目标 之间间隔有且仅有一个空格,权限必须为0xxx格式。

-

chown

-

chown uid gid 目标

-

如:chown 900 800 /storage/myDir

-

chown 100 100 /storage/myFile.txt

-

修改属组命令,chown uid gid 目标 之间间隔有且仅有一个空格。

-

mount

-

mount fileSystemType src dst flags data

-

如:mount vfat /dev/mmcblk0 /sdc rw,umask=000

-

mount jffs2 /dev/mtdblock3 /storage nosuid

-

挂载命令,各参数之间有且仅有一个空格。flags当前仅支持nodev、noexec、nosuid、rdonly,data为可选字段。

-

start

-

start serviceName

-

如:start foundation

-

start shell

-

启动服务命令,start后面跟着service名称,该service名称必须能够在services数组中找到。

-

loadcfg

-

loadcfg filePath

-

如:loadcfg /patch/fstab.cfg

-

加载其他cfg文件命令。后面跟着的目标文件大小不得超过50KB,且目前仅支持加载/patch/fstab.cfg,其他文件路径和文件名均不支持。/patch/fstab.cfg文件的每一行都是一条命令,命令类型和格式必须符合本表格描述,命令条数不得超过20条。

-
- -**表 3** service字段说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

字段名

-

说明

-

name

-

当前服务的名称,须确保非空且长度≤32字节。

-

path

-

当前服务的可执行文件全路径和参数,数组形式。须确保第一个数组元素为可执行文件路径、数组元素个数≤20、每个元素为字符串形式以及每个字符串长度≤64字节。

-

uid

-

当前服务进程的uid值。

-

gid

-

当前服务进程的gid值。

-

once

-

当前服务进程是否为一次性进程:

-

1:一次性进程,当该进程退出时,init不会重新启动该服务进程

-

0 : 常驻进程,当该进程退出时,init收到SIGCHLD信号并重新启动该服务进程;

-

注意:对于常驻进程,若在4分钟之内连续退出5次,第5次退出时init将不会再重新拉起该服务进程。

-

importance

-

当前服务进程是否为关键系统进程:

-

0:非关键系统进程,当该进程退出时,init不会将系统复位重启;

-

1:关键系统进程,当该进程退出时,init将系统复位重启。

-

caps

-

当前服务所需的capability值,根据安全子系统已支持的capability,评估所需的capability,遵循最小权限原则配置(当前最多可配置100个值)。

-
+[组件化启动](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-boot-init-sub-unit.md) ## 相关仓 -[启动恢复子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%90%AF%E5%8A%A8%E6%81%A2%E5%A4%8D%E5%AD%90%E7%B3%BB%E7%BB%9F.md) - -[startup\_syspara\_lite](https://gitee.com/openharmony/startup_syspara_lite/blob/master/README_zh.md) - -[startup\_appspawn\_lite](https://gitee.com/openharmony/startup_appspawn_lite/blob/master/README_zh.md) - -[startup\_bootstrap\_lite](https://gitee.com/openharmony/startup_bootstrap_lite/blob/master/README_zh.md) +**[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite)** -**[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)** +[startup\_appspawn](https://gitee.com/openharmony/startup_appspawn) +[startup\_bootstrap\_lite](https://gitee.com/openharmony/startup_bootstrap_lite) diff --git a/begetd.gni b/begetd.gni new file mode 100644 index 0000000000000000000000000000000000000000..6d6cd9eeef71ce33344e231f9372cc055038eee6 --- /dev/null +++ b/begetd.gni @@ -0,0 +1,79 @@ +# Copyright (c) 2021 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. + +init_innerkits_path = "//base/startup/init/interfaces/innerkits" + +declare_args() { + enable_ohos_startup_init_feature_watcher = true + enable_ohos_startup_init_feature_deviceinfo = true + + # only for test + param_test = true + param_base_log = false + init_feature_ab_partition = false + + # init begetctl support liteos + init_feature_begetctl_liteos = false + + # only support mbedtls for hash + init_lite_use_thirdparty_mbedtls = true + init_lite_use_posix_file_api = false + config_ohos_startup_init_lite_data_path = "/" + + # enable process_priority for ohos_lite + init_feature_enable_lite_process_priority = false + + # config memory size for liteos-m + init_lite_memory_size = 5120 + + startup_init_feature_decode_group_file = false + + startup_init_test_performance = true + + # log display control + init_lite_no_log = false + + startup_init_with_param_base = false + if (!use_musl) { + startup_init_with_param_base = true + startup_init_feature_decode_group_file = true + } + + #deps appspawn_client + init_appspawn_client_module = true + + # begetutil extension module + init_begetutil_extra_modules = "" + init_extra_static_modules = "" + + init_use_encaps = false + + # erofs overlay feature switch + init_startup_feature_erofs_overlay = false + + # system call wrap switch + init_startup_feature_system_call_switch = false + + #deps param_watcher xcollie + init_paramwatcher_hicollie_enable = true + if (defined(global_parts_info) && + !defined(global_parts_info.hiviewdfx_hicollie)) { + init_paramwatcher_hicollie_enable = false + } + + # seccomp privilege + init_feature_seccomp_privilege = false + + # group_type support system + init_feature_group_type = true +} diff --git a/bundle.json b/bundle.json new file mode 100755 index 0000000000000000000000000000000000000000..28ceb22cd16f02c18c7539a6a7b671a373e05398 --- /dev/null +++ b/bundle.json @@ -0,0 +1,198 @@ +{ + "name": "@ohos/init", + "description": "ohos init process", + "homePage": "https://gitee.com/openharmony", + "version": "4.0.2", + "license": "Apache License 2.0", + "repository": "https://gitee.com/openharmony/startup_init", + "supplier": "Organization: OpenHarmony", + "publishAs": "code-segment", + "segment": { + "destPath": "base/startup/init" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "init", + "subsystem": "startup", + "syscap": [ + "SystemCapability.Startup.SystemInfo", + "SystemCapability.Startup.SystemInfo.Lite", + "SystemCapability.Base" + ], + "features": [ + "init_feature_begetctl_liteos", + "init_lite_use_posix_file_api", + "init_feature_ab_partition", + "init_feature_loader", + "init_lite_use_thirdparty_mbedtls", + "init_appspawn_client_module", + "init_feature_seccomp_privilege" + ], + "adapted_system_type": [ + "mini", + "small", + "standard" + ], + "rom": "3.9MB", + "ram": "8356KB", + "hisysevent_config": [ + "//base/startup/init/services/modules/sysevent/init_events.yaml" + ], + "deps": { + "components": [ + "appspawn", + "safwk", + "c_utils", + "napi", + "ipc", + "config_policy", + "hilog", + "hilog_lite", + "samgr", + "access_token", + "hvb", + "hisysevent", + "hiprofiler", + "bounds_checking_function", + "bundle_framework", + "selinux", + "selinux_adapter", + "storage_service", + "mbedtls", + "zlib", + "cJSON", + "mksh", + "libunwind", + "toybox", + "hicollie", + "drivers_interface_partitionslot" + ], + "third_party": [ + "mksh", + "e2fsprogs", + "f2fs-tools" + ] + }, + "build": { + "group_type": { + "base_group": [ + ], + "fwk_group": [ + "//base/startup/init:init_fwk_group" + ], + "service_group": [ + "//base/startup/init:init_service_group" + ] + }, + "inner_kits": [ + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/include/", + "header_files": [ + "init_socket.h", + "init_file.h", + "init_reboot.h", + "loop_event.h", + "hookmgr.h", + "service_control.h", + "beget_ext.h", + "systemcapability.h", + "syspara/parameter.h", + "syspara/parameters.h", + "syspara/param_wrapper.h", + "syspara/sysparam_errno.h", + "syspara/sysversion.h", + "param/init_param.h" + ] + }, + "name": "//base/startup/init/interfaces/innerkits:libbegetutil" + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/include/", + "header_files": [] + }, + "name": "//base/startup/init/interfaces/innerkits:libbegetutil_static", + "visibility": [ "updater" ] + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/include/fs_manager/", + "header_files": [ + "fs_manager.h" + ] + }, + "name": "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static" + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/include/fs_manager/", + "header_files": [] + }, + "name": "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static_real", + "visibility": [ "updater" ] + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/include/", + "header_files": [ + "service_watcher.h", + "syspara/parameter.h", + "syspara/sysparam_errno.h" + ] + }, + "name": "//base/startup/init/interfaces/innerkits:libbeget_proxy" + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits", + "header_files": [ + "init_module_engine/include/init_module_engine.h" + ] + }, + "name": "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/seccomp/include/", + "header_files": [ + "seccomp_policy.h" + ] + }, + "name": "//base/startup/init/interfaces/innerkits/seccomp:seccomp" + }, + { + "header": { + "header_base": "//base/startup/init/interfaces/innerkits/include/param", + "header_files": [ + ] + }, + "name": "//base/startup/init/interfaces/innerkits/zh_extral_dir:export_headers_lib" + }, + { + "header": { + "header_base": "//base/startup/init/services/param/base", + "header_files": [] + }, + "name": "//base/startup/init/services/param/base:parameterbase", + "visibility": [ "musl" ] + }, + { + "header": { + "header_base": "//base/startup/init/services/param/base", + "header_files": [] + }, + "name": "//base/startup/init/services/param/base:parameterbase_noflto", + "visibility": [ "musl" ] + }, + { + "name": "//base/startup/init/interfaces/kits/syscap_ts:syscap_ts" + } + ], + "test": [ + "//base/startup/init/test:testgroup" + ] + } + } +} diff --git a/device_info/BUILD.gn b/device_info/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e61fa2a7bb64726e4f960fbb505e9110c2a5cd26 --- /dev/null +++ b/device_info/BUILD.gn @@ -0,0 +1,92 @@ +# Copyright (c) 2021 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/begetd.gni") +if (!defined(ohos_lite)) { + import("//build/ohos.gni") + import("//build/ohos/sa_profile/sa_profile.gni") + + ohos_sa_profile("device_info_profile") { + sources = [ "etc/3902.json" ] + part_name = "init" + } + + ohos_prebuilt_etc("device_info.cfg") { + source = "etc/deviceinfoservice.cfg" + relative_install_dir = "init" + part_name = "init" + subsystem_name = "startup" + } + + ohos_shared_library("deviceinfoservice") { + sources = [ + "//base/startup/init/interfaces/innerkits/syspara/param_comm.c", + "device_info_stub.cpp", + ] + + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + shlib_type = "sa" + + include_dirs = [ + ".", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/syspara", + "//base/startup/init/interfaces/hals", + ] + defines = [ + "INIT_AGENT", + "_GNU_SOURCE", + "USE_MBEDTLS", + "DINFO_TAG=\"DeviceInfoService\"", + ] + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/modules/udid:libudidcomm", + "//base/startup/init/services/utils:libinit_utils", + ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "c_utils:utils", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + if (defined(global_parts_info) && + defined(global_parts_info.security_access_token)) { + external_deps += [ "access_token:libaccesstoken_sdk" ] + defines += [ "INIT_SUPPORT_ACCESS_TOKEN" ] + } + install_images = [ "system" ] + part_name = "init" + subsystem_name = "startup" + } +} + +group("device_info_group") { + if (!defined(ohos_lite) && enable_ohos_startup_init_feature_deviceinfo) { + deps = [ + ":device_info.cfg", + ":device_info_profile", + ":deviceinfoservice", + ] + } +} diff --git a/device_info/device_info.cpp b/device_info/device_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89947e2928058b86545a8fd9667e73c2d03297d9 --- /dev/null +++ b/device_info/device_info.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 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 "beget_ext.h" +#ifdef PARAM_FEATURE_DEVICEINFO +#include "device_info_kits.h" +#endif +#include "param_comm.h" +#include "securec.h" +#include "sysparam_errno.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +int AclGetDevUdid(char *udid, int size) +{ + if (udid == nullptr || size < UDID_LEN) { + return SYSPARAM_INVALID_INPUT; + } + (void)memset_s(udid, size, 0, size); +#ifdef PARAM_FEATURE_DEVICEINFO + std::string result = {}; + OHOS::device_info::DeviceInfoKits &instance = OHOS::device_info::DeviceInfoKits::GetInstance(); + int ret = instance.GetUdid(result); + if (ret == 0) { + ret = strcpy_s(udid, size, result.c_str()); + } +#else + int ret = GetDevUdid_(udid, size); +#endif + return ret; +} + +const char *AclGetSerial(void) +{ + static char serialNumber[MAX_SERIAL_LEN] = {0}; +#ifdef PARAM_FEATURE_DEVICEINFO + std::string result = {}; + OHOS::device_info::DeviceInfoKits &instance = OHOS::device_info::DeviceInfoKits::GetInstance(); + int ret = instance.GetSerialID(result); + if (ret == 0) { + ret = strcpy_s(serialNumber, sizeof(serialNumber), result.c_str()); + BEGET_ERROR_CHECK(ret == 0, return nullptr, "Failed to copy"); + } +#else + const char *tmpSerial = GetSerial_(); + if (tmpSerial != nullptr) { + int ret = strcpy_s(serialNumber, sizeof(serialNumber), tmpSerial); + BEGET_ERROR_CHECK(ret == 0, return nullptr, "Failed to copy"); + } +#endif + return serialNumber; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ diff --git a/device_info/device_info_kits.cpp b/device_info/device_info_kits.cpp new file mode 100644 index 0000000000000000000000000000000000000000..61c1424c8ff0a169756e92315f0ed226a5f4d658 --- /dev/null +++ b/device_info/device_info_kits.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021 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 "device_info_kits.h" + +#include "beget_ext.h" +#include "device_info_proxy.h" +#include "device_info_load.h" +#include "idevice_info.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "securec.h" +#include "sysparam_errno.h" + +namespace OHOS { +namespace device_info { + +static const int DEVINFO_SAID = 3902; +static const int DEVICEINFO_LOAD_SA_TIMEOUT_MS = 5000; + +DeviceInfoKits::DeviceInfoKits() {} + +DeviceInfoKits::~DeviceInfoKits() {} + +DeviceInfoKits &DeviceInfoKits::GetInstance() +{ + return DelayedRefSingleton::GetInstance(); +} + +void DeviceInfoKits::LoadDeviceInfoSa(std::unique_lock &lock) +{ + DINFO_LOGV("deviceInfoService_ is %d", deviceInfoService_ == nullptr); + if (deviceInfoService_ != nullptr) { + return; + } + auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + DINFO_CHECK(sam != nullptr, return, "GetSystemAbilityManager return null"); + + auto remoteObject = sam->CheckSystemAbility(DEVINFO_SAID); + if (remoteObject) { + DINFO_LOGV("deviceinfo sa is already loaded"); + deviceInfoService_ = iface_cast(remoteObject); + return; + } + sptr deviceInfoLoad = new (std::nothrow) DeviceInfoLoad(); + DINFO_CHECK(deviceInfoLoad != nullptr, return, "new deviceInfoLoad fail."); + + int32_t ret = sam->LoadSystemAbility(SYSPARAM_DEVICE_SERVICE_ID, deviceInfoLoad); + DINFO_CHECK(ret == ERR_OK, return, "LoadSystemAbility deviceinfo sa failed"); + + if (deathRecipient_ == nullptr) { + deathRecipient_ = new DeathRecipient(); + } + + // wait_for release lock and block until time out(60s) or match the condition with notice + auto waitStatus = deviceInfoLoadCon_.wait_for(lock, std::chrono::milliseconds(DEVICEINFO_LOAD_SA_TIMEOUT_MS), + [this]() { return deviceInfoService_ != nullptr; }); + if (!waitStatus || deviceInfoService_ == nullptr) { + // time out or loadcallback fail + DINFO_LOGE("tokensync load sa timeout"); + return; + } + + // for dead + auto object = deviceInfoService_->AsObject(); + if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) { + DINFO_LOGE("Failed to add death recipient"); + } +} + +sptr DeviceInfoKits::GetService(std::unique_lock &lock) +{ + LoadDeviceInfoSa(lock); + return deviceInfoService_; +} + +void DeviceInfoKits::FinishStartSASuccess(const sptr &remoteObject) +{ + DINFO_LOGI("get deviceinfo sa success."); + // get lock which wait_for release and send a notice so that wait_for can out of block + std::unique_lock lock(lock_); + deviceInfoService_ = iface_cast(remoteObject); + deviceInfoLoadCon_.notify_one(); +} + +void DeviceInfoKits::FinishStartSAFailed() +{ + DINFO_LOGI("Get deviceinfo sa failed."); + // get lock which wait_for release and send a notice + std::unique_lock lock(lock_); + deviceInfoService_ = nullptr; + deviceInfoLoadCon_.notify_one(); +} + +int32_t DeviceInfoKits::GetUdid(std::string& result) +{ + std::unique_lock lock(lock_); + static std::optional> resultPair; + if (resultPair.has_value()) { + int32_t ret = resultPair->first; + result = resultPair->second; + DINFO_LOGV("GetUdid from resultPair ret = %d", ret); + return ret; + } + auto deviceService = GetService(lock); + DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager"); + int ret = deviceService->GetUdid(result); + DINFO_LOGV("GetSerialID from remote ret = %d", ret); + if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) { + resultPair = std::make_optional(std::make_pair(ret, result)); + } + return ret; +} + +int32_t DeviceInfoKits::GetSerialID(std::string& result) +{ + std::unique_lock lock(lock_); + static std::optional> resultPair; + if (resultPair.has_value()) { + int32_t ret = resultPair->first; + result = resultPair->second; + DINFO_LOGV("GetSerialID from resultPair ret = %d", ret); + return ret; + } + auto deviceService = GetService(lock); + DINFO_CHECK(deviceService != nullptr, return -1, "Failed to get deviceinfo manager"); + int ret = deviceService->GetSerialID(result); + DINFO_LOGV("GetSerialID from remote ret = %d", ret); + if (ret == 0 || ret == SYSPARAM_PERMISSION_DENIED) { + resultPair = std::make_optional(std::make_pair(ret, result)); + } + return ret; +} + +void DeviceInfoKits::DeathRecipient::OnRemoteDied(const wptr &remote) +{ + DelayedRefSingleton::GetInstance().ResetService(remote); +} + +void DeviceInfoKits::ResetService(const wptr &remote) +{ + DINFO_LOGI("Remote is dead, reset service instance"); + std::lock_guard lock(lock_); + if (deviceInfoService_ != nullptr) { + sptr object = deviceInfoService_->AsObject(); + if ((object != nullptr) && (remote == object)) { + object->RemoveDeathRecipient(deathRecipient_); + deviceInfoService_ = nullptr; + } + } +} +} // namespace device_info +} // namespace OHOS diff --git a/device_info/device_info_kits.h b/device_info/device_info_kits.h new file mode 100644 index 0000000000000000000000000000000000000000..9f3e71cc1b13a851e506af1a9b2536361dc3b91d --- /dev/null +++ b/device_info/device_info_kits.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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 OHOS_SYSTEM_DEVICE_ID_KITS_S +#define OHOS_SYSTEM_DEVICE_ID_KITS_S +#include +#include "idevice_info.h" +#include "singleton.h" +#include "beget_ext.h" + +namespace OHOS { +namespace device_info { +class INIT_LOCAL_API DeviceInfoKits final : public DelayedRefSingleton { + DECLARE_DELAYED_REF_SINGLETON(DeviceInfoKits); +public: + DISALLOW_COPY_AND_MOVE(DeviceInfoKits); + + static DeviceInfoKits &GetInstance(); + int32_t GetUdid(std::string& result); + int32_t GetSerialID(std::string& result); + + void FinishStartSASuccess(const sptr &remoteObject); + void FinishStartSAFailed(); + void ResetService(const wptr &remote); +private: + // For death event procession + class DeathRecipient final : public IRemoteObject::DeathRecipient { + public: + DeathRecipient(void) = default; + ~DeathRecipient(void) final = default; + DISALLOW_COPY_AND_MOVE(DeathRecipient); + void OnRemoteDied(const wptr &remote) final; + }; + sptr GetDeathRecipient(void) + { + return deathRecipient_; + } + + void LoadDeviceInfoSa(std::unique_lock &lock); + sptr GetService(std::unique_lock &lock); + std::mutex lock_; + std::condition_variable deviceInfoLoadCon_; + sptr deathRecipient_ {}; + sptr deviceInfoService_ {}; +}; +} // namespace device_info +} // namespace OHOS +#endif // OHOS_SYSTEM_DEVICE_ID_KITS_S diff --git a/device_info/device_info_load.cpp b/device_info/device_info_load.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e392ebe8571bcd3e34d9d730a3209db0ecb2c183 --- /dev/null +++ b/device_info/device_info_load.cpp @@ -0,0 +1,52 @@ +/* + * 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 "device_info_load.h" + +#include "device_info_kits.h" +#include "system_ability_definition.h" + +namespace OHOS { +namespace device_info { +DeviceInfoLoad::DeviceInfoLoad() +{ +} + +void DeviceInfoLoad::OnLoadSystemAbilitySuccess(int32_t systemAbilityId, + const sptr& remoteObject) +{ + DINFO_CHECK(systemAbilityId == SYSPARAM_DEVICE_SERVICE_ID, return, + "start systemabilityId is not deviceinfo! %d", systemAbilityId); + if (remoteObject == nullptr) { + DINFO_LOGI("OnLoadSystemAbilitySuccess but remote is null %d", systemAbilityId); + DeviceInfoKits::GetInstance().FinishStartSAFailed(); + return; + } + + DINFO_LOGI("OnLoadSystemAbilitySuccess start systemAbilityId: %d success!", systemAbilityId); + DeviceInfoKits::GetInstance().FinishStartSASuccess(remoteObject); +} + +void DeviceInfoLoad::OnLoadSystemAbilityFail(int32_t systemAbilityId) +{ + DINFO_CHECK(systemAbilityId == SYSPARAM_DEVICE_SERVICE_ID, return, + "start systemabilityId is not deviceinfo! %d", systemAbilityId); + + DINFO_LOGI("OnLoadSystemAbilityFail systemAbilityId: %d failed.", systemAbilityId); + + DeviceInfoKits::GetInstance().FinishStartSAFailed(); +} +} // namespace device_info +} // namespace OHOS diff --git a/device_info/device_info_load.h b/device_info/device_info_load.h new file mode 100644 index 0000000000000000000000000000000000000000..9cf74126f2188715e887902dc1531112aae5f176 --- /dev/null +++ b/device_info/device_info_load.h @@ -0,0 +1,34 @@ +/* + * 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 DEVICE_INFO_LOAD_H +#define DEVICE_INFO_LOAD_H + +#include "system_ability_load_callback_stub.h" +#include "idevice_info.h" + +namespace OHOS { +namespace device_info { +class DeviceInfoLoad : public SystemAbilityLoadCallbackStub { +public: + explicit DeviceInfoLoad(); + + void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr& remoteObject); + void OnLoadSystemAbilityFail(int32_t systemAbilityId); +private: +}; +} // namespace device_info +} // namespace OHOS +#endif // DEVICE_INFO_LOAD_H diff --git a/device_info/device_info_proxy.cpp b/device_info/device_info_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffe8acf4e801b9101efae47ba8ea14356783fbc3 --- /dev/null +++ b/device_info/device_info_proxy.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 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 "device_info_proxy.h" + +#include "beget_ext.h" +#include "idevice_info.h" +#include "parcel.h" +#include "string_ex.h" +#include "sysparam_errno.h" +#include "deviceinfoservice_ipc_interface_code.h" + +namespace OHOS { +namespace device_info { +int32_t DeviceInfoProxy::DeviceInfoSendRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ +#ifdef STARTUP_INIT_TEST + int ret = 0; +#else + int ret = SYSPARAM_SYSTEM_ERROR; +#endif + auto remote = Remote(); + if (remote != nullptr) { + ret = remote->SendRequest(code, data, reply, option); + } + return ret; +} + +int32_t DeviceInfoProxy::GetUdid(std::string& result) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option { MessageOption::TF_SYNC }; + data.WriteInterfaceToken(DeviceInfoProxy::GetDescriptor()); + int32_t ret = DeviceInfoSendRequest(static_cast (DeviceInfoInterfaceCode::COMMAND_GET_UDID), + data, reply, option); + DINFO_CHECK(ret == ERR_NONE, return ret, "getUdid failed, error code is %d", ret); + result = Str16ToStr8(reply.ReadString16()); + return ERR_OK; +} + +int32_t DeviceInfoProxy::GetSerialID(std::string& result) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option { MessageOption::TF_SYNC }; + + data.WriteInterfaceToken(DeviceInfoProxy::GetDescriptor()); + int32_t ret = DeviceInfoSendRequest(static_cast (DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID), + data, reply, option); + DINFO_CHECK(ret == ERR_NONE, return ret, "GetSerial failed, error code is %d", ret); + result = Str16ToStr8(reply.ReadString16()); + return ERR_OK; +} +} // namespace device_info +} // namespace OHOS diff --git a/device_info/device_info_proxy.h b/device_info/device_info_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..ca7acef3ff8617c715170c426b27660b3f134348 --- /dev/null +++ b/device_info/device_info_proxy.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 OHOS_SYSTEM_DEVICEIDPROXY_H +#define OHOS_SYSTEM_DEVICEIDPROXY_H + +#include "iremote_proxy.h" +#include "idevice_info.h" +#include "beget_ext.h" + +namespace OHOS { +namespace device_info { +class INIT_LOCAL_API DeviceInfoProxy : public IRemoteProxy { +public: + explicit DeviceInfoProxy(const sptr &impl) : IRemoteProxy(impl) {} + virtual ~DeviceInfoProxy() {} + + int32_t GetUdid(std::string& result) override; + int32_t GetSerialID(std::string& result) override; +private: + int32_t DeviceInfoSendRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option); + static inline BrokerDelegator delegator_; +}; +} // namespace system +} // namespace OHOS +#endif // OHOS_SYSTEM_DEVICEIDPROXY_H \ No newline at end of file diff --git a/device_info/device_info_stub.cpp b/device_info/device_info_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbe51d262bb67bbe27b6d896a25733395fdbab40 --- /dev/null +++ b/device_info/device_info_stub.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021 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 "device_info_stub.h" + +#include +#include + +#include "beget_ext.h" +#include "idevice_info.h" +#include "ipc_skeleton.h" +#ifdef INIT_SUPPORT_ACCESS_TOKEN +#include "accesstoken_kit.h" +#endif +#include "parcel.h" +#include "string_ex.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "param_comm.h" +#include "parameter.h" +#include "sysparam_errno.h" +#include "init_utils.h" +#include "deviceinfoservice_ipc_interface_code.h" + +namespace OHOS { +#ifdef INIT_SUPPORT_ACCESS_TOKEN +using namespace Security; +using namespace Security::AccessToken; +#endif + +namespace device_info { +REGISTER_SYSTEM_ABILITY_BY_ID(DeviceInfoService, SYSPARAM_DEVICE_SERVICE_ID, true) + +static std::mutex g_lock; +static struct timespec g_lastTime; +#ifndef STARTUP_INIT_TEST +static const int DEVICE_INFO_EXIT_TIMEOUT_S = 60; +#else +static const int DEVICE_INFO_EXIT_TIMEOUT_S = 3; +#endif +static const int DEVICE_INFO_EXIT_WAITTIMES = 12; + +static int UnloadDeviceInfoSa(void) +{ + { + std::unique_lock lock(g_lock); + struct timespec currTimer = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &currTimer); + if (IntervalTime(&g_lastTime, &currTimer) < DEVICE_INFO_EXIT_TIMEOUT_S) { + return 0; + } + } + DINFO_LOGI("DeviceInfoService::UnloadDeviceInfoSa"); + auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + DINFO_CHECK(sam != nullptr, return 0, "GetSystemAbilityManager return null"); + + int32_t ret = sam->UnloadSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + DINFO_CHECK(ret == ERR_OK, return 0, "UnLoadSystemAbility deviceinfo sa failed"); + return 1; +} + +int32_t DeviceInfoStub::OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string myDescriptor = IDeviceInfo::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + DINFO_CHECK(myDescriptor == remoteDescriptor, return ERR_FAIL, "Invalid remoteDescriptor"); + + { + std::unique_lock lock(g_lock); + (void)clock_gettime(CLOCK_MONOTONIC, &g_lastTime); + } + + int ret = ERR_FAIL; + switch (code) { + case static_cast(DeviceInfoInterfaceCode::COMMAND_GET_UDID): { + if (!CheckPermission(data, "ohos.permission.sec.ACCESS_UDID")) { + return SYSPARAM_PERMISSION_DENIED; + } + char localDeviceInfo[UDID_LEN] = {0}; + ret = GetDevUdid_(localDeviceInfo, UDID_LEN); + DINFO_CHECK(ret == 0, break, "Failed to get dev udid"); + reply.WriteString16(Str8ToStr16(localDeviceInfo)); + break; + } + case static_cast(DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID): { + if (!CheckPermission(data, "ohos.permission.sec.ACCESS_UDID")) { + return SYSPARAM_PERMISSION_DENIED; + } + const char *serialNumber = GetSerial_(); + DINFO_CHECK(serialNumber != nullptr, break, "Failed to get serialNumber"); + reply.WriteString16(Str8ToStr16(serialNumber)); + ret = ERR_NONE; + break; + } + default: { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } + return ret; +} + +bool DeviceInfoStub::CheckPermission(MessageParcel &data, const std::string &permission) +{ +#ifdef INIT_SUPPORT_ACCESS_TOKEN + AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID(); + int32_t result = TypePermissionState::PERMISSION_GRANTED; + int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(callerToken); + if (tokenType == TOKEN_INVALID) { + DINFO_LOGE("AccessToken type:%d, permission:%d denied!", tokenType, callerToken); + return false; + } else { + result = AccessTokenKit::VerifyAccessToken(callerToken, permission); + } + if (result == TypePermissionState::PERMISSION_DENIED) { + DINFO_LOGE("permission:%s denied!", permission.c_str()); + return false; + } + return true; +#else + DINFO_LOGE("CheckPermission is not supported"); + return false; +#endif +} + +int32_t DeviceInfoService::GetUdid(std::string& result) +{ + return 0; +} +int32_t DeviceInfoService::GetSerialID(std::string& result) +{ + return 0; +} + +void DeviceInfoService::OnStart(void) +{ + int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_INFO); + SetInitLogLevel((InitLogLevel)level); + DINFO_LOGI("DeviceInfoService OnStart"); + bool res = Publish(this); + if (!res) { + DINFO_LOGE("DeviceInfoService Publish failed"); + } + threadStarted_ = true; + std::thread([this] {this->ThreadForUnloadSa();}).detach(); + return; +} + +void DeviceInfoService::OnStop(void) +{ + threadStarted_ = false; + DINFO_LOGI("DeviceInfoService OnStop"); +} + +int DeviceInfoService::Dump(int fd, const std::vector& args) +{ + (void)args; + DINFO_LOGI("DeviceInfoService Dump"); + DINFO_CHECK(fd >= 0, return -1, "Invalid fd for dump %d", fd); + return dprintf(fd, "%s\n", "No information to dump for this service"); +} + +void DeviceInfoService::ThreadForUnloadSa(void) +{ + while (1) { + std::this_thread::sleep_for(std::chrono::seconds(DEVICE_INFO_EXIT_TIMEOUT_S / DEVICE_INFO_EXIT_WAITTIMES)); + if (!threadStarted_) { + break; + } + if (UnloadDeviceInfoSa() == 1) { + break; + } + } +} +} // namespace device_info +} // namespace OHOS diff --git a/device_info/device_info_stub.h b/device_info/device_info_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..d0d7a9b93fe64fe1aad6af35108ba94c4e84b816 --- /dev/null +++ b/device_info/device_info_stub.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 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 OHOS_SYSTEM_DEVICEIDSTUB_H +#define OHOS_SYSTEM_DEVICEIDSTUB_H + +#include +#include +#include "iremote_stub.h" +#include "idevice_info.h" +#include "system_ability.h" + +namespace OHOS { +namespace device_info { +class DeviceInfoStub : public IRemoteStub { +public: + explicit DeviceInfoStub(bool serialInvokeFlag = true) + : IRemoteStub(serialInvokeFlag), serialInvokeFlag_(serialInvokeFlag) {} + int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption &option) override; + bool serialInvokeFlag_ = { true }; +private: + bool CheckPermission(MessageParcel &data, const std::string &permission); +}; + +class DeviceInfoService : public SystemAbility, public DeviceInfoStub { +public: + DECLARE_SYSTEM_ABILITY(DeviceInfoService); + DISALLOW_COPY_AND_MOVE(DeviceInfoService); + explicit DeviceInfoService(int32_t systemAbilityId, bool runOnCreate = true) + : SystemAbility(systemAbilityId, runOnCreate) + { + } + ~DeviceInfoService() override {} + int32_t GetUdid(std::string& result) override; + int32_t GetSerialID(std::string& result) override; +protected: + void OnStart(void) override; + void OnStop(void) override; + int Dump(int fd, const std::vector& args) override; + void ThreadForUnloadSa(void); + std::atomic_bool threadStarted_ { false }; +}; +} // namespace device_info +} // namespace OHOS +#endif // OHOS_SYSTEM_DEVICEIDSTUB_H \ No newline at end of file diff --git a/device_info/deviceinfoservice_ipc_interface_code.h b/device_info/deviceinfoservice_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..f97c9464bd0e8ce3fdb6ab2f6b6f8186542afce9 --- /dev/null +++ b/device_info/deviceinfoservice_ipc_interface_code.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 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 DEVICEINFOSERVICE_IPC_INTERFACE_CODE_H +#define DEVICEINFOSERVICE_IPC_INTERFACE_CODE_H + +/* SAID: 3902 */ +namespace OHOS { +namespace device_info { +enum class DeviceInfoInterfaceCode { + COMMAND_GET_UDID = 1, + COMMAND_GET_SERIAL_ID = 2, +}; +} // namespace device_info +} // namespace OHOS + +#endif // DEVICEINFOSERVICE_IPC_INTERFACE_CODE_H diff --git a/device_info/etc/3902.json b/device_info/etc/3902.json new file mode 100644 index 0000000000000000000000000000000000000000..4eeaf8415761e9d1eb09dbb2f935ec20e7bc6279 --- /dev/null +++ b/device_info/etc/3902.json @@ -0,0 +1,12 @@ +{ + "process": "deviceinfoservice", + "systemability": [ + { + "name": 3902, + "libpath": "libdeviceinfoservice.z.so", + "run-on-create": true, + "distributed": false, + "dump_level": 1 + } + ] +} \ No newline at end of file diff --git a/device_info/etc/deviceinfoservice.cfg b/device_info/etc/deviceinfoservice.cfg new file mode 100755 index 0000000000000000000000000000000000000000..6a4ca239c2e9d5c74e8d9f510671ef55b03c2111 --- /dev/null +++ b/device_info/etc/deviceinfoservice.cfg @@ -0,0 +1,12 @@ +{ + "services" : [{ + "name" : "deviceinfoservice", + "path" : ["/system/bin/sa_main", "/system/profile/deviceinfoservice.json"], + "uid" : "deviceinfo", + "gid" : ["deviceinfo", "shell"], + "ondemand" : true, + "secon" : "u:r:deviceinfoservice:s0", + "recycle-strategy": "low-memory" + } + ] +} \ No newline at end of file diff --git a/device_info/idevice_info.h b/device_info/idevice_info.h new file mode 100644 index 0000000000000000000000000000000000000000..14791c93a2768bc6334ebd178fb33ce99832004d --- /dev/null +++ b/device_info/idevice_info.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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 OHOS_SYSTEM_IDEVICEID_H +#define OHOS_SYSTEM_IDEVICEID_H + +#include +#include "beget_ext.h" +#include "iremote_broker.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace device_info { +class IDeviceInfo : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"ohos.system.IDeviceInfo"); + + virtual int32_t GetUdid(std::string& result) = 0; + virtual int32_t GetSerialID(std::string& result) = 0; + + static constexpr int ERR_FAIL = -1; +}; +} // namespace device_info +} // namespace OHOS + +#ifndef DINFO_DOMAIN +#define DINFO_DOMAIN (BASE_DOMAIN + 8) +#endif + +#ifndef DINFO_TAG +#define DINFO_TAG "DeviceInfoKits" +#endif + +#define DINFO_LOGI(fmt, ...) STARTUP_LOGI(DINFO_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) +#define DINFO_LOGE(fmt, ...) STARTUP_LOGE(DINFO_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) +#define DINFO_LOGV(fmt, ...) STARTUP_LOGV(DINFO_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) + +#define DINFO_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + DINFO_LOGE(__VA_ARGS__); \ + exper; \ + } +#define DINFO_ONLY_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + exper; \ + } + +#endif // OHOS_SYSTEM_IDEVICEID_H \ No newline at end of file diff --git "a/figures/init\347\263\273\347\273\237\346\236\266\346\236\204.png" "b/figures/init\347\263\273\347\273\237\346\236\266\346\236\204.png" new file mode 100644 index 0000000000000000000000000000000000000000..b6a2c9eb76c086e8c48a9e60facd4936305b18fb Binary files /dev/null and "b/figures/init\347\263\273\347\273\237\346\236\266\346\236\204.png" differ diff --git a/initsync/BUILD.gn b/initsync/BUILD.gn index 773ee36c3b2b0c823a13ee80eacaf9e066726188..f6e0f22fb5ec03eed33bbc1c36db0350886e5db1 100644 --- a/initsync/BUILD.gn +++ b/initsync/BUILD.gn @@ -14,30 +14,29 @@ import("//build/lite/config/component/lite_component.gni") lite_component("initsync") { - features = [ "//base/startup/init_lite/initsync:libinitsync_shared" ] + features = [ "//base/startup/init/initsync:libinitsync_shared" ] } shared_library("libinitsync_shared") { sources = [ "src/init_sync.c" ] - cflags = [ "-Wall" ] include_dirs = [ - "//base/startup/init_lite/initsync/include", - "//base/startup/init_lite/interfaces/kits", - "//base/startup/init_lite/services/log", - ] - public_deps = [ - "//base/startup/init_lite/services/log:init_log", - "//third_party/bounds_checking_function:libsec_shared", + "//base/startup/init/initsync/include", + "//base/startup/init/interfaces/kits/syscap", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", ] + public_deps = [ "//base/startup/init/services/log:init_log" ] + + external_deps = [ "bounds_checking_function:libsec_shared" ] } static_library("libinitsync_static") { sources = [ "src/init_sync.c" ] - cflags = [ "-Wall" ] include_dirs = [ - "//base/startup/init_lite/initsync/include", - "//base/startup/init_lite/interfaces/kits", - "//base/startup/init_lite/services/log", + "//base/startup/init/initsync/include", + "//base/startup/init/interfaces/kits/syscap", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", ] - public_deps = [ "//third_party/bounds_checking_function:libsec_static" ] + external_deps = [ "bounds_checking_function:libsec_static" ] } diff --git a/initsync/include/init_stage.h b/initsync/include/init_stage.h index 7d5b7848b38e6f62cf6c707df5b8d38911d18800..e1c3b8723067f047de87693b0ee467e18a30fb94 100644 --- a/initsync/include/init_stage.h +++ b/initsync/include/init_stage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -51,7 +51,7 @@ typedef struct { #define QUICKSTART_NODE "/dev/quickstart" -/* Simple sample Useage: +/* Simple sample Usage: * INIT PROCESS * SystemInitStage(QS_STAGE1)----(1)fork----> key APP * |(2) |(3) diff --git a/initsync/src/init_sync.c b/initsync/src/init_sync.c index 73ba642b7afcddc341e892277ae9104ad60a97ad..e58145b6cc970367cc6c35704bf1b3e99065544b 100644 --- a/initsync/src/init_sync.c +++ b/initsync/src/init_sync.c @@ -18,14 +18,13 @@ #include #include #include -#include -#include #include #include #include #include #include #include "init_log.h" + static int SendCmd(int cmd, unsigned long arg) { int fd = open(QUICKSTART_NODE, O_RDONLY); diff --git a/interfaces/hals/hal_sys_param.h b/interfaces/hals/hal_sys_param.h new file mode 100644 index 0000000000000000000000000000000000000000..c2aea3097d035c5d34b7aa541a250ab46e74a8b2 --- /dev/null +++ b/interfaces/hals/hal_sys_param.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020-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 HAL_SYS_PARAM_H +#define HAL_SYS_PARAM_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +const char* HalGetDeviceType(void); +const char* HalGetManufacture(void); +const char* HalGetBrand(void); +const char* HalGetMarketName(void); +const char* HalGetProductSeries(void); +const char* HalGetProductModel(void); +const char* HalGetSoftwareModel(void); +const char* HalGetHardwareModel(void); +const char* HalGetHardwareProfile(void); +const char* HalGetSerial(void); +const char* HalGetBootloaderVersion(void); +const char* HalGetAbiList(void); +const char* HalGetDisplayVersion(void); +const char* HalGetIncrementalVersion(void); +const char* HalGetBuildType(void); +const char* HalGetBuildUser(void); +const char* HalGetBuildHost(void); +const char* HalGetBuildTime(void); +int HalGetFirstApiVersion(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // HAL_SYS_PARAM_H \ No newline at end of file diff --git a/interfaces/hals/hal_token.h b/interfaces/hals/hal_token.h new file mode 100644 index 0000000000000000000000000000000000000000..7ed1f1ca7b6c5d33d80413199d2d92a44d01bb1d --- /dev/null +++ b/interfaces/hals/hal_token.h @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2020-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 HAL_TOKEN_H +#define HAL_TOKEN_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define KIT_FRAMEWORK_UID_MAX 1000 + +/** + * @brief Read token value from device. + * + * @param token the result token value, if read successfully. + * @param len length of the token. + * @returns 0 if success and get the update area token, + * 1 if success and get the pre-made token, + * -1 if failed, + * -2 if no pre-made token. + */ +int HalReadToken(char *token, unsigned int len); + +/** + * @brief Write token value to device. + * + * @param token the token to write. + * @param len length of the token. + * @returns 0 if success, otherwise -1. + */ +int HalWriteToken(const char *token, unsigned int len); + +/** + * @brief Get AcKey value from device. + * + * @param acKey the result acKey, if get successfully. + * @param len length of the acKey. + * @returns 0 if success, otherwise -1. + */ +int HalGetAcKey(char *acKey, unsigned int len); + +/** + * @brief Get ProdId value from device. + * + * @param productId product IDs to be populated with. + * @param len length of the productId. + * @returns 0 if success, otherwise -1. + */ +int HalGetProdId(char *productId, unsigned int len); + +/** + * @brief Get ProdKey value from device. + * + * @param productKey The productKey value + * @param len The productKey len. + * @returns 0 if success, otherwise -1. + */ +int HalGetProdKey(char *productKey, unsigned int len); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // HAL_TOKEN_H diff --git a/interfaces/hals/utils/sys_param/BUILD.gn b/interfaces/hals/utils/sys_param/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..73e041b58442a860991c8fdb16ce7d7dbd50f2dd --- /dev/null +++ b/interfaces/hals/utils/sys_param/BUILD.gn @@ -0,0 +1,26 @@ +# +# Copyright (c) 2020-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. + +static_library("hal_sys_param") { + sources = [ "hal_sys_param.c" ] + include_dirs = [ "//base/startup/init/interfaces/hals" ] + defines = [ + "INCREMENTAL_VERSION=\"${ohos_version}\"", + "BUILD_TYPE=\"${ohos_build_type}\"", + "BUILD_USER=\"${ohos_build_user}\"", + "BUILD_TIME=\"${ohos_build_time}\"", + "BUILD_HOST=\"${ohos_build_host}\"", + "BUILD_ROOTHASH=\"${ohos_build_roothash}\"", + ] +} diff --git a/interfaces/hals/utils/sys_param/hal_sys_param.c b/interfaces/hals/utils/sys_param/hal_sys_param.c new file mode 100644 index 0000000000000000000000000000000000000000..a373b0b217e16e24bc3e9a161b92e220e7191ef1 --- /dev/null +++ b/interfaces/hals/utils/sys_param/hal_sys_param.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020-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 "hal_sys_param.h" + +static const char OHOS_ABI_LIST[] = {"****"}; +static const char OHOS_BOOTLOADER_VERSION[] = {"bootloader"}; +static const char OHOS_BRAND[] = {"****"}; +static const char OHOS_DEVICE_TYPE[] = {"****"}; +static const char OHOS_DISPLAY_VERSION[] = {"OpenHarmony 3.1"}; +static const char OHOS_HARDWARE_MODEL[] = {"****"}; +static const char OHOS_HARDWARE_PROFILE[] = {"aout:true,display:true"}; +static const char OHOS_MARKET_NAME[] = {"****"}; +static const char OHOS_MANUFACTURE[] = {"****"}; +static const char OHOS_PRODUCT_MODEL[] = {"****"}; +static const char OHOS_PRODUCT_SERIES[] = {"****"}; +static const char OHOS_SERIAL[] = {"****"}; // provided by OEM. +static const char OHOS_SOFTWARE_MODEL[] = {"****"}; +static const int OHOS_FIRST_API_VERSION = 1; + +__attribute__((weak)) const char* HalGetDeviceType(void) +{ + return OHOS_DEVICE_TYPE; +} + +__attribute__((weak)) const char* HalGetManufacture(void) +{ + return OHOS_MANUFACTURE; +} + +__attribute__((weak)) const char* HalGetBrand(void) +{ + return OHOS_BRAND; +} + +__attribute__((weak)) const char* HalGetMarketName(void) +{ + return OHOS_MARKET_NAME; +} + +__attribute__((weak)) const char* HalGetProductSeries(void) +{ + return OHOS_PRODUCT_SERIES; +} + +__attribute__((weak)) const char* HalGetProductModel(void) +{ + return OHOS_PRODUCT_MODEL; +} + +__attribute__((weak)) const char* HalGetSoftwareModel(void) +{ + return OHOS_SOFTWARE_MODEL; +} + +__attribute__((weak)) const char* HalGetHardwareModel(void) +{ + return OHOS_HARDWARE_MODEL; +} + +__attribute__((weak)) const char* HalGetHardwareProfile(void) +{ + return OHOS_HARDWARE_PROFILE; +} + +__attribute__((weak)) const char* HalGetSerial(void) +{ + return OHOS_SERIAL; +} + +__attribute__((weak)) const char* HalGetBootloaderVersion(void) +{ + return OHOS_BOOTLOADER_VERSION; +} + +__attribute__((weak)) const char* HalGetAbiList(void) +{ + return OHOS_ABI_LIST; +} + +__attribute__((weak)) const char* HalGetDisplayVersion(void) +{ + return OHOS_DISPLAY_VERSION; +} + +__attribute__((weak)) const char* HalGetIncrementalVersion(void) +{ + return INCREMENTAL_VERSION; +} + +__attribute__((weak)) const char* HalGetBuildType(void) +{ + return BUILD_TYPE; +} + +__attribute__((weak)) const char* HalGetBuildUser(void) +{ + return BUILD_USER; +} + +__attribute__((weak)) const char* HalGetBuildHost(void) +{ + return BUILD_HOST; +} + +__attribute__((weak)) const char* HalGetBuildTime(void) +{ + return BUILD_TIME; +} + +__attribute__((weak)) int HalGetFirstApiVersion(void) +{ + return OHOS_FIRST_API_VERSION; +} \ No newline at end of file diff --git a/interfaces/hals/utils/token/BUILD.gn b/interfaces/hals/utils/token/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..95c818a966a659e44809cc8652149e8d8de69e54 --- /dev/null +++ b/interfaces/hals/utils/token/BUILD.gn @@ -0,0 +1,22 @@ +# +# Copyright (c) 2020-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. + +static_library("static_hal_token") { + sources = [ "hal_token.c" ] + include_dirs = [ + "//base/startup/init/interfaces/hals", + "//commonlibrary/utils_lite/include", + ] + deps = [] +} diff --git a/interfaces/hals/utils/token/hal_token.c b/interfaces/hals/utils/token/hal_token.c new file mode 100644 index 0000000000000000000000000000000000000000..99512a5edeb639db0ec76b24a01ddc61b4aedd3b --- /dev/null +++ b/interfaces/hals/utils/token/hal_token.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020-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 "hal_token.h" +#include "ohos_errno.h" +#include "ohos_types.h" + +__attribute__((weak)) static int OEMReadToken(char* token, unsigned int len) +{ + // OEM need add here, read token from device + (void)(token); + (void)(len); + return EC_SUCCESS; +} + +__attribute__((weak)) static int OEMWriteToken(const char* token, unsigned int len) +{ + // OEM need add here, write token to device + (void)(token); + (void)(len); + return EC_SUCCESS; +} + +__attribute__((weak)) static int OEMGetAcKey(char* acKey, unsigned int len) +{ + // OEM need add here, get AcKey + (void)(acKey); + (void)(len); + return EC_SUCCESS; +} + +__attribute__((weak)) static int OEMGetProdId(char* productId, unsigned int len) +{ + // OEM need add here, get ProdId + (void)(productId); + (void)(len); + return EC_SUCCESS; +} + +__attribute__((weak)) static int OEMGetProdKey(char* productKey, unsigned int len) +{ + // OEM need add here, get ProdKey + (void)(productKey); + (void)(len); + return EC_SUCCESS; +} + +__attribute__((weak)) int HalReadToken(char* token, unsigned int len) +{ + if (token == NULL) { + return EC_FAILURE; + } + + return OEMReadToken(token, len); +} + +__attribute__((weak)) int HalWriteToken(const char* token, unsigned int len) +{ + if (token == NULL) { + return EC_FAILURE; + } + + return OEMWriteToken(token, len); +} + +__attribute__((weak)) int HalGetAcKey(char* acKey, unsigned int len) +{ + if (acKey == NULL) { + return EC_FAILURE; + } + + return OEMGetAcKey(acKey, len); +} + +__attribute__((weak)) int HalGetProdId(char* productId, unsigned int len) +{ + if (productId == NULL) { + return EC_FAILURE; + } + + return OEMGetProdId(productId, len); +} + +__attribute__((weak)) int HalGetProdKey(char* productKey, unsigned int len) +{ + if (productKey == NULL) { + return EC_FAILURE; + } + + return OEMGetProdKey(productKey, len); +} \ No newline at end of file diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..b9eddfd1140acbcb5a78ee0a356436d196b62812 --- /dev/null +++ b/interfaces/innerkits/BUILD.gn @@ -0,0 +1,346 @@ +# Copyright (c) 2021-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/begetd.gni") +if (!defined(ohos_lite) || init_feature_begetctl_liteos) { + syspara_sources = [ + "syscap/init_syscap.c", + "syspara/param_comm.c", + "syspara/parameter.c", + "syspara/sysversion.c", + ] +} + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/include/token", + "//base/startup/init/interfaces/innerkits/include/param", + ] +} + +include_common = [ + "./include", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/hals", + "//base/startup/init/interfaces/innerkits/syspara", + "//base/startup/init/services/param/include", +] + +if (defined(ohos_lite)) { + import("//build/lite/config/component/lite_component.gni") + import("//build/lite/ndk/ndk.gni") + + if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + shared_library("libbegetutil") { + cflags = [ "-fPIC" ] + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + ] + sources = [] + include_dirs = include_common + include_dirs += [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits" ] + public_configs = [ ":exported_header_files" ] + deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/services/modules/init_hook:inithook", + ] + deps += [ + "//base/startup/init/services/log:init_log", + "//base/startup/init/services/modules/udid:libudidcomm", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ "bounds_checking_function:libsec_shared" ] + if (init_feature_begetctl_liteos) { + sources += syspara_sources + defines += [ "LITEOS_SUPPORT" ] + deps += [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ] + } else { + sources += [ "syscap/init_syscap.c" ] + } + if (ohos_kernel_type == "liteos_a") { + defines += [ "__LITEOS_A__" ] + deps += + [ "//base/startup/init/services/param/liteos:param_client_lite" ] + } else if (ohos_kernel_type == "linux") { + sources += [ "socket/init_socket.c" ] + defines += [ "__LINUX__" ] + deps += [ + "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/param/base:param_base", + "//base/startup/init/services/param/linux:param_client", + ] + } + } + + static_library("libbegetutil_static") { + } + } + if (ohos_kernel_type == "liteos_m") { + static_library("libbegetutil") { + public_configs = [ ":exported_header_files" ] + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + "__LITEOS_M__", + ] + + include_dirs = include_common + include_dirs += [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits" ] + deps = [ + "//base/startup/init/services/modules/init_hook:inithook", + "//base/startup/init/services/modules/udid:libudidcomm", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + if (init_lite_no_log) { + defines += [ "INIT_NO_LOG" ] + } else { + deps += + [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_static" ] + } + + sources = [] + if (init_feature_begetctl_liteos) { + PRODUCT_HAL_SYSPARAM_PATH = + rebase_path("${ohos_product_adapter_dir}/utils/sys_param") + cmd = "if [ -f ${PRODUCT_HAL_SYSPARAM_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + PRODUCT_HAL_SYSPARAM_EXISTS = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (PRODUCT_HAL_SYSPARAM_EXISTS) { + deps += [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ] + } + deps += [ + "//base/startup/init/interfaces/hals/utils/sys_param:hal_sys_param", + ] + defines += [ "LITEOS_SUPPORT" ] + sources += syspara_sources + } else { + sources += [ "syscap/init_syscap.c" ] + } + + if (init_feature_begetctl_liteos) { + deps += [ + "//base/startup/init/services/param/liteos:param_client_lite", + "//base/startup/init/services/utils:libinit_utils", + ] + if (!init_lite_no_log) { + deps += [ "//base/startup/init/services/log:init_log" ] + } + } + } + + static_library("libbegetutil_static") { + } + } + + lite_component("parameter") { + features = [ ":libbegetutil" ] + } + + ndk_lib("parameter_notes") { + if (ohos_kernel_type != "liteos_m") { + lib_extension = ".so" + } + deps = [ ":libbegetutil" ] + head_files = [ "//base/startup/init/interfaces/innerkits/include/syspara" ] + } + + group("libbeget_proxy") { + } +} else { + import("//build/ohos.gni") + modulemgr_sources = [ + "hookmgr/hookmgr.c", + "modulemgr/modulemgr.c", + ] + + ohos_shared_library("libbegetutil") { + sources = [ + "fd_holder/fd_holder.c", + "reboot/init_reboot_innerkits.c", + "service_control/service_control.c", + ] + sources += syspara_sources + sources += [ "syspara/param_wrapper.cpp" ] + sources += modulemgr_sources + + innerapi_tags = [ + "chipsetsdk", + "platformsdk", + "sasdk", + ] + + version_script = "libbegetutil.versionscript" + + defines = [ + "INIT_AGENT", + "_GNU_SOURCE", + ] + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines += [ "SUPPORT_64BIT" ] + } + + include_dirs = include_common + deps = [ + "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd", + "//base/startup/init/interfaces/innerkits/fd_holder:fdholder", + "//base/startup/init/interfaces/innerkits/file:libfile", + "//base/startup/init/interfaces/innerkits/socket:libsocket", + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/modules/udid:libudidcomm", + "//base/startup/init/services/param/linux:param_client", + "//base/startup/init/services/utils:libinit_utils", + ] + deps += [ "//base/startup/init/services/param/base:param_base" ] + if (init_begetutil_extra_modules != "") { + deps += [ init_begetutil_extra_modules ] + } + + external_deps = [ + "bounds_checking_function:libsec_shared", + "c_utils:utils", + "config_policy:configpolicy_util_for_init_static", + "hilog:libhilog_base", + ] + public_configs = [ ":exported_header_files" ] + part_name = "init" + subsystem_name = "startup" + install_images = [ + "system", + "updater", + ] + } + + # watcher lib must separate compilation avoid interdependence. + ohos_shared_library("libbeget_proxy") { + defines = [ + "INIT_AGENT", + "_GNU_SOURCE", + ] + sources = [ + "//base/startup/init/device_info/device_info.cpp", + "service_watcher/service_watcher.c", + ] + + version_script = "libbeget_proxy.versionscript" + + include_dirs = include_common + deps = [ + ":libbegetutil", + "//base/startup/init/services/utils:libinit_utils", + ] + + if (enable_ohos_startup_init_feature_watcher) { + sources += [ + "//base/startup/init/services/param/watcher/agent/watcher.cpp", + "//base/startup/init/services/param/watcher/agent/watcher_manager_kits.cpp", + "//base/startup/init/services/param/watcher/agent/watcher_manager_proxy.cpp", + "//base/startup/init/services/param/watcher/agent/watcher_stub.cpp", + ] + deps += [ "//base/startup/init/services/param/linux:param_client" ] + include_dirs += [ + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include/param", + ] + } else { + defines += [ "NO_PARAM_WATCHER" ] + } + + if (enable_ohos_startup_init_feature_deviceinfo) { + sources += [ + "//base/startup/init/device_info/device_info_kits.cpp", + "//base/startup/init/device_info/device_info_load.cpp", + "//base/startup/init/device_info/device_info_proxy.cpp", + ] + defines += [ "PARAM_FEATURE_DEVICEINFO" ] + } else { + sources += + [ "//base/startup/init/interfaces/innerkits/syspara/param_comm.c" ] + } + + external_deps = [ + "bounds_checking_function:libsec_shared", + "c_utils:utils", + "hilog:libhilog_base", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + public_configs = [ ":exported_header_files" ] + innerapi_tags = [ + "chipsetsdk", + "platformsdk", + ] + part_name = "init" + subsystem_name = "startup" + install_images = [ "system" ] + } + + ohos_static_library("libbegetutil_static") { + sources = syspara_sources + sources += [ + "reboot/init_reboot_innerkits.c", + "syspara/param_wrapper.cpp", + ] + + defines = [ + "INIT_AGENT", + "_GNU_SOURCE", + ] + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines += [ "SUPPORT_64BIT" ] + } + + include_dirs = include_common + deps = [ + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/modules/udid:libudidcomm_static", + "//base/startup/init/services/param/linux:param_client", + "//base/startup/init/services/utils:libinit_utils", + ] + deps += [ "//base/startup/init/services/param/base:param_base" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utilsbase", + "hilog:libhilog_base", + ] + public_configs = [ ":exported_header_files" ] + part_name = "init" + subsystem_name = "startup" + } +} + +group("innergroup") { + deps = [ ":libbegetutil" ] + if (build_seccomp) { + deps += [ "seccomp:seccomp" ] + } + if (!defined(ohos_lite)) { + deps += [ + ":libbeget_proxy", + "file:libfile", + "init_module_engine:modulegroup", + "socket:libsocket", + ] + } else { + } +} diff --git a/interfaces/innerkits/control_fd/BUILD.gn b/interfaces/innerkits/control_fd/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..53db2865c28bebd0566324a2ec021304629e2a8d --- /dev/null +++ b/interfaces/innerkits/control_fd/BUILD.gn @@ -0,0 +1,39 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/control_fd", + ] +} + +ohos_static_library("libcontrolfd") { + sources = [ + "control_fd_client.c", + "control_fd_service.c", + ] + public_configs = [ ":exported_header_files" ] + include_dirs = [ + ".", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/loopevent/include", + ] + external_deps = [ "bounds_checking_function:libsec_shared" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/interfaces/innerkits/control_fd/control_fd.h b/interfaces/innerkits/control_fd/control_fd.h new file mode 100644 index 0000000000000000000000000000000000000000..e026899debcb29410afc68d0303ada709053fd0a --- /dev/null +++ b/interfaces/innerkits/control_fd/control_fd.h @@ -0,0 +1,94 @@ +/* + * 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 CONTROL_FD_ +#define CONTROL_FD_ + +#include +#include +#include + +#include "list.h" +#include "loop_event.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define INIT_CONTROL_FD_SOCKET_PATH "/dev/unix/socket/init_control_fd" + +#define CONTROL_FD_FIFO_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) +#define PTY_BUF_SIZE 4096 +#define PTY_PATH_SIZE 128 + +#ifdef STARTUP_INIT_TEST +#define CONTROL_FD_STATIC +#else +#define CONTROL_FD_STATIC static +#endif + +typedef struct CmdService_ { + TaskHandle serverTask; + struct ListNode head; +} CmdService; + +typedef struct CmdAgent_ { + TaskHandle task; + WatcherHandle input; // watch stdin + WatcherHandle reader; // watch read pty + int ptyFd; +} CmdAgent; + +typedef struct CmdTask_ { + TaskHandle task; + struct ListNode item; + int ptyFd; + pid_t pid; +} CmdTask; + +typedef void (* CallbackControlFdProcess)(uint16_t type, const char *serviceCmd, const void *context); +typedef int (* CallbackSendMsgProcess)(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName); + +typedef enum { + ACTION_SANDBOX = 0, + ACTION_DUMP, + ACTION_MODULEMGR, + ACTION_APP_SPAWNTIME, + ACTION_APP_SANDBOX, + ACTION_MAX +} ActionType; + +typedef struct { + uint16_t msgSize; + uint16_t type; + char ptyName[PTY_PATH_SIZE]; + char cmd[0]; +} CmdMessage; + +void CmdServiceInit(const char *socketPath, CallbackControlFdProcess func, LoopHandle loop); +void CmdClientInit(const char *socketPath, uint16_t type, const char *cmd, CallbackSendMsgProcess callback); +void CmdServiceProcessDelClient(pid_t pid); +void CmdServiceProcessDestroyClient(void); +int InitPtyInterface(CmdAgent *agent, uint16_t type, const char *cmd, CallbackSendMsgProcess callback); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif diff --git a/interfaces/innerkits/control_fd/control_fd_client.c b/interfaces/innerkits/control_fd/control_fd_client.c new file mode 100644 index 0000000000000000000000000000000000000000..c909fb45d7d703113c74c1c3d5f1484d5f14716e --- /dev/null +++ b/interfaces/innerkits/control_fd/control_fd_client.c @@ -0,0 +1,222 @@ +/* + * 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 "beget_ext.h" +#include "control_fd.h" +#include "securec.h" + +CallbackSendMsgProcess g_sendMsg = NULL; + +CONTROL_FD_STATIC void ProcessPtyWrite(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) +{ + if ((fd < 0) || (events == NULL) || (context == NULL)) { + BEGET_LOGE("[control_fd] Invalid fifo write parameter"); + return; + } + CmdAgent *agent = (CmdAgent *)context; + char rbuf[PTY_BUF_SIZE] = {0}; + ssize_t rlen = read(fd, rbuf, PTY_BUF_SIZE - 1); + int ret = fflush(stdin); + BEGET_ERROR_CHECK(ret == 0, return, "[control_fd] Failed fflush err=%d", errno); + if (rlen > 0) { + ssize_t wlen = write(agent->ptyFd, rbuf, rlen); + BEGET_ERROR_CHECK(wlen == rlen, return, "[control_fd] Failed write fifo err=%d", errno); + } + ret = fflush(stdout); + BEGET_ERROR_CHECK(ret == 0, return, "[control_fd] Failed fflush err=%d", errno); + *events = EVENT_READ; +} + +CONTROL_FD_STATIC void ProcessPtyRead(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) +{ + if ((fd < 0) || (events == NULL) || (context == NULL)) { + BEGET_LOGE("[control_fd] Invalid fifo read parameter"); + return; + } + CmdAgent *agent = (CmdAgent *)context; + char buf[PTY_BUF_SIZE] = {0}; + ssize_t readlen = 0; + do { + readlen = read(fd, buf, PTY_BUF_SIZE - 1); + } while (readlen == -1 && errno == EINTR); + + if (readlen > 0) { + fprintf(stdout, "%s", buf); + } else { + (void)close(agent->ptyFd); + LE_StopLoop(LE_GetDefaultLoop()); + *events = 0; + return; + } + int ret = fflush(stdout); + BEGET_ERROR_CHECK(ret == 0, return, "[control_fd] Failed fflush err=%d", errno); + *events = EVENT_READ; +} + +CONTROL_FD_STATIC void CmdClientOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen) +{ + BEGET_LOGI("[control_fd] CmdOnRecvMessage %s len %d.", (char *)buffer, buffLen); +} + +CONTROL_FD_STATIC void CmdOnConnectComplete(const TaskHandle client) +{ + BEGET_LOGI("[control_fd] CmdOnConnectComplete"); +} + +CONTROL_FD_STATIC void CmdOnClose(const TaskHandle task) +{ + BEGET_LOGI("[control_fd] CmdOnClose"); + CmdAgent *agent = (CmdAgent *)LE_GetUserData(task); + BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Invalid agent"); + (void)close(agent->ptyFd); + agent->ptyFd = -1; + LE_StopLoop(LE_GetDefaultLoop()); +} + +CONTROL_FD_STATIC void CmdDisConnectComplete(const TaskHandle client) +{ + BEGET_LOGI("[control_fd] CmdDisConnectComplete"); +} + +CONTROL_FD_STATIC void CmdOnSendMessageComplete(const TaskHandle task, const BufferHandle handle) +{ + BEGET_LOGI("[control_fd] CmdOnSendMessageComplete"); +} + +CONTROL_FD_STATIC CmdAgent *CmdAgentCreate(const char *server) +{ + if (server == NULL) { + BEGET_LOGE("[control_fd] Invalid parameter"); + return NULL; + } + TaskHandle task = NULL; + LE_StreamInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; + info.server = (char *)server; + info.baseInfo.userDataSize = sizeof(CmdAgent); + info.baseInfo.close = CmdOnClose; + info.disConnectComplete = CmdDisConnectComplete; + info.connectComplete = CmdOnConnectComplete; + info.sendMessageComplete = CmdOnSendMessageComplete; + info.recvMessage = CmdClientOnRecvMessage; + LE_STATUS status = LE_CreateStreamClient(LE_GetDefaultLoop(), &task, &info); + BEGET_ERROR_CHECK(status == 0, return NULL, "[control_fd] Failed create client"); + CmdAgent *agent = (CmdAgent *)LE_GetUserData(task); + BEGET_ERROR_CHECK(agent != NULL, return NULL, "[control_fd] Invalid agent"); + agent->task = task; + return agent; +} + +CONTROL_FD_STATIC int SendCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName) +{ + if ((agent == NULL) || (cmd == NULL) || (ptyName == NULL)) { + BEGET_LOGE("[control_fd] Invalid parameter"); + return -1; + } + BufferHandle handle = NULL; + uint32_t bufferSize = sizeof(CmdMessage) + strlen(cmd) + PTY_PATH_SIZE + 1; + handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize); + char *buff = (char *)LE_GetBufferInfo(handle, NULL, NULL); + BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info"); + CmdMessage *message = (CmdMessage *)buff; + message->msgSize = bufferSize; + message->type = type; + int ret = strcpy_s(message->ptyName, PTY_PATH_SIZE - 1, ptyName); + BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), agent->task, handle); + return -1, "[control_fd] Failed to copy pty name %s", ptyName); + ret = strcpy_s(message->cmd, bufferSize - sizeof(CmdMessage) - PTY_PATH_SIZE, cmd); + BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), agent->task, handle); + return -1, "[control_fd] Failed to copy cmd %s", cmd); + ret = LE_Send(LE_GetDefaultLoop(), agent->task, handle, bufferSize); + BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed LE_Send msg type %d, cmd %s", + message->type, message->cmd); + return 0; +} + +int InitPtyInterface(CmdAgent *agent, uint16_t type, const char *cmd, CallbackSendMsgProcess callback) +{ + if ((cmd == NULL) || (agent == NULL)) { + return -1; + } +#ifndef STARTUP_INIT_TEST + g_sendMsg = callback; + // initialize terminal + struct termios term; + int ret = tcgetattr(STDIN_FILENO, &term); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed tcgetattr stdin, err=%d", errno); + cfmakeraw(&term); + term.c_cc[VTIME] = 0; + term.c_cc[VMIN] = 1; + ret = tcsetattr(STDIN_FILENO, TCSANOW, &term); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed tcsetattr term, err=%d", errno); + // open master pty and get slave pty + int pfd = open("/dev/ptmx", O_RDWR | O_CLOEXEC); + BEGET_ERROR_CHECK(pfd >= 0, return -1, "Failed open pty err=%d", errno); + BEGET_ERROR_CHECK(grantpt(pfd) >= 0, close(pfd); return -1, "Failed to call grantpt"); + BEGET_ERROR_CHECK(unlockpt(pfd) >= 0, close(pfd); return -1, "Failed to call unlockpt"); + char ptsbuffer[PTY_PATH_SIZE] = {0}; + ret = ptsname_r(pfd, ptsbuffer, sizeof(ptsbuffer)); + BEGET_ERROR_CHECK(ret >= 0, close(pfd); return -1, "Failed to get pts name err=%d", errno); + BEGET_LOGI("ptsbuffer is %s", ptsbuffer); + BEGET_ERROR_CHECK(chmod(ptsbuffer, S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0, + close(pfd); return -1, "Failed to chmod %s, err=%d", ptsbuffer, errno); + agent->ptyFd = pfd; + + LE_WatchInfo info = {}; + info.flags = 0; + info.events = EVENT_READ; + info.processEvent = ProcessPtyRead; + info.fd = pfd; // read ptmx + BEGET_ERROR_CHECK(LE_StartWatcher(LE_GetDefaultLoop(), &agent->reader, &info, agent) == LE_SUCCESS, + close(pfd); return -1, "[control_fd] Failed le_loop start watcher ptmx read"); + info.processEvent = ProcessPtyWrite; + info.fd = STDIN_FILENO; // read stdin and write ptmx + BEGET_ERROR_CHECK(LE_StartWatcher(LE_GetDefaultLoop(), &agent->input, &info, agent) == LE_SUCCESS, + close(pfd); return -1, "[control_fd] Failed le_loop start watcher stdin read and write ptmx"); + if (g_sendMsg == NULL) { + ret = SendCmdMessage(agent, type, cmd, ptsbuffer); + } else { + ret = g_sendMsg(agent, type, cmd, ptsbuffer); + } + BEGET_ERROR_CHECK(ret == 0, close(pfd); return -1, "[control_fd] Failed send message"); +#endif + return 0; +} + +void CmdClientInit(const char *socketPath, uint16_t type, const char *cmd, CallbackSendMsgProcess callback) +{ + if ((socketPath == NULL) || (cmd == NULL)) { + BEGET_LOGE("[control_fd] Invalid parameter"); + } + BEGET_LOGI("[control_fd] CmdAgentInit"); + CmdAgent *agent = CmdAgentCreate(socketPath); + BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Failed to create agent"); +#ifndef STARTUP_INIT_TEST + int ret = InitPtyInterface(agent, type, cmd, callback); + if (ret != 0) { + return; + } + LE_RunLoop(LE_GetDefaultLoop()); + LE_CloseLoop(LE_GetDefaultLoop()); +#endif + BEGET_LOGI("Cmd Client exit "); +} diff --git a/interfaces/innerkits/control_fd/control_fd_service.c b/interfaces/innerkits/control_fd/control_fd_service.c new file mode 100644 index 0000000000000000000000000000000000000000..8b4ffce5a61567ed133422ed157a83af5ad001ca --- /dev/null +++ b/interfaces/innerkits/control_fd/control_fd_service.c @@ -0,0 +1,199 @@ +/* + * 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 "beget_ext.h" +#include "control_fd.h" +#include "init_utils.h" +#include "securec.h" + +static CmdService g_cmdService; +static LoopHandle g_controlFdLoop = NULL; + +CallbackControlFdProcess g_controlFdFunc = NULL; + +static void OnClose(const TaskHandle task) +{ + CmdTask *agent = (CmdTask *)LE_GetUserData(task); + BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent"); + OH_ListRemove(&agent->item); + OH_ListInit(&agent->item); +} + +CONTROL_FD_STATIC int CheckSocketPermission(const TaskHandle task) +{ + struct ucred uc = {-1, -1, -1}; + socklen_t len = sizeof(uc); + if (getsockopt(LE_GetSocketFd(task), SOL_SOCKET, SO_PEERCRED, &uc, &len) < 0) { + BEGET_LOGE("Failed to get socket option. err = %d", errno); + return -1; + } + // Only root is permitted to use control fd of init. + if (uc.uid != 0) { // non-root user + errno = EPERM; + return -1; + } + return 0; +} + +CONTROL_FD_STATIC void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen) +{ + if (buffer == NULL) { + return; + } + CmdTask *agent = (CmdTask *)LE_GetUserData(task); + BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent"); + + // parse msg to exec + CmdMessage *msg = (CmdMessage *)buffer; + if ((msg->type >= ACTION_MAX) || (msg->cmd[0] == '\0') || (msg->ptyName[0] == '\0')) { + BEGET_LOGE("[control_fd] Received msg is invalid"); + return; + } + + BEGET_ERROR_CHECK(CheckSocketPermission(task) >= 0, return, "Check socket permission failed, err = %d", errno); + +#ifndef STARTUP_INIT_TEST + agent->pid = fork(); + if (agent->pid == 0) { + OpenConsole(); + char *realPath = GetRealPath(msg->ptyName); + BEGET_ERROR_CHECK(realPath != NULL, _exit(1), "Failed get realpath, err=%d", errno); + int n = strncmp(realPath, "/dev/pts/", strlen("/dev/pts/")); + BEGET_ERROR_CHECK(n == 0, free(realPath); _exit(1), "pts path %s is invaild", realPath); + int fd = open(realPath, O_RDWR); + free(realPath); + BEGET_ERROR_CHECK(fd >= 0, _exit(1), "Failed open %s, err=%d", msg->ptyName, errno); + (void)dup2(fd, STDIN_FILENO); + (void)dup2(fd, STDOUT_FILENO); + (void)dup2(fd, STDERR_FILENO); // Redirect fd to 0, 1, 2 + (void)close(fd); + if (g_controlFdFunc != NULL) { + g_controlFdFunc(msg->type, msg->cmd, NULL); + } + _exit(0); + } else if (agent->pid < 0) { + BEGET_LOGE("[control_fd] Failed to fork child process, err = %d", errno); + } +#endif + return; +} + +CONTROL_FD_STATIC int SendMessage(LoopHandle loop, TaskHandle task, const char *message) +{ + if (message == NULL) { + BEGET_LOGE("[control_fd] Invalid parameter"); + return -1; + } + BufferHandle handle = NULL; + uint32_t bufferSize = strlen(message) + 1; + handle = LE_CreateBuffer(loop, bufferSize); + char *buff = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize); + BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info"); + int ret = memcpy_s(buff, bufferSize, message, strlen(message) + 1); + BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(g_controlFdLoop, task, handle); + return -1, "[control_fd] Failed memcpy_s err=%d", errno); + LE_STATUS status = LE_Send(loop, task, handle, strlen(message) + 1); + BEGET_ERROR_CHECK(status == LE_SUCCESS, return -1, "[control_fd] Failed le send msg"); + return 0; +} + +CONTROL_FD_STATIC int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server) +{ + TaskHandle client = NULL; + LE_StreamInfo info = {}; +#ifndef STARTUP_INIT_TEST + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; +#else + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT | TASK_TEST; +#endif + info.baseInfo.close = OnClose; + info.baseInfo.userDataSize = sizeof(CmdTask); + info.disConnectComplete = NULL; + info.sendMessageComplete = NULL; + info.recvMessage = CmdOnRecvMessage; + int ret = LE_AcceptStreamClient(g_controlFdLoop, server, &client, &info); + BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed accept stream") + CmdTask *agent = (CmdTask *)LE_GetUserData(client); + BEGET_ERROR_CHECK(agent != NULL, return -1, "[control_fd] Invalid agent"); + agent->task = client; + OH_ListInit(&agent->item); + ret = SendMessage(g_controlFdLoop, agent->task, "connect success."); + BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed send msg"); + OH_ListAddTail(&g_cmdService.head, &agent->item); + return 0; +} + +void CmdServiceInit(const char *socketPath, CallbackControlFdProcess func, LoopHandle loop) +{ + if ((socketPath == NULL) || (func == NULL) || (loop == NULL)) { + BEGET_LOGE("[control_fd] Invalid parameter"); + return; + } + OH_ListInit(&g_cmdService.head); + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE; + info.server = (char *)socketPath; + info.socketId = -1; + info.baseInfo.close = NULL; + info.disConnectComplete = NULL; + info.incommingConnect = CmdOnIncommingConnect; + info.sendMessageComplete = NULL; + info.recvMessage = NULL; + g_controlFdFunc = func; + if (g_controlFdLoop == NULL) { + g_controlFdLoop = loop; + } + (void)LE_CreateStreamServer(g_controlFdLoop, &g_cmdService.serverTask, &info); +} + +static int ClientTraversalProc(ListNode *node, void *data) +{ + CmdTask *info = ListEntry(node, CmdTask, item); + int pid = *(int *)data; + return pid - info->pid; +} + +void CmdServiceProcessDelClient(pid_t pid) +{ + ListNode *node = OH_ListFind(&g_cmdService.head, (void *)&pid, ClientTraversalProc); + if (node != NULL) { + CmdTask *agent = ListEntry(node, CmdTask, item); + OH_ListRemove(&agent->item); + OH_ListInit(&agent->item); + LE_CloseTask(g_controlFdLoop, agent->task); + } +} + +static void CmdServiceDestroyProc(ListNode *node) +{ + if (node == NULL) { + return; + } + CmdTask *agent = ListEntry(node, CmdTask, item); + OH_ListRemove(&agent->item); + OH_ListInit(&agent->item); + LE_CloseTask(g_controlFdLoop, agent->task); +} + +void CmdServiceProcessDestroyClient(void) +{ + OH_ListRemoveAll(&g_cmdService.head, CmdServiceDestroyProc); + LE_StopLoop(g_controlFdLoop); +} diff --git a/interfaces/innerkits/reboot/BUILD.gn b/interfaces/innerkits/fd_holder/BUILD.gn similarity index 54% rename from interfaces/innerkits/reboot/BUILD.gn rename to interfaces/innerkits/fd_holder/BUILD.gn index d603b712bd10d036e37f1d8144c7bb743e3a0268..be043bd40dbc092179a50a6e65825336eb5ebc12 100644 --- a/interfaces/innerkits/reboot/BUILD.gn +++ b/interfaces/innerkits/fd_holder/BUILD.gn @@ -12,20 +12,23 @@ # limitations under the License. import("//build/ohos.gni") -ohos_static_library("libreboot") { - sources = - [ "//base/startup/init_lite/interfaces/innerkits/reboot/init_reboot.c" ] +config("exported_header_files") { + visibility = [ ":*" ] include_dirs = [ - "//base/startup/init_lite/interfaces/innerkits/include", - "//base/startup/init_lite/services/include/param", - "//third_party/bounds_checking_function/include", - "//base/startup/init_lite/services/log", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/fd_holder", ] +} - deps = [ - "//base/startup/init_lite/services/log:init_log", - "//base/startup/init_lite/services/param:paramclient", - "//third_party/bounds_checking_function:libsec_static", +ohos_static_library("fdholder") { + sources = [ "fd_holder_internal.c" ] + include_dirs = [ + "//base/startup/init/services/loopevent/include", + "//base/startup/init/interfaces/innerkits/include", ] + public_configs = [ ":exported_header_files" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + part_name = "init" + subsystem_name = "startup" } diff --git a/interfaces/innerkits/fd_holder/fd_holder.c b/interfaces/innerkits/fd_holder/fd_holder.c new file mode 100644 index 0000000000000000000000000000000000000000..13ffbfaaefd9b0f229185fbfbbb6c98c736b08ab --- /dev/null +++ b/interfaces/innerkits/fd_holder/fd_holder.c @@ -0,0 +1,193 @@ +/* +* Copyright (c) 2021 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 "fd_holder.h" +#include +#include + +#include "beget_ext.h" +#include "fd_holder_internal.h" +#include "init_utils.h" +#include "securec.h" + +static int BuildClientSocket(void) +{ + int sockFd; + sockFd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + BEGET_ERROR_CHECK(sockFd >= 0, return -1, "Failed to build socket, err = %d", errno); + + struct sockaddr_un addr; + (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + int ret = strncpy_s(addr.sun_path, sizeof(addr.sun_path), INIT_HOLDER_SOCKET_PATH, + strlen(INIT_HOLDER_SOCKET_PATH)); + BEGET_ERROR_CHECK(ret == 0, close(sockFd); + return -1, "Failed to build socket path"); + + socklen_t len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1); + + ret = connect(sockFd, (struct sockaddr *)&addr, len); + BEGET_ERROR_CHECK(ret >= 0, close(sockFd); + return -1, "Failed to connect to socket, err = %d", errno); + return sockFd; +} + +STATIC int BuildSendData(char *buffer, size_t size, const char *serviceName, bool hold, bool poll) +{ + if (buffer == NULL || size == 0 || serviceName == 0) { + return -1; + } + + if (!hold && poll) { + BEGET_LOGE("Get fd with poll set, invalid parameter"); + return -1; + } + + char *holdString = ACTION_HOLD; + if (!hold) { + holdString = ACTION_GET; + } + char *pollString = WITHPOLL; + if (!poll) { + pollString = WITHOUTPOLL; + } + + if (snprintf_s(buffer, size, size - 1, "%s|%s|%s", serviceName, holdString, pollString) == -1) { + BEGET_LOGE("Failed to build send data"); + return -1; + } + return 0; +} + +static int ServiceSendFds(const char *serviceName, int *fds, int fdCount, bool doPoll) +{ + int sock = BuildClientSocket(); + BEGET_CHECK(sock >= 0, return -1); + + struct iovec iovec = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + }; + + char sendBuffer[MAX_FD_HOLDER_BUFFER] = {}; + int ret = BuildSendData(sendBuffer, sizeof(sendBuffer), serviceName, true, doPoll); + BEGET_ERROR_CHECK(ret >= 0, close(sock); + return -1, "Failed to build send data"); + + BEGET_LOGV("Send data: [%s]", sendBuffer); + iovec.iov_base = sendBuffer; + iovec.iov_len = strlen(sendBuffer); + + if (BuildControlMessage(&msghdr, fds, fdCount, true) < 0) { + BEGET_LOGE("Failed to build control message"); + if (msghdr.msg_control != NULL) { + free(msghdr.msg_control); + msghdr.msg_control = NULL; + } + msghdr.msg_controllen = 0; + close(sock); + return -1; + } + + if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) { + BEGET_LOGE("Failed to send fds to init, err = %d", errno); + if (msghdr.msg_control != NULL) { + free(msghdr.msg_control); + msghdr.msg_control = NULL; + } + msghdr.msg_controllen = 0; + close(sock); + return -1; + } + if (msghdr.msg_control != NULL) { + free(msghdr.msg_control); + msghdr.msg_control = NULL; + } + msghdr.msg_controllen = 0; + BEGET_LOGI("Send fds done"); + close(sock); + return 0; +} + +int ServiceSaveFd(const char *serviceName, int *fds, int fdCount) +{ + // Sanity checks + if (serviceName == NULL || fds == NULL || + fdCount < 0 || fdCount > MAX_HOLD_FDS) { + BEGET_LOGE("Invalid parameters"); + return -1; + } + return ServiceSendFds(serviceName, fds, fdCount, false); +} + +int ServiceSaveFdWithPoll(const char *serviceName, int *fds, int fdCount) +{ + // Sanity checks + if (serviceName == NULL || fds == NULL || + fdCount < 0 || fdCount > MAX_HOLD_FDS) { + BEGET_LOGE("Invalid parameters"); + return -1; + } + return ServiceSendFds(serviceName, fds, fdCount, true); +} + +int *ServiceGetFd(const char *serviceName, size_t *outfdCount) +{ + if (serviceName == NULL || outfdCount == NULL) { + BEGET_LOGE("Invalid parameters"); + return NULL; + } + + char path[MAX_FD_HOLDER_BUFFER] = {}; + int ret = snprintf_s(path, MAX_FD_HOLDER_BUFFER, MAX_FD_HOLDER_BUFFER - 1, ENV_FD_HOLD_PREFIX"%s", serviceName); + BEGET_ERROR_CHECK(ret > 0, return NULL, "Failed snprintf_s err=%d", errno); + const char *value = getenv(path); + if (value == NULL) { + BEGET_LOGE("Cannot get env %s\n", path); + return NULL; + } + + char fdBuffer[MAX_FD_HOLDER_BUFFER] = {}; + ret = strncpy_s(fdBuffer, MAX_FD_HOLDER_BUFFER - 1, value, strlen(value)); + BEGET_ERROR_CHECK(ret == 0, return NULL, "Failed strncpy_s err=%d", errno); + BEGET_LOGV("fds = %s", fdBuffer); + int fdCount = 0; + char **fdList = SplitStringExt(fdBuffer, " ", &fdCount, MAX_HOLD_FDS); + BEGET_ERROR_CHECK(fdList != NULL, return NULL, "Cannot get fd list"); + + int *fds = calloc((size_t)fdCount, sizeof(int)); + BEGET_ERROR_CHECK(fds != NULL, FreeStringVector(fdList, fdCount); + *outfdCount = 0; + return NULL, + "Allocate memory for fd failed. err = %d", errno); + + bool encounterError = false; + for (int i = 0; i < fdCount; i++) { + errno = 0; + fds[i] = (int)strtol(fdList[i], NULL, DECIMAL_BASE); + BEGET_ERROR_CHECK(errno == 0, encounterError = true; + break, "Failed to convert \' %s \' to fd number", fdList[i]); + } + + if (encounterError) { + free(fds); + fds = NULL; + fdCount = 0; + } + *outfdCount = fdCount; + FreeStringVector(fdList, fdCount); + return fds; +} diff --git a/interfaces/innerkits/fd_holder/fd_holder_internal.c b/interfaces/innerkits/fd_holder/fd_holder_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..314c4087b1e7b6424e5b5078459bb793a1659393 --- /dev/null +++ b/interfaces/innerkits/fd_holder/fd_holder_internal.c @@ -0,0 +1,140 @@ +/* +* Copyright (c) 2021 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 "fd_holder_internal.h" +#include +#include +#include "beget_ext.h" +#include "securec.h" + +#ifndef PAGE_SIZE +#define PAGE_SIZE (4096U) +#endif + +int BuildControlMessage(struct msghdr *msghdr, int *fds, int fdCount, bool sendUcred) +{ + if (msghdr == NULL || (fdCount > 0 && fds == NULL)) { + BEGET_LOGE("Build control message with invalid parameter"); + return -1; + } + + if (fdCount > 0) { + msghdr->msg_controllen = CMSG_SPACE(sizeof(int) * fdCount); + } else { + msghdr->msg_controllen = 0; + } + + if (sendUcred) { + msghdr->msg_controllen += CMSG_SPACE(sizeof(struct ucred)); + } + + msghdr->msg_control = calloc(1, ((msghdr->msg_controllen == 0) ? 1 : msghdr->msg_controllen)); + BEGET_ERROR_CHECK(msghdr->msg_control != NULL, return -1, "Failed to build control message"); + + struct cmsghdr *cmsg = NULL; + cmsg = CMSG_FIRSTHDR(msghdr); + BEGET_ERROR_CHECK(cmsg != NULL, return -1, "Failed to build cmsg"); + + if (fdCount > 0) { + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount); + int ret = memcpy_s(CMSG_DATA(cmsg), cmsg->cmsg_len, fds, sizeof(int) * fdCount); + BEGET_ERROR_CHECK(ret == 0, free(msghdr->msg_control); + msghdr->msg_control = NULL; + return -1, "Control message is not valid"); + // build ucred info + cmsg = CMSG_NXTHDR(msghdr, cmsg); + } + + if (sendUcred) { + BEGET_ERROR_CHECK(cmsg != NULL, free(msghdr->msg_control); + msghdr->msg_control = NULL; + return -1, "Control message is not valid"); + + struct ucred *ucred; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + ucred = (struct ucred*) CMSG_DATA(cmsg); + ucred->pid = getpid(); + ucred->uid = getuid(); + ucred->gid = getgid(); + } + return 0; +} + +STATIC int *GetFdsFromMsg(size_t *outFdCount, pid_t *requestPid, struct msghdr msghdr) +{ + if ((msghdr.msg_flags) & MSG_TRUNC) { + BEGET_LOGE("Message was truncated when receiving fds"); + return NULL; + } + + struct cmsghdr *cmsg = NULL; + int *fds = NULL; + size_t fdCount = 0; + for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + fds = (int*)CMSG_DATA(cmsg); + fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + BEGET_ERROR_CHECK(fdCount <= MAX_HOLD_FDS, return NULL, "Too many fds returned."); + } + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + // Ignore credentials + if (requestPid != NULL) { + struct ucred *ucred = (struct ucred*)CMSG_DATA(cmsg); + *requestPid = ucred->pid; + } + continue; + } + } + int *outFds = NULL; + if (fds != NULL && fdCount > 0) { + outFds = calloc(fdCount + 1, sizeof(int)); + BEGET_ERROR_CHECK(outFds != NULL, return NULL, "Failed to allocate memory for fds"); + BEGET_ERROR_CHECK(memcpy_s(outFds, sizeof(int) * (fdCount + 1), fds, sizeof(int) * fdCount) == 0, + free(outFds); return NULL, "Failed to copy fds"); + } + *outFdCount = fdCount; + return outFds; +} + +// This function will allocate memory to store FDs +// Remember to delete when not used anymore. +int *ReceiveFds(int sock, struct iovec iovec, size_t *outFdCount, bool nonblock, pid_t *requestPid) +{ + CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(int) * MAX_HOLD_FDS)) control; + + BEGET_ERROR_CHECK(sizeof(control) <= PAGE_SIZE, return NULL, "Too many fds, out of memory"); + + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_flags = 0, + }; + + int flags = MSG_CMSG_CLOEXEC | MSG_TRUNC; + if (nonblock) { + flags |= MSG_DONTWAIT; + } + ssize_t rc = TEMP_FAILURE_RETRY(recvmsg(sock, &msghdr, flags)); + BEGET_ERROR_CHECK(rc >= 0, return NULL, "Failed to get fds from remote, err = %d", errno); + return GetFdsFromMsg(outFdCount, requestPid, msghdr); +} \ No newline at end of file diff --git a/interfaces/innerkits/fd_holder/fd_holder_internal.h b/interfaces/innerkits/fd_holder/fd_holder_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..b334dfb3c7a00df99fc90e2939d3057d90a5fa2c --- /dev/null +++ b/interfaces/innerkits/fd_holder/fd_holder_internal.h @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2021 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_FD_HOLDER_INTERNAL_H +#define BASE_STARTUP_INITLITE_FD_HOLDER_INTERNAL_H +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INIT_HOLDER_SOCKET_PATH "/dev/unix/socket/fd_holder" +#define MAX_HOLD_FDS (64) +#define MAX_FD_HOLDER_BUFFER (MAX_HOLD_FDS * sizeof(int)) + +#define ENV_FD_HOLD_PREFIX "OHOS_FD_HOLD_" + +// actions +#define ACTION_HOLD "hold" +#define ACTION_GET "get" + +// poll or not +#define WITHPOLL "poll" +#define WITHOUTPOLL "withoutpoll" + +int BuildControlMessage(struct msghdr *msghdr, int *fds, int fdCount, bool sendUcred); +// This function will allocate memory to store FDs +// Remember to delete when not used anymore. +int *ReceiveFds(int sock, struct iovec iovec, size_t *outFdCount, bool nonblock, pid_t *requestPid); + +#define CMSG_BUFFER_TYPE(size) \ + union { \ + struct cmsghdr cmsghdr; \ + uint8_t buf[size]; \ + uint8_t align_check[(size) >= CMSG_SPACE(0) && \ + (size) == CMSG_ALIGN(size) ? 1 : -1]; \ + } + +#ifdef __cplusplus +} +#endif +#endif // BASE_STARTUP_INITLITE_FD_HOLDER_INTERNAL_H diff --git a/interfaces/innerkits/file/BUILD.gn b/interfaces/innerkits/file/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..62a0a3e11bff0ac7c4597e6eaf1dc36af30fbc18 --- /dev/null +++ b/interfaces/innerkits/file/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2021-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("//build/ohos.gni") +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ "//base/startup/init/interfaces/innerkits/include" ] +} + +ohos_static_library("libfile") { + sources = [ "init_file.c" ] + include_dirs = [ + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + ] + external_deps = [ "bounds_checking_function:libsec_shared" ] + public_configs = [ ":exported_header_files" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/interfaces/innerkits/file/init_file.c b/interfaces/innerkits/file/init_file.c new file mode 100644 index 0000000000000000000000000000000000000000..e6f6100427312b4f6daa62051164fc1308d7fb73 --- /dev/null +++ b/interfaces/innerkits/file/init_file.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 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 "init_file.h" + +#include +#include +#include +#include + +#include "beget_ext.h" +#include "init_utils.h" +#include "securec.h" + +#define N_DEC 10 + +int GetControlFile(const char *pathName) +{ + if (pathName == NULL) { + return -1; + } + char path[PATH_MAX] = { 0 }; + BEGET_ERROR_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1, OHOS_FILE_ENV_PREFIX "%s", pathName) >= 0, + return -1, "Failed snprintf_s err=%d", errno); + BEGET_ERROR_CHECK(StringReplaceChr(path, '/', '_') == 0, + return -1, "Failed string replace char"); + BEGET_LOGI("Environment path is %s ", path); + const char *val = getenv(path); + BEGET_ERROR_CHECK(val != NULL, return -1, "Failed getenv err=%d", errno); + errno = 0; + int fd = strtol(val, NULL, N_DEC); + BEGET_ERROR_CHECK(errno == 0, return -1, "Failed strtol val"); + BEGET_LOGI("Get environment fd is %d ", fd); + BEGET_ERROR_CHECK(fcntl(fd, F_GETFD) >= 0, return -1, "Failed fcntl fd err=%d ", errno); + return fd; +} diff --git a/interfaces/innerkits/fs_manager/BUILD.gn b/interfaces/innerkits/fs_manager/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..e0ac82cc709901b2bc7e0101e94ae05698dec923 --- /dev/null +++ b/interfaces/innerkits/fs_manager/BUILD.gn @@ -0,0 +1,132 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +# For init only +config("libfsmanager_exported_configs") { + visibility = [ ":*" ] + include_dirs = [ + "./libfs_dm/include", + "./libfs_hvb/include", + "//base/startup/init/interfaces/innerkits/include/fs_manager", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", + "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/include", + "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include", + ] +} + +ohos_static_library("libfsmanager_static") { + if (!defined(ohos_lite)) { + sources = [ + "fstab.c", + "fstab_mount.c", + "switch_root/switch_root.c", + ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include", + "//base/startup/init/services/log", + "//base/startup/init/services/param/include", + ] + defines = [] + external_deps = [ "bounds_checking_function:libsec_static" ] + deps = [ "//base/startup/init/services/utils:libinit_utils" ] + + if ((defined(global_parts_info) && + defined(global_parts_info.startup_hvb)) || + init_startup_feature_erofs_overlay) { + sources += [ "libfs_dm/fs_dm.c" ] + include_dirs += [ + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", + "//base/startup/init/ueventd/include", + ] + deps += [ "//base/startup/init/ueventd:libueventd_ramdisk_static" ] + } + + if (defined(global_parts_info) && defined(global_parts_info.startup_hvb)) { + sources += [ + "dm_verity/dm_verity.c", + "libfs_hvb/fs_hvb.c", + "libfs_hvb/hvb_ops.c", + ] + + include_dirs += [ + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/include", + "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/include", + ] + + defines += [ "SUPPORT_HVB" ] + external_deps += [ "hvb:libhvb_static" ] + } + if (init_startup_feature_erofs_overlay) { + sources += [ + "erofs_overlay/erofs_mount_overlay.c", + "erofs_overlay/erofs_overlay_common.c", + "erofs_overlay/erofs_remount_overlay.c", + ] + include_dirs += [ "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/include" ] + + defines += [ "EROFS_OVERLAY" ] + } + } + + public_configs = [ ":libfsmanager_exported_configs" ] + part_name = "init" + subsystem_name = "startup" +} + +ohos_static_library("libfsmanager_static_real") { + if (!defined(ohos_lite)) { + sources = [ + "fstab.c", + "fstab_mount.c", + "switch_root/switch_root.c", + ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include", + "//base/startup/init/services/log", + "//base/startup/init/services/param/include", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + deps = [ "//base/startup/init/services/utils:libinit_utils" ] + if (defined(global_parts_info) && defined(global_parts_info.startup_hvb)) { + sources += [ + "dm_verity/dm_verity.c", + "libfs_dm/fs_dm.c", + "libfs_hvb/fs_hvb.c", + "libfs_hvb/hvb_ops.c", + ] + + include_dirs += [ + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/include", + "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/include", + "//base/startup/init/ueventd/include", + ] + + defines = [ "SUPPORT_HVB" ] + external_deps += [ "hvb:libhvb_static" ] + deps += [ "//base/startup/init/ueventd:libueventd_ramdisk_static_real" ] + } + } + + public_configs = [ ":libfsmanager_exported_configs" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c b/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c new file mode 100755 index 0000000000000000000000000000000000000000..6776bba151251e18fc8da6429e68508c445e06b1 --- /dev/null +++ b/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022-2023 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 "dm_verity.h" +#include "fs_hvb.h" +#include "hvb_cmdline.h" +#include "securec.h" +#include "beget_ext.h" +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define HVB_VB_STATE_STR_MAX_LEN 32 +#define HVB_FORCE_ENABLE_STR_MAX_LEN 16 +#define HVB_CMDLINE_HVB_FORCE_ENABLE "ohos.boot.hvb.oem_swtype" + +#define DM_VERITY_RETURN_ERR_IF_NULL(__ptr) \ + do { \ + if ((__ptr) == NULL) { \ + BEGET_LOGE("error, %s is NULL\n", #__ptr); \ + return -1; \ + } \ + } while (0) + +static bool HvbDmVerityIsEnable(void) +{ + int rc; + char forceEnable[HVB_FORCE_ENABLE_STR_MAX_LEN] = {0}; + char vBState[HVB_VB_STATE_STR_MAX_LEN] = {0}; + + rc = FsHvbGetValueFromCmdLine(&forceEnable[0], sizeof(forceEnable), HVB_CMDLINE_HVB_FORCE_ENABLE); + if (rc == 0 && strcmp(&forceEnable[0], "factory") == 0) { + return true; + } + + rc = FsHvbGetValueFromCmdLine(&vBState[0], sizeof(vBState), HVB_CMDLINE_VB_STATE); + + if (rc != 0) { + BEGET_LOGE("error 0x%x, get verifed boot state, force enable dm-verity", rc); + return true; + } + + if (strcmp(&vBState[0], "false") == 0 || strcmp(&vBState[0], "FALSE") == 0) { + return false; + } + + if (strcmp(&vBState[0], "orange") == 0 || strcmp(&vBState[0], "ORANGE") == 0) { + return false; + } + + return true; +} + +int HvbDmVerityinit(const Fstab *fstab) +{ + int rc; + FstabItem *p = NULL; + + if (!HvbDmVerityIsEnable()) { + BEGET_LOGI("hvb not enable, not init"); + return 0; + } + + for (p = fstab->head; p != NULL; p = p->next) { + if (p->fsManagerFlags & FS_MANAGER_HVB) + break; + } + + if (p == NULL) { + BEGET_LOGI("no need init fs hvb"); + return 0; + } + + rc = FsHvbInit(MAIN_HVB); + if (rc != 0) { + BEGET_LOGE("init fs hvb error, ret=%d", rc); + return rc; + } + + return rc; +} + +int HvbDmVeritySetUp(FstabItem *fsItem) +{ + int rc; + + if (!HvbDmVerityIsEnable()) { + BEGET_LOGI("hvb not enable, not setup"); + return 0; + } + + DM_VERITY_RETURN_ERR_IF_NULL(fsItem); + + if ((fsItem->fsManagerFlags & FS_MANAGER_HVB) == 0) { + BEGET_LOGW("device %s not need hvb", fsItem->deviceName ? fsItem->deviceName : "none"); + return 0; + } + + rc = FsHvbSetupHashtree(fsItem); + if (rc != 0) { + BEGET_LOGE("error, setup hashtree fail, ret=%d", rc); + } + + return rc; +} + +void HvbDmVerityFinal(void) +{ + int rc; + + if (!HvbDmVerityIsEnable()) { + BEGET_LOGI("hvb not enable, not final"); + return; + } + + rc = FsHvbFinal(MAIN_HVB); + if (rc != 0) { + BEGET_LOGE("final fs hvb error, ret=%d", rc); + return; + } +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/services/param/cmd/param_set.c b/interfaces/innerkits/fs_manager/dm_verity/include/dm_verity.h old mode 100644 new mode 100755 similarity index 45% rename from services/param/cmd/param_set.c rename to interfaces/innerkits/fs_manager/dm_verity/include/dm_verity.h index 3c3943df95ad2df4048cecf61777cacc77536050..69e9fb813121489b0ff72cf3670373c6d984835a --- a/services/param/cmd/param_set.c +++ b/interfaces/innerkits/fs_manager/dm_verity/include/dm_verity.h @@ -1,39 +1,39 @@ -/* -* Copyright (c) 2021 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 "sys_param.h" - -#define HELP_PARAM "--help" - -int main(int argc, char* argv[]) -{ - if (argc == 1 || argc > 3) { - printf("setparam: Need 2 arguments (see \"setparam --help\")\n"); - return 0; - } - if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) { - printf("usage: setparam NAME VALUE\n"); - return 0; - } - int ret = SystemSetParameter(argv[1], argv[2]); - if (ret == 0) { - printf("setparam %s %s success\n", argv[1], argv[2]); - } else { - printf("setparam %s %s fail\n", argv[1], argv[2]); - } -} +/* +* Copyright (c) 2023 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 STARTUP_DM_VERITY_H +#define STARTUP_DM_VERITY_H + +#include +#include +#include "fs_manager/fs_manager.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int HvbDmVerityinit(const Fstab *fstab); +int HvbDmVeritySetUp(FstabItem *fsItem); +void HvbDmVerityFinal(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // STARTUP_DM_VERITY_H diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c new file mode 100644 index 0000000000000000000000000000000000000000..f74c27edbae2f1cace7770ffd8757baf6b2d8910 --- /dev/null +++ b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2024-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 +#include +#include +#include "securec.h" +#include "init_utils.h" +#include "fs_dm.h" +#include "switch_root.h" +#include "fs_manager/fs_manager.h" + +#include "erofs_mount_overlay.h" + +#define BYTE_UNIT 1024 +#define ALIGN_BLOCK_SIZE (16 * BYTE_UNIT) +#define MIN_DM_SIZE (2 * BYTE_UNIT * BYTE_UNIT) +#define BLOCK_SIZE_UINT 4096 +#define EXTHDR_MAGIC 0xFEEDBEEF +#define EXTHDR_BLKSIZE 4096 + +struct extheader_v1 { + uint32_t magic_number; + uint16_t exthdr_size; + uint16_t bcc16; + uint64_t part_size; +}; + +INIT_STATIC void AllocDmName(const char *name, char *nameRofs, const uint64_t nameRofsLen, + char *nameExt4, const uint64_t nameExt4Len) +{ + if (snprintf_s(nameRofs, nameRofsLen, nameRofsLen - 1, "%s_erofs", name) < 0) { + BEGET_LOGE("Failed to copy nameRofs."); + return; + } + + if (snprintf_s(nameExt4, nameExt4Len, nameExt4Len - 1, "%s_ext4", name) < 0) { + BEGET_LOGE("Failed to copy nameExt4."); + return; + } + + uint64_t i = 0; + while (nameRofs[i] != '\0') { + if (nameRofs[i] == '/') { + nameRofs[i] = '_'; + } + i++; + } + i = 0; + while (nameExt4[i] != '\0') { + if (nameExt4[i] == '/') { + nameExt4[i] = '_'; + } + i++; + } + + BEGET_LOGI("alloc dm namerofs:[%s], nameext4:[%s]", nameRofs, nameExt4); +} + +INIT_STATIC uint64_t LookupErofsEnd(const char *dev) +{ + int fd = -1; + fd = open(dev, O_RDONLY | O_LARGEFILE); + if (fd < 0) { + BEGET_LOGE("open dev:[%s] failed.", dev); + return 0; + } + + if (lseek(fd, EROFS_SUPER_BLOCK_START_POSITION, SEEK_SET) < 0) { + BEGET_LOGE("lseek dev:[%s] failed.", dev); + close(fd); + return 0; + } + + struct erofs_super_block sb; + ssize_t nbytes = read(fd, &sb, sizeof(sb)); + if (nbytes != sizeof(sb)) { + BEGET_LOGE("read dev:[%s] failed.", dev); + close(fd); + return 0; + } + close(fd); + + if (sb.magic != EROFS_SUPER_MAGIC) { + BEGET_LOGE("dev:[%s] is not erofs system, magic is 0x%x", dev, sb.magic); + return 0; + } + + uint64_t erofsSize = (uint64_t)sb.blocks * BLOCK_SIZE_UINT; + return erofsSize; +} + +INIT_STATIC uint64_t GetImgSize(const char *dev, uint64_t offset) +{ + int fd = -1; + fd = open(dev, O_RDONLY | O_LARGEFILE); + if (fd < 0) { + BEGET_LOGE("open dev:[%s] failed.", dev); + return 0; + } + + if (lseek(fd, offset, SEEK_SET) < 0) { + BEGET_LOGE("lseek dev:[%s] failed, offset is %llu", dev, offset); + close(fd); + return 0; + } + + struct extheader_v1 header; + ssize_t nbytes = read(fd, &header, sizeof(header)); + if (nbytes != sizeof(header)) { + BEGET_LOGE("read dev:[%s] failed.", dev); + close(fd); + return 0; + } + close(fd); + + if (header.magic_number != EXTHDR_MAGIC) { + BEGET_LOGI("dev:[%s] is not have ext path, magic is 0x%x", dev, header.magic_number); + return 0; + } + BEGET_LOGI("get img size [%llu]", header.part_size); + return header.part_size; +} + +INIT_STATIC uint64_t GetFsSize(int fd) +{ + struct stat st; + if (fstat(fd, &st) == -1) { + BEGET_LOGE("fstat failed. errno: %d", errno); + return 0; + } + + uint64_t size = 0; + if (S_ISBLK(st.st_mode)) { + if (ioctl(fd, BLKGETSIZE64, &size) == -1) { + BEGET_LOGE("ioctl failed. errno: %d", errno); + return 0; + } + } else if (S_ISREG(st.st_mode)) { + if (st.st_size < 0) { + BEGET_LOGE("st_size is not right. st_size: %lld", st.st_size); + return 0; + } + size = (uint64_t)st.st_size; + } else { + BEGET_LOGE("unspported type st_mode:[%llu]", st.st_mode); + errno = EACCES; + return 0; + } + + BEGET_LOGI("get fs size:[%llu]", size); + return size; +} + +INIT_STATIC uint64_t GetBlockSize(const char *dev) +{ + int fd = -1; + fd = open(dev, O_RDONLY | O_LARGEFILE); + if (fd < 0) { + BEGET_LOGE("open dev:[%s] failed.", dev); + return 0; + } + + uint64_t blockSize = GetFsSize(fd); + close(fd); + return blockSize; +} + +/* 字节对齐函数,基于alignment进行字节对齐 */ +INIT_STATIC uint64_t AlignTo(uint64_t base, uint64_t alignment) +{ + if (alignment == 0) { + return base; + } + return (((base - 1) / alignment + 1) * alignment); +} + +INIT_STATIC int GetMapperAddr(const char *dev, uint64_t *start, uint64_t *length) +{ + /* 获取EROFS文件系统大小 */ + *start = LookupErofsEnd(dev); + if (*start == 0) { + BEGET_LOGE("get erofs end failed."); + return -1; + } + + /* + * 获取镜像大小 当前镜像布局有2种 + * 老布局:EROFS文件系统 + 全0数据填充 + HVB数据 老布局不存在EXTHEADER,获取到的镜像大小为0。直接基于文件系统切分 + * 新布局:EROFS文件系统 + EXTHEADER + HVB数据 新布局存在EXTHEADER,基于EXTHEADER获取镜像大小后进行分区切分 + */ + uint64_t imgSize = GetImgSize(dev, *start); + if (imgSize > 0) { + *start = AlignTo(imgSize, ALIGN_BLOCK_SIZE); + } + + /* 获取分区大小,老分区布局:分区大小 = 镜像大小 新分区布局:分区大小 = 镜像大小 + 无镜像填充的分区空位 */ + uint64_t totalSize = GetBlockSize(dev); + if (totalSize == 0) { + BEGET_LOGE("get block size failed."); + return -1; + } + + BEGET_LOGI("total size:[%llu], used size: [%llu], empty size:[%llu] on dev: [%s]", + totalSize, *start, totalSize - *start, dev); + + if (totalSize > *start) { + *length = totalSize - *start; + } else { + *length = 0; + } + + if (*length < MIN_DM_SIZE) { + BEGET_LOGE("empty size is too small, skip..."); + return -1; + } + + return 0; +} + +INIT_STATIC int ConstructLinearTarget(DmVerityTarget *target, const char *dev, uint64_t mapStart, uint64_t mapLength) +{ + if (target == NULL || dev == NULL) { + return -1; + } + + target->start = 0; + target->length = mapLength / SECTOR_SIZE; + target->paras = calloc(1, MAX_BUFFER_LEN); + if (target->paras == NULL) { + BEGET_LOGE("Failed to calloc target paras"); + return -1; + } + + if (snprintf_s(target->paras, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s %llu", dev, mapStart / SECTOR_SIZE) < 0) { + BEGET_LOGE("Failed to copy target paras."); + return -1; + } + target->paras_len = strlen(target->paras); + BEGET_LOGI("dev [%s], linearparas [%s], length [%s]", dev, target->paras, target->paras_len); + return 0; +} + +INIT_STATIC void DestoryLinearTarget(DmVerityTarget *target) +{ + if (target != NULL && target->paras != NULL) { + free(target->paras); + target->paras = NULL; + } +} + +INIT_STATIC int GetOverlayDevice(FstabItem *item, char *devRofs, const uint32_t devRofsLen, + char *devExt4, const uint32_t devExt4Len) +{ + uint64_t mapStart; + uint64_t mapLength; + char nameExt4[MAX_BUFFER_LEN] = {0}; + char nameRofs[MAX_BUFFER_LEN] = {0}; + + if (access(item->deviceName, 0) < 0) { + BEGET_LOGE("connot access dev [%s]", item->deviceName); + return -1; + } + + AllocDmName(item->mountPoint, nameRofs, MAX_BUFFER_LEN, nameExt4, MAX_BUFFER_LEN); + + if (GetMapperAddr(item->deviceName, &mapStart, &mapLength)) { + BEGET_LOGE("get mapper addr failed, dev is [%s]", item->deviceName); + return -1; + } + + DmVerityTarget dmRofsTarget = {0}; + DmVerityTarget dmExt4Target = {0}; + + int rc = ConstructLinearTarget(&dmRofsTarget, item->deviceName, 0, mapStart); + if (rc != 0) { + BEGET_LOGE("fs construct erofs linear target failed, dev is [%s]", item->deviceName); + goto exit; + } + rc = FsDmCreateLinearDevice(nameRofs, devRofs, devRofsLen, &dmRofsTarget); + if (rc != 0) { + BEGET_LOGE("fs create erofs linear device failed, dev is [%s]", item->deviceName); + goto exit; + } + + rc = ConstructLinearTarget(&dmExt4Target, item->deviceName, mapStart, mapLength); + if (rc != 0) { + BEGET_LOGE("fs construct ext4 linear target failed, dev is [%s]", item->deviceName); + goto exit; + } + rc = FsDmCreateLinearDevice(nameExt4, devExt4, devExt4Len, &dmExt4Target); + if (rc != 0) { + BEGET_LOGE("fs create ext4 linear device failed, dev is [%s]", item->deviceName); + goto exit; + } + BEGET_LOGI("get overlay device success , dev is [%s]", item->deviceName); +exit: + DestoryLinearTarget(&dmRofsTarget); + DestoryLinearTarget(&dmExt4Target); + return rc; +} + +INIT_STATIC int MountRofsDevice(const char *dev, const char *mnt) +{ + int rc = 0; + int retryCount = 3; + while (retryCount-- > 0) { + rc = mount(dev, mnt, "erofs", MS_RDONLY, NULL); + if (rc && (errno != EBUSY)) { + BEGET_LOGI("mount erofs dev [%s] on mnt [%s] failed, retry", dev, mnt); + sleep(1); + continue; + } + break; + } + + return 0; +} + +int MountExt4Device(const char *dev, const char *mnt, bool isFirstMount) +{ + int ret = 0; + char dirExt4[MAX_BUFFER_LEN] = {0}; + char dirUpper[MAX_BUFFER_LEN] = {0}; + char dirWork[MAX_BUFFER_LEN] = {0}; + ret = snprintf_s(dirExt4, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, PREFIX_OVERLAY"%s", mnt); + if (ret < 0) { + BEGET_LOGE("dirExt4 copy failed errno %d.", errno); + return -1; + } + + ret = snprintf_s(dirUpper, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, PREFIX_OVERLAY"%s"PREFIX_UPPER, mnt); + if (ret < 0) { + BEGET_LOGE("dirUpper copy failed errno %d.", errno); + return -1; + } + + ret = snprintf_s(dirWork, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, PREFIX_OVERLAY"%s"PREFIX_WORK, mnt); + if (ret < 0) { + BEGET_LOGE("dirWork copy failed errno %d.", errno); + return -1; + } + + if (mkdir(dirExt4, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir %s failed.", dirExt4); + return -1; + } + + int retryCount = 3; + while (retryCount-- > 0) { + ret = mount(dev, dirExt4, "ext4", MS_NOATIME | MS_NODEV, NULL); + if (ret && (errno != EBUSY)) { + BEGET_LOGI("mount ext4 dev [%s] on mnt [%s] failed, retry", dev, dirExt4); + sleep(1); + continue; + } + break; + } + + if (isFirstMount && mkdir(dirUpper, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir dirUpper:%s failed.", dirUpper); + return -1; + } + + if (isFirstMount && mkdir(dirWork, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir dirWork:%s failed.", dirWork); + return -1; + } + + return ret; +} + +INIT_STATIC void UnlinkMountPoint(const char *mountPoint) +{ + struct stat statInfo; + if (!lstat(mountPoint, &statInfo)) { + if ((statInfo.st_mode & S_IFMT) == S_IFLNK) { + unlink(mountPoint); + } + } +} + +INIT_STATIC int MountPartitionDevice(FstabItem *item, const char *devRofs, const char *devExt4) +{ + UnlinkMountPoint(item->mountPoint); + if (mkdir(item->mountPoint, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir mountPoint:%s failed.errno %d", item->mountPoint, errno); + return -1; + } + + WaitForFile(devRofs, WAIT_MAX_SECOND); + WaitForFile(devExt4, WAIT_MAX_SECOND); + + if (MountRofsDevice(devRofs, item->mountPoint)) { + BEGET_LOGE("mount erofs dev [%s] on mnt [%s] failed", devRofs, item->mountPoint); + return -1; + } + + if (strcmp(item->mountPoint, "/usr") == 0) { + SwitchRoot("/usr"); + } + + if (mkdir(PREFIX_LOWER, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir /lower failed. errno: %d", errno); + return -1; + } + + if (mkdir(PREFIX_OVERLAY, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir /overlay failed. errno: %d", errno); + return -1; + } + + char dirLower[MAX_BUFFER_LEN] = {0}; + if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s", PREFIX_LOWER, item->mountPoint) < 0) { + BEGET_LOGE("dirLower[%s]copy failed errno %d.", dirLower, errno); + return -1; + } + + if (mkdir(dirLower, MODE_MKDIR) && (errno != EEXIST)) { + BEGET_LOGE("mkdir dirLower[%s] failed. errno: %d", dirLower, errno); + return -1; + } + + if (MountRofsDevice(devRofs, dirLower)) { + BEGET_LOGE("mount erofs dev [%s] on mnt [%s] failed", devRofs, dirLower); + return -1; + } + + if (!CheckIsExt4(devExt4, 0)) { + BEGET_LOGI("is not ext4 devExt4 [%s] on mnt [%s]", devExt4, item->mountPoint); + return 0; + } + + BEGET_LOGI("is ext4 devExt4 [%s] on mnt [%s]", devExt4, item->mountPoint); + if (MountExt4Device(devExt4, item->mountPoint, false)) { + BEGET_LOGE("mount ext4 dev [%s] on mnt [%s] failed", devExt4, item->mountPoint); + return -1; + } + + return 0; +} + +int DoMountOverlayDevice(FstabItem *item) +{ + char devRofs[MAX_BUFFER_LEN] = {0}; + char devExt4[MAX_BUFFER_LEN] = {0}; + int rc = 0; + rc = GetOverlayDevice(item, devRofs, MAX_BUFFER_LEN, devExt4, MAX_BUFFER_LEN); + if (rc) { + BEGET_LOGE("get overlay device failed, source [%s] target [%s]", item->deviceName, item->mountPoint); + return -1; + } + + rc = FsDmInitDmDev(devRofs, true); + if (rc) { + BEGET_LOGE("init erofs dm dev failed"); + return -1; + } + + rc = FsDmInitDmDev(devExt4, true); + if (rc) { + BEGET_LOGE("init ext4 dm dev failed"); + return -1; + } + + rc = MountPartitionDevice(item, devRofs, devExt4); + if (rc) { + BEGET_LOGE("init ext4 dm dev failed"); + return -1; + } + return rc; +} \ No newline at end of file diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c new file mode 100644 index 0000000000000000000000000000000000000000..b11df82831eb7d4361b3167d3ace6d4baaf8f6f1 --- /dev/null +++ b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024-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 +#include +#include "securec.h" +#include "init_utils.h" + +#include "erofs_overlay_common.h" + +bool IsOverlayEnable(void) +{ + char oemMode[MAX_BUFFER_LEN] = {0}; + int ret = GetExactParameterFromCmdLine("oemmode", oemMode, MAX_BUFFER_LEN, EMPTY_VALUE); + if (ret) { + BEGET_LOGE("Failed get oenmode from cmdline."); + return false; + } + + char buildvariant[MAX_BUFFER_LEN] = {0}; + ret = GetExactParameterFromCmdLine("buildvariant", buildvariant, MAX_BUFFER_LEN, EMPTY_VALUE); + if (ret) { + BEGET_LOGE("Failed get buildvariant from cmdline."); + return false; + } + + if (strcmp(oemMode, "user") == 0 || strcmp(buildvariant, "eng") != 0) { + BEGET_LOGI("not support overlay, oemMode:[%s] buildvariant:[%s]", oemMode, buildvariant); + return false; + } + BEGET_LOGI("overlay enable."); + return true; +} + +bool CheckIsExt4(const char *dev, uint64_t offset) +{ + int fd = open(dev, O_RDONLY | O_LARGEFILE); + if (fd < 0) { + BEGET_LOGE("cannot open [dev]:%s", dev); + return false; + } + + if (lseek(fd, offset + EXT4_SUPER_BLOCK_START_POSITION, SEEK_SET) < 0) { + BEGET_LOGE("cannot seek [dev]:%s", dev); + close(fd); + return false; + } + ext4_super_block superBlock; + ssize_t nbytes = read(fd, &superBlock, sizeof(superBlock)); + if (nbytes != sizeof(superBlock)) { + BEGET_LOGE("read ext4 super block fail"); + close(fd); + return false; + } + + if (superBlock.s_magic == EXT4_SUPER_MAGIC) { + BEGET_LOGI("this [dev] %s is ext4:[block cout]: %d, [size]: %d", dev, + superBlock.s_blocks_count_lo, (superBlock.s_blocks_count_lo * BLOCK_SIZE_UNIT)); + close(fd); + return true; + } + close(fd); + return false; +} + +bool CheckIsErofs(const char *dev) +{ + int fd = open(dev, O_RDONLY | O_LARGEFILE); + if (fd < 0) { + BEGET_LOGE("cannot open [dev]:%s", dev); + return false; + } + + if (lseek(fd, EROFS_SUPER_BLOCK_START_POSITION, SEEK_SET) < 0) { + BEGET_LOGE("cannot seek [dev]:%s", dev); + close(fd); + return false; + } + struct erofs_super_block superBlock; + ssize_t nbytes = read(fd, &superBlock, sizeof(superBlock)); + if (nbytes != sizeof(superBlock)) { + BEGET_LOGE("read erofs super block fail"); + close(fd); + return false; + } + + BEGET_LOGI("the [dev] %s magic [%u]", dev, superBlock.magic); + if (superBlock.magic == EROFS_SUPER_MAGIC) { + BEGET_LOGI("this [dev] %s is erofs", dev); + close(fd); + return true; + } + close(fd); + return false; +} \ No newline at end of file diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c new file mode 100644 index 0000000000000000000000000000000000000000..da52dd2ee6ce858647555e3b65993df6718ddbb2 --- /dev/null +++ b/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2024-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 +#include +#include +#include "securec.h" +#include "init_utils.h" +#include "fs_dm.h" +#include "fs_manager/fs_manager.h" +#include "erofs_remount_overlay.h" + +int GetRemountResult(void) +{ + int fd = open(REMOUNT_RESULT_FLAG, O_RDONLY); + if (fd >= 0) { + char buff[1]; + int ret = read(fd, buff, 1); + if (ret < 0) { + BEGET_LOGE("read remount.result.done failed errno %d", errno); + close(fd); + return REMOUNT_FAIL; + } + close(fd); + if (buff[0] == '0' + REMOUNT_SUCC) { + return REMOUNT_SUCC; + } + } + return REMOUNT_FAIL; +} + +void SetRemountResultFlag() +{ + struct stat st; + int ret; + + int statRet = stat(REMOUNT_RESULT_PATH, &st); + if (statRet != 0) { + ret = mkdir(REMOUNT_RESULT_PATH, MODE_MKDIR); + if (ret < 0 && errno != EEXIST) { + BEGET_LOGE("mkdir remount path failed errno %d", errno); + return; + } + } + + int fd = open(REMOUNT_RESULT_FLAG, O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + BEGET_LOGE("open remount.result.done failed errno %d", errno); + return; + } + + char buff[1]; + buff[0] = '0' + REMOUNT_SUCC; + + ret = write(fd, buff, 1); + if (ret < 0) { + BEGET_LOGE("write buff failed errno %d", errno); + } + close(fd); + BEGET_LOGI("set remount result flag successfully"); +} + +INIT_STATIC int Modem2Exchange(const char *modemPath, const char *exchangePath) +{ + int ret; + ret = mkdir(exchangePath, MODE_MKDIR); + if (ret) { + BEGET_LOGE("mkdir %s failed.", exchangePath); + } else { + BEGET_LOGI("mkdir %s succeed.", exchangePath); + } + + ret = mount(modemPath, exchangePath, NULL, MS_BIND | MS_RDONLY, NULL); + if (ret) { + BEGET_LOGE("bind %s to %s failed.", modemPath, exchangePath); + } else { + BEGET_LOGI("bind %s to %s succeed.", modemPath, exchangePath); + } + + return ret; +} + +INIT_STATIC int Exchange2Modem(const char *modemPath, const char *exchangePath) +{ + int ret; + struct stat statInfo; + if (lstat(exchangePath, &statInfo)) { + BEGET_LOGE("no exchangePath %s.", exchangePath); + return 0; + } + + ret = mount(exchangePath, modemPath, NULL, MS_BIND | MS_RDONLY, NULL); + if (ret) { + BEGET_LOGE("bind %s to %s failed.", exchangePath, modemPath); + } else { + BEGET_LOGI("bind %s to %s succeed.", exchangePath, modemPath); + } + + ret = umount(exchangePath); + if (ret) { + BEGET_LOGE("umount %s failed.", exchangePath); + } else { + BEGET_LOGI("umount %s succeed.", exchangePath); + } + + ret = remove(exchangePath); + if (ret) { + BEGET_LOGE("remove %s failed.", exchangePath); + } else { + BEGET_LOGI("remove %s succeed.", exchangePath); + } + + return ret; +} + +void OverlayRemountVendorPre(void) +{ + struct stat statInfo; + + if (!stat(MODEM_DRIVER_MNT_PATH, &statInfo)) { + Modem2Exchange(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH); + } + + if (!stat(MODEM_VENDOR_MNT_PATH, &statInfo)) { + Modem2Exchange(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH); + } + + if (!stat(MODEM_FW_MNT_PATH, &statInfo)) { + Modem2Exchange(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH); + } +} + +void OverlayRemountVendorPost() +{ + Exchange2Modem(MODEM_DRIVER_MNT_PATH, MODEM_DRIVER_EXCHANGE_PATH); + Exchange2Modem(MODEM_VENDOR_MNT_PATH, MODEM_VENDOR_EXCHANGE_PATH); + Exchange2Modem(MODEM_FW_MNT_PATH, MODEM_FW_EXCHANGE_PATH); +} + +int MountOverlayOne(const char *mnt) +{ + if ((strcmp(mnt, MODEM_DRIVER_MNT_PATH) == 0) || (strcmp(mnt, MODEM_VENDOR_MNT_PATH) == 0)) { + return 0; + } + char dirLower[MAX_BUFFER_LEN] = {0}; + char dirUpper[MAX_BUFFER_LEN] = {0}; + char dirWork[MAX_BUFFER_LEN] = {0}; + char mntOpt[MAX_BUFFER_LEN] = {0}; + + if (strcmp(mnt, "/usr") == 0) { + if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s", "/system") < 0) { + BEGET_LOGE("copy system dirLower failed. errno %d", errno); + return -1; + } + } else { + if (snprintf_s(dirLower, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s", PREFIX_LOWER, mnt) < 0) { + BEGET_LOGE("copy dirLower failed. errno %d", errno); + return -1; + } + } + + if (snprintf_s(dirUpper, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_UPPER) < 0) { + BEGET_LOGE("copy dirUpper failed. errno %d", errno); + return -1; + } + + if (snprintf_s(dirWork, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%s%s%s", PREFIX_OVERLAY, mnt, PREFIX_WORK) < 0) { + BEGET_LOGE("copy dirWork failed. errno %d", errno); + return -1; + } + + if (snprintf_s(mntOpt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, + "upperdir=%s,lowerdir=%s,workdir=%s,override_creds=off", dirUpper, dirLower, dirWork) < 0) { + BEGET_LOGE("copy mntOpt failed. errno %d", errno); + return -1; + } + + if (strcmp(mnt, "/usr") == 0) { + if (mount("overlay", "/system", "overlay", 0, mntOpt)) { + BEGET_LOGE("mount system overlay failed. errno %d", errno); + return -1; + } + } else { + if (mount("overlay", mnt, "overlay", 0, mntOpt)) { + BEGET_LOGE("mount overlay fs failed. errno %d", errno); + return -1; + } + } + BEGET_LOGI("mount overlay fs success on mnt:%s", mnt); + return 0; +} + +int RemountOverlay(void) +{ + char *remountPath[] = { + "/usr", "/vendor", "/sys_prod", "/chip_prod", "/preload", "/cust", "/version", "/patch_hw" + }; + for (size_t i = 0; i < ARRAY_LENGTH(remountPath); i++) { + struct stat statInfo; + char dirMnt[MAX_BUFFER_LEN] = {0}; + if (snprintf_s(dirMnt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "/mnt/overlay%s/upper", remountPath[i]) < 0) { + BEGET_LOGE("copy dirMnt [%s] failed.", dirMnt); + return -1; + } + + if (lstat(dirMnt, &statInfo)) { + BEGET_LOGW("dirMnt [%s] not exist.", dirMnt); + continue; + } + + if (strcmp(remountPath[i], "/vendor") == 0) { + OverlayRemountVendorPre(); + } + + if (MountOverlayOne(remountPath[i])) { + BEGET_LOGE("mount overlay failed on mnt [%s].", dirMnt); + return -1; + } + + if (strcmp(remountPath[i], "/vendor") == 0) { + OverlayRemountVendorPost(); + } + } + return 0; +} \ No newline at end of file diff --git a/services/include/init_read_cfg.h b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_mount_overlay.h similarity index 62% rename from services/include/init_read_cfg.h rename to interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_mount_overlay.h index 4cb57e130f98b570e9bb792492d3026ad04b1f93..591451e519f023edd8318770f8d83c92bf2609e0 100644 --- a/services/include/init_read_cfg.h +++ b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_mount_overlay.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -13,20 +13,21 @@ * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_READ_CFG_H -#define BASE_STARTUP_INITLITE_READ_CFG_H +#ifndef EROFS_MOUNT_OVERLAY_H +#define EROFS_MOUNT_OVERLAY_H + +#include "fs_manager/fs_manager.h" +#include "erofs_overlay_common.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -#define INIT_CONFIGURATION_FILE "/etc/init.cfg" -#define MAX_PATH_ARGS_CNT 20 -#define MAX_ONE_ARG_LEN 200 // max length of one param/path -void InitReadCfg(); -void ParseInitCfg(const char *configFile); +int DoMountOverlayDevice(FstabItem *item); + +int MountExt4Device(const char *dev, const char *mnt, bool isFirstMount); #ifdef __cplusplus #if __cplusplus @@ -34,4 +35,4 @@ void ParseInitCfg(const char *configFile); #endif #endif -#endif // BASE_STARTUP_INITLITE_READ_CFG_H +#endif // EROFS_MOUNT_OVERLAY_H diff --git a/ueventd/list.h b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_overlay_common.h old mode 100755 new mode 100644 similarity index 50% rename from ueventd/list.h rename to interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_overlay_common.h index 06eaaff05d799f7c4c5f2f7c172c09fa69f8d841..71c9def506f33c4b6967791b4a84cf678ca8958d --- a/ueventd/list.h +++ b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_overlay_common.h @@ -1,44 +1,51 @@ -/* - * Copyright (c) 2021 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_LIST_H -#define BASE_STARTUP_INITLITE_LIST_H - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -typedef struct ListNode { - struct ListNode *next; - struct ListNode *prev; -} ListNode; - -#define ListEmpty(node) ((node).next == &(node) && (node).prev == &(node)) -#define ListEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member)) -#define ForEachListEntry(list, node) \ - for (node = (list)->next; node != (list); node = node->next) - -void ListInit(struct ListNode *list); -void ListAddTail(struct ListNode *list, struct ListNode *item); -void ListRemove(struct ListNode *item); -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif - -#endif // BASE_STARTUP_INITLITE_LIST_H +/* + * Copyright (c) 2024-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 EROFS_OVERLAY_COMMON_H +#define EROFS_OVERLAY_COMMON_H + +#include +#include +#include "fs_manager/ext4_super_block.h" +#include "fs_manager/erofs_super_block.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MODE_MKDIR 0755 +#define EXT4_SUPER_MAGIC 0xEF53 +#define EXT4_SUPER_OFFSET 0x400 +#define SECTOR_SIZE 512 +#define PREFIX_LOWER "/mnt/lower" +#define PREFIX_OVERLAY "/mnt/overlay" +#define PREFIX_UPPER "/upper" +#define PREFIX_WORK "/work" + +bool IsOverlayEnable(void); + +bool CheckIsExt4(const char *dev, uint64_t offset); + +bool CheckIsErofs(const char *dev); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif \ No newline at end of file diff --git a/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_remount_overlay.h b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_remount_overlay.h new file mode 100644 index 0000000000000000000000000000000000000000..99f6e3102fe947c38392bdb3e69598b3920ac538 --- /dev/null +++ b/interfaces/innerkits/fs_manager/erofs_overlay/include/erofs_remount_overlay.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024-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 EROFS_REMOUNT_OVERLAY_H +#define EROFS_REMOUNT_OVERLAY_H + +#include "erofs_overlay_common.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MODEM_DRIVER_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_driver" +#define MODEM_VENDOR_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_vendor" +#define MODEM_FW_MNT_PATH STARTUP_INIT_UT_PATH"/vendor/modem/modem_fw" +#define MODEM_DRIVER_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/driver_exchange" +#define MODEM_VENDOR_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/vendor_exchange" +#define MODEM_FW_EXCHANGE_PATH STARTUP_INIT_UT_PATH"/mnt/fw_exchange" +#define REMOUNT_RESULT_PATH STARTUP_INIT_UT_PATH"/data/service/el1/startup/remount/" +#define REMOUNT_RESULT_FLAG STARTUP_INIT_UT_PATH"/data/service/el1/startup/remount/remount.result.done" + +#define REMOUNT_SUCC 0 +#define REMOUNT_FAIL 1 + +int GetRemountResult(void); + +void SetRemountResultFlag(); + +int RemountOverlay(void); + +int MountOverlayOne(const char *mnt); + +void OverlayRemountVendorPre(void); + +void OverlayRemountVendorPost(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // EROFS_REMOUNT_OVERLAY_H diff --git a/interfaces/innerkits/fs_manager/fstab.c b/interfaces/innerkits/fs_manager/fstab.c new file mode 100644 index 0000000000000000000000000000000000000000..8baad448fd7cfa8ffac1608b42ae287f3cf18761 --- /dev/null +++ b/interfaces/innerkits/fs_manager/fstab.c @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2021-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 "beget_ext.h" +#include "fs_manager/fs_manager.h" +#include "init_utils.h" +#include "securec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define CMDLINE_LABEL_FSCRYPT_DISABLE "ohos.init.fscrypt.disable" +#define CMDLINE_VALUE_FSCRYPT_DISABLE "disabled" +#define CMDLINE_VALUE_LEN (sizeof(CMDLINE_VALUE_FSCRYPT_DISABLE) - 1) +struct FsManagerFlags { + char *name; + unsigned int flags; +}; + +struct MountFlags { + char *name; + unsigned long flags; +}; + +static char *g_fscryptPolicy = NULL; + +static unsigned int ConvertFlags(char *flagBuffer) +{ + static struct FsManagerFlags fsFlags[] = { + {"check", FS_MANAGER_CHECK}, + {"wait", FS_MANAGER_WAIT}, + {"required", FS_MANAGER_REQUIRED}, + {"nofail", FS_MANAGER_NOFAIL}, +#ifdef SUPPORT_HVB + {"hvb", FS_MANAGER_HVB}, +#endif + {"fsprojquota", FS_MANAGER_PROJQUOTA}, + {"fscasefold", FS_MANAGER_CASEFOLD}, + {"fscompression", FS_MANAGER_COMPRESSION}, + {"fsdedup", FS_MANAGER_DEDUP}, + {"formattable", FS_MANAGER_FORMATTABLE}, + }; + + BEGET_CHECK_RETURN_VALUE(flagBuffer != NULL && *flagBuffer != '\0', 0); // No valid flags. + int flagCount = 0; + unsigned int flags = 0; + const int maxCount = 3; + char **vector = SplitStringExt(flagBuffer, ",", &flagCount, maxCount); + BEGET_CHECK_RETURN_VALUE(vector != NULL && flagCount != 0, 0); + for (size_t i = 0; i < ARRAY_LENGTH(fsFlags); i++) { + for (int j = 0; j < flagCount; j++) { + if (strcmp(fsFlags[i].name, vector[j]) == 0) { + flags |= fsFlags[i].flags; + } + } + } + FreeStringVector(vector, flagCount); + return flags; +} + +static int AddToFstab(Fstab *fstab, FstabItem *item) +{ + if (fstab == NULL || item == NULL) { + return -1; + } + if (fstab->tail == NULL) { + fstab->head = fstab->tail = item; + } else { + fstab->tail->next = item; + fstab->tail = item; + } + return 0; +} + +void ReleaseFstabItem(FstabItem *item) +{ + if (item != NULL) { + if (item->deviceName != NULL) { + free(item->deviceName); + item->deviceName = NULL; + } + + if (item->mountPoint != NULL) { + free(item->mountPoint); + item->mountPoint = NULL; + } + + if (item->fsType != NULL) { + free(item->fsType); + item->fsType = NULL; + } + + if (item->mountOptions != NULL) { + free(item->mountOptions); + item->mountOptions = NULL; + } + + free(item); + } +} + +void ReleaseFstab(Fstab *fstab) +{ + if (fstab != NULL) { + FstabItem *item = fstab->head; + while (item != NULL) { + FstabItem *tmp = item->next; + ReleaseFstabItem(item); + item = tmp; + } + fstab->head = fstab->tail = NULL; + free(fstab); + fstab = NULL; + } +} + +int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator) +{ + BEGET_CHECK_RETURN_VALUE(str != NULL && fstab != NULL, -1); + char *rest = NULL; + FstabItem *item = NULL; + char *p = NULL; + BEGET_ERROR_CHECK(separator != NULL && *separator != '\0', return -1, "Invalid separator for parsing fstab"); + + if ((item = (FstabItem *)calloc(1, sizeof(FstabItem))) == NULL) { + errno = ENOMEM; + BEGET_LOGE("Allocate memory for FS table item failed, err = %d", errno); + return -1; + } + + do { + BEGET_ERROR_CHECK((p = strtok_r(str, separator, &rest)) != NULL, break, "Failed to parse block device."); + item->deviceName = strdup(p); + BEGET_ERROR_CHECK(item->deviceName != NULL, break, "strdup deviceName failed."); + + BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse mount point."); + item->mountPoint = strdup(p); + BEGET_ERROR_CHECK(item->mountPoint != NULL, break, "strdup mountPoint failed."); + + BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse fs type."); + item->fsType = strdup(p); + BEGET_ERROR_CHECK(item->fsType != NULL, break, "strdup fsType failed."); + + BEGET_ERROR_CHECK((p = strtok_r(NULL, separator, &rest)) != NULL, break, "Failed to parse mount options."); + item->mountOptions = strdup(p); + BEGET_ERROR_CHECK(item->mountOptions != NULL, break, "strdup mountOptions failed."); + + if ((p = strtok_r(NULL, separator, &rest)) == NULL) { + BEGET_LOGE("Failed to parse fs manager flags."); + break; + } + // @fsManagerFlags only for fstab + // Ignore it if we read from /proc/mounts + if (!procMounts) { + item->fsManagerFlags = ConvertFlags(p); + } else { + item->fsManagerFlags = 0; + } + return AddToFstab(fstab, item); + } while (0); + + ReleaseFstabItem(item); + item = NULL; + return -1; +} + +Fstab *ReadFstabFromFile(const char *file, bool procMounts) +{ + char *line = NULL; + size_t allocn = 0; + ssize_t readn = 0; + Fstab *fstab = NULL; + + FILE *fp = NULL; + char *realPath = GetRealPath(file); + if (realPath != NULL) { + fp = fopen(realPath, "r"); + free(realPath); + } else { + fp = fopen(file, "r"); // no file system, can not get real path + } + BEGET_ERROR_CHECK(fp != NULL, return NULL, "Open %s failed, err = %d", file, errno); + + if ((fstab = (Fstab *)calloc(1, sizeof(Fstab))) == NULL) { + BEGET_LOGE("Allocate memory for FS table failed, err = %d", errno); + fclose(fp); + fp = NULL; + return NULL; + } + + // Record line number of fstab file + size_t ln = 0; + while ((readn = getline(&line, &allocn, fp)) != -1) { + char *p = NULL; + ln++; + if (line[readn - 1] == '\n') { + line[readn - 1] = '\0'; + } + p = line; + while (isspace(*p)) { + p++; + } + + if (*p == '\0' || *p == '#') { + continue; + } + + if (ParseFstabPerLine(p, fstab, procMounts, " \t") < 0) { + if (errno == ENOMEM) { + // Ran out of memory, there is no reason to continue. + break; + } + // If one line in fstab file parsed with a failure. just give a warning + // and skip it. + BEGET_LOGW("Cannot parse file \" %s \" at line %zu. skip it", file, ln); + continue; + } + } + if (line != NULL) { + free(line); + } + (void)fclose(fp); + fp = NULL; + return fstab; +} + +FstabItem *FindFstabItemForMountPoint(Fstab fstab, const char *mp) +{ + FstabItem *item = NULL; + if (mp != NULL) { + for (item = fstab.head; item != NULL; item = item->next) { + if ((item->mountPoint != NULL) && (strcmp(item->mountPoint, mp) == 0)) { + break; + } + } + } + return item; +} + +FstabItem *FindFstabItemForPath(Fstab fstab, const char *path) +{ + FstabItem *item = NULL; + + if (path == NULL || *path != '/') { + return NULL; + } + + char tmp[PATH_MAX] = {0}; + char *dir = NULL; + if (strncpy_s(tmp, PATH_MAX - 1, path, strlen(path)) != EOK) { + BEGET_LOGE("Failed to copy path."); + return NULL; + } + + dir = tmp; + while (true) { + item = FindFstabItemForMountPoint(fstab, dir); + if (item != NULL) { + break; + } + dir = dirname(dir); + // Reverse walk through path and met "/", just quit. + if (dir == NULL || strcmp(dir, "/") == 0) { + break; + } + } + return item; +} + +static char *GetFstabFile(char *fileName, size_t size) +{ + if (InUpdaterMode() == 1) { + if (strncpy_s(fileName, size, "/etc/fstab.updater", strlen("/etc/fstab.updater")) != 0) { + BEGET_LOGE("Failed strncpy_s err=%d", errno); + return NULL; + } + } else { + char hardware[MAX_BUFFER_LEN] = {0}; + int ret = GetParameterFromCmdLine("hardware", hardware, MAX_BUFFER_LEN); + if (ret != 0) { + BEGET_LOGE("Failed get hardware from cmdline"); + return NULL; + } + if (snprintf_s(fileName, size, size - 1, "/vendor/etc/fstab.%s", hardware) == -1) { + BEGET_LOGE("Failed to build fstab file, err=%d", errno); + return NULL; + } + } + BEGET_LOGI("fstab file is %s", fileName); + return fileName; +} + +int GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char *deviceName, int nameLen) +{ + if (fstab == NULL || mountPoint == NULL || *mountPoint == '\0' || deviceName == NULL) { + return -1; + } + FstabItem *item = FindFstabItemForMountPoint(*fstab, mountPoint); + if (item == NULL) { + BEGET_LOGE("Failed to get fstab item from mount point \" %s \"", mountPoint); + return -1; + } + if (strncpy_s(deviceName, nameLen, item->deviceName, strlen(item->deviceName)) != 0) { + BEGET_LOGE("Failed to copy block device name, err=%d", errno); + return -1; + } + return 0; +} + +int GetBlockDeviceByName(const char *deviceName, const Fstab *fstab, char* miscDev, size_t size) +{ + for (FstabItem *item = fstab->head; item != NULL; item = item->next) { + if (strstr(item->deviceName, deviceName) != NULL) { + BEGET_CHECK_RETURN_VALUE(strcpy_s(miscDev, size, item->deviceName) != 0, 0); + } + } + return -1; +} + +static const struct MountFlags MOUNT_FLAGS[] = { + { "noatime", MS_NOATIME }, + { "noexec", MS_NOEXEC }, + { "nosuid", MS_NOSUID }, + { "nodev", MS_NODEV }, + { "nodiratime", MS_NODIRATIME }, + { "ro", MS_RDONLY }, + { "rw", 0 }, + { "sync", MS_SYNCHRONOUS }, + { "remount", MS_REMOUNT }, + { "bind", MS_BIND }, + { "rec", MS_REC }, + { "unbindable", MS_UNBINDABLE }, + { "private", MS_PRIVATE }, + { "slave", MS_SLAVE }, + { "shared", MS_SHARED }, + { "defaults", 0 }, +}; + +static bool IsDefaultMountFlags(const char *str) +{ + bool isDefault = false; + + if (str != NULL) { + for (size_t i = 0; i < ARRAY_LENGTH(MOUNT_FLAGS); i++) { + if (strcmp(str, MOUNT_FLAGS[i].name) == 0) { + isDefault = true; + } + } + } + return isDefault; +} + +static unsigned long ParseDefaultMountFlag(const char *str) +{ + unsigned long flags = 0; + + if (str != NULL) { + for (size_t i = 0; i < ARRAY_LENGTH(MOUNT_FLAGS); i++) { + if (strcmp(str, MOUNT_FLAGS[i].name) == 0) { + flags = MOUNT_FLAGS[i].flags; + break; + } + } + } + return flags; +} + +static bool IsFscryptOption(const char *option) +{ + if (!option) { + return false; + } + char *fscryptPre = "fscrypt="; + if (strncmp(option, fscryptPre, strlen(fscryptPre)) == 0) { + return true; + } + return false; +} + +static void StoreFscryptPolicy(const char *option) +{ + if (option == NULL) { + return; + } + + char fscryptDisable[CMDLINE_VALUE_LEN_MAX] = {0}; + int ret = GetParameterFromCmdLine(CMDLINE_LABEL_FSCRYPT_DISABLE, fscryptDisable, sizeof(fscryptDisable)); + if (ret == 0 && strncmp(fscryptDisable, + CMDLINE_VALUE_FSCRYPT_DISABLE, CMDLINE_VALUE_LEN) == 0) { + BEGET_LOGE("fscrypt policy is disabled by cmdline"); + return; + } + + if (g_fscryptPolicy != NULL) { + BEGET_LOGW("StoreFscryptPolicy:inited policy is not empty"); + free(g_fscryptPolicy); + } + g_fscryptPolicy = strdup(option); + if (g_fscryptPolicy == NULL) { + BEGET_LOGE("StoreFscryptPolicy:no memory"); + return; + } + BEGET_LOGI("StoreFscryptPolicy:store fscrypt policy, %s", option); +} + +int LoadFscryptPolicy(char *buf, size_t size) +{ + BEGET_LOGI("LoadFscryptPolicy start"); + if (buf == NULL || g_fscryptPolicy == NULL) { + BEGET_LOGE("LoadFscryptPolicy:buf or fscrypt policy is empty"); + return -ENOMEM; + } + if (size == 0) { + BEGET_LOGE("LoadFscryptPloicy:size is invalid"); + return -EINVAL; + } + if (strcpy_s(buf, size, g_fscryptPolicy) != 0) { + BEGET_LOGE("loadFscryptPolicy:strcmp failed, error = %d", errno); + return -EFAULT; + } + free(g_fscryptPolicy); + g_fscryptPolicy = NULL; + BEGET_LOGI("LoadFscryptPolicy success"); + + return 0; +} + +unsigned long GetMountFlags(char *mountFlag, char *fsSpecificData, size_t fsSpecificDataSize, + const char *mountPoint) +{ + unsigned long flags = 0; + BEGET_CHECK_RETURN_VALUE(mountFlag != NULL && fsSpecificData != NULL, 0); + int flagCount = 0; + // Why max count of mount flags is 15? + // There are lots for mount flags defined in sys/mount.h + // But we only support to parse 15 in @ParseDefaultMountFlags() function + // So set default mount flag number to 15. + // If the item configured in fstab contains flag over than 15, + // @SplitStringExt can handle it and parse them all. but the parse function will drop it. + const int maxCount = 15; + char **flagsVector = SplitStringExt(mountFlag, ",", &flagCount, maxCount); + + if (flagsVector == NULL || flagCount == 0) { + // No flags or something wrong in SplitStringExt,just return. + return 0; + } + + for (int i = 0; i < flagCount; i++) { + char *p = flagsVector[i]; + if (IsDefaultMountFlags(p)) { + flags |= ParseDefaultMountFlag(p); + } else { + if (IsFscryptOption(p) && + !strncmp(mountPoint, "/data", strlen("/data"))) { + StoreFscryptPolicy(p + strlen("fscrypt=")); + continue; + } + if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, p, strlen(p)) != EOK) { + BEGET_LOGW("Failed to append mount flag \" %s \", ignore it.", p); + continue; + } + if (i == flagCount - 1) { // last flags, do not need to append ',' + break; + } + // Combined each mount flag with ',' + if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) { + BEGET_LOGW("Failed to append comma"); + break; // If cannot add ',' to the end of flags, there is not reason to continue. + } + } + } + + FreeStringVector(flagsVector, flagCount); + return flags; +} + +int GetBlockDevicePath(const char *partName, char *path, size_t size) +{ + BEGET_CHECK_RETURN_VALUE(partName != NULL && path != NULL, -1); + Fstab *fstab = LoadFstabFromCommandLine(); + if (fstab == NULL) { + BEGET_LOGI("fstab not found from cmdline, try to get it from file"); + char *fstabFile = GetFstabFile(path, size); + BEGET_CHECK_RETURN_VALUE(fstabFile != NULL, -1); + fstab = ReadFstabFromFile(fstabFile, false); + } + BEGET_CHECK_RETURN_VALUE(fstab != NULL, -1); + int ret = GetBlockDeviceByMountPoint(partName, fstab, path, size); + BEGET_INFO_CHECK(ret == 0, ret = GetBlockDeviceByName(partName, fstab, path, size), + "Mount point not found, try to get path by device name."); + ReleaseFstab(fstab); + return ret; +} + +#define OHOS_REQUIRED_MOUNT_PREFIX "ohos.required_mount." +/* + * Fstab includes block device node, mount point, file system type, MNT_ Flags and options. + * We separate them by spaces in fstab.required file, but the separator is '@' in CmdLine. + * The prefix "ohos.required_mount." is the flag of required fstab information in CmdLine. + * Format as shown below: + * @@@@ + * e.g. + * ohos.required_mount.system=/dev/block/xxx/by-name/system@/usr@ext4@ro,barrier=1@wait,required + */ +static int ParseRequiredMountInfo(const char *item, Fstab *fstab) +{ + char mountOptions[MAX_BUFFER_LEN] = {}; + char partName[NAME_SIZE] = {}; + // Sanity checks + BEGET_CHECK(!(item == NULL || *item == '\0' || fstab == NULL), return -1); + + char *p = NULL; + if ((p = strstr(item, "=")) != NULL) { + const char *q = item + strlen(OHOS_REQUIRED_MOUNT_PREFIX); // Get partition name + BEGET_CHECK(!(q == NULL || *q == '\0' || (p - q) <= 0), return -1); + BEGET_ERROR_CHECK(strncpy_s(partName, NAME_SIZE -1, q, p - q) == EOK, + return -1, "Failed to copy required partition name"); + p++; // skip '=' + BEGET_ERROR_CHECK(strncpy_s(mountOptions, MAX_BUFFER_LEN -1, p, strlen(p)) == EOK, + return -1, "Failed to copy required mount info: %s", item); + } + BEGET_LOGV("Config mount option of partition %s is [%s]", partName, mountOptions); + if (ParseFstabPerLine(mountOptions, fstab, false, "@") < 0) { + BEGET_LOGE("Failed to parse mount options of partition \' %s \', options: %s", partName, mountOptions); + return -1; + } + return 0; +} + +Fstab* LoadFstabFromCommandLine(void) +{ + Fstab *fstab = NULL; + char *cmdline = ReadFileData(BOOT_CMD_LINE); + bool isDone = false; + + BEGET_ERROR_CHECK(cmdline != NULL, return NULL, "Read from \'%s\' failed, err = %d", BOOT_CMD_LINE, errno); + TrimTail(cmdline, '\n'); + fstab = (Fstab *)calloc(1, sizeof(Fstab)); + BEGET_ERROR_CHECK(fstab != NULL, free(cmdline); return NULL, + "Allocate memory for FS table failed, err = %d", errno); + char *start = cmdline; + char *end = start + strlen(cmdline); + while (start < end) { + char *token = strstr(start, " "); + if (token == NULL) { + break; + } + + // Startswith " " + if (token == start) { + start++; + continue; + } + *token = '\0'; + if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX, + strlen(OHOS_REQUIRED_MOUNT_PREFIX)) != 0) { + start = token + 1; + continue; + } + isDone = true; + if (ParseRequiredMountInfo(start, fstab) < 0) { + BEGET_LOGE("Failed to parse \' %s \'", start); + isDone = false; + break; + } + start = token + 1; + } + + // handle last one + if (start < end) { + if (strncmp(start, OHOS_REQUIRED_MOUNT_PREFIX, + strlen(OHOS_REQUIRED_MOUNT_PREFIX)) == 0 && + ParseRequiredMountInfo(start, fstab) < 0) { + BEGET_LOGE("Failed to parse \' %s \'", start); + isDone = false; + } + } + + if (!isDone) { + ReleaseFstab(fstab); + fstab = NULL; + } + free(cmdline); + return fstab; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c new file mode 100755 index 0000000000000000000000000000000000000000..58bd6c5263a1bfe3d8b419e14feded6be468a2b6 --- /dev/null +++ b/interfaces/innerkits/fs_manager/fstab_mount.c @@ -0,0 +1,798 @@ +/* + * Copyright (c) 2021 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 "beget_ext.h" +#include "fs_manager/fs_manager.h" +#include "init_utils.h" +#include "param/init_param.h" +#include "securec.h" +#include "switch_root.h" +#ifdef SUPPORT_HVB +#include "fs_dm.h" +#include "dm_verity.h" +#endif +#include "init_filesystems.h" +#ifdef EROFS_OVERLAY +#include "erofs_mount_overlay.h" +#endif +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define FS_MANAGER_BUFFER_SIZE 512 +#define BLOCK_SIZE_BUFFER (64) +#define RESIZE_BUFFER_SIZE 1024 +const off_t PARTITION_ACTIVE_SLOT_OFFSET = 1024; +const off_t PARTITION_ACTIVE_SLOT_SIZE = 4; + +__attribute__((weak)) void InitPostMount(const char *mountPoint, int rc) +{ +} + +__attribute__((weak)) void InitTimerControl(bool isSuspend) +{ +} + +__attribute__((weak)) bool NeedDoAllResize(const unsigned int fsManagerFlags) +{ + BEGET_LOGW("kdump: static"); + return true; +} + +static const SUPPORTED_FILE_SYSTEM supportedFileSystems[] = { + { "ext4", 0 }, + { "f2fs", 1 }, + { "overlay", 0 }, + { NULL, 0 } +}; + +static void **extendedFileSystems_ = NULL; + +void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[]) +{ + extendedFileSystems_ = (void **)extendedFileSystems; +} + +static const SUPPORTED_FILE_SYSTEM *GetSupportedFileSystemInfo(const char *fsType) +{ + return (const SUPPORTED_FILE_SYSTEM *)OH_ExtendableStrDictGet((void **)supportedFileSystems, + sizeof(SUPPORTED_FILE_SYSTEM), fsType, 0, extendedFileSystems_); +} + +static bool IsSupportedDataType(const char *fsType) +{ + const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType); + if (item == NULL) { + return false; + } + if (item->for_userdata) { + return true; + } + return false; +} + +bool IsSupportedFilesystem(const char *fsType) +{ + const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType); + if (item == NULL) { + return false; + } + return true; +} + +/* 1024(stdout buffer size) - 256(log tag max size approximately) */ +#define LOG_LINE_SZ 768 +#define PIPE_FDS 2 + +static void LogToKmsg(int fd) +{ + char buffer[LOG_LINE_SZ] = {0}; + int lineMaxSize = LOG_LINE_SZ - 1; + int pos = 0; + + do { + ssize_t lineSize = read(fd, buffer, lineMaxSize); + if (lineSize < 0) { + BEGET_LOGE("Failed to read, errno: %d", errno); + break; + } + if (!lineSize) { + /* No more lines, just break */ + break; + } + if (lineSize > lineMaxSize) { + BEGET_LOGE("Invalid read size, ret: %d is larger than buffer size: %d", lineSize, lineMaxSize); + lineSize = lineMaxSize; + } + /* Make sure that each line terminates with '\0' */ + buffer[lineSize] = '\0'; + int posStart = 0; + for (pos = posStart; pos < lineSize; pos++) { + if (buffer[pos] == '\n') { + buffer[pos] = '\0'; + BEGET_LOGI("%s", &buffer[posStart]); + posStart = pos + 1; + } + } + if (posStart < pos) { + BEGET_LOGI("%s", &buffer[posStart]); + } + } while (1); + (void)close(fd); +} + +static void RedirectToStdFd(int fd) +{ + if (dup2(fd, STDOUT_FILENO) < 0) { + BEGET_LOGE("Failed to dup2 stdout, errno: %d, just continue", errno); + } + if (dup2(fd, STDERR_FILENO) < 0) { + BEGET_LOGE("Failed to dup2 stderr, errno: %d, just continue", errno); + } + (void)close(fd); +} + +static int ExecCommand(int argc, char **argv) +{ + BEGET_CHECK(!(argc == 0 || argv == NULL || argv[0] == NULL), return -1); + + bool logToKmsg = false; + int pipeFds[PIPE_FDS]; + if (pipe2(pipeFds, O_CLOEXEC) < 0) { + BEGET_LOGE("Failed to create pipe, errno: %d, just continue", errno); + } else { + logToKmsg = true; + } + + BEGET_LOGI("Execute %s begin", argv[0]); + pid_t pid = fork(); + BEGET_ERROR_CHECK(pid >= 0, return -1, "Fork new process to format failed: %d", errno); + if (pid == 0) { + if (logToKmsg) { + (void)close(pipeFds[0]); + RedirectToStdFd(pipeFds[1]); + } + execv(argv[0], argv); + BEGET_LOGE("Failed to execv, errno: %d", errno); + exit(-1); + } + if (logToKmsg) { + (void)close(pipeFds[1]); + LogToKmsg(pipeFds[0]); + } + int status = 0; + waitpid(pid, &status, 0); + if (WIFEXITED(status)) { + BEGET_LOGI("Execute success, status: %d, command: %s", WEXITSTATUS(status), argv[0]); + return WEXITSTATUS(status); + } + BEGET_LOGE("Failed to execute %s", argv[0]); + return -1; +} + +int DoFormat(const char *devPath, const char *fsType) +{ + if (devPath == NULL || fsType == NULL) { + return -1; + } + + if (!IsSupportedFilesystem(fsType)) { + BEGET_LOGE("Do not support filesystem \" %s \"", fsType); + return -1; + } + int ret = 0; + if (strcmp(fsType, "ext4") == 0) { + char blockSizeBuffer[BLOCK_SIZE_BUFFER] = {0}; + const unsigned int blockSize = 4096; + ret = snprintf_s(blockSizeBuffer, BLOCK_SIZE_BUFFER, BLOCK_SIZE_BUFFER - 1, "%u", blockSize); + BEGET_ERROR_CHECK(ret != -1, return -1, "Failed to build block size buffer"); + + char *formatCmds[] = { + "/bin/mke2fs", "-F", "-t", (char *)fsType, "-b", blockSizeBuffer, (char *)devPath, NULL + }; + int argc = ARRAY_LENGTH(formatCmds); + char **argv = (char **)formatCmds; + ret = ExecCommand(argc, argv); + } else if (IsSupportedDataType(fsType)) { +#ifdef __MUSL__ + char *formatCmds[] = { + "/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr", + "-O", "sb_checksum", (char *)devPath, NULL + }; +#else + char *formatCmds[] = { + "/bin/make_f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr", + "-O", "sb_checksum", (char *)devPath, NULL + }; +#endif + int argc = ARRAY_LENGTH(formatCmds); + char **argv = (char **)formatCmds; + ret = ExecCommand(argc, argv); + } + return ret; +} + +MountStatus GetMountStatusForMountPoint(const char *mp) +{ + if (mp == NULL) { + return MOUNT_ERROR; + } + char buffer[FS_MANAGER_BUFFER_SIZE] = {0}; + const int expectedItems = 6; + int count = 0; + char **mountItems = NULL; + MountStatus status = MOUNT_ERROR; + bool found = false; + + FILE *fp = fopen("/proc/mounts", "r"); + BEGET_CHECK(fp != NULL, return status); + + while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) { + size_t n = strlen(buffer); + if (buffer[n - 1] == '\n') { + buffer[n - 1] = '\0'; + } + mountItems = SplitStringExt(buffer, " ", &count, expectedItems); + if (mountItems != NULL && count == expectedItems) { + // Second item in /proc/mounts is mount point + if (strcmp(mountItems[1], mp) == 0) { + FreeStringVector(mountItems, count); + found = true; + break; + } + FreeStringVector(mountItems, count); + } + } + if (found) { + status = MOUNT_MOUNTED; + } else if (feof(fp) > 0) { + status = MOUNT_UMOUNTED; + } + (void)fclose(fp); + fp = NULL; + return status; +} + +static int DoMountOneItem(FstabItem *item); +#define MAX_RESIZE_PARAM_NUM 20 +static int DoResizeF2fs(FstabItem *item, const unsigned long long size) +{ + char *file = "/system/bin/resize.f2fs"; + char sizeStr[RESIZE_BUFFER_SIZE] = {0}; + char *argv[MAX_RESIZE_PARAM_NUM] = {NULL}; + int argc = 0; + + BEGET_ERROR_CHECK(NeedDoAllResize(item->fsManagerFlags), return -1, "no need do resize, bucause kdump has done"); + BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize.f2fs is not exists."); + + argv[argc++] = file; + if (item->fsManagerFlags & FS_MANAGER_PROJQUOTA) { + argv[argc++] = "-O"; + argv[argc++] = "extra_attr,project_quota"; + } + if (item->fsManagerFlags & FS_MANAGER_CASEFOLD) { + argv[argc++] = "-O"; + argv[argc++] = "casefold"; + argv[argc++] = "-C"; + argv[argc++] = "utf8"; + } + if (item->fsManagerFlags & FS_MANAGER_COMPRESSION) { + argv[argc++] = "-O"; + argv[argc++] = "extra_attr,compression"; + } + if (item->fsManagerFlags & FS_MANAGER_DEDUP) { + argv[argc++] = "-O"; + argv[argc++] = "extra_attr,dedup"; + } + + if (size != 0) { + unsigned long long realSize = size * + ((unsigned long long)RESIZE_BUFFER_SIZE * RESIZE_BUFFER_SIZE / FS_MANAGER_BUFFER_SIZE); + int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%llu", realSize); + if (len <= 0) { + BEGET_LOGE("Write buffer size failed."); + } + argv[argc++] = "-t"; + argv[argc++] = sizeStr; + } + + argv[argc++] = (char*)(item->deviceName); + BEGET_ERROR_CHECK(argc <= MAX_RESIZE_PARAM_NUM, return -1, "argc: %d is too big.", argc); + int ret = ExecCommand(argc, argv); + if (ret == 0) { + BEGET_LOGI("resize success."); + return ret; + } + DoMountOneItem(item); + umount(item->mountPoint); + BEGET_LOGE("remount and resize again."); + return ExecCommand(argc, argv); +} + +static int DoFsckF2fs(const char* device) +{ + char *file = "/system/bin/fsck.f2fs"; + BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "fsck.f2fs is not exists."); + + char *cmd[] = { + file, "-p1", (char *)device, NULL + }; + int argc = ARRAY_LENGTH(cmd); + char **argv = (char **)cmd; + InitTimerControl(true); + int ret = ExecCommand(argc, argv); + InitTimerControl(false); + return ret; +} + +static int DoResizeExt(const char* device, const unsigned long long size) +{ + char *file = "/system/bin/resize2fs"; + BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize2fs is not exists."); + + int ret = 0; + if (size == 0) { + char *cmd[] = { + file, "-f", (char *)device, NULL + }; + int argc = ARRAY_LENGTH(cmd); + char **argv = (char **)cmd; + ret = ExecCommand(argc, argv); + } else { + char sizeStr[RESIZE_BUFFER_SIZE] = {0}; + int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%lluM", size); + if (len <= 0) { + BEGET_LOGE("Write buffer size failed."); + } + char *cmd[] = { + file, "-f", (char *)device, sizeStr, NULL + }; + int argc = ARRAY_LENGTH(cmd); + char **argv = (char **)cmd; + ret = ExecCommand(argc, argv); + } + return ret; +} + +static int DoFsckExt(const char* device) +{ + char *file = "/system/bin/e2fsck"; + BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "e2fsck is not exists."); + + char *cmd[] = { + file, "-y", (char *)device, NULL + }; + int argc = ARRAY_LENGTH(cmd); + char **argv = (char **)cmd; + return ExecCommand(argc, argv); +} + +static int Mount(const char *source, const char *target, const char *fsType, + unsigned long flags, const char *data) +{ + struct stat st = {}; + int rc = -1; + + bool isTrue = source == NULL || target == NULL || fsType == NULL; + BEGET_ERROR_CHECK(!isTrue, return -1, "Invalid argument for mount."); + + isTrue = stat(target, &st) != 0 && errno != ENOENT; + BEGET_ERROR_CHECK(!isTrue, return -1, "Cannot get stat of \" %s \", err = %d", target, errno); + + BEGET_CHECK((st.st_mode & S_IFMT) != S_IFLNK, unlink(target)); // link, delete it. + + if (mkdir(target, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) { + BEGET_ERROR_CHECK(errno == EEXIST, return -1, "Failed to create dir \" %s \", err = %d", target, errno); + } + errno = 0; + if ((rc = mount(source, target, fsType, flags, data)) != 0) { + BEGET_WARNING_CHECK(errno != EBUSY, rc = 0, "Mount %s to %s busy, ignore", source, target); + } + return rc; +} + +static int GetSlotInfoFromCmdLine(const char *slotInfoName) +{ + char value[MAX_BUFFER_LEN] = {0}; + BEGET_INFO_CHECK(GetParameterFromCmdLine(slotInfoName, value, MAX_BUFFER_LEN) == 0, + return -1, "Failed to get %s value from cmdline", slotInfoName); + return atoi(value); +} + +static int GetSlotInfoFromBootctrl(off_t offset, off_t size) +{ + char bootctrlDev[MAX_BUFFER_LEN] = {0}; + BEGET_ERROR_CHECK(GetBlockDevicePath("/bootctrl", bootctrlDev, MAX_BUFFER_LEN) == 0, + return -1, "Failed to get bootctrl device"); + char *realPath = GetRealPath(bootctrlDev); + BEGET_ERROR_CHECK(realPath != NULL, return -1, "Failed to get bootctrl device real path"); + int fd = open(realPath, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + free(realPath); + BEGET_ERROR_CHECK(fd >= 0, return -1, "Failed to open bootctrl device, errno %d", errno); + BEGET_ERROR_CHECK(lseek(fd, offset, SEEK_SET) >= 0, close(fd); return -1, + "Failed to lseek bootctrl device fd, errno %d", errno); + int slotInfo = 0; + BEGET_INFO_CHECK(read(fd, &slotInfo, sizeof(slotInfo)) == size, close(fd); return -1, + "Failed to read current slot from bootctrl, errno %d", errno); + close(fd); + return slotInfo; +} + +int GetBootSlots(void) +{ + return GetSlotInfoFromCmdLine("bootslots"); +} + +int GetCurrentSlot(void) +{ + // get current slot from cmdline + int currentSlot = GetSlotInfoFromCmdLine("currentslot"); + BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot); + BEGET_LOGI("No valid slot value found from cmdline, try to get it from bootctrl"); + + // get current slot from bootctrl + return GetSlotInfoFromBootctrl(PARTITION_ACTIVE_SLOT_OFFSET, PARTITION_ACTIVE_SLOT_SIZE); +} + +static int DoMountOneItem(FstabItem *item) +{ + BEGET_LOGI("Mount device %s to %s", item->deviceName, item->mountPoint); + unsigned long mountFlags; + char fsSpecificData[FS_MANAGER_BUFFER_SIZE] = {0}; + + mountFlags = GetMountFlags(item->mountOptions, fsSpecificData, sizeof(fsSpecificData), + item->mountPoint); + + int retryCount = 3; + int rc = 0; + while (retryCount-- > 0) { + rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData); + if (rc == 0) { + return rc; + } + + if (FM_MANAGER_FORMATTABLE_ENABLED(item->fsManagerFlags)) { + BEGET_LOGI("Device is formattable"); + int ret = DoFormat(item->deviceName, item->fsType); + BEGET_LOGI("End format image ret %d", ret); + if (ret != 0) { + continue; + } + rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData); + if (rc == 0) { + return rc; + } + } + BEGET_LOGE("Mount device %s to %s failed, err = %d, retry", item->deviceName, item->mountPoint, errno); + } + return rc; +} + +#ifdef EROFS_OVERLAY +static int MountItemByFsType(FstabItem *item) +{ + if (CheckIsErofs(item->deviceName)) { + if (strcmp(item->fsType, "erofs") == 0) { + if (IsOverlayEnable()) { + return DoMountOverlayDevice(item); + } + int rc = DoMountOneItem(item); + if (rc == 0 && strcmp(item->mountPoint, "/usr") == 0) { + SwitchRoot("/usr"); + } + return rc; + } else { + BEGET_LOGI("fsType not erofs system, device [%s] skip erofs mount process", item->deviceName); + return 0; + } + } + + if (strcmp(item->fsType, "erofs") != 0) { + int rc = DoMountOneItem(item); + if (rc == 0 && strcmp(item->mountPoint, "/usr") == 0) { + SwitchRoot("/usr"); + } + return rc; + } + + BEGET_LOGI("fsType is erofs system, device [%s] skip ext4 or hms mount process", item->deviceName); + return 0; +} +#endif + +int MountOneItem(FstabItem *item) +{ + if (item == NULL) { + return -1; + } + + if (FM_MANAGER_WAIT_ENABLED(item->fsManagerFlags)) { + WaitForFile(item->deviceName, WAIT_MAX_SECOND); + } + + if (strcmp(item->mountPoint, "/data") == 0 && IsSupportedDataType(item->fsType)) { + int ret = DoFsckF2fs(item->deviceName); + if (ret != 0) { + BEGET_LOGE("Failed to fsck.f2fs dir %s , ret = %d", item->deviceName, ret); + } + ret = DoResizeF2fs(item, 0); + if (ret != 0) { + BEGET_LOGE("Failed to resize.f2fs dir %s , ret = %d", item->deviceName, ret); + } + } else if (strcmp(item->fsType, "ext4") == 0 && strcmp(item->mountPoint, "/data") == 0) { + int ret = DoResizeExt(item->deviceName, 0); + if (ret != 0) { + BEGET_LOGE("Failed to resize2fs dir %s , ret = %d", item->deviceName, ret); + } + ret = DoFsckExt(item->deviceName); + if (ret != 0) { + BEGET_LOGE("Failed to e2fsck dir %s , ret = %d", item->deviceName, ret); + } + } + + int rc = 0; +#ifdef EROFS_OVERLAY + rc = MountItemByFsType(item); +#else + rc = DoMountOneItem(item); + if (rc == 0 && (strcmp(item->mountPoint, "/usr") == 0)) { + SwitchRoot("/usr"); + } +#endif + InitPostMount(item->mountPoint, rc); + if (rc != 0) { + if (FM_MANAGER_NOFAIL_ENABLED(item->fsManagerFlags)) { + BEGET_LOGE("Mount no fail device %s to %s failed, err = %d", item->deviceName, item->mountPoint, errno); + } else { + BEGET_LOGW("Mount %s to %s failed, err = %d. Ignore failure", item->deviceName, item->mountPoint, errno); + rc = 0; + } + } else { + BEGET_LOGI("Mount %s to %s successful", item->deviceName, item->mountPoint); + } + return rc; +} + +#if defined EROFS_OVERLAY && defined SUPPORT_HVB +static bool NeedDmVerity(FstabItem *item) +{ + if (CheckIsErofs(item->deviceName)) { + if (strcmp(item->fsType, "erofs") == 0) { + return true; + } + } else { + if (strcmp(item->fsType, "erofs") != 0) { + return true; + } + } + return false; +} +#endif + +static void AdjustPartitionNameByPartitionSlot(FstabItem *item) +{ + BEGET_CHECK_ONLY_RETURN(strstr(item->deviceName, "/system") != NULL || + strstr(item->deviceName, "/vendor") != NULL); + char buffer[MAX_BUFFER_LEN] = {0}; + int slot = GetCurrentSlot(); + BEGET_ERROR_CHECK(slot > 0 && slot <= MAX_SLOT, slot = 1, "slot value %d is invalid, set default value", slot); + BEGET_ERROR_CHECK(sprintf_s(buffer, sizeof(buffer), "%s_%c", item->deviceName, 'a' + slot - 1) > 0, + return, "Failed to format partition name suffix, use default partition name"); + free(item->deviceName); + item->deviceName = strdup(buffer); + if (item->deviceName == NULL) { + BEGET_LOGE("failed dup devicename"); + return; + } + BEGET_LOGI("partition name with slot suffix: %s", item->deviceName); +} + +static int CheckRequiredAndMount(FstabItem *item, bool required) +{ + int rc = 0; + if (item == NULL) { + return -1; + } + + // Mount partition during second startup. + if (!required) { + if (!FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { + rc = MountOneItem(item); + } + return rc; + } + + // Mount partition during one startup. + if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { + int bootSlots = GetBootSlots(); + BEGET_INFO_CHECK(bootSlots <= 1, AdjustPartitionNameByPartitionSlot(item), + "boot slots is %d, now adjust partition name according to current slot", bootSlots); +#ifdef SUPPORT_HVB +#ifdef EROFS_OVERLAY + if (!NeedDmVerity(item)) { + BEGET_LOGI("not need dm verity, do mount item %s", item->deviceName); + return MountOneItem(item); + } +#endif + rc = HvbDmVeritySetUp(item); + if (rc != 0) { + BEGET_LOGE("set dm_verity err, ret = 0x%x", rc); + if (!FM_MANAGER_NOFAIL_ENABLED(item->fsManagerFlags)) { + rc = 0; + BEGET_LOGW("DmVeritySetUp fail for %s, ignore error and do not mount", item->deviceName); + } else { + BEGET_LOGE("DmVeritySetUp fail for no fail devices %s, error!", item->deviceName); + } + return rc; + } +#endif + rc = MountOneItem(item); + } + return rc; +} + +int MountAllWithFstab(const Fstab *fstab, bool required) +{ + BEGET_CHECK(fstab != NULL, return -1); + + FstabItem *item = NULL; + int rc = -1; + +#ifdef SUPPORT_HVB + if (required) { + rc = HvbDmVerityinit(fstab); + if (rc != 0) { + BEGET_LOGE("set dm_verity init, ret = 0x%x", rc); + return rc; + } + } +#endif + + for (item = fstab->head; item != NULL; item = item->next) { + rc = CheckRequiredAndMount(item, required); + if (required && (rc < 0)) { // Init fail to mount in the first stage and exit directly. + break; + } + } + +#ifdef SUPPORT_HVB + if (required) + HvbDmVerityFinal(); +#endif + + return rc; +} + +int MountAllWithFstabFile(const char *fstabFile, bool required) +{ + bool isFile = fstabFile == NULL || *fstabFile == '\0'; + BEGET_CHECK(!isFile, return -1); + + Fstab *fstab = NULL; + if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) { + BEGET_LOGE("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile); + return -1; + } + + int rc = MountAllWithFstab(fstab, required); + if (rc != 0) { + BEGET_LOGE("[startup_failed]MountAllWithFstab failed %s %d %d %d", fstabFile, + FSTAB_MOUNT_FAILED, required, rc); + } + ReleaseFstab(fstab); + fstab = NULL; + return rc; +} + +int UmountAllWithFstabFile(const char *fstabFile) +{ + bool isFile = fstabFile == NULL || *fstabFile == '\0'; + BEGET_CHECK(!isFile, return -1); + + Fstab *fstab = NULL; + fstab = ReadFstabFromFile(fstabFile, false); + BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile); + + FstabItem *item = NULL; + int rc = -1; + for (item = fstab->head; item != NULL; item = item->next) { + BEGET_LOGI("Umount %s.", item->mountPoint); + MountStatus status = GetMountStatusForMountPoint(item->mountPoint); + if (status == MOUNT_ERROR) { + BEGET_LOGW("Cannot get mount status of mount point \" %s \"", item->mountPoint); + continue; // Cannot get mount status, just ignore it and try next one. + } else if (status == MOUNT_UMOUNTED) { + BEGET_LOGI("Mount point \" %s \" already unmounted. device path: %s, fs type: %s.", + item->mountPoint, item->deviceName, item->fsType); + continue; + } else { + rc = umount(item->mountPoint); + if (rc == -1) { + BEGET_LOGE("Umount %s failed, device path: %s, fs type: %s, err = %d.", + item->mountPoint, item->deviceName, item->fsType, errno); + } else { + BEGET_LOGE("Umount %s successfully.", item->mountPoint); + } + } + } + ReleaseFstab(fstab); + fstab = NULL; + return rc; +} + +int FsManagerDmRemoveDevice(const char *devName) +{ +#ifdef SUPPORT_HVB + return FsDmRemoveDevice(devName); +#endif + return 0; +} + +int MountOneWithFstabFile(const char *fstabFile, const char *devName, bool required) +{ + bool isFile = fstabFile == NULL || *fstabFile == '\0'; + BEGET_CHECK(!isFile, return -1); + + Fstab *fstab = NULL; + fstab = ReadFstabFromFile(fstabFile, false); + BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile); + + FstabItem *item = NULL; + int rc = -1; + +#ifdef SUPPORT_HVB + if (required) { + rc = HvbDmVerityinit(fstab); + if (rc != 0) { + BEGET_LOGE("set dm_verity init, ret = 0x%x", rc); + return rc; + } + } +#endif + + for (item = fstab->head; item != NULL; item = item->next) { + if (strcmp(item->mountPoint, devName) == 0) { + rc = CheckRequiredAndMount(item, required); + break; + } + } + +#ifdef SUPPORT_HVB + if (required) { + HvbDmVerityFinal(); + } +#endif + + ReleaseFstab(fstab); + fstab = NULL; + return rc; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c b/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c new file mode 100755 index 0000000000000000000000000000000000000000..10b6c49f72f4b5f094397ebe573069cc4a369f02 --- /dev/null +++ b/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2022-2023 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 "securec.h" +#include "beget_ext.h" +#include +#include +#include +#include +#include +#include +#include +#include "ueventd.h" +#include "ueventd_socket.h" +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define DM_VERSION0 (4) +#define DM_VERSION1 (0) +#define DM_VERSION2 (0) +#define DM_ALIGN_MASK (7) +#define DM_ALIGN(x) (((x) + DM_ALIGN_MASK) & ~DM_ALIGN_MASK) +#define DEVICE_MAPPER_PATH "/dev/mapper/control" +#define DM_DEVICE_PATH_PREFIX "/dev/block/dm-" + +#define FS_DM_RETURN_ERR_IF_NULL(__ptr) \ + do { \ + if ((__ptr) == NULL) { \ + BEGET_LOGE("error, %s is NULL\n", #__ptr); \ + return -1; \ + } \ + } while (0) + +static int InitDmIo(struct dm_ioctl *io, const char *devName) +{ + errno_t err; + + err = memset_s(io, sizeof(*io), 0, sizeof(*io)); + if (err != EOK) { + BEGET_LOGE("memset io, ret=%d", err); + return -1; + } + + io->version[0] = DM_VERSION0; + io->version[1] = DM_VERSION1; + io->version[2] = DM_VERSION2; + io->data_size = sizeof(*io); + io->data_start = 0; + + if (devName == NULL) { + return 0; + } + + err = strcpy_s(io->name, sizeof(io->name), devName); + if (err != EOK) { + BEGET_LOGE("cp devName, ret=%d", err); + return -1; + } + + return 0; +} + +static int CreateDmDevice(int fd, const char *devName) +{ + int rc; + struct dm_ioctl io; + + rc = InitDmIo(&io, devName); + if (rc != 0) { + return rc; + } + + rc = ioctl(fd, DM_DEV_CREATE, &io); + if (rc != 0) { + BEGET_LOGE("error, DM_DEV_CREATE failed for %s, ret=%d", devName, rc); + return rc; + } + + return 0; +} + +static int LoadDmDeviceTable(int fd, const char *devName, + DmVerityTarget *target, bool needDmVerity) +{ + int rc; + errno_t err; + char *parasBuf = NULL; + size_t parasTotalSize; + struct dm_ioctl *io = NULL; + struct dm_target_spec *ts = NULL; + char *paras = NULL; + + FS_DM_RETURN_ERR_IF_NULL(target); + FS_DM_RETURN_ERR_IF_NULL(target->paras); + + parasTotalSize = DM_ALIGN(sizeof(*io) + sizeof(*ts) + target->paras_len + 1); + parasBuf = calloc(1, parasTotalSize); + if (parasBuf == NULL) { + BEGET_LOGE("error, calloc dm table fail"); + return -1; + } + + io = (struct dm_ioctl *)parasBuf; + ts = (struct dm_target_spec *)(parasBuf + sizeof(*io)); + paras = parasBuf + sizeof(*io) + sizeof((*ts)); + + do { + rc = InitDmIo(io, devName); + if (rc != 0) { + BEGET_LOGE("error 0x%x, init dm io", rc); + break; + } + + io->data_size = parasTotalSize; + io->data_start = sizeof(*io); + io->target_count = 1; + io->flags |= DM_READONLY_FLAG; + + ts->status = 0; + ts->sector_start = target->start; + ts->length = target->length; + char *targetType = needDmVerity ? "verity" : "linear"; + err = strcpy_s(ts->target_type, sizeof(ts->target_type), targetType); + if (err != EOK) { + rc = -1; + BEGET_LOGE("error 0x%x, cp target type", err); + break; + } + + err = strcpy_s(paras, target->paras_len + 1, target->paras); + if (err != EOK) { + rc = -1; + BEGET_LOGE("error 0x%x, cp target paras", err); + break; + } + + ts->next = parasTotalSize - sizeof(*io); + + rc = ioctl(fd, DM_TABLE_LOAD, io); + if (rc != 0) { + BEGET_LOGE("error 0x%x, DM_TABLE_LOAD failed for %s", rc, devName); + break; + } + } while (0); + + free(parasBuf); + + return rc; +} + +static int ActiveDmDevice(int fd, const char *devName) +{ + int rc; + struct dm_ioctl io; + + rc = InitDmIo(&io, devName); + if (rc != 0) { + return rc; + } + + io.flags |= DM_READONLY_FLAG; + + rc = ioctl(fd, DM_DEV_SUSPEND, &io); + if (rc != 0) { + BEGET_LOGE("error, DM_TABLE_SUSPEND for %s, ret=%d", devName, rc); + return rc; + } + + return 0; +} + +int GetDmDevPath(int fd, char **dmDevPath, const char *devName) +{ + int rc; + char *path = NULL; + size_t path_len = strlen(DM_DEVICE_PATH_PREFIX) + 32; + unsigned int dev_num; + struct dm_ioctl io; + + rc = InitDmIo(&io, devName); + if (rc != 0) { + BEGET_LOGE("error 0x%x, init Dm io", rc); + return rc; + } + + rc = ioctl(fd, DM_DEV_STATUS, &io); + if (rc != 0) { + BEGET_LOGE("error, DM_DEV_STATUS for %s, ret=%d", devName, rc); + return rc; + } + + dev_num = minor(io.dev); + + path = calloc(1, path_len); + if (path == NULL) { + BEGET_LOGE("error, alloc dm dev path"); + return -1; + } + + rc = snprintf_s(path, path_len, path_len - 1, "%s%u", DM_DEVICE_PATH_PREFIX, dev_num); + if (rc < 0) { + BEGET_LOGE("error 0x%x, cp dm dev path", rc); + free(path); + return -1; + } + + *dmDevPath = path; + + return 0; +} + +int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target) +{ + int rc; + int fd = -1; + + fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC); + if (fd < 0) { + BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH); + return -1; + } + + rc = CreateDmDevice(fd, devName); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create dm device fail", rc); + close(fd); + return rc; + } + + rc = LoadDmDeviceTable(fd, devName, target, true); + if (rc != 0) { + BEGET_LOGE("error 0x%x, load device table fail", rc); + close(fd); + return rc; + } + + rc = ActiveDmDevice(fd, devName); + if (rc != 0) { + BEGET_LOGE("error 0x%x, active device fail", rc); + close(fd); + return rc; + } + + rc = GetDmDevPath(fd, dmDevPath, devName); + if (rc != 0) { + BEGET_LOGE("error 0x%x, get dm dev fail", rc); + close(fd); + return rc; + } + close(fd); + return 0; +} + +int FsDmInitDmDev(char *devPath, bool useSocket) +{ + int rc; + char dmDevPath[PATH_MAX] = {0}; + char *devName = NULL; + + if (devPath == NULL) { + BEGET_LOGE("error, devPath is NULL"); + return -1; + } + + devName = basename(devPath); + + rc = snprintf_s(&dmDevPath[0], sizeof(dmDevPath), sizeof(dmDevPath) - 1, "%s%s", "/sys/block/", devName); + if (rc < 0) { + BEGET_LOGE("error 0x%x, format dm dev", rc); + return rc; + } + + int ueventSockFd = -1; + if (useSocket) { + ueventSockFd = UeventdSocketInit(); + if (ueventSockFd < 0) { + BEGET_LOGE("error, Failed to create uevent socket"); + return -1; + } + } + + RetriggerUeventByPath(ueventSockFd, &dmDevPath[0]); + + close(ueventSockFd); + + return 0; +} + +int FsDmRemoveDevice(const char *devName) +{ + int rc; + int fd = -1; + struct dm_ioctl io; + + fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC); + if (fd < 0) { + BEGET_LOGE("error 0x%x, open %s", errno, DEVICE_MAPPER_PATH); + return -1; + } + + rc = InitDmIo(&io, devName); + if (rc != 0) { + close(fd); + BEGET_LOGE("error 0x%x, init dm io", rc); + return -1; + } + + io.flags |= DM_READONLY_FLAG; + + rc = ioctl(fd, DM_DEV_REMOVE, &io); + if (rc != 0) { + close(fd); + BEGET_LOGE("error, DM_DEV_REMOVE failed for %s, ret=%d", devName, rc); + return -1; + } + + close(fd); + return 0; +} + +static int DmGetDeviceName(int fd, const char *devName, char *outDevName, const uint64_t outDevNameLen) +{ + int rc; + char *path = NULL; + size_t pathLen = strlen(DM_DEVICE_PATH_PREFIX) + 32; + struct dm_ioctl io; + rc = InitDmIo(&io, devName); + if (rc != 0) { + BEGET_LOGE("init dm io failed"); + return rc; + } + + rc = ioctl(fd, DM_DEV_STATUS, &io); + if (rc != 0) { + BEGET_LOGE("get DM_DEV_STATUS failed"); + return rc; + } + + int devNum = (io.dev & 0xff) | ((io.dev >> 12) & 0xff00); + path = calloc(1, pathLen); + if (path == NULL) { + BEGET_LOGE("calloc path failed"); + return rc; + } + + rc = snprintf_s(path, pathLen, pathLen - 1, "%s%d", DM_DEVICE_PATH_PREFIX, devNum); + if (rc < 0) { + BEGET_LOGE("copy dm path failed"); + free(path); + path = NULL; + return rc; + } + + rc = memcpy_s(outDevName, outDevNameLen, path, pathLen); + if (rc < 0) { + BEGET_LOGE("copy dm path failed"); + } + BEGET_LOGI("dm get device outDevName %s, devNum %d", path, devNum); + free(path); + path = NULL; + return rc; +} + +int FsDmCreateLinearDevice(const char *devName, char *dmBlkName, uint64_t dmBlkNameLen, DmVerityTarget *target) +{ + int rc; + int fd = -1; + fd = open(DEVICE_MAPPER_PATH, O_RDWR | O_CLOEXEC); + if (fd < 0) { + BEGET_LOGE("open mapper path failed"); + return -1; + } + + rc = CreateDmDevice(fd, devName); + if (rc) { + BEGET_LOGE("create dm device failed"); + close(fd); + return -1; + } + + rc = DmGetDeviceName(fd, devName, dmBlkName, dmBlkNameLen); + if (rc) { + BEGET_LOGE("get dm device name failed"); + close(fd); + return -1; + } + + rc = LoadDmDeviceTable(fd, devName, target, false); + if (rc) { + BEGET_LOGE("load dm device name failed"); + close(fd); + return -1; + } + + rc = ActiveDmDevice(fd, devName); + if (rc) { + BEGET_LOGE("active dm device name failed"); + close(fd); + return -1; + } + close(fd); + BEGET_LOGI("fs create rofs linear device success, dev is [%s]", devName); + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/fs_manager/libfs_dm/include/fs_dm.h b/interfaces/innerkits/fs_manager/libfs_dm/include/fs_dm.h new file mode 100755 index 0000000000000000000000000000000000000000..368275a0ef0272f8af3baebb1448962bbc4cb342 --- /dev/null +++ b/interfaces/innerkits/fs_manager/libfs_dm/include/fs_dm.h @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2023 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 STARTUP_LIBFS_DM_H +#define STARTUP_LIBFS_DM_H + +#include +#include +#include +#include "fs_manager.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct { + uint64_t start; + uint64_t length; + char *paras; + uint64_t paras_len; +} DmVerityTarget; + +int FsDmInitDmDev(char *devPath, bool useSocket); +int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target); +int FsDmRemoveDevice(const char *devName); +int FsDmCreateLinearDevice(const char *devName, char *dmBlkName, uint64_t dmBlkNameLen, DmVerityTarget *target); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // STARTUP_LIBFS_DM_H diff --git a/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c b/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c new file mode 100755 index 0000000000000000000000000000000000000000..aa72376df947813f5ca9587015d55fc054f78e6f --- /dev/null +++ b/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c @@ -0,0 +1,857 @@ +/* + * Copyright (c) 2022-2023 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 "fs_hvb.h" +#include "fs_dm.h" +#include "securec.h" +#include "fs_manager/ext4_super_block.h" +#include "fs_manager/erofs_super_block.h" +#include +#include "beget_ext.h" +#include "init_utils.h" +#include +#include +#include "hvb_sm2.h" +#include "hvb_sm3.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define FS_HVB_VERITY_TARGET_MAX 512 +#define FS_HVB_BLANK_SPACE_ASCII 32 +#define FS_HVB_SECTOR_BYTES 512 +#define FS_HVB_UINT64_MAX_LENGTH 64 +#define FS_HVB_HASH_ALG_STR_MAX 32 + +#define FS_HVB_DIGEST_SHA256_BYTES 32 +#define FS_HVB_DIGEST_SHA512_BYTES 64 +#define FS_HVB_DIGEST_SM3_BYTES 32 +#define FS_HVB_DIGEST_MAX_BYTES FS_HVB_DIGEST_SHA512_BYTES +#define FS_HVB_DIGEST_STR_MAX_BYTES 128 +#define FS_HVB_DEVPATH_MAX_LEN 128 +#define FS_HVB_RVT_PARTITION_NAME "rvt" +#define FS_HVB_EXT_RVT_PARTITION_NAME "ext_rvt" +#define FS_HVB_CMDLINE_PATH "/proc/cmdline" +#define FS_HVB_PARTITION_PREFIX "/dev/block/by-name/" +#define HVB_CMDLINE_EXT_CERT_DIGEST "ohos.boot.hvb.ext_rvt" + +#define HASH_ALGO_SHA256 0 +#define HASH_ALGO_SHA256_STR "sha256" +#define HASH_ALGO_SHA512 2 +#define HASH_ALGO_SHA512_STR "sha512" +#define HASH_ALGO_SM3 3 +#define HASH_ALGO_SM3_STR "sm3" + +#define FS_HVB_RETURN_ERR_IF_NULL(__ptr) \ + do { \ + if ((__ptr) == NULL) { \ + BEGET_LOGE("error, %s is NULL\n", #__ptr); \ + return -1; \ + } \ + } while (0) + +static struct hvb_verified_data *g_vd = NULL; +static struct hvb_verified_data *g_extVd = NULL; + +static enum hvb_errno GetCurrVerifiedData(InitHvbType hvbType, struct hvb_verified_data ***currVd) +{ + if (currVd == NULL) { + BEGET_LOGE("error, invalid input"); + return HVB_ERROR_INVALID_ARGUMENT; + } + if (hvbType == MAIN_HVB) { + *currVd = &g_vd; + } else if (hvbType == EXT_HVB) { + *currVd = &g_extVd; + } else { + BEGET_LOGE("error, invalid hvb type"); + return HVB_ERROR_INVALID_ARGUMENT; + } + + return HVB_OK; +} + +static char FsHvbBinToHexChar(char octet) +{ + return octet < 10 ? '0' + octet : 'a' + (octet - 10); +} + +static char FsHvbHexCharToBin(char hex) +{ + return '0' <= hex && hex <= '9' ? hex - '0' : 10 + (hex - 'a'); +} + +static int FsHvbGetHashStr(char *str, size_t size, InitHvbType hvbType) +{ + if (hvbType == MAIN_HVB) { + return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_HASH_ALG); + } + + if (hvbType == EXT_HVB) { + if (memcpy_s(str, size, HASH_ALGO_SHA256_STR, strlen(HASH_ALGO_SHA256_STR)) != 0) { + BEGET_LOGE("fail to copy hvb hash str"); + return -1; + } + return 0; + } + + BEGET_LOGE("error, invalid hvbType"); + return -1; +} + +static int FsHvbGetCertDigstStr(char *str, size_t size, InitHvbType hvbType) +{ + if (hvbType == MAIN_HVB) { + return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_CERT_DIGEST); + } + + if (hvbType == EXT_HVB) { + return FsHvbGetValueFromCmdLine(str, size, HVB_CMDLINE_EXT_CERT_DIGEST); + } + + BEGET_LOGE("error, invalid hvbType"); + return -1; +} + +static int FsHvbComputeSha256(char *digest, uint32_t size, struct hvb_cert_data *certs, uint64_t num_certs) +{ + int ret; + uint64_t n; + struct hash_ctx_t ctx = {0}; + + if (size < FS_HVB_DIGEST_SHA256_BYTES) { + BEGET_LOGE("error, size=%zu", size); + return -1; + } + + ret = hash_ctx_init(&ctx, HASH_ALG_SHA256); + if (ret != HASH_OK) { + BEGET_LOGE("error 0x%x, sha256 init", ret); + return -1; + } + + for (n = 0; n < num_certs; n++) { + ret = hash_calc_update(&ctx, certs[n].data.addr, certs[n].data.size); + if (ret != HASH_OK) { + BEGET_LOGE("error 0x%x, sha256 update", ret); + return -1; + } + } + + ret = hash_calc_do_final(&ctx, NULL, 0, (uint8_t *)digest, size); + if (ret != HASH_OK) { + BEGET_LOGE("error 0x%x, sha256 final", ret); + return -1; + } + + return 0; +} + +static int FsHvbComputeSM3Hash(char *digest, uint32_t *size, struct hvb_cert_data *certs, uint64_t num_certs) +{ + BEGET_CHECK(digest != NULL && certs != NULL && size != NULL, return -1); + int ret; + uint64_t n; + struct sm3_ctx_t ctx = {0}; + + if (*size < FS_HVB_DIGEST_SM3_BYTES) { + BEGET_LOGE("error, size=%zu", *size); + return -1; + } + + ret = hvb_sm3_init(&ctx); + if (ret != SM3_OK) { + BEGET_LOGE("error 0x%x, sm3 init", ret); + return -1; + } + + for (n = 0; n < num_certs; n++) { + ret = hvb_sm3_update(&ctx, certs[n].data.addr, certs[n].data.size); + if (ret != SM3_OK) { + BEGET_LOGE("error 0x%x, sm3 update", ret); + return -1; + } + } + + ret = hvb_sm3_final(&ctx, (uint8_t *)digest, size); + if (ret != SM3_OK) { + BEGET_LOGE("error 0x%x, sha256 final", ret); + return -1; + } + + return 0; +} + +static int FsHvbHexStrToBin(char *bin, size_t bin_size, char *str, size_t str_size) +{ + size_t i; + + if ((str_size & 0x1) != 0 || bin_size < (str_size >> 1)) { + BEGET_LOGE("error, bin_size %zu str_size %zu", bin_size, str_size); + return -1; + } + + for (i = 0; i < (str_size >> 1); i++) { + bin[i] = (FsHvbHexCharToBin(str[2 * i]) << 4) | FsHvbHexCharToBin(str[2 * i + 1]); + } + + return 0; +} + +static int FsHvbCheckCertChainDigest(struct hvb_cert_data *certs, uint64_t num_certs, InitHvbType hvbType) +{ + int ret; + size_t digest_len = 0; + char hashAlg[FS_HVB_HASH_ALG_STR_MAX] = {0}; + char certDigest[FS_HVB_DIGEST_MAX_BYTES] = {0}; + char computeDigest[FS_HVB_DIGEST_MAX_BYTES] = {0}; + char certDigestStr[FS_HVB_DIGEST_STR_MAX_BYTES + 1] = {0}; + uint32_t computeDigestLen = FS_HVB_DIGEST_MAX_BYTES; + + ret = FsHvbGetHashStr(&hashAlg[0], sizeof(hashAlg), hvbType); + if (ret != 0) { + BEGET_LOGE("error 0x%x, get hash val from cmdline", ret); + return ret; + } + + ret = FsHvbGetCertDigstStr(&certDigestStr[0], sizeof(certDigestStr), hvbType); + if (ret != 0) { + BEGET_LOGE("error 0x%x, get digest val from cmdline", ret); + return ret; + } + + ret = FsHvbHexStrToBin(&certDigest[0], sizeof(certDigest), &certDigestStr[0], strlen(certDigestStr)); + if (ret != 0) { + return ret; + } + + if (strcmp(&hashAlg[0], "sha256") == 0) { + digest_len = FS_HVB_DIGEST_SHA256_BYTES; + ret = FsHvbComputeSha256(computeDigest, computeDigestLen, certs, num_certs); + } else if (strcmp(&hashAlg[0], "sm3") == 0) { + digest_len = FS_HVB_DIGEST_SM3_BYTES; + ret = FsHvbComputeSM3Hash(computeDigest, &computeDigestLen, certs, num_certs); + } else { + BEGET_LOGE("error, not support alg %s", &hashAlg[0]); + return -1; + } + + if (ret != 0) { + BEGET_LOGE("error 0x%x, compute hash", ret); + return -1; + } + + ret = memcmp(&certDigest[0], &computeDigest[0], digest_len); + if (ret != 0) { + BEGET_LOGE("error, cert digest not match with cmdline"); + return -1; + } + + return 0; +} + +int FsHvbInit(InitHvbType hvbType) +{ + enum hvb_errno rc; + struct hvb_verified_data **currVd = NULL; + char *rootPartitionName = NULL; + rc = GetCurrVerifiedData(hvbType, &currVd); + if (rc != HVB_OK) { + BEGET_LOGE("error 0x%x, GetCurrVerifiedData", rc); + return rc; + } + + // return ok if the hvb is already initialized + if (*currVd != NULL) { + BEGET_LOGI("Hvb has already been inited"); + return 0; + } + + if (hvbType == MAIN_HVB) { + rootPartitionName = FS_HVB_RVT_PARTITION_NAME; + } else { + rootPartitionName = FS_HVB_EXT_RVT_PARTITION_NAME; + } + + rc = hvb_chain_verify(FsHvbGetOps(), rootPartitionName, NULL, currVd); + if (*currVd == NULL) { + BEGET_LOGE("error 0x%x, hvb chain verify, vd is NULL", rc); + return rc; + } + + if (rc != HVB_OK) { + BEGET_LOGE("error 0x%x, hvb chain verify", rc); + hvb_chain_verify_data_free(*currVd); + *currVd = NULL; + return rc; + } + + rc = FsHvbCheckCertChainDigest((*currVd)->certs, (*currVd)->num_loaded_certs, hvbType); + if (rc != 0) { + BEGET_LOGE("error 0x%x, cert chain hash", rc); + hvb_chain_verify_data_free(*currVd); + *currVd = NULL; + return rc; + } + + BEGET_LOGI("hvb type %d verify succ in init", hvbType); + + return 0; +} + +static int FsHvbGetCert(struct hvb_cert *cert, const char *devName, struct hvb_verified_data *vd) +{ + enum hvb_errno hr; + size_t devNameLen = strlen(devName); + struct hvb_cert_data *p = vd->certs; + struct hvb_cert_data *end = p + vd->num_loaded_certs; + + for (; p < end; p++) { + if (devNameLen != strlen(p->partition_name)) { + continue; + } + + if (memcmp(p->partition_name, devName, devNameLen) == 0) { + break; + } + } + + if (p == end) { + BEGET_LOGE("error, can't found %s partition", devName); + return -1; + } + + hr = hvb_cert_parser(cert, &p->data); + if (hr != HVB_OK) { + BEGET_LOGE("error 0x%x, parser hvb cert", hr); + return -1; + } + + return 0; +} + +static int FsHvbVerityTargetAppendString(char **p, char *end, char *str, size_t len) +{ + errno_t err; + + // check range for append string + if (*p + len >= end || *p + len < *p) { + BEGET_LOGE("error, append string overflow"); + return -1; + } + // append string + err = memcpy_s(*p, end - *p, str, len); + if (err != EOK) { + BEGET_LOGE("error 0x%x, cp string fail", err); + return -1; + } + *p += len; + + // check range for append blank space + if (*p + 1 >= end || *p + 1 < *p) { + BEGET_LOGE("error, append blank space overflow"); + return -1; + } + // append blank space + **p = FS_HVB_BLANK_SPACE_ASCII; + *p += 1; + + BEGET_LOGI("append string %s", str); + + return 0; +} + +static int FsHvbVerityTargetAppendOctets(char **p, char *end, char *octs, size_t octs_len) +{ + size_t i; + int rc; + char *str = NULL; + size_t str_len = octs_len * 2; + + str = calloc(1, str_len + 1); + if (str == NULL) { + BEGET_LOGE("error, calloc str fail"); + return -1; + } + + for (i = 0; i < octs_len; i++) { + str[2 * i] = FsHvbBinToHexChar((octs[i] >> 4) & 0xf); + str[2 * i + 1] = FsHvbBinToHexChar(octs[i] & 0xf); + } + + rc = FsHvbVerityTargetAppendString(p, end, str, str_len); + if (rc != 0) { + BEGET_LOGE("error 0x%x, append str fail", rc); + } + free(str); + + return rc; +} + +static int FsHvbVerityTargetAppendNum(char **p, char *end, uint64_t num) +{ + int rc; + char num_str[FS_HVB_UINT64_MAX_LENGTH] = {0}; + + rc = sprintf_s(&num_str[0], sizeof(num_str), "%llu", num); + if (rc < 0) { + BEGET_LOGE("error 0x%x, calloc num_str", rc); + return rc; + } + + rc = FsHvbVerityTargetAppendString(p, end, num_str, strlen(&num_str[0])); + if (rc != 0) { + BEGET_LOGE("error 0x%x, append num_str fail", rc); + } + + return rc; +} + +#define RETURN_ERR_IF_APPEND_STRING_ERR(p, end, str, str_len) \ + do { \ + int __ret = FsHvbVerityTargetAppendString(p, end, str, str_len); \ + if (__ret != 0) \ + return __ret; \ + } while (0) + +#define RETURN_ERR_IF_APPEND_OCTETS_ERR(p, end, octs, octs_len) \ + do { \ + int __ret = FsHvbVerityTargetAppendOctets(p, end, octs, octs_len); \ + if (__ret != 0) \ + return __ret; \ + } while (0) + +#define RETURN_ERR_IF_APPEND_DIGIT_ERR(p, end, num) \ + do { \ + int __ret = FsHvbVerityTargetAppendNum(p, end, num); \ + if (__ret != 0) \ + return __ret; \ + } while (0) + +static char *FsHvbGetHashAlgStr(unsigned int hash_algo) +{ + char *alg = NULL; + + switch (hash_algo) { + case HASH_ALGO_SHA256: + alg = HASH_ALGO_SHA256_STR; + break; + + case HASH_ALGO_SHA512: + alg = HASH_ALGO_SHA512_STR; + break; + + case HASH_ALGO_SM3: + alg = HASH_ALGO_SM3_STR; + break; + + default: + alg = NULL; + break; + } + + return alg; +} + +/* + * add optional fec data if supported, format as below; + * + */ +static int FsHvbVerityTargetAddFecArgs(struct hvb_cert *cert, char *devPath, char **str, char *end) +{ + FS_HVB_RETURN_ERR_IF_NULL(cert); + FS_HVB_RETURN_ERR_IF_NULL(devPath); + FS_HVB_RETURN_ERR_IF_NULL(str); + FS_HVB_RETURN_ERR_IF_NULL(end); + + // append + RETURN_ERR_IF_APPEND_STRING_ERR(str, end, USE_FEC_FROM_DEVICE, strlen(USE_FEC_FROM_DEVICE)); + RETURN_ERR_IF_APPEND_STRING_ERR(str, end, &devPath[0], strlen(devPath)); + + // append + RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_ROOTS, strlen(FEC_ROOTS)); + RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_num_roots); + + if (cert->data_block_size == 0 || cert->hash_block_size == 0) { + BEGET_LOGE("error, block size is zero"); + return -1; + } + // append + RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_BLOCKS, strlen(FEC_BLOCKS)); + RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_offset / cert->hash_block_size); + + // append + RETURN_ERR_IF_APPEND_STRING_ERR(str, end, FEC_START, strlen(FEC_START)); + RETURN_ERR_IF_APPEND_DIGIT_ERR(str, end, cert->fec_offset / cert->data_block_size); + + return 0; +} + +/* + * target->paras is verity table target, format as below; + * + * + * [<#opt_params>] + * exp: 1 /dev/sda1 /dev/sda1 4096 4096 262144 262144 sha256 \ + xxxxx + xxxxx + */ + +int FsHvbConstructVerityTarget(DmVerityTarget *target, const char *devName, struct hvb_cert *cert) +{ + char *p = NULL; + char *end = NULL; + char *hashALgo = NULL; + char devPath[FS_HVB_DEVPATH_MAX_LEN] = {0}; + + FS_HVB_RETURN_ERR_IF_NULL(target); + FS_HVB_RETURN_ERR_IF_NULL(devName); + FS_HVB_RETURN_ERR_IF_NULL(cert); + + target->start = 0; + target->length = cert->image_len / FS_HVB_SECTOR_BYTES; + target->paras = calloc(1, FS_HVB_VERITY_TARGET_MAX); // simple it, just calloc a big mem + if (target->paras == NULL) { + BEGET_LOGE("error, alloc target paras"); + return -1; + } + + if (snprintf_s(&devPath[0], sizeof(devPath), sizeof(devPath) - 1, "%s%s", + ((strchr(devName, '/') == NULL) ? FS_HVB_PARTITION_PREFIX : ""), devName) == -1) { + BEGET_LOGE("error, snprintf_s devPath"); + return -1; + } + + p = target->paras; + end = p + FS_HVB_VERITY_TARGET_MAX; + + // append + RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, 1); + // append + RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, &devPath[0], strlen(devPath)); + // append + RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, &devPath[0], strlen(devPath)); + + if (cert->data_block_size == 0 || cert->hash_block_size == 0) { + BEGET_LOGE("error, block size is zero"); + return -1; + } + // append + RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->data_block_size); + // append + RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->hash_block_size); + // append + RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->image_len / cert->data_block_size); + // append + RETURN_ERR_IF_APPEND_DIGIT_ERR(&p, end, cert->hashtree_offset / cert->hash_block_size); + + // append + hashALgo = FsHvbGetHashAlgStr(cert->hash_algo); + if (hashALgo == NULL) { + BEGET_LOGE("error, hash alg %d is invalid", cert->hash_algo); + return -1; + } + RETURN_ERR_IF_APPEND_STRING_ERR(&p, end, hashALgo, strlen(hashALgo)); + + // append + RETURN_ERR_IF_APPEND_OCTETS_ERR(&p, end, (char *)cert->hash_payload.digest, cert->digest_size); + + // append + RETURN_ERR_IF_APPEND_OCTETS_ERR(&p, end, (char *)cert->hash_payload.salt, cert->salt_size); + + if (cert->fec_size > 0) { + if (FsHvbVerityTargetAddFecArgs(cert, devPath, &p, end) != 0) { + return -1; + } + } + + // remove last blank + *(p - 1) = '\0'; + + target->paras_len = strlen(target->paras); + + return 0; +} + +static int FsHvbCreateVerityTarget(DmVerityTarget *target, char *devName, struct hvb_verified_data *vd) +{ + int rc; + struct hvb_cert cert = {0}; + + rc = FsHvbGetCert(&cert, devName, vd); + if (rc != 0) { + return rc; + } + + rc = FsHvbConstructVerityTarget(target, devName, &cert); + if (rc != 0) { + BEGET_LOGE("error 0x%x, can't construct verity target", rc); + return rc; + } + + return rc; +} + +static int FsExtHvbCreateVerityTarget(DmVerityTarget *target, const char *devName, + const char *partition, struct hvb_verified_data *vd) +{ + int rc; + struct hvb_cert cert = {0}; + + rc = FsHvbGetCert(&cert, partition, vd); + if (rc != 0) { + return rc; + } + + rc = FsHvbConstructVerityTarget(target, devName, &cert); + if (rc != 0) { + BEGET_LOGE("error 0x%x, can't construct verity target", rc); + return rc; + } + + return rc; +} + +void FsHvbDestoryVerityTarget(DmVerityTarget *target) +{ + if (target != NULL && target->paras != NULL) { + free(target->paras); + target->paras = NULL; + } +} + +int FsHvbSetupHashtree(FstabItem *fsItem) +{ + int rc; + DmVerityTarget target = {0}; + char *dmDevPath = NULL; + char *devName = NULL; + + FS_HVB_RETURN_ERR_IF_NULL(fsItem); + FS_HVB_RETURN_ERR_IF_NULL(g_vd); + + // fsItem->deviceName is like /dev/block/platform/xxx/by-name/system + // we just basename system + devName = basename(fsItem->deviceName); + if (devName == NULL) { + BEGET_LOGE("error, get basename"); + return -1; + } + + rc = FsHvbCreateVerityTarget(&target, devName, g_vd); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create verity-table", rc); + goto exit; + } + + rc = FsDmCreateDevice(&dmDevPath, devName, &target); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create dm-verity", rc); + goto exit; + } + + rc = FsDmInitDmDev(dmDevPath, true); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create init dm dev", rc); + goto exit; + } + + free(fsItem->deviceName); + fsItem->deviceName = dmDevPath; + +exit: + FsHvbDestoryVerityTarget(&target); + + return rc; +} + +static int FsExtHvbSetupHashtree(const char *devName, const char *partition, char **outPath) +{ + int rc; + DmVerityTarget target = {0}; + char *tmpDevName = NULL; + char *dmDevPath = NULL; + size_t devLen; + + FS_HVB_RETURN_ERR_IF_NULL(g_extVd); + + devLen = strnlen(devName, FS_HVB_MAX_PATH_LEN); + if (devLen >= FS_HVB_MAX_PATH_LEN) { + BEGET_LOGE("error, invalid devName"); + return -1; + } + tmpDevName = malloc(devLen + 1); + if (tmpDevName == NULL) { + BEGET_LOGE("error, fail to malloc"); + return -1; + } + + (void)memset_s(tmpDevName, devLen + 1, 0, devLen + 1); + if (memcpy_s(tmpDevName, devLen + 1, devName, devLen) != 0) { + free(tmpDevName); + BEGET_LOGE("error, fail to copy"); + return -1; + } + + rc = FsExtHvbCreateVerityTarget(&target, tmpDevName, partition, g_extVd); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create verity-table", rc); + goto exit; + } + + rc = FsDmCreateDevice(&dmDevPath, basename(tmpDevName), &target); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create dm-verity", rc); + goto exit; + } + + rc = FsDmInitDmDev(dmDevPath, true); + if (rc != 0) { + BEGET_LOGE("error 0x%x, create init dm dev", rc); + goto exit; + } + + *outPath = dmDevPath; + +exit: + FsHvbDestoryVerityTarget(&target); + free(tmpDevName); + return rc; +} + +int FsHvbFinal(InitHvbType hvbType) +{ + struct hvb_verified_data **currVd = NULL; + + if (GetCurrVerifiedData(hvbType, &currVd) != HVB_OK) { + BEGET_LOGE("error GetCurrVerifiedData"); + return -1; + } + if (*currVd != NULL) { + hvb_chain_verify_data_free(*currVd); + *currVd = NULL; + } + + return 0; +} + +int FsHvbGetValueFromCmdLine(char *val, size_t size, const char *key) +{ + FS_HVB_RETURN_ERR_IF_NULL(val); + FS_HVB_RETURN_ERR_IF_NULL(key); + + return GetExactParameterFromCmdLine(key, val, size, EMPTY_VALUE); +} + +int VerifyExtHvbImage(const char *devPath, const char *partition, char **outPath) +{ + int rc; + FS_HVB_RETURN_ERR_IF_NULL(devPath); + FS_HVB_RETURN_ERR_IF_NULL(partition); + FS_HVB_RETURN_ERR_IF_NULL(outPath); + + rc = FsHvbInit(EXT_HVB); + if (rc != 0) { + BEGET_LOGE("ext hvb error, ret=%d", rc); + goto exit; + } + + rc = FsExtHvbSetupHashtree(devPath, partition, outPath); + if (rc != 0) { + BEGET_LOGE("error, setup hashtree fail, ret=%d", rc); + } + +exit: + if (FsHvbFinal(EXT_HVB) != 0) { + BEGET_LOGE("final ext hvb error, ret=%d", rc); + return -1; + } + return rc; +} + +bool CheckAndGetExt4Size(const char *headerBuf, uint64_t *imageSize, const char* image) +{ + ext4_super_block *superBlock = (ext4_super_block *)headerBuf; + + if (headerBuf == NULL || imageSize == NULL || image == NULL) { + BEGET_LOGE("param is error"); + return false; + } + + if (superBlock->s_magic == EXT4_SUPER_MAGIC) { + *imageSize = (uint64_t)superBlock->s_blocks_count_lo * BLOCK_SIZE_UNIT; + BEGET_LOGI("%s is ext4:[block cout]: %d, [size]: 0x%lx", image, + superBlock->s_blocks_count_lo, *imageSize); + return true; + } + return false; +} + +bool CheckAndGetErofsSize(const char *headerBuf, uint64_t *imageSize, const char* image) +{ + struct erofs_super_block *superBlock = (struct erofs_super_block *)headerBuf; + + if (headerBuf == NULL || imageSize == NULL || image == NULL) { + BEGET_LOGE("param is error"); + return false; + } + + if (superBlock->magic == EROFS_SUPER_MAGIC) { + *imageSize = (uint64_t)superBlock->blocks * BLOCK_SIZE_UINT; + BEGET_LOGI("%s is erofs:[block cout]: %d, [size]: 0x%lx", image, + superBlock->blocks, *imageSize); + return true; + } + return false; +} + +bool CheckAndGetExtheaderSize(const int fd, uint64_t offset, + uint64_t *imageSize, const char* image) +{ + ExtheaderV1 header; + ssize_t nbytes; + if (fd < 0 || imageSize == NULL || image == NULL) { + BEGET_LOGE("param is error"); + return false; + } + + if (lseek(fd, offset, SEEK_SET) < 0) { + BEGET_LOGE("lseek %s failed for offset 0x%lx", image, offset); + return false; + } + + nbytes = read(fd, &header, sizeof(header)); + if (nbytes != sizeof(header)) { + BEGET_LOGE("read %s failed.", image); + return false; + } + + if (header.magicNumber != EXTHDR_MAGIC) { + BEGET_LOGW("%s extheader doesnt match, magic is 0x%lx", image, header.magicNumber); + return false; + } + + *imageSize = header.partSize; + return true; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c b/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c new file mode 100755 index 0000000000000000000000000000000000000000..9fe9a838de88758f2555e59510cd9b1b90078a7f --- /dev/null +++ b/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2022-2023 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 "beget_ext.h" +#include "fs_dm.h" +#include "fs_hvb.h" +#include "securec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define PARTITION_PATH_PREFIX "/dev/block/by-name/" +#define MAX_EXT_HVB_PARTITION_NUM 1 + +static const ExtHvbVerifiedDev g_extVerifiedDev[] = { + { + .partitionName = "module_update", + .pathName = "/data/module_update/active/ModuleTrain/module.img" + }, +}; + +static int64_t GetImageSizeForHVB(const int fd, const char* image) +{ + char headerBuf[SZ_2KB] = {0}; + ssize_t nbytes; + uint64_t fileSysSize; + uint64_t realFileSize; + + if (fd < 0) { + BEGET_LOGE("param is error"); + return -1; + } + + lseek64(fd, 0, SEEK_SET); + nbytes = read(fd, &headerBuf, sizeof(headerBuf)); + if (nbytes != sizeof(headerBuf)) { + BEGET_LOGE("read file system header fail"); + return -1; + } + + if (CheckAndGetErofsSize(&headerBuf[SZ_1KB], &fileSysSize, image) && + CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) { + BEGET_LOGI("get %s size from erofs and extheader, size=0x%lx", image, realFileSize); + return realFileSize; + } else if (CheckAndGetExt4Size(&headerBuf[SZ_1KB], &fileSysSize, image) && + CheckAndGetExtheaderSize(fd, fileSysSize, &realFileSize, image)) { + BEGET_LOGI("get %s size from ext4 and extheader, size=0x%lx", image, realFileSize); + return realFileSize; + } else { + BEGET_LOGI("read %s file extheader fail, use the actual img size", image); + } + + return lseek64(fd, 0, SEEK_END); +} + +static bool IsExtHvbVerifiedPtn(const char *ptn, size_t ptnLen, size_t *outIndex) +{ + int index; + if (ptn == NULL || outIndex == NULL) { + BEGET_LOGE("error, invalid ptn"); + return false; + } + + for (index = 0; index < MAX_EXT_HVB_PARTITION_NUM; index++) { + if (strncmp(g_extVerifiedDev[index].partitionName, ptn, ptnLen) == 0) { + *outIndex = index; + return true; + } + } + + return false; +} + +static char *GetExtHvbVerifiedPath(size_t index) +{ + char *tmpPath = NULL; + + if (index >= MAX_EXT_HVB_PARTITION_NUM) { + BEGET_LOGE("error, invalid index"); + return NULL; + } + + size_t pathLen = strnlen(g_extVerifiedDev[index].pathName, FS_HVB_MAX_PATH_LEN); + if (pathLen >= FS_HVB_MAX_PATH_LEN) { + BEGET_LOGE("error, invalid path"); + return tmpPath; + } + tmpPath = malloc(pathLen + 1); + if (tmpPath == NULL) { + BEGET_LOGE("error, fail to malloc"); + return NULL; + } + + (void)memset_s(tmpPath, pathLen + 1, 0, pathLen + 1); + if (memcpy_s(tmpPath, pathLen + 1, g_extVerifiedDev[index].pathName, pathLen) != 0) { + free(tmpPath); + BEGET_LOGE("error, fail to copy"); + return NULL; + } + return tmpPath; +} + +static char *HvbGetPartitionPath(const char *partition) +{ + int rc; + size_t pathLen; + char *path = NULL; + size_t index; + size_t ptnLen = strnlen(partition, HVB_MAX_PARTITION_NAME_LEN); + if (ptnLen >= HVB_MAX_PARTITION_NAME_LEN) { + BEGET_LOGE("error, invalid ptn name"); + return NULL; + } + if (IsExtHvbVerifiedPtn(partition, ptnLen, &index)) { + return GetExtHvbVerifiedPath(index); + } + + pathLen = strlen(PARTITION_PATH_PREFIX) + ptnLen; + path = calloc(1, pathLen + 1); + if (path == NULL) { + BEGET_LOGE("error, calloc fail"); + return NULL; + } + rc = snprintf_s(path, pathLen + 1, pathLen, "%s%s", PARTITION_PATH_PREFIX, + partition); + if (rc < 0) { + BEGET_LOGE("error, snprintf_s fail, ret = %d", rc); + free(path); + return NULL; + } + return path; +} + +static enum hvb_io_errno HvbReadFromPartition(struct hvb_ops* ops, + const char* partition, + int64_t offset, uint64_t numBytes, + void* buf, uint64_t* outNumRead) +{ + int fd = -1; + char *path = NULL; + enum hvb_io_errno ret = HVB_IO_ERROR_IO; + + if (ops == NULL || partition == NULL || + buf == NULL || outNumRead == NULL) { + BEGET_LOGE("error, invalid parameter"); + return HVB_IO_ERROR_IO; + } + + /* get and malloc img path */ + path = HvbGetPartitionPath(partition); + if (path == NULL) { + BEGET_LOGE("error, get partition path"); + ret = HVB_IO_ERROR_OOM; + goto exit; + } + + fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + BEGET_LOGE("error, Failed to open %s, errno = %d", path, errno); + ret = HVB_IO_ERROR_IO; + goto exit; + } + + if (offset < 0) { + int64_t total_size = GetImageSizeForHVB(fd, partition); + if (total_size == -1) { + BEGET_LOGE("Failed to get the size of the partition %s", partition); + ret = HVB_IO_ERROR_IO; + goto exit; + } + offset = total_size + offset; + } + + lseek64(fd, offset, SEEK_SET); + + ssize_t numRead = read(fd, buf, numBytes); + if (numRead < 0 || (size_t)numRead != numBytes) { + BEGET_LOGE("Failed to read %lld bytes from %s offset %lld", numBytes, + path, offset); + ret = HVB_IO_ERROR_IO; + goto exit; + } + + *outNumRead = numRead; + + ret = HVB_IO_OK; + +exit: + + if (path != NULL) { + free(path); + } + + if (fd >= 0) { + close(fd); + } + return ret; +} + +static enum hvb_io_errno HvbWriteToPartition(struct hvb_ops* ops, + const char* partition, + int64_t offset, uint64_t numBytes, + const void* buf) +{ + return HVB_IO_OK; +} + +static enum hvb_io_errno HvbInvaldateKey(struct hvb_ops* ops, + const uint8_t* publicKeyData, + uint64_t publicKeyLength, + const uint8_t* publicKeyMetadata, + uint64_t publicKeyMetadataLength, + bool* outIsTrusted) +{ + if (outIsTrusted == NULL) { + return HVB_IO_ERROR_IO; + } + + *outIsTrusted = true; + + return HVB_IO_OK; +} + +static enum hvb_io_errno HvbReadRollbackIdx(struct hvb_ops* ops, + uint64_t rollBackIndexLocation, + uint64_t* outRollbackIndex) +{ + if (outRollbackIndex == NULL) { + return HVB_IO_ERROR_IO; + } + + // return 0 as we only need to set up HVB HASHTREE partitions + *outRollbackIndex = 0; + + return HVB_IO_OK; +} + +static enum hvb_io_errno HvbWriteRollbackIdx(struct hvb_ops* ops, + uint64_t rollBackIndexLocation, + uint64_t rollbackIndex) +{ + return HVB_IO_OK; +} + +static enum hvb_io_errno HvbReadLockState(struct hvb_ops* ops, + bool* lock_state) +{ + return HVB_IO_OK; +} + +static enum hvb_io_errno HvbGetSizeOfPartition(struct hvb_ops* ops, + const char* partition, + uint64_t* size) +{ + if (size == NULL) { + return HVB_IO_ERROR_IO; + } + + // The function is for bootloader to load entire content of HVB HASH + // partitions. In user-space, return 0 as we only need to set up HVB + // HASHTREE partitions. + *size = 0; + return HVB_IO_OK; +} + +static struct hvb_ops g_hvb_ops = { + .user_data = &g_hvb_ops, + .read_partition = HvbReadFromPartition, + .write_partition = HvbWriteToPartition, + .valid_rvt_key = HvbInvaldateKey, + .read_rollback = HvbReadRollbackIdx, + .write_rollback = HvbWriteRollbackIdx, + .read_lock_state = HvbReadLockState, + .get_partiton_size = HvbGetSizeOfPartition, +}; + +struct hvb_ops* FsHvbGetOps(void) +{ + return &g_hvb_ops; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/interfaces/innerkits/fs_manager/libfs_hvb/include/fs_hvb.h b/interfaces/innerkits/fs_manager/libfs_hvb/include/fs_hvb.h new file mode 100755 index 0000000000000000000000000000000000000000..b5c76cd9fe5f2666faaa04adfd1941c2ba5227e8 --- /dev/null +++ b/interfaces/innerkits/fs_manager/libfs_hvb/include/fs_hvb.h @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2023 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 STARTUP_LIBFS_HVB_H +#define STARTUP_LIBFS_HVB_H + +#include +#include +#include +#include +#include +#include "fs_dm.h" +#include "fs_manager.h" +#include "ext4_super_block.h" +#include "erofs_super_block.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define USE_FEC_FROM_DEVICE "use_fec_from_device" +#define FEC_ROOTS "fec_roots" +#define FEC_BLOCKS "fec_blocks" +#define FEC_START "fec_start" +#define BLOCK_SIZE_UINT 4096 +#define EXTHDR_MAGIC 0xFEEDBEEF +#define EXTHDR_BLKSIZ 4096 +#define SZ_1KB (0x1 << 10) +#define SZ_1MB (0x1 << 20) +#define SZ_1GB (0x1 << 30) + +#define SZ_2KB (2 * SZ_1KB) +#define SZ_4KB (4 * SZ_1KB) +#define FS_HVB_MAX_PATH_LEN 128 + +typedef struct { + uint32_t magicNumber; + uint16_t exthdrSize; + uint16_t bcc16; + uint64_t partSize; +} ExtheaderV1; + +typedef enum InitHvbType { + MAIN_HVB = 0, + EXT_HVB +} InitHvbType; + +typedef struct { + char *partitionName; + char *pathName; +} ExtHvbVerifiedDev; + +int FsHvbInit(InitHvbType hvbType); +int FsHvbSetupHashtree(FstabItem *fsItem); +int FsHvbFinal(InitHvbType hvbType); +struct hvb_ops *FsHvbGetOps(void); +int FsHvbGetValueFromCmdLine(char *val, size_t size, const char *key); +int FsHvbConstructVerityTarget(DmVerityTarget *target, const char *devName, struct hvb_cert *cert); +void FsHvbDestoryVerityTarget(DmVerityTarget *target); +int VerifyExtHvbImage(const char *dev_path, const char *partition, char **out_path); + +bool CheckAndGetExt4Size(const char *headerBuf, uint64_t *imageSize, const char* image); +bool CheckAndGetErofsSize(const char *headerBuf, uint64_t *imageSize, const char* image); +bool CheckAndGetExtheaderSize(const int fd, uint64_t offset, uint64_t *imageSize, const char* image); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // STARTUP_LIBFS_HVB_H diff --git a/services/include/init_capability.h b/interfaces/innerkits/fs_manager/switch_root/include/switch_root.h similarity index 78% rename from services/include/init_capability.h rename to interfaces/innerkits/fs_manager/switch_root/include/switch_root.h index 842959e73e0cc043949640656e435d7aa01e8d26..d8e7b46f9229b7a76949f52fdab254e02ed9ac63 100644 --- a/services/include/init_capability.h +++ b/interfaces/innerkits/fs_manager/switch_root/include/switch_root.h @@ -13,13 +13,9 @@ * limitations under the License. */ -#ifndef INIT_CAPABILITY_H -#define INIT_CAPABILITY_H +#ifndef INIT_SWITCH_ROOT_H +#define INIT_SWITCH_ROOT_H -#include "cJSON.h" -#include "init_service.h" - -int GetServiceCaps(const cJSON* curArrItem, Service* curServ); - -#endif +int SwitchRoot(const char *newRoot); +#endif // INIT_SWITCH_ROOT_H \ No newline at end of file diff --git a/interfaces/innerkits/fs_manager/switch_root/switch_root.c b/interfaces/innerkits/fs_manager/switch_root/switch_root.c new file mode 100644 index 0000000000000000000000000000000000000000..0855ff785495dde668fb10e03fb77afd72b4c730 --- /dev/null +++ b/interfaces/innerkits/fs_manager/switch_root/switch_root.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2021 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 "switch_root.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "init_log.h" +#include "fs_manager/fs_manager.h" +#include "securec.h" +#include "init_utils.h" + +static void FreeOldRoot(DIR *dir, dev_t dev) +{ + if (dir == NULL) { + return; + } + int dfd = dirfd(dir); + bool isDir = false; + struct dirent *de = NULL; + while ((de = readdir(dir)) != NULL) { + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) { + continue; + } + isDir = false; + if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) { + struct stat st = {}; + if (fstatat(dfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + INIT_LOGE("Failed to get stat of %s", de->d_name); + continue; + } + + if (st.st_dev != dev) { + continue; // Not the same device, ignore. + } + if (!S_ISDIR(st.st_mode)) { + continue; + } + int fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); + isDir = true; + if (fd < 0) { + continue; + } + DIR *subDir = fdopendir(fd); + if (subDir != NULL) { + FreeOldRoot(subDir, dev); + closedir(subDir); + } else { + close(fd); + } + } + if (unlinkat(dfd, de->d_name, isDir ? AT_REMOVEDIR : 0) < 0) { + INIT_LOGE("Failed to unlink %s, err = %d", de->d_name, errno); + } + } +} + +// For sub mountpoint under /dev, /sys, /proc +// There is no need to move them individually +// We will find a better solution to take care of +// all sub mount tree in the future. +static bool UnderBasicMountPoint(const char *path) +{ + unsigned int i; + if (path == NULL || *path == '\0') { + return false; + } + const char *basicMountPoint[] = {"/dev/", "/sys/", "/proc/"}; + for (i = 0; i < ARRAY_LENGTH(basicMountPoint); i++) { + if (strncmp(path, basicMountPoint[i], strlen(basicMountPoint[i])) == 0) { + return true; + } + } + return false; +} + +static int MountToNewTarget(const char *target) +{ + if (target == NULL || *target == '\0') { + return -1; + } + Fstab *fstab = ReadFstabFromFile("/proc/mounts", true); + if (fstab == NULL) { + INIT_LOGE("Fatal error. Read mounts info from \" /proc/mounts \" failed"); + return -1; + } + + for (FstabItem *item = fstab->head; item != NULL; item = item->next) { + const char *mountPoint = item->mountPoint; + if (mountPoint == NULL || strcmp(mountPoint, "/") == 0 || + strcmp(mountPoint, target) == 0) { + continue; + } + char newMountPoint[PATH_MAX] = {0}; + if (snprintf_s(newMountPoint, PATH_MAX, PATH_MAX - 1, "%s%s", target, mountPoint) == -1) { + INIT_LOGW("Cannot build new mount point for old mount point \" %s \"", mountPoint); + // Just ignore this one or return error? + continue; + } + INIT_LOGV("new mount point is: %s", newMountPoint); + if (!UnderBasicMountPoint(mountPoint)) { + INIT_LOGV("Move mount %s to %s", mountPoint, newMountPoint); + if (mount(mountPoint, newMountPoint, NULL, MS_MOVE, NULL) < 0) { + INIT_LOGE("Failed to mount moving %s to %s, err = %d", mountPoint, newMountPoint, errno); + // If one mount entry cannot move to new mountpoint, umount it. + umount2(mountPoint, MNT_FORCE); + continue; + } + } + } + ReleaseFstab(fstab); + fstab = NULL; + return 0; +} + +static void FreeRootDir(DIR *oldRoot, dev_t dev) +{ + if (oldRoot != NULL) { + FreeOldRoot(oldRoot, dev); + closedir(oldRoot); + } +} + +// Switch root from ramdisk to system +int SwitchRoot(const char *newRoot) +{ + if (newRoot == NULL || *newRoot == '\0') { + errno = EINVAL; + INIT_LOGE("Fatal error. Try to switch to new root with invalid new mount point"); + return -1; + } + + struct stat oldRootStat = {}; + INIT_ERROR_CHECK(stat("/", &oldRootStat) == 0, return -1, "Failed to get old root \"/\" stat"); + DIR *oldRoot = opendir("/"); + INIT_ERROR_CHECK(oldRoot != NULL, return -1, "Failed to open root dir \"/\""); + struct stat newRootStat = {}; + if (stat(newRoot, &newRootStat) != 0) { + INIT_LOGE("Failed to get new root \" %s \" stat", newRoot); + FreeRootDir(oldRoot, oldRootStat.st_dev); + return -1; + } + + if (oldRootStat.st_dev == newRootStat.st_dev) { + INIT_LOGW("Try to switch root in same device, skip switching root"); + FreeRootDir(oldRoot, oldRootStat.st_dev); + return 0; + } + if (MountToNewTarget(newRoot) < 0) { + INIT_LOGE("Failed to move mount to new root \" %s \" stat", newRoot); + FreeRootDir(oldRoot, oldRootStat.st_dev); + return -1; + } + // OK, we've done move mount. + // Now mount new root. + if (chdir(newRoot) < 0) { + INIT_LOGE("Failed to change directory to %s, err = %d", newRoot, errno); + FreeRootDir(oldRoot, oldRootStat.st_dev); + return -1; + } + + if (mount(newRoot, "/", NULL, MS_MOVE, NULL) < 0) { + INIT_LOGE("Failed to mount moving %s to %s, err = %d", newRoot, "/", errno); + FreeRootDir(oldRoot, oldRootStat.st_dev); + return -1; + } + + if (chroot(".") < 0) { + INIT_LOGE("Failed to change root directory"); + FreeRootDir(oldRoot, oldRootStat.st_dev); + return -1; + } + FreeRootDir(oldRoot, oldRootStat.st_dev); + INIT_LOGI("SwitchRoot to %s finish", newRoot); + return 0; +} diff --git a/interfaces/innerkits/hookmgr/hookmgr.c b/interfaces/innerkits/hookmgr/hookmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..5776f4df0fa113250a587b7d3e9e31495da1a45c --- /dev/null +++ b/interfaces/innerkits/hookmgr/hookmgr.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2021 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 "list.h" +#include "beget_ext.h" +#include "hookmgr.h" + +// Forward declaration +typedef struct tagHOOK_STAGE HOOK_STAGE; + +/* + * Internal HOOK Item with priorities + */ +typedef struct tagHOOK_ITEM { + ListNode node; + HOOK_INFO info; + HOOK_STAGE *stage; +} HOOK_ITEM; + +/* + * Internal HOOK Stage in the same stage + */ +struct tagHOOK_STAGE { + ListNode node; + int stage; + ListNode hooks; +}; + +/* + * HookManager is consist of different hook stages + */ +struct tagHOOK_MGR { + const char *name; + ListNode stages; +}; + +/* + * Default HookManager is created automatically for HookMgrAddHook + */ +static HOOK_MGR *defaultHookMgr = NULL; + +static HOOK_MGR *getHookMgr(HOOK_MGR *hookMgr, int autoCreate) +{ + BEGET_CHECK(hookMgr == NULL, return hookMgr); + // Use default HOOK_MGR if possible + BEGET_CHECK(defaultHookMgr == NULL, return defaultHookMgr); + + BEGET_CHECK(autoCreate, return NULL); + + // Create default HOOK_MGR if not created + defaultHookMgr = HookMgrCreate("default"); + return defaultHookMgr; +} + +static int hookStageCompare(ListNode *node, void *data) +{ + const HOOK_STAGE *stage; + int compareStage = *((int *)data); + + stage = (const HOOK_STAGE *)node; + return (stage->stage - compareStage); +} + +static void hookStageDestroy(ListNode *node) +{ + HOOK_STAGE *stage; + + BEGET_CHECK(node != NULL, return); + + stage = (HOOK_STAGE *)node; + OH_ListRemoveAll(&(stage->hooks), NULL); + free((void *)stage); +} + +// Get HOOK_STAGE if found, otherwise create it +static HOOK_STAGE *getHookStage(HOOK_MGR *hookMgr, int stage, int createIfNotFound) +{ + HOOK_STAGE *stageItem; + + stageItem = (HOOK_STAGE *)OH_ListFind(&(hookMgr->stages), (void *)(&stage), hookStageCompare); + BEGET_CHECK(stageItem == NULL, return stageItem); + + BEGET_CHECK(createIfNotFound, return NULL); + + // Not found, create it + stageItem = (HOOK_STAGE *)malloc(sizeof(HOOK_STAGE)); + BEGET_CHECK(stageItem != NULL, return NULL); + stageItem->stage = stage; + OH_ListInit(&(stageItem->hooks)); + OH_ListAddTail(&(hookMgr->stages), (ListNode *)stageItem); + return stageItem; +} + +static int hookItemCompare(ListNode *node, ListNode *newNode) +{ + const HOOK_ITEM *hookItem; + const HOOK_ITEM *newItem; + + hookItem = (const HOOK_ITEM *)node; + newItem = (const HOOK_ITEM *)newNode; + return (hookItem->info.prio - newItem->info.prio); +} + +struct HOOKITEM_COMPARE_VAL { + int prio; + OhosHook hook; + void *hookCookie; +}; + +static int hookItemCompareValue(ListNode *node, void *data) +{ + const HOOK_ITEM *hookItem; + struct HOOKITEM_COMPARE_VAL *compareVal = (struct HOOKITEM_COMPARE_VAL *)data; + + hookItem = (const HOOK_ITEM *)node; + BEGET_CHECK(hookItem->info.prio == compareVal->prio, return (hookItem->info.prio - compareVal->prio)); + if (hookItem->info.hook == compareVal->hook && hookItem->info.hookCookie == compareVal->hookCookie) { + return 0; + } + return -1; +} + +// Add hook to stage list with prio ordered +static int addHookToStage(HOOK_STAGE *hookStage, int prio, OhosHook hook, void *hookCookie) +{ + HOOK_ITEM *hookItem; + struct HOOKITEM_COMPARE_VAL compareVal; + + // Check if exists + compareVal.prio = prio; + compareVal.hook = hook; + compareVal.hookCookie = hookCookie; + hookItem = (HOOK_ITEM *)OH_ListFind(&(hookStage->hooks), (void *)(&compareVal), hookItemCompareValue); + BEGET_CHECK(hookItem == NULL, return 0); + + // Create new item + hookItem = (HOOK_ITEM *)malloc(sizeof(HOOK_ITEM)); + BEGET_CHECK(hookItem != NULL, return -1); + hookItem->info.stage = hookStage->stage; + hookItem->info.prio = prio; + hookItem->info.hook = hook; + hookItem->info.hookCookie = hookCookie; + hookItem->stage = hookStage; + + // Insert with order + OH_ListAddWithOrder(&(hookStage->hooks), (ListNode *)hookItem, hookItemCompare); + return 0; +} + +int HookMgrAddEx(HOOK_MGR *hookMgr, const HOOK_INFO *hookInfo) +{ + HOOK_STAGE *stageItem; + BEGET_CHECK(hookInfo != NULL, return -1); + BEGET_CHECK(hookInfo->hook != NULL, return -1); + + // Get HOOK_MGR + hookMgr = getHookMgr(hookMgr, true); + BEGET_CHECK(hookMgr != NULL, return -1); + + // Get HOOK_STAGE list + stageItem = getHookStage(hookMgr, hookInfo->stage, true); + BEGET_CHECK(stageItem != NULL, return -1); + + // Add hook to stage + return addHookToStage(stageItem, hookInfo->prio, hookInfo->hook, hookInfo->hookCookie); +} + +int HookMgrAdd(HOOK_MGR *hookMgr, int stage, int prio, OhosHook hook) +{ + HOOK_INFO info; + info.stage = stage; + info.prio = prio; + info.hook = hook; + info.hookCookie = NULL; + return HookMgrAddEx(hookMgr, &info); +} + +static int hookTraversalDelProc(ListNode *node, void *cookie) +{ + HOOK_ITEM *hookItem = (HOOK_ITEM *)node; + + // Not equal, just return + BEGET_CHECK((void *)hookItem->info.hook == cookie, return 0); + + // Remove from the list + OH_ListRemove(node); + // Destroy myself + free((void *)node); + + return 0; +} + +/* + * 删除钩子函数 + * hook为NULL,表示删除该stage上的所有hooks + */ +void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook) +{ + HOOK_STAGE *stageItem; + + // Get HOOK_MGR + hookMgr = getHookMgr(hookMgr, 0); + BEGET_CHECK(hookMgr != NULL, return); + + // Get HOOK_STAGE list + stageItem = getHookStage(hookMgr, stage, false); + BEGET_CHECK(stageItem != NULL, return); + + if (hook != NULL) { + OH_ListTraversal(&(stageItem->hooks), hook, hookTraversalDelProc, 0); + return; + } + + // Remove from list + OH_ListRemove((ListNode *)stageItem); + + // Destroy stage item + hookStageDestroy((ListNode *)stageItem); +} + +typedef struct tagHOOK_EXECUTION_ARGS { + void *executionContext; + const HOOK_EXEC_OPTIONS *options; +} HOOK_EXECUTION_ARGS; + +static int hookExecutionProc(ListNode *node, void *cookie) +{ + int ret; + HOOK_ITEM *hookItem = (HOOK_ITEM *)node; + HOOK_EXECUTION_ARGS *args = (HOOK_EXECUTION_ARGS *)cookie; + + if ((args->options != NULL) && (args->options->preHook != NULL)) { + args->options->preHook(&hookItem->info, args->executionContext); + } + ret = hookItem->info.hook(&hookItem->info, args->executionContext); + if ((args->options != NULL) && (args->options->postHook != NULL)) { + args->options->postHook(&hookItem->info, args->executionContext, ret); + } + + return ret; +} + +/* + * 执行钩子函数 + */ +int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *options) +{ + unsigned int flags; + HOOK_STAGE *stageItem; + HOOK_EXECUTION_ARGS args; + + // Get HOOK_MGR + hookMgr = getHookMgr(hookMgr, 0); + BEGET_CHECK(hookMgr != NULL, return -1) + + // Get HOOK_STAGE list + stageItem = getHookStage(hookMgr, stage, false); + BEGET_CHECK(stageItem != NULL, return ERR_NO_HOOK_STAGE); + + flags = 0; + if (options != NULL) { + flags = (unsigned int)(options->flags); + } + + args.executionContext = executionContext; + args.options = options; + + // Traversal all hooks in the specified stage + return OH_ListTraversal(&(stageItem->hooks), (void *)(&args), hookExecutionProc, flags); +} + +HOOK_MGR *HookMgrCreate(const char *name) +{ + HOOK_MGR *ret; + + BEGET_CHECK(name != NULL, return NULL); + ret = (HOOK_MGR *)malloc(sizeof(HOOK_MGR)); + BEGET_CHECK(ret != NULL, return NULL); + + ret->name = strdup(name); + if (ret->name == NULL) { + free((void *)ret); + return NULL; + } + OH_ListInit(&(ret->stages)); + return ret; +} + +void HookMgrDestroy(HOOK_MGR *hookMgr) +{ + hookMgr = getHookMgr(hookMgr, 0); + BEGET_CHECK(hookMgr != NULL, return); + + OH_ListRemoveAll(&(hookMgr->stages), hookStageDestroy); + + if (hookMgr == defaultHookMgr) { + defaultHookMgr = NULL; + } + if (hookMgr->name != NULL) { + free((void *)hookMgr->name); + } + free((void *)hookMgr); +} + +typedef struct tagHOOK_TRAVERSAL_ARGS { + void *traversalCookie; + OhosHookTraversal traversal; +} HOOK_TRAVERSAL_ARGS; + +static int hookItemTraversal(ListNode *node, void *data) +{ + HOOK_ITEM *hookItem; + HOOK_TRAVERSAL_ARGS *stageArgs; + + hookItem = (HOOK_ITEM *)node; + stageArgs = (HOOK_TRAVERSAL_ARGS *)data; + + stageArgs->traversal(&(hookItem->info), stageArgs->traversalCookie); + return 0; +} + +static int hookStageTraversal(ListNode *node, void *data) +{ + HOOK_STAGE *stageItem = (HOOK_STAGE *)node; + OH_ListTraversal(&(stageItem->hooks), data, hookItemTraversal, 0); + return 0; +} + +/* + * 遍历所有的hooks + */ +void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal) +{ + HOOK_TRAVERSAL_ARGS stageArgs; + + BEGET_CHECK(traversal != NULL, return); + + hookMgr = getHookMgr(hookMgr, 0); + BEGET_CHECK(hookMgr != NULL, return); + + // Prepare common args + stageArgs.traversalCookie = traversalCookie; + stageArgs.traversal = traversal; + OH_ListTraversal(&(hookMgr->stages), (void *)(&stageArgs), hookStageTraversal, 0); +} + +/* + * 获取指定stage中hooks的个数 + */ +int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage) +{ + HOOK_STAGE *stageItem; + + hookMgr = getHookMgr(hookMgr, 0); + BEGET_CHECK(hookMgr != NULL, return 0); + + // Get HOOK_STAGE list + stageItem = getHookStage(hookMgr, stage, false); + BEGET_CHECK(stageItem != NULL, return 0); + + return OH_ListGetCnt(&(stageItem->hooks)); +} + +/* + * 获取指定stage中hooks的个数 + */ +int HookMgrGetStagesCnt(HOOK_MGR *hookMgr) +{ + hookMgr = getHookMgr(hookMgr, 0); + BEGET_CHECK(hookMgr != NULL, return 0); + + return OH_ListGetCnt(&(hookMgr->stages)); +} diff --git a/interfaces/innerkits/include/beget_ext.h b/interfaces/innerkits/include/beget_ext.h new file mode 100644 index 0000000000000000000000000000000000000000..e85a757055c4cf1238ca5ac17aa40ef4312cff55 --- /dev/null +++ b/interfaces/innerkits/include/beget_ext.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2021-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 BEGET_EXT_API_H +#define BEGET_EXT_API_H +#include +#include +#include +#ifdef __LITEOS_M__ +#include "hilog_lite/hiview_log.h" +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define INIT_DEBUG_LEVEL "persist.init.debug.loglevel" + +#ifndef INIT_LOG_PATH +#define INIT_LOG_PATH STARTUP_INIT_UT_PATH"/data/init_agent/" +#endif + +#if defined(__GNUC__) && (__GNUC__ >= 4) + #define INIT_PUBLIC_API __attribute__((visibility ("default"))) + #define INIT_INNER_API __attribute__((visibility ("default"))) + #define INIT_LOCAL_API __attribute__((visibility("hidden"))) +#else + #define INIT_PUBLIC_API + #define INIT_INNER_API + #define INIT_LOCAL_API +#endif + +typedef enum InitLogLevel { + INIT_DEBUG = 0, + INIT_INFO, + INIT_WARN, + INIT_ERROR, + INIT_FATAL +} InitLogLevel; + +typedef enum { + FSTAB_MOUNT_FAILED = 0, + SYS_PARAM_INIT_FAILED, + INIT_GOLBALY_KEY_FAILED, + CORE_PROCESS_FAILED +} StartupInitErrno; + +#if (defined(STARTUP_INIT_TEST) || defined(APPSPAWN_TEST)) +#define STARTUP_FILE_NAME (__FILE_NAME__) +#define STATIC +#else +#define STARTUP_FILE_NAME (strrchr((__FILE_NAME__), '/') ? strrchr((__FILE_NAME__), '/') + 1 : (__FILE_NAME__)) +#define STATIC static +#endif + +#ifndef STARTUP_INIT_UT_PATH +#ifdef STARTUP_INIT_TEST // ut +#define STARTUP_INIT_UT_PATH "/data/init_ut" +#else +#define STARTUP_INIT_UT_PATH "" +#endif +#endif + +INIT_PUBLIC_API void StartupLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...); +INIT_PUBLIC_API void SetInitLogLevel(InitLogLevel level); +INIT_PUBLIC_API InitLogLevel GetInitLogLevel(void); + +#if defined(INIT_NO_LOG) +#define STARTUP_LOGV(domain, tag, fmt, ...) +#define STARTUP_LOGI(domain, tag, fmt, ...) +#define STARTUP_LOGW(domain, tag, fmt, ...) +#define STARTUP_LOGE(domain, tag, fmt, ...) +#define STARTUP_LOGF(domain, tag, fmt, ...) +#else +#ifndef __LITEOS_M__ +#define STARTUP_LOGV(domain, tag, fmt, ...) \ + StartupLog(INIT_DEBUG, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define STARTUP_LOGI(domain, tag, fmt, ...) \ + StartupLog(INIT_INFO, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define STARTUP_LOGW(domain, tag, fmt, ...) \ + StartupLog(INIT_WARN, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define STARTUP_LOGE(domain, tag, fmt, ...) \ + StartupLog(INIT_ERROR, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define STARTUP_LOGF(domain, tag, fmt, ...) \ + StartupLog(INIT_FATAL, domain, tag, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#else +#define STARTUP_LOGV(domain, tag, fmt, ...) \ + HILOG_DEBUG(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define STARTUP_LOGI(domain, tag, fmt, ...) \ + HILOG_INFO(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define STARTUP_LOGW(domain, tag, fmt, ...) \ + HILOG_WARN(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define STARTUP_LOGE(domain, tag, fmt, ...) \ + HILOG_ERROR(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define STARTUP_LOGF(domain, tag, fmt, ...) \ + HILOG_FATAL(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#endif +#endif + +#define BASE_DOMAIN 0xD002C00 +#ifndef BEGET_DOMAIN +#define BEGET_DOMAIN (BASE_DOMAIN + 0xb) +#endif +#define BEGET_LABEL "BEGET" +#define BEGET_LOGI(fmt, ...) STARTUP_LOGI(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__) +#define BEGET_LOGE(fmt, ...) STARTUP_LOGE(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__) +#define BEGET_LOGV(fmt, ...) STARTUP_LOGV(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__) +#define BEGET_LOGW(fmt, ...) STARTUP_LOGW(BEGET_DOMAIN, BEGET_LABEL, fmt, ##__VA_ARGS__) + +#define InitLogPrint(outFileName, logLevel, kLevel, fmt, ...) \ + StartupLog(logLevel, BEGET_DOMAIN, kLevel, fmt, ##__VA_ARGS__) + +#define BEGET_ERROR_CHECK(ret, statement, format, ...) \ + if (!(ret)) { \ + BEGET_LOGE(format, ##__VA_ARGS__); \ + statement; \ + } \ + +#define BEGET_INFO_CHECK(ret, statement, format, ...) \ + if (!(ret)) { \ + BEGET_LOGI(format, ##__VA_ARGS__); \ + statement; \ + } \ + +#define BEGET_WARNING_CHECK(ret, statement, format, ...) \ + if (!(ret)) { \ + BEGET_LOGW(format, ##__VA_ARGS__); \ + statement; \ + } \ + +#define BEGET_CHECK(ret, statement) \ + if (!(ret)) { \ + statement; \ + } \ + +#define BEGET_CHECK_RETURN_VALUE(ret, result) \ + do { \ + if (!(ret)) { \ + return result; \ + } \ + } while (0) + +#define BEGET_CHECK_ONLY_RETURN(ret) \ + do { \ + if (!(ret)) { \ + return; \ + } \ + } while (0) + +#define BEGET_CHECK_ONLY_ELOG(ret, format, ...) \ + do { \ + if (!(ret)) { \ + BEGET_LOGE(format, ##__VA_ARGS__); \ + } \ + } while (0) + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/services/param/cmd/param_get.c b/interfaces/innerkits/include/fd_holder.h similarity index 31% rename from services/param/cmd/param_get.c rename to interfaces/innerkits/include/fd_holder.h index 1435dab09c2f2f1b263f9d30fd99537e0577323f..c979fe3b550185468f3941f452ac2738635c1501 100644 --- a/services/param/cmd/param_get.c +++ b/interfaces/innerkits/include/fd_holder.h @@ -1,59 +1,39 @@ -/* -* Copyright (c) 2021 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 "sys_param.h" - -#define HELP_PARAM "--help" -#define BUFFER_SIZE 256 - -static void ProcessParam(ParamHandle handle, void* cookie) -{ - if (cookie == NULL) { - printf("ProcessParam cookie is NULL\n"); - return; - } - SystemGetParameterName(handle, (char*)cookie, BUFFER_SIZE); - u_int32_t size = BUFFER_SIZE; - SystemGetParameterValue(handle, ((char*)cookie) + BUFFER_SIZE, &size); - printf("\t%s = %s \n", (char*)cookie, ((char*)cookie) + BUFFER_SIZE); -} - -int main(int argc, char* argv[]) -{ - if (argc == 1) { // 显示所有的记录 - char value[BUFFER_SIZE + BUFFER_SIZE] = {0}; - SystemTraversalParameter(ProcessParam, (void*)value); - return 0; - } - if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) { // 显示帮助 - printf("usage: getparam NAME VALUE\n"); - return 0; - } - if (argc != 2) { - printf("usage: getparam NAME VALUE\n"); - return 0; - } - char value[BUFFER_SIZE] = {0}; - u_int32_t size = BUFFER_SIZE; - int ret = SystemGetParameter(argv[1], value, &size); - if (ret == 0) { - printf("%s \n", value); - } else { - printf("getparam %s %s fail\n", argv[1], value); - } - -} +/* +* Copyright (c) 2021 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_FD_HOLDER_H +#define BASE_STARTUP_INITLITE_FD_HOLDER_H +#include + +#ifdef __cplusplus +extern "C" { +#endif +// fds stored in allocated memory, do not forget to release the memory when not use anymore +int *ServiceGetFd(const char *serviceName, size_t *fdCount); + +// Let init poll the fd for service +// This function will not take responsibility to close these fds +// Caller need to handle them. +int ServiceSaveFdWithPoll(const char *serviceName, int *fds, int fdCount); + +// Init only save the fd for service +// This function will not take responsibility to close these fds +// Caller need to handle them. +int ServiceSaveFd(const char *serviceName, int *fds, int fdCount); +#ifdef __cplusplus +} +#endif + +#endif // BASE_STARTUP_INITLITE_FD_HOLDER_H diff --git a/interfaces/innerkits/include/fs_manager/erofs_super_block.h b/interfaces/innerkits/include/fs_manager/erofs_super_block.h new file mode 100644 index 0000000000000000000000000000000000000000..16798ad5f63e9adadf938a332efc74898ef06610 --- /dev/null +++ b/interfaces/innerkits/include/fs_manager/erofs_super_block.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024-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 EROFS_H +#define EROFS_H + +#include + +#define EROFS_SUPER_MAGIC 0xE0F5E1E2 +#define EROFS_SUPER_BLOCK_START_POSITION 1024 + +struct erofs_super_block { + __le32 magic; + __le32 checksum; + __le32 feature_compat; + __u8 blkszbits; + __u8 reserved; + + __le16 root_nid; + __le64 inos; + + __le64 build_time; + __le32 build_time_nsec; + __le32 blocks; + __le32 meta_blkaddr; + __le32 xattr_blkaddr; + __u8 uuid[16]; + __u8 volume_name[16]; + __le32 feature_incompat; + __u8 reserved2[44]; +} __attribute((packed)); /* 128 byte */ + +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/fs_manager/ext4_super_block.h b/interfaces/innerkits/include/fs_manager/ext4_super_block.h new file mode 100644 index 0000000000000000000000000000000000000000..3305052d5b1c5ee7ec8e10f3fdfa5048a5dc6991 --- /dev/null +++ b/interfaces/innerkits/include/fs_manager/ext4_super_block.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024-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 EXT4_H +#define EXT4_H + +#include + +#define EXT4_SUPER_MAGIC 0xEF53 +#define EXT4_SUPER_BLOCK_START_POSITION 0x400 +#define BLOCK_SIZE_UNIT 4096 + +typedef struct ext4_super_block { +__le32 s_inodes_count; +__le32 s_blocks_count_lo; +__le32 s_r_blocks_count_lo; +__le32 s_free_blocks_count_lo; +__le32 s_free_inodes_count; +__le32 s_first_data_block; +__le32 s_log_block_size; +__le32 s_log_cluster_size; +__le32 s_blocks_per_group; +__le32 s_clusters_per_group; +__le32 s_inodes_per_group; +__le32 s_mtime; +__le32 s_wtime; +__le16 s_mnt_count; +__le16 s_max_mnt_count; +__le16 s_magic; +__le16 s_state; +__le16 s_errors; +__le16 s_minor_rev_level; +__le32 s_lastcheck; +__le32 s_checkinterval; +__le32 s_creator_os; +__le32 s_rev_level; +__le16 s_def_resuid; +__le16 s_def_resgid; + +__le32 s_first_ino; +__le16 s_inode_size; +__le16 s_block_group_nr; +__le32 s_feature_compat; +__le32 s_feature_incompat; +__le32 s_feature_ro_compat; +__u8 s_uuid[16]; +char s_volume_name[16]; +char s_last_mounted[64]; +__le32 s_algorithm_usage_bitmap; + +__u8 s_prealloc_blocks; +__u8 s_prealloc_dir_blocks; +__le16 s_reserved_gdt_blocks; + +__u8 s_journal_uuid[16]; +__le32 s_journal_inum; +__le32 s_journal_dev; +__le32 s_last_orphan; +__le32 s_hash_seed[4]; +__u8 s_def_hash_version; +__u8 s_jnl_backup_type; +__le16 s_desc_size; +__le32 s_default_mount_opts; +__le32 s_first_meta_bg; +__le32 s_mkfs_time; +__le32 s_jnl_blocks[17]; + +__le32 s_blocks_count_hi; +__le32 s_r_blocks_count_hi; +__le32 s_free_blocks_count_hi; +__le16 s_min_extra_isize; +__le16 s_want_extra_isize; +__le32 s_flags; +__le16 s_raid_stride; +__le16 s_mmp_interval; +__le64 s_mmp_block; +__le32 s_raid_stripe_width; +__u8 s_log_groups_per_flex; +__u8 s_checksum_type; +__le16 s_reserved_pad; +__le64 s_kbytes_written; +__le32 s_snapshot_inum; +__le32 s_snapshot_id; +__le64 s_snapshot_r_blocks_count; +__le32 s_snapshot_list; +__le32 s_error_count; +__le32 s_first_error_time; +__le32 s_first_error_ino; +__le64 s_first_error_block; +__u8 s_first_error_func[32]; +__le32 s_first_error_line; +__le32 s_last_error_time; +__le32 s_last_error_ino; +__le32 s_last_error_line; +__le64 s_last_error_block; +__u8 s_last_error_func[32]; +__u8 s_mount_opts[64]; +__le32 s_usr_quota_inum; +__le32 s_grp_quota_inum; +__le32 s_overhead_blocks; +__le32 s_backup_bgs[2]; +__u8 s_encrypt_algos[4]; +__u8 s_encrypt_pw_salt[16]; +__le32 s_lpf_ino; +__le32 s_prj_quota_inum; +__le32 s_checksum_seed; +__le32 s_reserved[98]; +__le32 s_checksum; +} ext4_super_block; /* 1024 byte */ + +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/fs_manager/fs_manager.h b/interfaces/innerkits/include/fs_manager/fs_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..de7d021bb7c64f6dacad18ef21d9ec08ea9d3be5 --- /dev/null +++ b/interfaces/innerkits/include/fs_manager/fs_manager.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021-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 STARTUP_FS_MANAGER_H +#define STARTUP_FS_MANAGER_H + +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* Fs manager flags definition */ +#define FS_MANAGER_CHECK 0x00000001 +#define FS_MANAGER_WAIT 0x00000002 +#define FS_MANAGER_REQUIRED 0x00000004 +#define FS_MANAGER_NOFAIL 0x00000008 +#define FS_MANAGER_HVB 0x00000010 +#define FS_MANAGER_PROJQUOTA 0x00000020 +#define FS_MANAGER_CASEFOLD 0x00000040 +#define FS_MANAGER_COMPRESSION 0x00000080 +#define FS_MANAGER_DEDUP 0x00000100 +#define FS_MANAGER_FORMATTABLE 0x00000200 +#define NAME_SIZE 32 +#define MAX_SLOT 2 + +#define VALID_FS_MANAGER_FLAGS (FS_MANAGER_CHECK | FS_MANAGER_WAIT | FS_MANAGER_REQUIRED) +#define FS_MANAGER_FLAGS_ENABLED(fsMgrFlags, flag) (((fsMgrFlags) & FS_MANAGER_##flag) != 0) + +#define FM_MANAGER_CHECK_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), CHECK) +#define FM_MANAGER_WAIT_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), WAIT) +#define FM_MANAGER_REQUIRED_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), REQUIRED) +#define FM_MANAGER_NOFAIL_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), NOFAIL) +#define FM_MANAGER_FORMATTABLE_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), FORMATTABLE) + +typedef enum MountStatus { + MOUNT_ERROR = -1, + MOUNT_UMOUNTED = 0, + MOUNT_MOUNTED = 1, +} MountStatus; + +typedef struct FstabItem { + char *deviceName; // Block device name + char *mountPoint; // Mount point + char *fsType; // File system type + char *mountOptions; // File system mount options. readonly, rw, remount etc. + unsigned int fsManagerFlags; // flags defined by fs manager. + struct FstabItem *next; +} FstabItem; + +typedef struct { + struct FstabItem *head; + struct FstabItem *tail; +} Fstab; + +typedef enum SlotFlag { + UNBOOT = 0, + ACTIVE = 1, +} SlotFlag; + +typedef struct SlotInfo { + int slotName; + char *slotSuffix; + SlotFlag slotFlag; + unsigned int retryCount; + unsigned int reserved; +} SlotInfo; + +Fstab* LoadFstabFromCommandLine(void); +int GetBootSlots(void); +int GetCurrentSlot(void); +void ReleaseFstab(Fstab *fstab); +Fstab *ReadFstabFromFile(const char *file, bool procMounts); +FstabItem *FindFstabItemForPath(Fstab fstab, const char *path); +FstabItem* FindFstabItemForMountPoint(Fstab fstab, const char *mp); +int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts, const char *separator); + +int GetBlockDeviceByMountPoint(const char *mountPoint, const Fstab *fstab, char *deviceName, int nameLen); +int GetBlockDeviceByName(const char *deviceName, const Fstab *fstab, char* miscDev, size_t size); +bool IsSupportedFilesystem(const char *fsType); +int DoFormat(const char *devPath, const char *fsType); +int MountOneItem(FstabItem *item); +MountStatus GetMountStatusForMountPoint(const char *mp); +int MountAllWithFstabFile(const char *fstabFile, bool required); +int MountAllWithFstab(const Fstab *fstab, bool required); +int UmountAllWithFstabFile(const char *file); +int MountOneWithFstabFile(const char *fstabFile, const char *devName, bool required); +int FsManagerDmRemoveDevice(const char *devName); +unsigned long GetMountFlags(char *mountFlag, char *fsSpecificFlags, size_t fsSpecificFlagSize, + const char *mountPoint); + +int GetBlockDevicePath(const char *partName, char *path, size_t size); + +// Get fscrypt policy if exist +int LoadFscryptPolicy(char *buf, size_t size); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // STARTUP_FS_MANAGER_H diff --git a/interfaces/innerkits/include/hookmgr.h b/interfaces/innerkits/include/hookmgr.h new file mode 100755 index 0000000000000000000000000000000000000000..c752272cd07922a59c37609c2ed81ebab768318e --- /dev/null +++ b/interfaces/innerkits/include/hookmgr.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021 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 OHOS_HOOK_MANAGER_H__ +#define OHOS_HOOK_MANAGER_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * @brief A Hook is a means of executing custom code (function) for existing running code. + * + * For a running process, it may consists of several stages. + * HookManager can help to add hooks to different stages with different priorities. + * The relationships for HookManager, HookStage and HookItem are shown as below: + * + * | ̄ ̄ ̄ ̄ ̄ ̄| + * | HookMgr | + * |__________| + * | + * | |▔▔▔▔▔▔▔▔▔▔▔| |▔▔▔▔▔▔▔▔▔▔▔| + * └--->| HookStage |--->| HookStage | ... + * |___________| |___________| + * | + * | |▔▔▔▔▔▔▔▔▔▔| |▔▔▔▔▔▔▔▔▔▔| + * └--->| HookItem |--->| HookItem | ... + * |__________| |__________| + * + * Usage example: + * + * For an existing module with several stages as below: + * ExistingStage1(...); + * ExistingStage2(...); + * ExistingStage3(...); + * We can add hooks capability to it as below: + * HookMgrExecute(hookMgr, PRE_STAGE1, ...); + * ExistingStage1(...); + * HookMgrExecute(hookMgr, PRE_STAGE2, ...); + * ExistingStage2(...); + * HookMgrExecute(hookMgr, PRE_STAGE3, ...); + * ExistingStage3(...); + * HookMgrExecute(hookMgr, POST_STAGE3, ...); + * + * For extending modules, we can add hooks without changing the existing module as below: + * int sampleHook() { + * ... + * } + * HookMgrAdd(hookMgr, PRE_STAGE1, priority, sampleHook); + */ + +/* Forward declaration for HookManager */ +typedef struct tagHOOK_MGR HOOK_MGR; + +/* Forward declaration for HOOK_INFO */ +typedef struct tagHOOK_INFO HOOK_INFO; + +/** + * @brief Hook function prototype + * + * @param hookInfo hook information + * @param executionContext input arguments for running the hook execution context + * @return return 0 if succeed; other values if failed. + */ +typedef int (*OhosHook)(const HOOK_INFO *hookInfo, void *executionContext); + +struct tagHOOK_INFO { + int stage; /* hook stage */ + int prio; /* hook priority */ + OhosHook hook; /* hook function */ + void *hookCookie; /* hook function cookie, for current hook only */ +}; + +/** + * @brief Add a hook function + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param stage hook stage + * @param prio hook priority + * @param hook hook function pointer + * @return return 0 if succeed; other values if failed. + */ +int HookMgrAdd(HOOK_MGR *hookMgr, int stage, int prio, OhosHook hook); + +/** + * @brief Add a hook function with full hook information + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param hookInfo full hook information + * @return return 0 if succeed; other values if failed. + */ +int HookMgrAddEx(HOOK_MGR *hookMgr, const HOOK_INFO *hookInfo); + +/** + * @brief Delete hook function + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param stage hook stage + * @param hook hook function pointer + * If hook is NULL, it will delete all hooks in the stage + * @return None + */ +void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook); + +/** + * @brief preHook function prototype for HookMgrExecute each hook + * + * @param hookInfo HOOK_INFO for the each hook. + * @param executionContext input arguments for running the hook execution context. + * @return None + */ +typedef void (*OhosHookPreExecution)(const HOOK_INFO *hookInfo, void *executionContext); + +/** + * @brief postHook function prototype for HookMgrExecute each hook + * + * @param hookInfo HOOK_INFO for the each hook. + * @param executionContext input arguments for running the hook execution context. + * @param executionRetVal return value for running the hook. + * @return None + */ +typedef void (*OhosHookPostExecution)(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal); + +/* Executing hooks in descending priority order */ +#define HOOK_EXEC_REVERSE_ORDER 0x01 +/* Stop executing hooks when error returned for each hook */ +#define HOOK_EXEC_EXIT_WHEN_ERROR 0x02 + +/** + * @brief Extra execution arguments for HookMgrExecute + */ +typedef struct tagHOOK_EXEC_OPTIONS { + /* Executing flags */ + int flags; + /* preHook for before executing each hook */ + OhosHookPreExecution preHook; + /* postHook for before executing each hook */ + OhosHookPostExecution postHook; +} HOOK_EXEC_OPTIONS; + +/** + * @brief Executing each hooks in specified stages + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param stage hook stage + * @param extraArgs HOOK_EXEC_ARGS for executing each hook. + * @return return 0 if succeed; other values if failed. + */ +int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *extraArgs); + +/** + * @brief Create a HookManager handle + * + * @param name HookManager name. + * @return return HookManager handle; NULL if failed. + */ +HOOK_MGR *HookMgrCreate(const char *name); + +/** + * @brief Destroy HookManager + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @return None. + */ +void HookMgrDestroy(HOOK_MGR *hookMgr); + +/** + * @brief Hook traversal function prototype + * + * @param hookInfo HOOK_INFO for traversing each hook. + * @return None + */ +typedef void (*OhosHookTraversal)(const HOOK_INFO *hookInfo, void *traversalCookie); + +/** + * @brief Traversing all hooks in the HookManager + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param traversalCookie traversal cookie. + * @param traversal traversal function. + * @return None. + */ +void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal); + +/** + * @brief Get number of hooks in specified stage + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param stage hook stage. + * @return number of hooks, return 0 if none + */ +int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage); + +/** + * @brief Get number of stages in the HookManager + * + * @param hookMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @return number of stages, return 0 if none + */ +int HookMgrGetStagesCnt(HOOK_MGR *hookMgr); + +#define HOOK_OK = 0 +#define ERR_NO_HOOK_STAGE (-1000) +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/include/init_error.h b/interfaces/innerkits/include/init_error.h new file mode 100644 index 0000000000000000000000000000000000000000..5eb8bbc7f15ead6a5339386963875e5f9ef77aee --- /dev/null +++ b/interfaces/innerkits/include/init_error.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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 INIT_ERROR_H +#define INIT_ERROR_H + +#include "beget_ext.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/* Expand this list if necessary. */ +#define INIT_ERRNO_MAP(XX) \ + XX(EPARAMETER, "Invalid parameter") \ + XX(EFORMAT, "Format string fail") \ + XX(ECFG, "cfg error") \ + XX(EPATH, "Invalid path") \ + XX(EFORK, "Fork fail") \ + XX(ESANDBOX, "Create sandbox fail") \ + XX(EACCESSTOKEN, "Set access token fail") \ + XX(ESOCKET, "Create socket fail") \ + XX(EFILE, "Create file fail") \ + XX(ECONSOLE, "Open console fail") \ + XX(EHOLDER, "Publish holder fail") \ + XX(EBINDCORE, "Bind core fail") \ + XX(EKEEPCAP, "Set keep capability fail") \ + XX(EGIDSET, "Set gid fail") \ + XX(ESECCOMP, "Set SECCOMP fail") \ + XX(EUIDSET, "Set uid fail") \ + XX(ECAP, "Set capability fail") \ + XX(EWRITEPID, "Write pid fail") \ + XX(ECONTENT, "Set sub content fail") \ + XX(EPRIORITY, "Set priority fail") \ + XX(EEXEC_CONTENT, "Set exec content fail") \ + XX(EEXEC, "Exec fail") + +typedef enum { + INIT_OK, +#define XX(code, _) INIT_ ## code, + INIT_ERRNO_MAP(XX) +#undef XX +} InitErrno; + +struct InitErrMap { + int code; + const char *info; +} ; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // INIT_UTILS_H diff --git a/interfaces/innerkits/include/init_file.h b/interfaces/innerkits/include/init_file.h new file mode 100644 index 0000000000000000000000000000000000000000..f4ca848f41d055415a49f7a173f0f3315d4ce799 --- /dev/null +++ b/interfaces/innerkits/include/init_file.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 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 INIT_FILE_API_H +#define INIT_FILE_API_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define OHOS_FILE_ENV_PREFIX "OHOS_FILE_" + +int GetControlFile(const char *name); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/include/init_hashmap.h b/interfaces/innerkits/include/init_hashmap.h new file mode 100644 index 0000000000000000000000000000000000000000..4b016b4bcbf19f632fe8b729baa09d02d9988ef9 --- /dev/null +++ b/interfaces/innerkits/include/init_hashmap.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 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 INIT_HASH_MAP_ +#define INIT_HASH_MAP_ +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define HASH_TAB_BUCKET_MAX 1024 +#define HASH_TAB_BUCKET_MIN 16 + +typedef struct HashNode_ { + struct HashNode_ *next; +} HashNode; + +#define HASHMAP_ENTRY(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) +#define HASHMAPInitNode(node) (node)->next = NULL + +typedef int (*HashNodeCompare)(const HashNode *node1, const HashNode *node2); +typedef int (*HashKeyCompare)(const HashNode *node1, const void *key); +typedef int (*HashNodeFunction)(const HashNode *node); +typedef int (*HashKeyFunction)(const void *key); +typedef void (*HashNodeOnFree)(const HashNode *node, void *context); + +typedef struct { + HashNodeCompare nodeCompare; + HashKeyCompare keyCompare; + HashNodeFunction nodeHash; + HashKeyFunction keyHash; + HashNodeOnFree nodeFree; + int maxBucket; +} HashInfo; + +typedef void *HashMapHandle; + +int OH_HashMapIsEmpty(HashMapHandle handle); +int32_t OH_HashMapCreate(HashMapHandle *handle, const HashInfo *info); +void OH_HashMapDestory(HashMapHandle handle, void *context); +int32_t OH_HashMapAdd(HashMapHandle handle, HashNode *hashNode); +void OH_HashMapRemove(HashMapHandle handle, const void *key); +HashNode *OH_HashMapGet(HashMapHandle handle, const void *key); +HashNode *OH_HashMapFind(HashMapHandle handle, + int hashCode, const void *key, HashKeyCompare keyCompare); +void OH_HashMapTraverse(HashMapHandle handle, void (*hashNodeTraverse)(const HashNode *node, const void *context), + const void *context); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/init_reboot.h b/interfaces/innerkits/include/init_reboot.h old mode 100755 new mode 100644 index 61034d9d8e4260d824806cbe6166e5c7248694d2..8157e5759de8aedce904ea2d28b7e5e11124ef8e --- a/interfaces/innerkits/include/init_reboot.h +++ b/interfaces/innerkits/include/init_reboot.h @@ -16,7 +16,43 @@ #ifndef INIT_REBOOT_API_H #define INIT_REBOOT_API_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define STARTUP_DEVICE_CTL "startup.device.ctl" +#define DEVICE_CMD_STOP "stop" +#define DEVICE_CMD_SUSPEND "suspend" +#define DEVICE_CMD_RESUME "resume" +#define DEVICE_CMD_FREEZE "freeze" +#define DEVICE_CMD_RESTORE "restore" + +/** + * @brief reboot system + * + * @param option format is: mode[:info] + * mode : command sub key, example: updater, shutdown ... + * info : extend info + * @return int + */ int DoReboot(const char *cmdContent); +/** + * @brief reboot system + * + * @param mode command sub key, example: updater, shutdown ... + * @param option extend info + * + * @return int + */ +int DoRebootExt(const char *mode, const char *option); + +#ifdef __cplusplus +#if __cplusplus +} +#endif #endif +#endif diff --git a/interfaces/innerkits/include/init_socket.h b/interfaces/innerkits/include/init_socket.h old mode 100755 new mode 100644 index 420264d147bf965ee58dc44f2b2a07dd856af2a8..786774858b28dfbfa54312f23bd6e3ffb930cfd9 --- a/interfaces/innerkits/include/init_socket.h +++ b/interfaces/innerkits/include/init_socket.h @@ -18,7 +18,16 @@ #define OHOS_SOCKET_DIR "/dev/unix/socket" #define OHOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif // parameter is service name int GetControlSocket(const char *name); - -#endif \ No newline at end of file +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/include/init_utils.h b/interfaces/innerkits/include/init_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..ce6449630e7ba047d1484def83dfcd793bbbf045 --- /dev/null +++ b/interfaces/innerkits/include/init_utils.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021 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 INIT_UTILS_H +#define INIT_UTILS_H +#include +#include +#include +#include +#include +#include + +#include "beget_ext.h" + +#ifndef STARTUP_INIT_TEST +#ifndef INIT_STATIC +#define INIT_STATIC static +#endif +#else +#ifndef INIT_STATIC +#define INIT_STATIC +#endif +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct { + char *name; + int value; +} InitArgInfo; + +#define BASE_MS_UNIT 1000 +#define MAX_INT_LEN 20 +#define HEX_BASE 16 +#define BINARY_BASE 2 +#define OCTAL_BASE 8 +#define DECIMAL_BASE 10 +#define WAIT_MAX_SECOND 5 +#define MAX_BUFFER_LEN 256 +#define CMDLINE_VALUE_LEN_MAX 512 +#define STDERR_HANDLE 2 +#define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0])) +#define BOOT_CMD_LINE STARTUP_INIT_UT_PATH"/proc/cmdline" + +#define FIRST_VALUE "First_Value" // 取第一个匹配值 +#define LAST_VALUE "Last_Value" // 取最后一个匹配值 +#define EMPTY_VALUE "EMPTY_VALUE" // 不取任何一个 + +uid_t DecodeUid(const char *name); +gid_t DecodeGid(const char *name); +char *ReadFileToBuf(const char *configFile); +int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length); +char *ReadFileData(const char *fileName); + +typedef struct INIT_TIMING_STAT { + struct timespec startTime; + struct timespec endTime; +} INIT_TIMING_STAT; + +typedef struct NameValuePair { + const char *name; + const char *nameEnd; + const char *value; + const char *valueEnd; +} NAME_VALUE_PAIR; +int IterateNameValuePairs(const char *src, void (*iterator)(const NAME_VALUE_PAIR *nv, void *context), void *context); + +int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum); +long long InitDiffTime(INIT_TIMING_STAT *stat); +void WaitForFile(const char *source, unsigned int maxSecond); +size_t WriteAll(int fd, const char *buffer, size_t size); +char *GetRealPath(const char *source); +int StringToInt(const char *str, int defaultValue); +int StringToUint(const char *name, unsigned int *value); +int MakeDirRecursive(const char *dir, mode_t mode); +void CheckAndCreateDir(const char *fileName); +int CheckAndCreatFile(const char *file, mode_t mode); +int MakeDir(const char *dir, mode_t mode); +int ReadFileInDir(const char *dirPath, const char *includeExt, + int (*processFile)(const char *fileName, void *context), void *context); +char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount); +void FreeStringVector(char **vector, int count); +int InUpdaterMode(void); +int InRescueMode(void); +int StringReplaceChr(char *strl, char oldChr, char newChr); + +int OpenConsole(void); +int OpenKmsg(void); +void TrimTail(char *str, char c); +char *TrimHead(char *str, char c); + +INIT_LOCAL_API uint32_t IntervalTime(struct timespec *startTime, struct timespec *endTime); + +INIT_LOCAL_API int StringToULL(const char *str, unsigned long long int *out); +INIT_LOCAL_API int StringToLL(const char *str, long long int *out); +void CloseStdio(void); + +int GetServiceGroupIdByPid(pid_t pid, gid_t *gids, uint32_t gidSize); +int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen); + +/** + * @brief Get param value from /proc/cmdline by exact match + * + * @param paramName the name of param + * @param value the array to receive the value of paramName + * @param valueLen the length of value + * @param conflictStrategy the strategy of conflicts, here are some options available + * FIRST_VALUE: select the first value + * LAST_VALUE: select the last value + * EMPTY_VALUE: return empty value + * "A + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * @brief Double linked list structure is show as below: + * + * | ̄ ̄ ̄ ̄ ̄|-----------------------------------------------| + * |->| head | | + * | |________|<-------------------------------------------| | + * | | | | + * | └-next->|▔▔▔▔▔▔|-next->|▔▔▔▔▔▔|-next->|▔▔▔▔▔▔|-next--| | + * └------prev-| node |<-prev-| node |<-prev-| node |<-prev----| + * |------| |------| |------| + * | extra| | extra| | extra| + * |______| |______| |______| + * + * Usage Example: + * 1. Define structure for each item in the list + * typedef struct tagTEST_LIST_ITEM { + * ListNode node; + * int value; + * } TEST_LIST_ITEM; + * + * 2. Define a list and init list by OH_ListAddTail + * ListNode testList; + * c(&testList); + * + * 3. Define a list item instance + * TEST_LIST_ITEM item; + * item.value = 0; + * + * 4. Add list item to list + * OH_ListAddTail(&testList, (ListNode *)(&item)); + * + * 5. Advanced usage: add with order + * // Ordering compare function + * static int TestListItemCompareProc(ListNode *node, ListNode *newNode) + * { + * TEST_LIST_ITEM *left = (TEST_LIST_ITEM *)node; + * TEST_LIST_ITEM *right = (TEST_LIST_ITEM *)newNode; + * return left->value - right->value; + * } + * OH_ListAddWithOrder(&testList, (ListNode *)(&item)) + */ + +/** + * @brief Double linked list node + */ +typedef struct ListNode { + struct ListNode *next; + struct ListNode *prev; +} ListNode, ListHead; + +#define ListEmpty(node) ((node).next == &(node) && (node).prev == &(node)) +#define ListEntry(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) +#define ForEachListEntry(list, node) for (node = (list)->next; node != (list); node = node->next) + +/** + * @brief Initialize a double-linked list head + * + * All other list API should be initialized by this function.\n + * + * @param head list head, make sure head is valid pointer + * @return None + */ +void OH_ListInit(struct ListNode *list); + +/** + * @brief Add a node to the end of the list + * + * @param head list head, make sure head is valid pointer + * @param item new node to be added + * @return None + */ +void OH_ListAddTail(struct ListNode *list, struct ListNode *item); + +/** + * @brief Remove a node from the list + * + * @param item the node to be removed from the list. + * This function does not free any memory within item. + * @return None + */ +void OH_ListRemove(struct ListNode *item); + +/** + * @brief ListNode comparison function prototype + * + * @param node ListNode to be compared. + * @param newNode new ListNode to be compared. + * @return + * <0 if node < newNode + * =0 if node = newNode + * >0 if Node > newNode + */ +typedef int (*ListCompareProc)(ListNode *node, ListNode *newNode); + +/** + * @brief Add a node to the list with order + * + * @param head list head, make sure head is valid pointer + * @param item new node to be added + * @param compareProc comparison function for adding node + * if it is ascending order, this function should return an integer less than, + * equal to, or greater than zero if the first argument is considered to be + * respectively less than, equal to, or greater than the second. + * @return None + */ +void OH_ListAddWithOrder(struct ListNode *head, struct ListNode *item, ListCompareProc compareProc); + +/** + * @brief ListNode traversing and find function prototype + * + * @param node ListNode to be compared. + * @param data value for traversing + * @return + * return 0 if node value equals data for OH_ListFind + */ +typedef int (*ListTraversalProc)(ListNode *node, void *data); + +/** + * @brief Find a node by traversing the list + * + * @param head list head, make sure head is valid pointer. + * @param data comparing data. + * @param compareProc comparing function, return 0 if matched. + * @return the found node; return NULL if none is found. + */ +ListNode *OH_ListFind(const ListNode *head, void *data, ListTraversalProc compareProc); + +/* Traversing from end to start */ +#define TRAVERSE_REVERSE_ORDER 0x1 +/* Stop traversing when error returned */ +#define TRAVERSE_STOP_WHEN_ERROR 0x2 + +/** + * @brief Traversal the list with specified function + * + * @param head list head, make sure head is valid pointer. + * @param cookie optional traversing data. + * @param traversalProc comparing function, return 0 if matched. + * @param flags optional traversing flags: + * TRAVERSE_REVERSE_ORDER: traversing from last node to first node; + * default behaviour is from first node to last node + * TRAVERSE_STOP_WHEN_ERROR: stop traversing if traversalProc return non-zero + * default behaviour will ignore traversalProc return values + * @return return -1 for invalid input arguments. + * when TRAVERSE_STOP_WHEN_ERROR is specified, it will return errors from traversalProc + */ +int OH_ListTraversal(ListNode *head, void *data, ListTraversalProc traversalProc, unsigned int flags); + +/** + * @brief ListNode destroy function prototype + * + * @param node ListNode to be destroyed. + * @return None + */ +typedef void (*ListDestroyProc)(ListNode *node); + +/** + * @brief Find a node by traversing the list + * + * @param head list head, make sure head is valid pointer. + * @param destroyProc destroy function; if NULL, it will free each node by default. + * @return None + */ +void OH_ListRemoveAll(ListNode *head, ListDestroyProc destroyProc); + +/** + * @brief Get list count + * + * @param head list head, make sure head is valid pointer. + * @return the count of nodes in the list; return 0 if error + */ +int OH_ListGetCnt(const ListNode *head); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_INITLITE_LIST_H diff --git a/interfaces/innerkits/include/loop_event.h b/interfaces/innerkits/include/loop_event.h new file mode 100644 index 0000000000000000000000000000000000000000..bd67675024682ee3b6b45135a67afc4d821f12d8 --- /dev/null +++ b/interfaces/innerkits/include/loop_event.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2021 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 LOOP_EVENT_H +#define LOOP_EVENT_H +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +// 配置 +#define LOOP_EVENT_USE_EPOLL 1 +#define LOOP_DEFAULT_BUFFER (1024 * 5) +#define LOOP_MAX_BUFFER (1024 * 64) + +#define LOOP_MAX_CLIENT 1024 +#define LOOP_MAX_SOCKET 1024 +#define DEFAULT_TIMEOUT 1000 + +typedef enum { + EVENT_READ = (0x0001), + EVENT_WRITE = (0x0002), + EVENT_ERROR = (0x0004), + EVENT_FREE = (0x0008), + EVENT_TIMEOUT = (0x0010), + EVENT_SIGNAL = (0x0020), +} EventOper; + +typedef enum { + LE_SUCCESS = 0, + LE_FAILURE = 10000, + LE_INVALID_PARAM, + LE_NO_MEMORY, + LE_DIS_CONNECTED, + LE_INVALID_TASK +} LE_STATUS; + +typedef struct { + uint32_t flags; +} LoopBase; + +typedef LoopBase *LoopHandle; +typedef LoopBase *TaskHandle; +typedef LoopBase *TimerHandle; +typedef LoopBase *SignalHandle; +typedef LoopBase *WatcherHandle; +typedef void *BufferHandle; + +LoopHandle LE_GetDefaultLoop(void); +LE_STATUS LE_CreateLoop(LoopHandle *loopHandle); +void LE_RunLoop(const LoopHandle loopHandle); +void LE_CloseLoop(const LoopHandle loopHandle); +void LE_StopLoop(const LoopHandle loopHandle); +void LE_CloseTask(const LoopHandle loopHandle, const TaskHandle taskHandle); + +/** + * 申请一个buffer,用于消息的发送和接收 + */ +BufferHandle LE_CreateBuffer(const LoopHandle loopHandle, uint32_t bufferSize); +void LE_FreeBuffer(const LoopHandle loopHandle, const TaskHandle taskHandle, const BufferHandle handle); +uint8_t *LE_GetBufferInfo(const BufferHandle handle, uint32_t *dataSize, uint32_t *buffSize); +void *LE_GetUserData(const TaskHandle handle); +int32_t LE_GetSendResult(const BufferHandle handle); + +typedef void (*LE_Close)(const TaskHandle taskHandle); +typedef struct { + uint32_t flags; + LE_Close close; + uint16_t userDataSize; +} LE_BaseInfo; + +/** + * 数据流服务,可以指定使用pipe或者普通的tcp + */ +#define TASK_STREAM 0x01 +#define TASK_TCP (0x01 << 8) +#define TASK_PIPE (0x02 << 8) +#define TASK_SERVER (0x01 << 16) +#define TASK_CONNECT (0x02 << 16) +#define TASK_TEST (0x01 << 24) +#define TASK_PUBLIC (0x01 << 25) // If the socket can be publicly connected +typedef void (*LE_DisConnectComplete)(const TaskHandle client); +typedef void (*LE_ConnectComplete)(const TaskHandle client); +typedef void (*LE_SendMessageComplete)(const TaskHandle taskHandle, BufferHandle handle); +typedef void (*LE_RecvMessage)(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen); +typedef int (*LE_IncommingConnect)(const LoopHandle loopHandle, const TaskHandle serverTask); +typedef int (*LE_HandleRecvMsg)(const TaskHandle taskHandle, uint8_t* buffer, int bufferSize, int flags); +typedef struct { + LE_BaseInfo baseInfo; + char *server; + int socketId; + LE_DisConnectComplete disConnectComplete; + LE_IncommingConnect incommingConnect; + LE_SendMessageComplete sendMessageComplete; + LE_RecvMessage recvMessage; +} LE_StreamServerInfo; + +typedef struct { + LE_BaseInfo baseInfo; + char *server; + LE_DisConnectComplete disConnectComplete; + LE_ConnectComplete connectComplete; + LE_SendMessageComplete sendMessageComplete; + LE_RecvMessage recvMessage; + LE_HandleRecvMsg handleRecvMsg; +} LE_StreamInfo; + +LE_STATUS LE_CreateStreamServer(const LoopHandle loopHandle, + TaskHandle *taskHandle, const LE_StreamServerInfo *info); +LE_STATUS LE_CreateStreamClient(const LoopHandle loopHandle, + TaskHandle *taskHandle, const LE_StreamInfo *info); +LE_STATUS LE_AcceptStreamClient(const LoopHandle loopHandle, + const TaskHandle serverTask, TaskHandle *taskHandle, const LE_StreamInfo *info); +LE_STATUS LE_Send(const LoopHandle loopHandle, + const TaskHandle taskHandle, const BufferHandle handle, uint32_t buffLen); +void LE_CloseStreamTask(const LoopHandle loopHandle, const TaskHandle taskHandle); +int LE_GetSocketFd(const TaskHandle taskHandle); + +/** + * 异步事件服务 + */ +typedef void (*LE_ProcessAsyncEvent)(const TaskHandle taskHandle, + uint64_t eventId, const uint8_t *buffer, uint32_t buffLen); +#define TASK_EVENT 0x02 +#define TASK_ASYNC_EVENT (0x01 << 8) +LE_STATUS LE_CreateAsyncTask(const LoopHandle loopHandle, + TaskHandle *taskHandle, LE_ProcessAsyncEvent processAsyncEvent); +LE_STATUS LE_StartAsyncEvent(const LoopHandle loopHandle, + const TaskHandle taskHandle, uint64_t eventId, const uint8_t *data, uint32_t buffLen); +void LE_StopAsyncTask(const LoopHandle loopHandle, const TaskHandle taskHandle); +#ifdef STARTUP_INIT_TEST +void LE_DoAsyncEvent(const LoopHandle loopHandle, const TaskHandle taskHandle); +#endif + +/** + * 定时器处理 + */ +#define TASK_TIME 0x04 +typedef void (*LE_ProcessTimer)(const TimerHandle taskHandle, void *context); + +LE_STATUS LE_CreateTimer(const LoopHandle loopHandle, TimerHandle *timer, + LE_ProcessTimer processTimer, void *context); +LE_STATUS LE_StartTimer(const LoopHandle loopHandle, + const TimerHandle timer, uint64_t timeout, uint64_t repeat); +void LE_StopTimer(const LoopHandle loopHandle, const TimerHandle timer); + +#define TASK_SIGNAL 0x08 +typedef void (*LE_ProcessSignal)(const struct signalfd_siginfo *siginfo); +LE_STATUS LE_CreateSignalTask(const LoopHandle loopHandle, + SignalHandle *signalHandle, LE_ProcessSignal processSignal); +LE_STATUS LE_AddSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal); +LE_STATUS LE_RemoveSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal); +void LE_CloseSignalTask(const LoopHandle loopHandle, const SignalHandle signalHandle); + +/** + * 监控句柄变化 + */ +#define TASK_WATCHER 0x10 +#define WATCHER_ONCE 0x0100 +typedef void (*ProcessWatchEvent)(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context); +typedef struct { + int fd; + uint32_t flags; + uint32_t events; + LE_Close close; + ProcessWatchEvent processEvent; +} LE_WatchInfo; +LE_STATUS LE_StartWatcher(const LoopHandle loopHandle, + WatcherHandle *watcherHandle, const LE_WatchInfo *info, const void *context); +void LE_RemoveWatcher(const LoopHandle loopHandle, const WatcherHandle watcherHandle); + +/** + * Idle Processing:Idle handlers will be called for every loop + */ + +/* Idle Handler */ +typedef void *IdleHandle; + +/** + * @brief Idle process function prototype + * + * @param taskHandle idle handler + * @param context idle function context + * @return None + */ +typedef void (*LE_ProcessIdle)(const IdleHandle taskHandle, void *context); + +/** + * @brief Add a new idle handler + * + * @param loopHandle the running loop this idle will be attached + * @param idle optional output parameter for the created idle handler + * @param processIdle the idle handler function + * @param context optional idle handler context + * @param repeat if the idle function will be repeated forevent (non zero) or once (zero) + * @return status code, 0 means succeed + */ +LE_STATUS LE_AddIdle(const LoopHandle loopHandle, IdleHandle *idle, + LE_ProcessIdle processIdle, void *context, int repeat); + +/** + * @brief Delete an idle handler + * + * @param idle idle handler + * @return None + */ +void LE_DelIdle(IdleHandle idle); + +/** + * @brief Execute an function once in the next loop + * + * @param loopHandle the running loop this idle will be attached + * @param idle the function to be executed + * @param context optional idle handler context + * @return status code, 0 means succeed + */ +int LE_DelayProc(const LoopHandle loopHandle, LE_ProcessIdle idle, void *context); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/modulemgr.h b/interfaces/innerkits/include/modulemgr.h new file mode 100755 index 0000000000000000000000000000000000000000..2f2967c9f747f9bda62b3d84040f00c053268b08 --- /dev/null +++ b/interfaces/innerkits/include/modulemgr.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2021 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 OHOS_MODULES_MANAGER_H__ +#define OHOS_MODULES_MANAGER_H__ + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * @brief Module constructor function + * + * For static modules, this code is executed before main(). + * For dynamic modules, this code is executed when ModuleMgrInstall(). + * + * Usage example: + * MODULE_CONSTRUCTOR(void) + * { + * ... + * } + */ +#define MODULE_CONSTRUCTOR(void) static void _init(void) __attribute__((constructor)); static void _init(void) + +/** + * @brief Module destructor function + * + * For static modules, this code will not be executed. + * For dynamic modules, this code is executed when ModuleMgrUninstall(). + * + * Usage example: + * MODULE_DESTRUCTOR(void) + * { + * ... + * } + */ +#define MODULE_DESTRUCTOR(void) static void _destroy(void) __attribute__((destructor)); static void _destroy(void) + +// Forward declaration +typedef struct tagMODULE_MGR MODULE_MGR; + +/** + * @brief Create dynamic module manager + * + * This dynamic module manager will manager modules + * in the directory: /system/lib/{name}/ + * @param name module manager name + * @return return module manager handle if succeed; return NULL if failed. + */ +MODULE_MGR *ModuleMgrCreate(const char *name); + +/** + * @brief Destroy dynamic module manager + * + * It will uninstall all modules managed by this moduleMgr + * @param moduleMgr module manager handle + * @return None + */ +void ModuleMgrDestroy(MODULE_MGR *moduleMgr); + +/** + * @brief Install a module + * + * The final module path is: /system/lib/{moduleMgrPath}/{moduleName}.z.so + * + * @param moduleMgr module manager handle + * @param moduleName module name + * @param argc argument counts for installing + * @param argv arguments for installing, the last argument is NULL. + * @return module handle returned by dlopen + */ +int ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName, + int argc, const char *argv[]); + +/** + * @brief Module install arguments + */ +typedef struct { + int argc; + const char **argv; +} MODULE_INSTALL_ARGS; + +/** + * @brief Get module install arguments + * + * This function is available only in MODULE_CONSTRUCTOR. + * + * @return install args if succeed; return NULL if failed. + */ +const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void); + +/** + * @brief Scan and install all modules in specified directory + * + * @param modulePath path for modules to be installed + * @return install args if succeed; return NULL if failed. + */ +MODULE_MGR *ModuleMgrScan(const char *modulePath); + +/** + * @brief Uninstall module + * + * @param moduleMgr module manager handle + * @param name module name. If name is NULL, it will uninstall all modules. + * @return install args if succeed; return NULL if failed. + */ +void ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name); + +/** + * @brief Get number of modules in module manager + * + * @param hookMgr module manager handle + * @return number of modules, return 0 if none + */ +int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr); + +/** + * @brief Module information for traversing modules + */ +typedef struct tagMODULE_INFO { + const char *name; /* module name */ + void *handle; /* module handler */ + void *cookie; /* hook execution cookie */ +} MODULE_INFO; + +/** + * @brief Module traversal function prototype + * + * @param moduleInfo MODULE_INFO for traversing each module. + * @return None + */ +typedef void (*OhosModuleTraversal)(const MODULE_INFO *moduleInfo); + +/** + * @brief Traversing all modules in the ModuleManager + * + * @param moduleMgr module manager handle + * @param cookie traversal cookie. + * @param traversal traversal function. + * @return None. + */ +void ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/include/param/init_param.h b/interfaces/innerkits/include/param/init_param.h new file mode 100644 index 0000000000000000000000000000000000000000..de5fe5abf24471ff19559b91d154ac9d86334b43 --- /dev/null +++ b/interfaces/innerkits/include/param/init_param.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2021 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_INIT_PARAM_H +#define BASE_STARTUP_INIT_PARAM_H +#include +#include +#ifdef PARAM_SUPPORT_TRIGGER +#include "cJSON.h" +#endif +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define DEFAULT_PARAM_WAIT_TIMEOUT 30 // 30s +#define DEFAULT_PARAM_SET_TIMEOUT 10 // 10s + +#ifndef PARAM_NAME_LEN_MAX +#define PARAM_CONST_VALUE_LEN_MAX 4096 +#define PARAM_VALUE_LEN_MAX 96 +#define PARAM_NAME_LEN_MAX 96 +#endif + +typedef enum { + PARAM_CODE_ERROR = -1, + PARAM_CODE_SUCCESS = 0, + PARAM_CODE_INVALID_PARAM = 100, + PARAM_CODE_INVALID_NAME, + PARAM_CODE_INVALID_VALUE, + PARAM_CODE_REACHED_MAX, + PARAM_CODE_NOT_SUPPORT, + PARAM_CODE_TIMEOUT, + PARAM_CODE_NOT_FOUND, + PARAM_CODE_READ_ONLY, + PARAM_CODE_IPC_ERROR, + PARAM_CODE_NODE_EXIST, + PARAM_WATCHER_CALLBACK_EXIST, + PARAM_WATCHER_GET_SERVICE_FAILED, + PARAM_CODE_MEMORY_MAP_FAILED, + PARAM_WORKSPACE_NOT_INIT, + PARAM_CODE_FAIL_CONNECT, + PARAM_CODE_MEMORY_NOT_ENOUGH, + PARAM_CODE_PERMISSION_DENIED, + PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH, + DAC_RESULT_INVALID_PARAM = 1000, + DAC_RESULT_FORBIDED, + SELINUX_RESULT_FORBIDED, + PARAM_CODE_MAX +} PARAM_CODE; + +typedef enum { + EVENT_TRIGGER_PARAM, + EVENT_TRIGGER_BOOT, + EVENT_TRIGGER_PARAM_WAIT, + EVENT_TRIGGER_PARAM_WATCH +} EventType; + +#define LOAD_PARAM_NORMAL 0x00 +#define LOAD_PARAM_ONLY_ADD 0x01 +#define LOAD_PARAM_PERSIST 0x02 + +typedef uint32_t ParamHandle; + +/** + * Init 接口 + * 初始化参数服务 + * + */ +int InitParamService(void); +void LoadSpecialParam(void); + +/** + * Init 接口 + * 启动参数服务,在main启动的最后调用,阻赛当前线程 + * + */ +int StartParamService(void); + +/** + * Init 接口 + * 停止参数服务 + * + */ +void StopParamService(void); + +/** + * Init 接口 + * 加载默认的参数值 + * + */ +int LoadDefaultParams(const char *fileName, uint32_t mode); + +/** + * Init 接口 + * 加载持久化参数。 + * + */ +int LoadPersistParams(void); + +/** + * Init 接口 + * 加载加密目录下持久化参数。 + * + */ +int LoadPrivatePersistParams(void); + +/** + * Init 接口 + * 设置参数,主要用于其他进程使用,通过管道修改参数 + * + */ +int SystemWriteParam(const char *name, const char *value); + +#ifdef PARAM_SUPPORT_TRIGGER +/** + * 对外接口 + * 触发一个trigger操作。 + * + */ +void PostTrigger(EventType type, const char *content, uint32_t contentLen); + +/** + * 对外接口 + * 解析trigger文件。 + * + */ +int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName), void *context); + +/** + * 对外接口 + * 按名字执行对应的trigger。 + * + */ +void DoTriggerExec(const char *triggerName); +void DoJobExecNow(const char *triggerName); + +/** + * 对外接口 + * 按名字添加一个job,用于group支持。 + * + */ +int AddCompleteJob(const char *name, const char *condition, const char *cmdContent); + +void RegisterBootStateChange(void (*bootStateChange)(int start, const char *)); + +/** + * 对外接口 + * dump 参数和trigger信息 + * + */ +void SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...)); +#endif + +/** + * 对外接口 + * 设置参数,主要用于其他进程使用,通过管道修改参数。 + * + */ +int SystemSetParameter(const char *name, const char *value); + +/** + * 对外接口 + * 保存共享内存中的所有持久化参数 + * +*/ +int SystemSaveParameters(void); + +/** + * Init 接口 + * 查询参数。 + * + */ +int SystemReadParam(const char *name, char *value, uint32_t *len); + +/** + * 对外接口 + * 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。 + * 如果 value == null,获取value的长度 + * 否则value的大小认为是len + * + */ +#define SystemGetParameter SystemReadParam + + +/** + * 外部接口 + * 等待某个参数值被修改,阻塞直到参数值被修改或超时 + * + */ +int SystemWaitParameter(const char *name, const char *value, int32_t timeout); + +typedef void (*ParameterChangePtr)(const char *key, const char *value, void *context); +int SystemWatchParameter(const char *keyprefix, ParameterChangePtr change, void *context); + +int SystemCheckParamExist(const char *name); + +void SystemDumpParameters(int verbose, int index, int (*dump)(const char *fmt, ...)); + +int WatchParamCheck(const char *keyprefix); + +void ResetParamSecurityLabel(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/param/sys_param.h b/interfaces/innerkits/include/param/sys_param.h new file mode 100644 index 0000000000000000000000000000000000000000..07e4d347046e1a6081875f14f84703fcf89a9377 --- /dev/null +++ b/interfaces/innerkits/include/param/sys_param.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2023 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_INIT_SYS_PARAM_H +#define BASE_STARTUP_INIT_SYS_PARAM_H + +#include +#ifndef __LITEOS_M__ +#include +#endif + +#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__)) +#include +#endif + +#ifndef __LITEOS_A__ +#if defined FUTEX_WAIT || defined FUTEX_WAKE +#include +#endif +#endif + +#define MEMORY_ORDER_ACQUIRE 2 + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef __LITEOS_M__ +#define ATOMIC_UINT32 uint32_t +#define ATOMIC_LLONG long long +#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) *(commitId) + +#else +#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__)) +#define ATOMIC_UINT32 atomic_uint +#define ATOMIC_LLONG atomic_llong +#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order) + +#else +#ifndef STARTUP_INIT_TEST +#define ATOMIC_UINT32 uint32_t +#define ATOMIC_LLONG int64_t +static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order) +{ + return *((volatile ATOMIC_LLONG *)ptr); +} +#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order) +#endif +#endif +#endif + +#ifdef __LITEOS_M__ +typedef struct { + uint32_t mutex; +} ParamRWMutex; + +typedef struct { + uint32_t mutex; +} ParamMutex; +#endif + +// support mutex +#ifndef STARTUP_INIT_TEST +typedef struct { + pthread_rwlock_t rwlock; +} ParamRWMutex; + +typedef struct { + pthread_mutex_t mutex; +} ParamMutex; +#endif + +#ifndef STARTUP_INIT_TEST +typedef struct { + int shmid; +} MemHandle; + +typedef struct { + ATOMIC_LLONG commitId; + ATOMIC_LLONG commitPersistId; + uint32_t trieNodeCount; + uint32_t paramNodeCount; + uint32_t securityNodeCount; + uint32_t currOffset; + uint32_t spaceSizeOffset; + uint32_t firstNode; + uint32_t dataSize; + char data[0]; +} ParamTrieHeader; + +typedef struct WorkSpace_ { + unsigned int flags; + MemHandle memHandle; + ParamTrieHeader *area; + ATOMIC_UINT32 rwSpaceLock; + uint32_t spaceSize; + uint32_t spaceIndex; + ParamRWMutex rwlock; + char fileName[0]; +} WorkSpace; + +typedef struct CachedParameter_ { + struct WorkSpace_ *workspace; + const char *(*cachedParameterCheck)(struct CachedParameter_ *param, int *changed); + long long spaceCommitId; + uint32_t dataCommitId; + uint32_t dataIndex; + uint32_t bufferLen; + uint32_t nameLen; + char *paramValue; + char data[0]; +} CachedParameter; + +typedef void *CachedHandle; +#endif +/** + * parameter client init + */ +void InitParameterClient(void); + +/** + * by name and default value,save parameter info in handle。 + * + */ +CachedHandle CachedParameterCreate(const char *name, const char *defValue); + +/** + * destroy handle + * + */ +void CachedParameterDestroy(CachedHandle handle); + +/** + * if name exist,return value else return default value + * + */ +static inline const char *CachedParameterGet(CachedHandle handle) +{ + struct CachedParameter_ *param = (struct CachedParameter_ *)handle; + if (param == NULL) { + return NULL; + } + + // no change, do not to find + long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(¶m->workspace->area->commitId, MEMORY_ORDER_ACQUIRE); + if (param->spaceCommitId == spaceCommitId) { + return param->paramValue; + } + param->spaceCommitId = spaceCommitId; + int changed = 0; + if (param->cachedParameterCheck == NULL) { + return param->paramValue; + } + return param->cachedParameterCheck(param, &changed); +} + +static inline const char *CachedParameterGetChanged(CachedHandle handle, int *changed) +{ + struct CachedParameter_ *param = (struct CachedParameter_ *)handle; + if (param == NULL) { + return NULL; + } + // no change, do not to find + long long spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(¶m->workspace->area->commitId, MEMORY_ORDER_ACQUIRE); + if (param->spaceCommitId == spaceCommitId) { + return param->paramValue; + } + param->spaceCommitId = spaceCommitId; + if ((changed == NULL) || (param->cachedParameterCheck == NULL)) { + return param->paramValue; + } + return param->cachedParameterCheck(param, changed); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/service_control.h b/interfaces/innerkits/include/service_control.h new file mode 100644 index 0000000000000000000000000000000000000000..ada09cbf0cc6174ef4c94652f224f5b961883266 --- /dev/null +++ b/interfaces/innerkits/include/service_control.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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 BEGET_UTILS_API_H +#define BEGET_UTILS_API_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define STARTUP_SERVICE_CTL "startup.service.ctl" + +typedef enum { + SERVICE_IDLE = 0, // service add + SERVICE_STARTING, // service start + SERVICE_STARTED, // 2 service ok running + SERVICE_READY, // 3 service ok running + SERVICE_STOPPING, + SERVICE_STOPPED, // 5 + SERVICE_ERROR, + SERVICE_SUSPENDED, + SERVICE_FREEZED, + SERVICE_DISABLED, + SERVICE_CRITICAL +} ServiceStatus; + +enum ServiceAction { + START = 0, + STOP = 1, + RESTART = 2, +}; + +int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc); +int ServiceControl(const char *serviceName, int action); +int ServiceWaitForStatus(const char *serviceName, ServiceStatus status, int waitTimeout); +int ServiceSetReady(const char *serviceName); +int StartServiceByTimer(const char *serviceName, uint64_t timeout); +int StopServiceTimer(const char *serviceName); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/services/param/include/trigger_processor.h b/interfaces/innerkits/include/service_watcher.h similarity index 64% rename from services/param/include/trigger_processor.h rename to interfaces/innerkits/include/service_watcher.h index fc9a5e89e29a3dfcba0aae7918e1397b59a3e3b5..bae424886d50250bdbd366489af46016315f6504 100644 --- a/services/param/include/trigger_processor.h +++ b/interfaces/innerkits/include/service_watcher.h @@ -1,49 +1,44 @@ -/* - * Copyright (c) 2021 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_EVENT_MANAGER_H -#define BASE_STARTUP_EVENT_MANAGER_H - -#include - -#include "sys_param.h" -#include "init_param.h" -#include "trigger_manager.h" -#include "uv.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -typedef struct TriggerEvent { - uv_work_t request; - EventType type; -} TriggerEvent; - -typedef struct { - uv_work_t request; - EventType type; - u_int32_t contentSize; - char content[0]; -} TriggerDataEvent; - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif -#endif \ No newline at end of file +/* + * Copyright (c) 2021 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 SERVICE_WATCH_API_H +#define SERVICE_WATCH_API_H + +#include +#include "init_param.h" +#include "service_control.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define INVALID_PID 0 + +typedef struct { + ServiceStatus status; + pid_t pid; +} ServiceInfo; + +typedef void (*ServiceStatusChangePtr)(const char *key, const ServiceInfo *serviceInfo); +int ServiceWatchForStatus(const char *serviceName, ServiceStatusChangePtr changeCallback); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/include/syspara/param_wrapper.h b/interfaces/innerkits/include/syspara/param_wrapper.h new file mode 100755 index 0000000000000000000000000000000000000000..c9b197f00d0b65a8c5c9720c4e2bddafdd5e0c14 --- /dev/null +++ b/interfaces/innerkits/include/syspara/param_wrapper.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021-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 PARAM_WRAPPER_H +#define PARAM_WRAPPER_H + +#include + +namespace OHOS { +namespace system { +int GetStringParameter(const std::string &key, std::string &value, const std::string def = ""); +int GetIntParameter(const std::string &key, int def); +} +} + +#endif // PARAM_WRAPPER_H diff --git a/interfaces/innerkits/include/syspara/parameter.h b/interfaces/innerkits/include/syspara/parameter.h new file mode 100644 index 0000000000000000000000000000000000000000..c99f39f811e0fd1799c7ff6f514f95bf68a7f74c --- /dev/null +++ b/interfaces/innerkits/include/syspara/parameter.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2021-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 STARTUP_SYSPARAM_PARAMETER_API_H +#define STARTUP_SYSPARAM_PARAMETER_API_H +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define PARAM_CONST_VALUE_LEN_MAX 4096 +#define PARAM_VALUE_LEN_MAX 96 +#define PARAM_NAME_LEN_MAX 96 +#define OS_FULL_NAME_LEN 128 +#define VERSION_ID_MAX_LEN 256 +#define PARAM_BUFFER_MAX (0x01 << 16) + +static const char EMPTY_STR[] = { "" }; + +/** + * @brief Obtains a system parameter matching the specified key. + * + * If no system parameter is found, the def parameter will be returned.\n + * + * @param key Indicates the key for the system parameter to query. + * The value can contain lowercase letters, digits, underscores (_), and dots (.). + * Its length cannot exceed 32 bytes (including the end-of-text character in the string). + * @param def Indicates the default value to return when no query result is found. + * This parameter is specified by the caller. + * @param value Indicates the data buffer that stores the query result. + * This parameter is applied for and released by the caller and can be used as an output parameter. + * @param len Indicates the length of the data in the buffer. + * @return Returns the number of bytes of the system parameter if the operation is successful; + * returns -9 if a parameter is incorrect; returns -1 in other scenarios. + * @since 1 + * @version 1 + */ +int GetParameter(const char *key, const char *def, char *value, uint32_t len); + +/** + * @brief Sets or updates a system parameter. + * + * You can use this function to set a system parameter that matches key as value.\n + * + * @param key Indicates the key for the parameter to set or update. + * The value can contain lowercase letters, digits, underscores (_), and dots (.). + * Its length cannot exceed 32 bytes (including the end-of-text character in the string). + * @param value Indicates the system parameter value. + * Its length cannot exceed 128 bytes (including the end-of-text character in the string). + * @return Returns 0 if the operation is successful; + * returns -9 if a parameter is incorrect; returns -1 in other scenarios. + * @since 1 + * @version 1 + */ +int SetParameter(const char *key, const char *value); + +/** + * @brief Wait for a system parameter with specified value. + * + * You can use this function to wait a system parameter that matches key as value.\n + * + * @param key Indicates the key for the parameter to wait. + * The value can contain lowercase letters, digits, underscores (_), and dots (.). + * Its length cannot exceed 96 bytes (including the end-of-text character in the string). + * @param value Indicates the system parameter value. + * Its length cannot exceed 96 bytes (including the end-of-text character in the string). + * value can use "*" to do arbitrary match. + * @param timeout Indicates the timeout value, in seconds. + * <=0 means wait for ever. + * >0 means wait for specified seconds + * @return Returns 0 if the operation is successful; + * returns -10 if timeout; returns -1 in other scenarios. + * @since 1.1 + * @version 1.1 + */ +int WaitParameter(const char *key, const char *value, int timeout); + +/** + * @brief Watch for system parameter values. + * + * You can use this function to watch system parameter values.\n + * + * @param keyPrefix Indicates the key prefix for the parameter to be watched. + * If keyPrefix is not a full name, "A.B." for example, it means to watch for all parameter started with "A.B.". + * @param callback Indicates value change callback. + * If callback is NULL, it means to cancel the watch. + * @return Returns 0 if the operation is successful; + * returns -1 in other scenarios. + * @since 1.1 + * @version 1.1 + */ +typedef void (*ParameterChgPtr)(const char *key, const char *value, void *context); +int WatchParameter(const char *keyPrefix, ParameterChgPtr callback, void *context); + +/** + * @brief Remove parameter watcher. + * + * You can use this function to remove system parameter watcher.\n + * + * @param keyPrefix Indicates the key prefix for the parameter to be watched. + * If keyPrefix is not a full name, "A.B." for example, it means to watch for all parameter started with "A.B.". + * @param callback Indicates value change callback. + * If callback is NULL, it means to cancel the watch. + * @return Returns 0 if the operation is successful; + * returns -1 in other scenarios. + * @since 1.1 + * @version 1.1 + */ +int RemoveParameterWatcher(const char *keyPrefix, ParameterChgPtr callback, void *context); + +/** + * @brief Synchronize saving persistent parameters. + * + * You can use this function to save system parameter in shared memory immediately.\n + * + * @return Returns 0 if the operation is successful; + * returns -1 in other scenarios. + * @since 4.1 + * @version 4.1 +*/ +int SaveParameters(void); +const char *GetSecurityPatchTag(void); +const char *GetOSFullName(void); +const char *GetVersionId(void); +const char *GetBuildRootHash(void); +const char *GetOsReleaseType(void); +int GetSdkApiVersion(void); + +const char *GetDeviceType(void); +const char *GetProductModel(void); +const char *GetProductModelAlias(void); +const char *GetManufacture(void); +const char *GetBrand(void); +const char *GetMarketName(void); +const char *GetProductSeries(void); +const char *GetSoftwareModel(void); +const char *GetHardwareModel(void); +const char *GetHardwareProfile(void); +const char *GetSerial(void); +const char *GetAbiList(void); +const char *GetDisplayVersion(void); +const char *GetIncrementalVersion(void); +const char *GetBootloaderVersion(void); +const char *GetBuildType(void); +const char *GetBuildUser(void); +const char *GetBuildHost(void); +const char *GetBuildTime(void); +int GetFirstApiVersion(void); +int GetDevUdid(char *udid, int size); + +const char *AclGetSerial(void); +int AclGetDevUdid(char *udid, int size); + +/** + * @brief Obtains a system parameter matching the specified key. + * + * If no system parameter is found, return -1.\n + * + * @param key Indicates the key for the system parameter to find. + * @return Returns the index for parameter; + * returns handle if a parameter is correct; returns -1 in other scenarios. + * @since 1 + * @version 1 + */ +uint32_t FindParameter(const char *key); +uint32_t GetParameterCommitId(uint32_t handle); +int GetParameterName(uint32_t handle, char *key, uint32_t len); +int GetParameterValue(uint32_t handle, char *value, uint32_t len); +long long GetSystemCommitId(void); + +int32_t GetIntParameter(const char *key, int32_t def); +uint32_t GetUintParameter(const char *key, uint32_t def); + +const char *GetDistributionOSName(void); +const char *GetDistributionOSVersion(void); +int GetDistributionOSApiVersion(void); +const char *GetDistributionOSApiName(void); +const char *GetDistributionOSReleaseType(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // STARTUP_SYSPARAM_PARAMETER_API_H diff --git a/interfaces/innerkits/include/syspara/parameters.h b/interfaces/innerkits/include/syspara/parameters.h new file mode 100755 index 0000000000000000000000000000000000000000..9aa0a68011321355d7112d3ea2358eb89b969d06 --- /dev/null +++ b/interfaces/innerkits/include/syspara/parameters.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021-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 SYSTEM_PARAMETERS_H +#define SYSTEM_PARAMETERS_H + +#include +#include + +namespace OHOS { +namespace system { +/* + * Returns the current value of the system parameter `key`. + * If the parameter is empty or doesn't exist, `def` will be returned. + */ +std::string GetParameter(const std::string& key, const std::string& def); + +/* + * Returns true if the system parameter `key` has the value "1", "y", "yes", "on", or "true", + * false for "0", "n", "no", "off", or "false", or `def` otherwise. + */ +bool GetBoolParameter(const std::string& key, bool def); + +/* + * Returns the signed integer corresponding to the system parameter `key`. + * If the parameter is empty, doesn't exist, doesn't have an integer value, or is outside + * the optional bounds, returns `def`. + */ +template +T GetIntParameter(const std::string& key, T def, T min = std::numeric_limits::min(), + T max = std::numeric_limits::max()); + +/* + * Returns the unsigned integer corresponding to the system parameter `key`. + * If the parameter is empty, doesn't exist, doesn't have an integer value, or is outside + * the optional bound, returns `def`. + */ +template +T GetUintParameter(const std::string& key, T def, T max = std::numeric_limits::max()); + +/* + * Sets the system parameter `key` to `value`. + * Note that system parameter setting is inherently asynchronous so a return value of `true` + * isn't particularly meaningful, and immediately reading back the value won't necessarily + * tell you whether or not your call succeeded. A `false` return value definitely means failure. + */ +bool SetParameter(const std::string& key, const std::string& value); + +/* + * Obtains the device type of your product represented by a string. + */ +std::string GetDeviceType(void); +} // namespace system +} // namespace OHOS + +#endif // SYSTEM_PARAMETERS_H \ No newline at end of file diff --git a/interfaces/innerkits/include/syspara/sysparam_errno.h b/interfaces/innerkits/include/syspara/sysparam_errno.h new file mode 100755 index 0000000000000000000000000000000000000000..54fd08ae3c0438ffde0234b384925d04b6f3cefd --- /dev/null +++ b/interfaces/innerkits/include/syspara/sysparam_errno.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-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 OHOS_STARTUP_SYSPARAM_ERRNO_H +#define OHOS_STARTUP_SYSPARAM_ERRNO_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ +/* --------------------------------------------------------------------------------------------* + * Definition of error code. The error codes are applicable to both the application and kernel + * -------------------------------------------------------------------------------------------- */ +enum OHOSStartUpSysParamErrorCode { + EC_SUCCESS = 0, /* OK or No error */ + EC_FAILURE = -1, /* Execution failed */ + EC_INVALID = -9, /* Invalid argument */ + EC_SYSTEM_ERR = -10, /* system error */ + + SYSPARAM_INVALID_INPUT = -401, /* Input parameter is missing or invalid */ + SYSPARAM_NOT_FOUND = -14700101, /* System parameter can not be found. */ + SYSPARAM_INVALID_VALUE = -14700102, /* System parameter value is invalid */ + SYSPARAM_PERMISSION_DENIED = -14700103, /* System permission operation permission denied */ + SYSPARAM_SYSTEM_ERROR = -14700104, /* System internal error including out of memory, deadlock etc. */ + SYSPARAM_WAIT_TIMEOUT = -14700105, /* System wait parameter value change time out. */ +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ +#endif // OHOS_STARTUP_SYSPARAM_ERRNO_H diff --git a/interfaces/innerkits/include/syspara/sysversion.h b/interfaces/innerkits/include/syspara/sysversion.h new file mode 100755 index 0000000000000000000000000000000000000000..c2153abf9447766de6fb65bfd1a8bae2db86915b --- /dev/null +++ b/interfaces/innerkits/include/syspara/sysversion.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-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 STARTUP_SYSVERSION_API_H +#define STARTUP_SYSVERSION_API_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +int GetMajorVersion(void); +int GetSeniorVersion(void); +int GetFeatureVersion(void); +int GetBuildVersion(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // STARTUP_SYSVERSION_API_H diff --git a/interfaces/innerkits/include/systemcapability.h b/interfaces/innerkits/include/systemcapability.h new file mode 100644 index 0000000000000000000000000000000000000000..b8d5fb0c86066cadb2329df1f50234180294722b --- /dev/null +++ b/interfaces/innerkits/include/systemcapability.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 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 INIT_SYSCAP_API_H +#define INIT_SYSCAP_API_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + + +bool HasSystemCapability(const char *cap); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/include/token/token.h b/interfaces/innerkits/include/token/token.h new file mode 100755 index 0000000000000000000000000000000000000000..152953611fe5d72c04c19a4466b042d7e6ff7c8e --- /dev/null +++ b/interfaces/innerkits/include/token/token.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 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 TOKEN_H +#define TOKEN_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +/** + * @brief Read token value form device. + * + * @param token The token value, len The token len. + * @returns 0 if it succeeds and get the update area token, + * 1 if it succeeds and get the pre-made token, + * -1 if it fails, -2 if it no pre-made token. + */ +int ReadToken(char *token, unsigned int len); + +/** + * @brief Write token value to device. + * + * @param token The token value, len The token len. + * @returns 0 if it succeeds, -1 if it fails. + */ +int WriteToken(const char *token, unsigned int len); + +/** + * @brief Get AcKey value form device. + * + * @param acKey The acKey value, len The acKey len. + * @returns 0 if it succeeds, -1 if it fails. + */ +int GetAcKey(char *acKey, unsigned int len); + +/** + * @brief Get ProdId value form device. + * + * @param productId The productId value, len The productId len. + * @returns 0 if it succeeds, -1 if it fails. + */ +int GetProdId(char *productId, unsigned int len); + +/** + * @brief Get ProdKey value form device. + * + * @param productKey The productKey value, len The productKey len. + * @returns 0 if it succeeds, -1 if it fails. + */ +int GetProdKey(char *productKey, unsigned int len); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // TOKEN_H \ No newline at end of file diff --git a/interfaces/innerkits/init_module_engine/BUILD.gn b/interfaces/innerkits/init_module_engine/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..da4f9db69cf4c7d93b4369ff34509f19f80ce720 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/BUILD.gn @@ -0,0 +1,103 @@ +# Copyright (c) 2021 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. + +if (defined(ohos_lite)) { + group("libinit_module_engine") { + } +} else { + import("//build/ohos.gni") + import("//build/ohos/native_stub/native_stub.gni") + + # + # exported include directories + # + config("init_module_engine_exported_config") { + visibility = [ ":*" ] + visibility += [ "./../../../services/*" ] + include_dirs = [ + "include/", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + ] + if (ohos_indep_compiler_enable) { + include_dirs += + [ "//binarys/third_party/cJSON/innerapis/cjson_static/includes" ] + } else { + include_dirs += [ "//third_party/cJSON" ] + } + } + + # + # innerkits for module development + # + ohos_native_stub_library("libinit_module_engine") { + cflags = [ "-fstack-protector-all" ] + output_extension = "so" + public_configs = [ ":init_module_engine_exported_config" ] + stub_description_file = "./stub/libinit.stub.json" + } + + # + # For init linking, + # export symbols defined in this json files only + # + ohos_native_stub_versionscript("libinit_stub_versionscript") { + stub_description_file = "./stub/libinit.stub.json" + } + + # + # Generate empty library with symlink name to satisfy init loading required libraries + # + ohos_native_stub_library("libinit_stub_empty") { + cflags = [ "-fstack-protector-all" ] + output_extension = "so" + stub_description_file = "./stub/libinit.stub.empty.json" + part_name = "init" + subsystem_name = "startup" + install_enable = true + install_images = [ + "system", + "updater", + "ramdisk", + ] + symlink_target_name = [ "libinit_module_engine.so" ] + } + + config("init_module_engine_sources_config") { + include_dirs = [ + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/log", + ] + } + + ohos_source_set("init_module_engine_sources") { + sources = [ "init_modulemgr.c" ] + public_configs = [ ":init_module_engine_sources_config" ] + external_deps = [ "cJSON:cjson" ] + } +} + +# +# init module engine all modules +# +group("modulegroup") { + if (!defined(ohos_lite)) { + deps = [ + ":libinit_module_engine", + ":libinit_stub_empty", + ] + } +} diff --git a/interfaces/innerkits/init_module_engine/include/bootstage.h b/interfaces/innerkits/init_module_engine/include/bootstage.h new file mode 100755 index 0000000000000000000000000000000000000000..98ec2787713138e685e6d354a15e14ec1c16d0ef --- /dev/null +++ b/interfaces/innerkits/init_module_engine/include/bootstage.h @@ -0,0 +1,260 @@ +/* + * 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_BOOTSTAGE_H +#define BASE_STARTUP_BOOTSTAGE_H + +#include "hookmgr.h" +#include "cJSON.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +enum INIT_BOOTSTAGE { + INIT_GLOBAL_INIT = 0, + INIT_FIRST_STAGE = 1, + INIT_MOUNT_STAGE = 3, + INIT_RESTORECON = 4, + INIT_POST_DATA_UNENCRYPT = 5, + INIT_PRE_PARAM_SERVICE = 10, + INIT_PRE_PARAM_LOAD = 20, + INIT_PARAM_LOAD_FILTER = 25, + INIT_PRE_CFG_LOAD = 30, + INIT_SERVICE_PARSE = 35, + INIT_POST_PERSIST_PARAM_LOAD = 40, + INIT_POST_CFG_LOAD = 50, + INIT_CMD_RECORD = 51, + INIT_REBOOT = 55, + INIT_SERVICE_CLEAR = 56, + INIT_SERVICE_DUMP = 57, + INIT_SERVICE_FORK_BEFORE = 58, + INIT_SERVICE_SET_PERMS_BEFORE = 59, + INIT_SERVICE_SET_PERMS = 60, + INIT_SERVICE_FORK_AFTER = 61, + INIT_SERVICE_BOOTEVENT = 62, + INIT_SERVICE_REAP = 65, + INIT_SHUT_DETECTOR = 66, + INIT_ALL_SERVICES_REAP = 67, + INIT_SERVICE_RESTART = 71, + INIT_JOB_PARSE = 70, + INIT_BOOT_COMPLETE = 100, +}; + +HOOK_MGR *GetBootStageHookMgr(); + +__attribute__((always_inline)) inline int InitAddGlobalInitHook(int prio, OhosHook hook) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_GLOBAL_INIT, prio, hook); +} + +__attribute__((always_inline)) inline int InitAddPreParamServiceHook(int prio, OhosHook hook) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, prio, hook); +} + +__attribute__((always_inline)) inline int InitAddPreParamLoadHook(int prio, OhosHook hook) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, prio, hook); +} + +/** + * @brief Parameter load filter context + */ +typedef struct tagPARAM_LOAD_FILTER_CTX { + const char *name; /* Parameter name */ + const char *value; /* Parameter value */ + int ignored; /* Ignore this parameter or not */ +} PARAM_LOAD_FILTER_CTX; + +/** + * @brief Parameter Load Hook function prototype + * + * @param hookInfo hook information + * @param filter filter information context + * @return return 0 if succeed; other values if failed. + */ +typedef int (*ParamLoadFilter)(const HOOK_INFO *hookInfo, PARAM_LOAD_FILTER_CTX *filter); + +__attribute__((always_inline)) inline int InitAddParamLoadFilterHook(int prio, ParamLoadFilter filter) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, prio, (OhosHook)filter); +} + +__attribute__((always_inline)) inline int InitAddPreCfgLoadHook(int prio, OhosHook hook) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, prio, hook); +} + +__attribute__((always_inline)) inline int InitAddPostCfgLoadHook(int prio, OhosHook hook) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, prio, hook); +} + +__attribute__((always_inline)) inline int InitAddPostPersistParamLoadHook(int prio, OhosHook hook) +{ + return HookMgrAdd(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, prio, hook); +} + +/** + * @brief service config parsing context information + */ +typedef struct tagSERVICE_PARSE_CTX { + const char *serviceName; /* Service name */ + const cJSON *serviceNode; /* Service JSON node */ +} SERVICE_PARSE_CTX; + +/** + * @brief job config parsing context information + */ +typedef struct tagJOB_PARSE_CTX { + const char *jobName; /* job name */ + const cJSON *jobNode; /* job JSON node */ +} JOB_PARSE_CTX; + +/** + * @brief service info + */ +typedef struct tagSERVICE_INFO_CTX { + const char *serviceName; /* Service name */ + const char *reserved; /* reserved info */ +} SERVICE_INFO_CTX; + +/** + * @brief service info + */ +typedef struct tagSERVICE_BOOTEVENT_CTX { + const char *serviceName; /* Service name */ + const char *reserved; /* reserved info */ + int state; /* bootevent state */ +} SERVICE_BOOTEVENT_CTX; + +/** + * @brief service restart info + */ +typedef struct tagSERVICE_RESTART_CTX { + const char *serviceName; /* Service name */ + const char *serviceNode; /* Service node */ +} SERVICE_RESTART_CTX; + +/** + * @brief init cmd info + */ +typedef struct InitCmdInfo { + const char *cmdName; /* cmd name */ + const char *cmdContent; /* cmd content */ + const char *reserved; /* reserved info */ +} INIT_CMD_INFO; + +/** + * @brief service config parse hook function prototype + * + * @param serviceParseCtx service config parsing context information + * @return None + */ +typedef void (*ServiceParseHook)(SERVICE_PARSE_CTX *serviceParseCtx); + +/** + * @brief job config parse hook function prototype + * + * @param JobParseHook job config parsing context information + * @return None + */ +typedef void (*JobParseHook)(JOB_PARSE_CTX *jobParseCtx); + +/** + * @brief service hook function prototype + * + * @param ServiceHook service info + * @return None + */ +typedef void (*ServiceHook)(SERVICE_INFO_CTX *serviceCtx); + +/** + * @brief service restart hook function prototype + * + * @param ServiceRestartHook service info + * @return None + */ +typedef void (*ServiceRestartHook) (SERVICE_RESTART_CTX *serviceRestartCtx); + +/** + * @brief Register a hook for service config parsing + * + * @param hook service config parsing hook + * in the hook, we can parse extra fields in the config file. + * @return return 0 if succeed; other values if failed. + */ +int InitAddServiceParseHook(ServiceParseHook hook); + +/** + * @brief service config parsing context information + */ +typedef struct tagReboot { + char *reason; +} RebootHookCtx; + +/** + * @brief service config parse hook function prototype + * + * @param serviceParseCtx service config parsing context information + * @return None + */ +typedef void (*InitRebootHook)(RebootHookCtx *ctx); +/** + * @brief Register a hook for reboot + * + * @param hook + * + * @return return 0 if succeed; other values if failed. + */ +int InitAddRebootHook(InitRebootHook hook); + +/** + * @brief Register a hook for job config parsing + * + * @param hook job config parsing hook + * in the hook, we can parse extra fields in the config file. + * @return return 0 if succeed; other values if failed. + */ +int InitAddJobParseHook(JobParseHook hook); + +/** + * @brief Register a hook for service + * + * @param hook service hook + * in the hook, we can get service. + * @param hookState init boot state + * @return return 0 if succeed; other values if failed. + */ +int InitAddServiceHook(ServiceHook hook, int hookState); + +/** + * @brief Register a hook for service restart + * + * @param hook service restart hook + * in the hook, we can get service. + * @return return 0 if succeed; other values if failed. + */ +int InitServiceRestartHook(ServiceRestartHook hook, int hookState); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/services/param/include/param_request.h b/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h similarity index 47% rename from services/param/include/param_request.h rename to interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h index d2ed318d6b17c3583b863d2e1f69ac48c2412ea7..89b1859573cb4c315ed4661980e8c56c9753ffb6 100644 --- a/services/param/include/param_request.h +++ b/interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,57 +12,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef STARTUP_INIT_CMD_EXECUTOR_H +#define STARTUP_INIT_CMD_EXECUTOR_H +#include +#include -#ifndef BASE_STARTUP_PARAM_REQUEST_H -#define BASE_STARTUP_PARAM_REQUEST_H +#include "list.h" -#include -#include "sys_param.h" -#include "param_manager.h" - -#include "uv.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -typedef enum RequestType { - SET_PARAM, - GET_PARAM, -} RequestType; - typedef struct { - ParamSecurityLabel securitylabel; - RequestType type; - int contentSize; - char content[0]; -} RequestMsg; + ListNode cmdExecutor; + int cmdId; + unsigned char careContext; + char *name; +} PluginCmd; +typedef int (*CmdExecutor)(int id, const char *name, int argc, const char **argv); typedef struct { - RequestType type; - int result; - int contentSize; - char content[0]; -} ResponseMsg; + ListNode node; + int id; + CmdExecutor execCmd; +} PluginCmdExecutor; -typedef struct { - uv_loop_t *loop; - uv_connect_t connect; - uv_pipe_t handle; - uv_write_t wr; - int result; - RequestMsg msg; -} RequestNode; +void PluginExecCmdByName(const char *name, const char *cmdContent); +// only exec in current context +int PluginExecCmd(const char *name, int argc, const char **argv); -typedef struct { - uv_write_t writer; - ResponseMsg msg; -} ResponseNode; +int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd); + +int AddRebootCmdExecutor(const char *cmd, CmdExecutor executor); #ifdef __cplusplus #if __cplusplus } #endif #endif -#endif \ No newline at end of file +#endif diff --git a/services/include/init_signal_handler.h b/interfaces/innerkits/init_module_engine/include/init_filesystems.h old mode 100644 new mode 100755 similarity index 63% rename from services/include/init_signal_handler.h rename to interfaces/innerkits/init_module_engine/include/init_filesystems.h index 433d4f99a696b8967a4aaa75447de37e18413aed..f79b7c37237a8ffc2d69294cb91fa8431477d9c0 --- a/services/include/init_signal_handler.h +++ b/interfaces/innerkits/init_module_engine/include/init_filesystems.h @@ -1,42 +1,36 @@ -/* - * Copyright (c) 2020 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_SIGNAL_HANDLE_H -#define BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H - -#ifdef __LINUX__ -#include -#include -#endif - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -void SignalInitModule(); - -#ifdef __LINUX__ -void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem); -#endif - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif - -#endif // BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H +/* + * Copyright (c) 2023 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 STARTUP_INIT_SUPPORTED_FILE_SYSTEMS_H +#define STARTUP_INIT_SUPPORTED_FILE_SYSTEMS_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct tagSUPPORTED_FILE_SYSTEM { + const char *fs_name; + int for_userdata; +} SUPPORTED_FILE_SYSTEM; + +void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[]); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/init_module_engine/include/init_module_engine.h b/interfaces/innerkits/init_module_engine/include/init_module_engine.h new file mode 100755 index 0000000000000000000000000000000000000000..8a1bd582f3a7e9e7bd3a6960055231e5267239a1 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/include/init_module_engine.h @@ -0,0 +1,54 @@ +/* + * 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_INIT_PLUGIN_H +#define BASE_STARTUP_INIT_PLUGIN_H +#include +#include +#include +#include "modulemgr.h" +#include "bootstage.h" +#include "init_modulemgr.h" +#include "init_cmdexecutor.h" +#include "init_running_hooks.h" +#include "init_filesystems.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int SystemWriteParam(const char *name, const char *value); + +int SystemReadParam(const char *name, char *value, unsigned int *len); + +int LoadParamsFile(const char *fileName, bool onlyAdd); + +typedef int (*CmdExecutor)(int id, const char *name, int argc, const char **argv); + +int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd); + +void RemoveCmdExecutor(const char *cmdName, int id); + +int DoJobNow(const char *jobName); + +int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_INIT_PLUGIN_H diff --git a/interfaces/innerkits/init_module_engine/include/init_modulemgr.h b/interfaces/innerkits/init_module_engine/include/init_modulemgr.h new file mode 100755 index 0000000000000000000000000000000000000000..ee528857cbb1f3ba171afc3029f2d2026d621781 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/include/init_modulemgr.h @@ -0,0 +1,40 @@ +/* + * 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_INIT_MODULEMGR_H +#define BASE_STARTUP_INIT_MODULEMGR_H + +#include "modulemgr.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int InitModuleMgrInstall(const char *moduleName); + +void InitModuleMgrUnInstall(const char *moduleName); + +void AutorunModuleMgrUnInstall(const char *moduleName); + +void InitModuleMgrDump(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/init_module_engine/include/init_running_hooks.h b/interfaces/innerkits/init_module_engine/include/init_running_hooks.h new file mode 100755 index 0000000000000000000000000000000000000000..522d4e89094623e8753a41626809a70fc31ac7ee --- /dev/null +++ b/interfaces/innerkits/init_module_engine/include/init_running_hooks.h @@ -0,0 +1,68 @@ +/* + * 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_BOOT_RUNNING_HOOKS_H +#define BASE_STARTUP_BOOT_RUNNING_HOOKS_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * @brief Running hook stage definition for init + */ +/* Hook stage for setting parameters */ +#define INIT_PARAM_SET_HOOK_STAGE 0 + +/** + * @brief parameter setting context information + */ +typedef struct tagPARAM_SET_CTX { + const char *name; /* Parameter name */ + const char *value; /* Parameter value */ + + /* Skip setting parameter if true + * When setting parameters, parameter service will save the the value by default + * If set skipParamSet in the hook, parameter service will not save + */ + int skipParamSet; +} PARAM_SET_CTX; + +/** + * @brief set parameter hook function prototype + * + * @param paramSetCtx parameter setting context information + * @return None + */ +typedef void (*ParamSetHook)(PARAM_SET_CTX *paramSetCtx); + +/** + * @brief Register a hook for setting parameters + * + * @param hook parameter setting hook + * in the hook, we can match the parameters with special patterns to do extra controls. + * For example, ohos.ctl.start will control services besides the normal parameter saving. + * @return return 0 if succeed; other values if failed. + */ +int ParamSetHookAdd(ParamSetHook hook); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/init_module_engine/init_modulemgr.c b/interfaces/innerkits/init_module_engine/init_modulemgr.c new file mode 100644 index 0000000000000000000000000000000000000000..76b6af802db6254729fc13ab0e59c495ac710450 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/init_modulemgr.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020-2021 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 "init_log.h" +#include "init_module_engine.h" +#include "loop_event.h" + +static MODULE_MGR *defaultModuleMgr = NULL; +static MODULE_MGR *autorunModuleMgr = NULL; + +int InitModuleMgrInstall(const char *moduleName) +{ + if (moduleName == NULL) { + return -1; + } + + if (defaultModuleMgr == NULL) { + defaultModuleMgr = ModuleMgrCreate("init"); + } + if (defaultModuleMgr == NULL) { + return -1; + } + + return ModuleMgrInstall(defaultModuleMgr, moduleName, 0, NULL); +} + +void InitModuleMgrUnInstall(const char *moduleName) +{ + ModuleMgrUninstall(defaultModuleMgr, moduleName); +} + +static void DelayedUninstall(const IdleHandle taskHandle, void *context) +{ + const char *moduleName = (const char *)context; + if (moduleName == NULL) { + return; + } + ModuleMgrUninstall(autorunModuleMgr, moduleName); +} + +void AutorunModuleMgrUnInstall(const char *moduleName) +{ + void *context = (void *)strdup(moduleName); + if (context == NULL) { + return; + } + LE_DelayProc(LE_GetDefaultLoop(), DelayedUninstall, context); +} + +static void InitModuleDump(const MODULE_INFO *moduleInfo) +{ + printf("%s\n", moduleInfo->name); +} + +void InitModuleMgrDump(void) +{ + if (defaultModuleMgr != NULL) { + ModuleMgrTraversal(defaultModuleMgr, NULL, InitModuleDump); + } + + if (autorunModuleMgr != NULL) { + ModuleMgrTraversal(autorunModuleMgr, NULL, InitModuleDump); + } +} + +static int ModuleMgrCmdInstall(int id, const char *name, int argc, const char **argv) +{ + INIT_ERROR_CHECK(argv != NULL && argc >= 1, return -1, "Invalid install parameter"); + int ret; + if (defaultModuleMgr == NULL) { + defaultModuleMgr = ModuleMgrCreate("init"); + } + ret = ModuleMgrInstall(defaultModuleMgr, argv[0], argc-1, argv+1); + INIT_ERROR_CHECK(ret == 0, return ret, "Install module %s fail errno %d", argv[0], ret); + return 0; +} + +static int ModuleMgrCmdUninstall(int id, const char *name, int argc, const char **argv) +{ + INIT_ERROR_CHECK(argv != NULL && argc >= 1, return -1, "Invalid install parameter"); + ModuleMgrUninstall(defaultModuleMgr, argv[0]); + return 0; +} + +static int moduleMgrCommandsInit(const HOOK_INFO *info, void *cookie) +{ + // "ohos.servicectrl.install" + (void)AddCmdExecutor("install", ModuleMgrCmdInstall); + (void)AddCmdExecutor("uninstall", ModuleMgrCmdUninstall); + // read cfg and start static plugin + return 0; +} + +static int loadAutorunModules(const HOOK_INFO *info, void *cookie) +{ + autorunModuleMgr = ModuleMgrScan("init/autorun"); + INIT_LOGV("Load autorun modules return autorunModuleMgr"); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + // Depends on parameter service + InitAddGlobalInitHook(0, loadAutorunModules); + InitAddPreCfgLoadHook(0, moduleMgrCommandsInit); +} diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.empty.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.empty.json new file mode 100755 index 0000000000000000000000000000000000000000..0d4f101c7a37a4c875e6999bee1a287fdb733380 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.empty.json @@ -0,0 +1,2 @@ +[ +] diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json new file mode 100644 index 0000000000000000000000000000000000000000..b51c09d9009ef4744aacf3beb9ae87f21d4fccc6 --- /dev/null +++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json @@ -0,0 +1,95 @@ +[ + { "name": "SystemWriteParam" }, + { "name": "SystemReadParam" }, + { "name": "LoadParamsFile" }, + { "name": "LoadPersistParams" }, + { "name": "SplitString" }, + { "name": "AddCmdExecutor" }, + { "name": "GetServiceByName"}, + { "name": "RemoveCmdExecutor" }, + { "name": "HookMgrAdd" }, + { "name": "HookMgrAddEx" }, + { "name": "HookMgrDel" }, + { "name": "GetBootStageHookMgr"}, + { "name": "InitAddGlobalInitHook" }, + { "name": "InitAddPreParamServiceHook" }, + { "name": "InitAddPreParamLoadHook" }, + { "name": "InitAddPreCfgLoadHook" }, + { "name": "InitAddPostCfgLoadHook" }, + { "name": "InitModuleMgrInstall" }, + { "name": "InitModuleMgrUnInstall" }, + { "name": "InitSetExtendedFileSystems" }, + { "name": "AutorunModuleMgrUnInstall" }, + { "name": "StartupLog" }, + { "name": "DoJobNow" }, + { "name": "GetServiceExtData" }, + { "name": "UpdateMiscMessage" }, + { "name": "AddRebootCmdExecutor" }, + { "name": "GetBootEventList" }, + { "name": "WaitForFile" }, + { "name": "DoCmdByIndex" }, + { "name": "GetMatchCmd" }, + { "name": "AddCareContextCmdExecutor" }, + { "name": "GetParameterFromCmdLine" }, + { "name": "InitSubInitContext" }, + { "name": "ExecReboot" }, + { "name": "LE_AcceptStreamClient" }, + { "name": "LE_AddSignal" }, + { "name": "LE_CloseLoop" }, + { "name": "LE_CloseSignalTask" }, + { "name": "LE_CloseStreamTask" }, + { "name": "LE_CloseTask" }, + { "name": "LE_CreateAsyncTask" }, + { "name": "LE_CreateBuffer" }, + { "name": "LE_CreateLoop" }, + { "name": "LE_CreateSignalTask" }, + { "name": "LE_CreateStreamClient" }, + { "name": "LE_CreateStreamServer" }, + { "name": "LE_CreateTimer" }, + { "name": "LE_FreeBuffer" }, + { "name": "LE_GetBufferInfo" }, + { "name": "LE_GetDefaultLoop" }, + { "name": "LE_GetSendResult" }, + { "name": "LE_GetSocketFd" }, + { "name": "LE_GetUserData" }, + { "name": "LE_RemoveSignal" }, + { "name": "LE_RemoveWatcher" }, + { "name": "LE_RunLoop" }, + { "name": "LE_Send" }, + { "name": "LE_StartAsyncEvent" }, + { "name": "LE_StartTimer" }, + { "name": "LE_StartWatcher" }, + { "name": "LE_StopAsyncTask" }, + { "name": "LE_StopLoop" }, + { "name": "LE_StopTimer" }, + { "name": "LE_AddIdle" }, + { "name": "LE_DelIdle" }, + { "name": "LE_DelayProc" }, + { "name": "OH_ListAddTail" }, + { "name": "OH_ListInit" }, + { "name": "OH_ListRemove" }, + { "name": "OH_ListGetCnt" }, + { "name": "OH_ListAddWithOrder" }, + { "name": "OH_ListFind" }, + { "name": "OH_ListRemoveAll" }, + { "name": "OH_ListTraversal" }, + { "name": "OH_HashMapAdd" }, + { "name": "OH_HashMapCreate" }, + { "name": "OH_HashMapDestory" }, + { "name": "OH_HashMapFind" }, + { "name": "OH_HashMapGet" }, + { "name": "OH_HashMapIsEmpty" }, + { "name": "OH_HashMapRemove" }, + { "name": "OH_HashMapTraverse" }, + { "name": "InitAddServiceHook" }, + { "name": "InitAddRebootHook" }, + { "name": "InitAddServiceParseHook" }, + { "name": "InitAddJobParseHook" }, + { "name": "InitAddPostPersistParamLoadHook"}, + { "name": "InitServiceRestartHook" }, + { "name": "OH_StrArrayGetIndex" }, + { "name": "OH_ExtendableStrArrayGetIndex" }, + { "name": "OH_StrDictGet" }, + { "name": "OH_ExtendableStrDictGet" }, + { "name": "GetUptimeInMicroSeconds" } +] diff --git a/interfaces/innerkits/libbeget_proxy.versionscript b/interfaces/innerkits/libbeget_proxy.versionscript new file mode 100644 index 0000000000000000000000000000000000000000..f35cd896b0e92c2e49e715eccfd26d16ef7d8ba4 --- /dev/null +++ b/interfaces/innerkits/libbeget_proxy.versionscript @@ -0,0 +1,24 @@ +# Copyright (c) 2021-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. + +1.0 { + global: + AclGetDevUdid; + AclGetSerial; + ServiceWatchForStatus; + SystemWatchParameter; + WatchParameter; + RemoveParameterWatcher; + local: + *; +}; diff --git a/interfaces/innerkits/libbegetutil.versionscript b/interfaces/innerkits/libbegetutil.versionscript new file mode 100644 index 0000000000000000000000000000000000000000..a6762300ec8510b3f2b939742c06223f8197cdcc --- /dev/null +++ b/interfaces/innerkits/libbegetutil.versionscript @@ -0,0 +1,161 @@ +# Copyright (c) 2023 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. + +1.0 { + global: + DecodeUid; + DecodeGid; + ResetParamSecurityLabel; + StartupLog; + ServiceGetFd; + ServiceSaveFd; + HookMgrAdd; + HookMgrAddEx; + HookMgrCreate; + HookMgrDel; + HookMgrDestroy; + HookMgrExecute; + HookMgrGetHooksCnt; + HookMgrGetStagesCnt; + HookMgrTraversal; + GetControlFile; + OH_HashMapAdd; + OH_HashMapCreate; + OH_HashMapDestory; + OH_HashMapFind; + OH_HashMapGet; + OH_HashMapIsEmpty; + OH_HashMapRemove; + OH_HashMapTraverse; + SystemReadParam; + SystemTraversalParameter; + GetSystemCommitId; + CachedParameterCreate; + CachedParameterGet; + CachedParameterGetChanged; + CachedParameterDestroy; + DoReboot; + DoRebootExt; + GetControlSocket; + OH_ListAddTail; + OH_ListAddWithOrder; + OH_ListFind; + OH_ListGetCnt; + OH_ListInit; + OH_ListRemove; + OH_ListRemoveAll; + OH_ListTraversal; + LE_AcceptStreamClient; + LE_AddSignal; + LE_CloseLoop; + LE_CloseSignalTask; + LE_CloseStreamTask; + LE_CloseTask; + LE_CreateAsyncTask; + LE_CreateBuffer; + LE_CreateLoop; + LE_CreateSignalTask; + LE_CreateStreamClient; + LE_CreateStreamServer; + LE_CreateTimer; + LE_FreeBuffer; + LE_GetBufferInfo; + LE_GetDefaultLoop; + LE_GetSendResult; + LE_GetSocketFd; + LE_GetUserData; + LE_RemoveSignal; + LE_RemoveWatcher; + LE_RunLoop; + LE_Send; + LE_StartAsyncEvent; + LE_StartTimer; + LE_StartWatcher; + LE_StopAsyncTask; + LE_StopLoop; + LE_StopTimer; + LE_AddIdle; + LE_DelIdle; + LE_DelayProc; + ModuleMgrCreate; + ModuleMgrDestroy; + ModuleMgrGetArgs; + ModuleMgrGetCnt; + ModuleMgrInstall; + ModuleMgrScan; + ModuleMgrTraversal; + ModuleMgrUninstall; + *GetStringParameter*; + FindParameter; + GetAbiList; + GetBootloaderVersion; + GetBrand; + GetBuildHost; + GetBuildRootHash; + GetBuildTime; + GetBuildType; + GetBuildUser; + GetDevUdid; + GetDisplayVersion; + GetFirstApiVersion; + GetHardwareModel; + GetHardwareProfile; + GetIncrementalVersion; + GetManufacture; + GetMarketName; + GetOSFullName; + GetOsReleaseType; + GetParameterCommitId; + GetParameterName; + GetParameterValue; + GetProductModel; + GetProductModelAlias; + GetProductSeries; + GetSdkApiVersion; + GetSecurityPatchTag; + GetSerial; + GetSoftwareModel; + GetVersionId; + WaitParameter; + *GetIntParameter*; + *GetDeviceType*; + *GetParameter*; + *GetUintParameter*; + *SetParameter*; + *GetBoolParameter*; + ServiceControl; + ServiceControlWithExtra; + ServiceSetReady; + ServiceWaitForStatus; + StartServiceByTimer; + StopServiceTimer; + HasSystemCapability; + GetBuildVersion; + GetFeatureVersion; + GetMajorVersion; + GetSeniorVersion; + OH_Ext*; + GetDistributionOSName; + GetDistributionOSVersion; + GetDistributionOSApiVersion; + GetDistributionOSApiName; + GetDistributionOSReleaseType; + SaveParameters; + OH_StrArrayGetIndex; + OH_ExtendableStrArrayGetIndex; + OH_StrDictGet; + OH_ExtendableStrDictGet; + OpenConsole; + local: + *; +}; diff --git a/interfaces/innerkits/modulemgr/modulemgr.c b/interfaces/innerkits/modulemgr/modulemgr.c new file mode 100644 index 0000000000000000000000000000000000000000..12b38fd45f67d3910d209cb954fe9ae38ee8ce99 --- /dev/null +++ b/interfaces/innerkits/modulemgr/modulemgr.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2021 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" +#include "config_policy_utils.h" +#include "init_utils.h" +#include "list.h" +#include "securec.h" +#include "modulemgr.h" + +#define MODULE_SUFFIX_D ".z.so" +#ifdef SUPPORT_64BIT +#define MODULE_LIB_NAME "lib64" +#else +#define MODULE_LIB_NAME "lib" +#endif +#define LIB_NAME_LEN 3 + +struct tagMODULE_MGR { + ListNode modules; + const char *name; + MODULE_INSTALL_ARGS installArgs; +}; + +MODULE_MGR *ModuleMgrCreate(const char *name) +{ + MODULE_MGR *moduleMgr; + + BEGET_CHECK(name != NULL, return NULL); + + moduleMgr = (MODULE_MGR *)malloc(sizeof(MODULE_MGR)); + BEGET_CHECK(moduleMgr != NULL, return NULL); + OH_ListInit(&(moduleMgr->modules)); + moduleMgr->name = strdup(name); + if (moduleMgr->name == NULL) { + free((void *)moduleMgr); + return NULL; + } + moduleMgr->installArgs.argc = 0; + moduleMgr->installArgs.argv = NULL; + + return moduleMgr; +} + +void ModuleMgrDestroy(MODULE_MGR *moduleMgr) +{ + BEGET_CHECK(moduleMgr != NULL, return); + + ModuleMgrUninstall(moduleMgr, NULL); + BEGET_CHECK(moduleMgr->name == NULL, free((void *)moduleMgr->name)); + free((void *)moduleMgr); +} + +/* + * Module Item related api + */ + + +typedef struct tagMODULE_ITEM { + ListNode node; + MODULE_MGR *moduleMgr; + const char *name; + void *handle; +} MODULE_ITEM; + +static void ModuleDestroy(ListNode *node) +{ + MODULE_ITEM *module; + + BEGET_CHECK(node != NULL, return); + + module = (MODULE_ITEM *)node; + BEGET_CHECK(module->name == NULL, free((void *)module->name)); + BEGET_CHECK(module->handle == NULL, dlclose(module->handle)); + free((void *)module); +} + +static MODULE_INSTALL_ARGS *currentInstallArgs = NULL; + +static void *ModuleInstall(MODULE_ITEM *module, int argc, const char *argv[]) +{ + void *handle; + char path[PATH_MAX]; + int rc; + + module->moduleMgr->installArgs.argc = argc; + module->moduleMgr->installArgs.argv = argv; + + BEGET_LOGV("Module install name %s", module->name); + if (module->name[0] == '/') { + rc = snprintf_s(path, sizeof(path), sizeof(path) - 1, STARTUP_INIT_UT_PATH"%s" MODULE_SUFFIX_D, module->name); + BEGET_CHECK(rc >= 0, return NULL); + } else { + const char *fmt = (InUpdaterMode() == 0) ? "/system/" MODULE_LIB_NAME : "/" MODULE_LIB_NAME; + rc = snprintf_s(path, sizeof(path), sizeof(path) - 1, + STARTUP_INIT_UT_PATH"%s/%s/lib%s" MODULE_SUFFIX_D, fmt, module->moduleMgr->name, module->name); + BEGET_CHECK(rc >= 0, return NULL); + } + BEGET_LOGV("Module install path %s", path); + char *realPath = GetRealPath(path); + BEGET_ERROR_CHECK(realPath != NULL, return NULL, "Failed to get real path"); + currentInstallArgs = &(module->moduleMgr->installArgs); + handle = dlopen(realPath, RTLD_LAZY | RTLD_GLOBAL); + currentInstallArgs = NULL; + BEGET_CHECK_ONLY_ELOG(handle != NULL, "ModuleInstall path %s fail %d", realPath, errno); + free(realPath); + return handle; +} + +static int ModuleCompare(ListNode *node, void *data) +{ + MODULE_ITEM *module = (MODULE_ITEM *)node; + const char *name = module->name; + if (module->name[0] == '/') { + name = strrchr((name), '/') + 1; + } + if (strncmp(name, "lib", LIB_NAME_LEN) == 0) { + name = name + LIB_NAME_LEN; + } + return strcmp(name, (char *)data); +} + +/* + * 用于扫描安装指定目录下所有的插件。 + */ +int ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName, + int argc, const char *argv[]) +{ + MODULE_ITEM *module; + BEGET_LOGV("ModuleMgrInstall moduleName %s", moduleName); + // Get module manager + BEGET_CHECK(!(moduleMgr == NULL || moduleName == NULL), return -1); + + module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)moduleName, ModuleCompare); + BEGET_ERROR_CHECK(module == NULL, return 0, "%s module already exists", moduleName); + + // Create module item + module = (MODULE_ITEM *)malloc(sizeof(MODULE_ITEM)); + BEGET_CHECK(module != NULL, return -1); + + module->handle = NULL; + module->moduleMgr = moduleMgr; + + module->name = strdup(moduleName); + BEGET_CHECK(module->name != NULL, free(module); + return -1); + + // Install + module->handle = ModuleInstall(module, argc, argv); +#ifndef STARTUP_INIT_TEST + if (module->handle == NULL) { + BEGET_LOGE("Failed to install module %s", module->name); + ModuleDestroy((ListNode *)module); + return -1; + } +#endif + // Add to list + OH_ListAddTail(&(moduleMgr->modules), (ListNode *)module); + + return 0; +} + +const MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void) +{ + return currentInstallArgs; +} + +static int StringEndsWith(const char *srcStr, const char *endStr) +{ + int srcStrLen = strlen(srcStr); + int endStrLen = strlen(endStr); + + BEGET_CHECK(!(srcStrLen < endStrLen), return -1); + + srcStr += (srcStrLen - endStrLen); + BEGET_CHECK(strcmp(srcStr, endStr) != 0, return (srcStrLen - endStrLen)); + return -1; +} + +static void ScanModules(MODULE_MGR *moduleMgr, const char *path) +{ + BEGET_LOGV("Scan module with name '%s'", path); + DIR *dir = opendir(path); + BEGET_CHECK(dir != NULL, return); + char *moduleName = calloc(PATH_MAX, sizeof(char)); + while (moduleName != NULL) { + struct dirent *file = readdir(dir); + if (file == NULL) { + break; + } + if ((file->d_type != DT_REG) && (file->d_type != DT_LNK)) { + continue; + } + + // Must be ended with MODULE_SUFFIX_D + int end = StringEndsWith(file->d_name, MODULE_SUFFIX_D); + if (end <= 0) { + continue; + } + + file->d_name[end] = '\0'; + int len = sprintf_s(moduleName, PATH_MAX - 1, "%s/%s", path, file->d_name); + if (len > 0) { + moduleName[len] = '\0'; + BEGET_LOGI("Scan module with name '%s'", moduleName); + ModuleMgrInstall(moduleMgr, moduleName, 0, NULL); + } + } + if (moduleName != NULL) { + free(moduleName); + } + closedir(dir); +} + +/* + * 用于扫描安装指定目录下所有的插件。 + */ +MODULE_MGR *ModuleMgrScan(const char *modulePath) +{ + MODULE_MGR *moduleMgr; + char path[PATH_MAX]; + BEGET_LOGV("ModuleMgrScan moduleName %s", modulePath); + moduleMgr = ModuleMgrCreate(modulePath); + BEGET_CHECK(moduleMgr != NULL, return NULL); + + if (modulePath[0] == '/') { + ScanModules(moduleMgr, modulePath); + } else if (InUpdaterMode() == 1) { + BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1, + "/%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL); + ScanModules(moduleMgr, path); + } else { + BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1, + "%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL); + CfgFiles *files = GetCfgFiles(path); + for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) { + if (files->paths[i]) { + ScanModules(moduleMgr, files->paths[i]); + } + } + FreeCfgFiles(files); + } + return moduleMgr; +} + +/* + * 卸载指定插件。 + */ +void ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name) +{ + MODULE_ITEM *module; + BEGET_CHECK(moduleMgr != NULL, return); + // Uninstall all modules if no name specified + if (name == NULL) { + OH_ListRemoveAll(&(moduleMgr->modules), ModuleDestroy); + return; + } + BEGET_LOGV("ModuleMgrUninstall moduleName %s", name); + // Find module by name + module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)name, ModuleCompare); + BEGET_ERROR_CHECK(module != NULL, return, "Can not find module %s", name); + + // Remove from the list + OH_ListRemove((ListNode *)module); + // Destroy the module + ModuleDestroy((ListNode *)module); +} + +int ModuleMgrGetCnt(const MODULE_MGR *moduleMgr) +{ + BEGET_CHECK(moduleMgr != NULL, return 0); + return OH_ListGetCnt(&(moduleMgr->modules)); +} + +typedef struct tagMODULE_TRAVERSAL_ARGS { + void *cookie; + OhosModuleTraversal traversal; +} MODULE_TRAVERSAL_ARGS; + +static int ModuleTraversalProc(ListNode *node, void *cookie) +{ + MODULE_ITEM *module; + MODULE_TRAVERSAL_ARGS *args; + MODULE_INFO info; + + module = (MODULE_ITEM *)node; + args = (MODULE_TRAVERSAL_ARGS *)cookie; + + info.cookie = args->cookie; + info.handle = module->handle; + info.name = module->name; + args->traversal(&info); + + return 0; +} + +/** + * @brief Traversing all hooks in the HookManager + * + * @param moduleMgr HookManager handle. + * If hookMgr is NULL, it will use default HookManager + * @param cookie traversal cookie. + * @param traversal traversal function. + * @return None. + */ +void ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal) +{ + MODULE_TRAVERSAL_ARGS args; + if (moduleMgr == NULL) { + return; + } + + args.cookie = cookie; + args.traversal = traversal; + OH_ListTraversal((ListNode *)(&(moduleMgr->modules)), (void *)(&args), ModuleTraversalProc, 0); +} diff --git a/interfaces/innerkits/reboot/init_reboot_innerkits.c b/interfaces/innerkits/reboot/init_reboot_innerkits.c new file mode 100644 index 0000000000000000000000000000000000000000..81d5023d9bfcc116368b18cccb42d8f9be86d518 --- /dev/null +++ b/interfaces/innerkits/reboot/init_reboot_innerkits.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 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 "init_reboot.h" + +#include +#include + +#include "beget_ext.h" +#include "securec.h" +#include "init_param.h" + +// Refer to parameter limit, value size should not bigger than 96 +#define MAX_REBOOT_OPTION_SIZE PARAM_VALUE_LEN_MAX + +#ifndef STARTUP_INIT_TEST +#define DOREBOOT_PARAM "ohos.startup.powerctrl" +#else +#define DOREBOOT_PARAM "reboot.ut" +#endif + +static int DoRebootByInitPlugin(const char *mode, const char *option) +{ + char value[MAX_REBOOT_OPTION_SIZE]; + int ret = 0; + if (mode != NULL) { + if (option != NULL) { + ret = snprintf_s(value, MAX_REBOOT_OPTION_SIZE, MAX_REBOOT_OPTION_SIZE - 1, "reboot,%s:%s", mode, option); + } else { + ret = snprintf_s(value, MAX_REBOOT_OPTION_SIZE, MAX_REBOOT_OPTION_SIZE - 1, "reboot,%s", mode); + } + } else { + if (option != NULL) { + ret = snprintf_s(value, MAX_REBOOT_OPTION_SIZE, MAX_REBOOT_OPTION_SIZE - 1, "reboot,%s", option); + } else { + ret = snprintf_s(value, MAX_REBOOT_OPTION_SIZE, MAX_REBOOT_OPTION_SIZE - 1, "%s", "reboot"); + } + } + BEGET_ERROR_CHECK(ret >= 0, return -1, "Failed to format boot mode"); + BEGET_LOGI("Reboot cmd %s", value); + ret = SystemSetParameter(STARTUP_DEVICE_CTL, DEVICE_CMD_STOP); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to set stop param"); + ret = SystemSetParameter(DOREBOOT_PARAM, value); + BEGET_ERROR_CHECK(ret == 0, return -1, "Set parameter to trigger reboot command \" %s \" failed", value); + return 0; +} + +static int ExecReboot(const char *mode, const char *option) +{ + // check if param set ok +#ifndef STARTUP_INIT_TEST + const int maxCount = 10; +#else + const int maxCount = 1; +#endif + int count = 0; + while (count <= maxCount) { + int status = DoRebootByInitPlugin(mode, option); + BEGET_ERROR_CHECK(status != 0, return 0, "reboot success(%s)", option); + count++; + if (count < maxCount) { + usleep(100 * 1000); // 100 * 1000 wait 100ms + } + } + BEGET_LOGE("Failed to reboot system"); + return -1; +} + +int DoReboot(const char *option) +{ + return ExecReboot(NULL, option); +} + +int DoRebootExt(const char *mode, const char *option) +{ + return ExecReboot(mode, option); +} \ No newline at end of file diff --git a/interfaces/innerkits/seccomp/BUILD.gn b/interfaces/innerkits/seccomp/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..ab1f57ee4643b6296135a005708300691bcae169 --- /dev/null +++ b/interfaces/innerkits/seccomp/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("//build/ohos.gni") + +config("seccomp_public_config") { + include_dirs = [ "include" ] +} + +if (defined(build_seccomp) && build_seccomp) { + if (build_variant == "root") { + seccomp_enable_debug = true + } else { + seccomp_enable_debug = false + } + + if (!defined(ohos_lite)) { + ohos_shared_library("seccomp") { + sources = [ "../../../services/modules/seccomp/seccomp_policy.c" ] + + public_configs = [ ":seccomp_public_config" ] + + include_dirs = [ + "../include", + "../../../services/modules", + "../../../services/log", + ] + + if (seccomp_enable_debug) { + include_dirs += [ + "../../../interfaces/innerkits/include", + "../../../interfaces/innerkits/include/param", + ] + + defines = [ "WITH_SECCOMP_DEBUG" ] + } + + deps = [ "../../innerkits:libbegetutil" ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "config_policy:configpolicy_util", + ] + + license_file = "//base/startup/init/LICENSE" + + part_name = "init" + subsystem_name = "startup" + + install_enable = true + install_images = [ "system" ] + } + } +} else { + group("seccomp") { + } +} diff --git a/interfaces/innerkits/seccomp/include/seccomp_policy.h b/interfaces/innerkits/seccomp/include/seccomp_policy.h new file mode 100644 index 0000000000000000000000000000000000000000..102ff287b75163efd0a1f152c60a62daa62fc349 --- /dev/null +++ b/interfaces/innerkits/seccomp/include/seccomp_policy.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECCOMP_POLICY_H +#define SECCOMP_POLICY_H + +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define SYSTEM_NAME "system" +#define APPSPAWN_NAME "appspawn" +#define NWEBSPAWN_NAME "nwebspawn" +#define APP_NAME "app" +#define IMF_EXTENTOIN_NAME "imf_secure_mode" +#define APP_PRIVILEGE "app_privilege" + +typedef enum { + SYSTEM_SA, // system service process + SYSTEM_OTHERS, // HDF process and daemon process + APP, + INDIVIDUAL // process which need enable individual policy +} SeccompFilterType; + +bool SetSeccompPolicyWithName(SeccompFilterType type, const char *filterName); + +bool IsEnableSeccomp(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // SECCOMP_POLICY_H diff --git a/interfaces/innerkits/service_control/service_control.c b/interfaces/innerkits/service_control/service_control.c new file mode 100644 index 0000000000000000000000000000000000000000..0c78d8da681cb444656b569f64e0cec4a05a0e8b --- /dev/null +++ b/interfaces/innerkits/service_control/service_control.c @@ -0,0 +1,206 @@ +/* +* Copyright (c) 2021 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 "service_control.h" + +#include +#include +#include +#include + +#include "beget_ext.h" +#include "init_utils.h" +#include "init_param.h" +#include "parameter.h" +#include "securec.h" + +static int StartProcess(const char *name, const char *extArgv[], int extArgc) +{ + BEGET_ERROR_CHECK(name != NULL, return -1, "Service name is null."); + int extraArg = 0; + if ((extArgv != NULL) && (extArgc > 0)) { + BEGET_LOGI("Start service by extra args"); + extraArg = 1; + } + int ret = 0; + if (extraArg == 1) { + unsigned int len = 0; + for (int i = 0; i < extArgc; i++) { + len += strlen(extArgv[i]); + } + len += strlen(name) + extArgc + 1; + char *nameValue = (char *)calloc(len, sizeof(char)); + BEGET_ERROR_CHECK(nameValue != NULL, return -1, "Failed calloc err=%d", errno); + + ret = strncat_s(nameValue, len, name, strlen(name)); + if (ret != 0) { + free(nameValue); + BEGET_LOGE("Failed to cat name"); + return -1; + } + for (int j = 0; j < extArgc; j++) { + ret = strncat_s(nameValue, len, "|", 1); + if (ret == 0) { + ret = strncat_s(nameValue, len, extArgv[j], strlen(extArgv[j])); + } + if (ret != 0) { + free(nameValue); + BEGET_LOGE("Failed to cat name"); + return -1; + } + } + ret = SystemSetParameter("ohos.ctl.start", nameValue); + free(nameValue); + } else { + ret = SystemSetParameter("ohos.ctl.start", name); + } + return ret; +} + +static int StopProcess(const char *serviceName) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + return SystemSetParameter("ohos.ctl.stop", serviceName); +} + +static int GetCurrentServiceStatus(const char *serviceName, ServiceStatus *status) +{ + char paramName[PARAM_NAME_LEN_MAX] = {0}; + if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, + "%s.%s", STARTUP_SERVICE_CTL, serviceName) == -1) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return -1; + } + uint32_t value = GetUintParameter(paramName, SERVICE_IDLE); + *status = (ServiceStatus)value; + return 0; +} + +static int RestartProcess(const char *serviceName, const char *extArgv[], int extArgc) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + ServiceStatus status = SERVICE_IDLE; + if (GetCurrentServiceStatus(serviceName, &status) != 0) { + BEGET_LOGE("Get service status failed.\n"); + return -1; + } + BEGET_LOGE("Process service %s status: %d ", serviceName, status); + if (status == SERVICE_STARTED || status == SERVICE_READY) { + if (StopProcess(serviceName) != 0) { + BEGET_LOGE("Stop service %s failed", serviceName); + return -1; + } + if (ServiceWaitForStatus(serviceName, SERVICE_STOPPED, DEFAULT_PARAM_WAIT_TIMEOUT) != 0) { + BEGET_LOGE("Failed wait service %s stopped", serviceName); + return -1; + } + if (StartProcess(serviceName, extArgv, extArgc) != 0) { + BEGET_LOGE("Start service %s failed", serviceName); + return -1; + } + } else if (status != SERVICE_STARTING) { + if (StartProcess(serviceName, extArgv, extArgc) != 0) { + BEGET_LOGE("Start service %s failed", serviceName); + return -1; + } + } + return 0; +} + +int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + int ret = 0; + switch (action) { + case START: + ret = StartProcess(serviceName, extArgv, extArgc); + break; + case STOP: + ret = StopProcess(serviceName); + break; + case RESTART: + ret = RestartProcess(serviceName, extArgv, extArgc); + break; + default: + BEGET_LOGE("Set service %s action %d error", serviceName, action); + ret = -1; + break; + } + return ret; +} + +int ServiceControl(const char *serviceName, int action) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + int ret = ServiceControlWithExtra(serviceName, action, NULL, 0); + return ret; +} + +static int GetProcessInfo(const char *serviceName, char *nameBuffer, char *valueBuffer, ServiceStatus status) +{ + if (snprintf_s(nameBuffer, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s.%s", + STARTUP_SERVICE_CTL, serviceName) == -1) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return -1; + } + if (snprintf_s(valueBuffer, MAX_INT_LEN, MAX_INT_LEN - 1, "%d", (int)status) == -1) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return -1; + } + return 0; +} + +int ServiceWaitForStatus(const char *serviceName, ServiceStatus status, int waitTimeout) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + BEGET_ERROR_CHECK(waitTimeout >= 0, return -1, "Invalid timeout."); + char paramName[PARAM_NAME_LEN_MAX] = {0}; + char value[MAX_INT_LEN] = {0}; + int ret = GetProcessInfo(serviceName, paramName, value, status); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get param info."); + return (SystemWaitParameter(paramName, value, waitTimeout) != 0) ? -1 : 0; +} + +int ServiceSetReady(const char *serviceName) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + char paramName[PARAM_NAME_LEN_MAX] = {0}; + char value[MAX_INT_LEN] = {0}; + int ret = GetProcessInfo(serviceName, paramName, value, SERVICE_READY); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get param info."); + return SystemSetParameter(paramName, value); +} + +int StartServiceByTimer(const char *serviceName, uint64_t timeout) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + if (timeout == 0) { + // start service immediately. + return ServiceControl(serviceName, START); + } + // restrict timeout value, not too long. + char value[PARAM_VALUE_LEN_MAX] = {}; + if (snprintf_s(value, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s|%lld", serviceName, timeout) == -1) { + BEGET_LOGE("Failed to build parameter value"); + return -1; + } + return SystemSetParameter("ohos.servicectrl.timer_start", value); +} + +int StopServiceTimer(const char *serviceName) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null."); + return SystemSetParameter("ohos.servicectrl.timer_stop", serviceName); +} diff --git a/interfaces/innerkits/service_watcher/service_watcher.c b/interfaces/innerkits/service_watcher/service_watcher.c new file mode 100644 index 0000000000000000000000000000000000000000..92fd7b2413405fb6881dcb8d9540157976bde16d --- /dev/null +++ b/interfaces/innerkits/service_watcher/service_watcher.c @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2021 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 "service_watcher.h" + +#include +#include +#include + +#include "beget_ext.h" +#include "init_utils.h" +#include "parameter.h" +#include "securec.h" +#include "service_control.h" +#include "sysparam_errno.h" + +static void ServiceStateChange(const char *key, const char *value, void *context) +{ + ServiceStatusChangePtr callback = (ServiceStatusChangePtr)context; + uint32_t v = 0; + int ret = StringToUint(value, &v); + BEGET_ERROR_CHECK(ret == 0, return, "Failed to get value from %s", value); + + // get pid + char paramName[PARAM_NAME_LEN_MAX] = { 0 }; + ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, "%s.pid", key); + BEGET_ERROR_CHECK(ret != -1, return, "Failed to get format pid ret %d for %s ", ret, key); + + ServiceInfo info = {0}; + info.status = (ServiceStatus)v; + info.pid = (pid_t)GetUintParameter(paramName, INVALID_PID); + if (strlen(key) > strlen(STARTUP_SERVICE_CTL)) { + callback(key + strlen(STARTUP_SERVICE_CTL) + 1, &info); + } else { + BEGET_LOGE("Invalid service name %s %s", key, value); + } +} + +int ServiceWatchForStatus(const char *serviceName, ServiceStatusChangePtr changeCallback) +{ + BEGET_ERROR_CHECK(serviceName != NULL, return EC_INVALID, "Service watch failed, service is null."); + BEGET_ERROR_CHECK(changeCallback != NULL, return EC_INVALID, "Service watch failed, callback is null."); + + char paramName[PARAM_NAME_LEN_MAX] = {0}; + BEGET_LOGI("Watcher service %s status", serviceName); + if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, + "%s.%s", STARTUP_SERVICE_CTL, serviceName) == -1) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return EC_SYSTEM_ERR; + } + int ret = SystemWatchParameter(paramName, ServiceStateChange, (void *)changeCallback); + if (ret != 0) { + BEGET_LOGE("Failed to watcher service %s ret %d.", serviceName, ret); + if (ret == DAC_RESULT_FORBIDED) { + return SYSPARAM_PERMISSION_DENIED; + } + return EC_SYSTEM_ERR; + } + return 0; +} + +int WatchParameter(const char *keyprefix, ParameterChgPtr callback, void *context) +{ + if (keyprefix == NULL) { + return EC_INVALID; + } +#ifdef NO_PARAM_WATCHER + printf("ParameterWatcher is disabled."); + return EC_INVALID; +#else + int ret = SystemWatchParameter(keyprefix, callback, context); + BEGET_CHECK_ONLY_ELOG(ret == 0, "WatchParameter failed! the errNum is %d", ret); + return ret; +#endif +} \ No newline at end of file diff --git a/interfaces/innerkits/socket/BUILD.gn b/interfaces/innerkits/socket/BUILD.gn index 0a95024a05867e84a51bb7dcf4634e452b4280a7..60fc681271cdada6db47b8da2060a1a565e0a5c7 100644 --- a/interfaces/innerkits/socket/BUILD.gn +++ b/interfaces/innerkits/socket/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-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 @@ -11,19 +11,29 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build/ohos.gni") -ohos_static_library("libsocket") { - sources = - [ "//base/startup/init_lite/interfaces/innerkits/socket/init_socket.c" ] +service_socket_sources = + [ "//base/startup/init/interfaces/innerkits/socket/init_socket.c" ] +service_socket_include = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/log", +] - include_dirs = [ - "//base/startup/init_lite/interfaces/innerkits/include", - "//base/startup/init_lite/services/log", - "//third_party/bounds_checking_function/include", - ] +if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux") { + static_library("libsocket") { + sources = service_socket_sources + include_dirs = service_socket_include + external_deps = [ "bounds_checking_function:libsec_static" ] + } + } +} else { + import("//build/ohos.gni") - deps = [ - "//base/startup/init_lite/services/log:init_log", - "//third_party/bounds_checking_function:libsec_static", - ] + ohos_static_library("libsocket") { + sources = service_socket_sources + include_dirs = service_socket_include + external_deps = [ "bounds_checking_function:libsec_static" ] + part_name = "init" + subsystem_name = "startup" + } } diff --git a/interfaces/innerkits/socket/init_socket.c b/interfaces/innerkits/socket/init_socket.c old mode 100755 new mode 100644 index f822a8340073175bfa53be0d15e15556e70ee890..4db6789efa97cfd730884d0e9868790e7c68c338 --- a/interfaces/innerkits/socket/init_socket.c +++ b/interfaces/innerkits/socket/init_socket.c @@ -14,78 +14,52 @@ */ #include "init_socket.h" -#include #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include #include -#include "init_log.h" +#include "beget_ext.h" #include "securec.h" #define N_DEC 10 #define MAX_SOCKET_ENV_PREFIX_LEN 64 #define MAX_SOCKET_DIR_LEN 128 -static int GetControlFromEnv(char *path, int length) +static int GetControlFromEnv(const char *path, int length) { - if (path == NULL || length <= 0) { - return -1; - } - INIT_LOGI("GetControlFromEnv path is %s ", path); + BEGET_CHECK_RETURN_VALUE(path != NULL && length > 0, -1); const char *val = getenv(path); - if (val == NULL) { - INIT_LOGE("GetControlFromEnv val is null %d", errno); - return -1; - } + BEGET_ERROR_CHECK(val != NULL, return -1, "Get environment from %s failed", path); errno = 0; int fd = strtol(val, NULL, N_DEC); - if (errno) { - return -1; - } - INIT_LOGI("GetControlFromEnv fd is %d ", fd); - if (fcntl(fd, F_GETFD) < 0) { - INIT_LOGE("GetControlFromEnv errno %d ", errno); - return -1; - } + BEGET_ERROR_CHECK(errno == 0, return -1, "Failed strtol err=%d", errno); + BEGET_ERROR_CHECK(fcntl(fd, F_GETFD) >= 0, return -1, "Failed fcntl err=%d ", errno); return fd; } int GetControlSocket(const char *name) { - if (name == NULL) { - return -1; - } + BEGET_CHECK_RETURN_VALUE(name != NULL, -1); char path[MAX_SOCKET_ENV_PREFIX_LEN] = {0}; - if (snprintf_s(path, sizeof(path), sizeof(path) - 1, OHOS_SOCKET_ENV_PREFIX"%s", name) == -1) { - return -1; - } - INIT_LOGI("GetControlSocket path is %s ", path); + BEGET_CHECK_RETURN_VALUE(snprintf_s(path, sizeof(path), sizeof(path) - 1, OHOS_SOCKET_ENV_PREFIX"%s", + name) != -1, -1); int fd = GetControlFromEnv(path, MAX_SOCKET_ENV_PREFIX_LEN); - if (fd < 0) { - INIT_LOGE("GetControlFromEnv fail "); - return -1; + BEGET_ERROR_CHECK(fd >= 0, return -1, "Get control fd from environment failed"); + int addrFamily = 0; + socklen_t afLen = sizeof(addrFamily); + int ret = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &addrFamily, &afLen); + BEGET_ERROR_CHECK(ret == 0, return -1, "Get socket option fail, err=%d ", errno); + if (addrFamily != AF_UNIX) { + return fd; } struct sockaddr_un addr; socklen_t addrlen = sizeof(addr); - int ret = getsockname(fd, (struct sockaddr*)&addr, &addrlen); - if (ret < 0) { - INIT_LOGE("GetControlSocket errno %d ", errno); - return -1; - } + ret = getsockname(fd, (struct sockaddr*)&addr, &addrlen); + BEGET_ERROR_CHECK(ret >= 0, return -1, "Failed getsockname err=%d ", errno); char sockDir[MAX_SOCKET_DIR_LEN] = {0}; - if (snprintf_s(sockDir, sizeof(sockDir), sizeof(sockDir) - 1, OHOS_SOCKET_DIR"/%s", name) == -1) { - return -1; - } - INIT_LOGI("sockDir %s ", sockDir); - INIT_LOGI("addr.sun_path %s ", addr.sun_path); + BEGET_CHECK_RETURN_VALUE(snprintf_s(sockDir, sizeof(sockDir), sizeof(sockDir) - 1, OHOS_SOCKET_DIR"/%s", + name) != -1, -1); + BEGET_LOGV("Compary sockDir %s and addr.sun_path %s", sockDir, addr.sun_path); if (strncmp(sockDir, addr.sun_path, strlen(sockDir)) == 0) { return fd; } diff --git a/services/cmds/service_control/BUILD.gn b/interfaces/innerkits/syscap/BUILD.gn similarity index 56% rename from services/cmds/service_control/BUILD.gn rename to interfaces/innerkits/syscap/BUILD.gn index 0e8f91315cadb335534da7af473659048e20a73f..d3b5fb91578e6a4d056690ed39806e37dda04658 100755 --- a/services/cmds/service_control/BUILD.gn +++ b/interfaces/innerkits/syscap/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Huawei Device Co., Ltd. +# 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 @@ -10,23 +10,27 @@ # 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("//build/ohos.gni") -ohos_executable("service_control") { - sources = [ "service_control.c" ] +config("syscap_config") { + include_dirs = [ "../include" ] +} + +ohos_shared_library("syscap") { + sources = [ "init_syscap.c" ] + include_dirs = [ - "//base/startup/init_lite/services/include/param", - "//base/startup/init_lite/services/include", - ] - deps = [ - "//base/startup/init_lite/services/param:paramclient", - "//third_party/bounds_checking_function:libsec_static", + "../include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/include", ] - symlink_target_name = [ - "start_service", - "stop_service", - ] - install_images = [ "system" ] - install_enable = true + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + + external_deps = [ "bounds_checking_function:libsec_shared" ] + + public_configs = [ ":syscap_config" ] part_name = "init" + subsystem_name = "startup" + install_images = [ "system" ] } diff --git a/interfaces/innerkits/syscap/init_syscap.c b/interfaces/innerkits/syscap/init_syscap.c new file mode 100644 index 0000000000000000000000000000000000000000..b5f85523ff29332ca7d7520f6c5ba30318b5e0fb --- /dev/null +++ b/interfaces/innerkits/syscap/init_syscap.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 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 "init_param.h" +#include "beget_ext.h" +#include "securec.h" +#include "systemcapability.h" + +#define SYSCAP_MAX_SIZE 100 +#define SYSCAP_PREFIX_NAME "SystemCapability" +#define CONST_SYSCAP_PREFIX_NAME "const.SystemCapability" + +bool HasSystemCapability(const char *cap) +{ + char capName[SYSCAP_MAX_SIZE] = { 0 }; + char paramValue[PARAM_VALUE_LEN_MAX] = { 0 }; + unsigned int valueLen = PARAM_VALUE_LEN_MAX; + int rc = -1; + + if (cap == NULL) { + BEGET_LOGE("cap input is null."); + return false; + } + + if (strncmp(SYSCAP_PREFIX_NAME, cap, sizeof(SYSCAP_PREFIX_NAME) - 1) == 0) { + rc = snprintf_s(capName, SYSCAP_MAX_SIZE, SYSCAP_MAX_SIZE - 1, "const.%s", cap); + BEGET_ERROR_CHECK(rc >= 0, return false, "Failed snprintf_s err=%d", errno); + } else if (snprintf_s(capName, SYSCAP_MAX_SIZE, SYSCAP_MAX_SIZE - 1, CONST_SYSCAP_PREFIX_NAME".%s", cap) == -1) { + BEGET_LOGE("Failed snprintf_s err=%d", errno); + return false; + } + + if (SystemGetParameter(capName, paramValue, &valueLen) != 0) { + BEGET_LOGE("Failed get paramName."); + return false; + } + + return true; +} \ No newline at end of file diff --git a/interfaces/innerkits/syspara/param_comm.c b/interfaces/innerkits/syspara/param_comm.c new file mode 100644 index 0000000000000000000000000000000000000000..9b4047e72fbd1fd27e70ffc57951864f81dcbd7f --- /dev/null +++ b/interfaces/innerkits/syspara/param_comm.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021-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 "param_comm.h" + +#include +#include + +#include "init_param.h" +#include "parameter.h" +#include "sysparam_errno.h" +#include "securec.h" +#include "beget_ext.h" + +INIT_LOCAL_API int GetSystemError(int err) +{ + switch (err) { + case 0: + return 0; + case PARAM_CODE_INVALID_PARAM: + case PARAM_CODE_INVALID_NAME: + case PARAM_CODE_READ_ONLY: + case PARAM_WORKSPACE_NOT_INIT: + case PARAM_WATCHER_CALLBACK_EXIST: + case PARAM_WATCHER_GET_SERVICE_FAILED: + return EC_INVALID; + case PARAM_CODE_INVALID_VALUE: + return SYSPARAM_INVALID_VALUE; + case PARAM_CODE_NOT_FOUND: + case PARAM_CODE_NODE_EXIST: + return SYSPARAM_NOT_FOUND; + case DAC_RESULT_FORBIDED: + case SELINUX_RESULT_FORBIDED: + return SYSPARAM_PERMISSION_DENIED; + case PARAM_CODE_REACHED_MAX: + case PARAM_CODE_FAIL_CONNECT: + case PARAM_CODE_NOT_SUPPORT: + case PARAM_CODE_IPC_ERROR: + case PARAM_CODE_MEMORY_MAP_FAILED: + case PARAM_CODE_MEMORY_NOT_ENOUGH: + return SYSPARAM_SYSTEM_ERROR; + case PARAM_CODE_TIMEOUT: + return SYSPARAM_WAIT_TIMEOUT; + default: + return SYSPARAM_SYSTEM_ERROR; + } +} + +INIT_LOCAL_API int IsValidParamValue(const char *value, uint32_t len) +{ + if ((value == NULL) || (strlen(value) + 1 > len)) { + return 0; + } + return 1; +} + +INIT_LOCAL_API int GetParameter_(const char *key, const char *def, char *value, uint32_t len) +{ + if ((key == NULL) || (value == NULL) || (len > (uint32_t)PARAM_BUFFER_MAX)) { + return EC_INVALID; + } + uint32_t size = len; + int ret = SystemGetParameter(key, NULL, &size); + if (ret != 0) { + if (def == NULL) { + return GetSystemError(ret); + } + if (strlen(def) > len) { + return EC_INVALID; + } + ret = strcpy_s(value, len, def); + return (ret == 0) ? 0 : EC_FAILURE; + } else if (size > len) { + return EC_INVALID; + } + + size = len; + ret = SystemGetParameter(key, value, &size); + BEGET_CHECK_ONLY_ELOG(ret == 0, "GetParameter_ failed! the errNum is: %d", ret); + return GetSystemError(ret); +} + +static PropertyValueProcessor g_propertyGetProcessor = NULL; + +INIT_LOCAL_API const char *GetProperty(const char *key, const char **paramHolder) +{ + BEGET_CHECK(paramHolder != NULL, return NULL); + if (*paramHolder != NULL) { + return *paramHolder; + } + uint32_t len = 0; + int ret = SystemGetParameter(key, NULL, &len); + if (ret == 0 && len > 0) { + char *res = (char *)calloc(1, len + 1); + BEGET_CHECK(res != NULL, return NULL); + ret = SystemGetParameter(key, res, &len); + if (ret != 0) { + free(res); + return NULL; + } + if (g_propertyGetProcessor != NULL) { + res = g_propertyGetProcessor(key, res); + } + *paramHolder = res; + } + return *paramHolder; +} + +INIT_LOCAL_API PropertyValueProcessor SetPropertyGetProcessor(PropertyValueProcessor processor) +{ + PropertyValueProcessor prev = g_propertyGetProcessor; + g_propertyGetProcessor = processor; + return prev; +} + +INIT_LOCAL_API const char *GetProductModel_(void) +{ + static const char *productModel = NULL; + return GetProperty("const.product.model", &productModel); +} + +INIT_LOCAL_API const char *GetProductModelAlias_(void) +{ + static const char *productModelAlias = NULL; + const char *result = GetProperty("const.product.model_alias", &productModelAlias); + if (result == NULL) { + return GetProperty("const.product.model", &productModelAlias); + } + return result; +} + +INIT_LOCAL_API const char *GetManufacture_(void) +{ + static const char *productManufacture = NULL; + return GetProperty("const.product.manufacturer", &productManufacture); +} + +INIT_LOCAL_API const char *GetFullName_(void) +{ + static const char *fillname = NULL; + return GetProperty("const.ohos.fullname", &fillname); +} diff --git a/interfaces/innerkits/syspara/param_comm.h b/interfaces/innerkits/syspara/param_comm.h new file mode 100755 index 0000000000000000000000000000000000000000..62b171bbd919ede8c784e5e3ee85753ad48507a2 --- /dev/null +++ b/interfaces/innerkits/syspara/param_comm.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-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 INIT_PARAM_COMM_H +#define INIT_PARAM_COMM_H +#include +#include "beget_ext.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define UDID_LEN 65 +#define MAX_SERIAL_LEN 65 +#define HASH_LENGTH 32 +#define DEV_BUF_LENGTH 3 +#define DEV_BUF_MAX_LENGTH 1024 + +typedef char *(*PropertyValueProcessor)(const char *key, char *value); + +INIT_LOCAL_API const char *GetProperty(const char *key, const char **paramHolder); +INIT_LOCAL_API PropertyValueProcessor SetPropertyGetProcessor(PropertyValueProcessor processor); +INIT_LOCAL_API int GetParameter_(const char *key, const char *def, char *value, uint32_t len); + +INIT_LOCAL_API const char *GetProductModel_(void); +INIT_LOCAL_API const char *GetProductModelAlias_(void); +INIT_LOCAL_API const char *GetManufacture_(void); +INIT_LOCAL_API const char *GetSerial_(void); +INIT_LOCAL_API int GetDevUdid_(char *udid, int size); +INIT_LOCAL_API int IsValidParamValue(const char *value, uint32_t len); + +INIT_LOCAL_API const char *GetFullName_(void); +INIT_LOCAL_API int GetSystemError(int err); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // STARTUP_PARAM_COMM_H diff --git a/interfaces/innerkits/syspara/param_wrapper.cpp b/interfaces/innerkits/syspara/param_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35b1bdb2d7de77e561a3f6e9f36f0349cf4d3fff --- /dev/null +++ b/interfaces/innerkits/syspara/param_wrapper.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021-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 "param_wrapper.h" + +#include +#include + +#include "beget_ext.h" +#include "param_comm.h" +#include "init_param.h" +#include "init_utils.h" +#include "sysparam_errno.h" +#include "securec.h" +#include "parameter.h" +#include "parameters.h" + +namespace OHOS { +namespace system { +static constexpr int MAX_VALUE_LEN = 128; +bool SetParameter(const std::string& key, const std::string& value) +{ + int ret = SystemSetParameter(key.c_str(), value.c_str()); + return (ret == 0) ? true : false; +} + +template +bool StringToInt(const std::string& str, T min, T max, T& out) +{ + long long int result = 0; + if (StringToLL(str.c_str(), &result) != 0) { + return false; + } + if (result < min || max < result) { + return false; + } + out = static_cast(result); + return true; +} + +template +bool StringToUint(const std::string& str, T max, T& out) +{ + unsigned long long int result = 0; + if (StringToULL(str.c_str(), &result) != 0) { + return false; + } + if (max < result) { + return false; + } + out = static_cast(result); + return true; +} + +std::string GetParameter(const std::string& key, const std::string& def) +{ + uint32_t size = 0; + int ret = SystemReadParam(key.c_str(), NULL, &size); + if (ret == 0) { + std::vector value(MAX_VALUE_LEN); + ret = SystemReadParam(key.c_str(), value.data(), &size); + if (ret == 0) { + return std::string(value.data()); + } + } + if (IsValidParamValue(def.c_str(), MAX_VALUE_LEN) == 1) { + return std::string(def); + } + return ""; +} + +bool GetBoolParameter(const std::string& key, bool def) +{ + static const std::string trueMap[] = { "1", "y", "yes", "on", "true" }; + static const std::string falseMap[] = { "0", "off", "n", "no", "false" }; + std::string value = GetParameter(key, ""); + for (size_t i = 0; i < sizeof(trueMap) / sizeof(trueMap[0]); i++) { + if (trueMap[i] == value) { + return true; + } + } + for (size_t i = 0; i < sizeof(falseMap) / sizeof(falseMap[0]); i++) { + if (falseMap[i] == value) { + return false; + } + } + return def; +} + +int GetStringParameter(const std::string &key, std::string &value, const std::string def) +{ + uint32_t size = 0; + int ret = SystemReadParam(key.c_str(), NULL, &size); + if (ret == 0) { + std::vector data(size + 1); + ret = SystemReadParam(key.c_str(), data.data(), &size); + if (ret == 0) { + value = std::string(data.data()); + return EC_SUCCESS; + } + } + if (IsValidParamValue(def.c_str(), MAX_VALUE_LEN) == 1) { + value = std::string(def); + return EC_SUCCESS; + } + return EC_FAILURE; +} + +template +T GetIntParameter(const std::string& key, T def, T min, T max) +{ + if (!std::is_signed::value) { + return def; + } + T result; + std::string value = GetParameter(key, ""); + if (!value.empty() && StringToInt(value, min, max, result)) { + return result; + } + return def; +} + +template int8_t GetIntParameter(const std::string&, int8_t, int8_t, int8_t); +template int16_t GetIntParameter(const std::string&, int16_t, int16_t, int16_t); +template int32_t GetIntParameter(const std::string&, int32_t, int32_t, int32_t); +template int64_t GetIntParameter(const std::string&, int64_t, int64_t, int64_t); + +template +T GetUintParameter(const std::string& key, T def, T max) +{ + if (!std::is_unsigned::value) { + return def; + } + T result; + std::string value = GetParameter(key, ""); + if (!value.empty() && StringToUint(value, max, result)) { + return result; + } + return def; +} + +template uint8_t GetUintParameter(const std::string&, uint8_t, uint8_t); +template uint16_t GetUintParameter(const std::string&, uint16_t, uint16_t); +template uint32_t GetUintParameter(const std::string&, uint32_t, uint32_t); +template uint64_t GetUintParameter(const std::string&, uint64_t, uint64_t); + +std::string GetDeviceType(void) +{ + std::unordered_map deviceTypeMap = { + {"watch", "wearable"}, + {"fitnessWatch", "liteWearable"}, + }; + static const char *productType = nullptr; + const char *type = GetProperty("const.product.devicetype", &productType); + if (type == nullptr) { + type = GetProperty("const.build.characteristics", &productType); + } + if (type == nullptr) { + return std::string(""); + } + if (deviceTypeMap.count(type) != 0) { + return deviceTypeMap[type]; + } + return std::string(type); +} + +int GetIntParameter(const std::string &key, int def) +{ + return GetIntParameter(key, def, INT_MIN, INT_MAX); +} +} // namespace system +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/innerkits/syspara/parameter.c b/interfaces/innerkits/syspara/parameter.c new file mode 100644 index 0000000000000000000000000000000000000000..3ef6f0a122425756c9be4909fce8b8f285dee041 --- /dev/null +++ b/interfaces/innerkits/syspara/parameter.c @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2021-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 "parameter.h" + +#include +#include + +#include "param_comm.h" +#include "init_param.h" +#include "param_init.h" +#include "init_utils.h" +#include "sysparam_errno.h" +#include "securec.h" +#include "beget_ext.h" + +int WaitParameter(const char *key, const char *value, int timeout) +{ + BEGET_CHECK(!(key == NULL || value == NULL), return EC_INVALID); + int ret = SystemWaitParameter(key, value, timeout); + BEGET_CHECK_ONLY_ELOG(ret == 0, "WaitParameter failed! the errNum is: %d", ret); + return GetSystemError(ret); +} + +uint32_t FindParameter(const char *key) +{ + BEGET_CHECK(key != NULL, return (uint32_t)(-1)); + uint32_t handle = 0; + int ret = SystemFindParameter(key, &handle); + if (ret != 0) { + return (uint32_t)(-1); + } + return handle; +} + +uint32_t GetParameterCommitId(uint32_t handle) +{ + uint32_t commitId = 0; + int ret = SystemGetParameterCommitId(handle, &commitId); + BEGET_CHECK(ret == 0, return (uint32_t)(-1)); + return commitId; +} + +int GetParameterName(uint32_t handle, char *name, uint32_t len) +{ + if (name == NULL) { + return EC_INVALID; + } + int ret = SystemGetParameterName(handle, name, len); + if (ret == 0) { + return strlen(name); + } + BEGET_CHECK_ONLY_ELOG(ret == 0, "GetParameterName failed! the errNum is: %d", ret); + return GetSystemError(ret); +} + +int GetParameterValue(uint32_t handle, char *value, uint32_t len) +{ + if (value == NULL) { + return EC_INVALID; + } + uint32_t size = len; + int ret = SystemGetParameterValue(handle, value, &size); + if (ret == 0) { + return strlen(value); + } + BEGET_CHECK_ONLY_ELOG(ret == 0, "GetParameterValue failed! the errNum is: %d", ret); + return GetSystemError(ret); +} + +int GetParameter(const char *key, const char *def, char *value, uint32_t len) +{ + if ((key == NULL) || (value == NULL)) { + return EC_INVALID; + } + int ret = GetParameter_(key, def, value, len); + return (ret != 0) ? ret : strlen(value); +} + +int SetParameter(const char *key, const char *value) +{ + if ((key == NULL) || (value == NULL)) { + return EC_INVALID; + } + int ret = SystemSetParameter(key, value); + BEGET_CHECK_ONLY_ELOG(ret == 0, "SetParameter failed! the errNum is:%d", ret); + return GetSystemError(ret); +} + +int SaveParameters(void) +{ + int ret = SystemSaveParameters(); + return GetSystemError(ret); +} + +const char *GetDeviceType(void) +{ + static const char *productType = NULL; + const char *deviceType = GetProperty("const.product.devicetype", &productType); + if (deviceType != NULL) { + return deviceType; + } + return GetProperty("const.build.characteristics", &productType); +} + +const char *GetProductModel(void) +{ + return GetProductModel_(); +} + +const char *GetProductModelAlias(void) +{ + return GetProductModelAlias_(); +} + +const char *GetManufacture(void) +{ + return GetManufacture_(); +} + +const char *GetBrand(void) +{ + static const char *productBrand = NULL; + return GetProperty("const.product.brand", &productBrand); +} + +const char *GetMarketName(void) +{ + static const char *marketName = NULL; + return GetProperty("const.product.name", &marketName); +} + +const char *GetProductSeries(void) +{ + static const char *productSeries = NULL; + return GetProperty("const.build.product", &productSeries); +} + +const char *GetSoftwareModel(void) +{ + static const char *softwareModel = NULL; + return GetProperty("const.software.model", &softwareModel); +} + +const char *GetHardwareModel(void) +{ + static const char *hardwareModel = NULL; + return GetProperty("const.product.hardwareversion", &hardwareModel); +} + +const char *GetHardwareProfile(void) +{ + static const char *hardwareProfile = NULL; + return GetProperty("const.product.hardwareprofile", &hardwareProfile); +} + +const char *GetAbiList(void) +{ + static const char *productAbiList = NULL; + return GetProperty("const.product.cpu.abilist", &productAbiList); +} + +const char *GetBootloaderVersion(void) +{ + static const char *productBootloader = NULL; + return GetProperty("const.product.bootloader.version", &productBootloader); +} + +int GetFirstApiVersion(void) +{ + static const char *firstApiVersion = NULL; + GetProperty("const.product.firstapiversion", &firstApiVersion); + if (firstApiVersion == NULL) { + return 0; + } + return atoi(firstApiVersion); +} + +const char *GetDisplayVersion(void) +{ + static const char *displayVersion = NULL; + return GetProperty("const.product.software.version", &displayVersion); +} + +const char *GetIncrementalVersion(void) +{ + static const char *incrementalVersion = NULL; + return GetProperty("const.product.incremental.version", &incrementalVersion); +} + +const char *GetOsReleaseType(void) +{ + static const char *osReleaseType = NULL; + return GetProperty("const.ohos.releasetype", &osReleaseType); +} + +static const char *GetSdkApiVersion_(void) +{ + static const char *sdkApiVersion = NULL; + return GetProperty("const.ohos.apiversion", &sdkApiVersion); +} + +const char *GetBuildType(void) +{ + static const char *buildType = NULL; + return GetProperty("const.product.build.type", &buildType); +} + +const char *GetBuildUser(void) +{ + static const char *buildUser = NULL; + return GetProperty("const.product.build.user", &buildUser); +} + +const char *GetBuildHost(void) +{ + static const char *buildHost = NULL; + return GetProperty("const.product.build.host", &buildHost); +} + +const char *GetBuildTime(void) +{ + static const char *buildTime = NULL; + return GetProperty("const.product.build.date", &buildTime); +} + +const char *GetSerial(void) +{ + return GetSerial_(); +} + +int GetDevUdid(char *udid, int size) +{ + return GetDevUdid_(udid, size); +} + +static const char *BuildOSFullName(void) +{ + const char release[] = "Release"; + const char *releaseType = GetOsReleaseType(); + const char *fullName = GetFullName_(); + if (fullName == NULL || releaseType == NULL) { + return NULL; + } + if (strncmp(releaseType, release, sizeof(release) - 1) != 0) { + char *value = calloc(1, OS_FULL_NAME_LEN); + if (value == NULL) { + return NULL; + } + int length = sprintf_s(value, OS_FULL_NAME_LEN, "%s(%s)", fullName, releaseType); + if (length < 0) { + free(value); + return NULL; + } + return value; + } + return strdup(fullName); +} + +const char *GetOSFullName(void) +{ + static const char *osFullName = NULL; + if (osFullName != NULL) { + return osFullName; + } + osFullName = BuildOSFullName(); + if (osFullName == NULL) { + return EMPTY_STR; + } + return osFullName; +} + +static const char *BuildVersionId(void) +{ + char value[VERSION_ID_MAX_LEN] = {0}; + if (GetDeviceType() == NULL) { + return NULL; + } + + int len = sprintf_s(value, VERSION_ID_MAX_LEN, "%s/%s/%s/%s/%s/%s/%s/%s/%s/%s", + GetDeviceType(), GetManufacture(), GetBrand(), GetProductSeries(), + GetOSFullName(), GetProductModel(), GetSoftwareModel(), + GetSdkApiVersion_(), GetIncrementalVersion(), GetBuildType()); + if (len <= 0) { + return NULL; + } + const char *versionId = strdup(value); + return versionId; +} + +const char *GetVersionId(void) +{ + static const char *ohosVersionId = NULL; + if (ohosVersionId != NULL) { + return ohosVersionId; + } + ohosVersionId = BuildVersionId(); + if (ohosVersionId == NULL) { + return EMPTY_STR; + } + return ohosVersionId; +} + +int GetSdkApiVersion(void) +{ + static const char *sdkApiVersion = NULL; + GetProperty("const.ohos.apiversion", &sdkApiVersion); + if (sdkApiVersion == NULL) { + return 0; + } + return atoi(sdkApiVersion); +} + +const char *GetSecurityPatchTag(void) +{ + static const char *securityPatchTag = NULL; + return GetProperty("const.ohos.version.security_patch", &securityPatchTag); +} + +const char *GetBuildRootHash(void) +{ + static const char *buildRootHash = NULL; + return GetProperty("const.ohos.buildroothash", &buildRootHash); +} + +int32_t GetIntParameter(const char *key, int32_t def) +{ + char value[MAX_INT_LEN] = {0}; + uint32_t size = sizeof(value); + int ret = SystemGetParameter(key, value, &size); + if (ret != 0) { + return def; + } + + long long int result = 0; + if (StringToLL(value, &result) != 0) { + return def; + } + if (result <= INT32_MIN || result >= INT32_MAX) { + return def; + } + return (int32_t)result; +} + +uint32_t GetUintParameter(const char *key, uint32_t def) +{ + char value[MAX_INT_LEN] = {0}; + uint32_t size = sizeof(value); + int ret = SystemGetParameter(key, value, &size); + if (ret != 0) { + return def; + } + + unsigned long long int result = 0; + if (StringToULL(value, &result) != 0) { + return def; + } + if (result >= UINT32_MAX) { + return def; + } + return (uint32_t)result; +} + +const char *GetDistributionOSName(void) +{ + static const char *distributionOsName = NULL; + GetProperty("const.product.os.dist.name", &distributionOsName); + if (distributionOsName == NULL) { + distributionOsName = EMPTY_STR; + } + return distributionOsName; +} + +const char *GetDistributionOSVersion(void) +{ + static const char *distributionOsVersion = NULL; + GetProperty("const.product.os.dist.version", &distributionOsVersion); + if (distributionOsVersion == NULL) { + distributionOsVersion = GetOSFullName(); + } + return distributionOsVersion; +} + +int GetDistributionOSApiVersion(void) +{ + static const char *distributionOsApiVersion = NULL; + GetProperty("const.product.os.dist.apiversion", &distributionOsApiVersion); + if (distributionOsApiVersion == NULL) { + distributionOsApiVersion = GetSdkApiVersion_(); + } + return atoi(distributionOsApiVersion); +} +const char *GetDistributionOSApiName(void) +{ + static const char *distributionOsApiName = NULL; + GetProperty("const.product.os.dist.apiname", &distributionOsApiName); + if (distributionOsApiName == NULL) { + distributionOsApiName = EMPTY_STR; + } + return distributionOsApiName; +} + +const char *GetDistributionOSReleaseType(void) +{ + static const char *distributionOsReleaseType = NULL; + GetProperty("const.product.os.dist.releasetype", &distributionOsReleaseType); + if (distributionOsReleaseType == NULL) { + distributionOsReleaseType = GetOsReleaseType(); + } + return distributionOsReleaseType; +} diff --git a/interfaces/innerkits/syspara/sysversion.c b/interfaces/innerkits/syspara/sysversion.c new file mode 100644 index 0000000000000000000000000000000000000000..c28e6afbac3f15b7cb1cdd583d8b5144929dd6f2 --- /dev/null +++ b/interfaces/innerkits/syspara/sysversion.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021-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 "sysversion.h" + +#include +#include + +#include "beget_ext.h" +#include "param_comm.h" +#include "securec.h" + +/* * + * Major(M) version number. + */ +static int g_majorVersion = 2; + +/* * + * Senior(S) version number. + */ +static int g_seniorVersion = 2; + +/* * + * Feature(F) version number. + */ +static int g_featureVersion = 0; + +/* * + * Build(B) version number. + */ +static int g_buildVersion = 0; + +static void GetVersions(void) +{ + static int versionInited = 0; + if (versionInited) { + return; + } + const char *fullName = GetFullName_(); + if (fullName == NULL) { + return; + } + const char *tmp = strstr(fullName, "-"); + if (tmp == NULL) { + return; + } + tmp++; // skip "-" + int ret = sscanf_s(tmp, "%d.%d.%d.%d", &g_majorVersion, &g_seniorVersion, &g_featureVersion, &g_buildVersion); + BEGET_LOGV("fullName %s %d.%d.%d.%d ret %d", + fullName, g_majorVersion, g_seniorVersion, g_featureVersion, g_buildVersion, ret); + if (ret == 4) { // 4 parameters + versionInited = 1; + } +} + +/* * + * Obtains the major (M) version number, which increases with any updates to the overall architecture. + *

The M version number monotonically increases from 1 to 99. + * + * @return Returns the M version number. + * @since 4 + */ +int GetMajorVersion(void) +{ + GetVersions(); + return g_majorVersion; +} + +/* * + * Obtains the senior (S) version number, which increases with any updates to the partial + * architecture or major features. + *

The S version number monotonically increases from 0 to 99. + * + * @return Returns the S version number. + * @since 4 + */ +int GetSeniorVersion(void) +{ + GetVersions(); + return g_seniorVersion; +} + +/* * + * Obtains the feature (F) version number, which increases with any planned new features. + *

The F version number monotonically increases from 0 or 1 to 99. + * + * @return Returns the F version number. + * @since 3 + */ +int GetFeatureVersion(void) +{ + GetVersions(); + return g_featureVersion; +} + +/* * + * Obtains the build (B) version number, which increases with each new development build. + *

The B version number monotonically increases from 0 or 1 to 999. + * + * @return Returns the B version number. + * @since 3 + */ +int GetBuildVersion(void) +{ + GetVersions(); + return g_buildVersion; +} \ No newline at end of file diff --git a/interfaces/innerkits/token/BUILD.gn b/interfaces/innerkits/token/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..4e32c3c495122885e465d27385ab7b1ab73baf42 --- /dev/null +++ b/interfaces/innerkits/token/BUILD.gn @@ -0,0 +1,81 @@ +# +# Copyright (c) 2020-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/begetd.gni") +import("//build/lite/config/component/lite_component.gni") +import("//build/lite/ndk/ndk.gni") + +if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + shared_library("token_shared") { + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/token", + "//commonlibrary/utils_lite/include", + "//base/startup/init/interfaces/innerkits/token", + ] + sources = [ "src/token_impl_posix/token.c" ] + + public_deps = [ + "$ohos_product_adapter_dir/utils/token:haltoken_shared", + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + ] + } +} + +if (ohos_kernel_type == "liteos_m") { + static_library("token_static") { + sources = [ "src/token_impl_hal/token.c" ] + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/token", + "//commonlibrary/utils_lite/include", + "//base/startup/init/interfaces/innerkits/token", + "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite", + ] + PRODUCT_HAL_TOKEN_PATH = + rebase_path("${ohos_product_adapter_dir}/utils/token") + cmd = "if [ -f ${PRODUCT_HAL_TOKEN_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + PRODUCT_HAL_TOKEN_EXISTS = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (PRODUCT_HAL_TOKEN_EXISTS) { + deps += [ "$ohos_product_adapter_dir/utils/token:hal_token_static" ] + } + deps += + [ "//base/startup/init/interfaces/hals/utils/token:static_hal_token" ] + } +} + +lite_component("token") { + features = [] + + if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + features += [ ":token_shared" ] + } + if (ohos_kernel_type == "liteos_m") { + features += [ ":token_static" ] + } +} + +ndk_lib("token_notes") { + deps = [] + head_files = [] + if (ohos_kernel_type != "liteos_m") { + lib_extension = ".so" + } + if (ohos_kernel_type != "liteos_m") { + deps += [ "//base/startup/init/interfaces/innerkits/token:token_shared" ] + } + head_files += [ "//base/startup/init/interfaces/include/token" ] +} diff --git a/interfaces/innerkits/token/hal_token.h b/interfaces/innerkits/token/hal_token.h new file mode 100755 index 0000000000000000000000000000000000000000..7ed1f1ca7b6c5d33d80413199d2d92a44d01bb1d --- /dev/null +++ b/interfaces/innerkits/token/hal_token.h @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2020-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 HAL_TOKEN_H +#define HAL_TOKEN_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define KIT_FRAMEWORK_UID_MAX 1000 + +/** + * @brief Read token value from device. + * + * @param token the result token value, if read successfully. + * @param len length of the token. + * @returns 0 if success and get the update area token, + * 1 if success and get the pre-made token, + * -1 if failed, + * -2 if no pre-made token. + */ +int HalReadToken(char *token, unsigned int len); + +/** + * @brief Write token value to device. + * + * @param token the token to write. + * @param len length of the token. + * @returns 0 if success, otherwise -1. + */ +int HalWriteToken(const char *token, unsigned int len); + +/** + * @brief Get AcKey value from device. + * + * @param acKey the result acKey, if get successfully. + * @param len length of the acKey. + * @returns 0 if success, otherwise -1. + */ +int HalGetAcKey(char *acKey, unsigned int len); + +/** + * @brief Get ProdId value from device. + * + * @param productId product IDs to be populated with. + * @param len length of the productId. + * @returns 0 if success, otherwise -1. + */ +int HalGetProdId(char *productId, unsigned int len); + +/** + * @brief Get ProdKey value from device. + * + * @param productKey The productKey value + * @param len The productKey len. + * @returns 0 if success, otherwise -1. + */ +int HalGetProdKey(char *productKey, unsigned int len); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // HAL_TOKEN_H diff --git a/interfaces/innerkits/token/src/token_impl_hal/token.c b/interfaces/innerkits/token/src/token_impl_hal/token.c new file mode 100644 index 0000000000000000000000000000000000000000..d68b4d6b7fbbfe4d8e6425899833fe7c9d9c35e4 --- /dev/null +++ b/interfaces/innerkits/token/src/token_impl_hal/token.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020-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 "token.h" +#include "hal_token.h" +#include "log.h" +#include "ohos_errno.h" + +int ReadToken(char *token, unsigned int len) +{ + if (token == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "token is nullptr\n"); + return EC_FAILURE; + } + + return HalReadToken(token, len); +} + +int WriteToken(const char *token, unsigned int len) +{ + if (token == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "token is nullptr\n"); + return EC_FAILURE; + } + + return HalWriteToken(token, len); +} + +int GetAcKey(char *acKey, unsigned int len) +{ + if (acKey == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "acKey is nullptr"); + return EC_FAILURE; + } + + return HalGetAcKey(acKey, len); +} + +int GetProdId(char *productId, unsigned int len) +{ + if (productId == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "productId is nullptr"); + return EC_FAILURE; + } + + return HalGetProdId(productId, len); +} + +int GetProdKey(char *productKey, unsigned int len) +{ + if (productKey == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "productKey is nullptr"); + return EC_FAILURE; + } + + return HalGetProdKey(productKey, len); +} \ No newline at end of file diff --git a/interfaces/innerkits/token/src/token_impl_posix/token.c b/interfaces/innerkits/token/src/token_impl_posix/token.c new file mode 100644 index 0000000000000000000000000000000000000000..caa24bdbf9d6abfe7772536e837504b86f77d5b1 --- /dev/null +++ b/interfaces/innerkits/token/src/token_impl_posix/token.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020-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 "token.h" +#include +#include +#include +#include +#include "hal_token.h" +#include "log.h" +#include "ohos_errno.h" + +static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int UidVerify(void) +{ + uid_t uid; + + uid = getuid(); + if (uid >= KIT_FRAMEWORK_UID_MAX) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "uid verify failed, get uid:%u", uid); + return EC_FAILURE; + } + + return EC_SUCCESS; +} + +int ReadToken(char *token, unsigned int len) +{ + int ret; + + if (token == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "token is nullptr"); + return EC_FAILURE; + } + ret = UidVerify(); + if (ret != EC_SUCCESS) { + return EC_FAILURE; + } + + pthread_mutex_lock(&g_mutex); + ret = HalReadToken(token, len); + pthread_mutex_unlock(&g_mutex); + + return ret; +} + +int WriteToken(const char *token, unsigned int len) +{ + int ret; + + if (token == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "token is nullptr"); + return EC_FAILURE; + } + ret = UidVerify(); + if (ret != EC_SUCCESS) { + return EC_FAILURE; + } + + pthread_mutex_lock(&g_mutex); + ret = HalWriteToken(token, len); + pthread_mutex_unlock(&g_mutex); + + return ret; +} + +int GetAcKey(char *acKey, unsigned int len) +{ + if (acKey == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "acKey is nullptr"); + return EC_FAILURE; + } + int ret = UidVerify(); + if (ret != EC_SUCCESS) { + return EC_FAILURE; + } + + return HalGetAcKey(acKey, len); +} + +int GetProdId(char *productId, unsigned int len) +{ + if (productId == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "productId is nullptr"); + return EC_FAILURE; + } + + return HalGetProdId(productId, len); +} + +int GetProdKey(char *productKey, unsigned int len) +{ + if (productKey == NULL) { + HILOG_ERROR(HILOG_MODULE_HIVIEW, "productKey is nullptr"); + return EC_FAILURE; + } + + int ret = UidVerify(); + if (ret != EC_SUCCESS) { + return EC_FAILURE; + } + + return HalGetProdKey(productKey, len); +} \ No newline at end of file diff --git a/interfaces/innerkits/zh_extral_dir/BUILD.gn b/interfaces/innerkits/zh_extral_dir/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..34d573261b4eea4d365848d073511348deabc956 --- /dev/null +++ b/interfaces/innerkits/zh_extral_dir/BUILD.gn @@ -0,0 +1,21 @@ +# Copyright (c) 2021-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. + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ "../../innerkits/include/param" ] +} + +static_library("export_headers_lib") { + public_configs = [ ":exported_header_files" ] +} diff --git a/interfaces/kits/BUILD.gn b/interfaces/kits/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..81b93ef7e54967ef951628c98211243059848ff5 --- /dev/null +++ b/interfaces/kits/BUILD.gn @@ -0,0 +1,33 @@ +# 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("//build/ohos.gni") + +group("kitsgroup") { + if (!defined(ohos_lite)) { + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + ] + deps += [ "syscap:deviceinfo_ndk" ] + if (support_jsapi) { + deps += [ + "cj:cj_device_info_ffi", + "cj:cj_system_parameter_enhance_ffi", + "jskits:deviceinfo", + "jskits:systemparameter", + "jskits:systemparameterenhance", + ] + } + } +} diff --git a/interfaces/kits/cj/BUILD.gn b/interfaces/kits/cj/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..461cadd1d15d819e60ba35768ef9dd18e1a4f57a --- /dev/null +++ b/interfaces/kits/cj/BUILD.gn @@ -0,0 +1,109 @@ +# 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. + +import("//build/ohos.gni") +import("../../../begetd.gni") + +ohos_shared_library("cj_device_info_ffi") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ + "src_deviceinfo", + "${init_innerkits_path}/syspara", + ] + + if (!defined(defines)) { + defines = [] + } + + if (product_name != "ohos-sdk") { + sources = [ + "src_deviceinfo/device_info.cpp", + "src_deviceinfo/device_info_ffi.cpp", + ] + + deps = [ + "${init_innerkits_path}:libbeget_proxy", + "${init_innerkits_path}:libbegetutil", + ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "hilog:libhilog", + "ipc:ipc_single", + "napi:cj_bind_ffi", + ] + } else { + defines += [ "PREVIEWER" ] + sources = [ "src_deviceinfo/device_info_mock.cpp" ] + } + + if (current_os == "ohos") { + defines += [ "OHOS_PLATFORM" ] + } + + if (current_os == "mingw") { + defines += [ "WINDOWS_PLATFORM" ] + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "startup" + part_name = "init" +} + +ohos_shared_library("cj_system_parameter_enhance_ffi") { + include_dirs = [ "src_enhance" ] + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + symlink_target_name = [ "libsystemparameterv9.z.so" ] + + if (!defined(defines)) { + defines = [] + } + + if (product_name != "ohos-sdk") { + sources = [ "src_enhance/system_parameter_ffi.cpp" ] + + deps = [ + "../../innerkits:libbeget_proxy", + "../../innerkits:libbegetutil", + ] + + external_deps = [ + "c_utils:utils", + "napi:cj_bind_ffi", + ] + } else { + defines += [ "PREVIEWER" ] + sources = [ "src_enhance/system_parameter_mock.cpp" ] + } + + if (current_os == "ohos") { + defines += [ "OHOS_PLATFORM" ] + } + + if (current_os == "mingw") { + defines += [ "WINDOWS_PLATFORM" ] + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "startup" + part_name = "init" +} diff --git a/interfaces/kits/cj/src_deviceinfo/device_info.cpp b/interfaces/kits/cj/src_deviceinfo/device_info.cpp new file mode 100755 index 0000000000000000000000000000000000000000..15aab5371a6cc2fc105029f8a0adb9f87105c692 --- /dev/null +++ b/interfaces/kits/cj/src_deviceinfo/device_info.cpp @@ -0,0 +1,210 @@ +/* + * 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 "parameter.h" +#include "sysversion.h" +#include "device_info.h" + +#include +#include + +namespace OHOS { +namespace CJSystemapi { +namespace DeviceInfo { + +const int UDID_LEN = 65; + +const char* DeviceInfo::CjGetHardwareProfile() +{ + return GetHardwareProfile(); +} + +const char* DeviceInfo::CjGetOsFullName() +{ + return GetOSFullName(); +} + +const char* DeviceInfo::CjGetProductModel() +{ + return GetProductModel(); +} + +const char* DeviceInfo::CjGetBrand() +{ + return GetBrand(); +} + +const char* DeviceInfo::CjGetDeviceType() +{ + return GetDeviceType(); +} + +const char* DeviceInfo::CjGetUdid() +{ + char* udid = static_cast(calloc(1, UDID_LEN)); + if (udid == nullptr) { + return nullptr; + } + int res = AclGetDevUdid(udid, UDID_LEN); + if (res != 0) { + free(udid); + return nullptr; + } + return udid; +} + +const char* DeviceInfo::CjGetBuildRootHash() +{ + return GetBuildRootHash(); +} + +const char* DeviceInfo::CjGetBuildTime() +{ + return GetBuildTime(); +} + +const char* DeviceInfo::CjGetBuildHost() +{ + return GetBuildHost(); +} + +const char* DeviceInfo::CjGetBuildUser() +{ + return GetBuildUser(); +} + +const char* DeviceInfo::CjGetBuildType() +{ + return GetBuildType(); +} + +const char* DeviceInfo::CjGetVersionId() +{ + return GetVersionId(); +} + +int64_t DeviceInfo::CjGetFirstApiVersion() +{ + return GetFirstApiVersion(); +} + +int64_t DeviceInfo::CjGetSdkApiVersion() +{ + return GetSdkApiVersion(); +} + +int64_t DeviceInfo::CjGetBuildVersion() +{ + return GetBuildVersion(); +} + +int64_t DeviceInfo::CjGetFeatureVersion() +{ + return GetFeatureVersion(); +} + +int64_t DeviceInfo::CjGetSeniorVersion() +{ + return GetSeniorVersion(); +} + +int64_t DeviceInfo::CjGetMajorVersion() +{ + return GetMajorVersion(); +} + +const char* DeviceInfo::CjGetDisplayVersion() +{ + return GetDisplayVersion(); +} + +const char* DeviceInfo::CjGetSerial() +{ + return AclGetSerial(); +} + +const char* DeviceInfo::CjGetOsReleaseType() +{ + return GetOsReleaseType(); +} + +const char* DeviceInfo::CjGetIncrementalVersion() +{ + return GetIncrementalVersion(); +} + +const char* DeviceInfo::CjGetSecurityPatchTag() +{ + return GetSecurityPatchTag(); +} + +const char* DeviceInfo::CjGetAbiList() +{ + return GetAbiList(); +} + +const char* DeviceInfo::CjGetBootloaderVersion() +{ + return GetBootloaderVersion(); +} + +const char* DeviceInfo::CjGetHardwareModel() +{ + return GetHardwareModel(); +} + +const char* DeviceInfo::CjGetSoftwareModel() +{ + return GetSoftwareModel(); +} + +const char* DeviceInfo::CjGetProductSeries() +{ + return GetProductSeries(); +} + +const char* DeviceInfo::CjGetMarketName() +{ + return GetMarketName(); +} + +const char* DeviceInfo::CjGetManufacture() +{ + return GetManufacture(); +} + +const char* DeviceInfo::CjGetDistributionOSName() +{ + return GetDistributionOSName(); +} + +const char* DeviceInfo::CjGetDistributionOSVersion() +{ + return GetDistributionOSVersion(); +} + +int64_t DeviceInfo::CjGetDistributionOSApiVersion() +{ + return GetDistributionOSApiVersion(); +} + +const char* DeviceInfo::CjGetDistributionOSReleaseType() +{ + return GetDistributionOSReleaseType(); +} + +} // DeviceInfo +} // CJSystemapi +} // OHOS diff --git a/interfaces/kits/cj/src_deviceinfo/device_info.h b/interfaces/kits/cj/src_deviceinfo/device_info.h new file mode 100644 index 0000000000000000000000000000000000000000..648ca64caba4a3801dae82161ec83504104ed1de --- /dev/null +++ b/interfaces/kits/cj/src_deviceinfo/device_info.h @@ -0,0 +1,68 @@ +/* + * 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 OHOS_DEVICE_INFO_H +#define OHOS_DEVICE_INFO_H + +#include +#include + +namespace OHOS { +namespace CJSystemapi { +namespace DeviceInfo { + +class DeviceInfo { +public: + static const char* CjGetHardwareProfile(); + static const char* CjGetOsFullName(); + static const char* CjGetProductModel(); + static const char* CjGetBrand(); + static const char* CjGetDeviceType(); + static const char* CjGetUdid(); + static const char* CjGetBuildRootHash(); + static const char* CjGetBuildTime(); + static const char* CjGetBuildHost(); + static const char* CjGetBuildUser(); + static const char* CjGetBuildType(); + static const char* CjGetVersionId(); + static int64_t CjGetFirstApiVersion(); + static int64_t CjGetSdkApiVersion(); + static int64_t CjGetBuildVersion(); + static int64_t CjGetFeatureVersion(); + static int64_t CjGetSeniorVersion(); + static int64_t CjGetMajorVersion(); + static const char* CjGetSerial(); + static const char* CjGetDisplayVersion(); + static const char* CjGetOsReleaseType(); + static const char* CjGetIncrementalVersion(); + static const char* CjGetSecurityPatchTag(); + static const char* CjGetAbiList(); + static const char* CjGetBootloaderVersion(); + static const char* CjGetHardwareModel(); + static const char* CjGetSoftwareModel(); + static const char* CjGetProductSeries(); + static const char* CjGetMarketName(); + static const char* CjGetManufacture(); + static const char* CjGetDistributionOSName(); + static const char* CjGetDistributionOSVersion(); + static int64_t CjGetDistributionOSApiVersion(); + static const char* CjGetDistributionOSReleaseType(); +}; + +} // DeviceInfo +} // CJSystemapi +} // OHOS + +#endif // OHOS_DEVICE_INFO_H \ No newline at end of file diff --git a/interfaces/kits/cj/src_deviceinfo/device_info_ffi.cpp b/interfaces/kits/cj/src_deviceinfo/device_info_ffi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d8098da752d33441120ec3beda0280b86517d10 --- /dev/null +++ b/interfaces/kits/cj/src_deviceinfo/device_info_ffi.cpp @@ -0,0 +1,232 @@ +/* + * 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 "device_info_ffi.h" +#include "device_info.h" +#include "log.h" + +namespace OHOS { +namespace CJSystemapi { +namespace DeviceInfo { + +extern "C" { +const char* FfiOHOSDeviceInfoGetHardwareProfile() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoGetHardwareProfile"); + return DeviceInfo::CjGetHardwareProfile(); +} + +const char* FfiOHOSDeviceInfoOsFullName() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoOsFullName"); + return DeviceInfo::CjGetOsFullName(); +} + +const char* FfiOHOSDeviceInfoProductModel() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoProductModel"); + return DeviceInfo::CjGetProductModel(); +} + +const char* FfiOHOSDeviceInfoBrand() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBrand"); + return DeviceInfo::CjGetBrand(); +} + +const char* FfiOHOSDeviceInfoUdid() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoUdid"); + return DeviceInfo::CjGetUdid(); +} + +const char* FfiOHOSDeviceInfoBuildRootHash() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBuildRootHash"); + return DeviceInfo::CjGetBuildRootHash(); +} + +const char* FfiOHOSDeviceInfoBuildTime() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBuildTime"); + return DeviceInfo::CjGetBuildTime(); +} + +const char* FfiOHOSDeviceInfoBuildHost() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBuildHost"); + return DeviceInfo::CjGetBuildHost(); +} + +const char* FfiOHOSDeviceInfoBuildUser() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBuildUser"); + return DeviceInfo::CjGetBuildUser(); +} + +const char* FfiOHOSDeviceInfoBuildType() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBuildType"); + return DeviceInfo::CjGetBuildType(); +} + +const char* FfiOHOSDeviceInfoDeviceType() +{ + LOGI("DeviceInfo::FfiOHOSFILEGetPath"); + return DeviceInfo::CjGetDeviceType(); +} + +const char* FfiOHOSDeviceInfoVersionId() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoVersionId"); + return DeviceInfo::CjGetVersionId(); +} + +int64_t FfiOHOSDeviceInfoFirstApiVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoFirstApiVersion"); + return DeviceInfo::CjGetFirstApiVersion(); +} + +int64_t FfiOHOSDeviceInfoSdkApiVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoSdkApiVersion"); + return DeviceInfo::CjGetSdkApiVersion(); +} + +int64_t FfiOHOSDeviceInfoBuildVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBuildVersion"); + return DeviceInfo::CjGetBuildVersion(); +} + +int64_t FfiOHOSDeviceInfoFeatureVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoFeatureVersion"); + return DeviceInfo::CjGetFeatureVersion(); +} + +int64_t FfiOHOSDeviceInfoSeniorVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoSeniorVersion"); + return DeviceInfo::CjGetSeniorVersion(); +} + +int64_t FfiOHOSDeviceInfoMajorVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoMajorVersion"); + return DeviceInfo::CjGetMajorVersion(); +} + +const char* FfiOHOSDeviceInfoDisplayVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoDisplayVersion"); + return DeviceInfo::CjGetDisplayVersion(); +} + +const char* FfiOHOSDeviceInfoSerial() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoSerial"); + return DeviceInfo::CjGetSerial(); +} + +const char* FfiOHOSDeviceInfoOsReleaseType() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoOsReleaseType"); + return DeviceInfo::CjGetOsReleaseType(); +} + +const char* FfiOHOSDeviceInfoIncrementalVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoIncrementalVersion"); + return DeviceInfo::CjGetIncrementalVersion(); +} + +const char* FfiOHOSDeviceInfoSecurityPatchTag() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoSecurityPatchTag"); + return DeviceInfo::CjGetSecurityPatchTag(); +} + +const char* FfiOHOSDeviceInfoAbiList() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoAbiList"); + return DeviceInfo::CjGetAbiList(); +} + +const char* FfiOHOSDeviceInfoBootloaderVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoBootloaderVersion"); + return DeviceInfo::CjGetBootloaderVersion(); +} + +const char* FfiOHOSDeviceInfoHardwareModel() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoHardwareModel"); + return DeviceInfo::CjGetHardwareModel(); +} + +const char* FfiOHOSDeviceInfoSoftwareModel() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoSoftwareModel"); + return DeviceInfo::CjGetSoftwareModel(); +} + +const char* FfiOHOSDeviceInfoProductSeries() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoProductSeries"); + return DeviceInfo::CjGetProductSeries(); +} + +const char* FfiOHOSDeviceInfoMarketName() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoMarketName"); + return DeviceInfo::CjGetMarketName(); +} + +const char* FfiOHOSDeviceInfoManufacture() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoManufacture"); + return DeviceInfo::CjGetManufacture(); +} + +const char* FfiOHOSDeviceInfoDistributionOSName() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoDistributionOSName"); + return DeviceInfo::CjGetDistributionOSName(); +} + +const char* FfiOHOSDeviceInfoDistributionOSVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoDistributionOSVersion"); + return DeviceInfo::CjGetDistributionOSVersion(); +} + +int64_t FfiOHOSDeviceInfoDistributionOSApiVersion() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoDistributionOSApiVersion"); + return DeviceInfo::CjGetDistributionOSApiVersion(); +} + +const char* FfiOHOSDeviceInfoDistributionOSReleaseType() +{ + LOGI("DeviceInfo::FfiOHOSDeviceInfoDistributionOSReleaseType"); + return DeviceInfo::CjGetDistributionOSReleaseType(); +} +} + +} // DeviceInfo +} // CJSystemapi +} // OHOS \ No newline at end of file diff --git a/interfaces/kits/cj/src_deviceinfo/device_info_ffi.h b/interfaces/kits/cj/src_deviceinfo/device_info_ffi.h new file mode 100644 index 0000000000000000000000000000000000000000..326ae53c24894e5f2cb27a0caeef19b28da912d2 --- /dev/null +++ b/interfaces/kits/cj/src_deviceinfo/device_info_ffi.h @@ -0,0 +1,59 @@ +/* + * 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 OHOS_DEVICE_INFO_FFI_H +#define OHOS_DEVICE_INFO_FFI_H + +#include "cj_common_ffi.h" +#include + +extern "C" { + FFI_EXPORT const char* FfiOHOSDeviceInfoGetHardwareProfile(); + FFI_EXPORT const char* FfiOHOSDeviceInfoDeviceType(); + FFI_EXPORT const char* FfiOHOSDeviceInfoOsFullName(); + FFI_EXPORT const char* FfiOHOSDeviceInfoProductModel(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBrand(); + FFI_EXPORT const char* FfiOHOSDeviceInfoUdid(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBuildRootHash(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBuildTime(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBuildHost(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBuildUser(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBuildType(); + FFI_EXPORT const char* FfiOHOSDeviceInfoVersionId(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoFirstApiVersion(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoSdkApiVersion(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoBuildVersion(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoFeatureVersion(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoSeniorVersion(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoMajorVersion(); + FFI_EXPORT const char* FfiOHOSDeviceInfoDisplayVersion(); + FFI_EXPORT const char* FfiOHOSDeviceInfoSerial(); + FFI_EXPORT const char* FfiOHOSDeviceInfoOsReleaseType(); + FFI_EXPORT const char* FfiOHOSDeviceInfoIncrementalVersion(); + FFI_EXPORT const char* FfiOHOSDeviceInfoSecurityPatchTag(); + FFI_EXPORT const char* FfiOHOSDeviceInfoAbiList(); + FFI_EXPORT const char* FfiOHOSDeviceInfoBootloaderVersion(); + FFI_EXPORT const char* FfiOHOSDeviceInfoHardwareModel(); + FFI_EXPORT const char* FfiOHOSDeviceInfoSoftwareModel(); + FFI_EXPORT const char* FfiOHOSDeviceInfoProductSeries(); + FFI_EXPORT const char* FfiOHOSDeviceInfoMarketName(); + FFI_EXPORT const char* FfiOHOSDeviceInfoManufacture(); + FFI_EXPORT const char* FfiOHOSDeviceInfoDistributionOSName(); + FFI_EXPORT const char* FfiOHOSDeviceInfoDistributionOSVersion(); + FFI_EXPORT int64_t FfiOHOSDeviceInfoDistributionOSApiVersion(); + FFI_EXPORT const char* FfiOHOSDeviceInfoDistributionOSReleaseType(); +} + +#endif // OHOS_DEVICE_INFO_FFI_H \ No newline at end of file diff --git a/interfaces/kits/cj/src_deviceinfo/device_info_mock.cpp b/interfaces/kits/cj/src_deviceinfo/device_info_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86d065d942f86bbc596bbea1f926bdc75e7be7bd --- /dev/null +++ b/interfaces/kits/cj/src_deviceinfo/device_info_mock.cpp @@ -0,0 +1,53 @@ +/* + * 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 "cj_common_ffi.h" + +extern "C" { +FFI_EXPORT int FfiOHOSDeviceInfoGetHardwareProfile = 0; +FFI_EXPORT int FfiOHOSDeviceInfoDeviceType = 0; +FFI_EXPORT int FfiOHOSDeviceInfoOsFullName = 0; +FFI_EXPORT int FfiOHOSDeviceInfoProductModel = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBrand = 0; +FFI_EXPORT int FfiOHOSDeviceInfoUdid = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBuildRootHash = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBuildTime = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBuildHost = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBuildUser = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBuildType = 0; +FFI_EXPORT int FfiOHOSDeviceInfoVersionId = 0; +FFI_EXPORT int FfiOHOSDeviceInfoFirstApiVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoSdkApiVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBuildVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoFeatureVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoSeniorVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoMajorVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoDisplayVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoSerial = 0; +FFI_EXPORT int FfiOHOSDeviceInfoOsReleaseType = 0; +FFI_EXPORT int FfiOHOSDeviceInfoIncrementalVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoSecurityPatchTag = 0; +FFI_EXPORT int FfiOHOSDeviceInfoAbiList = 0; +FFI_EXPORT int FfiOHOSDeviceInfoBootloaderVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoHardwareModel = 0; +FFI_EXPORT int FfiOHOSDeviceInfoSoftwareModel = 0; +FFI_EXPORT int FfiOHOSDeviceInfoProductSeries = 0; +FFI_EXPORT int FfiOHOSDeviceInfoMarketName = 0; +FFI_EXPORT int FfiOHOSDeviceInfoManufacture = 0; +FFI_EXPORT int FfiOHOSDeviceInfoDistributionOSName = 0; +FFI_EXPORT int FfiOHOSDeviceInfoDistributionOSVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoDistributionOSApiVersion = 0; +FFI_EXPORT int FfiOHOSDeviceInfoDistributionOSReleaseType = 0; +} \ No newline at end of file diff --git a/interfaces/kits/cj/src_deviceinfo/log.h b/interfaces/kits/cj/src_deviceinfo/log.h new file mode 100644 index 0000000000000000000000000000000000000000..7d7801d4071fc54b8942d4ef075cb8311c23cfe9 --- /dev/null +++ b/interfaces/kits/cj/src_deviceinfo/log.h @@ -0,0 +1,42 @@ +/* + * 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 OHOS_DEVICE_INFO_LOG_H +#define OHOS_DEVICE_INFO_LOG_H + +#include "hilog/log.h" + +#ifdef LOG_DOMAIN +#undef LOG_DOMAIN +#endif +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define BASE_DOMAIN 0xD002C00 +#define LOG_DOMAIN (BASE_DOMAIN + 8) +#define LOG_TAG "DEVICE-INFO" + +#define LOGI(...) \ +if (HiLogIsLoggable(LOG_DOMAIN, LOG_TAG, LOG_INFO)) { \ + HILOG_INFO(LOG_CORE, ##__VA_ARGS__); \ +} + +#define LOGE(...) \ +if (HiLogIsLoggable(LOG_DOMAIN, LOG_TAG, LOG_ERROR)) { \ + HILOG_ERROR(LOG_CORE, __VA_ARGS__); \ +} + +#endif // OHOS_DEVICE_INFO_LOG_H \ No newline at end of file diff --git a/interfaces/kits/cj/src_enhance/system_parameter_ffi.cpp b/interfaces/kits/cj/src_enhance/system_parameter_ffi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10b7dc3df11275c7acda8650f41709c9f55a0fd4 --- /dev/null +++ b/interfaces/kits/cj/src_enhance/system_parameter_ffi.cpp @@ -0,0 +1,88 @@ +/* + * 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 "parameter.h" +#include "param_wrapper.h" +#include "sysparam_errno.h" +#include "system_parameter_ffi.h" + +namespace OHOS { +namespace Parameter { + +const int PARA_FAILURE = -1; +const int PARA_SUCCESS = 0; +static constexpr int MAX_VALUE_LENGTH = PARAM_CONST_VALUE_LEN_MAX; + +extern "C" { + char* MallocCString(const char* origin) + { + if (origin == nullptr) { + return nullptr; + } + auto len = strlen(origin) + 1; + char* res = static_cast(malloc(sizeof(char) * len)); + if (res == nullptr) { + return nullptr; + } + return std::char_traits::copy(res, origin, len); + } + + static int GetErrorInfo(int status) + { + switch (status) { + case EC_FAILURE: + case EC_SYSTEM_ERR: + case SYSPARAM_SYSTEM_ERROR: + return -SYSPARAM_SYSTEM_ERROR; + case EC_INVALID: + case SYSPARAM_INVALID_INPUT: + return -SYSPARAM_INVALID_INPUT; + case SYSPARAM_PERMISSION_DENIED: + return -SYSPARAM_PERMISSION_DENIED; + case SYSPARAM_NOT_FOUND: + return -SYSPARAM_NOT_FOUND; + case SYSPARAM_INVALID_VALUE: + return -SYSPARAM_INVALID_VALUE; + default: + return -SYSPARAM_SYSTEM_ERROR; + } + return 0; + } + + RetDataCString FfiOHOSSysTemParameterGet(const char* key, const char* def) + { + RetDataCString ret = {.code = PARA_FAILURE, .data = nullptr}; + std::vector value(MAX_VALUE_LENGTH, 0); + int status = GetParameter(key, (strlen(def) == 0) ? nullptr : def, value.data(), MAX_VALUE_LENGTH); + if (status < PARA_SUCCESS) { + ret.code = GetErrorInfo(status); + } else { + ret.code = PARA_SUCCESS; + ret.data = MallocCString(value.data()); + } + return ret; + } + + int32_t FfiOHOSSysTemParameterSet(const char* key, const char* value) + { + int32_t ret = SetParameter(key, value); + if (ret != 0) { + return GetErrorInfo(ret); + } + return ret; + } +} +} +} \ No newline at end of file diff --git a/interfaces/kits/cj/src_enhance/system_parameter_ffi.h b/interfaces/kits/cj/src_enhance/system_parameter_ffi.h new file mode 100644 index 0000000000000000000000000000000000000000..e140a9593e70ed291fdb315d2ac76b265e56ca89 --- /dev/null +++ b/interfaces/kits/cj/src_enhance/system_parameter_ffi.h @@ -0,0 +1,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 SYSTEM_PARAMETER_FFI_H +#define SYSTEM_PARAMETER_FFI_H + +#include +#include "ffi_remote_data.h" +#include "cj_common_ffi.h" + +extern "C" { + FFI_EXPORT RetDataCString FfiOHOSSysTemParameterGet(const char* key, const char* def); + FFI_EXPORT int32_t FfiOHOSSysTemParameterSet(const char* key, const char* value); +} + +#endif // SYSTEM_PARAMETER_FFI_H \ No newline at end of file diff --git a/interfaces/kits/cj/src_enhance/system_parameter_mock.cpp b/interfaces/kits/cj/src_enhance/system_parameter_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c07c7e17c9a10361a5312c5a9c18831e6fdb810 --- /dev/null +++ b/interfaces/kits/cj/src_enhance/system_parameter_mock.cpp @@ -0,0 +1,20 @@ +/* + * 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 "cj_common_ffi.h" + +extern "C" { +FFI_EXPORT int FfiOHOSSysTemParameterGet = 0; +FFI_EXPORT int FfiOHOSSysTemParameterSet = 0; +} \ No newline at end of file diff --git a/interfaces/kits/jskits/BUILD.gn b/interfaces/kits/jskits/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..db29017da1577dc3332f6497b2f0eb3cc14bfe4b --- /dev/null +++ b/interfaces/kits/jskits/BUILD.gn @@ -0,0 +1,87 @@ +# Copyright (c) 2021-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. + +import("//build/ohos.gni") + +ohos_shared_library("deviceinfo") { + include_dirs = [ "//base/startup/init/interfaces/innerkits/include" ] + + sources = [ "src/native_deviceinfo_js.cpp" ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog_base", + "ipc:ipc_single", + "napi:ace_napi", + "samgr:samgr_proxy", + ] + + defines = [] + if (defined(global_parts_info) && + defined(global_parts_info.bundlemanager_bundle_framework)) { + external_deps += [ "bundle_framework:appexecfwk_base" ] + defines += [ "DEPENDENT_APPEXECFWK_BASE" ] + } + + relative_install_dir = "module" + subsystem_name = "startup" + part_name = "init" +} + +ohos_shared_library("systemparameter") { + include_dirs = [ "src" ] + + sources = [ + "src/native_parameters_js.cpp", + "src/native_parameters_watch.cpp", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "napi:ace_napi", + ] + relative_install_dir = "module" + subsystem_name = "startup" + part_name = "init" +} + +ohos_shared_library("systemparameterenhance") { + include_dirs = [ "src" ] + + sources = [ "src_enhance/native_parameters_js.cpp" ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + ] + + symlink_target_name = [ "libsystemparameterv9.z.so" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "napi:ace_napi", + ] + relative_install_dir = "module" + subsystem_name = "startup" + part_name = "init" +} diff --git a/interfaces/kits/jskits/src/native_deviceinfo_js.cpp b/interfaces/kits/jskits/src/native_deviceinfo_js.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5e2e9dd7effc60dbbb50d0bfd2f4d42c38c3ca1 --- /dev/null +++ b/interfaces/kits/jskits/src/native_deviceinfo_js.cpp @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2021-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 +#include + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "parameter.h" +#include "sysversion.h" +#ifdef DEPENDENT_APPEXECFWK_BASE +#include "bundlemgr/bundle_mgr_proxy.h" +#endif +#include "iservice_registry.h" +#include "if_system_ability_manager.h" +#include "system_ability_definition.h" +#include "beget_ext.h" +#include "init_error.h" +#include "securec.h" + +#ifndef DEVICEINFO_JS_DOMAIN +#define DEVICEINFO_JS_DOMAIN (BASE_DOMAIN + 8) +#endif + +#ifndef DINFO_TAG +#define DINFO_TAG "DEVICEINFO_JS" +#endif + +#define DEVINFO_LOGV(fmt, ...) STARTUP_LOGV(DEVICEINFO_JS_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) +#define DEVINFO_LOGI(fmt, ...) STARTUP_LOGI(DEVICEINFO_JS_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) +#define DEVINFO_LOGW(fmt, ...) STARTUP_LOGW(DEVICEINFO_JS_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) +#define DEVINFO_LOGE(fmt, ...) STARTUP_LOGE(DEVICEINFO_JS_DOMAIN, DINFO_TAG, fmt, ##__VA_ARGS__) + +const int UDID_LEN = 65; +const int ODID_LEN = 37; + +typedef enum { + DEV_INFO_OK, + DEV_INFO_ENULLPTR, + DEV_INFO_EGETODID, + DEV_INFO_ESTRCOPY +} DevInfoError; + +static napi_value GetDeviceType(napi_env env, napi_callback_info info) +{ + napi_value deviceType = nullptr; + const char *value = GetDeviceType(); + if (value == nullptr) { + value = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, value, strlen(value), &deviceType)); + return deviceType; +} + +static napi_value GetManufacture(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *manfactureName = GetManufacture(); + if (manfactureName == nullptr) { + manfactureName = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, manfactureName, strlen(manfactureName), &napiValue)); + return napiValue; +} + +static napi_value GetBrand(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *productBrand = GetBrand(); + if (productBrand == nullptr) { + productBrand = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, productBrand, strlen(productBrand), &napiValue)); + return napiValue; +} + +static napi_value GetMarketName(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *marketName = GetMarketName(); + if (marketName == nullptr) { + marketName = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, marketName, strlen(marketName), &napiValue)); + return napiValue; +} + +static napi_value GetProductSeries(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *productSeries = GetProductSeries(); + if (productSeries == nullptr) { + productSeries = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, productSeries, strlen(productSeries), &napiValue)); + return napiValue; +} + +static napi_value GetProductModel(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *productModel = GetProductModel(); + if (productModel == nullptr) { + productModel = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, productModel, strlen(productModel), &napiValue)); + return napiValue; +} + +static napi_value GetProductModelAlias(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *productModel = GetProductModelAlias(); + if (productModel == nullptr) { + productModel = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, productModel, strlen(productModel), &napiValue)); + return napiValue; +} + +static napi_value GetSoftwareModel(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *softwareModel = GetSoftwareModel(); + if (softwareModel == nullptr) { + softwareModel = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, softwareModel, strlen(softwareModel), &napiValue)); + return napiValue; +} + +static napi_value GetHardwareModel(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *hardwareModel = GetHardwareModel(); + if (hardwareModel == nullptr) { + hardwareModel = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, hardwareModel, strlen(hardwareModel), &napiValue)); + return napiValue; +} + +static napi_value GetHardwareProfile(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *hardwareProfile = GetHardwareProfile(); + if (hardwareProfile == nullptr) { + hardwareProfile = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, hardwareProfile, strlen(hardwareProfile), &napiValue)); + return napiValue; +} + +static napi_value GetSerial(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *serialNumber = AclGetSerial(); + if (serialNumber == nullptr) { + serialNumber = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, serialNumber, strlen(serialNumber), &napiValue)); + return napiValue; +} + +static napi_value GetBootloaderVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *bootloaderVersion = GetBootloaderVersion(); + if (bootloaderVersion == nullptr) { + bootloaderVersion = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, bootloaderVersion, strlen(bootloaderVersion), &napiValue)); + return napiValue; +} + +static napi_value GetAbiList(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *abiList = GetAbiList(); + if (abiList == nullptr) { + abiList = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, abiList, strlen(abiList), &napiValue)); + return napiValue; +} + +static napi_value GetSecurityPatchTag(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *securityPatchTag = GetSecurityPatchTag(); + if (securityPatchTag == nullptr) { + securityPatchTag = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, securityPatchTag, strlen(securityPatchTag), &napiValue)); + return napiValue; +} + +static napi_value GetDisplayVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *productVersion = GetDisplayVersion(); + if (productVersion == nullptr) { + productVersion = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, productVersion, strlen(productVersion), &napiValue)); + return napiValue; +} + +static napi_value GetIncrementalVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *incrementalVersion = GetIncrementalVersion(); + if (incrementalVersion == nullptr) { + incrementalVersion = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, incrementalVersion, strlen(incrementalVersion), &napiValue)); + return napiValue; +} + +static napi_value GetOsReleaseType(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *osReleaseType = GetOsReleaseType(); + if (osReleaseType == nullptr) { + osReleaseType = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, osReleaseType, strlen(osReleaseType), &napiValue)); + return napiValue; +} + +static napi_value GetOSFullName(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *osVersion = GetOSFullName(); + if (osVersion == nullptr) { + osVersion = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, osVersion, strlen(osVersion), &napiValue)); + return napiValue; +} + +static napi_value GetMajorVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int majorVersion = GetMajorVersion(); + + NAPI_CALL(env, napi_create_int32(env, majorVersion, &napiValue)); + return napiValue; +} + +static napi_value GetSeniorVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int seniorVersion = GetSeniorVersion(); + + NAPI_CALL(env, napi_create_int32(env, seniorVersion, &napiValue)); + return napiValue; +} + +static napi_value GetFeatureVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int featureVersion = GetFeatureVersion(); + + NAPI_CALL(env, napi_create_int32(env, featureVersion, &napiValue)); + return napiValue; +} + +static napi_value GetBuildVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int buildVersion = GetBuildVersion(); + + NAPI_CALL(env, napi_create_int32(env, buildVersion, &napiValue)); + return napiValue; +} + +static napi_value GetSdkApiVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int sdkApiVersion = GetSdkApiVersion(); + + NAPI_CALL(env, napi_create_int32(env, sdkApiVersion, &napiValue)); + return napiValue; +} + +static napi_value GetFirstApiVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int firstApiVersion = GetFirstApiVersion(); + + NAPI_CALL(env, napi_create_int32(env, firstApiVersion, &napiValue)); + return napiValue; +} + +static napi_value GetVersionId(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *versionId = GetVersionId(); + if (versionId == nullptr) { + versionId = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, versionId, strlen(versionId), &napiValue)); + return napiValue; +} + +static napi_value GetBuildType(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *buildType = GetBuildType(); + if (buildType == nullptr) { + buildType = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, buildType, strlen(buildType), &napiValue)); + return napiValue; +} + +static napi_value GetBuildUser(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *buildUser = GetBuildUser(); + if (buildUser == nullptr) { + buildUser = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, buildUser, strlen(buildUser), &napiValue)); + return napiValue; +} + +static napi_value GetBuildHost(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *buildHost = GetBuildHost(); + if (buildHost == nullptr) { + buildHost = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, buildHost, strlen(buildHost), &napiValue)); + return napiValue; +} + +static napi_value GetBuildTime(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *buildTime = GetBuildTime(); + if (buildTime == nullptr) { + buildTime = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, buildTime, strlen(buildTime), &napiValue)); + return napiValue; +} + +static napi_value GetBuildRootHash(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *buildRootHash = GetBuildRootHash(); + if (buildRootHash == nullptr) { + buildRootHash = ""; + } + + NAPI_CALL(env, napi_create_string_utf8(env, buildRootHash, strlen(buildRootHash), &napiValue)); + return napiValue; +} + +static napi_value GetDevUdid(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + char localDeviceId[UDID_LEN] = {0}; + AclGetDevUdid(localDeviceId, UDID_LEN); + + NAPI_CALL(env, napi_create_string_utf8(env, localDeviceId, strlen(localDeviceId), &napiValue)); + return napiValue; +} + +static napi_value NAPI_GetDistributionOSName(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *val = GetDistributionOSName(); + + NAPI_CALL(env, napi_create_string_utf8(env, val, strlen(val), &napiValue)); + return napiValue; +} + +static napi_value NAPI_GetDistributionOSVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *val = GetDistributionOSVersion(); + + NAPI_CALL(env, napi_create_string_utf8(env, val, strlen(val), &napiValue)); + return napiValue; +} + +static napi_value NAPI_GetDistributionOSApiVersion(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + int sdkApiVersion = GetDistributionOSApiVersion(); + + NAPI_CALL(env, napi_create_int32(env, sdkApiVersion, &napiValue)); + return napiValue; +} + +static napi_value NAPI_GetDistributionOSApiName(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *val = GetDistributionOSApiName(); + + NAPI_CALL(env, napi_create_string_utf8(env, val, strlen(val), &napiValue)); + return napiValue; +} + +static napi_value NAPI_GetDistributionOSReleaseType(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + const char *val = GetDistributionOSReleaseType(); + + NAPI_CALL(env, napi_create_string_utf8(env, val, strlen(val), &napiValue)); + return napiValue; +} + +static DevInfoError AclGetDevOdid(char *odid, int size) +{ + DevInfoError ret = DEV_INFO_OK; + if (odid[0] != '\0') { + return DEV_INFO_OK; + } + auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (!systemAbilityManager) { + return DEV_INFO_ENULLPTR; + } + + auto remoteObject = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (!remoteObject) { + return DEV_INFO_ENULLPTR; + } + +#ifdef DEPENDENT_APPEXECFWK_BASE + auto bundleMgrProxy = OHOS::iface_cast(remoteObject); + if (!bundleMgrProxy) { + return DEV_INFO_ENULLPTR; + } + + std::string odidStr; + if (bundleMgrProxy->GetOdid(odidStr) != 0) { + return DEV_INFO_EGETODID; + } + + if (strcpy_s(odid, size, odidStr.c_str()) != EOK) { + return DEV_INFO_ESTRCOPY; + } +#else + DEVINFO_LOGE("DEPENDENT_APPEXECFWK_BASE does not exist, The ODID could not be obtained"); + ret = DEV_INFO_EGETODID; +#endif + + return ret; +} + +static napi_value GetDevOdid(napi_env env, napi_callback_info info) +{ + napi_value napiValue = nullptr; + static char odid[ODID_LEN] = {0}; + DevInfoError ret = AclGetDevOdid(odid, ODID_LEN); + if (ret != DEV_INFO_OK) { + DEVINFO_LOGE("GetDevOdid ret:%d", ret); + } + + NAPI_CALL(env, napi_create_string_utf8(env, odid, strlen(odid), &napiValue)); + return napiValue; +} + +EXTERN_C_START +/* + * Module init + */ +static napi_value Init(napi_env env, napi_value exports) +{ + /* + * Attribute definition + */ + napi_property_descriptor desc[] = { + {"deviceType", nullptr, nullptr, GetDeviceType, nullptr, nullptr, napi_default, nullptr}, + {"manufacture", nullptr, nullptr, GetManufacture, nullptr, nullptr, napi_default, nullptr}, + {"brand", nullptr, nullptr, GetBrand, nullptr, nullptr, napi_default, nullptr}, + {"marketName", nullptr, nullptr, GetMarketName, nullptr, nullptr, napi_default, nullptr}, + {"productSeries", nullptr, nullptr, GetProductSeries, nullptr, nullptr, napi_default, nullptr}, + {"productModel", nullptr, nullptr, GetProductModel, nullptr, nullptr, napi_default, nullptr}, + {"softwareModel", nullptr, nullptr, GetSoftwareModel, nullptr, nullptr, napi_default, nullptr}, + {"hardwareModel", nullptr, nullptr, GetHardwareModel, nullptr, nullptr, napi_default, nullptr}, + {"hardwareProfile", nullptr, nullptr, GetHardwareProfile, nullptr, nullptr, napi_default, nullptr}, + {"serial", nullptr, nullptr, GetSerial, nullptr, nullptr, napi_default, nullptr}, + {"bootloaderVersion", nullptr, nullptr, GetBootloaderVersion, nullptr, nullptr, napi_default, nullptr}, + {"abiList", nullptr, nullptr, GetAbiList, nullptr, nullptr, napi_default, nullptr}, + {"securityPatchTag", nullptr, nullptr, GetSecurityPatchTag, nullptr, nullptr, napi_default, nullptr}, + {"displayVersion", nullptr, nullptr, GetDisplayVersion, nullptr, nullptr, napi_default, nullptr}, + {"incrementalVersion", nullptr, nullptr, GetIncrementalVersion, nullptr, nullptr, napi_default, nullptr}, + {"osReleaseType", nullptr, nullptr, GetOsReleaseType, nullptr, nullptr, napi_default, nullptr}, + {"osFullName", nullptr, nullptr, GetOSFullName, nullptr, nullptr, napi_default, nullptr}, + {"majorVersion", nullptr, nullptr, GetMajorVersion, nullptr, nullptr, napi_default, nullptr}, + {"seniorVersion", nullptr, nullptr, GetSeniorVersion, nullptr, nullptr, napi_default, nullptr}, + {"featureVersion", nullptr, nullptr, GetFeatureVersion, nullptr, nullptr, napi_default, nullptr}, + {"buildVersion", nullptr, nullptr, GetBuildVersion, nullptr, nullptr, napi_default, nullptr}, + {"sdkApiVersion", nullptr, nullptr, GetSdkApiVersion, nullptr, nullptr, napi_default, nullptr}, + {"firstApiVersion", nullptr, nullptr, GetFirstApiVersion, nullptr, nullptr, napi_default, nullptr}, + {"versionId", nullptr, nullptr, GetVersionId, nullptr, nullptr, napi_default, nullptr}, + {"buildType", nullptr, nullptr, GetBuildType, nullptr, nullptr, napi_default, nullptr}, + {"buildUser", nullptr, nullptr, GetBuildUser, nullptr, nullptr, napi_default, nullptr}, + {"buildHost", nullptr, nullptr, GetBuildHost, nullptr, nullptr, napi_default, nullptr}, + {"buildTime", nullptr, nullptr, GetBuildTime, nullptr, nullptr, napi_default, nullptr}, + {"buildRootHash", nullptr, nullptr, GetBuildRootHash, nullptr, nullptr, napi_default, nullptr}, + {"udid", nullptr, nullptr, GetDevUdid, nullptr, nullptr, napi_default, nullptr}, + {"distributionOSName", nullptr, nullptr, NAPI_GetDistributionOSName, nullptr, nullptr, napi_default, nullptr}, + {"distributionOSVersion", nullptr, nullptr, NAPI_GetDistributionOSVersion, nullptr, nullptr, napi_default, nullptr}, + {"distributionOSApiVersion", nullptr, nullptr, NAPI_GetDistributionOSApiVersion, nullptr, nullptr, napi_default, nullptr}, + {"distributionOSApiName", nullptr, nullptr, NAPI_GetDistributionOSApiName, nullptr, nullptr, napi_default, nullptr}, + {"distributionOSReleaseType", nullptr, nullptr, NAPI_GetDistributionOSReleaseType, nullptr, nullptr, napi_default, nullptr}, + {"ODID", nullptr, nullptr, GetDevOdid, nullptr, nullptr, napi_default, nullptr}, + {"productModelAlias", nullptr, nullptr, GetProductModelAlias, nullptr, nullptr, napi_default, nullptr}, + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc)); + + return exports; +} +EXTERN_C_END + +/* + * Module definition + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = NULL, + .nm_register_func = Init, + .nm_modname = "deviceInfo", + .nm_priv = ((void *)0), + .reserved = { 0 } +}; +/* + * Module registration function + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} diff --git a/interfaces/kits/jskits/src/native_parameters_js.cpp b/interfaces/kits/jskits/src/native_parameters_js.cpp new file mode 100644 index 0000000000000000000000000000000000000000..461603d5a3c3d91725b91d0701e3d0097bb1ba90 --- /dev/null +++ b/interfaces/kits/jskits/src/native_parameters_js.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2021 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 "native_parameters_js.h" +#include "securec.h" + +static constexpr int MAX_LENGTH = 128; +static constexpr int ARGC_NUMBER = 2; +static constexpr int ARGC_THREE_NUMBER = 3; +static constexpr int BUF_LENGTH = 256; + +using StorageAsyncContext = struct StorageAsyncContext { + napi_env env = nullptr; + napi_async_work work = nullptr; + + char key[BUF_LENGTH] = { 0 }; + size_t keyLen = 0; + char value[BUF_LENGTH] = { 0 }; + size_t valueLen = 0; + napi_deferred deferred = nullptr; + napi_ref callbackRef = nullptr; + + int status = -1; + std::string getValue; +}; + +using StorageAsyncContextPtr = StorageAsyncContext *; + +static void SetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext) +{ + napi_value resource = nullptr; + napi_create_string_utf8(env, "JSStartupSet", NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + asyncContext->status = SetParameter(asyncContext->key, asyncContext->value); + PARAM_JS_LOGV("JSApp set::asyncContext-> status = %d, asyncContext->key = %s, asyncContext->value = %s.", + asyncContext->status, asyncContext->key, asyncContext->value); + }, + [](napi_env env, napi_status status, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + napi_value result[ARGC_NUMBER] = { 0 }; + if (asyncContext->status == 0) { + napi_get_undefined(env, &result[0]); + napi_get_undefined(env, &result[1]); + } else { + napi_value value = nullptr; + napi_create_object(env, &result[0]); + napi_create_int32(env, asyncContext->status, &value); + napi_set_named_property(env, result[0], "code", value); + napi_get_undefined(env, &result[1]); + } + + if (asyncContext->deferred) { + if (asyncContext->status == 0) { + napi_resolve_deferred(env, asyncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, asyncContext->deferred, result[0]); + } + } else { + napi_value callback = nullptr; + napi_value callResult = nullptr; + napi_get_reference_value(env, asyncContext->callbackRef, &callback); + napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult); + napi_delete_reference(env, asyncContext->callbackRef); + } + napi_delete_async_work(env, asyncContext->work); + delete asyncContext; + }, + reinterpret_cast(asyncContext), &asyncContext->work); + napi_queue_async_work(env, asyncContext->work); +} + +static napi_value Set(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_THREE_NUMBER; + napi_value argv[ARGC_THREE_NUMBER] = { nullptr }; + napi_value thisVar = nullptr; + void *data = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); + NAPI_ASSERT(env, argc >= ARGC_NUMBER, "requires 2 parameter"); + StorageAsyncContextPtr asyncContext = new StorageAsyncContext(); + asyncContext->env = env; + for (size_t i = 0; i < argc; i++) { + napi_valuetype valueType = napi_null; + napi_typeof(env, argv[i], &valueType); + + if (i == 0 && valueType == napi_string) { + napi_get_value_string_utf8(env, argv[i], asyncContext->key, + BUF_LENGTH - 1, &asyncContext->keyLen); + } else if (i == 1 && valueType == napi_string) { + napi_get_value_string_utf8(env, argv[i], asyncContext->value, + BUF_LENGTH - 1, &asyncContext->valueLen); + } else if (i == ARGC_NUMBER && valueType == napi_function) { + napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); + } else { + delete asyncContext; + NAPI_ASSERT(env, false, "type mismatch"); + } + } + + napi_value result = nullptr; + if (asyncContext->callbackRef == nullptr) { + napi_create_promise(env, &asyncContext->deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + SetCallbackWork(env, asyncContext); + return result; +} + +static napi_value SetSync(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_NUMBER; + napi_value args[ARGC_NUMBER] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + NAPI_ASSERT(env, argc == ARGC_NUMBER, "Wrong number of arguments"); + napi_valuetype valuetype0 = napi_null; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + napi_valuetype valuetype1 = napi_null; + NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NAPI_ASSERT(env, valuetype0 == napi_string && valuetype1 == napi_string, "Wrong argument type. string expected."); + + char keyBuf[BUF_LENGTH] = { 0 }; + size_t keySize = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], keyBuf, BUF_LENGTH - 1, &keySize)); + if (keySize >= MAX_LENGTH) { + return nullptr; + } + + char valueBuf[BUF_LENGTH] = { 0 }; + size_t valueSize = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, args[1], valueBuf, BUF_LENGTH - 1, &valueSize)); + if (valueSize >= MAX_LENGTH) { + return nullptr; + } + + std::string keyStr = keyBuf; + std::string valueStr = valueBuf; + int setResult = SetParameter(keyStr.c_str(), valueStr.c_str()); + PARAM_JS_LOGV("JSApp SetSync::setResult = %d, input keyBuf = %s.", setResult, keyBuf); + + napi_value napiValue = nullptr; + if (setResult != 0) { // set failed + std::stringstream ss; + ss << "set: " << keyStr << " failed, error code: " << setResult; + napi_throw_error((env), nullptr, ss.str().c_str()); + } else { + napi_get_undefined(env, &napiValue); + } + return napiValue; +} + +static napi_value GetSync(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_NUMBER; + napi_value args[ARGC_NUMBER] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + NAPI_ASSERT(env, argc == 1 || argc == ARGC_NUMBER, "Wrong number of arguments"); + napi_valuetype valuetype0 = napi_null; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_string, "Wrong argument type. Numbers expected."); + + napi_valuetype valuetype1 = napi_null; + if (argc == ARGC_NUMBER) { + NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + NAPI_ASSERT(env, (valuetype1 == napi_string) || (valuetype1 == napi_undefined), + "Wrong argument type. string expected."); + } + + char keyBuf[BUF_LENGTH] = { 0 }; + size_t keySize = 0; + NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], keyBuf, BUF_LENGTH - 1, &keySize)); + if (keySize >= MAX_LENGTH) { + return nullptr; + } + + std::string keyStr = keyBuf; + std::string valueStr = ""; + std::string getValue = ""; + if (argc == ARGC_NUMBER) { + char valueBuf[BUF_LENGTH] = { 0 }; + size_t valueSize = 0; + if (valuetype1 == napi_undefined) { + valueStr = ""; + } else { + NAPI_CALL(env, napi_get_value_string_utf8(env, args[1], valueBuf, BUF_LENGTH - 1, &valueSize)); + if (valueSize >= MAX_LENGTH) { + return nullptr; + } + valueStr = valueBuf; + } + } + int ret = OHOS::system::GetStringParameter(keyStr, getValue, valueStr); + PARAM_JS_LOGV("JSApp GetSync::getValue = %s, input keyStr = %s.", getValue.c_str(), keyBuf); + + napi_value napiValue = nullptr; + if (ret == 0) { + NAPI_CALL(env, napi_create_string_utf8(env, getValue.c_str(), strlen(getValue.c_str()), &napiValue)); + } + return napiValue; +} + +static void GetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext) +{ + napi_value resource = nullptr; + napi_create_string_utf8(env, "JSStartupGet", NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + asyncContext->status = + OHOS::system::GetStringParameter(asyncContext->key, asyncContext->getValue, asyncContext->value); + PARAM_JS_LOGV("JSApp get status = %d, asyncContext->getValue = %s, asyncContext->key = %s, value = %s.", + asyncContext->status, asyncContext->getValue.c_str(), asyncContext->key, asyncContext->value); + }, + [](napi_env env, napi_status status, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + napi_value result[ARGC_NUMBER] = { 0 }; + if (asyncContext->status == 0) { + napi_get_undefined(env, &result[0]); + napi_create_string_utf8(env, asyncContext->getValue.c_str(), strlen(asyncContext->getValue.c_str()), + &result[1]); + } else { + napi_value message = nullptr; + napi_create_object(env, &result[0]); + napi_create_int32(env, asyncContext->status, &message); + napi_set_named_property(env, result[0], "code", message); + napi_get_undefined(env, &result[1]); + } + + if (asyncContext->deferred) { + if (asyncContext->status == 0) { + napi_resolve_deferred(env, asyncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, asyncContext->deferred, result[0]); + } + } else { + napi_value callback = nullptr; + napi_value callResult = nullptr; + napi_get_reference_value(env, asyncContext->callbackRef, &callback); + napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult); + napi_delete_reference(env, asyncContext->callbackRef); + } + napi_delete_async_work(env, asyncContext->work); + delete asyncContext; + }, + reinterpret_cast(asyncContext), &asyncContext->work); + napi_queue_async_work(env, asyncContext->work); +} + +static napi_value Get(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_THREE_NUMBER; + napi_value argv[ARGC_THREE_NUMBER] = { nullptr }; + napi_value thisVar = nullptr; + void *data = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); + NAPI_ASSERT(env, argc >= 1, "requires 1 parameter"); + StorageAsyncContextPtr asyncContext = new StorageAsyncContext(); + asyncContext->env = env; + for (size_t i = 0; i < argc; i++) { + napi_valuetype valueType = napi_null; + napi_typeof(env, argv[i], &valueType); + + if (i == 0 && valueType == napi_string) { + napi_get_value_string_utf8(env, argv[i], asyncContext->key, + BUF_LENGTH - 1, &asyncContext->keyLen); + } else if (i == 1 && valueType == napi_string) { + napi_get_value_string_utf8(env, argv[i], asyncContext->value, + BUF_LENGTH - 1, &asyncContext->valueLen); + } else if (i == 1 && valueType == napi_undefined) { + strcpy_s(asyncContext->value, BUF_LENGTH, "\0"); + } else if (i == 1 && valueType == napi_function) { + napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); + break; + } else if (i == ARGC_NUMBER && valueType == napi_function) { + napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); + } else { + delete asyncContext; + NAPI_ASSERT(env, false, "type mismatch"); + } + } + + napi_value result = nullptr; + if (asyncContext->callbackRef == nullptr) { + napi_create_promise(env, &asyncContext->deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + GetCallbackWork(env, asyncContext); + return result; +} + +EXTERN_C_START +/* + * Module init + */ +static napi_value Init(napi_env env, napi_value exports) +{ + /* + * Attribute definition + */ + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("set", Set), + DECLARE_NAPI_FUNCTION("setSync", SetSync), + DECLARE_NAPI_FUNCTION("get", Get), + DECLARE_NAPI_FUNCTION("getSync", GetSync), + DECLARE_NAPI_FUNCTION("wait", ParamWait), + DECLARE_NAPI_FUNCTION("getWatcher", GetWatcher) + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc)); + return RegisterWatcher(env, exports); +} +EXTERN_C_END + +/* + * Module definition + */ +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = NULL, + .nm_register_func = Init, + .nm_modname = "systemparameter", + .nm_priv = ((void *)0), + .reserved = { 0 } +}; + +/* + * Module registration function + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} diff --git a/interfaces/kits/jskits/src/native_parameters_js.h b/interfaces/kits/jskits/src/native_parameters_js.h new file mode 100755 index 0000000000000000000000000000000000000000..152aae40f58a084e8c27a8948a2295cfd50544ee --- /dev/null +++ b/interfaces/kits/jskits/src/native_parameters_js.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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 NATIVE_PARAMETERS_JS_H +#define NATIVE_PARAMETERS_JS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "beget_ext.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "param_wrapper.h" +#include "parameter.h" + +#define PARAM_JS_DOMAIN (BASE_DOMAIN + 0xc) +#define PARAM_JS_LOGI(fmt, ...) STARTUP_LOGI(PARAM_JS_DOMAIN, "PARAM_JS", fmt, ##__VA_ARGS__) +#define PARAM_JS_LOGE(fmt, ...) STARTUP_LOGE(PARAM_JS_DOMAIN, "PARAM_JS", fmt, ##__VA_ARGS__) +#define PARAM_JS_LOGV(fmt, ...) STARTUP_LOGV(PARAM_JS_DOMAIN, "PARAM_JS", fmt, ##__VA_ARGS__) +#define PARAM_JS_LOGW(fmt, ...) STARTUP_LOGW(PARAM_JS_DOMAIN, "PARAM_JS", fmt, ##__VA_ARGS__) + +#define PARAM_JS_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + PARAM_JS_LOGE(__VA_ARGS__); \ + exper; \ + } + +EXTERN_C_START +napi_value GetWatcher(napi_env env, napi_callback_info info); +napi_value ParamWait(napi_env env, napi_callback_info info); +napi_value RegisterWatcher(napi_env env, napi_value exports); +EXTERN_C_END + +#endif // NATIVE_PARAMETERS_JS_H \ No newline at end of file diff --git a/interfaces/kits/jskits/src/native_parameters_watch.cpp b/interfaces/kits/jskits/src/native_parameters_watch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..acd70a04a848d8f52fdfba8003562a1b2f17a791 --- /dev/null +++ b/interfaces/kits/jskits/src/native_parameters_watch.cpp @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2021 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 "native_parameters_js.h" +#include "uv.h" + +using namespace OHOS::system; +static constexpr int ARGC_NUMBER = 2; +static constexpr int BUF_LENGTH = 128; + +static napi_ref g_paramWatchRef; + +using ParamAsyncContext = struct ParamAsyncContext { + napi_env env = nullptr; + napi_async_work work = nullptr; + + char key[BUF_LENGTH] = { 0 }; + size_t keyLen = 0; + char value[BUF_LENGTH] = { 0 }; + size_t valueLen = 0; + int32_t timeout = 0; + napi_deferred deferred = nullptr; + napi_ref callbackRef = nullptr; + + int status = -1; + std::string getValue; +}; + +using ParamWatcher = struct ParamWatcher { + napi_env env = nullptr; + napi_ref thisVarRef = nullptr; + char keyPrefix[BUF_LENGTH] = { 0 }; + size_t keyLen = 0; + bool notifySwitch = false; + bool startWatch = false; + std::mutex mutex {}; + napi_ref currCallbackRef = nullptr; + std::map callbackReferences {}; +}; + +using ParamWatcherWork = struct ParamWatcherWork { + napi_async_work work = nullptr; + ParamWatcher *watcher = nullptr; + bool startWatch = false; +}; + +using ParamChangeValue = struct ParamChangeValue { + uv_work_t work; + ParamWatcher *watcher; + std::string key; + std::string value; +}; + +using ParamAsyncContextPtr = ParamAsyncContext *; +using ParamWatcherPtr = ParamWatcher *; + +static napi_value NapiGetNull(napi_env env) +{ + napi_value result = 0; + napi_get_null(env, &result); + return result; +} + +static napi_value GetNapiValue(napi_env env, int val) +{ + napi_value result = nullptr; + napi_create_int32(env, val, &result); + return result; +} + +static int GetParamValue(napi_env env, napi_value arg, napi_valuetype valueType, char *buffer, size_t &buffLen) +{ + napi_valuetype type = napi_null; + napi_typeof(env, arg, &type); + PARAM_JS_CHECK(type == valueType, return -1, "Invalid type %d %d", type, valueType); + napi_status status = napi_ok; + if (valueType == napi_string) { + status = napi_get_value_string_utf8(env, arg, buffer, buffLen, &buffLen); + } else if (valueType == napi_number) { + status = napi_get_value_int32(env, arg, reinterpret_cast(buffer)); + } + return status; +} + +static void WaitCallbackWork(napi_env env, ParamAsyncContextPtr asyncContext) +{ + napi_value resource = nullptr; + napi_create_string_utf8(env, "JSStartupGet", NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + ParamAsyncContext *asyncContext = reinterpret_cast(data); + asyncContext->status = WaitParameter(asyncContext->key, asyncContext->value, asyncContext->timeout); + PARAM_JS_LOGV("JSApp Wait status: %d, key: %s", asyncContext->status, asyncContext->key); + }, + [](napi_env env, napi_status status, void *data) { + ParamAsyncContext *asyncContext = reinterpret_cast(data); + napi_value result[ARGC_NUMBER] = { 0 }; + napi_value message = nullptr; + napi_create_object(env, &result[0]); + napi_create_int32(env, asyncContext->status, &message); + napi_set_named_property(env, result[0], "code", message); + napi_get_undefined(env, &result[1]); // only one param + + PARAM_JS_LOGV("JSApp Wait status: %d, key: %s ", asyncContext->status, asyncContext->key); + if (asyncContext->deferred) { + if (asyncContext->status == 0) { + napi_resolve_deferred(env, asyncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, asyncContext->deferred, result[0]); + } + } else { + napi_value callbackRef = nullptr; + napi_value callResult = nullptr; + napi_status status = napi_get_reference_value(env, asyncContext->callbackRef, &callbackRef); + PARAM_JS_CHECK(status == 0 && callbackRef != nullptr, return, "Failed to get reference "); + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_call_function(env, undefined, callbackRef, ARGC_NUMBER, result, &callResult); + napi_delete_reference(env, asyncContext->callbackRef); + } + napi_delete_async_work(env, asyncContext->work); + delete asyncContext; + }, + reinterpret_cast(asyncContext), &asyncContext->work); + napi_queue_async_work(env, asyncContext->work); +} + +napi_value ParamWait(napi_env env, napi_callback_info info) +{ + constexpr int PARAM_TIMEOUT_INDEX = 2; + constexpr int ARGC_THREE_NUMBER = 3; + size_t argc = ARGC_THREE_NUMBER + 1; + napi_value argv[ARGC_THREE_NUMBER + 1]; + napi_value thisVar = nullptr; + napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + PARAM_JS_CHECK(status == napi_ok, return GetNapiValue(env, status), "Failed to get cb info"); + PARAM_JS_CHECK(argc >= ARGC_THREE_NUMBER, return GetNapiValue(env, status), "Failed to get argc"); + + ParamAsyncContextPtr asyncContext = new ParamAsyncContext(); + PARAM_JS_CHECK(asyncContext != nullptr, return GetNapiValue(env, status), "Failed to create context"); + asyncContext->env = env; + + // get param key + asyncContext->keyLen = BUF_LENGTH - 1; + asyncContext->valueLen = BUF_LENGTH - 1; + size_t len = sizeof(asyncContext->timeout); + int ret = GetParamValue(env, argv[0], napi_string, asyncContext->key, asyncContext->keyLen); + PARAM_JS_CHECK(ret == 0, delete asyncContext; + return GetNapiValue(env, ret), "Invalid param for wait"); + ret = GetParamValue(env, argv[1], napi_string, asyncContext->value, asyncContext->valueLen); + PARAM_JS_CHECK(ret == 0, delete asyncContext; + return GetNapiValue(env, ret), "Invalid param for wait"); + ret = GetParamValue(env, argv[PARAM_TIMEOUT_INDEX], napi_number, (char *)&asyncContext->timeout, len); + PARAM_JS_CHECK(ret == 0, delete asyncContext; + return GetNapiValue(env, ret), "Invalid param for wait"); + if (argc > ARGC_THREE_NUMBER) { + napi_valuetype valueType = napi_null; + napi_typeof(env, argv[ARGC_THREE_NUMBER], &valueType); + PARAM_JS_CHECK(valueType == napi_function, delete asyncContext; + return GetNapiValue(env, ret), "Invalid param for wait callbackRef"); + napi_create_reference(env, argv[ARGC_THREE_NUMBER], 1, &asyncContext->callbackRef); + } + PARAM_JS_LOGV("JSApp Wait key: %s, value: %s timeout %d.", + asyncContext->key, asyncContext->value, asyncContext->timeout); + + napi_value result = nullptr; + if (asyncContext->callbackRef == nullptr) { + napi_create_promise(env, &asyncContext->deferred, &result); + } else { + result = GetNapiValue(env, 0); + } + WaitCallbackWork(env, asyncContext); + return result; +} + +static bool GetFristRefence(ParamWatcherPtr watcher, uint32_t &next) +{ + std::lock_guard lock(watcher->mutex); + auto iter = watcher->callbackReferences.begin(); + if (iter != watcher->callbackReferences.end()) { + next = watcher->callbackReferences.begin()->first; + return true; + } + return false; +} + +static napi_ref GetWatcherReference(ParamWatcherPtr watcher, uint32_t next) +{ + std::lock_guard lock(watcher->mutex); + auto iter = watcher->callbackReferences.find(next); + if (iter != watcher->callbackReferences.end()) { + return iter->second; + } + return nullptr; +} + +static uint32_t GetNextRefence(ParamWatcherPtr watcher, uint32_t &next) +{ + std::lock_guard lock(watcher->mutex); + auto iter = watcher->callbackReferences.upper_bound(next); + if (iter == watcher->callbackReferences.end()) { + return false; + } + next = iter->first; + return true; +} + +static void AddWatcherCallback(ParamWatcherPtr watcher, napi_ref callbackRef) +{ + static uint32_t watcherId = 0; + std::lock_guard lock(watcher->mutex); + watcherId++; + watcher->callbackReferences[watcherId] = callbackRef; + PARAM_JS_LOGV("JSApp watcher add watcher callback %s %u.", + watcher->keyPrefix, watcherId); +} + +static void DelWatcherCallback(ParamWatcherPtr watcher, uint32_t next) +{ + PARAM_JS_LOGV("JSApp watcher key %s delete callback %u", watcher->keyPrefix, next); + std::lock_guard lock(watcher->mutex); + watcher->callbackReferences.erase(next); +} + +static void DelCallbackRef(napi_env env, ParamWatcherPtr watcher, napi_ref callbackRef, uint32_t id) +{ + std::lock_guard lock(watcher->mutex); + if (callbackRef == watcher->currCallbackRef) { + PARAM_JS_LOGV("JSApp watcher key %s has been callbacked %u.", + watcher->keyPrefix, id); + watcher->currCallbackRef = nullptr; + } else { + napi_delete_reference(env, callbackRef); + } + watcher->callbackReferences.erase(id); +} + +static void DelCallback(napi_env env, napi_value callback, ParamWatcherPtr watcher) +{ + bool isEquals = false; + uint32_t next = 0; + bool ret = GetFristRefence(watcher, next); + while (ret) { + napi_ref callbackRef = GetWatcherReference(watcher, next); + if (callbackRef == nullptr) { + PARAM_JS_LOGV("JSApp watcher key %s callbackRef has been deleted %d.", watcher->keyPrefix, next); + DelWatcherCallback(watcher, next); + } else if (callback != nullptr) { + napi_value handler = nullptr; + napi_get_reference_value(env, callbackRef, &handler); + napi_strict_equals(env, handler, callback, &isEquals); + if (isEquals) { + DelCallbackRef(env, watcher, callbackRef, next); + break; + } + } else { + DelCallbackRef(env, watcher, callbackRef, next); + } + ret = GetNextRefence(watcher, next); + } +} + +static bool CheckCallbackEqual(napi_env env, napi_value callback, ParamWatcherPtr watcher) +{ + bool isEquals = false; + uint32_t next = 0; + bool ret = GetFristRefence(watcher, next); + while (ret) { + napi_ref callbackRef = GetWatcherReference(watcher, next); + if (callbackRef != nullptr) { + napi_value handler = nullptr; + napi_get_reference_value(env, callbackRef, &handler); + napi_strict_equals(env, handler, callback, &isEquals); + if (isEquals) { + return true; + } + } + ret = GetNextRefence(watcher, next); + } + return false; +} + +static napi_value ParamWatchConstructor(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1]; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + ParamWatcherPtr watcher = new ParamWatcher(); + PARAM_JS_CHECK(watcher != nullptr, return NapiGetNull(env), "Failed to create param watcher"); + napi_status status = napi_create_reference(env, thisVar, 1, &watcher->thisVarRef); + PARAM_JS_CHECK(status == 0, delete watcher; + return NapiGetNull(env), "Failed to create reference %d", status); + + napi_wrap( + env, thisVar, watcher, + [](napi_env env, void *data, void *hint) { + ParamWatcherPtr watcher = static_cast(data); + if (watcher) { + DelCallback(env, nullptr, watcher); + WatchParameter(watcher->keyPrefix, nullptr, nullptr); + delete watcher; + watcher = nullptr; + } + }, + nullptr, nullptr); + return thisVar; +} + +napi_value GetWatcher(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value argv[1]; + napi_value thisVar = nullptr; + void *data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + + napi_value obj = thisVar; + ParamWatcherPtr watcher = nullptr; + napi_unwrap(env, thisVar, (void **)&watcher); + if (watcher == nullptr) { // check if watcher exist + napi_value constructor = nullptr; + int status = napi_get_reference_value(env, g_paramWatchRef, &constructor); + PARAM_JS_CHECK(status == 0, return NapiGetNull(env), "Failed to get reference"); + status = napi_new_instance(env, constructor, 0, nullptr, &obj); + PARAM_JS_CHECK(status == 0, return NapiGetNull(env), "Failed to create instance for watcher"); + napi_unwrap(env, obj, (void **)&watcher); + } + if (watcher != nullptr) { + watcher->keyLen = BUF_LENGTH; + int ret = GetParamValue(env, argv[0], napi_string, watcher->keyPrefix, watcher->keyLen); + PARAM_JS_CHECK(ret == 0, return NapiGetNull(env), "Failed to get key prefix"); + PARAM_JS_LOGV("JSApp watcher keyPrefix = %s ", watcher->keyPrefix); + ret = WatchParameter(watcher->keyPrefix, nullptr, watcher); + PARAM_JS_CHECK(ret == 0, return NapiGetNull(env), "Failed to get watcher ret %d", ret); + } + return obj; +} + +static ParamWatcherPtr GetWatcherInfo(napi_env env, napi_callback_info info, napi_value *callback) +{ + size_t argc = ARGC_NUMBER; + napi_value argv[ARGC_NUMBER]; + napi_value thisVar = nullptr; + void *data = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); + + size_t typeLen = BUF_LENGTH - 1; + std::vector eventType(typeLen, 0); + int ret = GetParamValue(env, argv[0], napi_string, eventType.data(), typeLen); + PARAM_JS_CHECK(ret == 0, return nullptr, "Failed to get event type"); + if (strcmp(eventType.data(), "valueChange") != 0) { + return nullptr; + } + // argv[1]:callbackRef + if (argc > 1) { + napi_valuetype valuetype; + napi_status status = napi_typeof(env, argv[1], &valuetype); + PARAM_JS_CHECK(status == 0, return nullptr, "Failed to get type"); + PARAM_JS_CHECK(valuetype == napi_function, return nullptr, "Invalid type %d", valuetype); + *callback = argv[1]; + } + ParamWatcherPtr watcher = nullptr; + napi_unwrap(env, thisVar, (void **)&watcher); + return watcher; +} + +static void NotifyValueChange(ParamWatcherPtr watcher, uint32_t id, napi_value thisVar, const napi_value result[]) +{ + napi_ref callbackRef = GetWatcherReference(watcher, id); + PARAM_JS_CHECK(callbackRef != nullptr, return, + "Failed to get callback for %s %d", watcher->keyPrefix, id); + napi_value callbackFunc = nullptr; + napi_status status = napi_get_reference_value(watcher->env, callbackRef, &callbackFunc); + PARAM_JS_CHECK(status == 0 && callbackFunc != nullptr, return, + "Failed to get callback for %s %d", watcher->keyPrefix, id); + { + std::lock_guard lock(watcher->mutex); + watcher->currCallbackRef = callbackRef; + } + + napi_value callbackResult = nullptr; + napi_call_function(watcher->env, thisVar, callbackFunc, ARGC_NUMBER, result, &callbackResult); + + { + std::lock_guard lock(watcher->mutex); + if (watcher->currCallbackRef == nullptr) { + PARAM_JS_LOGV("JSApp watcher notify key %s callback deleted watcherId %u", + watcher->keyPrefix, id); + napi_delete_reference(watcher->env, callbackRef); + } + watcher->currCallbackRef = nullptr; + } +} + +static void HandleParameterChange(ParamWatcherPtr watcher, const char *key, const char *value) +{ + napi_handle_scope scope = nullptr; + napi_status status = napi_open_handle_scope(watcher->env, &scope); + PARAM_JS_CHECK(status == 0, return, "Failed to get reference "); + napi_value result[ARGC_NUMBER] = { 0 }; + napi_create_string_utf8(watcher->env, key, strlen(key), &result[0]); + napi_create_string_utf8(watcher->env, value, strlen(value), &result[1]); + napi_value thisVar = nullptr; + status = napi_get_reference_value(watcher->env, watcher->thisVarRef, &thisVar); + PARAM_JS_CHECK(status == 0 && thisVar != nullptr, napi_close_handle_scope(watcher->env, scope); + return, "Failed to get reference "); + uint32_t next = 0; + bool ret = GetFristRefence(watcher, next); + while (ret) { + NotifyValueChange(watcher, next, thisVar, result); + ret = GetNextRefence(watcher, next); + } + napi_close_handle_scope(watcher->env, scope); + PARAM_JS_LOGV("JSApp watcher ProcessParamChange %s finish", key); +} + +static void ProcessParamChange(const char *key, const char *value, void *context) +{ + ParamWatcherPtr watcher = static_cast(context); + PARAM_JS_CHECK(watcher != nullptr && watcher->env != nullptr, return, "Invalid param"); + PARAM_JS_CHECK(watcher->callbackReferences.size() > 0, return, "No callback for watcher"); + + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(watcher->env, &loop); + PARAM_JS_CHECK(loop != nullptr, return, "Failed to get loop for %s", watcher->keyPrefix); + ParamChangeValue *change = new (std::nothrow) ParamChangeValue; + PARAM_JS_CHECK(change != nullptr, return, "Failed to get change for %s", watcher->keyPrefix); + change->work.data = reinterpret_cast(change); + change->watcher = watcher; + change->key = std::string(key); + change->value = std::string(value); + int ret = uv_queue_work(loop, &change->work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int result) { + ParamChangeValue *change = reinterpret_cast(work->data); + HandleParameterChange(change->watcher, change->key.c_str(), change->value.c_str()); + delete change; + change = nullptr; + }); + PARAM_JS_CHECK(ret == 0, delete change; + return, "Failed to start work for %s", watcher->keyPrefix); +} + +static void WatchCallbackWork(napi_env env, ParamWatcherPtr watcher) +{ + PARAM_JS_LOGV("JSApp WatchCallbackWork key: %s", watcher->keyPrefix); + ParamWatcherWork *worker = new ParamWatcherWork(); + PARAM_JS_CHECK(worker != nullptr, return, "Failed to create worker "); + worker->watcher = watcher; + worker->work = nullptr; + worker->startWatch = watcher->startWatch; + + napi_value resource = nullptr; + napi_create_string_utf8(env, "JSStartupWatch", NAPI_AUTO_LENGTH, &resource); + napi_create_async_work(env, nullptr, resource, + [](napi_env env, void *data) { + ParamWatcherWork *worker = reinterpret_cast(data); + PARAM_JS_CHECK(worker != nullptr && worker->watcher != nullptr, return, "Invalid worker "); + int status = WatchParameter(worker->watcher->keyPrefix, + worker->startWatch ? ProcessParamChange : nullptr, worker->watcher); + PARAM_JS_LOGV("JSApp WatchCallbackWork %s status: %d, key: %s", + worker->startWatch ? "on" : "off", status, worker->watcher->keyPrefix); + }, + [](napi_env env, napi_status status, void *data) { + ParamWatcherWork *worker = reinterpret_cast(data); + PARAM_JS_LOGV("JSApp WatchCallbackWork delete %s key: %s", + worker->startWatch ? "on" : "off", worker->watcher->keyPrefix); + napi_delete_async_work(env, worker->work); + delete worker; + }, + reinterpret_cast(worker), &worker->work); + napi_queue_async_work(env, worker->work); +} + +static napi_value SwithWatchOn(napi_env env, napi_callback_info info) +{ + napi_value callback = nullptr; + ParamWatcherPtr watcher = GetWatcherInfo(env, info, &callback); + PARAM_JS_CHECK(watcher != nullptr, return GetNapiValue(env, -1), "Failed to get watcher switch param"); + + if (CheckCallbackEqual(env, callback, watcher)) { + PARAM_JS_LOGE("JSApp watcher repeater switch on %s", watcher->keyPrefix); + return 0; + } + PARAM_JS_LOGV("JSApp watcher on %s", watcher->keyPrefix); + // save callback + napi_ref callbackRef; + napi_create_reference(env, callback, 1, &callbackRef); + AddWatcherCallback(watcher, callbackRef); + watcher->env = env; + { + std::lock_guard lock(watcher->mutex); + if (watcher->startWatch) { + return GetNapiValue(env, 0); + } + watcher->startWatch = true; + } + + PARAM_JS_LOGV("JSApp watcher add %s", watcher->keyPrefix); + WatchCallbackWork(env, watcher); + PARAM_JS_LOGV("JSApp watcher on %s finish", watcher->keyPrefix); + return GetNapiValue(env, 0); +} + +static napi_value SwithWatchOff(napi_env env, napi_callback_info info) +{ + napi_value callback = nullptr; + ParamWatcherPtr watcher = GetWatcherInfo(env, info, &callback); + PARAM_JS_CHECK(watcher != nullptr, return GetNapiValue(env, -1), "Failed to get watcher"); + PARAM_JS_LOGV("JSApp watcher off %s", watcher->keyPrefix); + DelCallback(env, callback, watcher); + { + std::lock_guard lock(watcher->mutex); + if (watcher->callbackReferences.size() == 0) { + watcher->startWatch = false; + WatchCallbackWork(env, watcher); + } + } + return GetNapiValue(env, 0); +} + +napi_value RegisterWatcher(napi_env env, napi_value exports) +{ + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("on", SwithWatchOn), + DECLARE_NAPI_FUNCTION("off", SwithWatchOff), + }; + + napi_value result = nullptr; + NAPI_CALL(env, + napi_define_class(env, + "paramWatcher", + NAPI_AUTO_LENGTH, + ParamWatchConstructor, + nullptr, + sizeof(properties) / sizeof(*properties), + properties, + &result)); + napi_set_named_property(env, exports, "paramWatcher", result); + napi_create_reference(env, result, 1, &g_paramWatchRef); + return exports; +} diff --git a/interfaces/kits/jskits/src_enhance/native_parameters_js.cpp b/interfaces/kits/jskits/src_enhance/native_parameters_js.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a675e2aa7114ab20d137b3d875de387333f4f3a --- /dev/null +++ b/interfaces/kits/jskits/src_enhance/native_parameters_js.cpp @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2021 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 "native_parameters_js.h" +#include "sysparam_errno.h" + +static constexpr int ARGC_NUMBER = 2; +static constexpr int ARGC_THREE_NUMBER = 3; +static constexpr int MAX_NAME_LENGTH = 128; +static constexpr int MAX_VALUE_LENGTH = PARAM_CONST_VALUE_LEN_MAX; + +using StorageAsyncContext = struct StorageAsyncContext { + napi_env env = nullptr; + napi_async_work work = nullptr; + + char key[MAX_NAME_LENGTH] = { 0 }; + size_t keyLen = 0; + char value[MAX_VALUE_LENGTH] = { 0 }; + size_t valueLen = 0; + napi_deferred deferred = nullptr; + napi_ref callbackRef = nullptr; + + int status = -1; + std::string getValue; +}; + +using StorageAsyncContextPtr = StorageAsyncContext *; + +static int GetErrorInfo(int status, std::string &errMsg) +{ + switch (status) { + case EC_FAILURE: + case EC_SYSTEM_ERR: + case SYSPARAM_SYSTEM_ERROR: + errMsg = "System internal error such as out memory or deadlock"; + return -SYSPARAM_SYSTEM_ERROR; + case EC_INVALID: + case SYSPARAM_INVALID_INPUT: + errMsg = "Input parameter is missing or invalid"; + return -SYSPARAM_INVALID_INPUT; + case SYSPARAM_PERMISSION_DENIED: + errMsg = "The operation on the system permission is denied"; + return -SYSPARAM_PERMISSION_DENIED; + case SYSPARAM_NOT_FOUND: + errMsg = "System parameter not found"; + return -SYSPARAM_NOT_FOUND; + case SYSPARAM_INVALID_VALUE: + errMsg = "Invalid system parameter value"; + return -SYSPARAM_INVALID_VALUE; + default: + errMsg = "System internal error such as out memory or deadlock"; + return -SYSPARAM_SYSTEM_ERROR; + } + return 0; +} + +static napi_value BusinessErrorCreate(napi_env env, int status) +{ + std::string errMsg = ""; + int ret = GetErrorInfo(status, errMsg); + PARAM_JS_LOGV("BusinessErrorCreate status %d err %d msg: %s", status, ret, errMsg.c_str()); + napi_value code = nullptr; + napi_create_int32(env, ret, &code); + napi_value msg = nullptr; + napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msg); + napi_value businessError = nullptr; + napi_create_error(env, nullptr, msg, &businessError); + napi_set_named_property(env, businessError, "code", code); + return businessError; +} + +#define PARAM_NAPI_ASSERT(env, assertion, result, info) \ + do { \ + if (!(assertion)) { \ + napi_value d_err = BusinessErrorCreate(env, result); \ + napi_throw(env, d_err); \ + return nullptr; \ + } \ + } while (0) + +static int GetParamString(napi_env env, napi_value arg, char *buffer, size_t maxBuff, size_t *keySize) +{ + (void)napi_get_value_string_utf8(env, arg, nullptr, maxBuff - 1, keySize); + if (*keySize >= maxBuff) { + return SYSPARAM_INVALID_INPUT; + } + (void)napi_get_value_string_utf8(env, arg, buffer, maxBuff - 1, keySize); + return 0; +} + +static void SetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext) +{ + napi_value resource = nullptr; + napi_create_string_utf8(env, "JSStartupSet", NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + asyncContext->status = SetParameter(asyncContext->key, asyncContext->value); + PARAM_JS_LOGV("JSApp set status: %d, key: '%s', value: '%s'.", + asyncContext->status, asyncContext->key, asyncContext->value); + }, + [](napi_env env, napi_status status, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + napi_value result[ARGC_NUMBER] = { 0 }; + if (asyncContext->status == 0) { + napi_get_undefined(env, &result[0]); + napi_get_undefined(env, &result[1]); + } else { + result[0] = BusinessErrorCreate(env, asyncContext->status); + napi_get_undefined(env, &result[1]); + } + + if (asyncContext->deferred) { + if (asyncContext->status == 0) { + napi_resolve_deferred(env, asyncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, asyncContext->deferred, result[0]); + } + } else { + napi_value callback = nullptr; + napi_value callResult = nullptr; + napi_get_reference_value(env, asyncContext->callbackRef, &callback); + napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult); + napi_delete_reference(env, asyncContext->callbackRef); + } + napi_delete_async_work(env, asyncContext->work); + delete asyncContext; + }, + reinterpret_cast(asyncContext), &asyncContext->work); + napi_queue_async_work(env, asyncContext->work); +} + +static napi_value Set(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_THREE_NUMBER; + napi_value argv[ARGC_THREE_NUMBER] = { nullptr }; + napi_value thisVar = nullptr; + void *data = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); + PARAM_NAPI_ASSERT(env, argc >= ARGC_NUMBER, SYSPARAM_INVALID_INPUT, "requires 2 parameter"); + StorageAsyncContextPtr asyncContext = new StorageAsyncContext(); + asyncContext->env = env; + for (size_t i = 0; i < argc; i++) { + napi_valuetype valueType = napi_null; + napi_typeof(env, argv[i], &valueType); + int ret = 0; + if (i == 0 && valueType == napi_string) { + ret = GetParamString(env, argv[i], asyncContext->key, MAX_NAME_LENGTH, &asyncContext->keyLen); + } else if (i == 1 && valueType == napi_string) { + ret = GetParamString(env, argv[i], asyncContext->value, MAX_VALUE_LENGTH, &asyncContext->valueLen); + } else if (i == ARGC_NUMBER && valueType == napi_function) { + napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); + } else { + ret = SYSPARAM_INVALID_INPUT; + } + if (ret != 0) { + delete asyncContext; + ret = (i == 1) ? SYSPARAM_INVALID_VALUE : ret; + napi_value err = BusinessErrorCreate(env, ret); + napi_throw(env, err); + return nullptr; + } + } + PARAM_JS_LOGV("JSApp set key: %s(%d), value: %s(%d).", + asyncContext->key, asyncContext->keyLen, asyncContext->value, asyncContext->valueLen); + + napi_value result = nullptr; + if (asyncContext->callbackRef == nullptr) { + napi_create_promise(env, &asyncContext->deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + SetCallbackWork(env, asyncContext); + return result; +} + +static napi_value SetSync(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_NUMBER; + napi_value args[ARGC_NUMBER] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + PARAM_NAPI_ASSERT(env, argc == ARGC_NUMBER, SYSPARAM_INVALID_INPUT, "Wrong number of arguments"); + napi_valuetype valuetype0 = napi_null; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + napi_valuetype valuetype1 = napi_null; + NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + PARAM_NAPI_ASSERT(env, valuetype0 == napi_string && valuetype1 == napi_string, + SYSPARAM_INVALID_INPUT, "Wrong argument type. string expected."); + + size_t keySize = 0; + std::vector keyBuf(MAX_NAME_LENGTH, 0); + int ret = GetParamString(env, args[0], keyBuf.data(), MAX_NAME_LENGTH, &keySize); + if (ret != 0) { + napi_value err = BusinessErrorCreate(env, SYSPARAM_INVALID_INPUT); + napi_throw(env, err); + return nullptr; + } + std::vector value(MAX_VALUE_LENGTH, 0); + size_t valueSize = 0; + ret = GetParamString(env, args[1], value.data(), MAX_VALUE_LENGTH, &valueSize); + if (ret != 0) { + napi_value err = BusinessErrorCreate(env, SYSPARAM_INVALID_VALUE); + napi_throw(env, err); + return nullptr; + } + ret = SetParameter(keyBuf.data(), value.data()); + PARAM_JS_LOGV("JSApp SetSync result:%d, key: '%s'.", ret, keyBuf.data()); + napi_value napiValue = nullptr; + if (ret != 0) { // set failed + napi_value err = BusinessErrorCreate(env, ret); + napi_throw(env, err); + } else { + napi_get_undefined(env, &napiValue); + } + return napiValue; +} + +static napi_value GetSync(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_NUMBER; + napi_value args[ARGC_NUMBER] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); + PARAM_NAPI_ASSERT(env, argc == 1 || argc == ARGC_NUMBER, SYSPARAM_INVALID_INPUT, "Wrong number of arguments"); + napi_valuetype valuetype0 = napi_null; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + PARAM_NAPI_ASSERT(env, valuetype0 == napi_string, SYSPARAM_INVALID_INPUT, "Wrong argument type. Numbers expected."); + + napi_valuetype valuetype1 = napi_null; + if (argc == ARGC_NUMBER) { + NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + PARAM_NAPI_ASSERT(env, (valuetype1 == napi_string) || (valuetype1 == napi_undefined), + SYSPARAM_INVALID_INPUT, "Wrong argument type. string expected."); + } + + size_t keySize = 0; + std::vector keyBuf(MAX_NAME_LENGTH, 0); + int ret = GetParamString(env, args[0], keyBuf.data(), MAX_NAME_LENGTH, &keySize); + if (ret != 0) { + napi_throw(env, BusinessErrorCreate(env, SYSPARAM_INVALID_INPUT)); + return nullptr; + } + std::vector defValue(MAX_VALUE_LENGTH, 0); + size_t valueSize = 0; + if (argc == ARGC_NUMBER) { + if (valuetype1 == napi_undefined) { + valueSize = 0; + } else { + ret = GetParamString(env, args[1], defValue.data(), MAX_VALUE_LENGTH, &valueSize); + if (ret != 0) { + napi_throw(env, BusinessErrorCreate(env, SYSPARAM_INVALID_INPUT)); + return nullptr; + } + } + } + std::vector value(MAX_VALUE_LENGTH, 0); + ret = GetParameter(keyBuf.data(), (valueSize == 0) ? nullptr : defValue.data(), value.data(), MAX_VALUE_LENGTH); + PARAM_JS_LOGV("JSApp get status: %d, key: '%s', value: '%s', defValue: '%s'.", + ret, keyBuf.data(), value.data(), defValue.data()); + + if (ret < 0) { + napi_throw(env, BusinessErrorCreate(env, ret)); + return nullptr; + } + + napi_value napiValue = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, value.data(), strlen(value.data()), &napiValue)); + return napiValue; +} + +static void GetCallbackWork(napi_env env, StorageAsyncContextPtr asyncContext) +{ + napi_value resource = nullptr; + napi_create_string_utf8(env, "JSStartupGet", NAPI_AUTO_LENGTH, &resource); + napi_create_async_work( + env, nullptr, resource, + [](napi_env env, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + std::vector value(MAX_VALUE_LENGTH, 0); + asyncContext->status = GetParameter(asyncContext->key, + (asyncContext->valueLen == 0) ? nullptr : asyncContext->value, value.data(), MAX_VALUE_LENGTH); + if (asyncContext->status == 0) { + asyncContext->getValue = ""; + } else if (asyncContext->status > 0) { + asyncContext->getValue = std::string(value.begin(), value.end()); + } + }, + [](napi_env env, napi_status status, void *data) { + StorageAsyncContext *asyncContext = reinterpret_cast(data); + napi_value result[ARGC_NUMBER] = { 0 }; + if (asyncContext->status >= 0) { + napi_get_undefined(env, &result[0]); + napi_create_string_utf8(env, + asyncContext->getValue.c_str(), strlen(asyncContext->getValue.c_str()), &result[1]); + } else { + result[0] = BusinessErrorCreate(env, asyncContext->status); + napi_get_undefined(env, &result[1]); + } + + if (asyncContext->deferred) { + if (asyncContext->status >= 0) { + napi_resolve_deferred(env, asyncContext->deferred, result[1]); + } else { + napi_reject_deferred(env, asyncContext->deferred, result[0]); + } + } else { + napi_value callback = nullptr; + napi_value callResult = nullptr; + napi_get_reference_value(env, asyncContext->callbackRef, &callback); + napi_call_function(env, nullptr, callback, ARGC_NUMBER, result, &callResult); + napi_delete_reference(env, asyncContext->callbackRef); + } + napi_delete_async_work(env, asyncContext->work); + delete asyncContext; + }, + reinterpret_cast(asyncContext), &asyncContext->work); + napi_queue_async_work(env, asyncContext->work); +} + +static napi_value Get(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_THREE_NUMBER; + napi_value argv[ARGC_THREE_NUMBER] = { nullptr }; + napi_value thisVar = nullptr; + void *data = nullptr; + napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); + PARAM_NAPI_ASSERT(env, argc >= 1, SYSPARAM_INVALID_INPUT, "requires 1 parameter"); + StorageAsyncContextPtr asyncContext = new StorageAsyncContext(); + asyncContext->env = env; + for (size_t i = 0; i < argc; i++) { + napi_valuetype valueType = napi_null; + napi_typeof(env, argv[i], &valueType); + + int ret = 0; + if (i == 0 && valueType == napi_string) { + ret = GetParamString(env, argv[i], asyncContext->key, MAX_NAME_LENGTH, &asyncContext->keyLen); + } else if (i == 1 && valueType == napi_string) { + ret = GetParamString(env, argv[i], asyncContext->value, MAX_VALUE_LENGTH, &asyncContext->valueLen); + } else if (i == 1 && valueType == napi_undefined) { + asyncContext->valueLen = 0; + } else if (i == 1 && valueType == napi_function) { + napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); + break; + } else if (i == ARGC_NUMBER && valueType == napi_function) { + napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); + } else { + ret = SYSPARAM_INVALID_INPUT; + } + if (ret != 0) { + delete asyncContext; + ret = (i == 1) ? SYSPARAM_INVALID_VALUE : ret; + napi_value err = BusinessErrorCreate(env, ret); + napi_throw(env, err); + return nullptr; + } + } + PARAM_JS_LOGV("JSApp Get key: '%s'(%d), def value: '%s'(%d).", + asyncContext->key, asyncContext->keyLen, asyncContext->value, asyncContext->valueLen); + + napi_value result = nullptr; + if (asyncContext->callbackRef == nullptr) { + napi_create_promise(env, &asyncContext->deferred, &result); + } else { + napi_get_undefined(env, &result); + } + + GetCallbackWork(env, asyncContext); + return result; +} + +EXTERN_C_START +/* + * Module init + */ +static napi_value Init(napi_env env, napi_value exports) +{ + /* + * Attribute definition + */ + const napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("set", Set), + DECLARE_NAPI_FUNCTION("setSync", SetSync), + DECLARE_NAPI_FUNCTION("get", Get), + DECLARE_NAPI_FUNCTION("getSync", GetSync), +#ifdef PARAM_SUPPORT_WAIT + DECLARE_NAPI_FUNCTION("wait", ParamWait), + DECLARE_NAPI_FUNCTION("getWatcher", GetWatcher) +#endif + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc)); +#ifdef PARAM_SUPPORT_WAIT + return RegisterWatcher(env, exports); +#else + return exports; +#endif +} +EXTERN_C_END + +/* + * Module definition + */ +static napi_module _module_old = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = NULL, + .nm_register_func = Init, + .nm_modname = "systemParameterV9", + .nm_priv = ((void *)0), + .reserved = { 0 } +}; + +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = NULL, + .nm_register_func = Init, + .nm_modname = "systemParameterEnhance", + .nm_priv = ((void *)0), + .reserved = { 0 } +}; + +/* + * Module registration function + */ +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); + napi_module_register(&_module_old); +} diff --git a/interfaces/kits/syscap/BUILD.gn b/interfaces/kits/syscap/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..beb4a7537b7b9916e229ebdeab17c28c71b14db0 --- /dev/null +++ b/interfaces/kits/syscap/BUILD.gn @@ -0,0 +1,27 @@ +# 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("//build/ohos.gni") + +ohos_shared_library("deviceinfo_ndk") { + cflags = [ "-fstack-protector-all" ] + sources = [ + "src/deviceinfo.c", + "src/syscap_ndk.c", + ] + include_dirs = [ "./include" ] + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + innerapi_tags = [ "ndk" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/interfaces/kits/syscap/include/deviceinfo.h b/interfaces/kits/syscap/include/deviceinfo.h new file mode 100644 index 0000000000000000000000000000000000000000..f0b71aba903ea72461144fe20b960b173ab373b6 --- /dev/null +++ b/interfaces/kits/syscap/include/deviceinfo.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2023 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 DEVICEINFO_CSDK_H +#define DEVICEINFO_CSDK_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * Obtains the device type represented by a string, + * which can be {@code phone} (or {@code default} for phones), {@code wearable}, {@code liteWearable}, + * {@code tablet}, {@code tv}, {@code car}, or {@code smartVision}. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found device type, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetDeviceType(void); + +/** + * Obtains the device manufacturer represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found device manufacturer, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetManufacture(void); + +/** + * Obtains the device brand represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found device brand, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBrand(void); + +/** + * Obtains the product name speaded in the market + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found market name, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetMarketName(void); + +/** + * Obtains the product series represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found product series, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetProductSeries(void); + +/** + * Obtains the product model represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found product model, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetProductModel(void); + +/** + * Obtains the product model alias represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found product model, or failed to invoke the internal interface. + * @since 14 + */ +const char *OH_GetProductModelAlias(void); + +/** + * Obtains the software model represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found software model, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetSoftwareModel(void); + +/** + * Obtains the hardware model represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found hardware model, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetHardwareModel(void); + +/** + * Obtains the bootloader version number represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found bootloader version number, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBootloaderVersion(void); + +/** + * Obtains the application binary interface (Abi) list represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found Abi list, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetAbiList(void); + +/** + * Obtains the security patch tag represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found security patch tag, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetSecurityPatchTag(void); + +/** + * Obtains the product version displayed for customer represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found the product version displayed, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetDisplayVersion(void); + +/** + * Obtains the incremental version represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found the incremental version, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetIncrementalVersion(void); + +/** + * Obtains the OS release type represented by a string. + * + *

The OS release category can be {@code Release}, {@code Beta}, or {@code Canary}. + * The specific release type may be {@code Release}, {@code Beta1}, or others alike. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found the OS release type, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetOsReleaseType(void); + +/** + * Obtains the OS full version name represented by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found the OS full version name, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetOSFullName(void); + +/** + * Obtains the SDK API version number. + * @syscap SystemCapability.Startup.SystemInfo + * @return 0 - Not found the SDK API version number, or failed to invoke the internal interface. + * @since 10 + */ +int OH_GetSdkApiVersion(void); + +/** + * Obtains the first API version number. + * @syscap SystemCapability.Startup.SystemInfo + * @return 0 - Not found the first API version number, or failed to invoke the internal interface. + * @since 10 + */ +int OH_GetFirstApiVersion(void); + +/** + * Obtains the version ID by a string. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found version ID, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetVersionId(void); + +/** + * Obtains the build type of the current running OS. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found build type, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBuildType(void); + +/** + * Obtains the build user of the current running OS. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found build user, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBuildUser(void); + +/** + * Obtains the build host of the current running OS. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found build host, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBuildHost(void); + +/** + * Obtains the build time of the current running OS. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found build time, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBuildTime(void); + +/** + * Obtains the version hash of the current running OS. + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found version hash, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetBuildRootHash(void); + +/** + * Obtains the Distribution OS name represented by a string. + * + *

Independent Software Vendor (ISV) may distribute OHOS with their own OS name. + * If ISV not specified, it will return an empty string + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found distribution OS name, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetDistributionOSName(void); + +/** + * Obtains the ISV distribution OS version represented by a string. + * If ISV not specified, it will return the same value as OH_GetOSFullName + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found distribution OS version, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetDistributionOSVersion(void); + +/** + * Obtains the ISV distribution OS api version represented by a integer. + * If ISV not specified, it will return the same value as OH_GetSdkApiVersion + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found distribution OS api version, or failed to invoke the internal interface. + * @since 10 + */ +int OH_GetDistributionOSApiVersion(void); + +/** + * Obtains the ISV distribution OS release type represented by a string. + * If ISV not specified, it will return the same value as OH_GetOsReleaseType + * @syscap SystemCapability.Startup.SystemInfo + * @return NULL - Not found distribution OS release type, or failed to invoke the internal interface. + * @since 10 + */ +const char *OH_GetDistributionOSReleaseType(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/kits/syscap/include/syscap_ndk.h b/interfaces/kits/syscap/include/syscap_ndk.h new file mode 100755 index 0000000000000000000000000000000000000000..f9f712a6b25b7407ba45845187117bf3a1c32c48 --- /dev/null +++ b/interfaces/kits/syscap/include/syscap_ndk.h @@ -0,0 +1,39 @@ +/* + * 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 SYSCAP_NDK_H +#define SYSCAP_NDK_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +/** + * @brief Queries whether a device supports a specified SystemCapability. + * @return true - Supports the specified SystemCapability. + * false - The specified SystemCapability is not supported. + */ +bool canIUse(const char *cap); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/interfaces/kits/init_sync.h b/interfaces/kits/syscap/init_sync.h old mode 100644 new mode 100755 similarity index 100% rename from interfaces/kits/init_sync.h rename to interfaces/kits/syscap/init_sync.h diff --git a/interfaces/kits/syscap/libdeviceinfo.ndk.json b/interfaces/kits/syscap/libdeviceinfo.ndk.json new file mode 100644 index 0000000000000000000000000000000000000000..dfed9279629410bcd503cf146c361860ba288421 --- /dev/null +++ b/interfaces/kits/syscap/libdeviceinfo.ndk.json @@ -0,0 +1,30 @@ +[ + {"name": "canIUse"}, + {"name": "OH_GetDeviceType"}, + {"name": "OH_GetManufacture"}, + {"name": "OH_GetBrand"}, + {"name": "OH_GetMarketName"}, + {"name": "OH_GetProductSeries"}, + {"name": "OH_GetProductModel"}, + {"name": "OH_GetSoftwareModel"}, + {"name": "OH_GetHardwareModel"}, + {"name": "OH_GetBootloaderVersion"}, + {"name": "OH_GetAbiList"}, + {"name": "OH_GetSecurityPatchTag"}, + {"name": "OH_GetDisplayVersion"}, + {"name": "OH_GetIncrementalVersion"}, + {"name": "OH_GetOsReleaseType"}, + {"name": "OH_GetOSFullName"}, + {"name": "OH_GetSdkApiVersion"}, + {"name": "OH_GetFirstApiVersion"}, + {"name": "OH_GetVersionId"}, + {"name": "OH_GetBuildType"}, + {"name": "OH_GetBuildUser"}, + {"name": "OH_GetBuildHost"}, + {"name": "OH_GetBuildTime"}, + {"name": "OH_GetBuildRootHash"}, + {"name": "OH_GetDistributionOSName"}, + {"name": "OH_GetDistributionOSVersion"}, + {"name": "OH_GetDistributionOSApiVersion"}, + {"name": "OH_GetDistributionOSReleaseType"} +] diff --git a/interfaces/kits/syscap/src/deviceinfo.c b/interfaces/kits/syscap/src/deviceinfo.c new file mode 100644 index 0000000000000000000000000000000000000000..ee37aa3ca9efcf7d6f8f69c237ee022c9e9233ab --- /dev/null +++ b/interfaces/kits/syscap/src/deviceinfo.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2023 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 "parameter.h" + +const char *OH_GetDeviceType(void) +{ + return GetDeviceType(); +} + +const char *OH_GetManufacture(void) +{ + return GetManufacture(); +} + +const char *OH_GetBrand(void) +{ + return GetBrand(); +} + +const char *OH_GetMarketName(void) +{ + return GetMarketName(); +} + +const char *OH_GetProductSeries(void) +{ + return GetProductSeries(); +} + +const char *OH_GetProductModel(void) +{ + return GetProductModel(); +} + +const char *OH_GetProductModelAlias(void) +{ + return GetProductModelAlias(); +} + +const char *OH_GetSoftwareModel(void) +{ + return GetSoftwareModel(); +} + +const char *OH_GetHardwareModel(void) +{ + return GetHardwareModel(); +} + +const char *OH_GetBootloaderVersion(void) +{ + return GetBootloaderVersion(); +} + +const char *OH_GetAbiList(void) +{ + return GetAbiList(); +} + +const char *OH_GetSecurityPatchTag(void) +{ + return GetSecurityPatchTag(); +} + +const char *OH_GetDisplayVersion(void) +{ + return GetDisplayVersion(); +} + +const char *OH_GetIncrementalVersion(void) +{ + return GetIncrementalVersion(); +} + +const char *OH_GetOsReleaseType(void) +{ + return GetOsReleaseType(); +} + +const char *OH_GetOSFullName(void) +{ + return GetOSFullName(); +} + +int OH_GetSdkApiVersion(void) +{ + return GetSdkApiVersion(); +} + +int OH_GetFirstApiVersion(void) +{ + return GetFirstApiVersion(); +} + +const char *OH_GetVersionId(void) +{ + return GetVersionId(); +} + +const char *OH_GetBuildType(void) +{ + return GetBuildType(); +} + +const char *OH_GetBuildUser(void) +{ + return GetBuildUser(); +} + +const char *OH_GetBuildHost(void) +{ + return GetBuildHost(); +} + +const char *OH_GetBuildTime(void) +{ + return GetBuildTime(); +} + +const char *OH_GetBuildRootHash(void) +{ + return GetBuildRootHash(); +} + +const char *OH_GetDistributionOSName(void) +{ + return GetDistributionOSName(); +} + +const char *OH_GetDistributionOSVersion(void) +{ + return GetDistributionOSVersion(); +} + +int OH_GetDistributionOSApiVersion(void) +{ + return GetDistributionOSApiVersion(); +} + +const char *OH_GetDistributionOSReleaseType(void) +{ + return GetDistributionOSReleaseType(); +} diff --git a/interfaces/kits/syscap/src/syscap_ndk.c b/interfaces/kits/syscap/src/syscap_ndk.c new file mode 100644 index 0000000000000000000000000000000000000000..ece8454723416e4bee6795d7e1b415b3c62f2f24 --- /dev/null +++ b/interfaces/kits/syscap/src/syscap_ndk.c @@ -0,0 +1,23 @@ +/* + * 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 "systemcapability.h" +#include "syscap_ndk.h" + +bool canIUse(const char *cap) +{ + return HasSystemCapability(cap); +} diff --git a/interfaces/kits/syscap_ts/BUILD.gn b/interfaces/kits/syscap_ts/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..abca28dc91a98f31c3b5f21bacd28fe76e0ada41 --- /dev/null +++ b/interfaces/kits/syscap_ts/BUILD.gn @@ -0,0 +1,31 @@ +# 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. + +import("//build/ohos.gni") + +config("syscap_ts_config") { + include_dirs = [ "include" ] +} + +ohos_static_library("syscap_ts") { + sources = [ "src/syscap_ts.cpp" ] + include_dirs = [ "//base/startup/init/interfaces/innerkits/include" ] + external_deps = [ "napi:ace_napi" ] + defines = [ "NAPI_ENABLE" ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + + public_configs = [ ":syscap_ts_config" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/interfaces/kits/syscap_ts/include/syscap_ts.h b/interfaces/kits/syscap_ts/include/syscap_ts.h new file mode 100644 index 0000000000000000000000000000000000000000..b14dece9d881a500e41fccafc1f72ace485f6c9b --- /dev/null +++ b/interfaces/kits/syscap_ts/include/syscap_ts.h @@ -0,0 +1,24 @@ +/* + * 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 STARTUP_INIT_SYSCAP_TS_H +#define STARTUP_INIT_SYSCAP_TS_H + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +void InitSyscapModule(napi_env env); + +#endif //STARTUP_INIT_SYSCAP_TS_H diff --git a/interfaces/kits/syscap_ts/src/syscap_ts.cpp b/interfaces/kits/syscap_ts/src/syscap_ts.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b871059e17ef2f28ae60f0d5be1dced4e3f965d --- /dev/null +++ b/interfaces/kits/syscap_ts/src/syscap_ts.cpp @@ -0,0 +1,91 @@ +/* + * 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 "systemcapability.h" +#include "syscap_ts.h" +#include "beget_ext.h" + +#ifdef NAPI_ENABLE + +static constexpr int SYSCAP_MAX_SIZE = 100; + +void BindNativeFunction(napi_env env, napi_value object, const char *name, + const char *moduleName, napi_callback func) +{ + std::string fullName(moduleName); + fullName += "."; + fullName += name; + napi_value result = nullptr; + napi_create_function(env, fullName.c_str(), fullName.length(), func, nullptr, &result); + napi_set_named_property(env, object, name, result); +} + +inline napi_value CreateJsUndefined(napi_env env) +{ + napi_value result = nullptr; + napi_get_undefined(env, &result); + return result; +} + +inline napi_value CreateJsValue(napi_env env, const bool &value) +{ + napi_value result; + napi_get_boolean(env, value, &result); + return result; +} + + +napi_value CanIUse(napi_env env, napi_callback_info info) +{ + if (env == nullptr || info == nullptr) { + BEGET_LOGE("get syscap failed since env or callback info is nullptr."); + return nullptr; + } + napi_value undefined = CreateJsUndefined(env); + + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != 1) { + BEGET_LOGE("get syscap failed with invalid parameter"); + return undefined; + } + + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[0], &valueType); + if (valueType != napi_string) { + BEGET_LOGE("%{public}s called, Params is invalid.", __func__); + return undefined; + } + + char syscap[SYSCAP_MAX_SIZE] = {0}; + + size_t strLen = 0; + napi_get_value_string_utf8(env, argv[0], syscap, sizeof(syscap), &strLen); + + bool ret = HasSystemCapability(syscap); + return CreateJsValue(env, ret); +} + +#endif + +void InitSyscapModule(napi_env env) +{ + #ifdef NAPI_ENABLE + napi_value globalObject = nullptr; + napi_get_global(env, &globalObject); + const char *moduleName = "JsRuntime"; + BindNativeFunction(env, globalObject, "canIUse", moduleName, CanIUse); + #endif +} \ No newline at end of file diff --git a/ohos.build b/ohos.build deleted file mode 100644 index a8ef47b0a3477a78a0bcf6fbf4077ca1a0450568..0000000000000000000000000000000000000000 --- a/ohos.build +++ /dev/null @@ -1,12 +0,0 @@ -{ - "subsystem": "startup", - "parts": { - "init": { - "module_list": [ - "//base/startup/init_lite/services:startup_init", - "//base/startup/init_lite/ueventd:ueventd", - "//base/startup/init_lite/ueventd:ueventd.config" - ] - } - } -} diff --git a/remount/BUILD.gn b/remount/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d70ee7e9abf351f70c705dcd14b9bceafb850e6e --- /dev/null +++ b/remount/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2024-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. + +if (defined(ohos_lite)) { + executable("remount") { + sources = [ "//base/startup/init/remount/remount.c" ] + defines = [ "_GNU_SOURCE" ] + if (ohos_kernel_type == "linux") { + defines += [ "LINUX_REMOUNT" ] + } + } +} else { + import("//base/startup/init/begetd.gni") + import("//build/ohos.gni") + ohos_executable("remount") { + sources = [ "remount.c" ] + + defines = [ "_GNU_SOURCE" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" + + if (init_startup_feature_erofs_overlay) { + sources += [ + "//base/startup/init/services/log/init_commlog.c", + "remount_overlay.c", + ] + + include_dirs = [ "//base/startup/init/remount/include" ] + + deps = [ + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/services/log:init_log", + ] + + external_deps = [ "bounds_checking_function:libsec_shared" ] + defines += [ "EROFS_OVERLAY" ] + } + } +} + +group("overlayremount") { + if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux" || ohos_kernel_type == "liteos_a") { + deps = [ ":remount" ] + } else { + deps = [] + } + } else { + deps = [ ":remount" ] + } +} diff --git a/services/include/init_perms.h b/remount/include/remount_overlay.h similarity index 67% rename from services/include/init_perms.h rename to remount/include/remount_overlay.h index ee8d9988e2d5b4339205d89dbf20323fa233d328..fedf4a2291e4277f88b1decfc236840f18b770fe 100644 --- a/services/include/init_perms.h +++ b/remount/include/remount_overlay.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -12,8 +12,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_PERMS_H -#define BASE_STARTUP_INITLITE_PERMS_H + +#ifndef REMOUNT_OVERLAY_H +#define REMOUNT_OVERLAY_H + +#include "fs_manager.h" #ifdef __cplusplus #if __cplusplus @@ -21,13 +24,7 @@ extern "C" { #endif #endif -#define FULL_CAP 0xFFFFFFFF - -// init -#define DEFAULT_UMASK_INIT 022 - -// kit framework -#define DEFAULT_UID_KIT_FRAMEWORK 3 +int RemountRofsOverlay(); #ifdef __cplusplus #if __cplusplus @@ -35,4 +32,5 @@ extern "C" { #endif #endif -#endif // BASE_STARTUP_INITLITE_PERMS_H +#endif // REMOUNT_OVERLAY_H + diff --git a/remount/remount.c b/remount/remount.c new file mode 100644 index 0000000000000000000000000000000000000000..b4942a4c067f5e27d7f5f063cc72942d33856d29 --- /dev/null +++ b/remount/remount.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024-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 +#ifdef EROFS_OVERLAY +#include "init_log.h" +#include "erofs_remount_overlay.h" +#include "remount_overlay.h" +#endif + +int main(int argc, const char *argv[]) +{ +#ifdef EROFS_OVERLAY + EnableInitLog(INIT_INFO); + if (getuid() == 0 && IsOverlayEnable()) { + int ret = RemountRofsOverlay(); + printf("remount %s\n", ret == REMOUNT_SUCC ? "success" : "failed"); + return ret; + } + printf("not need erofs overlay, remount success\n"); +#endif + return 0; +} + diff --git a/remount/remount_overlay.c b/remount/remount_overlay.c new file mode 100644 index 0000000000000000000000000000000000000000..a214d2a5a943dc6d2151a45d036290872d02b512 --- /dev/null +++ b/remount/remount_overlay.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2024-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 +#include +#include +#include +#include +#include +#include "securec.h" +#include "init_log.h" +#include "init_utils.h" +#include "fs_manager/fs_manager.h" +#include "erofs_mount_overlay.h" +#include "erofs_remount_overlay.h" +#include "remount_overlay.h" + +#define MODE_MKDIR 0755 +#define BLOCK_SIZE_UNIT 4096 +#define PATH_MAX 256 +#define PREFIX_LOWER "/mnt/lower" +#define MNT_VENDOR "/vendor" +#define ROOT_MOUNT_DIR "/" +#define SYSTEM_DIR "/usr" + +INIT_STATIC bool MntNeedRemount(const char *mnt) +{ + char *remountPath[] = { + "/", "/vendor", "/sys_prod", "/chip_prod", "/preload", "/cust", "/version", "/patch_hw" + }; + for (size_t i = 0; i < ARRAY_LENGTH(remountPath); i++) { + if (strcmp(remountPath[i], mnt) == 0) { + return true; + } + } + return false; +} + +INIT_STATIC bool IsSkipRemount(const struct mntent mentry) +{ + if (mentry.mnt_type == NULL || mentry.mnt_dir == NULL) { + return true; + } + if (!MntNeedRemount(mentry.mnt_dir)) { + return true; + } + if (strncmp(mentry.mnt_type, "erofs", strlen("erofs")) != 0) { + return true; + } + + if (strncmp(mentry.mnt_fsname, "/dev/block/dm-", strlen("/dev/block/dm-")) != 0) { + return true; + } + return false; +} + +INIT_STATIC int ExecCommand(int argc, char **argv) +{ + INIT_CHECK(!(argc == 0 || argv == NULL || argv[0] == NULL), return -1); + + INIT_LOGI("Execute %s begin", argv[0]); + pid_t pid = fork(); + INIT_ERROR_CHECK(pid >= 0, return -1, "Fork new process to format failed: %d", errno); + + if (pid == 0) { + execv(argv[0], argv); + exit(-1); + } + int status; + waitpid(pid, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + INIT_LOGE("Command %s failed with status %d", argv[0], WEXITSTATUS(status)); + } + INIT_LOGI("Execute %s end", argv[0]); + return WEXITSTATUS(status); +} + +INIT_STATIC int GetDevSize(const char *fsBlkDev, uint64_t *devSize) +{ + int fd = -1; + fd = open(fsBlkDev, O_RDONLY); + if (fd < 0) { + INIT_LOGE("open %s failed errno %d", fsBlkDev, errno); + return -1; + } + + if (ioctl(fd, BLKGETSIZE64, devSize) < 0) { + INIT_LOGE("get block device [%s] size failed, errno %d", fsBlkDev, errno); + close(fd); + return -1; + } + + close(fd); + return 0; +} + +INIT_STATIC int FormatExt4(const char *fsBlkDev, const char *fsMntPoint) +{ + uint64_t devSize; + int ret = GetDevSize(fsBlkDev, &devSize); + if (ret) { + INIT_LOGE("get dev size failed."); + return ret; + } + + char blockSizeBuffer[MAX_BUFFER_LEN] = {0}; + if (snprintf_s(blockSizeBuffer, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "%llu", devSize / BLOCK_SIZE_UNIT) < 0) { + BEGET_LOGE("Failed to copy nameRofs."); + return -1; + } + + const char *mke2fsArgs[] = { + "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fsBlkDev, blockSizeBuffer, NULL + }; + int mke2fsArgsLen = ARRAY_LENGTH(mke2fsArgs); + ret = ExecCommand(mke2fsArgsLen, (char **)mke2fsArgs); + if (ret) { + INIT_LOGE("mke2fs failed returned %d", ret); + return -1; + } + + const char *e2fsdroidArgs[] = { + "system/bin/e2fsdroid", "-e", "-a", fsMntPoint, fsBlkDev, NULL + + }; + int e2fsdroidArgsLen = ARRAY_LENGTH(e2fsdroidArgs); + ret = ExecCommand(e2fsdroidArgsLen, (char **)e2fsdroidArgs); + if (ret) { + INIT_LOGE("e2fsdroid failed returned %d", ret); + } + return 0; +} + +INIT_STATIC void OverlayRemountPre(const char *mnt) +{ + if (strcmp(mnt, MNT_VENDOR) == 0) { + OverlayRemountVendorPre(); + } +} + +INIT_STATIC void OverlayRemountPost(const char *mnt) +{ + if (strcmp(mnt, MNT_VENDOR) == 0) { + OverlayRemountVendorPost(); + } +} + +INIT_STATIC bool DoRemount(struct mntent *mentry) +{ + int devNum = 0; + char *mnt = NULL; + int ret = 0; + ret = sscanf_s(mentry->mnt_fsname + strlen("/dev/block/dm-"), "%d", &devNum); + if (ret < 0) { + INIT_LOGE("get devNum failed returned"); + return false; + } + + char devExt4[MAX_BUFFER_LEN] = {0}; + devNum = devNum + 1; + if (snprintf_s(devExt4, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "/dev/block/dm-%d", devNum) < 0) { + INIT_LOGE("Failed to copy devExt4."); + return false; + } + + if (strncmp(mentry->mnt_dir, PREFIX_LOWER, strlen(PREFIX_LOWER)) == 0) { + mnt = mentry->mnt_dir + strlen(PREFIX_LOWER); + } else { + mnt = mentry->mnt_dir; + } + + if (CheckIsExt4(devExt4, 0)) { + INIT_LOGI("is ext4, not need format %s", devExt4); + } else { + ret = FormatExt4(devExt4, mnt); + if (ret) { + INIT_LOGE("Failed to format devExt4 %s.", devExt4); + return false; + } + + ret = MountExt4Device(devExt4, mnt, true); + if (ret) { + INIT_LOGE("Failed to mount devExt4 %s.", devExt4); + return false; + } + } + + if (strncmp(mentry->mnt_dir, "/mnt/lower", strlen("/mnt/lower")) == 0) { + return true; + } + + OverlayRemountPre(mnt); + if (MountOverlayOne(mnt)) { + INIT_LOGE("Failed to mount overlay on mnt:%s.", mnt); + return false; + } + OverlayRemountPost(mnt); + return true; +} + +INIT_STATIC bool DirectoryExists(const char *path) +{ + struct stat sb; + return stat(path, &sb) != -1 && S_ISDIR(sb.st_mode); +} + +int RootOverlaySetup(void) +{ + const char *rootOverlay = "/mnt/overlay/usr"; + const char *rootUpper = "/mnt/overlay/usr/upper"; + const char *rootWork = "/mnt/overlay/usr/work"; + char mntOpt[MAX_BUFFER_LEN] = {0}; + + if (snprintf_s(mntOpt, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, + "upperdir=%s,lowerdir=/system,workdir=%s,override_creds=off", rootUpper, rootWork) < 0) { + INIT_LOGE("copy mntOpt failed. errno %d", errno); + return -1; + } + + if (!DirectoryExists(rootOverlay)) { + if (mkdir(rootOverlay, MODE_MKDIR) && (errno != EEXIST)) { + INIT_LOGE("make dir failed on %s", rootOverlay); + return -1; + } + + if (mkdir(rootUpper, MODE_MKDIR) && (errno != EEXIST)) { + INIT_LOGE("make dir failed on %s", rootUpper); + return -1; + } + + if (mkdir(rootWork, MODE_MKDIR) && (errno != EEXIST)) { + INIT_LOGE("make dir failed on %s", rootWork); + return -1; + } + } + + if (mount("overlay", "/system", "overlay", 0, mntOpt)) { + INIT_LOGE("system mount overlay failed on %s", mntOpt); + return -1; + } + INIT_LOGI("system mount overlay sucess"); + return 0; +} + +INIT_STATIC bool DoSystemRemount(struct mntent *mentry) +{ + int devNum = 0; + int ret = 0; + ret = sscanf_s(mentry->mnt_fsname + strlen("/dev/block/dm-"), "%d", &devNum); + if (ret < 0) { + INIT_LOGE("get devNum failed returned"); + return false; + } + + char devExt4[MAX_BUFFER_LEN] = {0}; + devNum = devNum + 1; + if (snprintf_s(devExt4, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, "/dev/block/dm-%d", devNum) < 0) { + BEGET_LOGE("Failed to copy devExt4."); + return false; + } + + if (CheckIsExt4(devExt4, 0)) { + INIT_LOGI("is ext4, not need format %s", devExt4); + } else { + ret = FormatExt4(devExt4, SYSTEM_DIR); + if (ret) { + INIT_LOGE("Failed to format devExt4 %s.", devExt4); + return false; + } + + ret = MountExt4Device(devExt4, SYSTEM_DIR, true); + if (ret) { + INIT_LOGE("Failed to mount devExt4 %s.", devExt4); + } + } + + if (RootOverlaySetup()) { + INIT_LOGE("Failed to root overlay."); + return false; + } + + return true; +} + +static bool IsRegularFile(const char *file) +{ + struct stat st = {0}; + if (lstat(file, &st) == 0) { + if (S_ISREG(st.st_mode)) { + return true; + } + } + return false; +} + +static void MountBindEngFile(const char *source, const char *target) +{ + char targetFullPath[PATH_MAX] = {0}; + const char *p = source; + char *q = NULL; + const char *end = source + strlen(source); + + if (*p != '/') { // source must start with '/' + return; + } + + // Get next '/' + q = strchr(p + 1, '/'); + if (q == NULL) { + INIT_LOGI("path \' %s \' without extra slash, ignore it", source); + return; + } + + if (*(end - 1) == '/') { + INIT_LOGI("path \' %s \' ends with slash, ignore it", source); + return; + } + // OK, now get sub dir and combine it with target + int ret = snprintf_s(targetFullPath, PATH_MAX, PATH_MAX - 1, "%s%s", strcmp(target, "/") == 0 ? "" : target, q); + if (ret == -1) { + INIT_LOGE("Failed to build target path"); + return; + } + INIT_LOGI("target full path is %s", targetFullPath); + if (access(targetFullPath, F_OK) != 0) { // file not exist, symlink targetFullPath + if (symlink(source, targetFullPath) < 0) { + INIT_LOGE("Failed to link %s to %s, err = %d", source, targetFullPath, errno); + } + return; + } + if (IsRegularFile(targetFullPath)) { // file exist, moung bind targetFullPath + if (mount(source, targetFullPath, NULL, MS_BIND, NULL) != 0) { + INIT_LOGE("Failed to bind mount %s to %s, err = %d", source, targetFullPath, errno); + } else { + INIT_LOGI("Bind mount %s to %s done", source, targetFullPath); + } + return; + } + INIT_LOGW("%s without expected type, skip overlay", targetFullPath); +} + +static void EngFilesOverlay(const char *source, const char *target) +{ + DIR *dir = NULL; + struct dirent *de = NULL; + + if ((dir = opendir(source)) == NULL) { + INIT_LOGE("Open path \' %s \' failed. err = %d", source, errno); + return; + } + int dfd = dirfd(dir); + char srcPath[PATH_MAX] = {}; + while ((de = readdir(dir)) != NULL) { + if (de->d_name[0] == '.') { + continue; + } + if (snprintf_s(srcPath, PATH_MAX, PATH_MAX - 1, "%s/%s", source, de->d_name) == -1) { + INIT_LOGE("Failed to build path for overlaying"); + break; + } + + // Determine file type + struct stat st = {}; + if (fstatat(dfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + continue; + } + if (S_ISDIR(st.st_mode)) { + EngFilesOverlay(srcPath, target); + } else if (S_ISREG(st.st_mode)) { + MountBindEngFile(srcPath, target); + } else { // Ignore any other file types + INIT_LOGI("Ignore %s while overlaying", srcPath); + } + } + closedir(dir); + dir = NULL; +} + +int RemountRofsOverlay() +{ + int lastRemountResult = GetRemountResult(); + INIT_LOGI("get last remount result is %d.", lastRemountResult); + if (lastRemountResult == REMOUNT_SUCC) { + return REMOUNT_SUCC; + } + FILE *fp; + struct mntent *mentry = NULL; + if ((fp = setmntent("/proc/mounts", "r")) == NULL) { + INIT_LOGE("Failed to open /proc/mounts."); + return REMOUNT_FAIL; + } + + while (NULL != (mentry = getmntent(fp))) { + if (IsSkipRemount(*mentry)) { + INIT_LOGI("skip remount %s", mentry->mnt_dir); + continue; + } + + if (strcmp(mentry->mnt_dir, ROOT_MOUNT_DIR) == 0) { + if (!DoSystemRemount(mentry)) { + endmntent(fp); + INIT_LOGE("do system remount failed on %s", mentry->mnt_dir); + return REMOUNT_FAIL; + } + continue; + } + INIT_LOGI("do remount %s", mentry->mnt_dir); + if (!DoRemount(mentry)) { + endmntent(fp); + INIT_LOGE("do remount failed on %s", mentry->mnt_dir); + return REMOUNT_FAIL; + } + } + + endmntent(fp); + SetRemountResultFlag(); + + INIT_LOGI("remount system overlay..."); + EngFilesOverlay("/eng_system", "/"); + INIT_LOGI("remount chipset overlay..."); + EngFilesOverlay("/eng_chipset", "/chipset"); + return REMOUNT_SUCC; +} \ No newline at end of file diff --git a/scripts/param_cfg_to_code.py b/scripts/param_cfg_to_code.py new file mode 100755 index 0000000000000000000000000000000000000000..8810bdaab14da7ac9816bc4b519363c428015e41 --- /dev/null +++ b/scripts/param_cfg_to_code.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# 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 argparse +import os +import sys + + +def decode_cfg_line(data): + data.replace('\n', '').replace('\r', '') + data = data.strip() + if (len(data) == 0 or data[0] == '#'): + return "", "" + strs = data.split('=') + if len(strs) <= 1: + return "", "" + return strs[0].strip(), strs[1].strip() + + +def get_param_from_cfg(cfg_name): + data_dict = {} + with open(cfg_name) as afile: + data = afile.readline() + while data: + name, value = decode_cfg_line(data) + if len(name) != 0 and len(value) != 0: + data_dict[name] = value + print("sample file name={%s %s}" % (name, value)) + data = afile.readline() + return data_dict + + +def decode_code_line(data): + data.replace('\n', '').replace('\r', '') + data = data.strip() + if (not data.startswith("PARAM_MAP")): + return "", "" + data_len = len(data) + data = data[len("PARAM_MAP") + 1 : data_len - 1] + data = data.strip() + strs = data.split(',') + if len(strs) <= 1: + return "", "" + return strs[0].strip(), data[len(strs[0]) + 1:].strip() + + +def get_param_from_c_code(code_name): + data_dict = {} + with open(code_name, "r+") as afile: + data = afile.readline() + while data: + name, value = decode_code_line(data) + if len(name) != 0 and len(value) != 0: + data_dict[name] = value + data = afile.readline() + afile.truncate(0) + return data_dict + + +def write_map_to_code(code_name, data_dict): + try: + with open(code_name, "w") as f: + # start with 0 + f.seek(0) + # write file header + f.write('#ifndef PARAM_LITE_DEF_CFG_' + os.linesep) + f.write('#define PARAM_LITE_DEF_CFG_' + os.linesep) + f.write('#include ' + os.linesep + os.linesep) + f.write('#ifdef __cplusplus' + os.linesep) + f.write('#if __cplusplus' + os.linesep) + f.write('extern "C" {' + os.linesep) + f.write('#endif' + os.linesep) + f.write('#endif' + os.linesep + os.linesep) + + #define struct + f.write('typedef struct Node_ {' + os.linesep) + f.write(' const char *name;' + os.linesep) + f.write(' const char *value;' + os.linesep) + f.write('} Node;' + os.linesep + os.linesep) + f.write('#define PARAM_MAP(name, value) {(const char *)#name, (const char *)#value},') + f.write(os.linesep + os.linesep) + # write data + f.write('static Node g_paramDefCfgNodes[] = {' + os.linesep) + for name, value in data_dict.items(): + if (value.startswith("\"")): + tmp_str = " PARAM_MAP({0}, {1})".format(name, value) + f.write(tmp_str + os.linesep) + else: + tmp_str = " PARAM_MAP({0}, \"{1}\")".format(name, value) + f.write(tmp_str + os.linesep) + f.write('};' + os.linesep + os.linesep) + + #end + f.write('#ifdef __cplusplus' + os.linesep) + f.write('#if __cplusplus' + os.linesep) + f.write('}' + os.linesep) + f.write('#endif' + os.linesep) + f.write('#endif' + os.linesep) + f.write('#endif // PARAM_LITE_DEF_CFG_' + os.linesep) + f.write(os.linesep) + f.truncate() + except IOError: + print("Error: open or write file %s fail" % {code_name}) + return 0 + + +def add_to_code_dict(code_dict, cfg_dict, high=True): + for name, value in cfg_dict.items(): + # check if name exit + has_key = name in code_dict + if has_key and high: + code_dict[name] = value + elif not has_key: + code_dict[name] = value + return code_dict + + +def main(): + parser = argparse.ArgumentParser( + description='A common change param.para file to h.') + parser.add_argument( + '--source', + action='append', + help='The source to change.', + required=True) + parser.add_argument( + '--dest_dir', + help='Path that the source should be changed to.', + required=True) + args = parser.parse_args() + + out_dir = args.dest_dir + if not os.path.exists(out_dir): + os.makedirs(out_dir, exist_ok=True) + print("out_dir {}".format(out_dir)) + + for source in args.source: + print("source {}".format(out_dir)) + if not os.path.exists(source): + continue + + src_dict = get_param_from_cfg(source) + dst = "".join([out_dir, "param_cfg.h"]) + + if os.path.exists(dst): + dst_dict = get_param_from_c_code(dst) + else: + dst_dict = {} + + dst_dict = add_to_code_dict(dst_dict, src_dict, False) + write_map_to_code(dst, dst_dict) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/BUILD.gn b/services/BUILD.gn old mode 100644 new mode 100755 index 1994c2efafb84e51013f454979fdc76ae94f7bf0..d48aaf3f708d2dd44b23f8e2848f09405874e50c --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Huawei Device Co., Ltd. +# Copyright (c) 2020-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 @@ -10,187 +10,61 @@ # 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. -if (defined(ohos_lite)) { - # feature: init - executable("init_lite") { - output_name = "init" - defines = [ - "_GNU_SOURCE", #syscall function need this macro definition - "OHOS_LITE", - ] - sources = [ - "log/init_log.c", - "src/init_adapter.c", - "src/init_capability.c", - "src/init_cmds.c", - "src/init_import.c", - "src/init_jobs.c", - "src/init_read_cfg.c", - "src/init_reboot.c", - "src/init_service.c", - "src/init_service_manager.c", - "src/init_service_socket.c", - "src/init_signal_handler.c", - "src/init_utils.c", - "src/main.c", - ] - - include_dirs = [ - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/param/include", - "//base/startup/init_lite/services/log", - "//third_party/cJSON", - "//third_party/bounds_checking_function/include", - "//base/startup/syspara_lite/interfaces/kits", - "//base/hiviewdfx/hilog_lite/interfaces/native/kits", - ] - - cflags = [ "-Wall" ] +import("//base/startup/init/begetd.gni") +group("startup_init") { + deps = [] + # for liteos + if (defined(ohos_lite) && ohos_kernel_type != "liteos_m") { deps = [ - "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", - "//base/startup/init_lite/initsync:initsync", - "//base/startup/syspara_lite/frameworks/parameter:parameter", - "//build/lite/config/component/cJSON:cjson_shared", - "//third_party/bounds_checking_function:libsec_shared", + "etc:etc_files", + "init/lite:init", ] - ldflags = [] - if (ohos_kernel_type == "liteos_a") { - include_dirs += [ - "//kernel/liteos_a/syscall", - "//base/startup/init_lite/interfaces/kits", - "//base/startup/init_lite/initsync/include", - ] - deps += [ "//base/startup/init_lite/initsync:initsync" ] - } - if (ohos_kernel_type == "linux") { - defines += [ "NEED_EXEC_RCS_LINUX" ] - ldflags += [ - "-lm", - "-lpthread", - ] - deps += [ - "//third_party/mksh", - "//third_party/toybox", - ] - } - } - if (ohos_build_type == "debug") { - group("unittest") { - deps = - [ "//base/startup/init_lite/services/test/unittest/common:unittest" ] + # for unittest + if (ohos_build_type == "debug") { + deps += [ "//base/startup/init/test/unittest/lite:init_test" ] } } -} else { - import("//build/ohos.gni") - ohos_executable("init") { - sources = [ - "src/device.c", - "src/init_adapter.c", - "src/init_capability.c", - "src/init_cmds.c", - "src/init_import.c", - "src/init_jobs.c", - "src/init_read_cfg.c", - "src/init_reboot.c", - "src/init_service.c", - "src/init_service_manager.c", - "src/init_service_socket.c", - "src/init_signal_handler.c", - "src/init_utils.c", - "src/main.c", - ] - include_dirs = [ - "//base/startup/init_lite/services/include/param", - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/log", - "//third_party/cJSON", - "//third_party/bounds_checking_function/include", - "//third_party/libuv/include", - ] + # for standard + if (!defined(ohos_lite)) { deps = [ - "//base/startup/init_lite/services/log:init_log", - "//base/startup/init_lite/services/param:paramservice", - "//third_party/bounds_checking_function:libsec_static", - "//third_party/cJSON:cjson_static", + "etc:etc_files", + "init/standard:init", ] + data_deps = [ "init/standard:init_early" ] + deps += [ "//base/startup/init/services/etc:watchdog.cfg" ] + deps += [ "//base/startup/init/services/etc:ueventd.cfg" ] + external_deps = [ + "e2fsprogs:blkid", + "e2fsprogs:e2fsck", + "e2fsprogs:e2fsdroid", + "e2fsprogs:libext2_blkid", + "e2fsprogs:libext2_com_err", + "e2fsprogs:libext2_e2p", + "e2fsprogs:libext2_misc", + "e2fsprogs:libext2_quota", + "e2fsprogs:libext2_uuid", + "e2fsprogs:libext2fs", + "e2fsprogs:mke2fs", + "e2fsprogs:resize2fs", + ] + if (use_musl) { - deps += [ - "//third_party/mksh:sh", - "//third_party/toybox:toybox", + external_deps += [ + "f2fs-tools:fsck.f2fs", + "f2fs-tools:libf2fs", + "f2fs-tools:mkfs.f2fs", ] } - install_images = [ - "system", - "updater", - ] - install_enable = true - part_name = "init" - } - - group("startup_init") { - deps = [ - ":init", - ":init_etc", - "//base/startup/init_lite/interfaces/innerkits/socket:libsocket", - "//base/startup/init_lite/services/cmds/reboot:reboot", - "//base/startup/init_lite/services/cmds/service_control:service_control", - "//base/startup/init_lite/services/param:getparam", - "//base/startup/init_lite/services/param:paramclient", - "//base/startup/init_lite/services/param:paramservice", - "//base/startup/init_lite/services/param:setparam", - ] - } - - # init etc files group - ohos_prebuilt_etc("init.cfg") { - source = "//base/startup/init_lite/services/etc/init.cfg" - part_name = "init" - } - ohos_prebuilt_etc("passwd") { - source = "//base/startup/init_lite/services/etc/passwd" - install_images = [ - "system", - "updater", - ] - part_name = "init" - } - - ohos_prebuilt_etc("group") { - source = "//base/startup/init_lite/services/etc/group" - install_images = [ - "system", - "updater", - ] - part_name = "init" - } - - ohos_prebuilt_etc("init.usb.cfg") { - source = "//base/startup/init_lite/services/etc/init.usb.cfg" - part_name = "init" - } - - ohos_prebuilt_etc("init.usb.configfs.cfg") { - source = "//base/startup/init_lite/services/etc/init.usb.configfs.cfg" - part_name = "init" - } - - ohos_prebuilt_etc("ohos.para") { - source = "//base/startup/init_lite/services/etc/ohos.para" - part_name = "init" - } - - group("init_etc") { - deps = [ - ":group", - ":init.cfg", - ":init.usb.cfg", - ":init.usb.configfs.cfg", - ":ohos.para", - ":passwd", - ] + if (enable_ohos_startup_init_feature_watcher) { + deps += [ + "//base/startup/init/services/param/watcher:param_watcher", + "//base/startup/init/services/param/watcher:param_watcher.rc", + "//base/startup/init/services/param/watcher/sa_profile:param_watcher_profile", + ] + } } } diff --git a/services/begetctl/BUILD.gn b/services/begetctl/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..77f143fc5167ac17fa2164c9b0d56c36cf1843b2 --- /dev/null +++ b/services/begetctl/BUILD.gn @@ -0,0 +1,288 @@ +# Copyright (c) 2021-2023 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/begetd.gni") + +common_include_dirs = [ + "//base/startup/init/services/begetctl", + "//base/startup/init/services/begetctl/shell", + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/adapter", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/param/base", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/syspara", +] + +if (defined(ohos_lite)) { + executable("begetctl") { + output_name = "begetctl" + sources = [ + "main.c", + "param_cmd.c", + "shell/shell_bas.c", + ] + defines = [ + "_GNU_SOURCE", #syscall function need this macro definition + "__MUSL__", + "OHOS_LITE", + ] + if (param_test) { + sources += [ "//base/startup/init/test/moduletest/syspara.cpp" ] + } + + include_dirs = common_include_dirs + include_dirs += + [ "//base/security/selinux_adapter/interfaces/policycoreutils/include" ] + deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/utils:libinit_utils", + "//build/lite/config/component/cJSON:cjson_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + if (ohos_kernel_type == "linux") { + deps += [ "//base/startup/init/services/param/linux:param_client" ] + } else { + deps += [ "//base/startup/init/services/param/liteos:param_client_lite" ] + } + } +} else { + import("//build/ohos.gni") + + ohos_executable("begetctl") { + sources = [ + "appspawntime_cmd.c", + "begetctl_cmd.c", + "bootchart_cmd.c", + "dump_service.c", + "init_cmd_reboot.c", + "main.c", + "misc_daemon.cpp", + "modulectl.c", + "param_cmd.c", + "sandbox.cpp", + "service_control.c", + "setloglevel.c", + "shell/shell_bas.c", + ] + + defines = [ "_GNU_SOURCE" ] + + include_dirs = common_include_dirs + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd", + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/param/linux:param_client", + "//base/startup/init/services/sandbox:sandbox", + "//base/startup/init/services/utils:libinit_utils", + ] + + deps += [ "//base/startup/init/services/param/base:param_base" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson", + "c_utils:utils", + ] + if (init_appspawn_client_module && defined(global_parts_info) && + defined(global_parts_info.startup_appspawn)) { + defines += [ "ENABLE_ENTER_APPSPAWN_SANDBOX" ] + external_deps += [ "appspawn:appspawn_client" ] + } + if (param_test) { + sources += [ + "//base/startup/init/test/moduletest/param_test_cmds.c", + "//base/startup/init/test/moduletest/syspara.cpp", + ] + deps += [ "//base/startup/init/interfaces/innerkits:libbeget_proxy" ] + defines += [ + "OHOS_SERVICE_DUMP", + "INIT_TEST", + ] + } + + if (build_selinux) { + external_deps += [ + "selinux:libselinux", + "selinux_adapter:libselinux_parameter_static", + ] + defines += [ "PARAM_SUPPORT_SELINUX" ] + } + + if (init_extra_static_modules == "") { + defines += [ "SUPPORT_REBOOT_CHARGE" ] + } + + symlink_target_name = [ + "reboot", + "service_control", + ] + + if (init_feature_ab_partition) { + sources += [ "partitionslot.cpp" ] + external_deps += [ + "drivers_interface_partitionslot:libpartitionslot_proxy_1.0", + "hdf_core:libhdi", + "hdf_core:libpub_utils", + ] + } + + install_images = [ "system" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" + } + + ohos_executable("reboot") { + sources = [ + "init_cmd_reboot.c", + "main.c", + "param_cmd.c", + "shell/shell_bas.c", + ] + + defines = [ "_GNU_SOURCE" ] + + include_dirs = common_include_dirs + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/param/linux:param_client", + "//base/startup/init/services/utils:libinit_utils", + ] + + deps += [ "//base/startup/init/services/param/base:param_base" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson", + "c_utils:utils", + "selinux:libselinux", + "selinux_adapter:libselinux_parameter_static", + ] + + if (init_extra_static_modules == "") { + defines += [ "SUPPORT_REBOOT_CHARGE" ] + } + + install_images = [ "updater" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" + } + + ohos_executable("paramshell") { + sources = [ + "param_cmd.c", + "shell/shell_bas.c", + "shell/shell_main.c", + ] + + defines = [ "_GNU_SOURCE" ] + include_dirs = common_include_dirs + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/param/linux:param_client", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ "bounds_checking_function:libsec_shared" ] + + if (build_selinux) { + external_deps += [ + "selinux:libselinux", + "selinux_adapter:libselinux_parameter_static", + ] + defines += [ "PARAM_SUPPORT_SELINUX" ] + } + + if (param_test) { + sources += [ + "//base/startup/init/test/moduletest/param_test_cmds.c", + "//base/startup/init/test/moduletest/syspara.cpp", + ] + deps += [ "//base/startup/init/interfaces/innerkits:libbeget_proxy" ] + defines += [ + "OHOS_SERVICE_DUMP", + "INIT_TEST", + ] + } + + install_images = [ "system" ] + install_enable = true + + part_name = "init" + subsystem_name = "startup" + } + + ohos_executable("param") { + sources = [ + "main.c", + "param_cmd.c", + "shell/shell_bas.c", + ] + + defines = [ + "INIT_AGENT", + "_GNU_SOURCE", + ] + + include_dirs = common_include_dirs + deps = [ + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/param/linux:param_client", + "//base/startup/init/services/utils:libinit_utils", + ] + deps += [ "//base/startup/init/services/param/base:param_base" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "c_utils:utils", + "hilog:libhilog_base", + ] + if (build_selinux) { + defines += [ "PARAM_SUPPORT_SELINUX" ] + external_deps += [ + "selinux:libselinux", + "selinux_adapter:libselinux_parameter_static", + ] + } + install_images = [ + "system", + "updater", + ] + install_enable = true + part_name = "init" + subsystem_name = "startup" + } +} + +group("begetctl_cmd") { + if (defined(ohos_lite)) { + if (init_feature_begetctl_liteos && ohos_kernel_type != "liteos_m") { + deps = [ ":begetctl" ] + } + } else { + deps = [ + ":begetctl", + ":param", + ":paramshell", + ":reboot", + ] + } +} diff --git a/services/begetctl/appspawntime_cmd.c b/services/begetctl/appspawntime_cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..9a94577404b9db0e8aa3c32099ebddb52e569b19 --- /dev/null +++ b/services/begetctl/appspawntime_cmd.c @@ -0,0 +1,85 @@ +/* + * 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 +#include +#include +#include +#include "begetctl.h" +#include "init_utils.h" +#include "control_fd.h" +#ifdef ENABLE_ENTER_APPSPAWN_SANDBOX +#include "appspawn.h" +#endif + +#define APPSPAWN_CMD_NUMBER 1 + +static int SendAppspawnTimeMessage(const CmdAgent *agent, uint16_t type, const char *ptyName) +{ +#ifdef ENABLE_ENTER_APPSPAWN_SANDBOX + if ((agent == NULL) || (ptyName == NULL)) { + BEGET_LOGE("Invalid parameter"); + return -1; + } + + AppSpawnClientHandle clientHandle; + int ret = AppSpawnClientInit("Appspawn", &clientHandle); + BEGET_ERROR_CHECK(ret == 0, return -1, "AppSpawnClientInit error, errno = %d", errno); + AppSpawnReqMsgHandle reqHandle; + ret = AppSpawnReqMsgCreate(MSG_BEGET_SPAWNTIME, "init", &reqHandle); + if (ret != 0) { + AppSpawnClientDestroy(clientHandle); + return -1; + } + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + if (ret != 0) { + AppSpawnClientDestroy(clientHandle); + return -1; + } + int minAppspawnTime = result.result; + int maxAppspawnTime = result.pid; + printf("minAppspawnTime: %d, maxAppspawnTime: %d \n", minAppspawnTime, maxAppspawnTime); + AppSpawnClientDestroy(clientHandle); + return 0; +#endif + return -1; +} + +static int main_cmd(BShellHandle shell, int argc, char* argv[]) +{ + if (argc != APPSPAWN_CMD_NUMBER) { + BShellCmdHelp(shell, argc, argv); + return 0; + } + CmdAgent agent; + int ret = InitPtyInterface(&agent, ACTION_APP_SPAWNTIME, "init", (CallbackSendMsgProcess)SendAppspawnTimeMessage); + if (ret != 0) { + BEGET_LOGE("initptyinterface failed"); + return -1; + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + CmdInfo infos[] = { + {"appspawn_time", main_cmd, "get appspawn time", "appspawn_time", ""}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} + diff --git a/services/begetctl/begetctl.h b/services/begetctl/begetctl.h new file mode 100644 index 0000000000000000000000000000000000000000..fc49319d152d4923afc24dd5509718dbb37d2138 --- /dev/null +++ b/services/begetctl/begetctl.h @@ -0,0 +1,49 @@ +/* + * 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 __BEGETCTL_CMD_H +#define __BEGETCTL_CMD_H +#include +#include +#include + +#include "shell.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef int (*BegetCtlCmdPtr)(int argc, char **argv); + +int BegetCtlCmdAdd(const char *name, BegetCtlCmdPtr cmd); + +#define MODULE_CONSTRUCTOR(void) static void _init(void) __attribute__((constructor)); static void _init(void) +#define MODULE_DESTRUCTOR(void) static void _destroy(void) __attribute__((destructor)); static void _destroy(void) + +BShellHandle GetShellHandle(void); +void demoExit(void); + +int SetParamShellPrompt(BShellHandle shell, const char *param); +int32_t BShellParamCmdRegister(BShellHandle shell, int execMode); +int32_t BShellCmdRegister(BShellHandle shell, int execMode); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // INIT_UTILS_H \ No newline at end of file diff --git a/services/begetctl/begetctl_cmd.c b/services/begetctl/begetctl_cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..d4413c5bd9c90821704b9e496cbdcebdaf32ddae --- /dev/null +++ b/services/begetctl/begetctl_cmd.c @@ -0,0 +1,168 @@ +/* +* 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 "begetctl.h" +#include "init_utils.h" +#include "init_param.h" +#include "securec.h" +#include "shell_utils.h" +#include "parameter.h" + +#define BEGETCTRL_INIT_CMD "ohos.servicectrl.cmd" + +/** + * @brief 通用的命令通道,注册函数完成参数校验,调用HandleCmd进行处理 + * init进程使用 initCmd 按命令字进行处理 + */ +static int HandleCmd(BShellHandle shell, const char *cmdName, int argc, char **argv) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_LOGI("initCmd %s argc %d", cmdName, argc); + // format args + if (argc == 0) { + return SystemSetParameter(BEGETCTRL_INIT_CMD, cmdName); + } + char value[PARAM_VALUE_LEN_MAX] = { 0 }; + int ret = sprintf_s(value, sizeof(value) - 1, "%s ", cmdName); + BSH_CHECK(ret > 0, return BSH_INVALID_PARAM, "Failed to format cmdName"); + for (int i = 0; i < argc; i++) { + ret = strcat_s(value, sizeof(value), argv[i]); + BSH_CHECK(ret == 0, return BSH_INVALID_PARAM, "Failed to format name"); + ret = strcat_s(value, sizeof(value), " "); + BSH_CHECK(ret == 0, return BSH_INVALID_PARAM, "Failed to format name"); + } + return SystemSetParameter(BEGETCTRL_INIT_CMD, value); +} + +static int SetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv) +{ + if (argc != 2) { // 2 is set log level parameter number + char *helpArgs[] = {"set", NULL}; + BShellCmdHelp(shell, 1, helpArgs); + return 0; + } + errno = 0; + unsigned int level = strtoul(argv[1], 0, 10); // 10 is decimal + if (errno != 0) { + printf("Failed to transform %s to unsigned int. \n", argv[1]); + return -1; + } + if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) { + const char *logLevelStr[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; + int ret = HandleCmd(shell, "setloglevel", argc - 1, &argv[1]); + if (ret != 0) { + printf("Failed to set log level %s. \n", logLevelStr[level]); + } else { + printf("Success to set log level %s. \n", logLevelStr[level]); + } + } else { + printf("%s is invalid. \n", argv[1]); + } + return 0; +} + +static int32_t GetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv) +{ + int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_ERROR); + if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) { + const char *logLevelStr[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; + printf("Init log level: %s \n", logLevelStr[level]); + } + return 0; +} + +static int32_t GetUidByName(BShellHandle shell, int argc, char **argv) +{ + if (argc != 2) { // 2 is dac get uid parameter number + char *helpArgs[] = {"dac", NULL}; + BShellCmdHelp(shell, 1, helpArgs); + return 0; + } + struct passwd *data = getpwnam(argv[1]); + if (data == NULL) { + printf("getpwnam uid failed\n"); + } else { + printf("getpwnam uid %s : %u\n", argv[1], data->pw_uid); + } + + data = NULL; + while ((data = getpwent()) != NULL) { + if ((data->pw_name != NULL) && (strcmp(data->pw_name, argv[1]) == 0)) { + printf("getpwent uid %s : %u\n", argv[1], data->pw_uid); + break; + } + } + endpwent(); + return 0; +} + +static void ShowUserInGroup(struct group *data) +{ + int index = 0; + printf("users in this group:"); + while (data->gr_mem[index]) { // user in this group + printf(" %s", data->gr_mem[index]); + index++; + } + printf("\n"); + return; +} + +static int32_t GetGidByName(BShellHandle shell, int argc, char **argv) +{ + if (argc != 2) { // 2 is dac get gid parameter number + char *helpArgs[] = {"dac", NULL}; + BShellCmdHelp(shell, 1, helpArgs); + return 0; + } + struct group *data = getgrnam(argv[1]); + if (data == NULL) { + printf("getgrnam gid failed\n"); + } else { + printf("getgrnam gid %s : %u\n", argv[1], data->gr_gid); + ShowUserInGroup(data); + } + + data = NULL; + while ((data = getgrent()) != NULL) { + if ((data->gr_name != NULL) && (strcmp(data->gr_name, argv[1]) == 0)) { + printf("getgrent gid %s : %u\n", argv[1], data->gr_gid); + ShowUserInGroup(data); + break; + } + } + endgrent(); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"set", SetInitLogLevelFromParam, + "set init log level 0:debug, 1:info, 2:warning, 3:err, 4:fatal", "set log level", "set log level"}, + {"get", GetInitLogLevelFromParam, "get init log level", "get log level", "get log level"}, + {"dac", GetGidByName, "get dac gid by group name", "dac gid groupname", "dac gid"}, + {"dac", GetUidByName, "get dac uid by user name", "dac uid username", "dac uid"}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} \ No newline at end of file diff --git a/services/begetctl/bootchart_cmd.c b/services/begetctl/bootchart_cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..87c8c5183bbbe598f8ccea4c42e06e81b80ef5f8 --- /dev/null +++ b/services/begetctl/bootchart_cmd.c @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2021 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 "begetctl.h" +#include "init_param.h" + +static int bootchartCmdEnable(BShellHandle shell, int argc, char **argv) +{ + SystemSetParameter("persist.init.bootchart.enabled", "1"); + return 0; +} + +static int bootchartCmdDisable(BShellHandle shell, int argc, char **argv) +{ + SystemSetParameter("persist.init.bootchart.enabled", "0"); + return 0; +} + +static int bootchartCmdStart(BShellHandle shell, int argc, char **argv) +{ + char enable[4] = {}; // 4 enable size + uint32_t size = sizeof(enable); + int ret = SystemGetParameter("persist.init.bootchart.enabled", enable, &size); + if (ret != 0 || strcmp(enable, "1") != 0) { + BShellEnvOutput(shell, "Not bootcharting\r\n"); + return 0; + } + SystemSetParameter("ohos.servicectrl.bootchart", "start"); + return 0; +} + +static int bootchartCmdStop(BShellHandle shell, int argc, char **argv) +{ + SystemSetParameter("ohos.servicectrl.bootchart", "stop"); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"bootchart", bootchartCmdEnable, "bootchart enable", "bootchart enable", "bootchart enable"}, + {"bootchart", bootchartCmdDisable, "bootchart disable", "bootchart disable", "bootchart disable"}, + {"bootchart", bootchartCmdStart, "bootchart start", "bootchart start", "bootchart start"}, + {"bootchart", bootchartCmdStop, "bootchart stop", "bootchart stop", "bootchart stop"}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/services/begetctl/dump_service.c b/services/begetctl/dump_service.c new file mode 100644 index 0000000000000000000000000000000000000000..b864c7e21ec48387d1f52a36e7884db1ddfd89a3 --- /dev/null +++ b/services/begetctl/dump_service.c @@ -0,0 +1,144 @@ +/* +* 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 + +#ifdef ENABLE_ENTER_APPSPAWN_SANDBOX +#include "appspawn.h" +#endif +#include "begetctl.h" +#include "beget_ext.h" +#include "control_fd.h" +#include "securec.h" +#include "init_param.h" + +#define DUMP_APPSPAWN_CMD_ARGS 1 +#define DUMP_SERVICE_INFO_CMD_ARGS 2 +#define DUMP_SERVICE_BOOTEVENT_CMD_ARGS 3 + +static int SendAppspawnCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName) +{ +#ifdef ENABLE_ENTER_APPSPAWN_SANDBOX + if ((agent == NULL) || (cmd == NULL) || (ptyName == NULL)) { + BEGET_LOGE("Invalid parameter"); + return -1; + } + + int ret = -1; + AppSpawnClientHandle clientHandle; + if (strcmp(cmd, "dump_appspawn") == 0) { + ret = AppSpawnClientInit("AppSpawn", &clientHandle); + } else if (strcmp(cmd, "dump_nwebspawn") == 0) { + ret = AppSpawnClientInit("NWebSpawn", &clientHandle); + } else { + BEGET_LOGE("Invalid parameter to dump appspawn"); + } + BEGET_ERROR_CHECK(ret == 0, return -1, "AppSpawnClientInit error, errno = %d", errno); + AppSpawnReqMsgHandle reqHandle; + ret = AppSpawnReqMsgCreate(MSG_DUMP, ptyName, &reqHandle); + BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); + return -1, "AppSpawnReqMsgCreate error"); + ret = AppSpawnReqMsgAddStringInfo(reqHandle, "pty-name", ptyName); + BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); + return -1, "add %s request message error", ptyName); + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + if (ret != 0 || result.result != 0) { + AppSpawnClientDestroy(clientHandle); + return -1; + } + AppSpawnClientDestroy(clientHandle); + return 0; +#endif + return -1; +} + +static void DumpAppspawnClientInit(const char *cmd, CallbackSendMsgProcess sendMsg) +{ + if (cmd == NULL) { + BEGET_LOGE("[control_fd] Invalid parameter"); + return; + } + + CmdAgent agent; + int ret = InitPtyInterface(&agent, ACTION_DUMP, cmd, sendMsg); + if (ret != 0) { + BEGET_LOGE("App with pid=%s does not support entering sandbox environment", cmd); + return; + } + LE_RunLoop(LE_GetDefaultLoop()); + LE_CloseLoop(LE_GetDefaultLoop()); + BEGET_LOGI("Cmd Client exit "); +} + +static int main_cmd(BShellHandle shell, int argc, char **argv) +{ + if (argc == DUMP_APPSPAWN_CMD_ARGS) { + DumpAppspawnClientInit(argv[0], SendAppspawnCmdMessage); + } else if (argc == DUMP_SERVICE_INFO_CMD_ARGS) { + printf("dump service info \n"); + CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_DUMP, argv[1], NULL); + } else if (argc == DUMP_SERVICE_BOOTEVENT_CMD_ARGS) { + if (strcmp(argv[1], "parameter_service") == 0) { + printf("dump parameter service info \n"); + } + size_t serviceNameLen = strlen(argv[1]) + strlen(argv[2]) + 2; // 2 is \0 and # + char *cmd = (char *)calloc(1, serviceNameLen); + BEGET_ERROR_CHECK(cmd != NULL, return 0, "failed to allocate cmd memory"); + BEGET_ERROR_CHECK(sprintf_s(cmd, serviceNameLen, "%s#%s", argv[1], argv[2]) >= 0, free(cmd); + return 0, "dump service arg create failed"); + CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_DUMP, cmd, NULL); + free(cmd); + } else { + BShellCmdHelp(shell, argc, argv); + } + return 0; +} + +static int BootEventEnable(BShellHandle shell, int argc, char **argv) +{ + if (SystemSetParameter("persist.init.bootevent.enable", "true") == 0) { + printf("bootevent enabled\n"); + } + return 0; +} +static int BootEventDisable(BShellHandle shell, int argc, char **argv) +{ + if (SystemSetParameter("persist.init.bootevent.enable", "false") == 0) { + printf("bootevent disabled\n"); + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"dump_service", main_cmd, "dump all loop info", "dump_service loop", NULL}, + {"dump_service", main_cmd, "dump one service info by serviceName", "dump_service serviceName", NULL}, + {"dump_service", main_cmd, "dump all services info", "dump_service all", NULL}, + {"dump_service", main_cmd, "dump parameter-service trigger", + "dump_service parameter_service trigger", NULL}, + {"bootevent", BootEventEnable, "bootevent enable", "bootevent enable", + "bootevent enable"}, + {"bootevent", BootEventDisable, "bootevent disable", "bootevent disable", + "bootevent disable"}, + {"dump_appspawn", main_cmd, "dump appspawn info", "dump_appspawn", NULL }, + {"dump_nwebspawn", main_cmd, "dump nwebspawn info", "dump_nwebspawn", NULL} + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/services/cmds/reboot/init_cmd_reboot.c b/services/begetctl/init_cmd_reboot.c similarity index 45% rename from services/cmds/reboot/init_cmd_reboot.c rename to services/begetctl/init_cmd_reboot.c index 943021b1e6112a308a702d540adcffcdaf329edf..7f8114fb40f3818b92d36995db7f4f7f81547588 100644 --- a/services/cmds/reboot/init_cmd_reboot.c +++ b/services/begetctl/init_cmd_reboot.c @@ -1,51 +1,73 @@ -/* - * Copyright (c) 2021 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 "init_reboot.h" - -#define REBOOT_CMD_NUMBER 2 - -int main(int argc, char* argv[]) -{ - if (argc > REBOOT_CMD_NUMBER) { - printf("usage: reboot shutdown\n reboot updater\n reboot updater[:options]\n reboot\n"); - return 0; - } - if (argc == REBOOT_CMD_NUMBER && strcmp(argv[1], "shutdown") != 0 && - strcmp(argv[1], "updater") != 0 && - strncmp(argv[1], "updater:", strlen("updater:")) != 0) { - printf("usage: reboot shutdown\n reboot updater\n reboot updater[:options]\n reboot\n"); - return 0; - } - int ret = 0; - if (argc == REBOOT_CMD_NUMBER) { - ret = DoReboot(argv[1]); - } else { - ret = DoReboot(NULL); - } - if (ret != 0) { - printf("[reboot command] DoReboot Api return error\n"); - } else { - printf("[reboot command] DoReboot Api return ok\n"); - } - while (1) { - pause(); - } - return 0; -} - +/* + * 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 "init_reboot.h" +#include "begetctl.h" + +#define REBOOT_CMD_NUMBER 2 +static int main_cmd(BShellHandle shell, int argc, char* argv[]) +{ + if (argc > REBOOT_CMD_NUMBER) { + BShellCmdHelp(shell, argc, argv); + return 0; + } + int ret; + if (argc == REBOOT_CMD_NUMBER) { +#ifndef SUPPORT_REBOOT_CHARGE + if (strncmp(argv[1], "charge", strlen("charge")) == 0) { + ret = DoReboot(NULL); + } else { + ret = DoReboot(argv[1]); + } +#else + ret = DoReboot(argv[1]); +#endif + } else { + ret = DoReboot(NULL); + } + if (ret != 0) { + printf("[reboot command] DoReboot Api return error\n"); + } else { + printf("[reboot command] DoReboot Api return ok\n"); + } +#ifndef STARTUP_INIT_TEST + while (1) { + pause(); + } +#endif + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + CmdInfo infos[] = { + {"reboot", main_cmd, "reboot system", "reboot", ""}, + {"reboot", main_cmd, "shutdown system", "reboot shutdown[:options]", ""}, + {"reboot", main_cmd, "suspend system", "reboot suspend", ""}, + {"reboot", main_cmd, "reboot and boot into updater", "reboot updater", ""}, + {"reboot", main_cmd, "reboot and boot into updater", "reboot updater[:options]", ""}, + {"reboot", main_cmd, "reboot and boot into flashd", "reboot flashd", ""}, + {"reboot", main_cmd, "reboot and boot into flashd", "reboot flashd[:options]", ""}, +#ifdef SUPPORT_REBOOT_CHARGE + {"reboot", main_cmd, "reboot and boot into charge", "reboot charge", ""}, +#endif + }; + for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i - 1]); + } +} diff --git a/ueventd/ueventd_utils.c b/services/begetctl/main.c old mode 100755 new mode 100644 similarity index 32% rename from ueventd/ueventd_utils.c rename to services/begetctl/main.c index 22b03da4b15ec64f066f654345867684aee66754..c59a0dbf1afe19404730065690caa26df8b4fdb0 --- a/ueventd/ueventd_utils.c +++ b/services/begetctl/main.c @@ -12,71 +12,64 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#include "ueventd_utils.h" -#include -#include +#include +#include #include -#include -#include "securec.h" -#define INIT_LOG_TAG "ueventd" -#include "init_log.h" -int MakeDir(const char *dir, mode_t mode) +#include "begetctl.h" +#include "shell.h" +#include "shell_utils.h" + +static BShellHandle g_handle = NULL; +BShellHandle GetShellHandle(void) { - int rc = -1; - if (INVALIDSTRING(dir)) { - errno = EINVAL; - return rc; - } - rc = mkdir(dir, mode); - if (rc < 0 && errno != EEXIST) { - INIT_LOGE("Create directory \" %s \" failed, err = %d", dir, errno); - return rc; + if (g_handle == NULL) { + BShellInfo info = {PARAM_SHELL_DEFAULT_PROMPT, NULL}; + BShellEnvInit(&g_handle, &info); } - // create dir success or it already exist. - return 0; + return g_handle; } -int MakeDirRecursive(const char *dir, mode_t mode) +static void signalHandler(int signal) { - int rc = -1; - char buffer[PATH_MAX] = {}; - const char *p = NULL; - if (INVALIDSTRING(dir)) { - errno = EINVAL; - return rc; - } - char *slash = strchr(dir, '/'); - p = dir; - while (slash != NULL) { - int gap = slash - p; - p = slash + 1; - if (gap == 0) { - slash = strchr(p, '/'); - continue; - } - if (gap < 0) { // end with '/' - break; - } - if (memcpy_s(buffer, PATH_MAX, dir, p - dir -1) != 0) { - return -1; - } - rc = MakeDir(buffer, mode); - if (rc < 0) { - return rc; - } - slash = strchr(p, '/'); - } - return MakeDir(dir, mode); + demoExit(); + exit(0); } -int StringToInt(const char *str, int defaultValue) +int main(int argc, char *argv[]) { - if (INVALIDSTRING(str)) { - return defaultValue; + (void)signal(SIGINT, signalHandler); + const char *last = strrchr(argv[0], '/'); + // Get the first ending command name + if (last != NULL) { + last = last + 1; + } else { + last = argv[0]; + } + + // If it is begetctl with subcommand name, try to do subcommand first + int number = argc; + char **args = argv; + if ((argc > 1) && (strcmp(last, "begetctl") == 0)) { + number = argc - 1; + args = argv + 1; + } + if (number >= 1 && strcmp(args[0], "devctl") == 0) { + if (memcpy_s(args[0], strlen(args[0]), "reboot", strlen("reboot")) != 0) { + printf("Failed to copy\n"); + } + } + BShellHandle handle = GetShellHandle(); + if (handle == NULL) { + printf("Failed to get shell handle \n"); + return 0; } - errno = 0; - int value = strtoul(str, NULL, DECIMALISM); - return errno != 0 ? defaultValue : value; + + BShellParamCmdRegister(handle, 0); +#ifdef INIT_TEST + BShellCmdRegister(handle, 0); +#endif + BShellEnvDirectExecute(handle, number, args); + demoExit(); + return 0; } diff --git a/services/begetctl/misc_daemon.cpp b/services/begetctl/misc_daemon.cpp new file mode 100755 index 0000000000000000000000000000000000000000..6ad945ca70fe1b76dd8b5e003efdfeb574c0f25e --- /dev/null +++ b/services/begetctl/misc_daemon.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021 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 "begetctl.h" +#include "fs_manager/fs_manager.h" +#include "shell.h" +#include "shell_utils.h" +#include "init_param.h" + +constexpr int MAX_LOGO_SIZE = 1024 * 2038; +constexpr int PARTITION_INFO_POS = 1144; +constexpr int PARTITION_INFO_MAX_LENGTH = 256; +constexpr int BLOCK_SZIE_1 = 512; +constexpr uint64_t LOGO_MAGIC = 0XABCABCAB; + +#define MISC_DEVICE_NODE "/dev/block/by-name/misc" + +static void ClearLogo(int fd) +{ + if (fd < 0) { + return; + } + char buffer[8] = {0}; // logo magic number + logo size is 8 + int addrOffset = (PARTITION_INFO_POS + PARTITION_INFO_MAX_LENGTH + BLOCK_SZIE_1 - 1) / BLOCK_SZIE_1; + if (lseek(fd, addrOffset * BLOCK_SZIE_1, SEEK_SET) < 0) { + std::cout << "Failed to clean file\n"; + return; + } + if (write(fd, &buffer, sizeof(buffer)) != sizeof(buffer)) { + std::cout << "clean misc failed\n"; + return; + } +} + +static void WriteLogoContent(int fd, const std::string &logoPath, uint32_t size) +{ + if (size == 0 || size > MAX_LOGO_SIZE) { + BSH_LOGE("logo size is invalid!"); + return; + } + FILE *rgbFile = fopen(logoPath.c_str(), "rb"); + if (rgbFile == nullptr) { + std::cout << "cannot find pic file\n"; + return; + } + char *buffer = reinterpret_cast(calloc(1, size)); + if (buffer == nullptr) { + (void)fclose(rgbFile); + return; + } + (void)fread(buffer, 1, size, rgbFile); + if (ferror(rgbFile)) { + (void)fclose(rgbFile); + free(buffer); + return; + } + ssize_t ret = write(fd, buffer, size); + if (ret == -1 || ret != size) { + (void)fclose(rgbFile); + free(buffer); + return; + } + free(buffer); + (void)fclose(rgbFile); +} + +static int WriteLogo(int fd, const std::string &logoPath) +{ + int addrOffset = (PARTITION_INFO_POS + PARTITION_INFO_MAX_LENGTH + BLOCK_SZIE_1 - 1) / BLOCK_SZIE_1; + if (lseek(fd, addrOffset * BLOCK_SZIE_1, SEEK_SET) < 0) { + BSH_LOGI("Failed lseek logoPath %s errno %d ", logoPath.c_str(), errno); + return -1; + } + + uint32_t magic = 0; + if (read(fd, &magic, sizeof(uint32_t)) != sizeof(uint32_t)) { + BSH_LOGI("Failed magic logoPath %s errno %d ", logoPath.c_str(), errno); + return -1; + } +#ifndef STARTUP_INIT_TEST + if (magic == LOGO_MAGIC) { + BSH_LOGI("Get matched magic number, logo already written\n"); + return 0; + } +#endif + struct stat st {}; + magic = LOGO_MAGIC; + lseek(fd, addrOffset * BLOCK_SZIE_1, SEEK_SET); + if (write(fd, &magic, sizeof(magic)) != sizeof(magic)) { + BSH_LOGI("Write magic number failed %d", errno); + return -1; + } + + if (stat(logoPath.c_str(), &st) < 0) { + if (errno == ENOENT) { + BSH_LOGI("%s is not exist", logoPath.c_str()); + } else { + BSH_LOGI("Failed to get %s stat", logoPath.c_str()); + } + ClearLogo(fd); + return -1; + } + + if (st.st_size <= 0 || st.st_size > MAX_LOGO_SIZE) { + BSH_LOGE("Invalid logo file with size "); + ClearLogo(fd); + return -1; + } + + uint32_t logoSize = static_cast(st.st_size); + if (write(fd, &logoSize, sizeof(logoSize)) != sizeof(logoSize)) { + BSH_LOGE("Write logo size failed "); + ClearLogo(fd); + return -1; + } + + WriteLogoContent(fd, logoPath, logoSize); + return 0; +} + +static void WriteLogoToMisc(const std::string &logoPath) +{ + if (logoPath.empty()) { + std::cout << "logo path is empty\n"; + return; + } + int fd = open(MISC_DEVICE_NODE, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) { + BSH_LOGI("Failed to writeLogoToMisc errno %d ", errno); + return; + } + + if (WriteLogo(fd, logoPath) < 0) { + BSH_LOGI("Failed WriteLogo errno %d ", errno); + } + close(fd); + int addrOffset = (PARTITION_INFO_POS + PARTITION_INFO_MAX_LENGTH + BLOCK_SZIE_1 - 1) / BLOCK_SZIE_1; + int fd1 = open(MISC_DEVICE_NODE, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd1 < 0) { + return; + } + if (lseek(fd1, addrOffset * BLOCK_SZIE_1, SEEK_SET) < 0) { + BSH_LOGI("Failed lseek errno %d ", errno); + close(fd1); + return; + } + + uint32_t magic = 0; + uint32_t size = 0; + if (read(fd1, &magic, sizeof(uint32_t)) != sizeof(uint32_t)) { + BSH_LOGI("Failed read errno %d ", errno); + close(fd1); + return; + } + if (read(fd1, &size, sizeof(uint32_t)) != sizeof(uint32_t)) { + BSH_LOGI("Failed read migic errno %d ", errno); + close(fd1); + return; + } + + close(fd1); +} + +static int main_cmd(BShellHandle shell, int argc, char **argv) +{ + if (argc >= 2 && strcmp(const_cast("--write_logo"), argv[0]) == 0) { // 2 min arg + WriteLogoToMisc(argv[1]); + } else { + char *helpArgs[] = {const_cast("misc_daemon"), nullptr}; + BShellCmdHelp(shell, 1, helpArgs); + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + { + const_cast("misc_daemon"), main_cmd, const_cast("write start logo"), + const_cast("misc_daemon --write_logo xxx.rgb"), const_cast("misc_daemon --write_logo") + } + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/services/begetctl/modulectl.c b/services/begetctl/modulectl.c new file mode 100644 index 0000000000000000000000000000000000000000..89e9bc4cf1fe54f3d55f51a700da7ac00435e124 --- /dev/null +++ b/services/begetctl/modulectl.c @@ -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. +*/ +#include +#include + +#include "begetctl.h" +#include "control_fd.h" +#include "init_utils.h" +#include "init_param.h" +#include "securec.h" +#include "shell_utils.h" + +#define MODULE_CTL_CMD_ARGS 2 +static int32_t ModuleInstallCmd(BShellHandle shell, int32_t argc, char *argv[]) +{ + if (argc != MODULE_CTL_CMD_ARGS) { + BShellCmdHelp(shell, argc, argv); + return 0; + } + BSH_LOGV("ModuleInstallCmd %s %s \n", argv[0], argv[1]); + char combinedArgs[MAX_BUFFER_LEN]; + int ret = sprintf_s(combinedArgs, sizeof(combinedArgs), "ohos.servicectrl.%s", argv[0]); + BSH_CHECK(ret > 0, return -1, "Invalid buffer"); + combinedArgs[ret] = '\0'; + SystemSetParameter(combinedArgs, argv[1]); + return 0; +} + +static int ModuleDisplayCmd(BShellHandle shell, int argc, char **argv) +{ + if (argc < 1) { + BShellCmdHelp(shell, argc, argv); + return 0; + } + CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_MODULEMGR, argv[0], NULL); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"modulectl", ModuleDisplayCmd, "dump all modules installed", + "modulectl list", "modulectl list"}, + {"modulectl", ModuleInstallCmd, "install specified module", + "modulectl install moduleName", "modulectl install"}, + {"modulectl", ModuleInstallCmd, "uninstall specified module", + "modulectl uninstall moduleName", "modulectl uninstall"}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/services/begetctl/param_cmd.c b/services/begetctl/param_cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..775b6852a69ca172ea9ac08dda4186ea8b897131 --- /dev/null +++ b/services/begetctl/param_cmd.c @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2021-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 +#undef _GNU_SOURCE +#define _GNU_SOURCE +#include + +#include "begetctl.h" +#include "param_manager.h" +#include "param_security.h" +#include "init_param.h" +#include "shell_utils.h" +#include "param_init.h" +#include "beget_ext.h" +#ifdef PARAM_SUPPORT_SELINUX +#include +#include +#include "selinux_parameter.h" +#endif // PARAM_SUPPORT_SELINUX + +typedef struct { + uid_t uid; + gid_t gid; + int cloneFlg; + char *parameter; +} ParamShellExecArgs; + +#define STACK_SIZE (1024 * 1024 * 8) +#define MASK_LENGTH_MAX 4 +pid_t g_shellPid = 0; +static struct termios g_terminalState; +char g_isSetTerminal = 0; + +void demoExit(void) +{ + if (g_shellPid != 0) { +#ifndef STARTUP_INIT_TEST + kill(g_shellPid, SIGKILL); +#endif + } +} + +#define CMD_PATH "/system/bin/paramshell" +#define SHELL_NAME "paramshell" +#ifndef TIOCSCTTY +#define TIOCSCTTY 0x540E +#endif +static char *GetLocalBuffer(uint32_t *buffSize) +{ + static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0}; + BEGET_CHECK(buffSize == NULL, *buffSize = sizeof(buffer)); + return buffer; +} + +static char *GetRealParameter(BShellHandle shell, const char *name, char *buffer, uint32_t buffSize) +{ + BSH_CHECK(buffer != NULL && name != NULL, return NULL, "Invalid parameter"); + const BShellParam *param = BShellEnvGetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER); + const char *current = (param == NULL) ? "" : param->value.string; + int32_t realLen = 0; + int ret = 0; + if (name[0] == '.') { // relatively + if (strcmp(name, "..") == 0) { + char *tmp = strrchr(current, '.'); + if (tmp != NULL) { + realLen = tmp - current; + ret = memcpy_s(buffer, buffSize, current, realLen); + } else { + ret = memcpy_s(buffer, buffSize, "#", 1); + realLen = 1; + } + BSH_CHECK(ret == 0, return NULL, "Failed to memcpy"); + } else if (strcmp(name, ".") == 0) { + realLen = sprintf_s(buffer, buffSize, "%s", current); + } else { + realLen = sprintf_s(buffer, buffSize, "%s%s", current, name); + } + } else if (strlen(name) == 0) { + realLen = sprintf_s(buffer, buffSize, "%s", current); + } else { + realLen = sprintf_s(buffer, buffSize, "%s", name); + } + BSH_CHECK(realLen >= 0, return NULL, "Failed to format buffer"); + buffer[realLen] = '\0'; + BSH_LOGV("GetRealParameter current %s input %s real %s", current, name, buffer); + return buffer; +} + +int SetParamShellPrompt(BShellHandle shell, const char *param) +{ + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, param, buffer, buffSize); + BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + if (strlen(realParameter) == 0) { + BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT); + return -1; + } + // check parameter + int ret = SystemCheckParamExist(realParameter); + if (ret == PARAM_CODE_NOT_FOUND) { + BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", realParameter); + return -1; + } else if (ret != 0 && ret != PARAM_CODE_NODE_EXIST) { + BShellEnvOutput(shell, "Error: Forbid to enter parameters \'%s\'\r\n", realParameter); + return -1; + } + if (strcmp(realParameter, "#") == 0) { + ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER, + "", PARAM_STRING, (void *)""); + BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value"); + BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT); + return 0; + } + ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER, + "", PARAM_STRING, (void *)realParameter); + BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value"); + if (strcat_s(realParameter, buffSize, "#") != 0) { + BSH_CHECK(ret != 0, return BSH_SYSTEM_ERR, "Failed to cat prompt %s", realParameter); + } + BShellEnvOutputPrompt(shell, realParameter); + return 0; +} + +static char *GetPermissionString(uint32_t mode, int shift, char *str, int size) +{ + BEGET_CHECK(!(size < MASK_LENGTH_MAX), return str); + str[0] = '-'; + str[1] = '-'; + str[2] = '-'; // 2 watcher + str[3] = '\0'; // 3 end + if (mode & (DAC_READ >> shift)) { + str[0] = 'r'; + } + if (mode & (DAC_WRITE >> shift)) { + str[1] = 'w'; + } + if (mode & (DAC_WATCH >> shift)) { + str[2] = 'w'; // 2 watcher + } + return str; +} + +static void ShowParam(BShellHandle shell, const char *name, const char *value) +{ + ParamAuditData auditData = {}; + int ret = GetParamSecurityAuditData(name, 0, &auditData); + BSH_CHECK(ret == 0, return, "Failed to get param security for %s", name); + BShellEnvOutput(shell, "Parameter information:\r\n"); +#ifdef PARAM_SUPPORT_SELINUX + BShellEnvOutput(shell, "selinux : %s \r\n", auditData.label); +#endif + char permissionStr[3][MASK_LENGTH_MAX] = {}; // 3 permission + struct passwd *user = getpwuid(auditData.dacData.uid); + struct group *group = getgrgid(auditData.dacData.gid); + if (user != NULL && group != NULL) { + BShellEnvOutput(shell, " dac : %s(%s) %s(%s) (%s) \r\n", + user->pw_name, + GetPermissionString(auditData.dacData.mode, 0, permissionStr[0], MASK_LENGTH_MAX), + group->gr_name, + GetPermissionString(auditData.dacData.mode, DAC_GROUP_START, permissionStr[1], MASK_LENGTH_MAX), + // 2 other + GetPermissionString(auditData.dacData.mode, DAC_OTHER_START, permissionStr[2], MASK_LENGTH_MAX)); + } + if (strcmp("#", name) != 0) { + BShellEnvOutput(shell, " name : %s\r\n", name); + } + if (value != NULL) { + BShellEnvOutput(shell, " value: %s\r\n", value); + } +} + +static void ShowParamForCmdLs(ParamHandle handle, void *cookie) +{ + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + if (buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)) { + return; + } + char *value = buffer + PARAM_NAME_LEN_MAX; + (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX); + uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX; + (void)SystemGetParameterValue(handle, value, &valueLen); + ShowParam((BShellHandle)cookie, buffer, value); +} + +static int32_t BShellParamCmdLs(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + int all = 0; + char *input = NULL; + for (int32_t i = 1; i < argc; i++) { + if (strcmp(argv[i], "-r") == 0) { + all = 1; + } else if (input == NULL) { + input = argv[i]; + } + } + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, (input == NULL) ? "" : input, buffer, buffSize); + BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + char *prefix = strdup((strlen(realParameter) == 0) ? "#" : realParameter); + BSH_CHECK(prefix != NULL, return BSH_SYSTEM_ERR, "failed dup perfix"); + BSH_LOGV("BShellParamCmdLs prefix %s", prefix); + int ret = 0; + if (all != 0) { + ret = SystemTraversalParameter(prefix, ShowParamForCmdLs, (void *)shell); + if (ret != 0) { + BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n"); + } + } else { + ret = SystemCheckParamExist(prefix); + if (ret == 0) { + ParamHandle handle; + ret = SystemFindParameter(prefix, &handle); + if (ret != 0) { + BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n"); + } else { + ShowParamForCmdLs(handle, (void *)shell); + } + } else if (ret == PARAM_CODE_NODE_EXIST) { + ShowParam(shell, prefix, NULL); + } else if (ret != PARAM_CODE_NOT_FOUND) { + BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n"); + } else { + BShellEnvOutput(shell, "Parameter %s not found\r\n", prefix); + } + } + free(prefix); + return 0; +} + +static int32_t BShellParamCmdCat(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env"); + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize); + BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + int ret = SystemGetParameter(realParameter, buffer, &buffSize); + BSH_CHECK(ret != 0, BShellEnvOutput(shell, " %s\r\n", buffer)); + return 0; +} + +static int32_t BShellParamCmdCd(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env"); + SetParamShellPrompt(shell, argv[1]); + return 0; +} + +static void ShowParamForCmdGet(ParamHandle handle, void *cookie) +{ + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + BSH_CHECK(!(buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)), return); + char *value = buffer + PARAM_NAME_LEN_MAX; + (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX); + uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX; + (void)SystemGetParameterValue(handle, value, &valueLen); + BShellEnvOutput((BShellHandle)cookie, " %s = %s\r\n", buffer, value); +} + +static int32_t BShellParamCmdGet(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env"); + int ret = 0; + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, (argc == 1) ? "" : argv[1], buffer, buffSize); + if ((argc == 1) || (realParameter == NULL) || + (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) { + ret = SystemTraversalParameter(realParameter, ShowParamForCmdGet, (void *)shell); + if (ret != 0) { + BShellEnvOutput(shell, "Error: Forbid to get all parameters\r\n"); + } + return 0; + } + char *key = strdup(realParameter); + BSH_CHECK(key != NULL, return BSH_SYSTEM_ERR, "failed to fup key"); + ret = SystemGetParameter(key, buffer, &buffSize); + if (ret == 0) { + BShellEnvOutput(shell, "%s \n", buffer); + } else { + BShellEnvOutput(shell, "Get parameter \"%s\" fail! errNum is:%d!\n", key, ret); + } + free(key); + return 0; +} + +static int32_t BShellParamCmdSet(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + if (argc < 3) { // 3 min param + char *helpArgs[] = {"param", NULL}; + BShellCmdHelp(shell, 1, helpArgs); + return 0; + } + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize); + if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) { + BShellEnvOutput(shell, "Set parameter %s %s fail\n", argv[1], argv[2]); // 2 value param + return 0; + } + int ret = SystemSetParameter(realParameter, argv[2]); // 2 value param + if (ret == 0) { + BShellEnvOutput(shell, "Set parameter %s %s success\n", realParameter, argv[2]); // 2 value param + } else { + BShellEnvOutput(shell, "Set parameter %s %s fail! errNum is:%d!\n", realParameter, argv[2], ret); // 2 param + } + return 0; +} + +static int32_t BShellParamCmdSave(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(argc == 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env"); + + int ret = SystemSaveParameters(); + if (ret == 0) { + BShellEnvOutput(shell, "Save persist parameters success\n"); + } else { + BShellEnvOutput(shell, "Save persist parameters fail! errNum is:%d!\n", ret); + } + return 0; +} + +static int32_t BShellParamCmdWait(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + if (argc < 2) { // 2 min param + char *helpArgs[] = {"param", NULL}; + BShellCmdHelp(shell, 1, helpArgs); + return 0; + } + int32_t timeout = 30; // 30s + char *value = "*"; + if (argc > 2) { // 2 value param + value = argv[2]; // 2 value param + } + if (argc > 3) { // 3 timeout param + timeout = atoi(argv[3]); // 3 timeout param + } + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize); + if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) { + BShellEnvOutput(shell, "Wait parameter %s fail\n", argv[1]); + return 0; + } + + int ret = SystemWaitParameter(realParameter, value, timeout); + if (ret == 0) { + BShellEnvOutput(shell, "Wait parameter %s success\n", argv[1]); + } else { + BShellEnvOutput(shell, "Wait parameter %s fail! errNum is:%d!\n", argv[1], ret); + } + return 0; +} + +static int32_t BShellParamCmdDump(BShellHandle shell, int32_t argc, char *argv[]) +{ + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + if (argc >= 2) { // 2 min parameter + if (strcmp(argv[1], "verbose") == 0) { + SystemDumpParameters(1, -1, printf); + return 0; + } + int index = StringToInt(argv[1], 0); + SystemDumpParameters(1, index, printf); + return 0; + } + SystemDumpParameters(0, -1, printf); + return 0; +} + +static int32_t BShellParamCmdPwd(BShellHandle shell, int32_t argc, char *argv[]) +{ + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + char *realParameter = GetRealParameter(shell, "", buffer, buffSize); + BShellEnvOutput(shell, "%s\r\n", realParameter); + return 0; +} + +static void GetUserInfo(ParamShellExecArgs *execArg, int32_t argc, char *argv[]) +{ + int32_t i = 0; + execArg->parameter = NULL; + while (i < argc) { + if (strcmp(argv[i], "-p") == 0 && ((i + 1) < argc)) { + execArg->parameter = argv[i + 1]; + ++i; + } else if (strcmp(argv[i], "-u") == 0 && ((i + 1) < argc)) { + execArg->uid = DecodeUid(argv[i + 1]); + execArg->uid = (execArg->uid == -1) ? 0 : execArg->uid; + ++i; + } else if (strcmp(argv[i], "-g") == 0 && ((i + 1) < argc)) { + execArg->gid = DecodeGid(argv[i + 1]); + execArg->gid = (execArg->gid == -1) ? 0 : execArg->gid; + ++i; + } else if (strcmp(argv[i], "-c") == 0) { + execArg->cloneFlg = 1; + } + ++i; + } +} + +static int ExecFunc(void *arg) +{ + ParamShellExecArgs *execArg = (ParamShellExecArgs *)arg; + int ret = 0; + setuid(execArg->uid); + setgid(execArg->gid); + BSH_LOGI("Exec shell %s \n", SHELL_NAME); + if (execArg->parameter != NULL) { // 2 min argc + char *args[] = {SHELL_NAME, execArg->parameter, NULL}; + ret = execv(CMD_PATH, args); + } else { + char *args[] = {SHELL_NAME, NULL}; + ret = execv(CMD_PATH, args); + } + if (ret != 0) { + printf("error on exec %d \n", errno); + exit(0); + } + return ret; +} + +static pid_t ForkChild(int (*childFunc)(void *arg), void *args) +{ + pid_t pid = fork(); + if (pid == 0) { + childFunc(args); + exit(0); + } + return pid; +} + +static int32_t BShellParamCmdShell(BShellHandle shell, int32_t argc, char *argv[]) +{ +#ifndef STARTUP_INIT_TEST + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + int ret = 0; + if (tcgetattr(0, &g_terminalState)) { + return BSH_SYSTEM_ERR; + } + g_isSetTerminal = 1; + ParamShellExecArgs args = {0, 0, 0, NULL}; + GetUserInfo(&args, argc, argv); + BSH_LOGV("BShellParamCmdShell %s %d %d argc %d", args.parameter, args.uid, args.gid, argc); + if (args.parameter != NULL) { + ret = SystemCheckParamExist(args.parameter); + if (ret != 0) { + BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", args.parameter); + return -1; + } + } + SetInitLogLevel(INIT_INFO); + pid_t pid = 0; + if (args.cloneFlg) { + char *childStack = (char *)calloc(1, STACK_SIZE); + BSH_CHECK(childStack != NULL, return -1, "calloc failed"); + pid = clone(ExecFunc, childStack + STACK_SIZE, CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, (void *)&args); + free(childStack); + } else { + pid = ForkChild(ExecFunc, (void *)&args); + } + if (pid > 0) { + g_shellPid = pid; + int status = 0; + wait(&status); + tcsetattr(0, TCSAFLUSH, &g_terminalState); + g_isSetTerminal = 0; + } +#endif + return 0; +} + +static int32_t BShellParamCmdRegForShell(BShellHandle shell) +{ + const CmdInfo infos[] = { + {"ls", BShellParamCmdLs, "display system parameter", "ls [-r] [name]", NULL}, + {"get", BShellParamCmdGet, "get system parameter", "get [name]", NULL}, + {"set", BShellParamCmdSet, "set system parameter", "set name value", NULL}, + {"wait", BShellParamCmdWait, "wait system parameter", "wait name [value] [timeout]", NULL}, + {"dump", BShellParamCmdDump, "dump system parameter", "dump [verbose]", ""}, + {"cd", BShellParamCmdCd, "change path of parameter", "cd name", NULL}, + {"cat", BShellParamCmdCat, "display value of parameter", "cat name", NULL}, + {"pwd", BShellParamCmdPwd, "display current parameter", "pwd", NULL}, + {"save", BShellParamCmdSave, "save all persist parameters in workspace", "save", NULL}, + }; + for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) { + BShellEnvRegisterCmd(shell, &infos[i - 1]); + } + return 0; +} + +static bool IsUserMode() +{ + bool isUser = true; + char value[2] = {0}; + uint32_t length = sizeof(value); + int ret = SystemGetParameter("const.debuggable", value, &length); + if (ret != 0) { + BSH_LOGI("Failed to get param"); + return isUser; + } + if (strcmp(value, "1") == 0) { + isUser = false; + } + return isUser; +} + +static bool IsDebugCmd(const CmdInfo *cmdInfo) +{ + if (strcmp(cmdInfo->multikey, "param dump") == 0 || strcmp(cmdInfo->multikey, "param shell") == 0) { + return true; + } + return false; +} + +static int32_t BShellParamCmdRegForIndepent(BShellHandle shell) +{ + const CmdInfo infos[] = { + {"param", BShellParamCmdLs, "display system parameter", "param ls [-r] [name]", "param ls"}, + {"param", BShellParamCmdGet, "get system parameter", "param get [name]", "param get"}, + {"param", BShellParamCmdSet, "set system parameter", "param set name value", "param set"}, + {"param", BShellParamCmdWait, "wait system parameter", "param wait name [value] [timeout]", "param wait"}, + {"param", BShellParamCmdDump, "dump system parameter", "param dump [verbose]", "param dump"}, + {"param", BShellParamCmdShell, "shell system parameter", + "param shell [-p] [name] [-u] [username] [-g] [groupname]", "param shell"}, + {"param", BShellParamCmdSave, "save all persist parameters in workspace", "param save", "param save"}, + }; + for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) { + if (IsUserMode() && IsDebugCmd(&infos[i - 1])) { + continue; + } + BShellEnvRegisterCmd(shell, &infos[i - 1]); + } + return 0; +} + +static void UpdateInitLogLevel(void) +{ + char level[2] = {0}; // 2 max length + uint32_t length = sizeof(level); + int ret = SystemGetParameter(INIT_DEBUG_LEVEL, level, &length); + if (ret == 0) { + errno = 0; + InitLogLevel value = (InitLogLevel)strtoul(level, NULL, DECIMAL_BASE); + SetInitLogLevel((errno != 0) ? INIT_WARN : value); + } +} + +int32_t BShellParamCmdRegister(BShellHandle shell, int execMode) +{ + UpdateInitLogLevel(); + if (execMode) { + BShellParamCmdRegForShell(shell); + } else { + BShellParamCmdRegForIndepent(shell); + } + return 0; +} diff --git a/services/begetctl/partitionslot.cpp b/services/begetctl/partitionslot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f8ee450b5667c67c715340208820c3d566dd7c5 --- /dev/null +++ b/services/begetctl/partitionslot.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2022-2023 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 "begetctl.h" +#include "idevmgr_hdi.h" +#include "v1_0/ipartition_slot.h" + +using namespace OHOS::HDI::Partitionslot::V1_0; +using OHOS::HDI::DeviceManager::V1_0::IDeviceManager; +static const int32_t PARTITION_ARGC = 2; + +static int LoadDevice() +{ + auto devmgr = IDeviceManager::Get(); + if (devmgr != nullptr) { + return devmgr->LoadDevice("partition_slot_service"); + } else { + std::cout << "Load devmgr failed" << std::endl; + return -1; + } +} + +static void UnloadDevice() +{ + auto devmgr = IDeviceManager::Get(); + if (devmgr != nullptr) { + devmgr->UnloadDevice("partition_slot_service"); + } +} + +static int GetSlot(BShellHandle handle, int32_t argc, char *argv[]) +{ + if (LoadDevice() != 0) { + return -1; + } + std::cout << "Command: partitionslot getslot" << std::endl; + sptr partitionslot = IPartitionSlot::Get(); + if (partitionslot != nullptr) { + int bootSlots = 0; + int currentSlot = 0; + partitionslot->GetCurrentSlot(currentSlot, bootSlots); + std::cout << "The number of slots: " << bootSlots << "," << "current slot: " << currentSlot << std::endl; + } + UnloadDevice(); + return 0; +} + +static int GetSuffix(BShellHandle handle, int32_t argc, char *argv[]) +{ + if (argc != PARTITION_ARGC) { + BShellCmdHelp(handle, argc, argv); + return -1; + } + if (LoadDevice() != 0) { + return -1; + } + std::cout << "Command: partitionslot getsuffix" << std::endl; + int slot = atoi(argv[1]); + sptr partitionslot = IPartitionSlot::Get(); + if (partitionslot != nullptr) { + std::string suffix = ""; + partitionslot->GetSlotSuffix(slot, suffix); + std::cout << "The slot " << slot << " matches with suffix: " << suffix << std::endl; + } + UnloadDevice(); + return 0; +} + +static int SetActiveSlot(BShellHandle handle, int32_t argc, char *argv[]) +{ + if (argc != PARTITION_ARGC) { + BShellCmdHelp(handle, argc, argv); + return -1; + } + if (LoadDevice() != 0) { + return -1; + } + std::cout << "Command: partitionslot setactive" << std::endl; + int slot = atoi(argv[1]); + sptr partitionslot = IPartitionSlot::Get(); + if (partitionslot != nullptr) { +#ifndef STARTUP_INIT_TEST + partitionslot->SetActiveSlot(slot); +#endif + std::cout << "Set active slot: " << slot << std::endl; + } + UnloadDevice(); + return 0; +} + +static int SetUnbootSlot(BShellHandle handle, int32_t argc, char *argv[]) +{ + if (argc != PARTITION_ARGC) { + BShellCmdHelp(handle, argc, argv); + return -1; + } + if (LoadDevice() != 0) { + return -1; + } + std::cout << "Command: partitionslot setunboot" << std::endl; + int slot = atoi(argv[1]); + sptr partitionslot = IPartitionSlot::Get(); + if (partitionslot != nullptr) { + partitionslot->SetSlotUnbootable(slot); + std::cout << "Set unboot slot: " << slot << std::endl; + } + UnloadDevice(); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + CmdInfo infos[] = { + { + const_cast("partitionslot"), GetSlot, + const_cast("get the number of slots and current slot"), + const_cast("partitionslot getslot"), const_cast("partitionslot getslot") + }, + { + const_cast("partitionslot"), GetSuffix, + const_cast("get suffix that matches with the slot"), + const_cast("partitionslot getsuffix [slot]"), const_cast("partitionslot getsuffix") + }, + { + const_cast("partitionslot"), SetActiveSlot, + const_cast("set active slot"), + const_cast("partitionslot setactive [slot]"), const_cast("partitionslot setactive") + }, + { + const_cast("partitionslot"), SetUnbootSlot, + const_cast("set unboot slot"), + const_cast("partitionslot setunboot [slot]"), const_cast("partitionslot setunboot") + } + }; + for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i - 1]); + } +} diff --git a/services/begetctl/sandbox.cpp b/services/begetctl/sandbox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2035d0115d0a6e08c2fffea4ebbc6274ab2fc68 --- /dev/null +++ b/services/begetctl/sandbox.cpp @@ -0,0 +1,276 @@ +/* + * 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 + +#ifdef ENABLE_ENTER_APPSPAWN_SANDBOX +#include "appspawn.h" +#endif +#include "begetctl.h" +#include "control_fd.h" +#include "init_utils.h" +#include "sandbox.h" +#include "sandbox_namespace.h" +#include "string_ex.h" + +using namespace OHOS; +struct option g_options[] = { + { "service_name", required_argument, nullptr, 's' }, + { "namespace_name", required_argument, nullptr, 'n' }, + { "process_name", required_argument, nullptr, 'p' }, + { "process_pid", required_argument, nullptr, 'b' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 }, +}; + +static void Usage() +{ + std::cout << "sandbox -s | -n [-p] | -p | -b | -h" << std::endl; + std::cout << "sandbox -s, --service_name=sandbox service \"enter service sandbox\"" << std::endl; + std::cout << "sandbox -n, --namespace_name=namespace name \"namespace name, system, chipset etc.\"" << std::endl; + std::cout << "sandbox -p, --process=process name \"sh, hdcd, hdf_devhost, etc.\"" << std::endl; + std::cout << "sandbox -b, --process_pid=process pid \"sh, enter native app sandbox, etc.\"" << std::endl; + std::cout << "sandbox -h, --help \"Show help\"" << std::endl; +#ifndef STARTUP_INIT_TEST + exit(0); +#endif +} + +static void RunSandbox(const std::string &sandboxName) +{ + 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[] = { const_cast("sh"), nullptr }; + 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) +{ + 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 int SendAppspawnCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName) +{ +#ifdef ENABLE_ENTER_APPSPAWN_SANDBOX + if ((agent == NULL) || (cmd == NULL) || (ptyName == NULL)) { + BEGET_LOGE("Invalid parameter"); + return -1; + } + + AppSpawnClientHandle clientHandle; + int ret = AppSpawnClientInit("AppSpawn", &clientHandle); + BEGET_ERROR_CHECK(ret == 0, return -1, "AppSpawnClientInit error, errno = %d", errno); + AppSpawnReqMsgHandle reqHandle; + ret = AppSpawnReqMsgCreate(AppSpawnMsgType::MSG_BEGET_CMD, cmd, &reqHandle); + BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); return -1, "AppSpawnReqMsgCreate error"); + ret = AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_BEGETCTL_BOOT); + BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); return -1, "AppSpawnReqMsgSetAppFlag error"); + ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_BEGET_PID, cmd); + BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); return -1, "add %s request message error", cmd); + ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_BEGET_PTY_NAME, ptyName); + BEGET_ERROR_CHECK(ret == 0, AppSpawnClientDestroy(clientHandle); + return -1, "add %s request message error", ptyName); + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + if (ret != 0 || result.result != 0) { + AppSpawnClientDestroy(clientHandle); + return -1; + } + AppSpawnClientDestroy(clientHandle); + return 0; +#endif + return -1; +} + +static void CmdAppspawnClientInit(const char *cmd, CallbackSendMsgProcess sendMsg) +{ + if (cmd == nullptr) { + BEGET_LOGE("[control_fd] Invalid parameter"); + return; + } + + CmdAgent agent; + int ret = InitPtyInterface(&agent, ACTION_APP_SANDBOX, cmd, sendMsg); + if (ret != 0) { + BEGET_LOGE("App with pid=%s does not support entering sandbox environment", cmd); + return; + } + LE_RunLoop(LE_GetDefaultLoop()); + LE_CloseLoop(LE_GetDefaultLoop()); + BEGET_LOGI("Cmd Client exit "); +} + +static void RunCmd(const std::string &serviceName, const std::string &namespaceName, const std::string &processName, + const std::string &pid) +{ + bool isNamespaceOnly = !namespaceName.empty() && processName.empty() && serviceName.empty() && pid.empty(); + bool isNamespaceAndProcess = !namespaceName.empty() && !processName.empty() && serviceName.empty() && pid.empty(); + bool isProcessOnly = namespaceName.empty() && !processName.empty() && serviceName.empty() && pid.empty(); + bool isServiceOnly = namespaceName.empty() && processName.empty() && !serviceName.empty() && pid.empty(); + bool isPidOnly = namespaceName.empty() && processName.empty() && serviceName.empty() && !pid.empty(); + if (isNamespaceOnly) { + RunSandbox(namespaceName); + EnterShell(); + } else if (isNamespaceAndProcess) { + RunSandbox(namespaceName); + EnterExec(processName); + } else if (isProcessOnly) { + std::cout << "process name:" << processName << std::endl; + RunSandbox(std::string("system")); + EnterExec(processName); + } else if (isServiceOnly) { + std::cout << "enter sandbox service name " << serviceName << std::endl; + CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_SANDBOX, serviceName.c_str(), nullptr); + } else if (isPidOnly) { + CmdAppspawnClientInit(pid.c_str(), SendAppspawnCmdMessage); + } else { + Usage(); + } +} + +static int main_cmd(BShellHandle shell, int argc, char **argv) +{ + int rc = -1; + int optIndex = -1; + std::string serviceName {}; + std::string namespaceName {}; + std::string processName {}; + std::string pid {}; + while ((rc = getopt_long(argc, argv, "s:n:p:h:b:", g_options, &optIndex)) != -1) { + switch (rc) { + case 0: { + std::string optionName = g_options[optIndex].name; + if (optionName == "service_name") { + serviceName = optarg; + } else if (optionName == "help") { + Usage(); + } else if (optionName == "namespace_name") { + namespaceName = optarg; + } else if (optionName == "process_name") { + processName = optarg; + } else if (optionName == "process_pid") { + pid = optarg; + } + break; + } + case 's': + serviceName = optarg; + break; + case 'h': + Usage(); + break; + case 'n': + namespaceName = optarg; + break; + case 'p': + processName = optarg; + break; + case 'b': + pid = optarg; + break; + case '?': + std::cout << "Invalid argument\n"; + break; + default: + std::cout << "Invalid argument\n"; + break; + } + } + RunCmd(serviceName, namespaceName, processName, pid); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + { + const_cast("sandbox"), main_cmd, const_cast("enter service sandbox"), + const_cast("sandbox -s service_name"), + NULL + }, + { + const_cast("sandbox"), main_cmd, const_cast("enter namespace, system, chipset etc."), + const_cast("sandbox -n namespace_name [-p]"), + NULL + }, + { + const_cast("sandbox"), main_cmd, const_cast("enter namespace and exec process"), + const_cast("sandbox -p process_name"), + NULL + }, + { + const_cast("sandbox"), main_cmd, const_cast("enter native app sandbox namespace"), + const_cast("sandbox -b pid"), + NULL + } + }; + for (size_t i = 0; i < ARRAY_LENGTH(infos); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/services/cmds/service_control/service_control.c b/services/begetctl/service_control.c old mode 100755 new mode 100644 similarity index 31% rename from services/cmds/service_control/service_control.c rename to services/begetctl/service_control.c index 320e15553a3a09ff592959053ef52677981f8652..5165d5094f283894a6310121bd2ce7302200888e --- a/services/cmds/service_control/service_control.c +++ b/services/begetctl/service_control.c @@ -12,81 +12,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "service_control.h" -#include +#include #include -#include "securec.h" -#include "sys_param.h" +#include + +#include "begetctl.h" +#include "init_utils.h" #define SERVICE_START_NUMBER 2 #define SERVICE_CONTROL_NUMBER 3 #define CONTROL_SERVICE_POS 2 #define SERVICE_CONTROL_MAX_SIZE 50 -static void ServiceControlUsage() +static void ServiceControlUsage(BShellHandle shell, int argc, char **argv) { - printf("Please input correct params, example:\n"); - printf(" start_service serviceName\n"); - printf(" stop_service serviceName\n"); - printf(" service_control start serviceName\n"); - printf(" service_control stop serviceName\n"); + BShellCmdHelp(shell, argc, argv); return; } -static void ServiceControl(int argc, char** argv) +static int main_cmd(BShellHandle shell, int argc, char **argv) { - if (argc != SERVICE_CONTROL_NUMBER) { - ServiceControlUsage(); - return; - } - char serviceCtl[SERVICE_CONTROL_MAX_SIZE]; - if (strcmp(argv[1], "start") == 0) { - if (strncpy_s(serviceCtl, sizeof(serviceCtl), "ohos.ctl.start", sizeof(serviceCtl) - 1) != EOK) { - printf("strncpy_s failed.\n"); - return; - } - } else if (strcmp(argv[1], "stop") == 0) { - if (strncpy_s(serviceCtl, sizeof(serviceCtl), "ohos.ctl.stop", sizeof(serviceCtl) - 1) != EOK) { - printf("strncpy_s failed.\n"); - return; - } - } else { - ServiceControlUsage(); - return; - } - if (SystemSetParameter(serviceCtl, argv[CONTROL_SERVICE_POS]) != 0) { - printf("%s service:%s failed.\n", argv[1], argv[CONTROL_SERVICE_POS]); - return; - } - return; -} - -int main(int argc, char** argv) -{ - if (argc != SERVICE_START_NUMBER && argc != SERVICE_CONTROL_NUMBER) { - ServiceControlUsage(); - return -1; + if (argc < SERVICE_START_NUMBER) { + ServiceControlUsage(shell, argc, argv); + return 0; } - - char serviceCtl[SERVICE_CONTROL_MAX_SIZE]; if (strcmp(argv[0], "start_service") == 0) { - if (strncpy_s(serviceCtl, sizeof(serviceCtl), "ohos.ctl.start", sizeof(serviceCtl) - 1) != EOK) { - printf("strncpy_s failed.\n"); - return -1; - } + ServiceControlWithExtra(argv[1], 0, (const char **)argv + SERVICE_START_NUMBER, argc - SERVICE_START_NUMBER); } else if (strcmp(argv[0], "stop_service") == 0) { - if (strncpy_s(serviceCtl, sizeof(serviceCtl), "ohos.ctl.stop", sizeof(serviceCtl) - 1) != EOK) { - printf("strncpy_s failed.\n"); + ServiceControlWithExtra(argv[1], 1, (const char **)argv + SERVICE_START_NUMBER, argc - SERVICE_START_NUMBER); + } else if (strcmp(argv[0], "start") == 0) { + ServiceControlWithExtra(argv[1], 0, (const char **)argv + SERVICE_START_NUMBER, argc - SERVICE_START_NUMBER); + } else if (strcmp(argv[0], "stop") == 0) { + ServiceControlWithExtra(argv[1], 1, (const char **)argv + SERVICE_START_NUMBER, argc - SERVICE_START_NUMBER); + } else if (strcmp(argv[0], "timer_start") == 0) { + if (argc <= SERVICE_START_NUMBER) { + ServiceControlUsage(shell, argc, argv); + return 0; + } + char *timeBuffer = argv[SERVICE_START_NUMBER]; + errno = 0; + uint64_t timeout = strtoull(timeBuffer, NULL, DECIMAL_BASE); + if (errno != 0) { return -1; } + StartServiceByTimer(argv[1], timeout); + } else if (strcmp(argv[0], "timer_stop") == 0) { + StopServiceTimer(argv[1]); } else { - ServiceControl(argc, argv); - return 0; + ServiceControlUsage(shell, argc, argv); } + return 0; +} - if (SystemSetParameter(serviceCtl, argv[1]) != 0) { - printf("%s service:%s failed.\n", argv[0], argv[1]); - return -1; +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"service_control", main_cmd, "stop service", "service_control stop servicename", "service_control stop"}, + {"service_control", main_cmd, "start service", "service_control start servicename", "service_control start"}, + {"stop_service", main_cmd, "stop service", "stop_service servicename", ""}, + {"start_service", main_cmd, "start service", "start_service servicename", ""}, + {"timer_start", main_cmd, "start service by timer", "timer_start servicename timeout", ""}, + {"timer_stop", main_cmd, "stop service timer", "timer_stop servicename", ""}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); } - return 0; } diff --git a/services/begetctl/setloglevel.c b/services/begetctl/setloglevel.c new file mode 100644 index 0000000000000000000000000000000000000000..a7337c6dad2e27757b75226e61fb49aa6856d10b --- /dev/null +++ b/services/begetctl/setloglevel.c @@ -0,0 +1,75 @@ +/* +* 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 "begetctl.h" +#include "init_log.h" +#include "init_utils.h" +#include "init_param.h" +#include "securec.h" +#include "shell_utils.h" + +static int32_t SetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv) +{ + if (argc != 2) { // 2 is set log level parameter number + BShellCmdHelp(shell, argc, argv); + return 0; + } + errno = 0; + unsigned int level = strtoul(argv[1], 0, 10); // 10 is decimal + if (errno != 0) { + printf("Failed to transform %s to unsigned int. \n", argv[1]); + return -1; + } + if ((level >= INIT_DEBUG) && (level <= INIT_FATAL)) { + int ret = SystemSetParameter("persist.init.debug.loglevel", argv[1]); + if (ret != 0) { + printf("Failed to set log level by param \"persist.init.debug.loglevel\" %s. \n", argv[1]); + } else { + printf("Success to set log level by param \"persist.init.debug.loglevel\" %s. \n", argv[1]); + } + } else { + printf("Set init log level in invailed parameter %s. \n", argv[1]); + } + return 0; +} + +static int32_t GetInitLogLevelFromParam(BShellHandle shell, int argc, char **argv) +{ + char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length. + uint32_t len = sizeof(logLevel); + int ret = SystemReadParam("persist.init.debug.loglevel", logLevel, &len); + if (ret == 0) { + printf("Success to get init log level: %s from param \"persist.init.debug.loglevel\". \n", logLevel); + } else { + printf("Failed to get init log level from param, keep the system origin log level. \n"); + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + {"setloglevel", SetInitLogLevelFromParam, "set init log level 0:debug, 1:info, 2:warning, 3:err, 4:fatal", + "setloglevel level", NULL}, + {"getloglevel", GetInitLogLevelFromParam, "get init log level 0:debug, 1:info, 2:warning, 3:err, 4:fatal", + "getloglevel", NULL}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} \ No newline at end of file diff --git a/services/begetctl/shell/shell.h b/services/begetctl/shell/shell.h new file mode 100644 index 0000000000000000000000000000000000000000..243e655f6719f54c3186ca61e2018412fb343b36 --- /dev/null +++ b/services/begetctl/shell/shell.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021 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 _BSHELL_H_ +#define _BSHELL_H_ +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define PARAM_REVERESD_NAME_CURR_PARAMETER "_current_param_" +#define PARAM_SHELL_DEFAULT_PROMPT "param#" + +typedef struct BShellEnv_ *BShellHandle; +typedef int32_t (*BShellCmdExecuter_)(BShellHandle handle, int32_t argc, char *argv[]); +typedef int32_t (*BShellInput_)(char *, int32_t); +typedef int32_t (*BShellOutput_)(const char *, int32_t); +typedef int32_t (*BShellkeyHandle)(BShellHandle, uint8_t code); + +typedef enum { + BSH_ERRNO_BASE = 1000, + BSH_SHELL_INFO, + BSH_INVALID_PARAM, + BSH_CMD_TOO_LONG, + BSH_SHOW_CMD_LIST, + BSH_CMD_NOT_EXIST, + BSH_CMD_PARAM_INVALID, + BSH_SYSTEM_ERR, +} BShellErrNo; + +typedef struct BShellErrInfo_ { + BShellErrNo err; + char *desc; +} BShellErrInfo; + +typedef struct CmdInfo_ { + char *name; + BShellCmdExecuter_ executer; + char *desc; + char *help; + char *multikey; +} CmdInfo; + +typedef enum { + PARAM_INT8 = 0, + PARAM_INT16, + PARAM_INT32, + PARAM_STRING, +} BShellParamType; + +typedef struct ParamInfo_ { + char *name; + char *desc; + BShellParamType type; +} ParamInfo; + +typedef struct BShellParam_ { + char *desc; + BShellParamType type; + union { + char data; + uint8_t data8; + uint16_t data16; + uint32_t data32; + char *string; + } value; + struct BShellParam_ *next; + char name[0]; +} BShellParam; + +typedef struct BShellInfo_ { + char *prompt; + BShellInput_ input; +} BShellInfo; + +int BShellEnvInit(BShellHandle *handle, const BShellInfo *info); +int BShellEnvStart(BShellHandle handle); +void BShellEnvDestory(BShellHandle handle); + +int BShellEnvRegisterCmd(BShellHandle handle, const CmdInfo *cmdInfo); +int BShellEnvSetParam(BShellHandle handle, const char *name, const char *desc, BShellParamType type, void *value); +const BShellParam *BShellEnvGetParam(BShellHandle handle, const char *name); +int BShellEnvRegisterKeyHandle(BShellHandle handle, uint8_t code, BShellkeyHandle keyHandle); +void BShellEnvLoop(BShellHandle handle); +const ParamInfo *BShellEnvGetReservedParam(BShellHandle handle, const char *name); + +int32_t BShellEnvOutput(BShellHandle handle, char *fmt, ...); +int32_t BShellEnvOutputString(BShellHandle handle, const char *string); +int32_t BShellEnvOutputPrompt(BShellHandle handle, const char *prompt); + +int32_t BShellCmdHelp(BShellHandle handle, int32_t argc, char *argv[]); +int32_t BShellEnvDirectExecute(BShellHandle handle, int argc, char *args[]); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/services/begetctl/shell/shell_bas.c b/services/begetctl/shell/shell_bas.c new file mode 100644 index 0000000000000000000000000000000000000000..9053f81a1e66559892d84c3f091247e40c88f26e --- /dev/null +++ b/services/begetctl/shell/shell_bas.c @@ -0,0 +1,757 @@ +/* + * 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 "shell_bas.h" +#include +#include + +#include "init_utils.h" +#include "shell_utils.h" + +char *BShellEnvErrString(BShellHandle handle, int32_t err) +{ + static BShellErrInfo shellErrString[] = { + {BSH_SHELL_INFO, "\r\n\r\n" + "+=========================================================+\r\n" + "| Parameter shell v"BSH_VERSION" |\r\n" + "+=========================================================+\r\n" + }, + {BSH_CMD_TOO_LONG, "\r\nWarnig: Command is too long\r\n"}, + {BSH_SHOW_CMD_LIST, "Command list:\r\n"}, + {BSH_CMD_NOT_EXIST, "Command not found\r\n"} + }; + for (size_t i = 0; i < sizeof(shellErrString) / sizeof(shellErrString[0]); i++) { + if ((int32_t)shellErrString[i].err == err) { + return shellErrString[i].desc; + } + } + BSH_CHECK(handle != NULL, return "System unknown err", "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + int len = sprintf_s(shell->data, sizeof(shell->data) - 1, "System unknown err 0x%08x", err); + if (len <= 0) { + BSH_LOGE("Write shell data size failed."); + } + return shell->data; +} + +static void BShellCmdOutputCmdHelp(BShellHandle handle, BShellCommand *cmd) +{ + BShellEnvOutputString(handle, " "); + int32_t spaceLength = BShellEnvOutputString(handle, cmd->help); + spaceLength = BSH_CMD_NAME_END - spaceLength; + spaceLength = (spaceLength > 0) ? spaceLength : 4; // 4 min + do { + BShellEnvOutputString(handle, " "); + } while (--spaceLength); + BShellEnvOutputString(handle, "--"); + BShellEnvOutputString(handle, cmd->desc); + BShellEnvOutputString(handle, "\r\n"); +} + +int32_t BShellCmdHelp(BShellHandle handle, int32_t argc, char *argv[]) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_SHOW_CMD_LIST)); + + int show = 0; + BShellCommand *cmd = shell->command; + while (cmd != NULL) { + if ((argc >= 1) && + (strncmp(argv[0], cmd->name, strlen(argv[0])) == 0) && + (strncmp(argv[0], "help", strlen(argv[0])) != 0)) { + BShellCmdOutputCmdHelp(handle, cmd); + show = 1; + } + cmd = cmd->next; + } + if (show) { + return 0; + } + cmd = shell->command; + while (cmd != NULL) { + BShellCmdOutputCmdHelp(handle, cmd); + cmd = cmd->next; + } + return 0; +} + +static int32_t BShellCmdExit(BShellHandle handle, int32_t argc, char *argv[]) +{ +#ifndef STARTUP_INIT_TEST + kill(getpid(), SIGINT); +#endif + return 0; +} + +int32_t BShellEnvOutput(BShellHandle handle, char *fmt, ...) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + va_list list; + va_start(list, fmt); + int len = vfprintf(stdout, fmt, list); + va_end(list); + (void)fflush(stdout); + return len; +} + +int32_t BShellEnvOutputString(BShellHandle handle, const char *string) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + printf("%s", string); + (void)fflush(stdout); + return strlen(string); +} + +int32_t BShellEnvOutputPrompt(BShellHandle handle, const char *prompt) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(prompt != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + if (shell->prompt != NULL) { + free(shell->prompt); + } + size_t promptLen = strlen(prompt); + if (promptLen > BSH_CMD_NAME_END) { + shell->prompt = strdup(prompt + promptLen - BSH_CMD_NAME_END); + if (shell->prompt != NULL) { + shell->prompt[0] = '.'; + shell->prompt[1] = '.'; + shell->prompt[2] = '.'; // 2 index + } + } else { + shell->prompt = strdup(prompt); + BSH_CHECK(shell->prompt != NULL, return BSH_INVALID_PARAM, "strdup prompt failed."); + } + return 0; +} + +void BShellEnvOutputByte(BShellHandle handle, char data) +{ + BSH_CHECK(handle != NULL, return, "Invalid shell env"); + printf("%c", data); + (void)fflush(stdout); +} + +void BShellEnvOutputResult(BShellHandle handle, int32_t result) +{ + if (result == 0) { + return; + } + printf("result: 0x%08x\r\n", result); + (void)fflush(stdout); +} + +static void BShellEnvOutputParam(BShellHandle handle, char *var) +{ + BShellEnvOutput(handle, (var[0] == '$') ? var + 1 : var); + BShellEnvOutputString(handle, " = "); + BShellEnvOutputString(handle, BShellEnvGetStringParam(handle, var)); +} + +void BShellEnvBackspace(BShellHandle handle, uint32_t length) +{ + for (uint32_t i = 0; i < length; i++) { + BShellEnvOutputString(handle, "\b \b"); + } +} + +static void BShellEnvParseParam(BShellEnv *shell) +{ + uint8_t quotes = 0; + uint8_t record = 1; + shell->argc = 0; + for (uint16_t i = 0; i < shell->length; i++) { + char data = *(shell->buffer + i); + if ((quotes != 0 || (data != ' ' && data != '\t' && data != ',')) && data != 0) { + if (data == '\"') { + quotes = quotes ? 0 : 1; + } + if (record == 1) { + BSH_CHECK(shell->argc < BSH_PARAMETER_MAX_NUMBER, return, "argc out of range"); + shell->args[shell->argc++] = shell->buffer + i; + record = 0; + } + if (*(shell->buffer + i) == '\\' && *(shell->buffer + i + 1) != 0) { + i++; + } + } else { + *(shell->buffer + i) = 0; + record = 1; + } + } +} + +static int32_t BShellEnvExcuteCmd(BShellEnv *shell, BShellCommand *cmd) +{ + return cmd->executer((BShellHandle)shell, shell->argc - cmd->argStart, &shell->args[cmd->argStart]); +} + +static int32_t BShellEnvHandleEnter(BShellHandle handle, uint8_t data) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + if (shell->length == 0) { + BShellEnvOutputString(shell, "\n"); + BShellEnvOutputString(handle, shell->prompt); + return 0; + } + + *(shell->buffer + shell->length++) = 0; + BShellEnvParseParam(shell); + shell->length = 0; + shell->cursor = 0; + if (shell->argc == 0) { + BShellEnvOutputString(shell, shell->prompt); + return 0; + } + + BShellEnvOutputString(shell, "\n"); + if (strcmp((const char *)shell->args[0], "help") == 0) { + BShellCmdHelp(handle, shell->argc, shell->args); + BShellEnvOutputString(shell, shell->prompt); + return 0; + } + if (shell->args[0][0] == '$') { + BShellEnvOutputParam(shell, shell->args[0]); + BShellEnvOutputString(shell, shell->prompt); + return 0; + } + + BShellCommand *cmd = BShellEnvGetCmd(handle, (uint32_t)shell->argc, shell->args); + if (cmd != NULL) { + int32_t ret = BShellEnvExcuteCmd(shell, cmd); + BShellEnvOutputResult(shell, ret); + } else { + BShellEnvOutputString(shell, BShellEnvErrString(handle, BSH_CMD_NOT_EXIST)); + } + BShellEnvOutputString(shell, shell->prompt); + return 0; +} + +static int32_t BShellEnvHandleBackspace(BShellHandle handle, uint8_t code) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + if (shell->length == 0) { + return 0; + } + if (shell->cursor == shell->length) { + shell->length--; + shell->cursor--; + shell->buffer[shell->length] = 0; + BShellEnvBackspace(handle, 1); + } else if (shell->cursor > 0) { + for (short i = 0; i < shell->length - shell->cursor; i++) { + shell->buffer[shell->cursor + i - 1] = shell->buffer[shell->cursor + i]; + } + shell->length--; + shell->cursor--; + shell->buffer[shell->length] = 0; + BShellEnvOutputByte(shell, '\b'); + for (short i = shell->cursor; i < shell->length; i++) { + BShellEnvOutputByte(shell, shell->buffer[i]); + } + BShellEnvOutputByte(shell, ' '); + for (short i = shell->length - shell->cursor + 1; i > 0; i--) { + BShellEnvOutputByte(shell, '\b'); + } + } + return 0; +} + +static int32_t BShellEnvHandleTab(BShellHandle handle, uint8_t code) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + return 0; +} + +static void BShellEnvHandleNormal(BShellHandle handle, uint8_t data) +{ + BSH_CHECK(handle != NULL, return, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + if (data == 0) { + return; + } + if (shell->length < BSH_COMMAND_MAX_LENGTH - 1) { + if (shell->length == shell->cursor) { + shell->buffer[shell->length++] = data; + shell->cursor++; + BShellEnvOutputByte(shell, data); + } else { + for (uint16_t i = shell->length - shell->cursor; i > 0; i--) { + shell->buffer[shell->cursor + i] = shell->buffer[shell->cursor + i - 1]; + } + shell->buffer[shell->cursor++] = data; + shell->buffer[++shell->length] = 0; + for (uint16_t i = shell->cursor - 1; i < shell->length; i++) { + BShellEnvOutputByte(shell, shell->buffer[i]); + } + for (uint16_t i = shell->length - shell->cursor; i > 0; i--) { + BShellEnvOutputByte(shell, '\b'); + } + } + } else { + BShellEnvOutputString(shell, BShellEnvErrString(handle, BSH_CMD_TOO_LONG)); + BShellEnvOutputString(shell, shell->prompt); + + shell->cursor = shell->length; + } +} + +static int32_t BShellEnvHandleCtrC(BShellHandle handle, uint8_t code) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_LOGV("BShellEnvHandleCtrC %d", getpid()); +#ifndef STARTUP_INIT_TEST + kill(getpid(), SIGKILL); +#endif + return 0; +} + +static int32_t BShellEnvHandleEsc(BShellHandle handle, uint8_t code) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + shell->shellState = BSH_ANSI_ESC; + return 0; +} + +BShellKey *BShellEnvGetDefaultKey(uint8_t code) +{ + static BShellKey defaultKeys[] = { + {BSH_KEY_LF, BShellEnvHandleEnter, NULL}, + {BSH_KEY_CR, BShellEnvHandleEnter, NULL}, + {BSH_KEY_TAB, BShellEnvHandleTab, NULL}, + {BSH_KEY_BACKSPACE, BShellEnvHandleBackspace, NULL}, + {BSH_KEY_DELETE, BShellEnvHandleBackspace, NULL}, + {BSH_KEY_CTRLC, BShellEnvHandleCtrC, NULL}, + {BSH_KEY_ESC, BShellEnvHandleEsc, NULL}, + }; + for (size_t i = 0; i < sizeof(defaultKeys) / sizeof(defaultKeys[0]); i++) { + if (defaultKeys[i].keyCode == code) { + return &defaultKeys[i]; + } + } + return NULL; +} + +SHELLSTATIC void BShellEnvProcessInput(BShellHandle handle, char data) +{ + BSH_CHECK(handle != NULL, return, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + if (shell->shellState == BSH_IN_NORMAL) { + BShellKey *key = BShellEnvGetKey(handle, data); + if (key != NULL) { + key->keyHandle(shell, (uint8_t)data); + return; + } + key = BShellEnvGetDefaultKey(data); + if (key != NULL) { + key->keyHandle(shell, (uint8_t)data); + return; + } + BShellEnvHandleNormal(shell, data); + } else if (shell->shellState == BSH_ANSI_CSI) { + switch (data) { + case 0x41: // up + break; + case 0x42: // down + break; + case 0x43: // -> + if (shell->cursor < shell->length) { + BShellEnvOutputByte(handle, shell->buffer[shell->cursor]); + shell->cursor++; + } + break; + case 0x44: // <- + if (shell->cursor > 0) { + BShellEnvOutputByte(shell, '\b'); + shell->cursor--; + } + break; + default: + break; + } + shell->shellState = BSH_IN_NORMAL; + } else if (shell->shellState == BSH_ANSI_ESC) { + if (data == 0x5B) { // input up/down + shell->shellState = BSH_ANSI_CSI; + } else { + shell->shellState = BSH_IN_NORMAL; + } + } +} + +void BShellEnvLoop(BShellHandle handle) +{ + BSH_CHECK(handle != NULL, return, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + BSH_CHECK(shell->input != NULL, return, "Invalid shell input"); + while (1) { + char data = 0; + if (shell->input(&data, 1) == 1) { + BShellEnvProcessInput(shell, data); + } + } +} + +int32_t BShellEnvInit(BShellHandle *handle, const BShellInfo *info) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(info != NULL && info->prompt != NULL, return BSH_INVALID_PARAM, "Invalid cmd name"); + + BShellEnv *shell = (BShellEnv *)calloc(1, sizeof(BShellEnv)); + BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Failed to create shell env"); + shell->length = 0; + shell->cursor = 0; + shell->shellState = BSH_IN_NORMAL; + shell->input = info->input; + shell->prompt = strdup(info->prompt); + BSH_CHECK(shell->prompt != NULL, free(shell); return BSH_INVALID_PARAM, "Failed to strdup prompt"); + shell->command = NULL; + shell->param = NULL; + shell->keyHandle = NULL; + shell->execMode = BSH_EXEC_INDEPENDENT; + *handle = (BShellHandle)shell; + return 0; +} + +int BShellEnvStart(BShellHandle handle) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + shell->execMode = BSH_EXEC_TASK; + BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_SHELL_INFO)); + BShellEnvOutputString(handle, shell->prompt); + + const CmdInfo infos[] = { + {"exit", BShellCmdExit, "exit parameter shell", "exit"}, + {"help", BShellCmdHelp, "help command", "help"} + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(handle, &infos[i]); + } + return 0; +} + +static void BShellParamFree(BShellParam *param) +{ + if (param->desc != NULL) { + free(param->desc); + } + if (param->type == PARAM_STRING && param->value.string != NULL) { + free(param->value.string); + } + free(param); +} + +static void BShellCmdFree(BShellCommand *cmd) +{ + if (cmd->desc != NULL) { + free(cmd->desc); + cmd->desc = NULL; + } + if (cmd->help != NULL) { + free(cmd->help); + cmd->help = NULL; + } + if (cmd->multikey != NULL) { + free(cmd->multikey); + cmd->multikey = NULL; + } + free(cmd); +} + +void BShellEnvDestory(BShellHandle handle) +{ + BSH_CHECK(handle != NULL, return, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + + BShellCommand *cmd = shell->command; + while (cmd != NULL) { + shell->command = cmd->next; + BShellCmdFree(cmd); + cmd = shell->command; + } + + BShellParam *param = shell->param; + while (param != NULL) { + shell->param = param->next; + BShellParamFree(param); + param = shell->param; + } + + BShellKey *key = shell->keyHandle; + while (key != NULL) { + shell->keyHandle = key->next; + free(key); + key = shell->keyHandle; + } + if (shell->prompt != NULL) { + free(shell->prompt); + } + free(shell); +} + +int32_t BShellEnvRegisterCmd(BShellHandle handle, const CmdInfo *cmdInfo) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(cmdInfo != NULL && cmdInfo->name != NULL, return BSH_INVALID_PARAM, "Invalid cmd name"); + BSH_CHECK(cmdInfo->executer != NULL, return BSH_INVALID_PARAM, "Invalid cmd executer"); + BShellEnv *shell = (BShellEnv *)handle; + size_t nameLen = strlen(cmdInfo->name) + 1; + BShellCommand *cmd = (BShellCommand *)calloc(1, sizeof(BShellCommand) + nameLen); + BSH_CHECK(cmd != NULL, return BSH_INVALID_PARAM, "Failed to alloc cmd name %s", cmdInfo->name); + cmd->executer = cmdInfo->executer; + cmd->argStart = 0; + int32_t ret = 0; + do { + ret = strcpy_s(cmd->name, nameLen, cmdInfo->name); + BSH_CHECK(ret == 0, break, "Failed to copy name %s", cmdInfo->name); + + ret = BSH_SYSTEM_ERR; + if (cmdInfo->desc != NULL) { + cmd->desc = strdup(cmdInfo->desc); + BSH_CHECK(cmd->desc != NULL, break, "Failed to copy desc %s", cmdInfo->name); + } + if (cmdInfo->help != NULL) { + cmd->help = strdup(cmdInfo->help); + BSH_CHECK(cmd->help != NULL, break, "Failed to copy help %s", cmdInfo->name); + } + cmd->multikey = NULL; + if (cmdInfo->multikey != NULL && strlen(cmdInfo->multikey) > nameLen) { + cmd->multikey = strdup(cmdInfo->multikey); + BSH_CHECK(cmd->multikey != NULL, break, "Failed to copy multikey %s", cmdInfo->name); + int argc = SplitString(cmd->multikey, " ", cmd->multikeys, (int)ARRAY_LENGTH(cmd->multikeys)); + BSH_CHECK(argc <= (int)ARRAY_LENGTH(cmd->multikeys) && argc > 0, break, "Invalid multikey"); + cmd->argStart = argc - 1; + if (argc == 1) { + free(cmd->multikey); + cmd->multikey = NULL; + } + } + ret = 0; + } while (0); + if (ret != 0) { + BShellCmdFree(cmd); + return ret; + } + cmd->next = shell->command; + shell->command = cmd; + return 0; +} + +static const char *GetRealCmdName(const char *name) +{ + int i = 0; + int last = 0; + while (*(name + i) != '\0') { + if (*(name + i) == '/') { + last = i; + } + i++; + } + if (last != 0) { + return name + last + 1; + } else { + return name; + } +} + +BShellCommand *BShellEnvGetCmd(BShellHandle handle, int32_t argc, char *argv[]) +{ + BSH_CHECK(handle != NULL, return NULL, "Invalid shell env"); + BSH_CHECK(argc >= 1, return NULL, "Invalid argc"); + const char *cmdName = GetRealCmdName(argv[0]); + BSH_LOGV("BShellEnvGetCmd %s cmd %s", argv[0], cmdName); + BShellEnv *shell = (BShellEnv *)handle; + BShellCommand *cmd = shell->command; + while (cmd != NULL) { + if (strcmp(cmd->name, cmdName) != 0) { + cmd = cmd->next; + continue; + } + if (cmd->multikey == NULL) { + return cmd; + } + int32_t i = 0; + for (i = 0; i < (int32_t)ARRAY_LENGTH(cmd->multikeys) && i < argc; i++) { + if (cmd->multikeys[i] == NULL) { + return cmd; + } + char *tmp = argv[i]; + if (i == 0) { + tmp = (char *)cmdName; + } + if (strcmp(cmd->multikeys[i], tmp) != 0) { + break; + } + } + if (i >= (int32_t)ARRAY_LENGTH(cmd->multikeys)) { + return cmd; + } + if (i >= argc) { + if (cmd->multikeys[i] == NULL) { + return cmd; + } + } + cmd = cmd->next; + } + return NULL; +} + +int32_t BShellEnvRegisterKeyHandle(BShellHandle handle, uint8_t code, BShellkeyHandle keyHandle) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(keyHandle != NULL, return BSH_INVALID_PARAM, "Invalid cmd name"); + BShellEnv *shell = (BShellEnv *)handle; + + BShellKey *key = (BShellKey *)calloc(1, sizeof(BShellKey)); + BSH_CHECK(key != NULL, return BSH_INVALID_PARAM, "Failed to alloc key code %d", code); + key->keyCode = code; + key->keyHandle = keyHandle; + key->next = shell->keyHandle; + shell->keyHandle = key; + return 0; +} + +BShellKey *BShellEnvGetKey(BShellHandle handle, uint8_t code) +{ + BSH_CHECK(handle != NULL, return NULL, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + BShellKey *key = shell->keyHandle; + while (key != NULL) { + if (key->keyCode == code) { + return key; + } + key = key->next; + } + return NULL; +} + +static int32_t BShellParamSetValue(BShellParam *param, void *value) +{ + static uint32_t paramValueLens[] = { + sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t), sizeof(char *) + }; + if (param->type == PARAM_STRING) { + if (param->value.string != NULL) { + free(param->value.string); + } + param->value.string = strdup((char *)value); + BSH_CHECK(param->value.string != NULL, return BSH_SYSTEM_ERR, "Failed to copy value for %s", param->name); + } else if (param->type < PARAM_STRING) { + int ret = memcpy_s(¶m->value, sizeof(param->value), value, paramValueLens[param->type]); + BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to copy value for %s", param->name); + } + return 0; +} + +int32_t BShellEnvSetParam(BShellHandle handle, const char *name, const char *desc, BShellParamType type, void *value) +{ + BSH_CHECK(handle != NULL, return BSH_INVALID_PARAM, "Invalid shell env"); + BSH_CHECK(name != NULL, return BSH_INVALID_PARAM, "Invalid param name"); + BSH_CHECK(value != NULL, return BSH_INVALID_PARAM, "Invalid cmd value"); + BSH_CHECK(type <= PARAM_STRING, return BSH_INVALID_PARAM, "Invalid param type"); + BShellEnv *shell = (BShellEnv *)handle; + const BShellParam *tmp = BShellEnvGetParam(handle, name); + if (tmp != NULL) { + BSH_CHECK(tmp->type <= type, return BSH_INVALID_PARAM, "Invalid param type %d", tmp->type); + return BShellParamSetValue((BShellParam *)tmp, value); + } + int32_t ret = 0; + BShellParam *param = NULL; + do { + size_t nameLen = strlen(name) + 1; + param = (BShellParam *)calloc(1, sizeof(BShellParam) + nameLen); + BSH_CHECK(param != NULL, return BSH_SYSTEM_ERR, "Failed to alloc cmd name %s", name); + param->type = type; + ret = strcpy_s(param->name, nameLen, name); + BSH_CHECK(ret == 0, break, "Failed to copy name %s", name); + if (desc != NULL) { + param->desc = strdup(desc); + BSH_CHECK(param->desc != NULL, free(param); return BSH_SYSTEM_ERR, "Failed to set desc"); + } + ret = BShellParamSetValue(param, value); + BSH_CHECK(ret == 0, break, "Failed set value for %s", name); + + param->next = shell->param; + shell->param = param; + } while (0); + if (ret != 0) { + BShellParamFree(param); + } + return ret; +} + +const BShellParam *BShellEnvGetParam(BShellHandle handle, const char *name) +{ + BSH_CHECK(handle != NULL, return NULL, "Invalid shell env"); + BShellEnv *shell = (BShellEnv *)handle; + BShellParam *param = shell->param; + while (param != NULL) { + if (strcmp(name, param->name) == 0) { + return param; + } + param = param->next; + } + return NULL; +} + +const char *BShellEnvGetStringParam(BShellHandle handle, const char *name) +{ + BSH_CHECK(handle != NULL, return "", "Invalid shell env"); + const BShellParam *param = BShellEnvGetParam(handle, name); + if (param == NULL) { + return ""; + } + switch (param->type) { + case PARAM_STRING: + return param->value.string; + default: + break; + } + return ""; +} + +const ParamInfo *BShellEnvGetReservedParam(BShellHandle handle, const char *name) +{ + BSH_CHECK(handle != NULL, return NULL, "Invalid shell env"); + static ParamInfo reservedParams[] = { + {PARAM_REVERESD_NAME_CURR_PARAMETER, "current parameter", PARAM_STRING} + }; + for (size_t i = 0; i < sizeof(reservedParams) / sizeof(reservedParams[0]); i++) { + if (strcmp(name, reservedParams[i].name) == 0) { + return &reservedParams[i]; + } + } + return NULL; +} + +int32_t BShellEnvDirectExecute(BShellHandle handle, int argc, char *args[]) +{ + BSH_CHECK(handle != NULL, return -1, "Invalid shell env"); + BShellCommand *cmd = BShellEnvGetCmd(handle, argc, args); + if (cmd != NULL) { + int32_t ret = cmd->executer(handle, argc - cmd->argStart, &args[cmd->argStart]); + BShellEnvOutputResult(handle, ret); + } else { + if (argc > 1) { + BShellEnvOutputString(handle, BShellEnvErrString(handle, BSH_CMD_NOT_EXIST)); + } + BShellCmdHelp(handle, argc, args); + } + return 0; +} diff --git a/services/begetctl/shell/shell_bas.h b/services/begetctl/shell/shell_bas.h new file mode 100644 index 0000000000000000000000000000000000000000..b53aac993791080edc73a30e8093cdb8cf63d233 --- /dev/null +++ b/services/begetctl/shell/shell_bas.h @@ -0,0 +1,115 @@ +/* + * 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 BSHELL_BAS_H +#define BSHELL_BAS_H +#include +#include +#include "shell.h" + +#define BSH_VERSION "0.0.1" +#define BSH_KEY_LF 0x0A +#define BSH_KEY_CR 0x0D +#define BSH_KEY_TAB 0x09 +#define BSH_KEY_BACKSPACE 0x08 +#define BSH_KEY_DELETE 0x7F +#define BSH_KEY_CTRLC 0x03 // ctr + c +#define BSH_KEY_ESC 0x1B // ecs + +#define BSH_COMMAND_MAX_LENGTH (5 * 1024) +#define BSH_PARAMETER_MAX_NUMBER 10 +#define BSH_CMD_NAME_END 48 +#define BSH_CMD_MAX_KEY 5 + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef STARTUP_INIT_TEST +#define SHELLSTATIC +#else +#define SHELLSTATIC static +#endif + +typedef enum { + BSH_IN_NORMAL = 0, + BSH_ANSI_ESC, + BSH_ANSI_CSI, +} BShellState; + +typedef enum { + BSH_EXEC_TASK = 0, + BSH_EXEC_INDEPENDENT, +} BShellExecMode; + +typedef struct BShellCommand_ { + char *desc; + char *help; + BShellCmdExecuter_ executer; + struct BShellCommand_ *next; + char *multikey; + char *multikeys[BSH_CMD_MAX_KEY]; + uint8_t argStart; + char name[0]; +} BShellCommand; + +typedef struct { + uint8_t shellState : 2; + uint8_t tabFlag : 1; +} BShellStatus; + +typedef struct BShellKey_ { + uint8_t keyCode; + BShellkeyHandle keyHandle; + struct BShellKey_ *next; +} BShellKey; + +typedef struct BShellEnv_ { + char *prompt; + char buffer[BSH_COMMAND_MAX_LENGTH]; + uint16_t length; + uint16_t cursor; + char *args[BSH_PARAMETER_MAX_NUMBER]; + uint8_t argc; + uint8_t shellState : 3; + uint8_t execMode : 2; + BShellCommand *command; + BShellParam *param; + BShellKey *keyHandle; + BShellStatus status; + BShellInput_ input; + char data[BSH_COMMAND_MAX_LENGTH]; +} BShellEnv; + +BShellKey *BShellEnvGetKey(BShellHandle handle, uint8_t code); +BShellCommand *BShellEnvGetCmd(BShellHandle handle, int32_t argc, char *argv[]); +int32_t BShellEnvOutputString(BShellHandle handle, const char *string); +void BShellEnvOutputByte(BShellHandle handle, char data); +void BShellEnvOutputResult(BShellHandle handle, int32_t result); +char *BShellEnvErrString(BShellHandle handle, int32_t err); +const char *BShellEnvGetStringParam(BShellHandle handle, const char *name); + +#ifdef STARTUP_INIT_TEST +void BShellEnvProcessInput(BShellHandle handle, char data); +BShellKey *BShellEnvGetDefaultKey(uint8_t code); +#endif + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/services/begetctl/shell/shell_main.c b/services/begetctl/shell/shell_main.c new file mode 100644 index 0000000000000000000000000000000000000000..041e60ce0e79fb976d9dd74a7e2de4a06dd201ed --- /dev/null +++ b/services/begetctl/shell/shell_main.c @@ -0,0 +1,93 @@ +/* + * 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 "begetctl.h" +#include "shell.h" +#include "shell_utils.h" + +static BShellHandle g_handle = NULL; +struct termios terminalState; +static void signalHandler(int signal) +{ + demoExit(); + exit(0); +} + +static int32_t ShellInput(char *data, int32_t len) +{ + for (int32_t i = 0; i < len; i++) { + data[i] = getchar(); + } + return len; +} + +BShellHandle GetShellHandle(void) +{ + if (g_handle == NULL) { + BShellInfo info = {PARAM_SHELL_DEFAULT_PROMPT, ShellInput}; + BShellEnvInit(&g_handle, &info); + } + return g_handle; +} + +#ifndef STARTUP_INIT_TEST +int main(int argc, char *args[]) +{ + (void)signal(SIGINT, signalHandler); + (void)signal(SIGKILL, signalHandler); + if (tcgetattr(0, &terminalState)) { + return -1; + } + struct termios tio; + if (tcgetattr(0, &tio)) { + return -1; + } + tio.c_lflag &= ~(ECHO | ICANON | ISIG); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + tcsetattr(0, TCSAFLUSH, &tio); + + BSH_LOGV("BShellEnvStart %d", argc); + do { + BShellHandle handle = GetShellHandle(); + if (handle == NULL) { + printf("Failed to get shell handle \n"); + return 0; + } + const ParamInfo *param = BShellEnvGetReservedParam(handle, PARAM_REVERESD_NAME_CURR_PARAMETER); + BSH_CHECK(param != NULL && param->type == PARAM_STRING, break, "Failed to get reversed param"); + BShellEnvSetParam(handle, param->name, param->desc, param->type, (void *)""); + if (argc > 1) { + int ret = SetParamShellPrompt(handle, args[1]); + if (ret != 0) { + break; + } + } + BShellParamCmdRegister(handle, 1); +#ifdef INIT_TEST + BShellCmdRegister(handle, 1); +#endif + BShellEnvStart(handle); + BShellEnvLoop(handle); + } while (0); + demoExit(); + tcsetattr(0, TCSAFLUSH, &terminalState); + return 0; +} +#endif diff --git a/services/begetctl/shell/shell_utils.h b/services/begetctl/shell/shell_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..9f4ff7a5868fa6b6c6a4c5a4fc1ca37ff2e0c649 --- /dev/null +++ b/services/begetctl/shell/shell_utils.h @@ -0,0 +1,43 @@ +/* + * 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 BSHELL_UTILS_ +#define BSHELL_UTILS_ +#include +#include +#include + +#include "init_log.h" +#include "securec.h" + +#define BSH_LABEL "SHELL" +#ifndef BSH_DOMAIN +#define BSH_DOMAIN (BASE_DOMAIN + 5) +#endif + +#define BSH_LOGI(fmt, ...) STARTUP_LOGI(BSH_DOMAIN, BSH_LABEL, fmt, ##__VA_ARGS__) +#define BSH_LOGE(fmt, ...) STARTUP_LOGE(BSH_DOMAIN, BSH_LABEL, fmt, ##__VA_ARGS__) +#define BSH_LOGV(fmt, ...) STARTUP_LOGV(BSH_DOMAIN, BSH_LABEL, fmt, ##__VA_ARGS__) + +#define BSH_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + BSH_LOGE(__VA_ARGS__); \ + exper; \ + } +#define BSH_ONLY_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + exper; \ + } +#endif \ No newline at end of file diff --git a/services/etc/BUILD.gn b/services/etc/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..897ab81dbcae414b63e9694739ece571c3b0806e --- /dev/null +++ b/services/etc/BUILD.gn @@ -0,0 +1,261 @@ +# Copyright (c) 2020-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/begetd.gni") +import("//base/startup/init/services/etc/passwd_appender/passwd_appender.gni") + +if (defined(ohos_lite)) { + copy("ohos.para") { + sources = [ "//base/startup/init/services/etc/param/ohos.para" ] + outputs = [ "$root_out_dir/system/etc/param/ohos.para" ] + } + + copy("ohos.para.dac") { + sources = [ "//base/startup/init/services/etc/param/ohos.para.dac" ] + outputs = [ "$root_out_dir/system/etc/param/ohos.para.dac" ] + } + copy("ohos.const") { + sources = + [ "//base/startup/init/services/etc_lite/param/ohos_const/ohos.para" ] + outputs = [ "$root_out_dir/system/etc/param/ohos_const/ohos.para" ] + } + + copy("ohos.passwd") { + sources = [ "//base/startup/init/services/etc_lite/passwd" ] + outputs = [ "$root_out_dir/etc/passwd" ] + } + copy("ohos.group") { + sources = [ "//base/startup/init/services/etc_lite/group" ] + outputs = [ "$root_out_dir/etc/group" ] + } + + group("etc_files") { + deps = [ + ":ohos.const", + ":ohos.para", + ":ohos.para.dac", + ] + if (ohos_kernel_type == "linux") { + deps += [ + ":ohos.group", + ":ohos.passwd", + ] + } + } +} else { + import("//build/config/components/init/param/param_fixer.gni") + import("//build/ohos.gni") + + # init etc files group + ohos_prebuilt_etc("init.cfg") { + if (!enable_ramdisk) { + source = "//base/startup/init/services/etc/init.without_two_stages.cfg" + } else { + source = "//base/startup/init/services/etc/init.cfg" + } + output = "init.cfg" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("watchdog.cfg") { + source = "//base/startup/init/services/etc/watchdog.cfg" + relative_install_dir = "init" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("console.cfg") { + source = "//base/startup/init/services/etc/console.cfg" + relative_install_dir = "init" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("ueventd.cfg") { + source = "//base/startup/init/services/etc/ueventd.cfg" + relative_install_dir = "init" + part_name = "init" + subsystem_name = "startup" + } + + ohos_passwd_appender("passwd") { + sources = [ "//base/startup/init/services/etc/passwd" ] + ranges = [ "0-6999" ] + output = "//base/startup/init/services/etc/passwd" + install_images = [ + "system", + "updater", + ] + if (init_extra_static_modules != "") { + install_enable = false + } + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("group") { + source = "//base/startup/init/services/etc/group" + install_images = [ + "system", + "updater", + ] + if (init_extra_static_modules != "") { + install_enable = false + } + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("init.usb.cfg") { + source = "//base/startup/init/services/etc/init.usb.cfg" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_para("ohos.para") { + source = "//base/startup/init/services/etc/param/ohos.para" + install_images = [ + "system", + "updater", + ] + part_name = "init" + subsystem_name = "startup" + extra_paras = [] + if (target_cpu == "arm64") { + extra_paras += [ "const.product.cpu.abilist=arm64-v8a" ] + } + if (target_cpu == "x86_64") { + extra_paras += [ "const.product.cpu.abilist=x86_64" ] + } + if (target_cpu == "riscv64") { + extra_paras += [ "const.product.cpu.abilist=riscv64" ] + } + if (build_variant == "user") { + extra_paras += [ + "const.secure=1", + "const.debuggable=0", + ] + } else if (build_variant == "root") { + extra_paras += [ + "const.secure=0", + "const.debuggable=1", + ] + } + if (device_type != "default") { + extra_paras += [ + "const.product.devicetype=${device_type}", + "const.build.characteristics=${device_type}", + ] + } + module_install_dir = "etc/param" + } + + ohos_prebuilt_para("ohos.startup.para") { + source = "//base/startup/init/services/etc/param/ohos.startup.para" + install_images = [ + "system", + "updater", + ] + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/param" + } + + ohos_prebuilt_para("ohos.para.dac") { + source = "//base/startup/init/services/etc/param/ohos.para.dac" + install_images = [ + "system", + "updater", + ] + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/param" + } + + ohos_prebuilt_para("ohos_const.para") { + source = "//base/startup/init/services/etc/param/ohos_const/ohos.para" + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/param/ohos_const" + } + + ohos_prebuilt_para("ohos.para.size") { + source = "//base/startup/init/services/etc/param/ohos.para.size" + install_images = [ + "system", + "updater", + ] + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/param" + } + + ohos_prebuilt_etc("boot.group") { + source = "//base/startup/init/services/etc/device.boot.group.cfg" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("syscap.para") { + source = "${preloader_output_dir}/system/etc/param/syscap.para" + module_install_dir = "etc/param/" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("syscap.json") { + source = "${preloader_output_dir}/system/etc/syscap.json" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("systemcapability.json") { + source = "${preloader_output_dir}/system/etc/SystemCapability.json" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("features.json") { + source = "${preloader_output_dir}/features.json" + part_name = "init" + subsystem_name = "startup" + } + + ohos_prebuilt_etc("init.reboot") { + source = "//base/startup/init/services/etc/init.reboot.cfg" + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/init" + } + + group("etc_files") { + deps = [ + ":boot.group", + ":console.cfg", + ":features.json", + ":group", + ":init.cfg", + ":init.reboot", + ":init.usb.cfg", + ":ohos.para", + ":ohos.para.dac", + ":ohos.para.size", + ":ohos.startup.para", + ":ohos_const.para", + ":passwd", + ":syscap.json", + ":syscap.para", + ":systemcapability.json", + ] + } +} diff --git a/services/etc/appender/file_appender.gni b/services/etc/appender/file_appender.gni new file mode 100755 index 0000000000000000000000000000000000000000..dfed821f0179b7be14257b23d02419cca286d7d3 --- /dev/null +++ b/services/etc/appender/file_appender.gni @@ -0,0 +1,124 @@ +# Copyright (c) 2021 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("//build/config/python.gni") +import("//build/templates/common/copy.gni") + +# Append something (files or lines) to a file and install it. +# +# Variables: +# source: file to be appended (Required) +# deps: some targets deps on (Optional) +# output: the final install file name (Optional); +# If not set, it will install with the source file name +# files: files to be appended to the end of source file (Optional) +# lines: lines of strings to be appended to the end of souce file (Optional) +# +# Example: +# ohos_file_appender("cust_passwd") { +# source = "//base/startup/init/services/etc/passwd" +# deps = [ "//base/startup/init/services/etc:passwd" ] +# files = [ "cust_passwd", "passwd2" ] +# lines = [ "tses::1222:1222:/bin/false", "tses2::1223:1223:/bin/false" ] +# output = "passwd" +# } +# It will append files and lines to source passwd file after deps targets +# +template("ohos_file_appender") { + assert(defined(invoker.source), "source full target name must be defined.") + + _file_appender_target = "${target_name}_appended" + + if (defined(invoker.output)) { + _final_install_name = get_path_info(invoker.output, "file") + } else { + _final_install_name = get_path_info(invoker.source, "file") + } + + _appended_file = + target_gen_dir + "/${target_name}.appended/" + _final_install_name + + action_with_pydeps(_file_appender_target) { + script = "//base/startup/init/services/etc/appender/file_appender.py" + depfile = "${target_gen_dir}/${target_name}.d" + if (defined(invoker.deps)) { + deps = invoker.deps + } else { + deps = [] + } + args = [ + "--output", + rebase_path(_appended_file, root_build_dir), + "--source-file", + rebase_path(invoker.source, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + if (defined(invoker.files)) { + foreach(file, invoker.files) { + args += [ + "--append-file", + rebase_path(file, root_build_dir), + ] + } + } + if (defined(invoker.lines)) { + foreach(line, invoker.lines) { + args += [ + "--append-line", + line, + ] + } + } + inputs = [ invoker.source ] + outputs = [ _appended_file ] + } + + ohos_copy(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + + "deps", + "public_configs", + "subsystem_name", + "part_name", + + # For generate_module_info + "install_images", + "module_install_dir", + "relative_install_dir", + "symlink_target_name", + + # Open source license related + "license_file", + "license_as_sources", + ]) + if (defined(deps)) { + deps += [ ":$_file_appender_target" ] + } else { + deps = [ ":$_file_appender_target" ] + } + set_sources_assignment_filter([]) + sources = [ _appended_file ] + outputs = [ "${target_out_dir}/${target_name}/${_final_install_name}" ] + module_type = "etc" + install_enable = true + module_source_dir = "${target_out_dir}/${target_name}" + module_install_name = _final_install_name + if (defined(invoker.install_enable)) { + install_enable = invoker.install_enable + } + } +} diff --git a/services/etc/appender/file_appender.py b/services/etc/appender/file_appender.py new file mode 100755 index 0000000000000000000000000000000000000000..09c4a91bba61e545ffb7bb294aed0e7a6fcd1da0 --- /dev/null +++ b/services/etc/appender/file_appender.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2021 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 optparse +import os +import sys +import stat +import json +import operator + + +def parse_args(args): + from scripts.util import build_utils # noqa: E402 + + args = build_utils.expand_file_args(args) + + parser = optparse.OptionParser() + build_utils.add_depfile_option(parser) + parser.add_option('--output', help='fixed para file') + parser.add_option('--source-file', help='source para file') + parser.add_option('--append-file', action="append", type="string", dest="files", help='appended files') + parser.add_option('--append-line', action="append", type="string", dest="lines", help='appended lines') + + options, _ = parser.parse_args(args) + return options + + +def load_group_file_as_dict(source_f): + source_dict = {} + for line in source_f: + arr = line.strip().split(":") + if arr: + key = arr[0] + passwd_gid_value = [arr[1], arr[2]] + value = [':'.join(passwd_gid_value), arr[3]] + source_dict[key] = value + return source_dict + + +def insert_append_user_value(key, arr, source_dict): + if source_dict[key][1] and arr[3]: + if arr[3] not in source_dict[key][1]: + user_value = [source_dict[key][1], arr[3]] + source_dict[key][1] = ','.join(user_value) + elif source_dict[key][1] == " " and arr[3]: + source_dict[key][1] = arr[3] + + +def get_append_value(src, source_dict): + for line in src: + if line != "\n": + arr = line.strip().split(":") + key = arr[0] + passwd_gid_value = [arr[1], arr[2]] + if len(arr) > 3: + value = [':'.join(passwd_gid_value), arr[3]] + else: + value = [':'.join(passwd_gid_value), " "] + if key in source_dict.keys(): + insert_append_user_value(key, arr, source_dict) + else: + source_dict[key] = value + + +def append_group_by_lines(options, source_dict): + for line in options.lines: + arr = line.strip().split(":") + key = arr[0] + passwd_gid_value = [arr[1], arr[2]] + if len(arr) > 3: + value = [':'.join(passwd_gid_value), arr[3]] + else: + value = [':'.join(passwd_gid_value), " "] + if key in source_dict.keys(): + insert_append_user_value(key, arr, source_dict) + else: + source_dict[key] = value + + +def append_group_by_files(options, source_dict): + for append_f in options.files: + with open(append_f, 'r') as src: + get_append_value(src, source_dict) + + +def append_group_files(target_f, options): + with open(options.source_file, 'r') as source_f: + source_dict = load_group_file_as_dict(source_f) + if options.files: + append_group_by_files(options, source_dict) + if options.lines: + append_group_by_lines(options, source_dict) + for item in source_dict: + target_f.write(f"{item}:{':'.join(source_dict[item])}\n") + + +def append_passwd_files(target_f, options): + # Read source file + with open(options.source_file, 'r') as source_f: + source_contents = source_f.read() + + target_f.write(source_contents) + if options.files: + for append_f in options.files: + with open(append_f, 'r') as src: + target_f.write(src.read()) + if options.lines: + for line in options.lines: + target_f.write(line) + target_f.write("\n") + + +def main(args): + sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, + os.pardir, os.pardir, os.pardir, os.pardir, "build")) + from scripts.util import build_utils # noqa: E402 + + options = parse_args(args) + + if options.files: + depfile_deps = ([options.source_file] + options.files) + else: + depfile_deps = ([options.source_file]) + + with os.fdopen(os.open(options.output, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 'w') as target_f: + if operator.contains(options.source_file, "group"): + append_group_files(target_f, options) + else: + append_passwd_files(target_f, options) + + build_utils.write_depfile(options.depfile, + options.output, depfile_deps, add_pydeps=False) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/services/etc/appender/file_appender.pydeps b/services/etc/appender/file_appender.pydeps new file mode 100755 index 0000000000000000000000000000000000000000..2255c08a9c4c3b6cea238c86cf402da4ef5a1579 --- /dev/null +++ b/services/etc/appender/file_appender.pydeps @@ -0,0 +1,9 @@ +# Generated by running: +# build/print_python_deps.py --root base/startup/init/services/etc/appender --output base/startup/init/services/etc/appender/file_appender.pydeps base/startup/init/services/etc/appender/file_appender.py +../../../../../../build/gn_helpers.py +../../../../../../build/scripts/__init__.py +../../../../../../build/scripts/util/__init__.py +../../../../../../build/scripts/util/build_utils.py +../../../../../../build/scripts/util/md5_check.py +../../../../../../build/scripts/util/pycache.py +file_appender.py diff --git a/services/etc/console.cfg b/services/etc/console.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d3ada076331e3fcd74160a074544f8dc5a93bbee --- /dev/null +++ b/services/etc/console.cfg @@ -0,0 +1,18 @@ +{ + "services" : [{ + "name" : "console", + "path" : ["/system/bin/sh"], + "start-mode" : "condition", + "disabled" : 1, + "console" : 1, + "sandbox" : 0, + "uid" : "root", + "gid" : ["shell", "log", "readproc"], + "ondemand" : true, + "jobs" : { + "on-start" : "services:console" + }, + "secon" : "u:r:console:s0" + } + ] +} diff --git a/services/etc/console.user.cfg b/services/etc/console.user.cfg new file mode 100644 index 0000000000000000000000000000000000000000..9635c231051dd999582cfc440c7431743cbbd036 --- /dev/null +++ b/services/etc/console.user.cfg @@ -0,0 +1,18 @@ +{ + "services" : [{ + "name" : "console", + "path" : ["/system/bin/sh"], + "disabled" : 1, + "console" : 1, + "sandbox" : 0, + "uid" : "shell", + "gid" : ["shell", "log", "readproc"], + "ondemand" : true, + "jobs" : { + "on-start" : "services:console" + }, + "caps" : ["SETGID", "SETUID"], + "secon" : "u:r:console:s0" + } + ] +} diff --git a/services/etc/device.boot.group.cfg b/services/etc/device.boot.group.cfg new file mode 100755 index 0000000000000000000000000000000000000000..563078d0b5d9a0e182f6daf82bda845d5908c504 --- /dev/null +++ b/services/etc/device.boot.group.cfg @@ -0,0 +1,8 @@ +{ + "jobs": [ + ], + "services": [ + ], + "groups": [ + ] +} \ No newline at end of file diff --git a/services/etc/group b/services/etc/group old mode 100755 new mode 100644 index 59e29faa5c19c4f1e0f7f39ceb767928de5f9d41..1ff37bfa4646a44f33ac8f53ca38b6f7275de01b --- a/services/etc/group +++ b/services/etc/group @@ -4,28 +4,167 @@ system:x:1000: radio:x:1001: bluetooth:x:1002: graphics:x:1003: +ueventd:x:1004:root +file_manager:x:1006: log:x:1007: +user_data_rw:x:1008: +dfs:x:1009: wifi:x:1010: +wifi_group:x:1011:wifi,wifi_host media:x:1013: dhcp:x:1014: vpn:x:1016: keystore:x:1017: usb:x:1018: drm:x:1019: +gps:x:1021: +location_host:x:1022: media_rw:x:1023: +dsoftbus:x:1024: nfc:x:1027: sdcard_r:x:1028: package_info:x:1032: logd:x:1036: shared_relro:x:1037: -audioserver:x:1041: +audio:x:1041: +intell_voice:x:1042: +media_monitor:x:1043: cameraserver:x:1047: -shell:x:2000: +uiserver:x:1048: +servicectrl:x:1050:root,shell,system,samgr,hdf_devmgr,foundation,powermgr,update,memmgr +powerctrl:x:1051:root,shell,system,update,power_host,charger,foundation,powermgr,atcmdserver,bms_animation,maintenance_service,quickfix +bootctrl:x:1052:root,shell,system +deviceprivate:x:1053:root,shell,system,samgr,hdf_devmgr,deviceinfo,dsoftbus,dms,account,pin_auth_host,access_token,device_manager,foundation,powermgr,dbms,deviceauth,huks_server,dlp_credential,dsserver,edm,update,device_attest,hiview,device_cert_manager_server,huawei_id,radio,useriam +data_reserve:x:1065: +ressched:x:1096: +hiview:x:1201: +hidumper_service:x:1212: +shell:x:2000:hiview cache:x:2001: +app_install:x:2002: net_bw_stats:x:3006: net_bw_acct:x:3007: readproc:x:3009: wakelock:x:3010: -uhid:x:3011: +uhid:x:3011:hdf_ext_devmgr +ddms:x:3012: +access_token:x:3020: +blue_host:x:3021: +sample_host:x:3022: +usb_host:x:3023:print,cups,audio +usbfn_host:x:3024: +power_host:x:3025: +wifi_host:x:3026: +audio_hdi_server_host:x:3027: +audio_host:x:3127: +camera_host:x:3028: +input_user_host:x:3029: +codec_host:x:3031: +riladapter_host:x:3032: +sensor_host:x:3033: +vibrator_host:x:3034: +light_host:x:3035: +composer_host:x:3036: +dcamera_host:x:3038: +daudio_host:x:3059: +allocator_host:x:3041: +nfc_host:x:3042: +a2dp_host:x:3043: +hdf_devmgr:x:3044: +connected_tag_host:x:3045: +dslm:x:3046: +secure_element_host:x:3047: +device_usage_stats:x:3048: +security_component:x:3050: +bgtask:x:3051: +dcamera:x:3052: +dinput:x:3053: +dscreen:x:3054: +daudio:x:3055: +dhardware:x:3056: +installs:x:3060: +vendor_mpp_driver:x:3061: +device_manager:x:3062: +se_service:x:3064: +deviceauth:x:3333: +huks_server:x:3510: +asset_service:x:6226: +cert_manager_server:x:3515: +device_cert_manager_server:x:3562: +dlp_credential:x:3553: +dlp_permission:x:3019: +dms:x:5522: +foundation:x:5523: +quickfixserver:x:5524: +cast_engine_service:x:5526: +sharing_service:x:5527: +powermgr:x:5528: +samgr:x:5555: +update:x:6666: +charger:x:6667: +sensor:x:6688: +input:x:6696: +msdp:x:6699: +av_session:x:6700: misc:x:9998: app:x:10000: +useriam:x:1088: +user_auth_host:x:1112: +pin_auth_host:x:1113: +face_auth_host:x:1114: +fingerprint_auth_host:x:1115: +backup:x:1089: +storage_manager:x:1090: +net_manager:x:1099: +netsysnative:x:1098: +netsys_socket:x:1097: +edm:x:3057: +account:x:3058: +download:x:3815: +pasteboard:x:3816: +wallpaper:x:3817: +screenlock:x:3818: +time:x:3819: +inputmethod:x:3820: +watchdog:x:1100: +paramwatcher:x:1101: +deviceinfo:x:1102: +accessibility:x:1103: +motion_host:x:3065: +uhdf_driver:x:3066: +memmgr:x:1111: +ispserver:x:3821: +dfs_share:x:3822: +appspawn:x:6005: +print:x:3823: +cups:x:3824: +security_guard:x:3520: +security_collector:x:3521: +tee:x:6668: +dsserver:x:3068: +device_attest:x:3049: +dev_dma_heap:x:3070: +dev_memory:x:3071: +dev_lcd_backlight:x:3072: +dev_vibrator:x:3080: +vcodec:x:3073: +dev_camera:x:3090: +servicerouter:x:6066: +nwebspawn:x:3081: +oaid_service:x:6101: +code_sign:x:3074: +el5_filekey_manager:x:3077: +hdf_ext_devmgr:x:3085: +intell_voice_host:x:3100: +user_data_r:x:2008: +huawei_id:x:7008: +drmserver:x:1077: +clearplay_host:x:3078: +wiseplay_host:x:3079: +i18n:x:3013: +testserver:x:3500: +media_db_rw:x:3008: +app_domain_verify:x:3111: +compiler_service:x:5300: +sandbox_manager:x:3076: +app_fwk_update:x:3350: diff --git a/services/etc/init.cfg b/services/etc/init.cfg index f435edbd6f0f03de580243ef5d76dd903224d7fd..afa4cacb3c896f939899fa1e7187a8b08f98a4ba 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -2,91 +2,43 @@ "import" : [ "/etc/init.usb.cfg", "/etc/init.usb.configfs.cfg", - "/etc/init.usb.cfg", - "/etc/init.Hi3516DV300.usb.cfg", - "/etc/init.Hi3516DV300.cfg" + "/vendor/etc/init.${ohos.boot.hardware}.cfg" ], "jobs" : [{ "name" : "pre-init", "cmds" : [ "write /proc/sys/kernel/sysrq 0", - "mkdir /acct/uid", - "chown root system /dev/memcg/memory.pressure_level", - "chmod 0040 /dev/memcg/memory.pressure_level", - "mkdir /dev/memcg/apps/ 0755 system system", - "mkdir /dev/memcg/system 0550 system system", + "write /proc/sys/kernel/dmesg_restrict 1", + "write /proc/sys/kernel/kptr_restrict 1", "start ueventd", - "mkdir /vendor", + "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" + "mount_fstab /vendor/etc/fstab.${ohos.boot.hardware}", + "restorecon /data --skip-ELX", + "chown system system /data", + "chmod 0771 /data", + "mkdir /data/service 0711 root root", + "mkdir /data/service/el0 0711 root root", + "mkdir /data/service/el0/startup 0755 root root", + "mkdir /data/service/el0/startup/init 0755 root root", + "mkdir /data/vendor/log 0755 system log", + "mount configfs none /config nodev noexec nosuid", + "load_persist_params ", + "bootchart start", + "chown access_token access_token /dev/access_token_id", + "chmod 0666 /dev/access_token_id", + "trigger init-hitrace" ] }, { "name" : "init", "cmds" : [ + "mksandbox system", + "mksandbox chipset", "copy /proc/cmdline /dev/urandom", "copy /system/etc/prop.default /dev/urandom", "symlink /proc/self/fd/0 /dev/stdin", "symlink /proc/self/fd/1 /dev/stdout", "symlink /proc/self/fd/2 /dev/stderr", - "symlink /system/bin /bin", - "symlink /system/etc /etc", - "symlink /sys/kernel/debug /d", - "symlink /system/vendor /vendor", - "mkdir /dev/stune/foreground", - "mkdir /dev/stune/background", - "mkdir /dev/stune/top-app", - "mkdir /dev/stune/rt", - "chown system system /dev/stune", - "chown system system /dev/stune/foreground", - "chown system system /dev/stune/background", - "chown system system /dev/stune/top-app", - "chown system system /dev/stune/rt", - "chown system system /dev/stune/tasks", - "chown system system /dev/stune/foreground/tasks", - "chown system system /dev/stune/background/tasks", - "chown system system /dev/stune/top-app/tasks", - "chown system system /dev/stune/rt/tasks", - "chmod 0664 /dev/stune/tasks", - "chmod 0664 /dev/stune/foreground/tasks", - "chmod 0664 /dev/stune/background/tasks", - "chmod 0664 /dev/stune/top-app/tasks", - "chmod 0664 /dev/stune/rt/tasks", - "mkdir /dev/blkio/background", - "chown system system /dev/blkio", - "chown system system /dev/blkio/background", - "chown system system /dev/blkio/tasks", - "chown system system /dev/blkio/background/tasks", - "chmod 0664 /dev/blkio/tasks", - "chmod 0664 /dev/blkio/background/tasks", - "write /dev/blkio/blkio.weight 1000", - "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", - "mkdir /mnt/secure 0700 root root", - "mkdir /mnt/secure/asec 0700 root root", - "mkdir /mnt/asec 0755 root system", - "mkdir /mnt/obb 0755 root system", - "mkdir /mnt/media_rw 0750 root media_rw", - "mkdir /mnt/user 0755 root root", - "mkdir /mnt/user/0 0755 root root", - "mkdir /mnt/expand 0771 system system", - "mkdir /mnt/appfuse 0711 root root", - "mkdir /mnt/runtime 0700 root root", - "mkdir /mnt/runtime/default 0755 root root", - "mkdir /mnt/runtime/default/self 0755 root root", - "mkdir /mnt/runtime/read 0755 root root", - "mkdir /mnt/runtime/read/self 0755 root root", - "mkdir /mnt/runtime/write 0755 root root", - "mkdir /mnt/runtime/write/self 0755 root root", - "mkdir /mnt/runtime/full 0755 root root", - "mkdir /mnt/runtime/full/self 0755 root root", - "symlink /storage/self/primary /sdcard", - "symlink /storage/self/primary /mnt/sdcard", - "symlink /mnt/user/0/primary /mnt/runtime/default/self/primary", "write /proc/sys/kernel/panic_on_oops 1", "write /proc/sys/kernel/hung_task_timeout_secs 0", "write /proc/cpu/alignment 4", @@ -100,7 +52,7 @@ "write /proc/sys/net/unix/max_dgram_qlen 600", "write /proc/sys/kernel/sched_rt_runtime_us 950000", "write /proc/sys/kernel/sched_rt_period_us 1000000", - "write /proc/sys/net/core/rmem_max 262144", + "write /proc/sys/net/core/rmem_max 16777216", "write /proc/sys/net/core/wmem_max 262144", "write /proc/sys/net/ipv4/fwmark_reflect 1", "write /proc/sys/net/ipv6/fwmark_reflect 1", @@ -108,95 +60,25 @@ "write /proc/sys/net/ipv4/conf/all/accept_redirects 0", "write /proc/sys/net/ipv6/conf/all/accept_redirects 0", "chmod 0400 /proc/net/fib_trie", - "chown system system /dev/cpuctl", - "chown system system /dev/cpuctl/tasks", - "chmod 0666 /dev/cpuctl/tasks", - "write /dev/cpuctl/cpu.rt_period_us 1000000", - "write /dev/cpuctl/cpu.rt_runtime_us 950000", - "mkdir /dev/cpuset/foreground", - "copy /dev/cpuset/cpus /dev/cpuset/foreground/cpus", - "copy /dev/cpuset/mems /dev/cpuset/foreground/mems", - "mkdir /dev/cpuset/background", - "copy /dev/cpuset/cpus /dev/cpuset/background/cpus", - "copy /dev/cpuset/mems /dev/cpuset/background/mems", - "mkdir /dev/cpuset/system-background", - "copy /dev/cpuset/cpus /dev/cpuset/system-background/cpus", - "copy /dev/cpuset/mems /dev/cpuset/system-background/mems", - "mkdir /dev/cpuset/restricted", - "copy /dev/cpuset/cpus /dev/cpuset/restricted/cpus", - "copy /dev/cpuset/mems /dev/cpuset/restricted/mems", - "mkdir /dev/cpuset/top-app", - "copy /dev/cpuset/cpus /dev/cpuset/top-app/cpus", - "copy /dev/cpuset/mems /dev/cpuset/top-app/mems", - "chown system system /dev/cpuset", - "chown system system /dev/cpuset/foreground", - "chown system system /dev/cpuset/background", - "chown system system /dev/cpuset/system-background", - "chown system system /dev/cpuset/top-app", - "chown system system /dev/cpuset/restricted", - "chown system system /dev/cpuset/tasks", - "chown system system /dev/cpuset/foreground/tasks", - "chown system system /dev/cpuset/background/tasks", - "chown system system /dev/cpuset/system-background/tasks", - "chown system system /dev/cpuset/top-app/tasks", - "chown system system /dev/cpuset/restricted/tasks", - "chmod 0775 /dev/cpuset/system-background", - "chmod 0664 /dev/cpuset/foreground/tasks", - "chmod 0664 /dev/cpuset/background/tasks", - "chmod 0664 /dev/cpuset/system-background/tasks", - "chmod 0664 /dev/cpuset/top-app/tasks", - "chmod 0664 /dev/cpuset/restricted/tasks", - "chmod 0664 /dev/cpuset/tasks", "chown system system /proc/pressure/memory", "chmod 0664 /proc/pressure/memory", - "chown root net_bw_acct /proc/net/xt_qtaguid/ctrl", - "chown root net_bw_stats /proc/net/xt_qtaguid/stats", - "chmod 0644 /dev/xt_qtaguid", - "chown root root /dev/cg2_bpf", - "chmod 0600 /dev/cg2_bpf", - "mount bpf bpf /sys/fs/bpf nodev noexec nosuid", "mkdir /dev/fscklogs 0770 root system", - "mount pstore pstore /sys/fs/pstore nodev noexec nosuid", - "chown system log /sys/fs/pstore", - "chmod 0550 /sys/fs/pstore", - "chown system log /sys/fs/pstore/console-ramoops", - "chmod 0440 /sys/fs/pstore/console-ramoops", - "chown system log /sys/fs/pstore/console-ramoops-0", - "chmod 0440 /sys/fs/pstore/console-ramoops-0", - "chown system log /sys/fs/pstore/pmsg-ramoops-0", - "chmod 0440 /sys/fs/pstore/pmsg-ramoops-0", "write /proc/sys/abi/swp 1", "symlink /proc/self/fd /dev/fd", "export DOWNLOAD_CACHE /data/cache", "setrlimit RLIMIT_NICE 40 40", "setrlimit RLIMIT_NOFILE 32768 32768", "write /sys/class/leds/vibrator/trigger transient", - "write /dev/cpu_variant:${ro.bionic.arch} ${ro.bionic.cpu_variant}", - "chmod 0444 /dev/cpu_variant:${ro.bionic.arch}", - "write /dev/cpu_variant:${ro.bionic.2nd_arch} ${ro.bionic.2nd_cpu_variant}", - "chmod 0444 /dev/cpu_variant:${ro.bionic.2nd_arch}", "chown system system /sys/power/state", "chown system system /sys/power/wakeup_count", "chmod 0660 /sys/power/state", + "mount pstore pstore /sys/fs/pstore nodev noexec nosuid", + "chown system log /sys/fs/pstore", + "chmod 0555 /sys/fs/pstore", "ifup lo", "hostname localhost", - "domainname localdomain" - ] - }, { - "name" : "param:sys.boot_from_charger_mode=1", - "condition" : "sys.boot_from_charger_mode=1", - "cmds" : [ - "trigger post-init" - ] - }, { - "name" : "load_persist_props_action", - "cmds" : [ - "load_persist_params load_persist_params" - ] - }, { - "name" : "firmware_mounts_complete", - "cmds" : [ - "rm /dev/.booting" + "domainname localdomain", + "export TMPDIR /data/local/tmp" ] }, { "name" : "post-init", @@ -206,40 +88,65 @@ "trigger post-fs", "trigger late-fs", "trigger post-fs-data", - "trigger load_persist_props_action", "trigger firmware_mounts_complete", "trigger early-boot", "trigger boot" ] }, { - "name" : "early-fs", + "name" : "fs", "cmds" : [ - "start vold" ] }, { "name" : "post-fs", "cmds" : [ - "exec - system system -- /system/bin/vdc checkpoint markBootAttempt", "mount rootfs rootfs / remount bind ro nodev", - "mount none /mnt/runtime/default /storage bind rec", - "mount none none /storage slave rec", - "chown system cache /cache", - "chmod 0770 /cache", - "mkdir /cache/recovery 0770 system cache", - "mkdir /cache/backup_stage 0700 system system", - "mkdir /cache/backup 0700 system system", "chown root log /proc/vmallocinfo", "chmod 0440 /proc/vmallocinfo", "chown root log /proc/slabinfo", "chmod 0440 /proc/slabinfo", "chown root system /proc/kmsg", "chmod 0440 /proc/kmsg", - "chown root system /proc/sysrq-trigger", - "chmod 0220 /proc/sysrq-trigger", - "chown system log /proc/last_kmsg", - "chmod 0440 /proc/last_kmsg", "chmod 0444 /sys/fs/selinux/policy", - "mkdir /cache/lost+found 0770 root root" + "init_global_key /data", + "mkdir /data/app 0711 root root", + "mkdir /data/app/el1 0711 root root", + "mkdir /data/app/el1/bundle 0711 root root", + "mkdir /data/app/el1/bundle/public 0711 root root", + "mkdir /data/app/el2 0711 root root", + "mkdir /data/app/el3 0711 root root", + "mkdir /data/app/el4 0711 root root", + "mkdir /data/app/el5 0711 root root", + "mkdir /data/service/el0/public 0711 root root", + "mkdir /data/service/el0/public/for-all-app 0711 root root", + "mkdir /data/service/el1 0711 root root", + "mkdir /data/service/el1/public 0711 root root", + "mkdir /data/service/el1/public/AbilityManagerService 0711 system system", + "mkdir /data/service/el1/public/for-all-app 0711 root root", + "mkdir /data/service/el2 0711 root root", + "mkdir /data/service/el2/public 0711 root root", + "mkdir /data/service/el3 0711 root root", + "mkdir /data/service/el4 0711 root root", + "mkdir /data/service/el5 0711 root root", + "mkdir /data/chipset 0711 root root", + "mkdir /data/chipset/el1 0711 root root", + "mkdir /data/chipset/el1/public 0711 root root", + "mkdir /data/chipset/el2 0711 root root", + "load_private_persist_params ", + "init_main_user ", + "mkdir /data/app/el1/0 0711 root root", + "mkdir /data/app/el1/0/base 0711 root root", + "mkdir /data/app/el1/0/database 0711 system system", + "mkdir /data/app/el2/0 0711 root root", + "mkdir /data/app/el2/0/base 0711 root root", + "mkdir /data/app/el2/0/database 0711 system system", + "mkdir /data/app/el2/0/log 0711 system system", + "mkdir /data/app/el3/0 0711 root root", + "mkdir /data/app/el3/0/base 0711 root root", + "mkdir /data/app/el4/0 0711 root root", + "mkdir /data/app/el4/0/base 0711 root root", + "mkdir /data/service/el2/0 0711 root root", + "mkdir /data/service/el2/0/hmdfs 0711 system system", + "mkdir /data/chipset/el2/0 0711 root root" ] }, { "name" : "late-fs", @@ -249,113 +156,26 @@ }, { "name" : "post-fs-data", "cmds" : [ - "chown system system /data", - "chmod 0771 /data", - "mkdir /data/bootchart 0755 shell shell", - "mkdir /data/app-staging 0750 system system", - "copy /data/system/entropy.dat /dev/urandom", + "mkdir /storage/media 0711 root root", "mkdir /data/misc 01771 system misc", - "mkdir /data/misc/recovery 0770 system log", - "copy /data/misc/recovery/ro.build.fingerprint /data/misc/recovery/ro.build.fingerprint.1", - "chmod 0440 /data/misc/recovery/ro.build.fingerprint.1", - "chown system log /data/misc/recovery/ro.build.fingerprint.1", - "write /data/misc/recovery/ro.build.fingerprint ${ro.build.fingerprint}", - "chmod 0440 /data/misc/recovery/ro.build.fingerprint", - "chown system log /data/misc/recovery/ro.build.fingerprint", - "mkdir /data/misc/recovery/proc 0770 system log", - "copy /data/misc/recovery/proc/version /data/misc/recovery/proc/version.1", - "chmod 0440 /data/misc/recovery/proc/version.1", - "chown system log /data/misc/recovery/proc/version.1", - "copy /proc/version /data/misc/recovery/proc/version", - "chmod 0440 /data/misc/recovery/proc/version", - "chown system log /data/misc/recovery/proc/version", - "mkdir /data/misc/bluedroid 02770 bluetooth bluetooth", - "chmod 0660 /data/misc/bluedroid/bt_config.conf", - "chown bluetooth bluetooth /data/misc/bluedroid/bt_config.conf", - "mkdir /data/misc/bluetooth 0770 bluetooth bluetooth", - "mkdir /data/misc/bluetooth/logs 0770 bluetooth bluetooth", - "mkdir /data/misc/keystore 0700 keystore keystore", - "mkdir /data/misc/gatekeeper 0700 system system", - "mkdir /data/misc/keychain 0771 system system", - "mkdir /data/misc/net 0750 root shell", - "mkdir /data/misc/radio 0770 system radio", - "mkdir /data/misc/sms 0770 system radio", - "mkdir /data/misc/carrierid 0770 system radio", - "mkdir /data/misc/apns 0770 system radio", - "mkdir /data/misc/zoneinfo 0775 system system", - "mkdir /data/misc/network_watchlist 0774 system system", - "mkdir /data/misc/textclassifier 0771 system system", - "mkdir /data/misc/vpn 0770 system vpn", - "mkdir /data/misc/shared_relro 0771 shared_relro shared_relro", - "mkdir /data/misc/systemkeys 0700 system system", - "mkdir /data/misc/wifi 0770 wifi wifi", - "mkdir /data/misc/wifi/sockets 0770 wifi wifi", - "mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi", - "mkdir /data/misc/ethernet 0770 system system", - "mkdir /data/misc/dhcp 0770 dhcp dhcp", - "mkdir /data/misc/user 0771 root root", - "mkdir /data/misc/perfprofd 0775 root root", - "chmod 0660 /data/misc/wifi/wpa_supplicant.conf", + "mkdir /data/misc/shared_relro 0771 root root", "mkdir /data/local 0751 root root", - "mkdir /data/misc/media 0700 media media", - "mkdir /data/misc/audioserver 0700 audioserver audioserver", - "mkdir /data/misc/cameraserver 0700 cameraserver cameraserver", - "mkdir /data/misc/vold 0700 root root", - "mkdir /data/misc/boottrace 0771 system shell", - "mkdir /data/misc/update_engine 0700 root root", - "mkdir /data/misc/update_engine_log 02750 root log", - "mkdir /data/misc/trace 0700 root root", - "mkdir /data/misc/wmtrace 0700 system system", - "mkdir /data/misc/profiles 0771 system system", - "mkdir /data/misc/profiles/cur 0771 system system", - "mkdir /data/misc/profiles/ref 0771 system system", - "mkdir /data/misc/profman 0770 system shell", - "mkdir /data/misc/gcov 0770 root root", - "mkdir /data/preloads 0775 system system", "mkdir /data/vendor 0771 root root", - "mkdir /data/vendor_ce 0771 root root", - "mkdir /data/vendor_de 0771 root root", - "mkdir /data/vendor/hardware 0771 root root", + "mkdir /data/local/ark-cache 0711 root root", "mkdir /data/local/tmp 0771 shell shell", + "mkdir /data/local/tmp/debugserver 0755 shell shell", "mkdir /data/local/traces 0777 shell shell", "mkdir /data/data 0771 system system", - "mkdir /data/app-private 0771 system system", - "mkdir /data/app-ephemeral 0771 system system", - "mkdir /data/app-asec 0700 root root", - "mkdir /data/app-lib 0771 system system", "mkdir /data/app 0771 system system", - "mkdir /data/ota 0771 root root", - "mkdir /data/ota_package 0770 system cache", - "mkdir /data/resource-cache 0771 system system", - "chown system system /data/resource-cache", - "chmod 0771 /data/resource-cache", - "mkdir /data/lost+found 0770 root root", - "mkdir /data/drm 0770 drm drm", - "mkdir /data/mediadrm 0770 mediadrm mediadrm", "mkdir /data/nfc 0770 nfc nfc", "mkdir /data/nfc/param 0770 nfc nfc", - "mkdir /data/backup 0700 system system", - "mkdir /data/ss 0700 system system", - "mkdir /data/system 0775 system system", - "mkdir /data/system/dropbox 0700 system system", - "mkdir /data/system/heapdump 0700 system system", - "mkdir /data/system/users 0775 system system", - "mkdir /data/system_de 0770 system system", - "mkdir /data/system_ce 0770 system system", - "mkdir /data/misc_de 01771 system misc", - "mkdir /data/misc_ce 01771 system misc", - "mkdir /data/user 0711 system system", - "mkdir /data/user_de 0711 system system", - "symlink /data/data /data/user/0", - "mkdir /data/media 0770 media_rw media_rw", - "mkdir /data/media/obb 0770 media_rw media_rw", - "mkdir /data/cache 0770 system cache", - "mkdir /data/cache/recovery 0770 system cache", - "mkdir /data/cache/backup_stage 0700 system system", - "mkdir /data/cache/backup 0700 system system", "setparam sys.use_memfd false", "chown root system /dev/fscklogs/log", - "chmod 0770 /dev/fscklogs/log" + "chmod 0770 /dev/fscklogs/log", + "chmod 0660 /dev/fuse", + "restorecon /data/service/el1/public", + "restorecon /data/service/el1/public/activation_lock", + "restorecon /data/service/el1/startup/parameters" ] }, { "name" : "boot", @@ -363,76 +183,12 @@ "write /proc/sys/net/core/xfrm_acq_expires 3600", "write /proc/sys/vm/overcommit_memory 1", "write /proc/sys/vm/min_free_order_shift 4", - "chown root system /sys/module/lowmemorykiller/parameters/adj", - "chmod 0664 /sys/module/lowmemorykiller/parameters/adj", - "chown root system /sys/module/lowmemorykiller/parameters/minfree", - "chmod 0664 /sys/module/lowmemorykiller/parameters/minfree", "chown root system /sys/block/zram0/idle", "chmod 0664 /sys/block/zram0/idle", - "chown root system /sys/block/zram0/writeback", - "chmod 0664 /sys/block/zram0/writeback", "write /proc/sys/vm/dirty_expire_centisecs 200", "write /proc/sys/vm/dirty_background_ratio 5", - "write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200", - "chown radio system /sys/android_power/state", - "chown radio system /sys/android_power/request_state", - "chown radio system /sys/android_power/acquire_full_wake_lock", - "chown radio system /sys/android_power/acquire_partial_wake_lock", - "chown radio system /sys/android_power/release_wake_lock", - "chown system system /sys/power/autosleep", - "chown radio wakelock /sys/power/wake_lock", - "chown radio wakelock /sys/power/wake_unlock", - "chmod 0660 /sys/power/wake_lock", - "chmod 0660 /sys/power/wake_unlock", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_slack", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_slack", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/target_loads", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/target_loads", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/boost", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boost", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/input_boost", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/input_boost", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration", - "chown system system /sys/devices/system/cpu/cpufreq/interactive/io_is_busy", - "chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy", - "chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", - "chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", - "chown system system /sys/class/leds/vibrator/trigger", - "chown system system /sys/class/leds/vibrator/activate", - "chown system system /sys/class/leds/vibrator/brightness", - "chown system system /sys/class/leds/vibrator/duration", - "chown system system /sys/class/leds/vibrator/state", - "chown system system /sys/class/timed_output/vibrator/enable", - "chown system system /sys/class/leds/keyboard-backlight/brightness", - "chown system system /sys/class/leds/lcd-backlight/brightness", - "chown system system /sys/class/leds/button-backlight/brightness", - "chown system system /sys/class/leds/jogball-backlight/brightness", - "chown system system /sys/class/leds/red/brightness", - "chown system system /sys/class/leds/green/brightness", - "chown system system /sys/class/leds/blue/brightness", - "chown system system /sys/class/leds/red/device/grpfreq", - "chown system system /sys/class/leds/red/device/grppwm", - "chown system system /sys/class/leds/red/device/blink", - "chown system system /sys/module/sco/parameters/disable_esco", - "chown system system /sys/kernel/ipv4/tcp_wmem_min", - "chown system system /sys/kernel/ipv4/tcp_wmem_def", - "chown system system /sys/kernel/ipv4/tcp_wmem_max", - "chown system system /sys/kernel/ipv4/tcp_rmem_min", - "chown system system /sys/kernel/ipv4/tcp_rmem_def", - "chown system system /sys/kernel/ipv4/tcp_rmem_max", "chown root radio /proc/cmdline", + "chown update update /dev/block/by-name/misc", "setparam net.tcp.default_init_rwnd 60" ] }, { @@ -448,41 +204,16 @@ "write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd}" ] }, { - "name" : "param:security.perf_harden=0", - "condition" : "security.perf_harden=0", - "cmds" : [ - "write /proc/sys/kernel/perf_event_paranoid 1", - "write /proc/sys/kernel/perf_event_max_sample_rate ${debug.perf_event_max_sample_rate:-100000}", - "write /proc/sys/kernel/perf_cpu_time_max_percent ${debug.perf_cpu_time_max_percent:-25}", - "write /proc/sys/kernel/perf_event_mlock_kb ${debug.perf_event_mlock_kb:-516}" - ] - }, { - "name" : "param:security.perf_harden=1", - "condition" : "security.perf_harden=1", + "name" : "services:console", "cmds" : [ - "write /proc/sys/kernel/perf_event_paranoid 3" + "chmod 0773 /data/misc/trace", + "chmod 0775 /data/misc/wmtrace" ] }, { - "name" : "boot && param:ro.debuggable=1", - "condition" : "boot && ro.debuggable=1", + "name" : "init-trace", "cmds" : [ - "chmod 0773 /data/misc/trace", - "chmod 0775 /data/misc/wmtrace", - "start console" + "init_trace start" ] } - ], - "services" : [{ - "name" : "ueventd", - "path" : ["/system/bin/ueventd"], - "critical" : 1 - }, { - "name" : "console", - "path" : ["/system/bin/sh"], - "disabled" : 1, - "console" : 1, - "uid" : "root", - "gid" : ["shell", "log", "readproc"] - } ] } diff --git a/services/etc/init.reboot.cfg b/services/etc/init.reboot.cfg new file mode 100755 index 0000000000000000000000000000000000000000..dbea31ae13f85b466cf7e846ec7153101c3dc617 --- /dev/null +++ b/services/etc/init.reboot.cfg @@ -0,0 +1,24 @@ +{ + "jobs" : [{ + "name" : "reboot", + "cmds" : [ + "stop_feed_highdog", + "stopAllServices true", + "sync ", + "umount /vendor", + "umount /data MNT_FORCE", + "sync " + ] + }, { + "name" : "suspend", + "cmds" : [ + "stopAllServices false", + "sync ", + "umount /vendor", + "umount /data MNT_FORCE", + "sync " + ] + } + ], + "services" : [] +} diff --git a/services/etc/init.usb.cfg b/services/etc/init.usb.cfg index dd282c005b18b190b3ef31a4742390168f0cea47..d28b2adf6b7940ca0d007d256a8d188a10c8c538 100755 --- a/services/etc/init.usb.cfg +++ b/services/etc/init.usb.cfg @@ -1,10 +1,8 @@ { + "import" : [ + "/vendor/etc/init.${ohos.boot.hardware}.usb.cfg" + ], "jobs" : [{ - "name" : "boot", - "cmds" : [ - "setparam sys.usb.configfs 0" - ] - }, { "name" : "boot && param:persist.sys.usb.config=*", "condition" : "boot && persist.sys.usb.config=*", "cmds" : [ @@ -16,21 +14,6 @@ "cmds" : [ "stop hdcd" ] - }, { - "name" : "param:sys.usb.config=hdc && param:sys.usb.configfs=0", - "condition" : "sys.usb.config=hdc && sys.usb.configfs=0", - "cmds" : [ - "start hdcd" - ] - } - ], - "services" : [{ - "name" : "hdcd", - "path" : ["/system/bin/hdcd"], - "socket" : [ - "hdcd seqpacket 660 system system false" - ], - "disabled" : 1 } ] } diff --git a/services/etc/init.usb.configfs.cfg b/services/etc/init.usb.configfs.cfg deleted file mode 100755 index 989fa74d1b373d914bd9b79da112a7b0714d411a..0000000000000000000000000000000000000000 --- a/services/etc/init.usb.configfs.cfg +++ /dev/null @@ -1,38 +0,0 @@ -{ - "jobs" : [{ - "name" : "param:sys.usb.config=none && param:sys.usb.configfs=1", - "condition" : "sys.usb.config=none && sys.usb.configfs=1", - "cmds" : [ - "write /config/usb_gadget/g1/UDC none", - "stop hdcd", - "setparam sys.usb.ffs.ready 0", - "write /config/usb_gadget/g1/bDeviceClass 0", - "write /config/usb_gadget/g1/bDeviceSubClass 0", - "write /config/usb_gadget/g1/bDeviceProtocol 0", - "rm /config/usb_gadget/g1/configs/b.1/f1", - "setparam sys.usb.state ${sys.usb.config}" - ] - }, { - "name" : "param:init.svc.hdcd=stopped", - "condition" : "init.svc.hdcd=stopped", - "cmds" : [ - "setparam sys.usb.ffs.ready 0" - ] - }, { - "name" : "param:sys.usb.config=hdc && param:sys.usb.configfs=1", - "condition" : "sys.usb.config=hdc && sys.usb.configfs=1", - "cmds" : [ - "start hdcd" - ] - }, { - "name" : "param:sys.usb.ffs.ready=1 && param:sys.usb.config=hdc && param:sys.usb.configfs=1", - "condition" : "sys.usb.ffs.ready=1 && sys.usb.config=hdc && sys.usb.configfs=1", - "cmds" : [ - "write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration hdc", - "symlink /config/usb_gadget/g1/functions/ffs.hdc /config/usb_gadget/g1/configs/b.1/f1", - "write /config/usb_gadget/g1/UDC ${sys.usb.controller}", - "setparam sys.usb.state ${sys.usb.config}" - ] - } - ] -} diff --git a/services/etc/init.without_two_stages.cfg b/services/etc/init.without_two_stages.cfg new file mode 100755 index 0000000000000000000000000000000000000000..d60d763699650bc145aaa74e330cc505bafcb790 --- /dev/null +++ b/services/etc/init.without_two_stages.cfg @@ -0,0 +1,296 @@ +{ + "import" : [ + "/etc/init.usb.cfg", + "/etc/init.usb.configfs.cfg", + "/vendor/etc/init.${ohos.boot.hardware}.cfg" + ], + "jobs" : [{ + "name" : "pre-init", + "cmds" : [ + "write /proc/sys/kernel/sysrq 0", + "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", + "mkdir /data/service/el0 0711 root root", + "mkdir /data/vendor/log 0755 system log", + "load_persist_params " + ] + }, { + "name" : "init", + "cmds" : [ + "copy /proc/cmdline /dev/urandom", + "copy /system/etc/prop.default /dev/urandom", + "symlink /proc/self/fd/0 /dev/stdin", + "symlink /proc/self/fd/1 /dev/stdout", + "symlink /proc/self/fd/2 /dev/stderr", + "write /proc/sys/kernel/panic_on_oops 1", + "write /proc/sys/kernel/hung_task_timeout_secs 0", + "write /proc/cpu/alignment 4", + "write /proc/sys/kernel/sched_tunable_scaling 0", + "write /proc/sys/kernel/sched_latency_ns 10000000", + "write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000", + "write /proc/sys/kernel/sched_child_runs_first 0", + "write /proc/sys/kernel/randomize_va_space 2", + "write /proc/sys/vm/mmap_min_addr 32768", + "write /proc/sys/net/ipv4/ping_group_range 0 2147483647", + "write /proc/sys/net/unix/max_dgram_qlen 600", + "write /proc/sys/kernel/sched_rt_runtime_us 950000", + "write /proc/sys/kernel/sched_rt_period_us 1000000", + "write /proc/sys/net/core/rmem_max 262144", + "write /proc/sys/net/core/wmem_max 262144", + "write /proc/sys/net/ipv4/fwmark_reflect 1", + "write /proc/sys/net/ipv6/fwmark_reflect 1", + "write /proc/sys/net/ipv4/tcp_fwmark_accept 1", + "write /proc/sys/net/ipv4/conf/all/accept_redirects 0", + "write /proc/sys/net/ipv6/conf/all/accept_redirects 0", + "chmod 0400 /proc/net/fib_trie", + "chown system system /proc/pressure/memory", + "chmod 0664 /proc/pressure/memory", + "mkdir /dev/fscklogs 0770 root system", + "write /proc/sys/abi/swp 1", + "symlink /proc/self/fd /dev/fd", + "export DOWNLOAD_CACHE /data/cache", + "setrlimit RLIMIT_NICE 40 40", + "setrlimit RLIMIT_NOFILE 32768 32768", + "write /sys/class/leds/vibrator/trigger transient", + "chown system system /sys/power/state", + "chown system system /sys/power/wakeup_count", + "chmod 0660 /sys/power/state", + "ifup lo", + "hostname localhost", + "domainname localdomain", + "export TMPDIR /data/local/tmp" + ] + }, { + "name" : "post-init", + "cmds" : [ + "trigger early-fs", + "trigger fs", + "trigger post-fs", + "trigger late-fs", + "trigger post-fs-data", + "trigger firmware_mounts_complete", + "trigger early-boot", + "trigger boot" + ] + }, { + "name" : "post-fs", + "cmds" : [ + "mount rootfs rootfs / remount bind ro nodev", + "chown root log /proc/vmallocinfo", + "chmod 0440 /proc/vmallocinfo", + "chown root log /proc/slabinfo", + "chmod 0440 /proc/slabinfo", + "chown root system /proc/kmsg", + "chmod 0440 /proc/kmsg", + "chmod 0444 /sys/fs/selinux/policy" + ] + }, { + "name" : "late-fs", + "cmds" : [ + "chmod 0755 /sys/kernel/debug/tracing" + ] + }, { + "name" : "post-fs-data", + "cmds" : [ + "init_global_key /data", + "mkdir /data/app 0711 root root", + "mkdir /data/app/el1 0711 root root", + "mkdir /data/app/el1/bundle 0711 root root", + "mkdir /data/app/el1/bundle/public 0711 root root", + "mkdir /data/app/el2 0711 root root", + "mkdir /data/app/el3 0711 root root", + "mkdir /data/app/el4 0711 root root", + "mkdir /data/service/el1 0711 root root", + "mkdir /data/service/el1/public 0711 root root", + "mkdir /data/service/el2 0711 root root", + "mkdir /data/service/el2/public 0711 root root", + "mkdir /data/chipset 0711 root root", + "mkdir /data/service/el0/public 0711 root root", + "mkdir /data/service/el0/public/for-all-app 0711 root root", + "mkdir /data/chipset/el1 0711 root root", + "mkdir /data/chipset/el1/public 0711 root root", + "mkdir /data/service/el1/public/for-all-app 0711 root root", + "mkdir /data/chipset/el2 0711 root root", + "init_main_user ", + "mkdir /data/app/el1/0 0711 root root", + "mkdir /data/app/el1/0/base 0711 root root", + "mkdir /data/app/el1/0/database 0711 system system", + "mkdir /data/app/el2/0 0711 root root", + "mkdir /data/app/el2/0/base 0711 root root", + "mkdir /data/app/el2/0/database 0711 system system", + "mkdir /data/app/el2/0/log 0711 system system", + "mkdir /data/app/el3/0 0711 root root", + "mkdir /data/app/el3/0/base 0711 root root", + "mkdir /data/app/el4/0 0711 root root", + "mkdir /data/app/el4/0/base 0711 root root", + "mkdir /data/service/el1/0 0711 root root", + "mkdir /data/service/el2/0 0711 root root", + "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", + "mkdir /data/bootchart 0755 shell shell", + "mkdir /data/app-staging 0750 system system", + "copy /data/system/entropy.dat /dev/urandom", + "mkdir /data/misc 01771 system misc", + "mkdir /data/local 0751 root root", + "mkdir /data/preloads 0775 system system", + "mkdir /data/vendor 0771 root root", + "mkdir /data/vendor_ce 0771 root root", + "mkdir /data/vendor_de 0771 root root", + "mkdir /data/vendor/hardware 0771 root root", + "mkdir /data/local/tmp 0771 shell shell", + "mkdir /data/local/traces 0777 shell shell", + "mkdir /data/data 0771 system system", + "mkdir /data/app-private 0771 system system", + "mkdir /data/app-ephemeral 0771 system system", + "mkdir /data/app-asec 0700 root root", + "mkdir /data/app-lib 0771 system system", + "mkdir /data/app 0771 system system", + "mkdir /data/ota 0771 root root", + "mkdir /data/ota_package 0770 update update", + "chown update update /data/ota_package", + "chmod 0770 /data/ota_package", + "mkdir /data/resource-cache 0771 system system", + "chown system system /data/resource-cache", + "chmod 0771 /data/resource-cache", + "mkdir /data/lost+found 0770 root root", + "mkdir /data/drm 0770 drm drm", + "mkdir /data/mediadrm 0770 mediadrm mediadrm", + "mkdir /data/nfc 0770 nfc nfc", + "mkdir /data/nfc/param 0770 nfc nfc", + "mkdir /data/backup 0700 system system", + "mkdir /data/ss 0700 system system", + "mkdir /data/system 0775 system system", + "mkdir /data/system/dropbox 0700 system system", + "mkdir /data/system/heapdump 0700 system system", + "mkdir /data/system_de 0770 system system", + "mkdir /data/system_ce 0770 system system", + "mkdir /data/misc_de 01771 system misc", + "mkdir /data/misc_ce 01771 system misc", + "mkdir /data/user 0711 system system", + "mkdir /data/user_de 0711 system system", + "symlink /data/data /data/user/0", + "mkdir /data/media 0770 media_rw media_rw", + "mkdir /data/media/obb 0770 media_rw media_rw", + "mkdir /data/cache 0770 system cache", + "mkdir /data/cache/recovery 0770 system cache", + "mkdir /data/cache/backup_stage 0700 system system", + "mkdir /data/cache/backup 0700 system system", + "setparam sys.use_memfd false", + "chown root system /dev/fscklogs/log", + "chmod 0770 /dev/fscklogs/log", + "chmod 0660 /dev/fuse" + ] + }, { + "name" : "boot", + "cmds" : [ + "write /proc/sys/net/core/xfrm_acq_expires 3600", + "write /proc/sys/vm/overcommit_memory 1", + "write /proc/sys/vm/min_free_order_shift 4", + "chown root system /sys/block/zram0/idle", + "chmod 0664 /sys/block/zram0/idle", + "write /proc/sys/vm/dirty_expire_centisecs 200", + "write /proc/sys/vm/dirty_background_ratio 5", + "chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", + "chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", + "chown system system /sys/class/leds/red/brightness", + "chown system system /sys/class/leds/green/brightness", + "chown system system /sys/class/leds/blue/brightness", + "chown root radio /proc/cmdline", + "setparam net.tcp.default_init_rwnd 60" + ] + }, { + "name" : "param:sys.sysctl.extra_free_kbytes=*", + "condition" : "sys.sysctl.extra_free_kbytes=*", + "cmds" : [ + "write /proc/sys/vm/extra_free_kbytes ${sys.sysctl.extra_free_kbytes}" + ] + }, { + "name" : "param:sys.sysctl.tcp_def_init_rwnd=*", + "condition" : "sys.sysctl.tcp_def_init_rwnd=*", + "cmds" : [ + "write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd}" + ] + }, { + "name" : "param:security.perf_harden=0", + "condition" : "security.perf_harden=0", + "cmds" : [ + "write /proc/sys/kernel/perf_event_paranoid 1", + "write /proc/sys/kernel/perf_event_max_sample_rate ${debug.perf_event_max_sample_rate:-100000}", + "write /proc/sys/kernel/perf_cpu_time_max_percent ${debug.perf_cpu_time_max_percent:-25}", + "write /proc/sys/kernel/perf_event_mlock_kb ${debug.perf_event_mlock_kb:-516}" + ] + }, { + "name" : "param:security.perf_harden=1", + "condition" : "security.perf_harden=1", + "cmds" : [ + "write /proc/sys/kernel/perf_event_paranoid 3" + ] + }, { + "name" : "boot && param:const.debuggable=1", + "condition" : "boot && const.debuggable=1", + "cmds" : [ + "chmod 0773 /data/misc/trace", + "chmod 0775 /data/misc/wmtrace", + "start console" + ] + }, { + "name" : "reboot", + "cmds" : [ + "stopAllServices ", + "sync ", + "umount /vendor", + "umount /data MNT_FORCE", + "sync " + ] + } + ], + "services" : [{ + "name" : "ueventd", + "path" : ["/system/bin/ueventd"], + "socket" : [{ + "name" : "ueventd", + "family" : "AF_NETLINK", + "type" : "SOCK_DGRAM", + "protocol" : "NETLINK_KOBJECT_UEVENT", + "permissions" : "0660", + "uid" : "system", + "gid" : "system", + "option" : [ + "SOCKET_OPTION_PASSCRED", + "SOCKET_OPTION_RCVBUFFORCE", + "SOCK_CLOEXEC", + "SOCK_NONBLOCK" + ] + }], + "critical" : [ 0, 15, 5], + "ondemand" : true, + "sandbox" : 0, + "start-mode" : "condition" + }, { + "name" : "console", + "path" : ["/system/bin/sh"], + "disabled" : 1, + "console" : 1, + "uid" : "root", + "gid" : ["shell", "log", "readproc"], + "start-mode" : "condition" + }, { + "name" : "watchdog_service", + "path" : ["/system/bin/watchdog_service", "10", "20"], + "disabled" : 1, + "uid" : "watchdog", + "gid" : ["watchdog", "log", "readproc"], + "start-mode" : "condition" + }, { + "name" : "misc", + "path" : ["/system/bin/misc_daemon", "--write_logo", "/vendor/logo.rgb"], + "once" : 1 + } + ] +} diff --git a/services/etc/param/ohos.para b/services/etc/param/ohos.para new file mode 100755 index 0000000000000000000000000000000000000000..a1ea2fa28c8c3a90a83190b67453015f471376b5 --- /dev/null +++ b/services/etc/param/ohos.para @@ -0,0 +1,40 @@ +# Copyright (c) 2021 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. + +const.actionable_compatible_property.enabled=false +const.postinstall.fstab.prefix=/system +const.secure=0 +security.perf_harden=1 +const.allow.mock.location=0 +const.debuggable=1 +const.build.characteristics=default +const.product.model=ohos +const.product.name="OpenHarmony 3.2" +const.sandbox=enable +const.product.devicetype=default +const.software.model=default +const.product.manufacturer=default +const.product.brand=default +const.build.product=default +const.product.hardwareversion=default +const.product.bootloader.version=bootloader +const.product.cpu.abilist=default +const.product.software.version=OpenHarmony 5.1.0.47 +const.product.incremental.version=default +const.product.firstapiversion=1 +const.product.build.type=default +const.product.build.user=default +const.product.build.host=default +const.product.build.date=default +const.product.hardwareprofile=default +const.ohos.buildroothash=default diff --git a/services/etc/param/ohos.para.dac b/services/etc/param/ohos.para.dac new file mode 100755 index 0000000000000000000000000000000000000000..d401bcd9a16af9e8a7409a1df7d4c2879a24da9d --- /dev/null +++ b/services/etc/param/ohos.para.dac @@ -0,0 +1,51 @@ +# Copyright (c) 2021 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. + +# default forbid other user to start service +ohos.servicectrl. = system:servicectrl:0775 +ohos.servicectrl.reboot. = system:powerctrl:0775 +ohos.boot. = system:bootctrl:0775 +bootevent. = root:root:0775 +bootevent.param_watcher.started = paramwatcher:paramwatcher:0775 +startup.service.ctl. = system:servicectrl:0775:int +startup.device. = system:powerctrl:0775 + +const.debuggable = root:root:0755 +const.build. = root:root:0775 +const.SystemCapability. = root:root:0775 +const.product. = root:root:0775 +persist.init. = root:root:0775 +startup.appspawn. = root:root:0750 +startup.uevent. = ueventd:ueventd:0775 + +persist.init.debug. = root:root:0775:int +persist.init.bootevent.enable = root:root:0775:bool +persist.appspawn. = root:root:0775 +persist.xts.devattest. = device_attest:device_attest:0775 + +#udid and sn, only read +ohos.boot.sn = root:deviceprivate:0750 +const.product.udid = root:deviceprivate:0750 +const.product.devUdid = root:deviceprivate:0750 + +const.actionable_compatible_property.enabled = root:root:0775 +const.postinstall.fstab.prefix = root:root:0775 +const.secure = root:root:0775 +const.allow.mock.location = root:root:0775 +persist.sys.usb.config = root:root:0775 + +#permission for system +persist.window.boot. = root:system:0775 +#permission for log +debug.bytrace. = root:system:0775 +persist.distributed_hardware.device_manager. = system:system:0775 diff --git a/services/etc/param/ohos.para.size b/services/etc/param/ohos.para.size new file mode 100755 index 0000000000000000000000000000000000000000..be927ab1b0afd231d38c014c6c35dd616066d52d --- /dev/null +++ b/services/etc/param/ohos.para.size @@ -0,0 +1,44 @@ +# 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. + +default_param=4096 +hilog_param=40960 +const_product_param=4096 +startup_param=40960 +persist_param=40960 +const_param=40960 +persist_sys_param=10240 +devinfo_public_param=40960 +sys_param=4096 +bootevent_param=4096 +startup_init_param=81920 +startup_appspawn_param=3145728 +hiviewdfx_profiler_param=4096 +ohos_boot_param = 8192 +bluetooth_param = 8192 +hiviewdfx_hiview_param = 8192 +telephony_param = 20480 +const_telephony_param = 4096 +vendor_camera_param=6144 +edm_writable_param = 4096 +arkui_param = 2048 +wireless_hid_accessory_manager_param = 8192 +debug_param = 4096 +sys_usb_param = 4096 +i18n_param = 4096 +media_library_param = 4096 +samgr_perf_param = 4096 +samgr_writable_param = 10240 +ffrt_param = 4096 +developtools_hdc_auth_param = 4096 +time_param = 2048 diff --git a/services/etc/param/ohos.startup.para b/services/etc/param/ohos.startup.para new file mode 100644 index 0000000000000000000000000000000000000000..1a039250c0fe7772aea825df7ab45e1752b1b1bd --- /dev/null +++ b/services/etc/param/ohos.startup.para @@ -0,0 +1,15 @@ +# 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. + +persist.sys.usb.config=hdc +persist.init.bootevent.enable=true \ No newline at end of file diff --git a/services/etc/param/ohos_const/ohos.para b/services/etc/param/ohos_const/ohos.para new file mode 100755 index 0000000000000000000000000000000000000000..956b24028f195df77d8146265733ffa0311ec41b --- /dev/null +++ b/services/etc/param/ohos_const/ohos.para @@ -0,0 +1,16 @@ +# Copyright (c) 2021 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. +const.ohos.version.security_patch=2025/01/01 +const.ohos.releasetype=Beta1 +const.ohos.apiversion=16 +const.ohos.fullname=OpenHarmony-5.1.0.47 \ No newline at end of file diff --git a/services/etc/passwd b/services/etc/passwd old mode 100755 new mode 100644 index 8c53db54da9794af591cb9265f68debb20681533..9ce0ebf903e6afdfcf195ae3927de730013e016e --- a/services/etc/passwd +++ b/services/etc/passwd @@ -4,7 +4,11 @@ system:x:1000:1000:::/bin/false radio:x:1001:1001:::/bin/false bluetooth:x:1002:1002:::/bin/false graphics:x:1003:1003:::/bin/false +ueventd:x:1004:1004:::/bin/false +file_manager:x:1006:1006:::/bin/false log:x:1007:1007:::/bin/false +user_data_rw:x:1008:1008:::/bin/false +dfs:x:1009:1009:::/bin/false wifi:x:1010:1010:::/bin/false media:x:1013:1013:::/bin/false dhcp:x:1014:1014:::/bin/false @@ -12,14 +16,25 @@ vpn:x:1016:1016:::/bin/false keystore:x:1017:1017:::/bin/false usb:x:1018:1018:::/bin/false drm:x:1019:1019:::/bin/false +gps:x:1021:1021:::/bin/false +location_host:x:1022:1022:::/bin/false media_rw:x:1023:1023:::/bin/false +dsoftbus:x:1024:1024:::/bin/false nfc:x:1027:1027:::/bin/false sdcard_r:x:1028:1028:::/bin/false package_info:x:1032:1032:::/bin/false logd:x:1036:1036:::/bin/false shared_relro:x:1037:1037:::/bin/false -audioserver:x:1041:1041:::/bin/false +audio:x:1041:1041:::/bin/false +intell_voice:x:1042:1042:::/bin/false +media_monitor:x:1043:1043:::/bin/false cameraserver:x:1047:1047:::/bin/false +uiserver:x:1048:1048:::/bin/false +data_reserve:x:1065:1065:::/bin/false +ressched:x:1096:1096:::/bin/false +hiview:x:1201:1201:::/bin/false +faultloggerd:x:1202:1202:::/bin/false +hidumper_service:x:1212:1212:::/bin/false shell:x:2000:2000:::/bin/false cache:x:2001:2001:::/bin/false net_bw_stats:x:3006:3006:::/bin/false @@ -27,5 +42,123 @@ net_bw_acct:x:3007:3007:::/bin/false readproc:x:3009:3009:::/bin/false wakelock:x:3010:3010:::/bin/false uhid:x:3011:3011:::/bin/false +ddms:x:3012:3012:::/bin/false +access_token:x:3020:3020:::/bin/false +blue_host:x:3021:3021:::/bin/false +sample_host:x:3022:3022:::/bin/false +usb_host:x:3023:3023:::/bin/false +usbfn_host:x:3024:3024:::/bin/false +power_host:x:3025:3025:::/bin/false +wifi_host:x:3026:3026:::/bin/false +audio_hdi_server_host:x:3027:3027:::/bin/false +audio_host:x:3127:3127:::/bin/false +camera_host:x:3028:3028:::/bin/false +input_user_host:x:3029:3029:::/bin/false +codec_host:x:3031:3031:::/bin/false +riladapter_host:x:3032:3032:::/bin/false +sensor_host:x:3033:3033:::/bin/false +vibrator_host:x:3034:3034:::/bin/false +light_host:x:3035:3035:::/bin/false +composer_host:x:3036:3036:::/bin/false +dcamera_host:x:3038:3038:::/bin/false +daudio_host:x:3059:3059:::/bin/false +allocator_host:x:3041:3041:::/bin/false +nfc_host:x:3042:3042:::/bin/false +a2dp_host:x:3043:3043:::/bin/false +hdf_devmgr:x:3044:3044:::/bin/false +connected_tag_host:x:3045:3045:::/bin/false +dslm:x:3046:3046:::/bin/false +secure_element_host:x:3047:3047:::/bin/false +device_usage_stats:x:3048:3048:::/bin/false +bgtask:x:3051:3051:::/bin/false +dcamera:x:3052:3052:::/bin/false +dinput:x:3053:3053:::/bin/false +dscreen:x:3054:3054:::/bin/false +daudio:x:3055:3055:::/bin/false +dhardware:x:3056:3056:::/bin/false +installs:x:3060:3060:::/bin/false +vendor_mpp_driver:x:3061:3061:::/bin/false +device_manager:x:3062:3062:::/bin/false +hiprofiler:x:3063:3063:::/bin/false +se_service:x:3064:3064:::/bin/false +deviceauth:x:3333:3333:::/bin/false +huks_server:x:3510:3510:::/bin/false +asset_service:x:6226:6226:::/bin/false +cert_manager_server:x:3515:3515:::/bin/false +device_cert_manager_server:x:3562:3562:::/bin/false +dlp_credential:x:3553:3553:::/bin/false +dlp_permission:x:3019:3019:::/bin/false +security_component:x:3050:3050:::/bin/false +dms:x:5522:5522:::/bin/false +foundation:x:5523:5523:::/bin/false +quickfixserver:x:5524:5524:::/bin/false +cast_engine_service:x:5526:5526:::/bin/false +sharing_service:x:5527:5527:::/bin/false +powermgr:x:5528:5528:::/bin/false +samgr:x:5555:5555:::/bin/false +dbms:x:6000:6000:::/bin/false +update:x:6666:6666:::/bin/false +charger:x:6667:6667:::/bin/false +sensor:x:6688:6688:::/bin/false +input:x:6696:6696:::/bin/false +msdp:x:6699:6699:::/bin/false +av_session:x:6700:6700:::/bin/false +quickfix:x:6701:6666:::/bin/false misc:x:9998:9998:::/bin/false app:x:10000:10000:::/bin/false +useriam:x:1088:1088:::/bin/false +user_auth_host:x:1112:1112:::/bin/false +pin_auth_host:x:1113:1113:::/bin/false +face_auth_host:x:1114:1114:::/bin/false +fingerprint_auth_host:x:1115:1115:::/bin/false +backup:x:1089:1089:::/bin/false +storage_manager:x:1090:1090:::/bin/false +net_manager:x:1099:1099:::/bin/false +netsysnative:x:1098:1098:::/bin/false +netsys_socket:x:1097:1097:::/bin/false +edm:x:3057:3057:::/bin/false +account:x:3058:3058:::/bin/false +download:x:3815:3815:::/bin/false +pasteboard:x:3816:3816:::/bin/false +wallpaper:x:3817:3817:::/bin/false +screenlock:x:3818:3818:::/bin/false +time:x:3819:3819:::/bin/false +inputmethod:x:3820:3820:::/bin/false +watchdog:x:1100:1100:::/bin/false +paramwatcher:x:1101:1101:::/bin/false +deviceinfo:x:1102:1102:::/bin/false +accessibility:x:1103:1103:::/bin/false +motion_host:x:3065:3065:::/bin/false +memmgr:x:1111:1111:::/bin/false +ispserver:x:3821:3821:::/bin/false +dfs_share:x:3822:3822:::/bin/false +print:x:3823:3823:::/bin/false +cups:x:3824:3824:::/bin/false +security_guard:x:3520:3520:::/bin/false +security_collector:x:3521:3521:::/bin/false +tee:x:6668:6668:::/bin/false +dsserver:x:3068:3068:::/bin/false +device_attest:x:3049:3049:::/bin/false +dev_dma_heap:x:3070:3070:::/bin/false +dev_memory:x:3071:3071:::/bin/false +dev_lcd_backlight:x:3072:3072:::/bin/false +dev_vibrator:x:3080:3080:::/bin/false +vcodec:x:3073:3073:::/bin/false +dev_camera:x:3090:3090:::/bin/false +servicerouter:x:6066:6066:::/bin/false +nwebspawn:x:3081:3081:::/bin/false +oaid_service:x:6101:6101:::/bin/false +code_sign:x:3074:3074:::/bin/false +el5_filekey_manager:x:3077:3077:::/bin/false +hdf_ext_devmgr:x:3085:3085:::/bin/false +intell_voice_host:x:3100:3100:::/bin/false +huawei_id:x:7008:7008:::/bin/false +drmserver:x:1077:1077:::/bin/false +clearplay_host:x:3078:3078:::/bin/false +wiseplay_host:x:3079:3079:::/bin/false +i18n:x:3013:3013:::/bin/false +testserver:x:3500:3500:::/bin/false +app_domain_verify:x:3111:3111:::/bin/false +compiler_service:x:5300:5300:::/bin/false +sandbox_manager:x:3076:3076:::/bin/false +app_fwk_update:x:3350:3350:::/bin/false diff --git a/services/etc/passwd_appender/passwd_appender.gni b/services/etc/passwd_appender/passwd_appender.gni new file mode 100755 index 0000000000000000000000000000000000000000..1dad7cfaac9a5dee4148edd0715723798a5e74a0 --- /dev/null +++ b/services/etc/passwd_appender/passwd_appender.gni @@ -0,0 +1,107 @@ +# 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. + +import("//build/config/python.gni") +import("//build/templates/common/copy.gni") + +# Append something (files or lines) to a file and install it. +# +# Variables: +# source: file to be appended (Required) +# deps: some targets deps on (Optional) +# output: the final install file name (Optional); +# If not set, it will install with the source file name +# ranges: uid/gid value range (Required) +# +# Example: +# ohos_passwd_appender("passwd") { +# sources = ["//base/startup/init/services/etc/passwd", +# "//base/startup/init/services/etc/passwd1", +# "//base/startup/init/services/etc/passwd2" +# ] +# ranges = ["0-6999", "7000-8000", "8001-9000"] +# output = "//base/startup/init/services/etc/passwd" +# } +# It will append files to source passwd file after deps targets +# +template("ohos_passwd_appender") { + assert(defined(invoker.sources), "source must be defined.") + assert(defined(invoker.ranges), "ranges must be defined.") + assert(defined(invoker.output), "output must be defined.") + + _passwd_appender_target = "${target_name}_passwd_fixed" + _final_install_name = get_path_info(invoker.output, "file") + tmp_install_file = target_gen_dir + "/${target_name}.tmp" + + passwd_file_list = [] + foreach(file, invoker.sources) { + passwd_file_list += [ rebase_path(file, root_build_dir) ] + } + input_passwd_files = string_join(":", passwd_file_list) + input_ranges = string_join(":", invoker.ranges) + + action_with_pydeps(_passwd_appender_target) { + script = + "//base/startup/init/services/etc/passwd_appender/passwd_appender.py" + depfile = "${target_gen_dir}/${target_name}.d" + if (defined(invoker.deps)) { + deps = invoker.deps + } else { + deps = [] + } + args = [ + "--output", + rebase_path(tmp_install_file, root_build_dir), + "--source-file", + input_passwd_files, + "--input-ranges", + input_ranges, + "--depfile", + rebase_path(depfile, root_build_dir), + ] + outputs = [ tmp_install_file ] + } + + ohos_copy(target_name) { + deps = [ ":$_passwd_appender_target" ] + forward_variables_from(invoker, + [ + "testonly", + "visibility", + + "deps", + "public_configs", + "subsystem_name", + "part_name", + + # For generate_module_info + "install_images", + "module_install_dir", + "relative_install_dir", + "symlink_target_name", + + # Open source license related + "license_file", + "license_as_sources", + ]) + sources = [ tmp_install_file ] + outputs = [ "${target_out_dir}/${target_name}/${_final_install_name}" ] + module_type = "etc" + install_enable = true + module_source_dir = "${target_out_dir}/${target_name}" + module_install_name = _final_install_name + if (defined(invoker.install_enable)) { + install_enable = invoker.install_enable + } + } +} diff --git a/services/etc/passwd_appender/passwd_appender.py b/services/etc/passwd_appender/passwd_appender.py new file mode 100755 index 0000000000000000000000000000000000000000..249da50f67314c28d12c814252527edc0b93f555 --- /dev/null +++ b/services/etc/passwd_appender/passwd_appender.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# 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. + +import optparse +import os +import sys +import stat +import json +import operator + + +def parse_args(args): + from scripts.util import build_utils # noqa: E402 + + args = build_utils.expand_file_args(args) + + parser = optparse.OptionParser() + build_utils.add_depfile_option(parser) + parser.add_option('--output', help='the final install file name') + parser.add_option('--source-file', help='source passwd files') + parser.add_option('--append-file', action="append", type="string", dest="files", help='appended files') + parser.add_option('--append-line', action="append", type="string", dest="lines", help='appended lines') + parser.add_option('--input-ranges', help="uid/gid value range") + + options, _ = parser.parse_args(args) + return options + + +def load_group_file_as_dict(source_f): + source_dict = {} + for line in source_f: + arr = line.strip().split(":") + if arr: + key = arr[0] + passwd_gid_value = [arr[1], arr[2]] + value = [':'.join(passwd_gid_value), arr[3]] + source_dict[key] = value + return source_dict + + +def insert_append_user_value(key, arr, source_dict): + if source_dict[key][1] and arr[3]: + if arr[3] not in source_dict[key][1]: + user_value = [source_dict[key][1], arr[3]] + source_dict[key][1] = ','.join(user_value) + elif source_dict[key][1] == " " and arr[3]: + source_dict[key][1] = arr[3] + + +def get_append_value(src, source_dict): + for line in src: + if line != "\n": + arr = line.strip().split(":") + key = arr[0] + passwd_gid_value = [arr[1], arr[2]] + if len(arr) > 3: + value = [':'.join(passwd_gid_value), arr[3]] + else: + value = [':'.join(passwd_gid_value), " "] + if key in source_dict.keys(): + insert_append_user_value(key, arr, source_dict) + else: + source_dict[key] = value + + +def append_group_by_lines(options, source_dict): + for line in options.lines: + arr = line.strip().split(":") + key = arr[0] + passwd_gid_value = [arr[1], arr[2]] + if len(arr) > 3: + value = [':'.join(passwd_gid_value), arr[3]] + else: + value = [':'.join(passwd_gid_value), " "] + if key in source_dict.keys(): + insert_append_user_value(key, arr, source_dict) + else: + source_dict[key] = value + + +def append_group_by_files(options, source_dict): + for append_f in options.files: + with open(append_f, 'r') as src: + get_append_value(src, source_dict) + + +def append_group_files(target_f, options): + with open(options.source_file, 'r') as source_f: + source_dict = load_group_file_as_dict(source_f) + if options.files: + append_group_by_files(options, source_dict) + if options.lines: + append_group_by_lines(options, source_dict) + for item in source_dict: + target_f.write(f"{item}:{':'.join(source_dict[item])}\n") + + +def handle_passwd_info(passwd_info, limits): + is_passed = True + name = passwd_info[0].strip() + gid = int(passwd_info[3], 10) + uid = int(passwd_info[2], 10) + if gid >= int(limits[0]) and gid <= int(limits[1]): + pass + else: + is_passed = False + log_str = "error: name={} gid={} is not in range {}".format(name, gid, limits) + print(log_str) + + if uid >= int(limits[0]) and uid <= int(limits[1]): + pass + else: + is_passed = False + log_str = "error: name={} uid={} is not in range {}".format(name, gid, limits) + print(log_str) + return is_passed + + +def check_passwd_file(file_name, limits): + is_passed = True + with open(file_name, encoding='utf-8') as fp: + line = fp.readline() + while line : + if line.startswith("#") or len(line) < 3: + line = fp.readline() + continue + passwd_info = line.strip("\n").split(":") + if len(passwd_info) < 4: + line = fp.readline() + continue + if not handle_passwd_info(passwd_info, limits): + is_passed = False + line = fp.readline() + return is_passed + + +def load_file(file_name, limit): + + if not os.path.exists(file_name): + print("error: %s is not exit", file_name) + return False + is_passed = True + limits = limit.split("-") + try: + is_passed = check_passwd_file(file_name, limits) + except: + raise Exception("Exception in reading passwd, file name:", file_name) + return is_passed + + +def append_passwd_files(target_f, options): + # Read source file + file_list = options.source_file.split(":") + range_list = options.input_ranges.split(":") + + for i, file in enumerate(file_list): + if i >= len(range_list): + print("error: %s is error", file) + return + if not load_file(file, range_list[i]): + # check gid/uid Exception log: raise Exception("Exception, check passwd file error, ", file) + print("error: heck passwd file error, file path: ", file) + pass + try: + with open(file, 'r') as source_f: + source_contents = source_f.read() + target_f.write(source_contents) + except: + raise Exception("Exception in appending passwd, file name:", file) + + +def main(args): + sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, + os.pardir, os.pardir, os.pardir, os.pardir, "build")) + from scripts.util import build_utils # noqa: E402 + + options = parse_args(args) + if options.files: + depfile_deps = ([options.source_file] + options.files) + else: + depfile_deps = ([options.source_file]) + + with os.fdopen(os.open(options.output, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 'w') as target_f: + if operator.contains(options.source_file, "group"): + append_group_files(target_f, options) + else: + append_passwd_files(target_f, options) + + build_utils.write_depfile(options.depfile, + options.output, depfile_deps, add_pydeps=False) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/services/etc/passwd_appender/passwd_appender.pydeps b/services/etc/passwd_appender/passwd_appender.pydeps new file mode 100755 index 0000000000000000000000000000000000000000..a36a2e7925b5ea24577862e472d9e00ffc93220b --- /dev/null +++ b/services/etc/passwd_appender/passwd_appender.pydeps @@ -0,0 +1,9 @@ +# Generated by running: +# build/print_python_deps.py --root base/startup/init/services/etc/passwd_appender --output base/startup/init/services/etc/passwd_appender/passwd_appender.pydeps base/startup/init/services/etc/passwd_appender/passwd_appender.py +../../../../../../build/gn_helpers.py +../../../../../../build/scripts/__init__.py +../../../../../../build/scripts/util/__init__.py +../../../../../../build/scripts/util/build_utils.py +../../../../../../build/scripts/util/md5_check.py +../../../../../../build/scripts/util/pycache.py +passwd_appender.py diff --git a/services/etc/ueventd.cfg b/services/etc/ueventd.cfg new file mode 100644 index 0000000000000000000000000000000000000000..68a1a5d6ddafd52ea6214aca8689a7b83301cbca --- /dev/null +++ b/services/etc/ueventd.cfg @@ -0,0 +1,29 @@ +{ + "services" : [{ + "name" : "ueventd", + "path" : ["/system/bin/ueventd"], + "uid" : "ueventd", + "gid" : ["ueventd"], + "socket" : [{ + "name" : "ueventd", + "family" : "AF_NETLINK", + "type" : "SOCK_DGRAM", + "protocol" : "NETLINK_KOBJECT_UEVENT", + "permissions" : "0660", + "uid" : "system", + "gid" : "system", + "option" : [ + "SOCKET_OPTION_PASSCRED", + "SOCKET_OPTION_RCVBUFFORCE", + "SOCK_CLOEXEC", + "SOCK_NONBLOCK" + ] + }], + "caps" : ["DAC_OVERRIDE", "MKNOD", "CHOWN", "FOWNER"], + "ondemand" : true, + "sandbox" : 0, + "start-mode" : "condition", + "secon" : "u:r:ueventd:s0" + } + ] +} diff --git a/services/etc/watchdog.cfg b/services/etc/watchdog.cfg new file mode 100644 index 0000000000000000000000000000000000000000..e6c541be6a85478bc9d7b786f0a153c3bce15dbd --- /dev/null +++ b/services/etc/watchdog.cfg @@ -0,0 +1,13 @@ +{ + "services" : [{ + "name" : "watchdog_service", + "start-mode" : "condition", + "path" : ["/system/bin/watchdog_service", "10", "20"], + "disabled" : 1, + "sandbox" : 0, + "uid" : "watchdog", + "gid" : ["watchdog", "log", "readproc"], + "secon" : "u:r:watchdog_service:s0" + } + ] +} diff --git a/services/etc_lite/group b/services/etc_lite/group new file mode 100755 index 0000000000000000000000000000000000000000..f0509267d5e8f478b2a4b0f8b74b76f41a35a39c --- /dev/null +++ b/services/etc_lite/group @@ -0,0 +1,9 @@ +root:x:0: +bin:x:2: +system:x:1000: +servicectrl:x:1050:root,shell,system,samgr,hdf_devmgr +shell:x:2000: +faultloggerd:x:1202:root,system +watchdog:x:2001:root +ueventd:x:2002:root +device_manager:x:3062: diff --git a/services/etc_lite/param/ohos_const/ohos.para b/services/etc_lite/param/ohos_const/ohos.para new file mode 100755 index 0000000000000000000000000000000000000000..bc001dc393ae5e9d3b16e1dd52ff05d47ba8dc6e --- /dev/null +++ b/services/etc_lite/param/ohos_const/ohos.para @@ -0,0 +1,17 @@ +# Copyright (c) 2021 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. + +const.ohos.releasetype=Beta1 +const.ohos.apiversion=16 +const.ohos.version.security_patch=2025/01/01 +const.ohos.fullname=OpenHarmony-5.1.0.47 \ No newline at end of file diff --git a/services/etc_lite/passwd b/services/etc_lite/passwd new file mode 100755 index 0000000000000000000000000000000000000000..7a640c28454d8e64974784380a0d5b7529ca0e6c --- /dev/null +++ b/services/etc_lite/passwd @@ -0,0 +1,8 @@ +root:x:0:0:::/bin/false +bin:x:2:2:::/bin/false +system:x:1000:1000:::/bin/false +shell:x:2000:2000:::/bin/false +faultloggerd:x:1202:1202:::/bin/false +watchdog:x:2001:2001:::/bin/false +ueventd:x:2002:2002:::/bin/false +device_manager:x:3062:3062:::/bin/false diff --git a/services/include/init_service.h b/services/include/init_service.h deleted file mode 100644 index fd269c23887f201e354d8eafd671c7ea27068b7b..0000000000000000000000000000000000000000 --- a/services/include/init_service.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2020 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_SERVICE_H -#define BASE_STARTUP_INITLITE_SERVICE_H - -#include -#include "init_cmds.h" -#include "init_service_socket.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -// return value -#define SERVICE_FAILURE (-1) -#define SERVICE_SUCCESS 0 - -// service attributes -#define SERVICE_ATTR_INVALID 0x001 // option invalid -#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits -#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future -#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap -#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash -#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes -#define SERVICE_ATTR_DISABLED 0x040 // disabled -#define SERVICE_ATTR_CONSOLE 0x080 // console - -#define MAX_SERVICE_NAME 32 -#define MAX_WRITEPID_FILES 100 - -#define CAP_NUM 2 - -#define SERVICES_ARR_NAME_IN_JSON "services" - -typedef struct { - uid_t uID; - gid_t *gIDArray; - int gIDCnt; - unsigned int *caps; - unsigned int capsCnt; -} Perms; - -struct OnRestartCmd { - CmdLine *cmdLine; - int cmdNum; -}; - -typedef struct { - char name[MAX_SERVICE_NAME + 1]; - char** pathArgs; - int pathArgsCnt; - int pid; - int crashCnt; - time_t firstCrashTime; - int criticalCrashCnt; // count for critical - time_t firstCriticalCrashTime; // record for critical - char *writepidFiles[MAX_WRITEPID_FILES]; - unsigned int attribute; - int importance; - Perms servPerm; - struct OnRestartCmd *onRestart; - struct ServiceSocket *socketCfg; -} Service; - -int ServiceStart(Service *service); -int ServiceStop(Service *service); -void ServiceReap(Service *service); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif - -#endif // BASE_STARTUP_INITLITE_SERVICE_H diff --git a/services/include/param/init_param.h b/services/include/param/init_param.h deleted file mode 100644 index dfdd52b0b966dbabf63d928398f38c46e968330c..0000000000000000000000000000000000000000 --- a/services/include/param/init_param.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2020 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_INIT_PARAM_H -#define BASE_STARTUP_INIT_PARAM_H -#include -#include "cJSON.h" -#include "sys_param.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -typedef enum { - EVENT_PROPERTY, // 参数修改事件 - EVENT_BOOT -} EventType; - -/** - * Init 接口 - * 初始化参数服务 - * - */ -void InitParamService(); - -/** - * Init 接口 - * 启动参数服务,在main启动的最后调用,阻赛当前线程 - * - */ -int StartParamService(); - -/** - * Init 接口 - * 停止参数服务 - * - */ -void StopParamService(); - -/** - * Init 接口 - * 加载默认的参数值 - * - */ -int LoadDefaultParams(const char *fileName); - -/** - * Init 接口 - * 安全使用,加载参数的信息,包括selinux label 等 - * - */ -int LoadParamInfos(const char *fileName); - -/** - * Init 接口 - * 加载默认参数。 - * - */ -int LoadPersistParams(); - -/** - * Init 接口 - * 设置参数,主要用于其他进程使用,通过管道修改参数 - * - */ -int SystemWriteParam(const char *name, const char *value); - -/** - * Init 接口 - * 查询参数。 - * - */ -int SystemReadParam(const char *name, char *value, unsigned int *len); - -/** - * 对Init接口 - * 触发一个trigger操作。 - * - */ -void PostTrigger(EventType type, const char *content, u_int32_t contentLen); - -/** - * 对Init接口 - * 触发一个参数trigger操作。 - * - */ -void PostParamTrigger(const char *name, const char *value); - -/** - * 对Init接口 - * 解析trigger文件。 - * - */ -int ParseTriggerConfig(cJSON *fileRoot); - -/** - * 对Init接口 - * 按名字执行对应的trigger。 - * - */ -void DoTriggerExec(const char *content); - -/** - * 对Init接口 - * 按名字执行对应的trigger。 - * - */ -int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif -#endif \ No newline at end of file diff --git a/services/src/init_adapter.c b/services/init/adapter/init_adapter.c similarity index 59% rename from services/src/init_adapter.c rename to services/init/adapter/init_adapter.c index 2788e646fba3d7f7daeb4b980d9f6c9c78456e92..f086b7abd4306cbbb9bd39d12b1ceecfa46492ff 100644 --- a/services/src/init_adapter.c +++ b/services/init/adapter/init_adapter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,37 +12,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "init_adapter.h" #include -#include -#include +#include #include -#include +#include +#if defined OHOS_LITE && !defined __LINUX__ +#include +#else +#include +#endif + #if ((defined __LINUX__) || (!defined OHOS_LITE)) #include #endif -#ifdef __LINUX__ -#include "init_signal_handler.h" -#endif #include "init_log.h" -void RebootSystem() +int KeepCapability(const Service *service) { - int ret = reboot(RB_AUTOBOOT); - if (ret != 0) { - INIT_LOGE("reboot failed! syscall ret %d, err %d.", ret, errno); - } -} - -int KeepCapability() -{ -#if ((defined __LINUX__) || (!defined OHOS_LITE)) +#ifdef __LINUX__ if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) { + INIT_LOGE("prctl PR_SET_SECUREBITS failed: %d", errno); + return -1; + } + return 0; +#else +#ifndef OHOS_LITE + if (service->attribute & SERVICE_ATTR_SETUID) { + if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) { + INIT_LOGE("prctl PR_SET_SECUREBITS failed: %d", errno); + return -1; + } + return 0; + } + if (prctl(PR_SET_SECUREBITS, SECBIT_KEEP_CAPS | SECBIT_KEEP_CAPS_LOCKED)) { INIT_LOGE("prctl PR_SET_SECUREBITS failed: %d", errno); return -1; } +#endif #endif return 0; } @@ -58,7 +66,33 @@ int SetAmbientCapability(int cap) return 0; } -void ExecuteRcs() +#if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX) +static pid_t g_waitPid = -1; +static sem_t *g_waitSem = NULL; +static void SignalRegWaitSem(pid_t waitPid, sem_t *waitSem) +{ + g_waitPid = waitPid; + g_waitSem = waitSem; +} + +void CheckWaitPid(pid_t sigPID) +{ + if (g_waitPid == sigPID && g_waitSem != NULL) { + if (sem_post(g_waitSem) != 0) { + INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno); + } + g_waitPid = -1; + g_waitSem = NULL; + } +} +#else +void CheckWaitPid(pid_t sigPID) +{ + (void)(sigPID); +} +#endif + +void SystemExecuteRcs(void) { #if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX) pid_t retPid = fork(); @@ -90,4 +124,3 @@ void ExecuteRcs() } #endif } - diff --git a/services/include/device.h b/services/init/include/device.h similarity index 84% rename from services/include/device.h rename to services/init/include/device.h index beef68ff448588e6cd95ddfec04ecc422d830d43..9729572a32e9f1d50367661ed747b8eb11db60cd 100644 --- a/services/include/device.h +++ b/services/init/include/device.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,26 +12,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef BASE_STARTUP_INITLITE_DEVICE_H #define BASE_STARTUP_INITLITE_DEVICE_H +#include #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -#include #define DEV_KMSG_MINOR 11 #define DEV_NULL_MINOR 3 #define DEV_RANDOM_MINOR 8 #define DEV_URANDOM_MINOR 9 -void MountBasicFs(void); -void CreateDeviceNode(void); -int MakeSocketDir(const char *path, mode_t mode); -void CloseStdio(void); +void CreateFsAndDeviceNode(void); #ifdef __cplusplus #if __cplusplus diff --git a/services/init/include/fd_holder_service.h b/services/init/include/fd_holder_service.h new file mode 100644 index 0000000000000000000000000000000000000000..5b23bfdc72f67bf031d9246e860ade2a6ee9cfee --- /dev/null +++ b/services/init/include/fd_holder_service.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 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_FD_HOLDER_SERVICE_H +#define BASE_STARTUP_INITLITE_FD_HOLDER_SERVICE_H +#ifdef __cplusplus +extern "C" { +#endif +void RegisterFdHoldWatcher(int sock); +#ifdef __cplusplus +} +#endif +#endif // BASE_STARTUP_INITLITE_FD_HOLDER_SERVICE_H diff --git a/services/init/include/init.h b/services/init/include/init.h new file mode 100644 index 0000000000000000000000000000000000000000..d2cc438ff0440fea71692fd2ebaf2a0ea7a9dc00 --- /dev/null +++ b/services/init/include/init.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021 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_INIT_H +#define BASE_STARTUP_INIT_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef PARAM_VALUE_LEN_MAX +#define PARAM_VALUE_LEN_MAX 96 +#endif + +#define PROCESS_EXIT_CODE 0x7f // 0x7f: user specified +// kit framework +#define DEFAULT_UID_KIT_FRAMEWORK 3 +// max length of one param/path +#define MAX_ONE_ARG_LEN 200 +#define FD_HOLDER_BUFFER_SIZE 4096 + +#define UNUSED(x) (void)(x) + +#ifndef STARTUP_INIT_TEST +#ifndef INIT_STATIC +#define INIT_STATIC static +#endif +#else +#ifndef INIT_STATIC +#define INIT_STATIC +#endif +#endif + +void SystemInit(void); +void LogInit(void); +void SystemPrepare(long long uptime); +void SystemConfig(const char *uptime); +void SystemRun(void); +void SystemExecuteRcs(void); + +void ParseInitCfgByPriority(void); +int ParseInitCfg(const char *configFile, void *context); +void ReadConfig(void); +void SignalInit(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_INIT_H diff --git a/services/include/init_adapter.h b/services/init/include/init_adapter.h similarity index 65% rename from services/include/init_adapter.h rename to services/init/include/init_adapter.h index ea02c1e06b7fd1ef97c7f649080263cc3e079e13..c556619dd1ff0bce75268387afd4acde4e11e826 100644 --- a/services/include/init_adapter.h +++ b/services/init/include/init_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,16 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef BASE_STARTUP_INITLITE_ADAPTER_H #define BASE_STARTUP_INITLITE_ADAPTER_H - -#if defined OHOS_LITE && !defined __LINUX__ -#include -#else -#include -#endif - +#include +#include "init_service.h" #ifdef __cplusplus #if __cplusplus extern "C" { @@ -31,27 +25,26 @@ extern "C" { #ifndef OHOS_LITE /* Control the ambient capability set */ #ifndef PR_CAP_AMBIENT -#define PR_CAP_AMBIENT 47 +#define PR_CAP_AMBIENT 47 #endif #ifndef PR_CAP_AMBIENT_IS_SET -#define PR_CAP_AMBIENT_IS_SET 1 +#define PR_CAP_AMBIENT_IS_SET 1 #endif #ifndef PR_CAP_AMBIENT_RAISE -#define PR_CAP_AMBIENT_RAISE 2 +#define PR_CAP_AMBIENT_RAISE 2 #endif #ifndef PR_CAP_AMBIENT_LOWER -#define PR_CAP_AMBIENT_LOWER 3 +#define PR_CAP_AMBIENT_LOWER 3 #endif #ifndef PR_CAP_AMBIENT_CLEAR_ALL -#define PR_CAP_AMBIENT_CLEAR_ALL 4 +#define PR_CAP_AMBIENT_CLEAR_ALL 4 #endif -extern int capset(void *a, void *b); #endif -void RebootSystem(); -int KeepCapability(); +int KeepCapability(const Service *service); int SetAmbientCapability(int cap); -void ExecuteRcs(); +void ExecuteRcs(void); +void CheckWaitPid(pid_t sigPID); #ifdef __cplusplus #if __cplusplus @@ -59,4 +52,4 @@ void ExecuteRcs(); #endif #endif -#endif // BASE_STARTUP_INITLITE_ADAPTER_H \ No newline at end of file +#endif // BASE_STARTUP_INITLITE_ADAPTER_H \ No newline at end of file diff --git a/services/init/include/init_cmdexecutor.h b/services/init/include/init_cmdexecutor.h new file mode 120000 index 0000000000000000000000000000000000000000..4c78ca360bf66e9c6413d05772d9de8099e94b72 --- /dev/null +++ b/services/init/include/init_cmdexecutor.h @@ -0,0 +1 @@ +../../../interfaces/innerkits/init_module_engine/include/init_cmdexecutor.h \ No newline at end of file diff --git a/services/init/include/init_cmds.h b/services/init/include/init_cmds.h new file mode 100644 index 0000000000000000000000000000000000000000..474b8aa7bce90bfabd91d3edce42e324f57e3a6c --- /dev/null +++ b/services/init/include/init_cmds.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020-2021 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_INIT_CMDS_H +#define BASE_STARTUP_INIT_CMDS_H +#include +#include +#include +#include +#include +#include + +#include "cJSON.h" +#include "init_cmdexecutor.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) // mkdir, default mode +#define SPACES_CNT_IN_CMD_MAX 10 // mount, max number of spaces in cmdline +#define SPACES_CNT_IN_CMD_MIN 2 // mount, min number of spaces in cmdline + +#define LOADCFG_BUF_SIZE 128 // loadcfg, max buffer for one cmdline +#define LOADCFG_MAX_FILE_LEN 51200 // loadcfg, max file size is 50K +#define LOADCFG_MAX_LOOP 20 // loadcfg, to prevent to be trapped in infite loop +#define OCTAL_TYPE 8 // 8 means octal to decimal +#define MAX_BUFFER 256UL +#define AUTHORITY_MAX_SIZE 128 + +#define MAX_CMD_NAME_LEN 32 +#define MAX_CMD_CONTENT_LEN 256 +#define MAX_CMD_CNT_IN_ONE_JOB 200 +#define MAX_COPY_BUF_SIZE 256 +#define DEFAULT_COPY_ARGS_CNT 2 + +#define OPTIONS_SIZE 128 + +#define SUPPORT_MAX_ARG_FOR_EXEC 10 +// one cmd line +typedef struct { + int cmdIndex; + char cmdContent[MAX_CMD_CONTENT_LEN + 1]; +} CmdLine; + +typedef struct { + int cmdNum; + CmdLine cmds[0]; +} CmdLines; + +struct CmdArgs { + int argc; + char *argv[0]; +}; + +struct CmdTable { + char name[MAX_CMD_NAME_LEN]; + unsigned char minArg; + unsigned char maxArg; + unsigned char careContext; + void (*DoFuncion)(const struct CmdArgs *ctx); +}; + +typedef enum _initContextType { + INIT_CONTEXT_CHIPSET, + INIT_CONTEXT_MAIN, +} InitContextType; + +typedef struct { + InitContextType type; +} ConfigContext; + +int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen); +const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount); +void FreeCmdArg(struct CmdArgs *cmd); +// exec in context, if context == null, exec in current context +void DoCmdByIndex(int index, const char *cmdContent, const ConfigContext *context); +const char *GetMatchCmd(const char *cmdStr, int *index); +const char *GetCmdKey(int index); +const struct CmdTable *GetCmdTable(int *number); +int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines); +const struct CmdTable *GetCmdByName(const char *name); +void ExecReboot(const char *value); +char *BuildStringFromCmdArg(const struct CmdArgs *ctx, int startIndex); +void ExecCmd(const struct CmdTable *cmd, const char *cmdContent); +int SetFileCryptPolicy(const char *dir); + +void OpenHidebug(const char *name); + +void StopSubInit(pid_t pid); +int ExecuteCmdInSubInit(const ConfigContext *context, const char *name, const char *cmdContent); +int SetSubInitContext(const ConfigContext *context, const char *service); +int CheckExecuteInSubInit(const ConfigContext *context); + +// exec in context, if context == null, exec in current context +void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context); +const char *PluginGetCmdIndex(const char *cmdStr, int *index); +const char *GetPluginCmdNameByIndex(int index); +int AddCareContextCmdExecutor(const char *cmdName, CmdExecutor executor); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_INITLITE_CMDS_H diff --git a/services/include/init_reboot.h b/services/init/include/init_control_fd_service.h similarity index 78% rename from services/include/init_reboot.h rename to services/init/include/init_control_fd_service.h index 181d811327ea1f4dfeb1bbf2c32b95ea8527687f..a383e747f4f9005370aeff597768754255e0978e 100644 --- a/services/include/init_reboot.h +++ b/services/init/include/init_control_fd_service.h @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2020 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 INIT_REBOOT_H -#define INIT_REBOOT_H - -void DoReboot(const char *value); - -#endif +/* + * 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 CONTROL_FD_SERVICE_H +#define CONTROL_FD_SERVICE_H + +void InitControlFd(void); + +#endif \ No newline at end of file diff --git a/services/init/include/init_group_manager.h b/services/init/include/init_group_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..b7be77216e0054a45e72b557c30b8b279fcc7fd8 --- /dev/null +++ b/services/init/include/init_group_manager.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020-2021 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 STARTUP_INIT_GROUP_MANAGER_H +#define STARTUP_INIT_GROUP_MANAGER_H +#include +#include +#include "init_service.h" +#include "init_hashmap.h" +#include "init_cmdexecutor.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define GROUP_IMPORT_MAX_LEVEL 5 +#define GROUP_NAME_MAX_LENGTH 64 +#define GROUP_HASHMAP_BUCKET 32 + +#define GROUP_DEFAULT_PATH STARTUP_INIT_UT_PATH"/system/etc" +#define BOOT_GROUP_NAME "bootgroup" +#define BOOT_GROUP_DEFAULT "device.boot.group" + +typedef enum { + GROUP_BOOT, + GROUP_CHARGE, + GROUP_UNKNOW +} InitGroupType; + +typedef enum { + NODE_TYPE_JOBS, + NODE_TYPE_SERVICES, + NODE_TYPE_PLUGINS, + NODE_TYPE_CMDS, + NODE_TYPE_GROUPS, + NODE_TYPE_MAX +} InitNodeType; + +typedef struct InitGroupNode_ { + struct InitGroupNode_ *next; + HashNode hashNode; + unsigned char type; + union { + Service *service; + PluginCmd *cmd; + } data; + char name[0]; +} InitGroupNode; + +typedef struct { + uint8_t initFlags; + InitGroupType groupMode; + InitGroupNode *groupNodes[NODE_TYPE_MAX]; + HashMapHandle hashMap[NODE_TYPE_GROUPS]; + char groupModeStr[GROUP_NAME_MAX_LENGTH]; + ServiceSocket *serviceSocketNode; +} InitWorkspace; + +void InitServiceSpace(void); +void CloseServiceSpace(void); +int InitParseGroupCfg(void); + +ServiceSocket *GetOnDemandSocketList(void); +void AddOnDemandSocket(ServiceSocket *socketNode); +void RemoveOnDemandSocket(ServiceSocket *sockopt); +int GenerateHashCode(const char *key); +InitGroupNode *AddGroupNode(int type, const char *name); +InitGroupNode *GetGroupNode(int type, const char *name); +InitGroupNode *GetNextGroupNode(int type, const InitGroupNode *curr); +void DelGroupNode(int type, const char *name); +int CheckNodeValid(int type, const char *name); +HashMapHandle GetGroupHashMap(int type); +#ifdef STARTUP_INIT_TEST +InitWorkspace *GetInitWorkspace(void); +#endif +int GetBootModeFromMisc(void); +void clearMisc(void); +void ReleaseCmd(PluginCmd *cmd); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // STARTUP_INIT_GROUP_MANAGER_H diff --git a/services/include/init_jobs.h b/services/init/include/init_jobs_internal.h similarity index 54% rename from services/include/init_jobs.h rename to services/init/include/init_jobs_internal.h index 7c7ffaed5cd53b53715f2317d128f7a9594f1e48..775a23b024116cd8abdadc34afb231f6b03ba3f4 100644 --- a/services/include/init_jobs.h +++ b/services/init/include/init_jobs_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,12 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#ifndef BASE_STARTUP_INITLITE_JOBS_H -#define BASE_STARTUP_INITLITE_JOBS_H - -#include "init_cmds.h" +#ifndef BASE_STARTUP_INITLITE_JOBS_INTERNAL_H +#define BASE_STARTUP_INITLITE_JOBS_INTERNAL_H #include "cJSON.h" +#include "init_cmds.h" #ifdef __cplusplus #if __cplusplus @@ -30,18 +28,28 @@ extern "C" { // one job, could have many cmd lines typedef struct { char name[MAX_JOB_NAME_LEN + 1]; - int cmdLinesCnt; - CmdLine* cmdLines; + CmdLines *cmdLines; } Job; -void ParseAllJobs(const cJSON* fileRoot); -void DoJob(const char* jobName); -void ReleaseAllJobs(); -void DumpAllJobs(); +void ParseAllJobs(const cJSON *fileRoot, const ConfigContext *context); +void DoJob(const char *jobName); +void ReleaseAllJobs(void); +void DumpAllJobs(void); + +int DoJobNow(const char *jobName); + +#define INIT_CONFIGURATION_FILE "/etc/init.cfg" +#define OTHER_CFG_PATH "/system/etc/init" +#define OTHER_CHARGE_PATH "/system/etc/charger" +#define INIT_RESCUE_MODE_PATH "/system/etc/rescue" +#define MAX_PATH_ARGS_CNT 20 + +void ReadConfig(void); + #ifdef __cplusplus #if __cplusplus } #endif #endif -#endif // BASE_STARTUP_INITLITE_JOBS_H +#endif // BASE_STARTUP_INITLITE_JOBS_INTERNAL_H diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h new file mode 100644 index 0000000000000000000000000000000000000000..422ee1fdcef59e5d87e31e45339e489bcef54191 --- /dev/null +++ b/services/init/include/init_service.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2020-2021 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_SERVICE_H +#define BASE_STARTUP_INITLITE_SERVICE_H +#include +#include +#include +#include +#include + +#include "cJSON.h" +#include "init_cmds.h" +#include "init_error.h" +#include "init_service_file.h" +#include "init_service_socket.h" +#include "list.h" +#include "loop_event.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +// return value +#define SERVICE_FAILURE (-1) +#define SERVICE_SUCCESS 0 + +// service attributes +#define SERVICE_ATTR_INVALID 0x001 // option invalid +#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits +#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future +#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap +#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash +#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes +#define SERVICE_ATTR_DISABLED 0x040 // disabled +#define SERVICE_ATTR_CONSOLE 0x080 // console +#define SERVICE_ATTR_ONDEMAND 0x100 // ondemand, manage socket by init +#define SERVICE_ATTR_TIMERSTART 0x200 // Mark a service will be started by timer +#define SERVICE_ATTR_NEEDWAIT 0x400 // service should execute waitpid while stopping +#define SERVICE_ATTR_WITHOUT_SANDBOX 0x800 // make service not enter sandbox + +#define SERVICE_ATTR_NOTIFY_STATE 0x1000 // service notify state +#define SERVICE_ATTR_MODULE_UPDATE 0x2000 // module update +#define SERVICE_ATTR_KMSG 0x4000 // kmsg +#define SERVICE_ATTR_PERIOD 0x8000 //service period + +#define SERVICE_ATTR_SETUID 0x10000 //service can setuid with no fixup + +#define MAX_SERVICE_NAME 32 +#define MAX_APL_NAME 32 +#define MAX_ENV_NAME 64 +#define MAX_JOB_NAME 128 +#define MAX_WRITEPID_FILES 100 +#define MAX_ENV_VALUE 128 + +#define FULL_CAP 0xFFFFFFFF +// init +#define DEFAULT_UMASK_INIT 022 + +#define CAP_NUM 2 + +#define SERVICES_ARR_NAME_IN_JSON "services" + +#define IsOnDemandService(service) \ + (((service)->attribute & SERVICE_ATTR_ONDEMAND) == SERVICE_ATTR_ONDEMAND) + +#define MarkServiceAsOndemand(service) \ + ((service)->attribute |= SERVICE_ATTR_ONDEMAND) + +#define UnMarkServiceAsOndemand(service) \ + ((service)->attribute &= ~SERVICE_ATTR_ONDEMAND) + +#define IsServiceWithTimerEnabled(service) \ + (((service)->attribute & SERVICE_ATTR_TIMERSTART) == SERVICE_ATTR_TIMERSTART) + +#define DisableServiceTimer(service) \ + ((service)->attribute &= ~SERVICE_ATTR_TIMERSTART) + +#define EnableServiceTimer(service) \ + ((service)->attribute |= SERVICE_ATTR_TIMERSTART) + +#define MarkServiceWithoutSandbox(service) \ + ((service)->attribute |= SERVICE_ATTR_WITHOUT_SANDBOX) + +#define MarkServiceWithSandbox(service) \ + ((service)->attribute &= ~SERVICE_ATTR_WITHOUT_SANDBOX) + +#pragma pack(4) +typedef enum { + START_MODE_CONDITION, + START_MODE_BOOT, + START_MODE_NORMAL, +} ServiceStartMode; + +typedef enum { + END_PRE_FORK, + END_AFTER_FORK, + END_AFTER_EXEC, + END_RECV_READY, +} ServiceEndMode; + +typedef struct { + uid_t uID; + gid_t *gIDArray; + int gIDCnt; + unsigned int *caps; + unsigned int capsCnt; +} Perms; + +typedef struct { + int count; + char **argv; +} ServiceArgs; + +typedef enum { + JOB_ON_BOOT, + JOB_PRE_START, + JOB_ON_START, + JOB_ON_STOP, + JOB_ON_RESTART, + JOB_ON_MAX +} ServiceJobType; + +typedef struct { + char *jobsName[JOB_ON_MAX]; +} ServiceJobs; + +typedef struct { + char name[MAX_ENV_NAME]; + char value[MAX_ENV_VALUE]; +} ServiceEnv; + +typedef struct Service { + char *name; + int pid; + int crashCnt; + uint32_t firstCrashTime; + int crashCount; + int crashTime; + unsigned int attribute; + int importance; + int startMode : 4; // startCondition/ startBoot / startNormal + int endMode : 4; // preFork/ fork / exec / ready + int status : 4; // ServiceStatus + uint64_t tokenId; + char *apl; + uint64_t period; + ServiceEnv *env; + int envCnt; + ServiceArgs capsArgs; + ServiceArgs permArgs; + ServiceArgs permAclsArgs; + Perms servPerm; + ServiceArgs pathArgs; + ServiceArgs writePidArgs; + CmdLines *restartArg; + ServiceSocket *socketCfg; + ServiceFile *fileCfg; + int *fds; + size_t fdCount; + TimerHandle timer; + ServiceJobs serviceJobs; + cpu_set_t *cpuSet; + struct ListNode extDataNode; + ConfigContext context; + InitErrno lastErrno; +} Service; +#pragma pack() + +Service *GetServiceByPid(pid_t pid); +Service *GetServiceByName(const char *servName); +int ServiceStart(Service *service, ServiceArgs *pathArgs); +int ServiceStop(Service *service); +void ServiceReap(Service *service); +void ReapService(Service *service); + +void NotifyServiceChange(Service *service, int status); +int IsForbidden(const char *fieldStr); +int SetImportantValue(Service *curServ, const char *attrName, int value, int flag); +int InitServiceCaps(const cJSON *curArrItem, Service *curServ); +int ServiceExec(Service *service, const ServiceArgs *pathArgs); +void CloseServiceFds(Service *service, bool needFree); +int UpdaterServiceFds(Service *service, int *fds, size_t fdCount); +int SetAccessToken(const Service *service); +void GetAccessToken(void); +void ServiceStopTimer(Service *service); +void ServiceStartTimer(Service *service, uint64_t timeout); +void ServiceReStartTimer(Service *service, uint64_t timeout); +void IsEnableSandbox(void); +void EnterServiceSandbox(Service *service); +int SetServiceEnterSandbox(const Service *service, const char *execPath); + +int CreateServiceFile(Service *service); +void CloseServiceFile(ServiceFile *fileOpt); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_INITLITE_SERVICE_H diff --git a/services/init/include/init_service_file.h b/services/init/include/init_service_file.h new file mode 100644 index 0000000000000000000000000000000000000000..3dbb142ad0de7a7eb2f285e0a9a0d62d7e0cecf4 --- /dev/null +++ b/services/init/include/init_service_file.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020-2021 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 INIT_SERVICE_FILE_ +#define INIT_SERVICE_FILE_ +#include +#include +#include +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define FILE_OPT_NUMS 5 +#define SERVICE_FILE_NAME 0 +#define SERVICE_FILE_FLAGS 1 +#define SERVICE_FILE_PERM 2 +#define SERVICE_FILE_UID 3 +#define SERVICE_FILE_GID 4 + +typedef struct ServiceFile_ { + struct ServiceFile_ *next; + int flags; + uid_t uid; // uid + gid_t gid; // gid + mode_t perm; // Setting permissions + int fd; + char fileName[0]; +} ServiceFile; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/services/init/include/init_service_manager.h b/services/init/include/init_service_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..b68272916efaba5d490af6a201708f6e3d94b5e5 --- /dev/null +++ b/services/init/include/init_service_manager.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020-2021 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_SERVICEMANAGER_H +#define BASE_STARTUP_INITLITE_SERVICEMANAGER_H + +#include "init_service.h" +#include "cJSON.h" +#include "init_cmds.h" +#include "list.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define UID_STR_IN_CFG "uid" +#define GID_STR_IN_CFG "gid" +#define ONCE_STR_IN_CFG "once" +#define IMPORTANT_STR_IN_CFG "importance" +#define BIN_SH_NOT_ALLOWED "/bin/sh" +#define CRITICAL_STR_IN_CFG "critical" +#define DISABLED_STR_IN_CFG "disabled" +#define CONSOLE_STR_IN_CFG "console" +#define SANDBOX_STR_IN_CFG "sandbox" +#define D_CAPS_STR_IN_CFG "d-caps" +#define APL_STR_IN_CFG "apl" +#define CPU_CORE_STR_IN_CFG "cpucore" +#define MODULE_UPDATE_STR_IN_CFG "module-update" +#define PERIOD_STR_IN_CFG "period" + +#define MAX_SERVICES_CNT_IN_FILE 100 + +typedef struct { + char *capStr; + unsigned int CapNum; +} CapStrCapNum; + +typedef struct { + int serviceCount; +} ServiceSpace; + +extern ServiceSpace g_serviceSpace; +cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName); +int ParseOneService(const cJSON *curItem, Service *service); + +void StartServiceByName(const char *serviceName); +void StopServiceByName(const char *serviceName); +void StopAllServices(int flags, const char **exclude, int size, + int (*filter)(const Service *service, const char **exclude, int size)); +void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context); +void ReleaseService(Service *service); +void LoadAccessTokenId(void); +Service *AddService(const char *name); +void DumpServiceHookExecute(const char *name, const char *info); +void ProcessControlFd(uint16_t type, const char *serviceCmd, const void *context); +int GetKillServiceSig(const char *name); +int WatchConsoleDevice(Service *service); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_INITLITE_SERVICEMANAGER_H diff --git a/services/init/include/init_service_socket.h b/services/init/include/init_service_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..70d426fb2d2f882288fde9ede68ece3cacf635c9 --- /dev/null +++ b/services/init/include/init_service_socket.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021 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 INIT_SERVICE_SOCKET_ +#define INIT_SERVICE_SOCKET_ +#ifndef __LITEOS_A__ +#include +#endif +#include +#include +#include +#include +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MAX_SOCK_NAME_LEN 16 +#define SOCK_OPT_NUMS 6 + +#define IsConnectionBasedSocket(sockopt) \ + ((sockopt)->type == SOCK_STREAM || (sockopt)->type == SOCK_SEQPACKET) + +enum SockOptionTab { + SERVICE_SOCK_NAME = 0, + SERVICE_SOCK_TYPE, + SERVICE_SOCK_PERM, + SERVICE_SOCK_UID, + SERVICE_SOCK_GID, + SERVICE_SOCK_SETOPT +}; +typedef void *ServiceWatcher; +typedef struct Service Service; +// socket option +#define SOCKET_OPTION_INVALID 0x001 // option invalid +#define SOCKET_OPTION_PASSCRED 0x002 // SO_PASSCRED +#define SOCKET_OPTION_RCVBUFFORCE 0x004 // SO_RCVBUFFORCE + +typedef union { +#ifndef __LITEOS_A__ + struct sockaddr_nl addrnl; +#endif + struct sockaddr_un addrun; +} sockaddr_union; + +typedef struct ServiceSocket { + struct ServiceSocket *next; + struct ServiceSocket *nextNode; + Service *service; + int family; // socket family + unsigned int type; // socket type + int protocol; // socket protocol + mode_t perm; // Setting permissions + uid_t uid; // uid + gid_t gid; // gid + unsigned int option; // setsocketopt + int sockFd; + ServiceWatcher watcher; + char name[0]; // service name +} ServiceSocket; + +int SetSocketEnvForService(Service *service); +int CreateSocketForService(Service *service); +void CloseServiceSocket(Service *service); +int AddSocketWatcher(ServiceWatcher *watcherHandle, Service *service, int fd); +void RemoveSocketWatcher(ServiceWatcher watcherHandle); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/services/init/init_capability.c b/services/init/init_capability.c new file mode 100644 index 0000000000000000000000000000000000000000..26b9792b517a214bef43279f5599fb942d638691 --- /dev/null +++ b/services/init/init_capability.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2020-2021 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 +#if defined OHOS_LITE && !defined __LINUX__ +#include +#else +#include +#endif +#include +#include + +#include "init_log.h" +#include "init_service.h" +#include "init_service_manager.h" +#include "init_utils.h" + +#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100 + +static unsigned int GetCapByString(const char *capStr) +{ + static const CapStrCapNum capStrCapNum[] = { + { "CHOWN", CAP_CHOWN }, + { "DAC_OVERRIDE", CAP_DAC_OVERRIDE }, + { "DAC_READ_SEARCH", CAP_DAC_READ_SEARCH }, + { "FOWNER", CAP_FOWNER }, + { "FSETID", CAP_FSETID }, + { "KILL", CAP_KILL }, + { "SETGID", CAP_SETGID }, + { "SETUID", CAP_SETUID }, + { "SETPCAP", CAP_SETPCAP }, + { "LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE }, + { "NET_BIND_SERVICE", CAP_NET_BIND_SERVICE }, + { "NET_BROADCAST", CAP_NET_BROADCAST }, + { "NET_ADMIN", CAP_NET_ADMIN }, + { "NET_RAW", CAP_NET_RAW }, + { "IPC_LOCK", CAP_IPC_LOCK }, + { "IPC_OWNER", CAP_IPC_OWNER }, + { "SYS_MODULE", CAP_SYS_MODULE }, + { "SYS_RAWIO", CAP_SYS_RAWIO }, + { "SYS_CHROOT", CAP_SYS_CHROOT }, + { "SYS_PTRACE", CAP_SYS_PTRACE }, + { "SYS_PACCT", CAP_SYS_PACCT }, + { "SYS_ADMIN", CAP_SYS_ADMIN }, + { "SYS_BOOT", CAP_SYS_BOOT }, + { "SYS_NICE", CAP_SYS_NICE }, + { "SYS_RESOURCE", CAP_SYS_RESOURCE }, + { "SYS_TIME", CAP_SYS_TIME }, + { "SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG }, + { "MKNOD", CAP_MKNOD }, + { "LEASE", CAP_LEASE }, + { "AUDIT_WRITE", CAP_AUDIT_WRITE }, + { "AUDIT_CONTROL", CAP_AUDIT_CONTROL }, + { "SETFCAP", CAP_SETFCAP }, + { "MAC_OVERRIDE", CAP_MAC_OVERRIDE }, + { "MAC_ADMIN", CAP_MAC_ADMIN }, + { "SYSLOG", CAP_SYSLOG }, + { "WAKE_ALARM", CAP_WAKE_ALARM }, + { "BLOCK_SUSPEND", CAP_BLOCK_SUSPEND }, + { "AUDIT_READ", CAP_AUDIT_READ }, +#if defined CAP_PERFMON + { "PERFMON", CAP_PERFMON }, +#endif + }; + int mapSize =(int)ARRAY_LENGTH(capStrCapNum); + int capLen=strlen("CAP_"); + for (int j = 0; j < mapSize; j++){ + if ((strcmp(capStr, capStrCapNum[j].capStr) == 0) || + ((strncmp(capStr, "CAP_", capLen) == 0) && + (strcmp(capStr + capLen, capStrCapNum[j].capStr) == 0))) { + return capStrCapNum[j].CapNum; + } + } + return CAP_LAST_CAP + 1; +} + +int InitServiceCaps(const cJSON *curArrItem, Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null ptr."); + INIT_ERROR_CHECK(curArrItem != NULL, return SERVICE_FAILURE, "json is null ptr."); + int capsCnt = 0; + cJSON *filedJ = GetArrayItem(curArrItem, &capsCnt, "caps"); + if (filedJ == NULL) { + return SERVICE_SUCCESS; + } + INIT_ERROR_CHECK(capsCnt <= MAX_CAPS_CNT_FOR_ONE_SERVICE, return SERVICE_FAILURE, + "service=%s, too many caps[cnt %d] for one service", service->name, capsCnt); + service->servPerm.capsCnt = 0; + if (service->servPerm.caps != NULL) { + free(service->servPerm.caps); + service->servPerm.caps = NULL; + } + service->servPerm.caps = (unsigned int *)calloc(1, sizeof(unsigned int) * capsCnt); + INIT_ERROR_CHECK(service->servPerm.caps != NULL, return SERVICE_FAILURE, + "Failed to malloc for service %s", service->name); + unsigned int caps = FULL_CAP; + for (int i = 0; i < capsCnt; ++i) { // number form + char *capStr = NULL; + cJSON *capJson = cJSON_GetArrayItem(filedJ, i); + if (cJSON_IsNumber(capJson)) { // for number + caps = (unsigned int)cJSON_GetNumberValue(capJson); + } else if (cJSON_IsString(capJson)) { + capStr = cJSON_GetStringValue(capJson); + if (capStr == NULL || strlen(capStr) == 0) { // check all errors + INIT_LOGE("service=%s, parse item[%d] as string, error.", service->name, i); + break; + } + caps = GetCapByString(capStr); + } else { + caps = CAP_LAST_CAP + 1; + } + if ((caps > CAP_LAST_CAP) && (caps != (unsigned int)FULL_CAP)) { + INIT_LOGE("service=%s not support caps = %s caps %d", service->name, capStr, caps); + continue; + } + service->servPerm.caps[service->servPerm.capsCnt] = (unsigned int)caps; + service->servPerm.capsCnt++; + } + return 0; +} \ No newline at end of file diff --git a/services/init/init_common_cmds.c b/services/init/init_common_cmds.c new file mode 100644 index 0000000000000000000000000000000000000000..7ba5530b0bbb7d04c76a72e411bfee3f5b42d36e --- /dev/null +++ b/services/init/init_common_cmds.c @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2020-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 "init_cmds.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_cmdexecutor.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "securec.h" + +#ifndef OHOS_LITE +#include "hookmgr.h" +#include "bootstage.h" + +/** + * init cmd hooking execute + */ +static void InitCmdHookExecute(const char *cmdName, const char *cmdContent, INIT_TIMING_STAT *cmdTimer) +{ + INIT_CMD_INFO context; + + context.cmdName = cmdName; + context.cmdContent = cmdContent; + context.reserved = (const char *)cmdTimer; + + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_CMD_RECORD, (void *)(&context), NULL); +} +#endif + +static char *AddOneArg(const char *param, size_t paramLen) +{ + int valueCount = 1; + char *begin = strchr(param, '$'); + while (begin != NULL) { + valueCount++; + begin = strchr(begin + 1, '$'); + } + size_t allocSize = paramLen + (PARAM_VALUE_LEN_MAX * valueCount) + 1; + char *arg = calloc(allocSize, sizeof(char)); + INIT_CHECK(arg != NULL, return NULL); + int ret = GetParamValue(param, paramLen, arg, allocSize); + INIT_ERROR_CHECK(ret == 0, free(arg); + return NULL, "Failed to get value for %s", param); + return arg; +} + +char *BuildStringFromCmdArg(const struct CmdArgs *ctx, int startIndex) +{ + INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to get cmd args "); + char *options = (char *)calloc(1, OPTIONS_SIZE + 1); + INIT_ERROR_CHECK(options != NULL, return NULL, "Failed to get memory "); + options[0] = '\0'; + int curr = 0; + for (int i = startIndex; i < ctx->argc; i++) { // save opt + if (ctx->argv[i] == NULL) { + continue; + } + int len = snprintf_s(options + curr, OPTIONS_SIZE - curr, OPTIONS_SIZE - 1 - curr, "%s ", ctx->argv[i]); + if (len <= 0) { + INIT_LOGE("Failed to format other opt"); + options[0] = '\0'; + return options; + } + curr += len; + } + if ((curr > 0) && (curr < OPTIONS_SIZE)) { + options[curr - 1] = '\0'; + } + return options; +} + +const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount) +{ + INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL); + INIT_CHECK_RETURN_VALUE(delim != NULL, NULL); + INIT_WARNING_CHECK(argsCount <= SPACES_CNT_IN_CMD_MAX, argsCount = SPACES_CNT_IN_CMD_MAX, + "Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX); + struct CmdArgs *ctx = (struct CmdArgs *)calloc(1, sizeof(struct CmdArgs) + sizeof(char *) * (argsCount + 1)); + INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to calloc memory for arg"); + ctx->argc = 0; + const char *p = cmdContent; + const char *end = cmdContent + strlen(cmdContent); + const char *token = NULL; + do { + // Skip lead whitespaces + while (isspace(*p)) { + p++; + } + if (end == p) { // empty cmd content + break; + } + token = strstr(p, delim); + if (token == NULL) { + ctx->argv[ctx->argc] = AddOneArg(p, end - p); + INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx); + return NULL); + } else { + ctx->argv[ctx->argc] = AddOneArg(p, token - p); + INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx); + return NULL); + } + ctx->argc++; + ctx->argv[ctx->argc] = NULL; + if (ctx->argc == argsCount) { + break; + } + p = token; + } while (token != NULL); + return ctx; +} + +void FreeCmdArg(struct CmdArgs *cmd) +{ + INIT_CHECK_ONLY_RETURN(cmd != NULL); + for (int i = 0; i < cmd->argc; ++i) { + if (cmd->argv[i] != NULL) { + free(cmd->argv[i]); + } + } + free(cmd); + return; +} + +void ExecCmd(const struct CmdTable *cmd, const char *cmdContent) +{ + INIT_ERROR_CHECK(cmd != NULL, return, "Invalid cmd."); + const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", cmd->maxArg); + if (ctx == NULL) { + INIT_LOGE("Invalid arguments cmd: %s content: %s", cmd->name, cmdContent); + } else if ((ctx->argc <= cmd->maxArg) && (ctx->argc >= cmd->minArg)) { + cmd->DoFuncion(ctx); + } else { + INIT_LOGE("Invalid arguments cmd: %s content: %s argc: %d %d", cmd->name, cmdContent, ctx->argc, cmd->maxArg); + } + FreeCmdArg((struct CmdArgs *)ctx); +} + +static void SetProcName(const struct CmdArgs *ctx, const char *procFile) +{ + int fd = open(procFile, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR); + INIT_ERROR_CHECK(fd >= 0, return, "Failed to set %s errno: %d", procFile, errno); + + size_t size = strlen(ctx->argv[0]); + ssize_t n = write(fd, ctx->argv[0], size); + INIT_ERROR_CHECK(n == (ssize_t)size, close(fd); + return, "Failed to write domainname errno: %d", errno); + close(fd); +} + +static void DoSetDomainname(const struct CmdArgs *ctx) +{ + SetProcName(ctx, "/proc/sys/kernel/domainname"); +} + +static void DoSetHostname(const struct CmdArgs *ctx) +{ + SetProcName(ctx, "/proc/sys/kernel/hostname"); +} + +static void DoSleep(const struct CmdArgs *ctx) +{ + errno = 0; + unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE); + INIT_ERROR_CHECK(errno == 0, return, "cannot convert sleep time in command \" sleep \""); + + // Limit sleep time in 5 seconds + const unsigned long sleepTimeLimit = 5; + INIT_CHECK(sleepTime <= sleepTimeLimit, sleepTime = sleepTimeLimit); + INIT_LOGI("Sleeping %d second(s)", sleepTime); + sleep((unsigned int)sleepTime); +} + +static void DoWait(const struct CmdArgs *ctx) +{ + const int filePos = 0; + const int timePos = 1; + unsigned long waitSecond = WAIT_MAX_SECOND; + + if (ctx->argc == timePos + 1) { + errno = 0; + waitSecond = strtoul(ctx->argv[timePos], NULL, DECIMAL_BASE); + INIT_ERROR_CHECK(errno == 0, + return, "cannot convert sleep time in command \" wait \""); + } + + INIT_LOGI("Waiting %s %lu second(s)", ctx->argv[filePos], waitSecond); + WaitForFile(ctx->argv[filePos], waitSecond); +} + +static void DoStart(const struct CmdArgs *ctx) +{ + INIT_LOGV("DoStart %s", ctx->argv[0]); + StartServiceByName(ctx->argv[0]); +} + +static void DoStop(const struct CmdArgs *ctx) +{ + INIT_LOGV("DoStop %s", ctx->argv[0]); + StopServiceByName(ctx->argv[0]); + return; +} + +static void DoReset(const struct CmdArgs *ctx) +{ + INIT_LOGV("DoReset %s", ctx->argv[0]); + Service *service = GetServiceByName(ctx->argv[0]); + if (service == NULL) { + INIT_LOGE("Reset cmd cannot find service %s.", ctx->argv[0]); + return; + } + if (service->pid > 0) { +#ifndef OHOS_LITE + SERVICE_RESTART_CTX context; + int pid = service->pid; + context.serviceName = service->name; + context.serviceNode = (const char *)&pid; + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_RESTART, (void *)(&context), NULL); +#endif + if (kill(service->pid, GetKillServiceSig(ctx->argv[0])) != 0) { + INIT_LOGE("stop service %s pid %d failed! err %d.", service->name, service->pid, errno); + return; + } + } else { + StartServiceByName(ctx->argv[0]); + } + return; +} + +static void DoCopy(const struct CmdArgs *ctx) +{ + int srcFd = -1; + int dstFd = -1; + char buf[MAX_COPY_BUF_SIZE] = { 0 }; + char *realPath1 = NULL; + char *realPath2 = NULL; + do { + realPath1 = GetRealPath(ctx->argv[0]); + if (realPath1 == NULL) { + INIT_LOGE("Failed to get real path %s", ctx->argv[0]); + break; + } + + srcFd = open(realPath1, O_RDONLY); + if (srcFd < 0) { + INIT_LOGE("Failed to open source path %s %d", ctx->argv[0], errno); + break; + } + + struct stat fileStat = { 0 }; + if (stat(ctx->argv[0], &fileStat) != 0) { + INIT_LOGE("Failed to state source path %s %d", ctx->argv[0], errno); + break; + } + mode_t mode = fileStat.st_mode; + realPath2 = GetRealPath(ctx->argv[1]); + if (realPath2 != NULL) { + dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode); + } else { + dstFd = open(ctx->argv[1], O_WRONLY | O_TRUNC | O_CREAT, mode); + } + if (dstFd < 0) { + INIT_LOGE("Failed to open dest path %s %d", ctx->argv[1], errno); + break; + } + int rdLen = 0; + while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) { + int rtLen = write(dstFd, buf, rdLen); + if (rtLen != rdLen) { + INIT_LOGE("Failed to write to dest path %s %d", ctx->argv[1], errno); + break; + } + } + fsync(dstFd); + } while (0); + INIT_CHECK(srcFd < 0, close(srcFd)); + INIT_CHECK(dstFd < 0, close(dstFd)); + INIT_CHECK(realPath1 == NULL, free(realPath1)); + INIT_CHECK(realPath2 == NULL, free(realPath2)); +} + +static int SetOwner(const char *file, const char *ownerStr, const char *groupStr) +{ + INIT_ERROR_CHECK(file != NULL, return -1, "SetOwner invalid file."); + INIT_ERROR_CHECK(ownerStr != NULL, return -1, "SetOwner invalid file."); + INIT_ERROR_CHECK(groupStr != NULL, return -1, "SetOwner invalid file."); + + uid_t owner = DecodeUid(ownerStr); + INIT_ERROR_CHECK(owner != (uid_t)-1, return -1, "SetOwner invalid uid : %s.", ownerStr); + gid_t group = DecodeGid(groupStr); + INIT_ERROR_CHECK(group != (gid_t)-1, return -1, "SetOwner invalid gid : %s.", groupStr); + return (chown(file, owner, group) != 0) ? -1 : 0; +} + +static void DoChown(const struct CmdArgs *ctx) +{ + // format: chown owner group /xxx/xxx/xxx + const int pathPos = 2; + int ret = SetOwner(ctx->argv[pathPos], ctx->argv[0], ctx->argv[1]); + if (ret != 0) { + INIT_LOGE("Failed to change owner for %s, err %d.", ctx->argv[pathPos], errno); + } + return; +} + +static void DoMkDir(const struct CmdArgs *ctx) +{ + // mkdir support format: + // 1.mkdir path + // 2.mkdir path mode + // 3.mkdir path mode owner group + const int ownerPos = 2; + const int groupPos = 3; + if (ctx->argc != 1 && ctx->argc != (groupPos + 1) && ctx->argc != ownerPos) { + INIT_LOGE("DoMkDir invalid arguments."); + return; + } + mode_t mode = DEFAULT_DIR_MODE; + if (mkdir(ctx->argv[0], mode) != 0 && errno != EEXIST) { + INIT_LOGE("Create directory '%s' failed, err=%d.", ctx->argv[0], errno); + return; + } + + /* + * Skip restoring default SELinux security contexts if the the folder already + * existed and its under /dev or /data/. These files will be proceed by loadSelinuxPolicy. + */ + if ((errno != EEXIST) || ((strncmp(ctx->argv[0], "/dev", strlen("/dev")) != 0) && + (strncmp(ctx->argv[0], "/data/", strlen("/data/")) != 0)) || + (strncmp(ctx->argv[0], "/data/service/el1", strlen("/data/service/el1")) == 0)) { + PluginExecCmdByName("restoreContentRecurse", ctx->argv[0]); + } + + if (ctx->argc <= 1) { + return; + } + + mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE); + INIT_CHECK_ONLY_ELOG(chmod(ctx->argv[0], mode) == 0, "DoMkDir failed for '%s', err %d.", ctx->argv[0], errno); + + if (ctx->argc <= ownerPos) { + return; + } + int ret = SetOwner(ctx->argv[0], ctx->argv[ownerPos], ctx->argv[groupPos]); + if (ret != 0) { + INIT_LOGE("Failed to change owner %s, err %d.", ctx->argv[0], errno); + } + ret = SetFileCryptPolicy(ctx->argv[0]); + INIT_CHECK_ONLY_ELOG(ret == 0, "Failed to set file fscrypt"); + return; +} + +static void DoChmod(const struct CmdArgs *ctx) +{ + // format: chmod xxxx /xxx/xxx/xxx + mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE); + if (mode == 0) { + INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", ctx->argv[1], errno); + return; + } + + if (chmod(ctx->argv[1], mode) != 0) { + INIT_LOGE("Failed to change mode \" %s \" to %04o, err=%d", ctx->argv[1], mode, errno); + } +} + +static int GetMountFlag(unsigned long *mountflag, const char *targetStr, const char *source) +{ + INIT_CHECK_RETURN_VALUE(targetStr != NULL && mountflag != NULL, 0); + struct { + char *flagName; + unsigned long value; + } mountFlagMap[] = { + { "noatime", MS_NOATIME }, + { "noexec", MS_NOEXEC }, + { "nosuid", MS_NOSUID }, + { "nodev", MS_NODEV }, + { "nodiratime", MS_NODIRATIME }, + { "ro", MS_RDONLY }, + { "rdonly", MS_RDONLY }, + { "rw", 0 }, + { "sync", MS_SYNCHRONOUS }, + { "remount", MS_REMOUNT }, + { "bind", MS_BIND }, + { "rec", MS_REC }, + { "unbindable", MS_UNBINDABLE }, + { "private", MS_PRIVATE }, + { "slave", MS_SLAVE }, + { "shared", MS_SHARED }, + { "defaults", 0 }, + }; + for (unsigned int i = 0; i < ARRAY_LENGTH(mountFlagMap); i++) { + if (strncmp(targetStr, mountFlagMap[i].flagName, strlen(mountFlagMap[i].flagName)) == 0) { + *mountflag |= mountFlagMap[i].value; + return 1; + } + } + if (strncmp(targetStr, "wait", strlen("wait")) == 0) { + WaitForFile(source, WAIT_MAX_SECOND); + return 1; + } + + return 0; +} + +static void DoMount(const struct CmdArgs *ctx) +{ + INIT_ERROR_CHECK(ctx->argc <= SPACES_CNT_IN_CMD_MAX, return, "Invalid arg number"); + // format: fileSystemType source target mountFlag1 mountFlag2... data + int index = 0; + char *fileSysType = (ctx->argc > index) ? ctx->argv[index] : NULL; + INIT_ERROR_CHECK(fileSysType != NULL, return, "Failed to get fileSysType."); + index++; + + char *source = (ctx->argc > index) ? ctx->argv[index] : NULL; + INIT_ERROR_CHECK(source != NULL, return, "Failed to get source."); + index++; + + // maybe only has "filesystype source target", 2 spaces + char *target = (ctx->argc > index) ? ctx->argv[index] : NULL; + INIT_ERROR_CHECK(target != NULL, return, "Failed to get target."); + ++index; + + int ret = 0; + unsigned long mountflags = 0; + while (index < ctx->argc) { + ret = GetMountFlag(&mountflags, ctx->argv[index], source); + if (ret == 0) { + break; + } + index++; + } + if (index >= ctx->argc) { + ret = mount(source, target, fileSysType, mountflags, NULL); + } else { + char *data = BuildStringFromCmdArg(ctx, index); + INIT_ERROR_CHECK(data != NULL, return, "Failed to get data."); + ret = mount(source, target, fileSysType, mountflags, data); + free(data); + } + if (ret != 0) { + INIT_LOGE("Failed to mount for %s, err %d.", target, errno); + } +} + +static int DoWriteWithMultiArgs(const struct CmdArgs *ctx, int fd) +{ + char buf[MAX_CMD_CONTENT_LEN]; + + /* Write to proc files should be done at once */ + buf[0] = '\0'; + INIT_ERROR_CHECK(strcat_s(buf, sizeof(buf), ctx->argv[1]) == 0, return -1, "Failed to format buf"); + int idx = 2; + while (idx < ctx->argc) { + INIT_ERROR_CHECK(strcat_s(buf, sizeof(buf), " ") == 0, return -1, "Failed to format buf"); + INIT_ERROR_CHECK(strcat_s(buf, sizeof(buf), ctx->argv[idx]) == 0, return -1, "Failed to format buf"); + idx++; + } + return write(fd, buf, strlen(buf)); +} + +static void DoWrite(const struct CmdArgs *ctx) +{ + // format: write path content + char *realPath = GetRealPath(ctx->argv[0]); + int fd = -1; + if (realPath != NULL) { + fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); + free(realPath); + realPath = NULL; + } else { + fd = open(ctx->argv[0], O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); + } + if (fd < 0) { + return; + } + ssize_t ret; + if (ctx->argc > 2) { + ret = DoWriteWithMultiArgs(ctx, fd); + } else { + ret = write(fd, ctx->argv[1], strlen(ctx->argv[1])); + } + INIT_CHECK_ONLY_ELOG(ret >= 0, "DoWrite: write to file %s failed: %d", ctx->argv[0], errno); + close(fd); +} + +static void DoRmdir(const struct CmdArgs *ctx) +{ + // format: rmdir path + int ret = rmdir(ctx->argv[0]); + if (ret == -1) { + INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno); + } + return; +} + +static void DoRebootCmd(const struct CmdArgs *ctx) +{ + ExecReboot(ctx->argv[0]); + return; +} + +static void DoSetrlimit(const struct CmdArgs *ctx) +{ + static const char *resource[] = { + "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS", + "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING", + "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS" + }; + // format: setrlimit resource curValue maxValue + const int rlimMaxPos = 2; + struct rlimit limit; + if (strcmp(ctx->argv[1], "unlimited") == 0) { + limit.rlim_cur = RLIM_INFINITY; + } else { + limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]); + } + if (strcmp(ctx->argv[rlimMaxPos], "unlimited") == 0) { + limit.rlim_max = RLIM_INFINITY; + } else { + limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]); + } + int rcs = -1; + for (unsigned int i = 0; i < ARRAY_LENGTH(resource); ++i) { + if (strcmp(ctx->argv[0], resource[i]) == 0) { + rcs = (int)i; + break; + } + } + if (rcs == -1) { + INIT_LOGE("DoSetrlimit failed, resources :%s not support.", ctx->argv[0]); + return; + } + INIT_CHECK_ONLY_ELOG(setrlimit(rcs, &limit) == 0, "Failed setrlimit err=%d", errno); + return; +} + +static void DoRm(const struct CmdArgs *ctx) +{ + // format: rm /xxx/xxx/xxx + INIT_CHECK_ONLY_ELOG(unlink(ctx->argv[0]) != -1, "Failed unlink %s err=%d.", ctx->argv[0], errno); + return; +} + +static void DoExport(const struct CmdArgs *ctx) +{ + // format: export xxx /xxx/xxx/xxx + INIT_CHECK_ONLY_ELOG(setenv(ctx->argv[0], ctx->argv[1], 1) == 0, "Failed setenv %s with %s err=%d.", + ctx->argv[0], ctx->argv[1], errno); + return; +} + +static const struct CmdTable g_cmdTable[] = { + { "start ", 0, 1, 0, DoStart }, + { "mkdir ", 1, 4, 1, DoMkDir }, + { "chmod ", 2, 2, 1, DoChmod }, + { "chown ", 3, 3, 1, DoChown }, + { "mount ", 1, 10, 0, DoMount }, + { "export ", 2, 2, 0, DoExport }, + { "rm ", 1, 1, 1, DoRm }, + { "rmdir ", 1, 1, 1, DoRmdir }, + { "write ", 2, 10, 1, DoWrite }, + { "stop ", 1, 1, 0, DoStop }, + { "reset ", 1, 1, 0, DoReset }, + { "copy ", 2, 2, 1, DoCopy }, + { "reboot ", 0, 1, 0, DoRebootCmd }, + { "setrlimit ", 3, 3, 0, DoSetrlimit }, + { "sleep ", 1, 1, 0, DoSleep }, + { "wait ", 1, 2, 1, DoWait }, + { "hostname ", 1, 1, 1, DoSetHostname }, + { "domainname ", 1, 1, 1, DoSetDomainname } +}; + +static const struct CmdTable *GetCommCmdTable(int *number) +{ + *number = (int)ARRAY_LENGTH(g_cmdTable); + return g_cmdTable; +} + +static char *GetCmdStart(const char *cmdContent) +{ + // Skip lead whitespaces + char *p = (char *)cmdContent; + while (p != NULL && isspace(*p)) { + p++; + } + if (p == NULL) { + return NULL; + } + if (*p == '#') { // start with # + return NULL; + } + return p; +} + +const struct CmdTable *GetCmdByName(const char *name) +{ + INIT_CHECK_RETURN_VALUE(name != NULL, NULL); + char *startCmd = GetCmdStart(name); + INIT_CHECK_RETURN_VALUE(startCmd != NULL, NULL); + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + for (int i = 0; i < cmdCnt; ++i) { + if (strncmp(startCmd, commCmds[i].name, strlen(commCmds[i].name)) == 0) { + return &commCmds[i]; + } + } + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + for (int i = 0; i < number; ++i) { + if (strncmp(startCmd, cmds[i].name, strlen(cmds[i].name)) == 0) { + return &cmds[i]; + } + } + return NULL; +} + +const char *GetMatchCmd(const char *cmdStr, int *index) +{ + INIT_CHECK_RETURN_VALUE(cmdStr != NULL && index != NULL, NULL); + char *startCmd = GetCmdStart(cmdStr); + INIT_CHECK_RETURN_VALUE(startCmd != NULL, NULL); + + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + for (int i = 0; i < cmdCnt; ++i) { + if (strncmp(startCmd, commCmds[i].name, strlen(commCmds[i].name)) == 0) { + *index = i; + return commCmds[i].name; + } + } + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + for (int i = 0; i < number; ++i) { + if (strncmp(startCmd, cmds[i].name, strlen(cmds[i].name)) == 0) { + *index = cmdCnt + i; + return cmds[i].name; + } + } + return PluginGetCmdIndex(startCmd, index); +} + +static const struct CmdTable *GetCmdTableByIndex(int index) +{ + int cmdCnt = 0; + const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt); + const struct CmdTable *cmdTable = NULL; + if (index < cmdCnt) { + cmdTable = &commCmds[index]; + } else { + int number = 0; + const struct CmdTable *cmds = GetCmdTable(&number); + if (index < (cmdCnt + number)) { + cmdTable = &cmds[index - cmdCnt]; + } + } + return cmdTable; +} + +const char *GetCmdKey(int index) +{ + const struct CmdTable *cmdTable = GetCmdTableByIndex(index); + if (cmdTable != NULL) { + return cmdTable->name; + } + return GetPluginCmdNameByIndex(index); +} + +int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines) +{ + INIT_CHECK(root != NULL, return -1); + INIT_CHECK(cmdLines != NULL, return -1); + *cmdLines = NULL; + if (!cJSON_IsArray(root)) { + return -1; + } + int cmdCnt = cJSON_GetArraySize(root); + INIT_CHECK_RETURN_VALUE(cmdCnt > 0, -1); + + *cmdLines = (CmdLines *)calloc(1, sizeof(CmdLines) + sizeof(CmdLine) * cmdCnt); + INIT_CHECK_RETURN_VALUE(*cmdLines != NULL, -1); + (*cmdLines)->cmdNum = 0; + for (int i = 0; i < cmdCnt; ++i) { + cJSON *line = cJSON_GetArrayItem(root, i); + if (!cJSON_IsString(line)) { + continue; + } + + char *tmp = cJSON_GetStringValue(line); + if (tmp == NULL) { + continue; + } + + int index = 0; + const char *cmd = GetMatchCmd(tmp, &index); + if (cmd == NULL) { + INIT_LOGE("Cannot support command: %s", tmp); + continue; + } + + int ret = strcpy_s((*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdContent, MAX_CMD_CONTENT_LEN, tmp + strlen(cmd)); + if (ret != EOK) { + INIT_LOGE("Invalid cmd arg: %s", tmp); + continue; + } + + (*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdIndex = index; + (*cmdLines)->cmdNum++; + } + return 0; +} + +void DoCmdByIndex(int index, const char *cmdContent, const ConfigContext *context) +{ + if (cmdContent == NULL) { + return; + } + INIT_TIMING_STAT cmdTimer; + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime); + + const char *cmdName = NULL; + const struct CmdTable *cmdTable = GetCmdTableByIndex(index); + if (cmdTable != NULL) { + cmdName = cmdTable->name; + if (!cmdTable->careContext || !CheckExecuteInSubInit(context)) { + ExecCmd(cmdTable, cmdContent); + } else { + ExecuteCmdInSubInit(context, cmdTable->name, cmdContent); + } + } else { + PluginExecCmdByCmdIndex(index, cmdContent, context); + cmdName = GetPluginCmdNameByIndex(index); + if (cmdName == NULL) { + cmdName = "Unknown"; + } + } + + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime); + long long diff = InitDiffTime(&cmdTimer); +#ifndef OHOS_LITE + InitCmdHookExecute(cmdName, cmdContent, &cmdTimer); +#endif + if (diff > 200000) { // 200000 > 200ms + INIT_LOGI("Execute command \"%s %s\" took %lld ms", cmdName, cmdContent, diff / BASE_MS_UNIT); + } else { + INIT_LOGV("Execute command \"%s %s\" took %lld ms", cmdName, cmdContent, diff / BASE_MS_UNIT); + } +} diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c new file mode 100644 index 0000000000000000000000000000000000000000..6f1ff19177111365b4c15bf871e14e5d854c4b51 --- /dev/null +++ b/services/init/init_common_service.c @@ -0,0 +1,1047 @@ +/* + * Copyright (c) 2021 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 +#ifdef __MUSL__ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "init_adapter.h" +#include "init_cmds.h" +#include "init_cmdexecutor.h" +#include "init_log.h" +#include "init_cmdexecutor.h" +#include "init_jobs_internal.h" +#include "init_param.h" +#include "init_service.h" +#include "init_service_manager.h" +#include "init_service_socket.h" +#include "init_utils.h" +#include "fd_holder_internal.h" +#include "loop_event.h" +#include "securec.h" +#include "service_control.h" +#include "init_group_manager.h" + +#ifndef OHOS_LITE +#include "hookmgr.h" +#include "bootstage.h" +#endif + +#ifdef WITH_SECCOMP +#define APPSPAWN_NAME ("appspawn") +#define NWEBSPAWN_NAME ("nwebspawn") +#endif + +#ifndef TIOCSCTTY +#define TIOCSCTTY 0x540E +#endif + +#define DEF_CRASH_TIME 240000 // default crash time is 240000 ms + +static int SetAllAmbientCapability(void) +{ + for (int i = 0; i <= CAP_LAST_CAP; ++i) { + if (SetAmbientCapability(i) != 0) { + return SERVICE_FAILURE; + } + } + return SERVICE_SUCCESS; +} + +static int SetSystemSeccompPolicy(const Service *service) +{ +#ifdef WITH_SECCOMP + if (strncmp(APPSPAWN_NAME, service->name, strlen(APPSPAWN_NAME)) + && strncmp(NWEBSPAWN_NAME, service->name, strlen(NWEBSPAWN_NAME))) { + char cmdContent[MAX_CMD_CONTENT_LEN + 1] = {0}; + + int rc = snprintf_s(cmdContent, MAX_CMD_CONTENT_LEN + 1, strlen(service->name) + 1, + "%s ", service->name); + if (rc == -1) { + return SERVICE_FAILURE; + } + + rc = strcat_s(cmdContent, MAX_CMD_CONTENT_LEN + 1, service->pathArgs.argv[0]); + if (rc != 0) { + return SERVICE_FAILURE; + } + + PluginExecCmdByName("SetSeccompPolicy", cmdContent); + } +#endif + return SERVICE_SUCCESS; +} + +#ifndef OHOS_LITE +/** + * service Hooking + */ +static int ServiceHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + SERVICE_INFO_CTX *serviceContext = (SERVICE_INFO_CTX *)executionContext; + ServiceHook realHook = (ServiceHook)hookInfo->hookCookie; + + realHook(serviceContext); + return 0; +}; + +int InitAddServiceHook(ServiceHook hook, int hookState) +{ + HOOK_INFO info; + + info.stage = hookState; + info.prio = 0; + info.hook = ServiceHookWrapper; + info.hookCookie = (void *)hook; + + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +static int ServiceRestartHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + SERVICE_RESTART_CTX *serviceContext = (SERVICE_RESTART_CTX *)executionContext; + ServiceRestartHook realHook = (ServiceRestartHook)hookInfo->hookCookie; + + realHook(serviceContext); + return 0; +} + +int InitServiceRestartHook(ServiceRestartHook hook, int hookState) +{ + HOOK_INFO info; + + info.stage = hookState; + info.prio = 0; + info.hook = ServiceRestartHookWrapper; + info.hookCookie = (void *)hook; + + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +/** + * service hooking execute + */ +static void ServiceHookExecute(const char *serviceName, const char *info, int stage) +{ + SERVICE_INFO_CTX context; + + context.serviceName = serviceName; + context.reserved = info; + + (void)HookMgrExecute(GetBootStageHookMgr(), stage, (void *)(&context), NULL); +} +#endif + +static int ServiceSetGid(const Service *service) +{ + if (service->servPerm.gIDCnt == 0) { + // use uid as gid + INIT_ERROR_CHECK(setgid(service->servPerm.uID) == 0, return SERVICE_FAILURE, + "Service error %d %s, failed to set gid.", errno, service->name); + } + if (service->servPerm.gIDCnt > 0) { + INIT_ERROR_CHECK(setgid(service->servPerm.gIDArray[0]) == 0, return SERVICE_FAILURE, + "Service error %d %s, failed to set gid.", errno, service->name); + } + if (service->servPerm.gIDCnt > 1) { + INIT_ERROR_CHECK(setgroups(service->servPerm.gIDCnt - 1, (const gid_t *)&service->servPerm.gIDArray[1]) == 0, + return SERVICE_FAILURE, + "Service error %d %s, failed to set gid.", errno, service->name); + } + + return SERVICE_SUCCESS; +} + +static void GetInvalidCaps(const Service *service, unsigned int *caps) +{ + int index = 0; + bool flags = false; + for (unsigned int cap = 0; cap <= CAP_LAST_CAP; cap++) { + for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) { + if (cap == service->servPerm.caps[i]) { + flags = true; + break; + } + flags = false; + } + if (!flags) { + caps[index] = cap; + index++; + } + } +} + +static void DropCapability(const Service *service) +{ +#ifndef OHOS_LITE + int invalidCnt = CAP_LAST_CAP - service->servPerm.capsCnt + 1; + unsigned int *caps = (unsigned int *)calloc(invalidCnt, sizeof(unsigned int)); + INIT_ERROR_CHECK(caps != NULL, return, "calloc caps failed! error:%d", errno); + + GetInvalidCaps(service, caps); + for (int i = 0; i < invalidCnt; i++) { + if (prctl(PR_CAPBSET_DROP, caps[i])) { + INIT_LOGE("prctl PR_SET_SECUREBITS failed: %d", errno); + free(caps); + return; + } + } + free(caps); +#else + return; +#endif +} + +static int SetPerms(const Service *service) +{ +#ifndef OHOS_LITE + /* + * service before setting Perms hooks + */ + ServiceHookExecute(service->name, (const char *)service->pathArgs.argv[0], INIT_SERVICE_SET_PERMS_BEFORE); +#endif + + INIT_ERROR_CHECK(KeepCapability(service) == 0, return INIT_EKEEPCAP, + "Service error %d %s, failed to set keep capability.", errno, service->name); + + INIT_ERROR_CHECK(ServiceSetGid(service) == SERVICE_SUCCESS, return INIT_EGIDSET, + "Service error %d %s, failed to set gid.", errno, service->name); + + // set seccomp policy before setuid + INIT_ERROR_CHECK(SetSystemSeccompPolicy(service) == SERVICE_SUCCESS, return INIT_ESECCOMP, + "Service error %d %s, failed to set system seccomp policy.", errno, service->name); + + if (service->servPerm.uID != 0) { + INIT_ERROR_CHECK(setuid(service->servPerm.uID) == 0, return INIT_EUIDSET, + "Service error %d %s, failed to set uid.", errno, service->name); + } else { + if (service->servPerm.capsCnt != 0) { + DropCapability(service); + } + } + + struct __user_cap_header_struct capHeader; + capHeader.version = _LINUX_CAPABILITY_VERSION_3; + capHeader.pid = 0; + struct __user_cap_data_struct capData[CAP_NUM] = {}; + for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) { + if (service->servPerm.caps[i] == FULL_CAP) { + for (int j = 0; j < CAP_NUM; ++j) { + capData[j].effective = FULL_CAP; + capData[j].permitted = FULL_CAP; + capData[j].inheritable = FULL_CAP; + } + break; + } + capData[CAP_TO_INDEX(service->servPerm.caps[i])].effective |= CAP_TO_MASK(service->servPerm.caps[i]); + capData[CAP_TO_INDEX(service->servPerm.caps[i])].permitted |= CAP_TO_MASK(service->servPerm.caps[i]); + capData[CAP_TO_INDEX(service->servPerm.caps[i])].inheritable |= CAP_TO_MASK(service->servPerm.caps[i]); + } + + INIT_ERROR_CHECK(capset(&capHeader, capData) == 0, return SERVICE_FAILURE, + "capset failed for service: %s, error: %d", service->name, errno); + for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) { + if (service->servPerm.caps[i] == FULL_CAP) { + int ret = SetAllAmbientCapability(); + INIT_ERROR_CHECK(ret == 0, return INIT_ECAP, + "Service error %d %s, failed to set ambient capability.", errno, service->name); + return 0; + } + INIT_ERROR_CHECK(SetAmbientCapability(service->servPerm.caps[i]) == 0, return INIT_ECAP, + "Service error %d %s, failed to set ambient capability.", errno, service->name); + } +#ifndef OHOS_LITE + /* + * service set Perms hooks + */ + ServiceHookExecute(service->name, NULL, INIT_SERVICE_SET_PERMS); +#endif + return SERVICE_SUCCESS; +} + +static int WritePid(const Service *service) +{ + pid_t childPid = getpid(); + for (int i = 0; i < service->writePidArgs.count; i++) { + if (service->writePidArgs.argv[i] == NULL) { + continue; + } + FILE *fd = NULL; + char *realPath = GetRealPath(service->writePidArgs.argv[i]); + if (realPath != NULL) { + fd = fopen(realPath, "wb"); + } else { + fd = fopen(service->writePidArgs.argv[i], "wb"); + } + if (fd != NULL) { + INIT_CHECK_ONLY_ELOG((int)fprintf(fd, "%d", childPid) > 0, + "Failed to write %s pid:%d", service->writePidArgs.argv[i], childPid); + (void)fclose(fd); + } else { + INIT_LOGE("Failed to open realPath: %s %s errno:%d.", realPath, service->writePidArgs.argv[i], errno); + } + if (realPath != NULL) { + free(realPath); + } + INIT_LOGV("ServiceStart writepid filename=%s, childPid=%d, ok", service->writePidArgs.argv[i], childPid); + } + return SERVICE_SUCCESS; +} + +void CloseServiceFds(Service *service, bool needFree) +{ + INIT_ERROR_CHECK(service != NULL, return, "Service null"); + INIT_LOGI("Closing service \' %s \' fds", service->name); + // fdCount > 0, There is no reason fds is NULL + if (service->fdCount != 0) { + size_t fdCount = service->fdCount; + int *fds = service->fds; + for (size_t i = 0; i < fdCount; i++) { + INIT_LOGV("Closing fd: %d", fds[i]); + if (fds[i] != -1) { + close(fds[i]); + fds[i] = -1; + } + } + } + service->fdCount = 0; + if (needFree && service->fds != NULL) { + free(service->fds); + service->fds = NULL; + } +} + +static int PublishHoldFds(Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return INIT_EPARAMETER, "Publish hold fds with invalid service"); + if (service->fdCount == 0 || service->fds == NULL) { + return 0; + } + char fdBuffer[MAX_FD_HOLDER_BUFFER] = {}; + char envName[MAX_BUFFER_LEN] = {}; + int ret = snprintf_s(envName, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, ENV_FD_HOLD_PREFIX"%s", service->name); + INIT_ERROR_CHECK(ret >= 0, return INIT_EFORMAT, + "Service error %d %s, failed to format string for publish", ret, service->name); + + size_t pos = 0; + for (size_t i = 0; i < service->fdCount; i++) { + int fd = dup(service->fds[i]); + if (fd < 0) { + INIT_LOGW("Service warning %d %s, failed to dup fd for publish", errno, service->name); + continue; + } + ret = snprintf_s((char *)fdBuffer + pos, sizeof(fdBuffer) - pos, sizeof(fdBuffer) - 1, "%d ", fd); + INIT_ERROR_CHECK(ret >= 0, return INIT_EFORMAT, + "Service error %d %s, failed to format fd for publish", ret, service->name); + pos += (size_t)ret; + } + fdBuffer[pos - 1] = '\0'; // Remove last ' ' + INIT_LOGI("Service %s publish fd [%s]", service->name, fdBuffer); + return setenv(envName, fdBuffer, 1); +} + +static int BindCpuCore(Service *service) +{ + if (service == NULL || service->cpuSet == NULL) { + return SERVICE_SUCCESS; + } + if (CPU_COUNT(service->cpuSet) == 0) { + return SERVICE_SUCCESS; + } +#ifndef __LITEOS_A__ + int pid = getpid(); + INIT_ERROR_CHECK(sched_setaffinity(pid, sizeof(cpu_set_t), service->cpuSet) == 0, + return SERVICE_FAILURE, "%s set affinity between process(pid=%d) with CPU's core failed", service->name, pid); + INIT_LOGI("%s set affinity between process(pid=%d) with CPU's core successfully", service->name, pid); +#endif + return SERVICE_SUCCESS; +} + +static void ClearEnvironment(Service *service) +{ + if (strcmp(service->name, "appspawn") != 0 && strcmp(service->name, "nwebspawn") != 0) { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGTERM); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + } + return; +} + +static void SetServiceEnv(Service *service) +{ + INIT_CHECK(service->env != NULL, return); + for (int i = 0; i < service->envCnt; i++) { + if (strlen(service->env[i].name) > 0 && strlen(service->env[i].value) > 0) { + int ret = setenv(service->env[i].name, service->env[i].value, 1); + INIT_CHECK_ONLY_ELOG(ret != 0, "set service:%s env:%s failed!", service->name, service->env[i].name); + } + } +} + +static int InitServiceProperties(Service *service, const ServiceArgs *pathArgs) +{ + INIT_ERROR_CHECK(service != NULL, return -1, "Invalid parameter."); + int ret = SetServiceEnterSandbox(service, pathArgs->argv[0]); + if (ret != 0) { + INIT_LOGW("Service warning %d %s, failed to enter sandbox.", ret, service->name); + service->lastErrno = INIT_ESANDBOX; + } + ret = SetAccessToken(service); + if (ret != 0) { + INIT_LOGW("Service warning %d %s, failed to set access token.", ret, service->name); + service->lastErrno = INIT_EACCESSTOKEN; + } + + SetServiceEnv(service); + + // deal start job + if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) { + DoJobNow(service->serviceJobs.jobsName[JOB_ON_START]); + INIT_LOGI("Deal service %s job end", service->name); + } + ClearEnvironment(service); + if (!IsOnDemandService(service)) { + INIT_ERROR_CHECK(CreateSocketForService(service) == 0, service->lastErrno = INIT_ESOCKET; + return INIT_ESOCKET, "Service error %d %s, failed to create service socket.", errno, service->name); + } + SetSocketEnvForService(service); + INIT_ERROR_CHECK(CreateServiceFile(service) == 0, service->lastErrno = INIT_EFILE; + return INIT_EFILE, "Service error %d %s, failed to create service file.", errno, service->name); + + if ((service->attribute & SERVICE_ATTR_CONSOLE)) { + INIT_ERROR_CHECK(OpenConsole() == 0, service->lastErrno = INIT_ECONSOLE; + return INIT_ECONSOLE, "Service error %d %s, failed to open console.", errno, service->name); + } + if ((service->attribute & SERVICE_ATTR_KMSG)) { + OpenKmsg(); + } + + INIT_ERROR_CHECK(PublishHoldFds(service) == 0, service->lastErrno = INIT_EHOLDER; + return INIT_EHOLDER, "Service error %d %s, failed to publish fd", errno, service->name); + + INIT_CHECK_ONLY_ELOG(BindCpuCore(service) == SERVICE_SUCCESS, + "Service warning %d %s, failed to publish fd", errno, service->name); + + // write pid + INIT_ERROR_CHECK(WritePid(service) == SERVICE_SUCCESS, service->lastErrno = INIT_EWRITEPID; + return INIT_EWRITEPID, "Service error %d %s, failed to write pid.", errno, service->name); + + // permissions + ret = SetPerms(service); + INIT_ERROR_CHECK(ret == SERVICE_SUCCESS, service->lastErrno = ret; + return ret, "Service error %d %s, failed to set permissions.", ret, service->name); + + PluginExecCmdByName("setServiceContent", service->name); + return 0; +} + +void EnterServiceSandbox(Service *service) +{ + INIT_ERROR_CHECK(InitServiceProperties(service, &service->pathArgs) == 0, return, "Failed init service property"); + if (service->importance != 0) { + if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) { + INIT_LOGE("setpriority failed for %s, importance = %d, err=%d", + service->name, service->importance, errno); + _exit(0x7f); // 0x7f: user specified + } + } +#ifndef STARTUP_INIT_TEST + char *argv[] = { (char *)"/bin/sh", NULL }; + INIT_CHECK_ONLY_ELOG(execv(argv[0], argv) == 0, + "service %s execv sh failed! err %d.", service->name, errno); + _exit(PROCESS_EXIT_CODE); +#endif +} + +#ifdef IS_DEBUG_VERSION +static bool ServiceNeedDebug(char *name) +{ + char nameValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int nameLen = PARAM_VALUE_LEN_MAX; + // specify process debugging: param set llvm.debug.service.name "service name" + if (SystemReadParam("llvm.debug.service.name", nameValue, &nameLen) == 0) { + if (strcmp(nameValue, name) == 0) { + return true; + } + } + + char debugValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int debugLen = PARAM_VALUE_LEN_MAX; + // multi process debugging: param set llvm.debug.service.all 1 + if (SystemReadParam("llvm.debug.service.all", debugValue, &debugLen) == 0) { + if (strcmp(debugValue, "1") == 0) { + return true; + } + } + return false; +} + +static bool IsDebuggableVersion(void) +{ + char secureValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int secureLen = PARAM_VALUE_LEN_MAX; + char debugValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int debugLen = PARAM_VALUE_LEN_MAX; + // the image is debuggable only when secureValue is 0 and debugValue is 1 + if (SystemReadParam("const.secure", secureValue, &secureLen) == 0 && + SystemReadParam("const.debuggable", debugValue, &debugLen) == 0) { + if (strcmp(secureValue, "0") == 0 && + strcmp(debugValue, "1") == 0) { + return true; + } + } + return false; +} + +static int32_t CheckTraceStatus(void) +{ + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) { + INIT_LOGE("lldb: open /proc/self/status error: %{public}d", errno); + return (-errno); + } + + char data[1024] = { 0 }; // 1024 data len + ssize_t dataNum = read(fd, data, sizeof(data)); + if (close(fd) < 0) { + INIT_LOGE("lldb: close fd error: %{public}d", errno); + return (-errno); + } + + if (dataNum <= 0) { + INIT_LOGE("lldb: fail to read data"); + return -1; + } + + const char* tracerPid = "TracerPid:\t"; + data[1023] = '\0'; // 1023 data last position + char *traceStr = strstr(data, tracerPid); + if (traceStr == NULL) { + INIT_LOGE("lldb: fail to find %{public}s", tracerPid); + return -1; + } + char *separator = strchr(traceStr, '\n'); + if (separator == NULL) { + INIT_LOGE("lldb: fail to find line break"); + return -1; + } + + int len = separator - traceStr - strlen(tracerPid); + char pid = *(traceStr + strlen(tracerPid)); + if (len > 1 || pid != '0') { + return 0; + } + return -1; +} + +static int32_t WaitForDebugger(void) +{ + uint32_t count = 0; + while (CheckTraceStatus() != 0) { + usleep(1000 * 100); // sleep 1000 * 100 microsecond + count++; + // remind users to connect to the debugger every 60 * 10 times + if (count % (10 * 60) == 0) { + INIT_LOGI("lldb: wait for debugger, please attach the process"); + count = 0; + } + } + return 0; +} +#endif + +static void CloseOnDemandServiceFdForOtherService(Service *service) +{ + ServiceSocket *tmpSockNode = GetOnDemandSocketList(); + while (tmpSockNode != NULL) { + if (tmpSockNode->service != service) { + ServiceSocket *tmpCloseSocket = tmpSockNode; + // If the service is not the OnDemand service itself, will close the OnDemand service socket fd + while (tmpCloseSocket != NULL) { + close(tmpCloseSocket->sockFd); + tmpCloseSocket = tmpCloseSocket->next; + } + } + tmpSockNode = tmpSockNode->nextNode; + } +} + +static void RunChildProcess(Service *service, ServiceArgs *pathArgs) +{ + // set selinux label by context + if (service->context.type != INIT_CONTEXT_MAIN && SetSubInitContext(&service->context, service->name) != 0) { + service->lastErrno = INIT_ECONTENT; + } + + CloseOnDemandServiceFdForOtherService(service); + +#ifdef IS_DEBUG_VERSION + // only the image is debuggable and need debug, then wait for debugger + if (ServiceNeedDebug(service->name) && IsDebuggableVersion()) { + WaitForDebugger(); + } +#endif +#ifdef INIT_ASAN + CloseStdio(); +#endif + // fail must exit sub process + int ret = InitServiceProperties(service, pathArgs); + INIT_ERROR_CHECK(ret == 0, + _exit(service->lastErrno), "Service error %d %s, failed to set properties", ret, service->name); + + (void)ServiceExec(service, pathArgs); + _exit(service->lastErrno); +} + +int ServiceStart(Service *service, ServiceArgs *pathArgs) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "ServiceStart failed! null ptr."); + INIT_INFO_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "ServiceStart already started:%s", service->name); + INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0, + return SERVICE_FAILURE, "ServiceStart pathArgs is NULL:%s", service->name); + struct timespec startingTime; + clock_gettime(CLOCK_REALTIME, &startingTime); + INIT_LOGI("ServiceStart starting:%s", service->name); + if (service->attribute & SERVICE_ATTR_INVALID) { + INIT_LOGE("ServiceStart invalid:%s", service->name); + return SERVICE_FAILURE; + } + struct stat pathStat = { 0 }; + service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP)); + if (stat(pathArgs->argv[0], &pathStat) != 0) { + service->attribute |= SERVICE_ATTR_INVALID; + service->lastErrno = INIT_EPATH; + INIT_LOGE("ServiceStart pathArgs invalid, please check %s,%s", service->name, service->pathArgs.argv[0]); + return SERVICE_FAILURE; + } +#ifndef OHOS_LITE + // before service fork hooks + ServiceHookExecute(service->name, NULL, INIT_SERVICE_FORK_BEFORE); +#endif + // pre-start job + if (service->serviceJobs.jobsName[JOB_PRE_START] != NULL) { + DoJobNow(service->serviceJobs.jobsName[JOB_PRE_START]); + } + struct timespec prefork; + clock_gettime(CLOCK_REALTIME, &prefork); + int pid = fork(); + if (pid == 0) { + RunChildProcess(service, pathArgs); + } else if (pid < 0) { + INIT_LOGE("ServiceStart error failed to fork %d, %s", errno, service->name); + service->lastErrno = INIT_EFORK; + return SERVICE_FAILURE; + } + struct timespec startedTime; + clock_gettime(CLOCK_REALTIME, &startedTime); + INIT_LOGI("ServiceStart started info %s(pid %d uid %d)", service->name, pid, service->servPerm.uID); + INIT_LOGI("starttime:%ld-%ld,preforktime:%ld-%ld,startedtime:%ld-%ld", + startingTime.tv_sec, startingTime.tv_nsec, prefork.tv_sec, + prefork.tv_nsec, startedTime.tv_sec, startedTime.tv_nsec); + service->pid = pid; + NotifyServiceChange(service, SERVICE_STARTED); +#ifndef OHOS_LITE + // after service fork hooks + ServiceHookExecute(service->name, (const char *)&pid, INIT_SERVICE_FORK_AFTER); +#endif + return SERVICE_SUCCESS; +} + +int ServiceStop(Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "stop service failed! null ptr."); + NotifyServiceChange(service, SERVICE_STOPPING); + if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) { + DoJobNow(service->serviceJobs.jobsName[JOB_ON_STOP]); + } + service->attribute &= ~SERVICE_ATTR_NEED_RESTART; + service->attribute |= SERVICE_ATTR_NEED_STOP; + if (service->pid <= 0) { + return SERVICE_SUCCESS; + } + CloseServiceSocket(service); + CloseServiceFile(service->fileCfg); + // Service stop means service is killed by init or command(i.e stop_service) or system is rebooting + // There is no reason still to hold fds + if (service->fdCount != 0) { + CloseServiceFds(service, true); + } + + if (IsServiceWithTimerEnabled(service)) { + ServiceStopTimer(service); + } + INIT_ERROR_CHECK(kill(service->pid, GetKillServiceSig(service->name)) == 0, return SERVICE_FAILURE, + "stop service %s pid %d failed! err %d.", service->name, service->pid, errno); + INIT_LOGI("stop service %s, pid %d.", service->name, service->pid); + service->pid = -1; + NotifyServiceChange(service, SERVICE_STOPPED); + return SERVICE_SUCCESS; +} + +static bool CalculateCrashTime(Service *service, int crashTimeLimit, int crashCountLimit) +{ + INIT_ERROR_CHECK(service != NULL && crashTimeLimit > 0 && crashCountLimit > 0, + return false, "input params error."); + struct timespec curTime = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &curTime); + struct timespec crashTime = {service->firstCrashTime, 0}; + if (service->crashCnt == 0) { + service->firstCrashTime = (uint32_t)curTime.tv_sec; + ++service->crashCnt; + if (service->crashCnt == crashCountLimit) { + return false; + } + } else if (IntervalTime(&crashTime, &curTime) > (uint32_t)crashTimeLimit) { + service->firstCrashTime = (uint32_t)curTime.tv_sec; + service->crashCnt = 1; + } else { + ++service->crashCnt; + if (service->crashCnt >= crashCountLimit) { + return false; + } + } + return true; +} + +static int ExecRestartCmd(Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr."); + if (service->restartArg == NULL) { + return SERVICE_SUCCESS; + } + for (int i = 0; i < service->restartArg->cmdNum; i++) { + INIT_LOGI("ExecRestartCmd cmdLine->cmdContent %s ", service->restartArg->cmds[i].cmdContent); + DoCmdByIndex(service->restartArg->cmds[i].cmdIndex, service->restartArg->cmds[i].cmdContent, NULL); + } + free(service->restartArg); + service->restartArg = NULL; + return SERVICE_SUCCESS; +} + +static void CheckServiceSocket(Service *service) +{ + if (service->socketCfg == NULL) { + return; + } + ServiceSocket *tmpSock = service->socketCfg; + while (tmpSock != NULL) { + if (tmpSock->sockFd <= 0) { + INIT_LOGE("Invalid socket %s for service", service->name); + tmpSock = tmpSock->next; + } + AddSocketWatcher(&tmpSock->watcher, service, tmpSock->sockFd); + tmpSock = tmpSock->next; + } + return; +} + +static bool IsDebugMode() +{ + char secureValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int secureLen = PARAM_VALUE_LEN_MAX; + char debugValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int debugLen = PARAM_VALUE_LEN_MAX; + // the image is debuggable only when secureValue is 0 and debugValue is 1 + if (SystemReadParam("const.secure", secureValue, &secureLen) == 0 && + SystemReadParam("const.debuggable", debugValue, &debugLen) == 0) { + if (strcmp(secureValue, "0") == 0 && + strcmp(debugValue, "1") == 0) { + return true; + } + } + return false; +} + +static void CheckOndemandService(Service *service) +{ + CheckServiceSocket(service); + if (strcmp(service->name, "console") == 0 && IsDebugMode()) { + INIT_LOGI("Watch console service in debug mode"); + if (WatchConsoleDevice(service) < 0) { + INIT_LOGE("Failed to watch console service after it exit, mark console service invalid"); + service->attribute |= SERVICE_ATTR_INVALID; + } + } +} + +static void ServiceReapHookExecute(Service *service) +{ +#ifndef OHOS_LITE + HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_REAP, (void*)service, NULL); +#endif +} + +void ServiceReap(Service *service) +{ + INIT_CHECK(service != NULL, return); + INIT_LOGI("ServiceReap info %s pid %d.", service->name, service->pid); + NotifyServiceChange(service, SERVICE_STOPPED); + int tmp = service->pid; + service->pid = -1; + + if (service->attribute & SERVICE_ATTR_INVALID) { + INIT_LOGE("ServiceReap error invalid service %s", service->name); + return; + } + + // If the service set timer + // which means the timer handler will start the service + // Init should not start it automatically. + INIT_CHECK(IsServiceWithTimerEnabled(service) == 0, return); + if (!IsOnDemandService(service)) { + CloseServiceSocket(service); + } + CloseServiceFile(service->fileCfg); + // stopped by system-init itself, no need to restart even if it is not one-shot service + if (service->attribute & SERVICE_ATTR_NEED_STOP) { + service->attribute &= (~SERVICE_ATTR_NEED_STOP); + service->crashCnt = 0; + return; + } + + // for one-shot service + if (service->attribute & SERVICE_ATTR_ONCE) { + // no need to restart + if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { + service->attribute &= (~SERVICE_ATTR_NEED_STOP); + return; + } + // the service could be restart even if it is one-shot service + } + + if (service->attribute & SERVICE_ATTR_PERIOD) { //period + ServiceStartTimer(service, service->period); + return; + } + + // service no need to restart if it is an ondemand service. + if (IsOnDemandService(service)) { + CheckOndemandService(service); + return; + } + + if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical + if (!CalculateCrashTime(service, service->crashTime, service->crashCount)) { + INIT_LOGE("ServiceReap error critical service crashed %s %d", service->name, service->crashCount); + service->pid = tmp; + ServiceReapHookExecute(service); + service->pid = -1; + ExecReboot("panic"); + } + } else if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { + if (!CalculateCrashTime(service, service->crashTime, service->crashCount)) { + INIT_LOGI("ServiceReap start failed! will reStart %d second later", service->name, service->crashTime); + service->crashCnt = 0; + ServiceReStartTimer(service, DEF_CRASH_TIME); + return; + } + } + + int ret = ExecRestartCmd(service); + INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "ServiceReap Failed to exec restartArg for %s", service->name); + + if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) { + DoJobNow(service->serviceJobs.jobsName[JOB_ON_RESTART]); + } + ret = ServiceStart(service, &service->pathArgs); + INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "ServiceReap ServiceStart failed %s", service->name); + service->attribute &= (~SERVICE_ATTR_NEED_RESTART); +} + +int UpdaterServiceFds(Service *service, int *fds, size_t fdCount) +{ + if (service == NULL || fds == NULL) { + INIT_LOGE("Invalid service info or fds"); + return -1; + } + + if (fdCount == 0) { + INIT_LOGE("Update service fds with fdCount is 0, ignore."); + return 0; + } + + // if service->fds is NULL, allocate new memory to hold the fds + // else if service->fds is not NULL, we will try to override it. + // There are two cases: + // 1) service->fdCount != fdCount: + // It is not easy to re-use the memory of service->fds, so we have to free the memory first + // then re-allocate memory to store new fds + // 2) service->fdCount == fdCount + // A situation we happy to meet, just override it. + + int ret = 0; + if (service->fdCount == fdCount) { + // case 2 + CloseServiceFds(service, false); + if (memcpy_s(service->fds, sizeof(int) * (fdCount + 1), fds, sizeof(int) * fdCount) != 0) { + INIT_LOGE("Failed to copy fds to service"); + // Something wrong happened, maybe service->fds is broken, clear it. + free(service->fds); + service->fds = NULL; + service->fdCount = 0; + ret = -1; + } else { + service->fdCount = fdCount; + } + } else { + if (service->fdCount > 0) { + // case 1 + CloseServiceFds(service, true); + } + INIT_ERROR_CHECK(fdCount <= MAX_HOLD_FDS, return -1, "Invalid fdCount %d", fdCount); + service->fds = calloc(fdCount + 1, sizeof(int)); + if (service->fds == NULL) { + INIT_LOGE("Service \' %s \' failed to allocate memory for fds", service->name); + ret = -1; + } else { + if (memcpy_s(service->fds, sizeof(int) * (fdCount + 1), fds, sizeof(int) * fdCount) != 0) { + INIT_LOGE("Failed to copy fds to service"); + // Something wrong happened, maybe service->fds is broken, clear it. + free(service->fds); + service->fds = NULL; + service->fdCount = 0; + return -1; + } else { + service->fdCount = fdCount; + } + } + } + INIT_LOGI("Hold fd for service \' %s \' done", service->name); + return ret; +} + +void ServiceStopTimer(Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return, "Stop timer with invalid service"); + if (IsServiceWithTimerEnabled(service)) { + // Stop timer first + if (service->timer) { + LE_StopTimer(LE_GetDefaultLoop(), service->timer); + } + service->timer = NULL; + DisableServiceTimer(service); + } +} + +static void ServiceTimerStartProcess(const TimerHandle handler, void *context) +{ + UNUSED(handler); + Service *service = (Service *)context; + + if (service == NULL) { + INIT_LOGE("Service timer process with invalid service"); + return; + } + + // OK, service is ready to start. + // Before start the service, stop service timer. + // make sure it will not enter timer handler next time. + ServiceStopTimer(service); + int ret = ServiceStart(service, &service->pathArgs); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("Start service \' %s \' in timer failed", service->name); + } +} + +static void ServiceTimerReStartProcess(const TimerHandle handler, void *context) +{ + UNUSED(handler); + Service *service = (Service *)context; + + if (service == NULL) { + INIT_LOGE("Service timer process with invalid service"); + return; + } + + // OK, service is ready to start. + // Before start the service, stop service timer. + // make sure it will not enter timer handler next time. + ServiceStopTimer(service); + + if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) { + DoJobNow(service->serviceJobs.jobsName[JOB_ON_RESTART]); + } + int ret = ServiceStart(service, &service->pathArgs); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("Start service \' %s \' in timer failed", service->name); + } +} + +void ServiceStartTimer(Service *service, uint64_t timeout) +{ + bool oldTimerClean = false; + INIT_ERROR_CHECK(service != NULL, return, "Start timer with invalid service"); + // If the service already set a timer. + // And a new request coming. close it and create a new one. + if (IsServiceWithTimerEnabled(service)) { + ServiceStopTimer(service); + oldTimerClean = true; + } + LE_STATUS status = LE_CreateTimer(LE_GetDefaultLoop(), &service->timer, ServiceTimerStartProcess, + (void *)service); + if (status != LE_SUCCESS) { + INIT_LOGE("Create service timer for service \' %s \' failed, status = %d", service->name, status); + if (oldTimerClean) { + INIT_LOGE("previous timer is cleared"); + } + return; + } + status = LE_StartTimer(LE_GetDefaultLoop(), service->timer, timeout, 1); + INIT_ERROR_CHECK(status == LE_SUCCESS, return, + "Start service timer for service \' %s \' failed, status = %d", service->name, status); + EnableServiceTimer(service); +} + +void ServiceReStartTimer(Service *service, uint64_t timeout) +{ + bool oldTimerClean = false; + INIT_ERROR_CHECK(service != NULL, return, "Start timer with invalid service"); + // If the service already set a timer. + // And a new request coming. close it and create a new one. + if (IsServiceWithTimerEnabled(service)) { + ServiceStopTimer(service); + oldTimerClean = true; + } + LE_STATUS status = LE_CreateTimer(LE_GetDefaultLoop(), &service->timer, ServiceTimerReStartProcess, + (void *)service); + if (status != LE_SUCCESS) { + INIT_LOGE("Create service timer for service \' %s \' failed, status = %d", service->name, status); + if (oldTimerClean) { + INIT_LOGE("previous timer is cleared"); + } + return; + } + status = LE_StartTimer(LE_GetDefaultLoop(), service->timer, timeout, 1); + INIT_ERROR_CHECK(status == LE_SUCCESS, return, + "Start service timer for service \' %s \' failed, status = %d", service->name, status); + EnableServiceTimer(service); +} diff --git a/services/init/init_config.c b/services/init/init_config.c new file mode 100644 index 0000000000000000000000000000000000000000..59c3a21091830cfe38fec994537a6f92d3aa3597 --- /dev/null +++ b/services/init/init_config.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020-2021 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 "init.h" +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "init_param.h" +#include "init_group_manager.h" + +static void ParseAllImports(const cJSON *root); + +InitContextType GetConfigContextType(const char *cfgName) +{ + static const char *vendorDir[] = { + "/vendor/etc/init/", "/chipset/etc/init/", "/chip_prod/etc/init/" + }; + + for (size_t j = 0; j < ARRAY_LENGTH(vendorDir); j++) { + if (strncmp(vendorDir[j], cfgName, strlen(vendorDir[j])) == 0) { + return INIT_CONTEXT_CHIPSET; + } + } + return INIT_CONTEXT_MAIN; +} + +static void ParseInitCfgContents(const char *cfgName, const cJSON *root) +{ + INIT_ERROR_CHECK(root != NULL, return, "Root is null"); + ConfigContext context = { INIT_CONTEXT_MAIN }; + context.type = GetConfigContextType(cfgName); + INIT_LOGV("Parse %s configs in context %d", cfgName, context.type); + ParseAllServices(root, &context); + // parse jobs + ParseAllJobs(root, &context); + // parse imports + ParseAllImports(root); +} + +int ParseInitCfg(const char *configFile, void *context) +{ + UNUSED(context); + INIT_LOGV("Parse init configs from %s", configFile); + char *fileBuf = ReadFileToBuf(configFile); + INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Cfg error, %s not found", configFile); + + cJSON *fileRoot = cJSON_Parse(fileBuf); + INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf); + return -1, "Cfg error, failed to parse json %s ", configFile); + + ParseInitCfgContents(configFile, fileRoot); + cJSON_Delete(fileRoot); + free(fileBuf); + return 0; +} + +static void ParseAllImports(const cJSON *root) +{ + char *tmpParamValue = calloc(PARAM_VALUE_LEN_MAX + 1, sizeof(char)); + INIT_ERROR_CHECK(tmpParamValue != NULL, return, "Failed to alloc memory for param"); + + cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import"); + if (!cJSON_IsArray(importAttr)) { + free(tmpParamValue); + return; + } + int importAttrSize = cJSON_GetArraySize(importAttr); + for (int i = 0; i < importAttrSize; i++) { + cJSON *importItem = cJSON_GetArrayItem(importAttr, i); + if (!cJSON_IsString(importItem)) { + INIT_LOGE("Invalid type of import item. should be string"); + break; + } + char *importContent = cJSON_GetStringValue(importItem); + if (importContent == NULL) { + INIT_LOGE("cannot get import config file"); + break; + } + int ret = GetParamValue(importContent, strlen(importContent), tmpParamValue, PARAM_VALUE_LEN_MAX); + if (ret != 0) { + INIT_LOGE("cannot get value for %s", importContent); + continue; + } + INIT_LOGI("Import %s ...", tmpParamValue); + ParseInitCfg(tmpParamValue, NULL); + } + free(tmpParamValue); + return; +} + +void ReadConfig(void) +{ + // parse cfg + char buffer[32] = {0}; // 32 reason max leb + uint32_t len = sizeof(buffer); + SystemReadParam("ohos.boot.mode", buffer, &len); + INIT_LOGI("ohos.boot.mode %s", buffer); + if ((strcmp(buffer, "charger_mode") == 0) || (GetBootModeFromMisc() == GROUP_CHARGE)) { + ParseInitCfg(INIT_CONFIGURATION_FILE, NULL); + ReadFileInDir(OTHER_CHARGE_PATH, ".cfg", ParseInitCfg, NULL); + ParseInitCfgByPriority(); + } else if (strcmp(buffer, "charger") == 0) { + ReadFileInDir(OTHER_CHARGE_PATH, ".cfg", ParseInitCfg, NULL); + } else if (InRescueMode() == 0) { + ParseInitCfg(INIT_CONFIGURATION_FILE, NULL); + ReadFileInDir(INIT_RESCUE_MODE_PATH, ".cfg", ParseInitCfg, NULL); + } else if (InUpdaterMode() == 0) { + ParseInitCfg(INIT_CONFIGURATION_FILE, NULL); + ParseInitCfgByPriority(); + } else { + ReadFileInDir("/etc", ".cfg", ParseInitCfg, NULL); + } +} diff --git a/services/init/init_group_manager.c b/services/init/init_group_manager.c new file mode 100644 index 0000000000000000000000000000000000000000..9700911b0b922962e39a4faadd428896a99ce268 --- /dev/null +++ b/services/init/init_group_manager.c @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2021 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 "init_group_manager.h" + +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_utils.h" +#include "securec.h" +#include "init_service_manager.h" + +static InitWorkspace g_initWorkspace = {0, 0, {0}, {0}, {0}}; + +ServiceSocket* GetOnDemandSocketList(void) +{ + return g_initWorkspace.serviceSocketNode; +} + +void AddOnDemandSocket(ServiceSocket *socketNode) +{ + INIT_ERROR_CHECK(socketNode != NULL, return, "socketNode is NULL!"); + socketNode->nextNode = g_initWorkspace.serviceSocketNode; + g_initWorkspace.serviceSocketNode = socketNode; +} + +void RemoveOnDemandSocket(ServiceSocket *sockopt) +{ + INIT_CHECK(sockopt != NULL, return); + ServiceSocket *tmp = g_initWorkspace.serviceSocketNode; + INIT_ERROR_CHECK(tmp != NULL, return, "tmp is NULL!"); + if (tmp->service == sockopt->service) { + g_initWorkspace.serviceSocketNode = tmp->nextNode; + return; + } + ServiceSocket *prev = tmp; + while (tmp != NULL) { + if (tmp->service != sockopt->service) { + prev = tmp; + tmp = tmp->nextNode; + continue; + } + prev->nextNode = tmp->nextNode; + return; + } +} + +int GenerateHashCode(const char *key) +{ + int code = 0; + size_t keyLen = strlen(key); + for (size_t i = 0; i < keyLen; i++) { + code += key[i] - 'A'; + } + return code; +} + +static int GetBootGroupMode(void) +{ + static const char *groupModes[] = { + "device.boot.group", + "device.charge.group" + }; + for (size_t i = 0; i < ARRAY_LENGTH(groupModes); i++) { + if (strcmp(g_initWorkspace.groupModeStr, groupModes[i]) == 0) { + return i; + } + } + return (int)GROUP_UNKNOW; +} + +static int ParseGroupCfgItem(cJSON *root, int type, const char *itemName) +{ + int itemNumber = 0; + cJSON *json = GetArrayItem(root, &itemNumber, itemName); + if (json == NULL) { + return 0; + } + + for (int i = 0; i < itemNumber; ++i) { + cJSON *item = cJSON_GetArrayItem(json, i); + char *strValue = cJSON_GetStringValue(item); + if (strValue != NULL) { + AddGroupNode(type, strValue); + } + } + return 0; +} + +static int InitParseGroupCfg_(const char *groupCfg) +{ + INIT_LOGI("Parse group config %s", groupCfg); + char *fileBuf = ReadFileData(groupCfg); + INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", groupCfg); + cJSON *fileRoot = cJSON_Parse(fileBuf); + INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf); + return -1, "Failed to parse json file %s", groupCfg); + + ParseGroupCfgItem(fileRoot, NODE_TYPE_JOBS, "jobs"); + ParseGroupCfgItem(fileRoot, NODE_TYPE_SERVICES, "services"); + ParseGroupCfgItem(fileRoot, NODE_TYPE_GROUPS, "groups"); + cJSON_Delete(fileRoot); + free(fileBuf); + return 0; +} + +static int InitImportGroupCfg_(InitGroupNode *groupRoot) +{ + InitGroupNode *groupNode = groupRoot; + while (groupNode != NULL) { + groupRoot = groupNode->next; + InitParseGroupCfg_(groupNode->name); + free(groupNode); + groupNode = groupRoot; + } + return 0; +} + +static int InitFreeGroupNodes_(InitGroupNode *groupRoot) +{ + InitGroupNode *groupNode = groupRoot; + while (groupNode != NULL) { + groupRoot = groupNode->next; + if (groupNode->type < NODE_TYPE_GROUPS) { // remove from hashmap + OH_HashMapRemove(g_initWorkspace.hashMap[groupNode->type], groupNode->name); + } + free(groupNode); + groupNode = groupRoot; + } + return 0; +} + +static char *GetAbsolutePath(const char *path, const char *cfgName, char *buffer, uint32_t buffSize) +{ + int len = 0; + size_t cfgNameLen = strlen(cfgName); + int ext = 0; + if (cfgNameLen > strlen(".cfg")) { + ext = strcmp(cfgName + cfgNameLen - strlen(".cfg"), ".cfg") == 0; + } + if (cfgName[0] != '/') { + const char *format = ((ext != 0) ? "%s/%s" : "%s/%s.cfg"); + len = sprintf_s(buffer, buffSize, format, path, cfgName); + } else { + const char *format = ((ext != 0) ? "%s" : "%s.cfg"); + len = sprintf_s(buffer, buffSize, format, cfgName); + } + if (len <= 0) { + return NULL; + } + buffer[len] = '\0'; + return buffer; +} + +static int GroupNodeNodeCompare(const HashNode *node1, const HashNode *node2) +{ + InitGroupNode *groupNode1 = HASHMAP_ENTRY(node1, InitGroupNode, hashNode); + InitGroupNode *groupNode2 = HASHMAP_ENTRY(node2, InitGroupNode, hashNode); + return strcmp(groupNode1->name, groupNode2->name); +} + +static int GroupNodeKeyCompare(const HashNode *node1, const void *key) +{ + InitGroupNode *groupNode1 = HASHMAP_ENTRY(node1, InitGroupNode, hashNode); + return strcmp(groupNode1->name, (char *)key); +} + +static int GroupNodeGetKeyHashCode(const void *key) +{ + return GenerateHashCode((const char *)key); +} + +static int GroupNodeGetNodeHashCode(const HashNode *node) +{ + InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode); + return GenerateHashCode((const char *)groupNode->name); +} + +static void GroupNodeFree(const HashNode *node, void *context) +{ + InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode); + if (groupNode->type == NODE_TYPE_SERVICES) { + ReleaseService(groupNode->data.service); + groupNode->data.service = NULL; + } else if (groupNode->type == NODE_TYPE_CMDS) { + ReleaseCmd(groupNode->data.cmd); + groupNode->data.cmd = NULL; + } + free(groupNode); +} + +void InitServiceSpace(void) +{ + if (g_initWorkspace.initFlags != 0) { + return; + } + HashInfo info = { + GroupNodeNodeCompare, + GroupNodeKeyCompare, + GroupNodeGetNodeHashCode, + GroupNodeGetKeyHashCode, + GroupNodeFree, + GROUP_HASHMAP_BUCKET + }; + for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) { + int ret = OH_HashMapCreate(&g_initWorkspace.hashMap[i], &info); + if (ret != 0) { + INIT_LOGE("%s", "Failed to create hash map"); + } + } + + for (int i = 0; i < NODE_TYPE_MAX; i++) { + g_initWorkspace.groupNodes[i] = NULL; + } + // get boot mode, set default mode + strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), BOOT_GROUP_DEFAULT); + int ret = GetParameterFromCmdLine(BOOT_GROUP_NAME, + g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr)); + if (ret != 0) { + INIT_LOGV("Failed to get boot group"); + if (GetBootModeFromMisc() == GROUP_CHARGE) { + strcpy_s(g_initWorkspace.groupModeStr, sizeof(g_initWorkspace.groupModeStr), "device.charge.group"); + } + } + INIT_LOGI("boot start %s", g_initWorkspace.groupModeStr); + g_initWorkspace.groupMode = GetBootGroupMode(); + g_initWorkspace.initFlags = 1; + g_initWorkspace.serviceSocketNode = NULL; +} + +int InitParseGroupCfg(void) +{ + char buffer[128] = {0}; // 128 buffer size + char *realPath = GetAbsolutePath(GROUP_DEFAULT_PATH, + g_initWorkspace.groupModeStr, buffer, sizeof(buffer)); + INIT_ERROR_CHECK(realPath != NULL, return -1, + "Failed to get path for %s", g_initWorkspace.groupModeStr); + InitParseGroupCfg_(realPath); + InitGroupNode *groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]; + int level = 0; + while ((groupRoot != NULL) && (level < GROUP_IMPORT_MAX_LEVEL)) { // for more import + g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL; + InitImportGroupCfg_(groupRoot); + groupRoot = g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]; + level++; + } + InitFreeGroupNodes_(g_initWorkspace.groupNodes[NODE_TYPE_GROUPS]); + g_initWorkspace.groupNodes[NODE_TYPE_GROUPS] = NULL; + return 0; +} + +InitGroupNode *AddGroupNode(int type, const char *name) +{ + INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type"); + INIT_ERROR_CHECK(name != NULL, return NULL, "Invalid name"); + InitGroupNode *groupNode = GetGroupNode(type, name); + if (groupNode != NULL) { + return groupNode; + } + INIT_LOGV("AddGroupNode type %d name %s", type, name); + uint32_t nameLen = (uint32_t)strlen(name); + groupNode = (InitGroupNode *)calloc(1, sizeof(InitGroupNode) + nameLen + 1); + INIT_ERROR_CHECK(groupNode != NULL, return NULL, "Failed to alloc for group %s", name); + int ret = memcpy_s(groupNode->name, nameLen + 1, name, nameLen + 1); + INIT_ERROR_CHECK(ret == 0, free(groupNode); + return NULL, "Failed to alloc for group %s", name); + groupNode->type = type; + groupNode->next = g_initWorkspace.groupNodes[type]; + g_initWorkspace.groupNodes[type] = groupNode; + + if (type < NODE_TYPE_GROUPS) { // add hashmap + OH_HashMapAdd(g_initWorkspace.hashMap[type], &groupNode->hashNode); + } + return groupNode; +} + +InitGroupNode *GetGroupNode(int type, const char *name) +{ + if (type >= NODE_TYPE_GROUPS) { + return NULL; + } + HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name); + if (node == NULL) { + return NULL; + } + return HASHMAP_ENTRY(node, InitGroupNode, hashNode); +} + +InitGroupNode *GetNextGroupNode(int type, const InitGroupNode *curr) +{ + INIT_ERROR_CHECK(type <= NODE_TYPE_MAX, return NULL, "Invalid type"); + if (curr == NULL) { + return g_initWorkspace.groupNodes[type]; + } + return curr->next; +} + +void DelGroupNode(int type, const char *name) +{ + if (type >= NODE_TYPE_GROUPS) { + return; + } + INIT_LOGV("DelGroupNode type %d name %s", type, name); + OH_HashMapRemove(g_initWorkspace.hashMap[type], name); + InitGroupNode *groupNode = g_initWorkspace.groupNodes[type]; + InitGroupNode *preNode = groupNode; + while (groupNode != NULL) { + if (strcmp(groupNode->name, name) != 0) { + preNode = groupNode; + groupNode = groupNode->next; + continue; + } + if (groupNode == g_initWorkspace.groupNodes[type]) { + g_initWorkspace.groupNodes[type] = groupNode->next; + } else { + preNode->next = groupNode->next; + } + free(groupNode); + break; + } +} + +int CheckNodeValid(int type, const char *name) +{ + if (type >= NODE_TYPE_GROUPS) { + return -1; + } + HashNode *node = OH_HashMapGet(g_initWorkspace.hashMap[type], name); + if (node != NULL) { + INIT_LOGV("Found %s in %s group", name, type == NODE_TYPE_JOBS ? "job" : "service"); + return 0; + } + if (g_initWorkspace.groupMode == GROUP_BOOT) { + // for boot start, can not start charger service + if (strcmp(name, "charger") == 0) { + return -1; + } + return 0; + } + return -1; +} + +HashMapHandle GetGroupHashMap(int type) +{ + if (type >= NODE_TYPE_GROUPS) { + return NULL; + } + return g_initWorkspace.hashMap[type]; +} + +void CloseServiceSpace(void) +{ + if (g_initWorkspace.initFlags == 0) { + return; + } + for (size_t i = 0; i < ARRAY_LENGTH(g_initWorkspace.hashMap); i++) { + if (g_initWorkspace.hashMap[i] != NULL) { + HashMapHandle handle = g_initWorkspace.hashMap[i]; + g_initWorkspace.hashMap[i] = NULL; + OH_HashMapDestory(handle, NULL); + } + } + g_initWorkspace.initFlags = 0; +} + +void ReleaseCmd(PluginCmd *cmd) +{ + if (cmd == NULL) { + return; + } + ListNode *node = cmd->cmdExecutor.next; + while (node != &cmd->cmdExecutor) { + PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node); + OH_ListRemove(&cmdExec->node); + free(cmdExec); + node = cmd->cmdExecutor.next; + } + free(cmd); +} + +#ifdef STARTUP_INIT_TEST +InitWorkspace *GetInitWorkspace(void) +{ + return &g_initWorkspace; +} +#endif diff --git a/services/init/init_service_file.c b/services/init/init_service_file.c new file mode 100644 index 0000000000000000000000000000000000000000..04f60552db71fe44f8d8bc1e8046a207ebbe9258 --- /dev/null +++ b/services/init/init_service_file.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020-2021 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 "init_service_file.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "init_log.h" +#include "init_service.h" +#include "init_utils.h" +#include "securec.h" + +#define HOS_FILE_ENV_PREFIX "OHOS_FILE_" +#define MAX_FILE_FD_LEN 16 + +static int CreateFile(ServiceFile *file) +{ + INIT_CHECK(file != NULL && file->fileName != NULL, return -1); + char path[PATH_MAX] = {0}; + if (realpath(file->fileName, path) == NULL) { + INIT_LOGE("Failed realpath err=%d", errno); + INIT_ERROR_CHECK(strncpy_s(path, strlen(file->fileName) + 1, file->fileName, strlen(file->fileName)) >= 0, + return -1, "Failed strncpy_s err=%d", errno); + } + INIT_LOGV("File path =%s . file flags =%d, file perm =%u ", path, file->flags, file->perm); + if (file->fd >= 0) { + close(file->fd); + file->fd = -1; + } + int fd = open(path, file->flags | O_CREAT, file->perm); + INIT_ERROR_CHECK(fd >= 0, return -1, "Failed open %s, err=%d ", path, errno); + close(fd); + INIT_CHECK_ONLY_ELOG(chmod(path, file->perm) >= 0, "Failed chmod err=%d", errno); + INIT_CHECK_ONLY_ELOG(chown(path, file->uid, file->gid) >= 0, "Failed chown err=%d", errno); + file->fd = open(path, file->flags); + return file->fd; +} + +static int SetFileEnv(int fd, const char *pathName) +{ + INIT_ERROR_CHECK(pathName != NULL, return -1, "Invalid fileName"); + char pubName[PATH_MAX] = { 0 }; + INIT_ERROR_CHECK(snprintf_s(pubName, sizeof(pubName), sizeof(pubName) - 1, + HOS_FILE_ENV_PREFIX "%s", pathName) >= 0, return -1, "Failed snprintf_s err=%d", errno); + INIT_ERROR_CHECK(StringReplaceChr(pubName, '/', '_') >= 0, return -1, "Failed StringReplaceChr"); + char val[MAX_FILE_FD_LEN] = { 0 }; + INIT_ERROR_CHECK(snprintf_s(val, sizeof(val), sizeof(val) - 1, "%d", fd) >= 0, return -1, + "Failed snprintf_s err=%d", errno); + int ret = setenv(pubName, val, 1); + INIT_ERROR_CHECK(ret >= 0, return -1, "Failed setenv err=%d ", errno); + fcntl(fd, F_SETFD, 0); + return 0; +} + +int CreateServiceFile(Service *service) +{ + INIT_CHECK(service != NULL, return INIT_EPARAMETER); + ServiceFile *tmpFile = service->fileCfg; + int ret = 0; + while (tmpFile != NULL) { + int fd = CreateFile(tmpFile); + if (fd < 0) { + ret++; + INIT_LOGE("Service error %d %s, failed to create file", errno, service->name, tmpFile->fileName); + tmpFile = tmpFile->next; + continue; + } + if (SetFileEnv(fd, tmpFile->fileName) != 0) { + ret++; + INIT_LOGE("Service error %d %s, failed to set env for file", errno, service->name, tmpFile->fileName); + } + tmpFile = tmpFile->next; + } + return ret > 0 ? INIT_EFILE : 0; +} + +void CloseServiceFile(ServiceFile *fileOpt) +{ + INIT_CHECK(fileOpt != NULL, return); + ServiceFile *tmpFileOpt = fileOpt; + while (tmpFileOpt != NULL) { + ServiceFile *tmp = tmpFileOpt; + if (tmp->fd >= 0) { + close(tmp->fd); + tmp->fd = -1; + } + tmpFileOpt = tmpFileOpt->next; + } + return; +} diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c new file mode 100755 index 0000000000000000000000000000000000000000..83ffb5e8a1e8f40bc7e933fb7a4db60f0d64ad24 --- /dev/null +++ b/services/init/init_service_manager.c @@ -0,0 +1,1324 @@ +/* + * Copyright (c) 2020-2021 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 "init_service_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" +#include "init.h" +#include "init_group_manager.h" +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_service_file.h" +#include "init_service_socket.h" +#include "init_utils.h" +#include "securec.h" +#include "service_control.h" +#ifdef ASAN_DETECTOR +#include "init_param.h" +#endif + +#ifndef OHOS_LITE +#include "hookmgr.h" +#include "bootstage.h" +#endif + +#define VALUE_ATTR_CONSOLE 1 +#define VALUE_ATTR_KMSG 2 + +// All service processes that init will fork+exec. +ServiceSpace g_serviceSpace = { 0 }; +static const int CRITICAL_DEFAULT_CRASH_TIME = 240; +// maximum number of crashes within time CRITICAL_DEFAULT_CRASH_TIME for one service +static const int CRITICAL_DEFAULT_CRASH_COUNT = 4; +static const int CRITICAL_CONFIG_ARRAY_LEN = 3; +static const int REBOOT_WAIT_TIME = 100000; +static const int INTERVAL_PER_WAIT = 10; + +static void FreeServiceArg(ServiceArgs *arg) +{ + if (arg == NULL) { + return; + } + for (int i = 0; i < arg->count; ++i) { + if (arg->argv[i] != NULL) { + free(arg->argv[i]); + arg->argv[i] = NULL; + } + } + free(arg->argv); + arg->argv = NULL; + arg->count = 0; +} + +static void FreeServiceSocket(ServiceSocket *sockopt) +{ + // remove service socket list head node from OnDemand socket list before free OnDemand service socket + RemoveOnDemandSocket(sockopt); + while (sockopt != NULL) { + ServiceSocket *tmp = sockopt; + if (tmp->sockFd >= 0) { + close(tmp->sockFd); + tmp->sockFd = -1; + } + sockopt = sockopt->next; + free(tmp); + } + sockopt = NULL; + return; +} + +Service *AddService(const char *name) +{ + // check service in group + if (CheckNodeValid(NODE_TYPE_SERVICES, name) != 0) { + INIT_LOGI("Service %s not exist in group ", name); + return NULL; + } + InitGroupNode *node = AddGroupNode(NODE_TYPE_SERVICES, name); + if (node == NULL) { + INIT_LOGE("Failed to create service name %s", name); + return NULL; + } + if (node->data.service != NULL) { + ReleaseService(node->data.service); + node->data.service = NULL; + } + Service *service = (Service *)calloc(1, sizeof(Service)); + INIT_ERROR_CHECK(service != NULL, return NULL, "Failed to malloc for service"); + node->data.service = service; + service->name = node->name; + service->status = SERVICE_IDLE; + service->cpuSet = NULL; + service->pid = -1; + service->context.type = INIT_CONTEXT_MAIN; + service->lastErrno = INIT_OK; + OH_ListInit(&service->extDataNode); + g_serviceSpace.serviceCount++; + INIT_LOGV("AddService %s", node->name); + return service; +} + +static void FreeServiceFile(ServiceFile *fileOpt) +{ + while (fileOpt != NULL) { + ServiceFile *tmp = fileOpt; + if (tmp->fd >= 0) { + close(tmp->fd); + tmp->fd = -1; + } + fileOpt = fileOpt->next; + free(tmp); + } + fileOpt = NULL; + return; +} + +static void ExecuteServiceClear(Service *service) +{ +#ifndef OHOS_LITE + // clear ext data + SERVICE_INFO_CTX ctx = {0}; + ctx.serviceName = service->name; + HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL); +#endif +} + +void ReleaseService(Service *service) +{ + INIT_CHECK(service != NULL, return); + FreeServiceArg(&service->pathArgs); + FreeServiceArg(&service->writePidArgs); + FreeServiceArg(&service->capsArgs); + FreeServiceArg(&service->permArgs); + FreeServiceArg(&service->permAclsArgs); + + if (service->servPerm.caps != NULL) { + free(service->servPerm.caps); + service->servPerm.caps = NULL; + } + service->servPerm.capsCnt = 0; + if (service->servPerm.gIDArray != NULL) { + free(service->servPerm.gIDArray); + service->servPerm.gIDArray = NULL; + } + service->servPerm.gIDCnt = 0; + + FreeServiceSocket(service->socketCfg); + FreeServiceFile(service->fileCfg); + + if (service->apl != NULL) { + free(service->apl); + service->apl = NULL; + } + + if (service->env != NULL) { + free(service->env); + service->env = NULL; + } + + for (size_t i = 0; i < JOB_ON_MAX; i++) { + if (service->serviceJobs.jobsName[i] != NULL) { + free(service->serviceJobs.jobsName[i]); + } + service->serviceJobs.jobsName[i] = NULL; + } + if (service->cpuSet != NULL) { + free(service->cpuSet); + service->cpuSet = NULL; + } + if (service->restartArg != NULL) { + free(service->restartArg); + service->restartArg = NULL; + } + CloseServiceFds(service, true); + ExecuteServiceClear(service); + g_serviceSpace.serviceCount--; + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, service->name); + INIT_CHECK(groupNode == NULL, groupNode->data.service = NULL); + free(service); +} + +static char *GetStringValue(const cJSON *json, const char *name, size_t *strLen) +{ + char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(json, name)); + INIT_CHECK(fieldStr != NULL, return NULL); + *strLen = strlen(fieldStr); + return fieldStr; +} + +cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName) +{ + cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName); + if (!cJSON_IsArray(arrItem)) { + return NULL; + } + *arrSize = cJSON_GetArraySize(arrItem); + INIT_CHECK_RETURN_VALUE(*arrSize > 0, NULL); + return arrItem; +} + +static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, ServiceArgs *args) +{ + INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson"); + cJSON *obj = cJSON_GetObjectItem(argJson, name); + INIT_CHECK(obj != NULL, return SERVICE_FAILURE); + + int ret = cJSON_IsArray(obj); + INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type"); + int count = cJSON_GetArraySize(obj); + INIT_ERROR_CHECK((count > 0) && (count < maxCount), return SERVICE_FAILURE, + "Args size is wrong %s, %d", name, count); + if ((args->argv != NULL) && (args->count > 0)) { + FreeServiceArg(args); + } + args->argv = (char **)malloc((count + 1) * sizeof(char *)); + INIT_ERROR_CHECK(args->argv != NULL, return SERVICE_FAILURE, "Failed to malloc for argv"); + for (int i = 0; i < count + 1; ++i) { + args->argv[i] = NULL; + } + // ServiceArgs have a variety of uses, some requiring a NULL ending, some not + if (strcmp(name, D_CAPS_STR_IN_CFG) != 0 && strcmp(name, "permission_acls") != 0 && + strcmp(name, "permission") != 0) { + args->count = count + 1; + } else { + args->count = count; + } + for (int i = 0; i < count; ++i) { + char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i)); + INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i); + INIT_ERROR_CHECK(strlen(curParam) <= MAX_ONE_ARG_LEN, return SERVICE_FAILURE, "Arg %s is tool long", curParam); + args->argv[i] = strdup(curParam); + INIT_ERROR_CHECK(args->argv[i] != NULL, return SERVICE_FAILURE, "Failed to duplicate argument %s", curParam); + } + return SERVICE_SUCCESS; +} + +static int GetUid(cJSON *json, uid_t *uid) +{ + INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS); + if (cJSON_IsString(json)) { + char *str = cJSON_GetStringValue(json); + INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Invalid str"); + *uid = DecodeUid(str); + } else if (cJSON_IsNumber(json)) { + *uid = (uid_t)cJSON_GetNumberValue(json); + } else { + *uid = (uid_t)(-1); + } + INIT_CHECK_RETURN_VALUE(*uid != (uid_t)(-1), SERVICE_FAILURE); + return SERVICE_SUCCESS; +} + +static int GetGid(cJSON *json, gid_t *gid, Service *curServ) +{ + INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS); + if (cJSON_IsString(json)) { + char *str = cJSON_GetStringValue(json); + INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Failed to get gid for %s", curServ->name); + *gid = DecodeGid(str); + } else if (cJSON_IsNumber(json)) { + *gid = (gid_t)cJSON_GetNumberValue(json); + } else { + INIT_LOGW("Service %s with invalid gid configuration", curServ->name); + *gid = -1; // Invalid gid, set as -1 + } + INIT_CHECK_RETURN_VALUE(*gid != (gid_t)(-1), SERVICE_FAILURE); + return SERVICE_SUCCESS; +} + +static int GetServiceGids(const cJSON *curArrItem, Service *curServ) +{ + int gidCount; + cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(curArrItem, GID_STR_IN_CFG); + if (!arrItem) { + return SERVICE_SUCCESS; + } else if (!cJSON_IsArray(arrItem)) { + gidCount = 1; + } else { + gidCount = cJSON_GetArraySize(arrItem); + } + INIT_ERROR_CHECK((gidCount != 0) && (gidCount <= NGROUPS_MAX + 1), return SERVICE_FAILURE, + "Invalid gid count %d", gidCount); + if (curServ->servPerm.gIDArray != NULL) { + free(curServ->servPerm.gIDArray); + } + curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * (gidCount + 1)); + INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc err=%d", errno); + curServ->servPerm.gIDCnt = gidCount; + + gid_t gid; + if (!cJSON_IsArray(arrItem)) { + int ret = GetGid(arrItem, &gid, curServ); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, + "Service error %s, failed to get gid.", curServ->name); + curServ->servPerm.gIDArray[0] = gid; + return SERVICE_SUCCESS; + } + int gidArrayIndex = 0; + for (int i = 0; i < gidCount; ++i) { + cJSON *item = cJSON_GetArrayItem(arrItem, i); + int ret = GetGid(item, &gid, curServ); + if (ret != 0) { + INIT_LOGW("Service warning %s, failed to get gid.", curServ->name); + continue; + } + curServ->servPerm.gIDArray[gidArrayIndex++] = gid; + } + if (gidArrayIndex == 0) { + curServ->servPerm.gIDArray[gidArrayIndex++] = curServ->servPerm.uID; + } + curServ->servPerm.gIDCnt = gidArrayIndex; + return SERVICE_SUCCESS; +} + +static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag, + int (*processAttr)(Service *curServ, const char *attrName, int value, int flag)) +{ + cJSON *filedJ = cJSON_GetObjectItem(curArrItem, attrName); + if (filedJ == NULL) { + return SERVICE_SUCCESS; + } + INIT_ERROR_CHECK(cJSON_IsNumber(filedJ), return SERVICE_FAILURE, + "Service error %s is null or is not a number %s", curServ->name, attrName); + curServ->attribute &= ~flag; + int value = (int)cJSON_GetNumberValue(filedJ); + if (processAttr == NULL) { + if (value == 1) { + curServ->attribute |= flag; + } + return 0; + } + return processAttr(curServ, attrName, value, flag); +} + +static int ParseSocketFamily(cJSON *json, ServiceSocket *sockopt) +{ + sockopt->family = AF_UNIX; + size_t strLen = 0; + char *stringValue = GetStringValue(json, "family", &strLen); + INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE, + "Failed to get string for family"); + if (strcmp(stringValue, "AF_UNIX") == 0) { + sockopt->family = AF_UNIX; + } else if (strncmp(stringValue, "AF_NETLINK", strLen) == 0) { + sockopt->family = AF_NETLINK; + } + return 0; +} + +static int ParseSocketType(cJSON *json, ServiceSocket *sockopt) +{ + sockopt->type = SOCK_SEQPACKET; + size_t strLen = 0; + char *stringValue = GetStringValue(json, "type", &strLen); + INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE, + "Failed to get string for type"); + if (strncmp(stringValue, "SOCK_SEQPACKET", strLen) == 0) { + sockopt->type = SOCK_SEQPACKET; + } else if (strncmp(stringValue, "SOCK_STREAM", strLen) == 0) { + sockopt->type = SOCK_STREAM; + } else if (strncmp(stringValue, "SOCK_DGRAM", strLen) == 0) { + sockopt->type = SOCK_DGRAM; + } + return 0; +} + +static int ParseSocketProtocol(cJSON *json, ServiceSocket *sockopt) +{ + sockopt->protocol = 0; + size_t strLen = 0; + char *stringValue = GetStringValue(json, "protocol", &strLen); + INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), return SERVICE_FAILURE, + "Failed to get string for protocol"); + if (strncmp(stringValue, "default", strLen) == 0) { + sockopt->protocol = 0; + } else if (strncmp(stringValue, "NETLINK_KOBJECT_UEVENT", strLen) == 0) { +#ifndef __LITEOS_A__ + sockopt->protocol = NETLINK_KOBJECT_UEVENT; +#else + return -1; +#endif + } + return 0; +} + +static int ParseSocketOption(cJSON *json, ServiceSocket *sockopt) +{ + sockopt->option = 0; + unsigned int tempType = 0; + int typeCnt = 0; + char *stringValue = NULL; + cJSON *typeItem = NULL; + cJSON *typeArray = GetArrayItem(json, &typeCnt, "option"); + INIT_CHECK((typeArray != NULL) && (typeCnt > 0), return 0); + for (int i = 0; i < typeCnt; ++i) { + typeItem = cJSON_GetArrayItem(typeArray, i); + INIT_CHECK_RETURN_VALUE(cJSON_IsString(typeItem), SERVICE_FAILURE); + stringValue = cJSON_GetStringValue(typeItem); + INIT_ERROR_CHECK(stringValue != NULL, return SERVICE_FAILURE, "Failed to get string for type"); + if (strncmp(stringValue, "SOCKET_OPTION_PASSCRED", strlen(stringValue)) == 0) { + sockopt->option |= SOCKET_OPTION_PASSCRED; + } else if (strncmp(stringValue, "SOCKET_OPTION_RCVBUFFORCE", strlen(stringValue)) == 0) { + sockopt->option |= SOCKET_OPTION_RCVBUFFORCE; + } else if (strncmp(stringValue, "SOCK_CLOEXEC", strlen(stringValue)) == 0) { + tempType |= SOCK_CLOEXEC; + } else if (strncmp(stringValue, "SOCK_NONBLOCK", strlen(stringValue)) == 0) { + tempType |= SOCK_NONBLOCK; + } + } + if (tempType != 0) { + sockopt->type |= tempType; + } + return 0; +} + +static int AddServiceSocket(cJSON *json, Service *service) +{ + size_t strLen = 0; + char* fieldStr = GetStringValue(json, "name", &strLen); + INIT_ERROR_CHECK(fieldStr != NULL, return SERVICE_FAILURE, "Failed to get socket name"); + INIT_ERROR_CHECK(strLen <= MAX_SERVICE_NAME, return SERVICE_FAILURE, "socket name exceeds length limit"); + ServiceSocket *sockopt = (ServiceSocket *)calloc(1, sizeof(ServiceSocket) + strLen + 1); + INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for service %s", service->name); + + int ret = strcpy_s(sockopt->name, strLen + 1, fieldStr); + INIT_INFO_CHECK(ret == 0, free(sockopt); sockopt = NULL; return SERVICE_FAILURE, + "Failed to copy socket name %s", fieldStr); + sockopt->sockFd = -1; + sockopt->watcher = NULL; + sockopt->service = service; + + ret = ParseSocketFamily(json, sockopt); + INIT_ERROR_CHECK(ret == 0, free(sockopt); + return SERVICE_FAILURE, "Failed to parse socket family"); + ret = ParseSocketType(json, sockopt); + INIT_ERROR_CHECK(ret == 0, free(sockopt); + return SERVICE_FAILURE, "Failed to parse socket type"); + ret = ParseSocketProtocol(json, sockopt); + INIT_ERROR_CHECK(ret == 0, free(sockopt); + return SERVICE_FAILURE, "Failed to parse socket protocol"); + + char *stringValue = GetStringValue(json, "permissions", &strLen); + INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt); + return SERVICE_FAILURE, "Failed to get string for permissions"); + sockopt->perm = strtoul(stringValue, 0, OCTAL_BASE); + stringValue = GetStringValue(json, "uid", &strLen); + INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt); + return SERVICE_FAILURE, "Failed to get string for uid"); + sockopt->uid = DecodeUid(stringValue); + stringValue = GetStringValue(json, "gid", &strLen); + INIT_ERROR_CHECK((stringValue != NULL) && (strLen > 0), free(sockopt); + return SERVICE_FAILURE, "Failed to get string for gid"); + sockopt->gid = DecodeGid(stringValue); + INIT_ERROR_CHECK((sockopt->uid != (uid_t)-1) && (sockopt->gid != (uid_t)-1), free(sockopt); + return SERVICE_FAILURE, "Invalid uid or gid"); + ret = ParseSocketOption(json, sockopt); + INIT_ERROR_CHECK(ret == 0, free(sockopt); + return SERVICE_FAILURE, "Failed to parse socket option"); + + sockopt->next = NULL; + if (service->socketCfg == NULL) { + service->socketCfg = sockopt; + } else { + sockopt->next = service->socketCfg->next; + service->socketCfg->next = sockopt; + } + return SERVICE_SUCCESS; +} + +static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ) +{ + int sockCnt = 0; + cJSON *filedJ = GetArrayItem(curArrItem, &sockCnt, "socket"); + INIT_CHECK(filedJ != NULL && sockCnt > 0, return SERVICE_FAILURE); + + CloseServiceSocket(curServ); + FreeServiceSocket(curServ->socketCfg); + int ret = 0; + curServ->socketCfg = NULL; + for (int i = 0; i < sockCnt; ++i) { + cJSON *sockJ = cJSON_GetArrayItem(filedJ, i); + ret = AddServiceSocket(sockJ, curServ); + if (ret != 0) { + return ret; + } + } + if (IsOnDemandService(curServ)) { + ret = CreateSocketForService(curServ); + } + return ret; +} + +static int AddServiceFile(cJSON *json, Service *service) +{ + if (!cJSON_IsString(json) || !cJSON_GetStringValue(json)) { + return SERVICE_FAILURE; + } + char *fileStr = cJSON_GetStringValue(json); + char *opt[FILE_OPT_NUMS] = { + NULL, + }; + int num = SplitString(fileStr, " ", opt, FILE_OPT_NUMS); + INIT_CHECK_RETURN_VALUE(num == FILE_OPT_NUMS, SERVICE_FAILURE); + if (opt[SERVICE_FILE_NAME] == NULL || opt[SERVICE_FILE_FLAGS] == NULL || opt[SERVICE_FILE_PERM] == NULL || + opt[SERVICE_FILE_UID] == NULL || opt[SERVICE_FILE_GID] == NULL) { + INIT_LOGE("Invalid file opt"); + return SERVICE_FAILURE; + } + ServiceFile *fileOpt = (ServiceFile *)calloc(1, sizeof(ServiceFile) + strlen(opt[SERVICE_FILE_NAME]) + 1); + INIT_INFO_CHECK(fileOpt != NULL, return SERVICE_FAILURE, "Failed to calloc for file %s", opt[SERVICE_FILE_NAME]); + int ret = strcpy_s(fileOpt->fileName, strlen(opt[SERVICE_FILE_NAME]) + 1, opt[SERVICE_FILE_NAME]); + INIT_INFO_CHECK(ret == 0, free(fileOpt); + return SERVICE_FAILURE, "Failed to copy file name %s", opt[SERVICE_FILE_NAME]); + if (strcmp(opt[SERVICE_FILE_FLAGS], "rd") == 0) { + fileOpt->flags = O_RDONLY; + } else if (strcmp(opt[SERVICE_FILE_FLAGS], "wd") == 0) { + fileOpt->flags = O_WRONLY; + } else if (strcmp(opt[SERVICE_FILE_FLAGS], "rw") == 0) { + fileOpt->flags = O_RDWR; + } else { + INIT_LOGE("Failed file flags %s", opt[SERVICE_FILE_FLAGS]); + free(fileOpt); + fileOpt = NULL; + return SERVICE_FAILURE; + } + fileOpt->perm = strtoul(opt[SERVICE_FILE_PERM], 0, OCTAL_BASE); + fileOpt->uid = DecodeUid(opt[SERVICE_FILE_UID]); + fileOpt->gid = DecodeGid(opt[SERVICE_FILE_GID]); + if (fileOpt->uid == (uid_t)-1 || fileOpt->gid == (gid_t)-1) { + free(fileOpt); + fileOpt = NULL; + INIT_LOGE("Invalid uid or gid"); + return SERVICE_FAILURE; + } + fileOpt->fd = -1; + fileOpt->next = NULL; + if (service->fileCfg == NULL) { + service->fileCfg = fileOpt; + } else { + fileOpt->next = service->fileCfg->next; + service->fileCfg->next = fileOpt; + } + return SERVICE_SUCCESS; +} + +static int ParseServiceFile(const cJSON *curArrItem, Service *curServ) +{ + int fileCnt = 0; + cJSON *filedJ = GetArrayItem(curArrItem, &fileCnt, "file"); + INIT_CHECK(filedJ != NULL && fileCnt > 0, return SERVICE_FAILURE); + FreeServiceFile(curServ->fileCfg); + int ret = 0; + curServ->fileCfg = NULL; + for (int i = 0; i < fileCnt; ++i) { + cJSON *fileJ = cJSON_GetArrayItem(filedJ, i); + ret = AddServiceFile(fileJ, curServ); + if (ret != 0) { + break; + } + } + return ret; +} + +static int GetServiceOnDemand(const cJSON *curArrItem, Service *curServ) +{ + cJSON *item = cJSON_GetObjectItem(curArrItem, "ondemand"); + if (item == NULL) { + return SERVICE_SUCCESS; + } + + INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE, + "Service : %s ondemand value only support bool.", curServ->name); + curServ->attribute &= ~SERVICE_ATTR_ONDEMAND; + + INIT_INFO_CHECK(cJSON_IsTrue(item), return SERVICE_SUCCESS, + "Service : %s ondemand value is false, it should be pulled up by init", curServ->name); + if (curServ->attribute & SERVICE_ATTR_CRITICAL) { + INIT_LOGE("Service : %s is invalid which has both critical and ondemand attribute", curServ->name); + return SERVICE_FAILURE; + } + + curServ->attribute |= SERVICE_ATTR_ONDEMAND; + return SERVICE_SUCCESS; +} + +static int GetServiceSetuid(const cJSON *curArrItem, Service *curServ) +{ + cJSON *item = cJSON_GetObjectItem(curArrItem, "setuid"); + if (item == NULL) { + return SERVICE_SUCCESS; + } + + INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE, + "Service : %s setuid value only support bool.", curServ->name); + curServ->attribute &= ~SERVICE_ATTR_SETUID; + + INIT_INFO_CHECK(cJSON_IsTrue(item), return SERVICE_SUCCESS, + "Service : %s setuid value is false, it should be pulled up by init", curServ->name); + + curServ->attribute |= SERVICE_ATTR_SETUID; + return SERVICE_SUCCESS; +} + +static int GetMapValue(const char *name, const InitArgInfo *infos, int argNum, int defValue) +{ + if ((argNum == 0) || (infos == NULL) || (name == NULL)) { + return defValue; + } + for (int i = 0; i < argNum; i++) { + if (strcmp(infos[i].name, name) == 0) { + return infos[i].value; + } + } + return defValue; +} + +static int GetServiceMode(Service *service, const cJSON *json) +{ + const InitArgInfo startModeMap[] = { + {"condition", START_MODE_CONDITION}, + {"boot", START_MODE_BOOT}, + {"normal", START_MODE_NORMAL} + }; + const InitArgInfo endModeMap[] = { + {"pre-fork", END_PRE_FORK}, + {"after-fork", END_AFTER_FORK}, + {"after-exec", END_AFTER_EXEC}, + {"ready", END_RECV_READY} + }; + service->startMode = START_MODE_NORMAL; + service->endMode = END_AFTER_EXEC; + char *value = cJSON_GetStringValue(cJSON_GetObjectItem(json, "start-mode")); + if (value != NULL) { + service->startMode = GetMapValue(value, + (InitArgInfo *)startModeMap, (int)ARRAY_LENGTH(startModeMap), START_MODE_NORMAL); + } + value = cJSON_GetStringValue(cJSON_GetObjectItem(json, "end-mode")); + if (value != NULL) { + service->endMode = GetMapValue(value, + (InitArgInfo *)endModeMap, (int)ARRAY_LENGTH(endModeMap), END_AFTER_EXEC); + } + return 0; +} + +static int GetServiceJobs(Service *service, cJSON *json) +{ + const char *jobTypes[] = { + "on-boot", "pre-start", "on-start", "on-stop", "on-restart" + }; + for (int i = 0; i < (int)ARRAY_LENGTH(jobTypes); i++) { + char *jobName = cJSON_GetStringValue(cJSON_GetObjectItem(json, jobTypes[i])); + if (jobName != NULL) { + if (service->serviceJobs.jobsName[i] != NULL) { + DelGroupNode(NODE_TYPE_JOBS, service->serviceJobs.jobsName[i]); + free(service->serviceJobs.jobsName[i]); + } + service->serviceJobs.jobsName[i] = strdup(jobName); + if (service->serviceJobs.jobsName[i] == NULL) { + return SERVICE_FAILURE; + } + // save job name for group job check + AddGroupNode(NODE_TYPE_JOBS, jobName); + } + } + return SERVICE_SUCCESS; +} + +int GetCritical(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag) +{ + int criticalSize = 0; + curServ->crashCount = CRITICAL_DEFAULT_CRASH_COUNT; + curServ->crashTime = CRITICAL_DEFAULT_CRASH_TIME; + cJSON *arrItem = cJSON_GetObjectItem(curArrItem, attrName); + if (arrItem == NULL) { + return SERVICE_SUCCESS; + } + + if (cJSON_IsNumber(arrItem)) { + return GetServiceAttr(curArrItem, curServ, attrName, flag, NULL); + } else if (cJSON_IsArray(arrItem)) { + criticalSize = cJSON_GetArraySize(arrItem); + cJSON *attrItem = cJSON_GetArrayItem(arrItem, 0); // 0 : critical attribute index + if (attrItem == NULL || !cJSON_IsNumber(attrItem)) { + INIT_LOGE("%s critical invalid", curServ->name); + return SERVICE_FAILURE; + } + int attrValue = (int)cJSON_GetNumberValue(attrItem); + curServ->attribute &= ~flag; + if (criticalSize == 1) { + if (attrValue == 1) { + curServ->attribute |= flag; + } + } else if (criticalSize == CRITICAL_CONFIG_ARRAY_LEN) { + cJSON *crashCountItem = cJSON_GetArrayItem(arrItem, 1); // 1 : critical crash count index + INIT_ERROR_CHECK(crashCountItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name); + int value = (int)cJSON_GetNumberValue(crashCountItem); + INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crashc ount invalid", curServ->name); + curServ->crashCount = value; + + cJSON *crashTimeItem = cJSON_GetArrayItem(arrItem, 2); // 2 : critical crash time index + INIT_ERROR_CHECK(crashTimeItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name); + value = (int)cJSON_GetNumberValue(crashTimeItem); + INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crash time invalid", curServ->name); + curServ->crashTime = value; + + if (attrValue == 1) { + curServ->attribute |= flag; + } + } else { + curServ->attribute &= ~flag; + INIT_LOGE("%s critical param invalid", curServ->name); + return SERVICE_FAILURE; + } + } else { + INIT_LOGE("%s critical type error", curServ->name); + return SERVICE_FAILURE; + } + return SERVICE_SUCCESS; +} + +static int GetCpuArgs(const cJSON *argJson, const char *name, Service *service) +{ + INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson"); + cJSON *obj = cJSON_GetObjectItem(argJson, name); + INIT_CHECK(obj != NULL, return SERVICE_FAILURE); + + int ret = cJSON_IsArray(obj); + INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type"); + int count = cJSON_GetArraySize(obj); + int cpus = -1; + int cpuNumMax = sysconf(_SC_NPROCESSORS_CONF); + if (count > 0 && service->cpuSet == NULL) { + service->cpuSet = malloc(sizeof(cpu_set_t)); + INIT_ERROR_CHECK(service->cpuSet != NULL, return SERVICE_FAILURE, "Failed to malloc for cpuset"); + } + CPU_ZERO(service->cpuSet); + for (int i = 0; i < count; ++i) { + cJSON *item = cJSON_GetArrayItem(obj, i); + INIT_ERROR_CHECK(item != NULL, return SERVICE_FAILURE, "prase invalid"); + cpus = (int)cJSON_GetNumberValue(item); + if (cpuNumMax <= cpus) { + INIT_LOGW("%s core number %d of CPU cores does not exist", service->name, cpus); + continue; + } + if (CPU_ISSET(cpus, service->cpuSet)) { + continue; + } + CPU_SET(cpus, service->cpuSet); + } + return SERVICE_SUCCESS; +} + +static int GetServiceSandbox(const cJSON *curItem, Service *service) +{ + cJSON *item = cJSON_GetObjectItem(curItem, "sandbox"); + if (item == NULL) { + return SERVICE_SUCCESS; + } + + INIT_ERROR_CHECK(cJSON_IsNumber(item), return SERVICE_FAILURE, + "Service : %s sandbox value only support number.", service->name); + int isSandbox = (int)cJSON_GetNumberValue(item); + if (isSandbox == 0) { + MarkServiceWithoutSandbox(service); + } else { + MarkServiceWithSandbox(service); + } + + return SERVICE_SUCCESS; +} + +#ifdef ASAN_DETECTOR +static int WrapPath(char *dest, size_t len, char *source, int i) +{ + char *q = source; + char *p = dest; + if (q == NULL) { + return -1; + } + + while (*p != '\0') { + if (--i <= 0) { + int ret = memmove_s(p + strlen(source), len, p, strlen(p) + 1); + INIT_ERROR_CHECK(ret == 0, return -1, "Dest is %s, source is %s, ret is %d.", dest, source, ret); + break; + } + p++; + } + while (*q != '\0') { + *p = *q; + p++; + q++; + } + + return 0; +} + +static int GetWrapServiceNameValue(const char *serviceName) +{ + char wrapServiceNameKey[PARAM_VALUE_LEN_MAX] = {0}; + char wrapServiceNameValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int valueLen = PARAM_VALUE_LEN_MAX; + + int len = sprintf_s(wrapServiceNameKey, PARAM_VALUE_LEN_MAX, "wrap.%s", serviceName); + INIT_INFO_CHECK(len > 0 && (len < PARAM_VALUE_LEN_MAX), return -1, "Invalid to format wrapServiceNameKey"); + + int ret = SystemReadParam(wrapServiceNameKey, wrapServiceNameValue, &valueLen); + INIT_INFO_CHECK(ret == 0, return -1, "Not wrap %s.", serviceName); + INIT_LOGI("Asan: GetParameter %s the value is %s.", serviceName, wrapServiceNameValue); + return 0; +} + +void SetServicePathWithAsan(Service *service) +{ + char tmpPathName[MAX_ONE_ARG_LEN] = {0}; + int anchorPos = -1; + + if (GetWrapServiceNameValue(service->name) != 0) { + return; + } + + int ret = strcpy_s(tmpPathName, MAX_ONE_ARG_LEN, service->pathArgs.argv[0]); + INIT_ERROR_CHECK(ret == 0, return, "Asan: failed to copy service path %s", service->pathArgs.argv[0]); + + if (strstr(tmpPathName, "/system/bin") != NULL) { + anchorPos = strlen("/system") + 1; + } else if (strstr(tmpPathName, "/vendor/bin") != NULL) { + anchorPos = strlen("/vendor") + 1; + } else { + INIT_LOGE("Asan: %s is not a system or vendor binary", tmpPathName); + return; + } + + ret = WrapPath(tmpPathName, MAX_ONE_ARG_LEN, "/asan", anchorPos); + INIT_ERROR_CHECK(ret == 0, return, "Asan: failed to add asan path."); + free(service->pathArgs.argv[0]); + service->pathArgs.argv[0] = strdup(tmpPathName); + INIT_ERROR_CHECK(service->pathArgs.argv[0] != NULL, return, "Asan: failed dup path."); + INIT_LOGI("Asan: replace module %s with %s successfully.", service->name, service->pathArgs.argv[0]); + + return; +} +#endif + +static void ParseOneServiceArgs(const cJSON *curItem, Service *service) +{ + GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs); + GetServiceArgs(curItem, D_CAPS_STR_IN_CFG, MAX_WRITEPID_FILES, &service->capsArgs); + GetServiceArgs(curItem, "permission", MAX_WRITEPID_FILES, &service->permArgs); + GetServiceArgs(curItem, "permission_acls", MAX_WRITEPID_FILES, &service->permAclsArgs); + size_t strLen = 0; + char *fieldStr = GetStringValue(curItem, APL_STR_IN_CFG, &strLen); + if (fieldStr != NULL) { + if (service->apl != NULL) { + free(service->apl); + } + service->apl = strdup(fieldStr); + INIT_CHECK(service->apl != NULL, return); + } + (void)GetCpuArgs(curItem, CPU_CORE_STR_IN_CFG, service); +} + +static int SetConsoleValue(Service *service, const char *attrName, int value, int flag) +{ + UNUSED(attrName); + UNUSED(flag); + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr."); + if (value == VALUE_ATTR_CONSOLE) { + service->attribute |= SERVICE_ATTR_CONSOLE; + } else if (value == VALUE_ATTR_KMSG) { + service->attribute |= SERVICE_ATTR_KMSG; + } + return SERVICE_SUCCESS; +} + +static int GetServiceEnv(Service *service, const cJSON *json) +{ + int envCnt = 0; + cJSON *envArray = GetArrayItem(json, &envCnt, "env"); + INIT_CHECK(envArray != NULL, return SERVICE_SUCCESS); + if (envCnt > 0) { + service->env = (ServiceEnv*)calloc(envCnt, sizeof(ServiceEnv)); + INIT_ERROR_CHECK(service->env != NULL, return SERVICE_FAILURE, "calloc ServiceEnv memory failed!"); + } + service->envCnt = envCnt; + + for (int i = 0; i < envCnt; ++i) { + cJSON *envItem = cJSON_GetArrayItem(envArray, i); + size_t strLen = 0; + char *name = GetStringValue(envItem, "name", &strLen); + INIT_ERROR_CHECK(name != NULL && strLen > 0, return SERVICE_FAILURE, "Failed to get env name failed!"); + int ret = strcpy_s(service->env[i].name, strLen + 1, name); + INIT_INFO_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to copy env name %s", name); + + char *value = GetStringValue(envItem, "value", &strLen); + INIT_ERROR_CHECK(value != NULL && strLen > 0, return SERVICE_FAILURE, "Failed to get value failed!"); + ret = strcpy_s(service->env[i].value, strLen + 1, value); + INIT_INFO_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to copy env value %s", value); + } + return SERVICE_SUCCESS; +} + +static int GetServicePeriod(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag) +{ + cJSON *arrItem = cJSON_GetObjectItem(curArrItem, attrName); + INIT_CHECK(arrItem != NULL, return SERVICE_SUCCESS); + + curServ->attribute &= ~SERVICE_ATTR_PERIOD; + INIT_ERROR_CHECK(cJSON_IsNumber(arrItem), return SERVICE_FAILURE, + "Service error %s is null or is not a number", curServ->name); + curServ->attribute |= SERVICE_ATTR_PERIOD; + uint64_t value = (uint64_t)cJSON_GetNumberValue(arrItem); + curServ->period = value * BASE_MS_UNIT; + return SERVICE_SUCCESS; +} + +int ParseOneService(const cJSON *curItem, Service *service) +{ + INIT_CHECK_RETURN_VALUE(curItem != NULL && service != NULL, SERVICE_FAILURE); + int ret = GetServiceArgs(curItem, "path", MAX_PATH_ARGS_CNT, &service->pathArgs); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get path for service %s", service->name); + if ((service->pathArgs.count > 0) && IsForbidden(service->pathArgs.argv[0])) { + INIT_LOGE("Service %s is forbidden.", service->name); + return SERVICE_FAILURE; + } +#ifdef ASAN_DETECTOR + SetServicePathWithAsan(service); +#endif + ret = GetUid(cJSON_GetObjectItem(curItem, UID_STR_IN_CFG), &service->servPerm.uID); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get uid for service %s", service->name); + ret = GetServiceGids(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get gid for service %s", service->name); + + ret = GetServiceAttr(curItem, service, ONCE_STR_IN_CFG, SERVICE_ATTR_ONCE, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name); + ret = GetCritical(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name); + ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, SetConsoleValue); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name); + ret = GetServiceAttr(curItem, service, "notify-state", SERVICE_ATTR_NOTIFY_STATE, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get notify-state for service %s", service->name); + ret = GetServiceAttr(curItem, service, MODULE_UPDATE_STR_IN_CFG, SERVICE_ATTR_MODULE_UPDATE, NULL); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get module-update for service %s", service->name); + + ParseOneServiceArgs(curItem, service); + ret = GetServiceEnv(service, curItem); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get env for service %s", service->name); + ret = GetServicePeriod(curItem, service, PERIOD_STR_IN_CFG, SERVICE_ATTR_PERIOD); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get period for service %s", service->name); + ret = GetServiceSandbox(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get sandbox for service %s", service->name); + ret = InitServiceCaps(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name); + ret = GetServiceOnDemand(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get ondemand flag for service %s", service->name); + ret = GetServiceSetuid(curItem, service); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get setuid flag for service %s", service->name); + ret = GetServiceMode(service, curItem); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get start/end mode for service %s", service->name); + ret = GetServiceJobs(service, cJSON_GetObjectItem(curItem, "jobs")); + INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get jobs for service %s", service->name); + return ret; +} + +#ifndef OHOS_LITE +/** + * Service Config File Parse Hooking + */ +static int ServiceParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + SERVICE_PARSE_CTX *serviceParseContext = (SERVICE_PARSE_CTX *)executionContext; + ServiceParseHook realHook = (ServiceParseHook)hookInfo->hookCookie; + + realHook(serviceParseContext); + return 0; +}; + +int InitAddServiceParseHook(ServiceParseHook hook) +{ + HOOK_INFO info; + + info.stage = INIT_SERVICE_PARSE; + info.prio = 0; + info.hook = ServiceParseHookWrapper; + info.hookCookie = (void *)hook; + + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +static void ParseServiceHookExecute(const char *name, const cJSON *serviceNode) +{ + SERVICE_PARSE_CTX context; + + context.serviceName = name; + context.serviceNode = serviceNode; + + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_PARSE, (void *)(&context), NULL); +} +#endif + +static void ProcessConsoleEvent(const WatcherHandle handler, int fd, uint32_t *events, const void *context) +{ + Service *service = (Service *)context; + LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)handler); + if (fd < 0 || service == NULL) { + INIT_LOGE("Process console event with invalid arguments"); + return; + } + // Since we've got event from console device + // the fd related to '/dev/console' does not need anymore, close it. + close(fd); + if (strcmp(service->name, "console") != 0) { + INIT_LOGE("Process console event with invalid service %s, only console service should do this", service->name); + return; + } + + if (ServiceStart(service, &service->pathArgs) != SERVICE_SUCCESS) { + INIT_LOGE("Start console service failed"); + } + return; +} + +static int AddFileDescriptorToWatcher(int fd, Service *service) +{ + if (fd < 0 || service == NULL) { + return -1; + } + + WatcherHandle watcher = NULL; + LE_WatchInfo info = {}; + info.fd = fd; + info.flags = 0; // WATCHER_ONCE; + info.events = EVENT_READ; + info.processEvent = ProcessConsoleEvent; + int ret = LE_StartWatcher(LE_GetDefaultLoop(), &watcher, &info, service); + if (ret != LE_SUCCESS) { + INIT_LOGE("Failed to watch console device for service \' %s \'", service->name); + return -1; + } + return 0; +} + +int WatchConsoleDevice(Service *service) +{ + if (service == NULL) { + return -1; + } + + int fd = open("/dev/console", O_RDWR); + if (fd < 0) { + if (errno == ENOENT) { + INIT_LOGW("/dev/console is not exist, wait for it..."); + WaitForFile("/dev/console", WAIT_MAX_SECOND); + } else { + INIT_LOGE("Failed to open /dev/console, err = %d", errno); + return -1; + } + fd = open("/dev/console", O_RDWR); + if (fd < 0) { + INIT_LOGW("Failed to open /dev/console after try 1 time, err = %d", errno); + return -1; + } + } + + if (AddFileDescriptorToWatcher(fd, service) < 0) { + close(fd); + return -1; + } + return 0; +} + +void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context) +{ + int servArrSize = 0; + cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON); + INIT_CHECK(serviceArr != NULL, return); + + size_t strLen = 0; + for (int i = 0; i < servArrSize; ++i) { + cJSON *curItem = cJSON_GetArrayItem(serviceArr, i); + char *fieldStr = GetStringValue(curItem, "name", &strLen); + if (fieldStr == NULL) { + INIT_LOGE("Failed to get service name"); + continue; + } + Service *service = GetServiceByName(fieldStr); + if (service == NULL) { + service = AddService(fieldStr); + if (service == NULL) { + INIT_LOGE("Failed to add service name %s", fieldStr); + continue; + } + } else { + INIT_LOGI("Service %s already exists, updating.", fieldStr); +#ifndef __MUSL__ + continue; +#endif + } + + if (context != NULL) { + service->context.type = context->type; + } + int ret = ParseOneService(curItem, service); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("Service error %s parse config error.", service->name); + service->lastErrno = INIT_ECFG; + continue; + } + ret = ParseServiceSocket(curItem, service); + INIT_CHECK(ret == 0, FreeServiceSocket(service->socketCfg); service->socketCfg = NULL); + ret = ParseServiceFile(curItem, service); + INIT_CHECK(ret == 0, FreeServiceFile(service->fileCfg); service->fileCfg = NULL); + // Watch "/dev/console" node for starting console service ondemand. + if ((strcmp(service->name, "console") == 0) && IsOnDemandService(service)) { + if (WatchConsoleDevice(service) < 0) { + INIT_LOGW("Failed to watch \'/dev/console\' device"); + } + } +#ifndef OHOS_LITE + /* + * Execute service parsing hooks + */ + ParseServiceHookExecute(fieldStr, curItem); +#endif + + ret = GetCmdLinesFromJson(cJSON_GetObjectItem(curItem, "onrestart"), &service->restartArg); + INIT_CHECK(ret == SERVICE_SUCCESS, service->restartArg = NULL); + } +} + +static Service *GetServiceByExtServName(const char *fullServName, ServiceArgs *extraArgs) +{ + INIT_ERROR_CHECK(fullServName != NULL, return NULL, "Failed get parameters"); + Service *service = GetServiceByName(fullServName); + if (service != NULL) { // none parameter in fullServName + return service; + } + char *tmpServName = strdup(fullServName); + INIT_ERROR_CHECK(tmpServName != NULL, return NULL, "Failed dup parameters"); + char *dstPtr[MAX_PATH_ARGS_CNT] = {NULL}; + int returnCount = SplitString(tmpServName, "|", dstPtr, MAX_PATH_ARGS_CNT); + if (returnCount == 0) { + INIT_LOGE("Service error %s start service bt ext parameter .", fullServName); + free(tmpServName); + return NULL; + } + INIT_LOGI("Service info %s start service bt ext parameter %s.", dstPtr[0], fullServName); + service = GetServiceByName(dstPtr[0]); + if (service == NULL) { + free(tmpServName); + return NULL; + } + extraArgs->count = service->pathArgs.count + returnCount - 1; + extraArgs->argv = (char **)calloc(extraArgs->count + 1, sizeof(char *)); + INIT_ERROR_CHECK(extraArgs->argv != NULL, free(tmpServName); + return NULL, "Failed calloc err=%d", errno); + int argc; + for (argc = 0; argc < (service->pathArgs.count - 1); argc++) { + extraArgs->argv[argc] = strdup(service->pathArgs.argv[argc]); + INIT_ERROR_CHECK(extraArgs->argv[argc] != NULL, free(tmpServName); + return NULL, "Failed dup path"); + } + int extArgc; + for (extArgc = 0; extArgc < (returnCount - 1); extArgc++) { + extraArgs->argv[extArgc + argc] = strdup(dstPtr[extArgc + 1]); + INIT_ERROR_CHECK(extraArgs->argv[extArgc + argc] != NULL, free(tmpServName); + return NULL, "Failed dup path"); + } + extraArgs->argv[extraArgs->count] = NULL; + free(tmpServName); + return service; +} + +void StartServiceByName(const char *servName) +{ + ServiceArgs extraArgs = { 0 }; + Service *service = GetServiceByName(servName); + if (service == NULL) { + service = GetServiceByExtServName(servName, &extraArgs); + } + INIT_ERROR_CHECK(service != NULL, FreeStringVector(extraArgs.argv, extraArgs.count); + return, "Cannot find service %s.service count %d", servName, g_serviceSpace.serviceCount); + + ServiceArgs *pathArgs = &service->pathArgs; + if (extraArgs.count != 0) { + pathArgs = &extraArgs; + } + if (ServiceStart(service, pathArgs) != SERVICE_SUCCESS) { + INIT_LOGE("Service %s start failed!", servName); + } + // After starting, clear the extra parameters. + FreeStringVector(extraArgs.argv, extraArgs.count); + return; +} + +void StopServiceByName(const char *servName) +{ + Service *service = GetServiceByName(servName); + INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName); + + if (ServiceStop(service) != SERVICE_SUCCESS) { + INIT_LOGE("Service %s stop failed!", servName); + } + return; +} + +void StopAllServices(int flags, const char **exclude, int size, + int (*filter)(const Service *service, const char **exclude, int size)) +{ + Service *service = GetServiceByName("appspawn"); + if (service != NULL && service->pid > 0) { // notify appspawn stop +#ifndef STARTUP_INIT_TEST + kill(service->pid, SIGTERM); + waitpid(service->pid, 0, 0); + service->pid = -1; +#endif + } + + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + Service *service = node->data.service; + if (service == NULL) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + INIT_LOGI("StopAllServices stop service %s ", service->name); + if (filter != NULL && filter(service, exclude, size) != 0) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + service->attribute |= (flags & SERVICE_ATTR_INVALID); + int ret = ServiceStop(service); + if (ret != SERVICE_SUCCESS) { + INIT_LOGE("Service %s stop failed!", service->name); + } + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } + + INIT_TIMING_STAT cmdTimer; + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime); + long long count = 1; + while (count > 0) { + usleep(INTERVAL_PER_WAIT); + count++; + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime); + long long diff = InitDiffTime(&cmdTimer); + if (diff > REBOOT_WAIT_TIME) { + count = 0; + } + } + INIT_LOGI("StopAllServices end"); +#ifndef OHOS_LITE + HookMgrExecute(GetBootStageHookMgr(), INIT_ALL_SERVICES_REAP, NULL, NULL); +#endif +} + +Service *GetServiceByPid(pid_t pid) +{ + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + Service *service = node->data.service; + if (service != NULL && service->pid == pid) { + return service; + } + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } + return NULL; +} + +Service *GetServiceByName(const char *servName) +{ + INIT_ERROR_CHECK(servName != NULL, return NULL, "Failed get servName"); + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, servName); + if (groupNode != NULL) { + return groupNode->data.service; + } + return NULL; +} + +void LoadAccessTokenId(void) +{ + GetAccessToken(); +} + +int GetKillServiceSig(const char *name) +{ + if (strcmp(name, "appspawn") == 0 || strcmp(name, "nwebspawn") == 0) { + return SIGTERM; + } + return SIGKILL; +} + +int GetServiceGroupIdByPid(pid_t pid, gid_t *gids, uint32_t gidSize) +{ + Service *service = GetServiceByPid(pid); + if (service != NULL) { + int ret = memcpy_s(gids, gidSize * sizeof(gid_t), + service->servPerm.gIDArray, service->servPerm.gIDCnt * sizeof(gid_t)); + INIT_ERROR_CHECK(ret == 0, return 0, "Failed get copy gids"); + return service->servPerm.gIDCnt; + } + return 0; +} \ No newline at end of file diff --git a/services/init/init_service_socket.c b/services/init/init_service_socket.c new file mode 100644 index 0000000000000000000000000000000000000000..3d5430c92c9ff34126c60f1261b3c350aae2733c --- /dev/null +++ b/services/init/init_service_socket.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2021 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 "init_service_socket.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "init_cmdexecutor.h" +#include "init_log.h" +#include "init_service.h" +#include "loop_event.h" +#include "securec.h" +#include "init_group_manager.h" +#define SOCKET_BUFF_SIZE (256 * 1024) + +#define HOS_SOCKET_DIR "/dev/unix/socket" +#define HOS_SOCKET_PATH 64 +#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_" +#define MAX_SOCKET_ENV_PREFIX_LEN 64 +#define MAX_SOCKET_FD_LEN 16 + +static int GetSocketAddr(struct sockaddr_un *addr, const char *name) +{ + (void)memset_s(addr, sizeof(struct sockaddr_un), 0x0, sizeof(struct sockaddr_un)); + addr->sun_family = AF_UNIX; + size_t addrLen = sizeof(addr->sun_path); + int ret = snprintf_s(addr->sun_path, addrLen, addrLen - 1, HOS_SOCKET_DIR "/%s", name); + INIT_ERROR_CHECK(ret >= 0, return -1, "Failed to format addr %s", name); + return 0; +} + +static int SetSocketAddr(ServiceSocket *sockopt, sockaddr_union *addr) +{ + int ret = 0; + if (sockopt->family == AF_NETLINK) { +#ifndef __LITEOS_A__ + if (memset_s(&(addr->addrnl), sizeof(addr->addrnl), 0, sizeof(addr->addrnl)) != EOK) { + INIT_LOGE("Failed to clear socket address"); + return -1; + } + addr->addrnl.nl_family = AF_NETLINK; + addr->addrnl.nl_pid = getpid(); + addr->addrnl.nl_groups = 0xffffffff; +#else + INIT_LOGE("No support in liteos kernel"); + return -1; +#endif + } else { + ret = GetSocketAddr(&(addr->addrun), sockopt->name); + INIT_ERROR_CHECK(ret == 0, return -1, "Failed to format addr %s", sockopt->name); + if (access(addr->addrun.sun_path, F_OK) == 0) { + INIT_LOGI("%s already exist, remove it", addr->addrun.sun_path); + unlink(addr->addrun.sun_path); + } + } + return ret; +} + +static int SetSocketOptionAndBind(ServiceSocket *sockopt) +{ + if (sockopt->option & SOCKET_OPTION_PASSCRED) { + int on = 1; + if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { + INIT_LOGE("Failed to setsockopt"); + return -1; + } + } + if (sockopt->option & SOCKET_OPTION_RCVBUFFORCE) { + int buffSize = SOCKET_BUFF_SIZE; + if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_RCVBUFFORCE, &buffSize, sizeof(buffSize))) { + INIT_LOGE("Failed to setsockopt"); + return -1; + } + } + sockaddr_union addr = {}; + if (SetSocketAddr(sockopt, &addr) != 0) { + INIT_LOGE("Failed to set socket addr"); + return -1; + } + if (sockopt->family == AF_NETLINK) { +#ifndef __LITEOS_A__ + if (bind(sockopt->sockFd, (struct sockaddr *)&(addr.addrnl), sizeof(addr.addrnl))) { + INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno); + return -1; + } +#else + INIT_LOGE("No support in liteos kernel"); + return -1; +#endif + } else { + if (bind(sockopt->sockFd, (struct sockaddr *)&(addr.addrun), sizeof(addr.addrun))) { + INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno); + return -1; + } + if (lchown(addr.addrun.sun_path, sockopt->uid, sockopt->gid)) { + INIT_LOGE("lchown fail %d ", errno); + unlink(addr.addrun.sun_path); + return -1; + } + if (fchmodat(AT_FDCWD, addr.addrun.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) { + INIT_LOGE("fchmodat fail %d ", errno); + unlink(addr.addrun.sun_path); + return -1; + } + } + return 0; +} + +static int CreateSocket(ServiceSocket *sockopt) +{ + INIT_ERROR_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Invalid socket options"); + INIT_LOGV("Socket name: %s, family: %d, type: %u, protocol: %d, perm: %u, uid: %u, gid: %u, option: %u", + sockopt->name, sockopt->family, sockopt->type, sockopt->protocol, + sockopt->perm, sockopt->uid, sockopt->gid, sockopt->option); + if (sockopt->sockFd >= 0) { + close(sockopt->sockFd); + sockopt->sockFd = -1; + } + sockopt->sockFd = socket(sockopt->family, sockopt->type, sockopt->protocol); + INIT_ERROR_CHECK(sockopt->sockFd >= 0, return -1, "socket fail %d ", errno); + + int ret = SetSocketOptionAndBind(sockopt); + if (ret != 0) { + close(sockopt->sockFd); + return -1; + } + INIT_LOGI("CreateSocket %s success", sockopt->name); + + char path[HOS_SOCKET_PATH] = { 0 }; + if (snprintf_s(path, sizeof(path), sizeof(path) - 1, HOS_SOCKET_DIR"/%s", sockopt->name) < 0) { + close(sockopt->sockFd); + return -1; + } + PluginExecCmdByName("restoreContentRecurse", path); + INIT_LOGI("CreateSocket restoreContentRecurse %s success", path); + return sockopt->sockFd; +} + +static void ProcessWatchEvent_(const WatcherHandle watcherHandle, int fd, uint32_t *events, const void *context) +{ + *events = 0; + Service *service = (Service *)context; + ServiceSocket *tmpSock = service->socketCfg; + while (tmpSock != NULL) { + if (tmpSock->sockFd == fd) { + tmpSock->watcher = NULL; + break; + } + tmpSock = tmpSock->next; + } + if (tmpSock == NULL) { // not found socket + INIT_LOGE("Service %s not match socket fd %d!", service->name, fd); + close(fd); + return; + } + INIT_LOGI("Socket information detected, fd:%d service name:%s", fd, service->name); + RemoveSocketWatcher(watcherHandle); + if (ServiceStart(service, &service->pathArgs) != SERVICE_SUCCESS) { + INIT_LOGE("Service %s start failed!", service->name); + } +} + +int AddSocketWatcher(ServiceWatcher *watcherHandle, Service *service, int fd) +{ + WatcherHandle handle; + LE_WatchInfo info = {}; + info.fd = fd; + info.flags = WATCHER_ONCE; + info.events = EVENT_READ; + info.processEvent = ProcessWatchEvent_; + int ret = LE_StartWatcher(LE_GetDefaultLoop(), &handle, &info, service); + INIT_LOGI("Watcher socket fd %d for service %s", fd, service->name); + *watcherHandle = (ServiceWatcher)handle; + return ret; +} + +void RemoveSocketWatcher(ServiceWatcher watcherHandle) +{ + LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)watcherHandle); +} + +int CreateSocketForService(Service *service) +{ + INIT_CHECK(service != NULL && service->socketCfg != NULL, return 0); + INIT_CHECK(service->socketCfg->sockFd == -1, return 0); + int ret = 0; + ServiceSocket *tmpSock = service->socketCfg; + // insert OnDemand service socket head node to InitWorkspace socketNode head node + if (tmpSock != NULL && IsOnDemandService(service)) { + AddOnDemandSocket(tmpSock); + } + while (tmpSock != NULL) { + PluginExecCmdByName("setSockCreateCon", service->name); + int fd = CreateSocket(tmpSock); + PluginExecCmdByName("setSockCreateCon", ""); + INIT_CHECK_RETURN_VALUE(fd >= 0, -1); + if (IsOnDemandService(service)) { + if (IsConnectionBasedSocket(tmpSock)) { + ret = listen(tmpSock->sockFd, MAX_SOCKET_FD_LEN); + INIT_CHECK_RETURN_VALUE(ret == 0, -1); + } + if (strcmp(service->name, "ueventd") != 0) { + ret = AddSocketWatcher(&tmpSock->watcher, service, tmpSock->sockFd); + INIT_CHECK_RETURN_VALUE(ret == 0, -1); + } + } + tmpSock = tmpSock->next; + } + return 0; +} + +int SetSocketEnvForService(Service *service) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Invalid name"); + char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = { 0 }; + char val[MAX_SOCKET_FD_LEN] = { 0 }; + + ServiceSocket *tmpSock = service->socketCfg; + + while (tmpSock != NULL) { + INIT_CHECK_RETURN_VALUE(snprintf_s(pubName, sizeof(pubName), sizeof(pubName) - 1, HOS_SOCKET_ENV_PREFIX "%s", + tmpSock->name) >= 0, -1); + INIT_CHECK_RETURN_VALUE(snprintf_s(val, sizeof(val), sizeof(val) - 1, "%d", tmpSock->sockFd) >= 0, -1); + + int ret = setenv(pubName, val, 1); + INIT_ERROR_CHECK(ret >= 0, continue, "setenv:%s fail %d ", tmpSock->name, errno); + fcntl(tmpSock->sockFd, F_SETFD, 0); + + tmpSock = tmpSock->next; + } + + return 0; +} + +void CloseServiceSocket(Service *service) +{ + INIT_CHECK(service != NULL && service->socketCfg != NULL, return); + struct sockaddr_un addr; + ServiceSocket *sockopt = service->socketCfg; + while (sockopt != NULL) { + if (sockopt->watcher != NULL) { + RemoveSocketWatcher(sockopt->watcher); + } + if (sockopt->sockFd >= 0) { + close(sockopt->sockFd); + sockopt->sockFd = -1; + } + if (GetSocketAddr(&addr, sockopt->name) == 0) { +#ifndef STARTUP_INIT_TEST + unlink(addr.sun_path); +#endif + } + sockopt = sockopt->next; + } + return; +} diff --git a/services/init/lite/BUILD.gn b/services/init/lite/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ce20aba1fa9af2f7ba9a450b7c6484e8008720ca --- /dev/null +++ b/services/init/lite/BUILD.gn @@ -0,0 +1,101 @@ +# 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/begetd.gni") + +init_common_sources = [ + "../init_capability.c", + "../init_common_cmds.c", + "../init_common_service.c", + "../init_config.c", + "../init_group_manager.c", + "../init_service_file.c", + "../init_service_manager.c", + "../init_service_socket.c", + "../main.c", +] + +# feature: init +executable("init") { + output_name = "init" + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + "__MUSL__", + ] + if (init_feature_begetctl_liteos) { + defines += [ "LITEOS_SUPPORT" ] + } + if (init_feature_enable_lite_process_priority) { + defines += [ "ENABLE_PROCESS_PRIORITY" ] + } + sources = [ + "../adapter/init_adapter.c", + "../lite/init.c", + "../lite/init_cmds.c", + "../lite/init_jobs.c", + "../lite/init_reboot.c", + "../lite/init_service.c", + "../lite/init_signal_handler.c", + ] + sources += init_common_sources + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/init/include", + "//third_party/cJSON", + "//base/hiviewdfx/hilog_lite/interfaces/native/kits", + ] + + ldflags = [] + deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/services/log:init_log", + "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/modules/init_hook:inithook", + "//base/startup/init/services/param/base:param_base", + "//base/startup/init/services/utils:libinit_utils", + "//build/lite/config/component/cJSON:cjson_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + if (ohos_kernel_type == "liteos_a") { + defines += [ "__LITEOS_A__" ] + include_dirs += [ + "//kernel/liteos_a/syscall", + "//kernel/liteos_a/kernel/include", + "//base/startup/init/interfaces/kits/syscap", + "//base/startup/init/initsync/include", + ] + deps += [ + "//base/startup/init/initsync:initsync", + "//base/startup/init/services/param/liteos:param_init_lite", + ] + } + if (ohos_kernel_type == "linux") { + defines += [ + "NEED_EXEC_RCS_LINUX", + "__LINUX__", + ] + ldflags += [ + "-lm", + "-lpthread", + ] + deps += [ + "//base/startup/init/services/param/linux:param_init", + "//third_party/mksh", + ] + external_deps += [ "toybox:toybox" ] + } +} diff --git a/services/init/lite/init.c b/services/init/lite/init.c new file mode 100644 index 0000000000000000000000000000000000000000..9071b66d6fb0401c9041278fe8b8de463ac6c5de --- /dev/null +++ b/services/init/lite/init.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2020-2021 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 "init.h" + +#include +#include +#ifdef __LINUX__ +#include +#endif +#include "init_group_manager.h" +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_utils.h" +#ifndef __LINUX__ +#include "init_stage.h" +#endif +#include "init_param.h" +#include "loop_event.h" + +void SystemInit(void) +{ + SignalInit(); + (void)MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); +} + +void LogInit(void) +{ +#ifdef __LINUX__ + int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR, makedev(MEM_MAJOR, 11)); + if (ret == 0) { + OpenLogDevice(); + } +#endif + return; +} + +void SystemPrepare(long long uptime) +{ +} + +void ParseInitCfgByPriority(void) +{ + ReadFileInDir(OTHER_CFG_PATH, ".cfg", ParseInitCfg, NULL); + ReadFileInDir("/vendor/etc/init", ".cfg", ParseInitCfg, NULL); +} + +void CreateFsAndDeviceNode(void) +{ +} + +void SystemConfig(const char *uptime) +{ + InitServiceSpace(); +#ifdef LITEOS_SUPPORT + InitParamService(); + // parse parameters + (void)LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL); + (void)LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL); + (void)LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD); + + (void)LoadPersistParams(); +#endif + // read config + ReadConfig(); + + // execute init + DoJob("pre-init"); +#ifndef __LINUX__ + TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1); +#endif + + DoJob("init"); +#ifndef __LINUX__ + TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2); +#endif + + DoJob("post-init"); +#ifndef __LINUX__ + TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3); + (void)InitStageFinished(); +#endif + ReleaseAllJobs(); +} + +void SystemRun(void) +{ +#ifndef __LITEOS_A__ + LE_RunLoop(LE_GetDefaultLoop()); +#else + while (1) { + // pause only returns when a signal was caught and the signal-catching function returned. + // pause only returns -1, no need to process the return value. + (void)pause(); + } +#endif +} diff --git a/services/init/lite/init_cmds.c b/services/init/lite/init_cmds.c new file mode 100644 index 0000000000000000000000000000000000000000..e280a46e9ec5409ae66574d16ed6a2dabb1e2056 --- /dev/null +++ b/services/init/lite/init_cmds.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020-2021 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 "init_cmds.h" + +#include +#include +#include + +#include "init_log.h" +#include "init_utils.h" +#include "securec.h" + +int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen) +{ + return (strncpy_s(paramValue, paramLen, symValue, symLen) == EOK) ? 0 : -1; +} + +static void DoExec(const struct CmdArgs *ctx) +{ + // format: exec /xxx/xxx/xxx xxx + if (ctx == NULL || ctx->argv[0] == NULL) { + INIT_LOGE("DoExec: invalid arguments"); + return; + } + pid_t pid = fork(); + if (pid < 0) { + INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", ctx->argv[0]); + return; + } + if (pid == 0) { + int ret = execve(ctx->argv[0], ctx->argv, NULL); + if (ret == -1) { + INIT_LOGE("DoExec: execute \"%s\" failed: %d.", ctx->argv[0], errno); + } + _exit(0x7f); + } + return; +} + +static bool CheckValidCfg(const char *path) +{ + static const char *supportCfg[] = { + "/etc/patch.cfg", + "/patch/fstab.cfg", + }; + INIT_ERROR_CHECK(path != NULL, return false, "Invalid path for cfg"); + struct stat fileStat = { 0 }; + if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) { + return false; + } + size_t cfgCnt = ARRAY_LENGTH(supportCfg); + for (size_t i = 0; i < cfgCnt; ++i) { + if (strcmp(path, supportCfg[i]) == 0) { + return true; + } + } + return false; +} + +static void DoLoadCfg(const struct CmdArgs *ctx) +{ + char buf[LOADCFG_BUF_SIZE] = { 0 }; + size_t maxLoop = 0; + if (!CheckValidCfg(ctx->argv[0])) { + INIT_LOGE("CheckCfg file %s Failed", ctx->argv[0]); + return; + } + char *realPath = GetRealPath(ctx->argv[0]); + INIT_ERROR_CHECK(realPath != NULL, return, "Failed to get realpath %s", ctx->argv[0]); + FILE *fp = fopen(realPath, "r"); + if (fp == NULL) { + INIT_LOGE("Failed to open cfg %s error:%d", ctx->argv[0], errno); + free(realPath); + return; + } + + while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) { + maxLoop++; + int len = strlen(buf); + if (len < 1) { + continue; + } + if (buf[len - 1] == '\n') { + buf[len - 1] = '\0'; // we replace '\n' with '\0' + } + const struct CmdTable *cmd = GetCmdByName(buf); + if (cmd == NULL) { + INIT_LOGE("Cannot support command: %s", buf); + continue; + } + ExecCmd(cmd, &buf[strlen(cmd->name) + 1]); + } + free(realPath); + (void)fclose(fp); +} + +static const struct CmdTable g_cmdTable[] = { + { "exec ", 1, 10, 0, DoExec }, + { "loadcfg ", 1, 1, 0, DoLoadCfg }, +}; + +const struct CmdTable *GetCmdTable(int *number) +{ + *number = (int)ARRAY_LENGTH(g_cmdTable); + return g_cmdTable; +} + +void PluginExecCmdByName(const char *name, const char *cmdContent) +{ +} + +void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context) +{ +} + +const char *PluginGetCmdIndex(const char *cmdStr, int *index) +{ + return NULL; +} + +const char *GetPluginCmdNameByIndex(int index) +{ + return NULL; +} + +int SetFileCryptPolicy(const char *dir) +{ + return 0; +} + +int SetSubInitContext(const ConfigContext *context, const char *service) +{ + return 0; +} + +int ExecuteCmdInSubInit(const ConfigContext *context, const char *name, const char *cmdContent) +{ + return 0; +} + +int CheckExecuteInSubInit(const ConfigContext *context) +{ + return 0; +} diff --git a/services/src/init_jobs.c b/services/init/lite/init_jobs.c similarity index 48% rename from services/src/init_jobs.c rename to services/init/lite/init_jobs.c index 563a5065dc73e069bf0c3b2e3608114a952366d1..093eaee12e263e412800b0c3438c140211f8e868 100644 --- a/services/src/init_jobs.c +++ b/services/init/lite/init_jobs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,10 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "init_jobs_internal.h" -#include "init_jobs.h" - -#include #include #include @@ -23,42 +21,38 @@ #include "init_log.h" #include "securec.h" - #define JOBS_ARR_NAME_IN_JSON "jobs" #define CMDS_ARR_NAME_IN_JSON "cmds" -#define MAX_JOBS_COUNT 100 - -// static const char* g_supportedJobs[] = { -// "pre-init", -// "init", -// "post-init", -// }; +#define MAX_JOBS_COUNT 100 -static Job* g_jobs = NULL; +static Job *g_jobs = NULL; static int g_jobCnt = 0; -void DumpAllJobs() +void DumpAllJobs(void) { - INIT_LOGD("Ready to dump all jobs:"); + INIT_LOGV("Start to dump all jobs..."); for (int i = 0; i < g_jobCnt; i++) { - INIT_LOGD("\tjob name: %s", g_jobs[i].name); - INIT_LOGD("\tlist all commands:"); - for (int j = 0; j < g_jobs[i].cmdLinesCnt; j++) { - INIT_LOGD("\t\tcommand name : %s, command options: %s", - g_jobs[i].cmdLines[j].name, g_jobs[i].cmdLines[j].cmdContent); + INIT_LOGV("\tjob name: %s", g_jobs[i].name); + if (g_jobs[i].cmdLines == NULL) { + continue; + } + INIT_LOGV("\tlist all commands:"); + for (int j = 0; j < g_jobs[i].cmdLines->cmdNum; j++) { + CmdLine *cmd = &g_jobs[i].cmdLines->cmds[j]; + INIT_LOGV("\t\tcommand: %s %s", GetCmdKey(cmd->cmdIndex), cmd->cmdContent); } } - INIT_LOGD("To dump all jobs finished"); + INIT_LOGV("Finish dump all jobs"); } -static int GetJobName(const cJSON* jobItem, Job* resJob) +static int GetJobName(const cJSON *jobItem, Job *resJob) { - char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name")); + char *jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name")); if (jobNameStr == NULL) { return 0; } - if (memcpy_s(resJob->name, MAX_JOB_NAME_LEN, jobNameStr, strlen(jobNameStr)) != EOK) { + if (strcpy_s(resJob->name, MAX_JOB_NAME_LEN, jobNameStr) != EOK) { INIT_LOGE("Get job name \"%s\" failed", jobNameStr); return 0; } @@ -66,7 +60,7 @@ static int GetJobName(const cJSON* jobItem, Job* resJob) return 1; } -static void ParseJob(const cJSON* jobItem, Job* resJob) +static void ParseJob(const cJSON *jobItem, Job *resJob) { if (!GetJobName(jobItem, resJob)) { INIT_LOGE("get JobName failed"); @@ -74,52 +68,27 @@ static void ParseJob(const cJSON* jobItem, Job* resJob) return; } - cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON); + cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON); if (!cJSON_IsArray(cmdsItem)) { - INIT_LOGE("job %s is not an arrary", resJob->name); - return; - } - - int cmdLinesCnt = cJSON_GetArraySize(cmdsItem); - if (cmdLinesCnt <= 0) { // empty job, no cmd - INIT_LOGE("empty job \"%s\"", resJob->name); + INIT_LOGE("job %s is not an array", resJob->name); return; } - - INIT_LOGD("job = %s, cmdLineCnt = %d", resJob->name, cmdLinesCnt); - if (cmdLinesCnt > MAX_CMD_CNT_IN_ONE_JOB) { - INIT_LOGE("ParseAllJobs, too many cmds[cnt %d] in one job, it should not exceed %d.", - cmdLinesCnt, MAX_CMD_CNT_IN_ONE_JOB); + int ret = GetCmdLinesFromJson(cmdsItem, &resJob->cmdLines); + if (ret != 0) { + INIT_LOGE("ParseJob, failed to get cmds for job!"); return; } - - resJob->cmdLines = (CmdLine*)malloc(cmdLinesCnt * sizeof(CmdLine)); - if (resJob->cmdLines == NULL) { - INIT_LOGE("allocate memory for command line failed"); - return; - } - - if (memset_s(resJob->cmdLines, cmdLinesCnt * sizeof(CmdLine), 0, cmdLinesCnt * sizeof(CmdLine)) != EOK) { - free(resJob->cmdLines); - resJob->cmdLines = NULL; - return; - } - resJob->cmdLinesCnt = cmdLinesCnt; - - for (int i = 0; i < cmdLinesCnt; ++i) { - char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i)); - ParseCmdLine(cmdLineStr, &(resJob->cmdLines[i])); - } + return; } -void ParseAllJobs(const cJSON* fileRoot) +void ParseAllJobs(const cJSON *fileRoot, const ConfigContext *context) { if (fileRoot == NULL) { INIT_LOGE("ParseAllJobs, input fileRoot is NULL!"); return; } - cJSON* jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON); + cJSON *jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON); if (!cJSON_IsArray(jobArr)) { INIT_LOGE("ParseAllJobs, job item is not array!"); return; @@ -132,13 +101,13 @@ void ParseAllJobs(const cJSON* fileRoot) return; } - Job* retJobs = (Job*)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize)); + Job *retJobs = (Job *)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize)); if (retJobs == NULL) { INIT_LOGE("ParseAllJobs, malloc failed! job arrSize %d.", jobArrSize); return; } - Job* tmp = retJobs + g_jobCnt; + Job *tmp = retJobs + g_jobCnt; if (memset_s(tmp, sizeof(Job) * jobArrSize, 0, sizeof(Job) * jobArrSize) != EOK) { INIT_LOGE("ParseAllJobs, memset_s failed."); free(retJobs); @@ -147,34 +116,35 @@ void ParseAllJobs(const cJSON* fileRoot) } for (int i = 0; i < jobArrSize; ++i) { - cJSON* jobItem = cJSON_GetArrayItem(jobArr, i); + cJSON *jobItem = cJSON_GetArrayItem(jobArr, i); ParseJob(jobItem, &(tmp[i])); } g_jobs = retJobs; g_jobCnt += jobArrSize; } -void DoJob(const char* jobName) +void DoJob(const char *jobName) { if (jobName == NULL) { INIT_LOGE("DoJob, input jobName NULL!"); return; } - INIT_LOGD("Call job with name %s", jobName); + INIT_LOGV("Call job with name %s", jobName); for (int i = 0; i < g_jobCnt; ++i) { if (strncmp(jobName, g_jobs[i].name, strlen(g_jobs[i].name)) == 0) { - CmdLine* cmdLines = g_jobs[i].cmdLines; - for (int j = 0; j < g_jobs[i].cmdLinesCnt; ++j) { - DoCmd(&(cmdLines[j])); + CmdLines *cmdLines = g_jobs[i].cmdLines; + if (cmdLines == NULL) { + continue; + } + for (int j = 0; j < cmdLines->cmdNum; ++j) { + DoCmdByIndex(cmdLines->cmds[j].cmdIndex, cmdLines->cmds[j].cmdContent, NULL); } - // Walk through all jobs - // break; } } } -void ReleaseAllJobs() +void ReleaseAllJobs(void) { if (g_jobs == NULL) { return; @@ -183,8 +153,6 @@ void ReleaseAllJobs() for (int i = 0; i < g_jobCnt; ++i) { if (g_jobs[i].cmdLines != NULL) { free(g_jobs[i].cmdLines); - g_jobs[i].cmdLines = NULL; - g_jobs[i].cmdLinesCnt = 0; } } @@ -193,3 +161,7 @@ void ReleaseAllJobs() g_jobCnt = 0; } +int DoJobNow(const char *jobName) +{ + return 0; +} diff --git a/ueventd/list.c b/services/init/lite/init_reboot.c old mode 100755 new mode 100644 similarity index 57% rename from ueventd/list.c rename to services/init/lite/init_reboot.c index 17e6f468fc9087fa8ef81ac29fd9a18d103f01fa..d97ab1492e82cf7e1019b90532c231bc0ba7d7d9 --- a/ueventd/list.c +++ b/services/init/lite/init_reboot.c @@ -1,36 +1,35 @@ -/* - * Copyright (c) 2020 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 "list.h" - -void ListInit(struct ListNode *node) -{ - node->next = node; - node->prev = node; -} - -void ListAddTail(struct ListNode *head, struct ListNode *item) -{ - item->next = head; - item->prev = head->prev; - head->prev->next = item; - head->prev = item; -} - -void ListRemove(struct ListNode *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; -} +/* + * Copyright (c) 2021 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 "init.h" +#include "init_log.h" + +void ExecReboot(const char *value) +{ + UNUSED(value); + int ret = reboot(RB_AUTOBOOT); + if (ret != 0) { + INIT_LOGE("reboot failed! syscall ret %d, err %d.", ret, errno); + } + return; +} + +int GetBootModeFromMisc(void) +{ + return 0; +} diff --git a/services/init/lite/init_service.c b/services/init/lite/init_service.c new file mode 100644 index 0000000000000000000000000000000000000000..f3e2ce03861abafb32139576fe79b8f787d3453b --- /dev/null +++ b/services/init/lite/init_service.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020-2021 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 "init_service.h" + +#include +#include +#include + +#include "init.h" +#include "init_log.h" +#include "init_service_manager.h" +#include "securec.h" + +#ifdef ENABLE_PROCESS_PRIORITY +#include +#define MIN_IMPORTANT_LEVEL (-20) +#define MAX_IMPORTANT_LEVEL (19) +#endif + +void NotifyServiceChange(Service *service, int status) +{ + UNUSED(service); + UNUSED(status); +} + +int IsForbidden(const char *fieldStr) +{ + size_t fieldLen = strlen(fieldStr); + size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED); + if (fieldLen == forbidStrLen) { + if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) { + return 1; + } + return 0; + } else if (fieldLen > forbidStrLen) { + // "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid + if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) { + if (fieldStr[forbidStrLen] == ' ') { + return 1; + } + } + return 0; + } else { + return 0; + } +} + +int SetImportantValue(Service *service, const char *attrName, int value, int flag) +{ + UNUSED(attrName); + UNUSED(flag); + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr."); +#ifdef ENABLE_PROCESS_PRIORITY + if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19 + service->attribute |= SERVICE_ATTR_IMPORTANT; + service->importance = value; + } else { + INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value); + return SERVICE_FAILURE; + } +#else + if (value != 0) { + service->attribute |= SERVICE_ATTR_IMPORTANT; + } +#endif + return SERVICE_SUCCESS; +} + +int ServiceExec(Service *service, const ServiceArgs *pathArgs) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr."); + INIT_LOGI("ServiceExec %s", service->name); + INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0, + return SERVICE_FAILURE, "Exec service failed! null ptr."); + +#ifdef ENABLE_PROCESS_PRIORITY + if (service->importance != 0) { + INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, + service->lastErrno = INIT_EPRIORITY; + return SERVICE_FAILURE, + "Service error %d %s, failed to set priority %d.", errno, service->name, service->importance); + } +#endif + int isCritical = (service->attribute & SERVICE_ATTR_CRITICAL); + INIT_ERROR_CHECK(execv(pathArgs->argv[0], pathArgs->argv) == 0, + service->lastErrno = INIT_EEXEC; + return errno, "[startup_failed]failed to execv %d %d %s", isCritical, errno, service->name); + return SERVICE_SUCCESS; +} + +int SetAccessToken(const Service *service) +{ + return SERVICE_SUCCESS; +} + +void GetAccessToken(void) +{ + return; +} + +void IsEnableSandbox(void) +{ + return; +} + +int SetServiceEnterSandbox(const Service *service, const char *path) +{ + UNUSED(path); + UNUSED(service); + return 0; +} diff --git a/services/src/init_signal_handler.c b/services/init/lite/init_signal_handler.c similarity index 36% rename from services/src/init_signal_handler.c rename to services/init/lite/init_signal_handler.c index b17fa929cde068bd6913cbbe0c87604d772c1817..deb4a105d2728489a22cbb9399fc0a50b6306fcf 100644 --- a/services/src/init_signal_handler.c +++ b/services/init/lite/init_signal_handler.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,46 +12,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#include "init_signal_handler.h" - +#include #include -#include +#include #include -#ifdef __LINUX__ -#include -#include -#endif /* __LINUX__ */ #include "init_log.h" #include "init_service_manager.h" -#ifndef OHOS_LITE -#include "init_param.h" -#include "uv.h" -#endif - -#ifdef __LINUX__ -static pid_t g_waitPid = -1; -static sem_t* g_waitSem = NULL; - -void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem) +static void RebootSystem(void) { - g_waitPid = waitPid; - g_waitSem = waitSem; +#ifndef STARTUP_INIT_TEST + int ret = reboot(RB_AUTOBOOT); + if (ret != 0) { + INIT_LOGE("reboot failed! syscall ret %d, err %d.", ret, errno); + } +#endif } -static void CheckWaitPid(pid_t sigPID) +void ReapService(Service *service) { - if (g_waitPid == sigPID && g_waitSem != NULL) { - if (sem_post(g_waitSem) != 0) { - INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno); - } - g_waitPid = -1; - g_waitSem = NULL; + if (service == NULL) { + return; + } + if (service->attribute & SERVICE_ATTR_IMPORTANT) { + // important process exit, need to reboot system + service->pid = -1; + StopAllServices(0, NULL, 0, NULL); + RebootSystem(); } + ServiceReap(service); } -#endif /* __LINUX__ */ static void SigHandler(int sig) { @@ -64,71 +55,27 @@ static void SigHandler(int sig) if (sigPID <= 0) { break; } - -#ifndef OHOS_LITE - // check child process exit status - if (WIFSIGNALED(procStat)) { - INIT_LOGE("Child process %d exit with signal: %d", sigPID, WTERMSIG(procStat)); - } - - if (WIFEXITED(procStat)) { - INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS(procStat)); - } -#endif - - INIT_LOGI("SigHandler, SIGCHLD received, sigPID = %d.", sigPID); -#ifdef __LINUX__ CheckWaitPid(sigPID); -#endif /* __LINUX__ */ - ReapServiceByPID((int)sigPID); + ReapService(GetServiceByPid(sigPID)); } break; } case SIGTERM: { - INIT_LOGI("SigHandler, SIGTERM received."); - StopAllServices(); + StopAllServices(0, NULL, 0, NULL); break; } default: - INIT_LOGI("SigHandler, unsupported signal %d.", sig); break; } } -#ifdef OHOS_LITE -void SignalInitModule() +void SignalInit(void) { struct sigaction act; act.sa_handler = SigHandler; - act.sa_flags = SA_RESTART; + act.sa_flags = SA_RESTART; (void)sigfillset(&act.sa_mask); sigaction(SIGCHLD, &act, NULL); sigaction(SIGTERM, &act, NULL); -} -#else // L2 or above, use signal event in libuv -uv_signal_t g_sigchldHandler; -uv_signal_t g_sigtermHandler; - -static void UVSignalHandler(uv_signal_t* handle, int signum) -{ - SigHandler(signum); -} - -void SignalInitModule() -{ - int ret = uv_signal_init(uv_default_loop(), &g_sigchldHandler); - int ret1 = uv_signal_init(uv_default_loop(), &g_sigtermHandler); - if (ret != 0 && ret1 != 0) { - INIT_LOGW("initialize signal handler failed"); - return; - } - - if (uv_signal_start(&g_sigchldHandler, UVSignalHandler, SIGCHLD) != 0) { - INIT_LOGW("start SIGCHLD handler failed"); - } - if (uv_signal_start(&g_sigtermHandler, UVSignalHandler, SIGTERM) != 0) { - INIT_LOGW("start SIGTERM handler failed"); - } -} -#endif +} \ No newline at end of file diff --git a/services/init/main.c b/services/init/main.c new file mode 100644 index 0000000000000000000000000000000000000000..01935e75e83881bef582601ba9897eee88eacf1c --- /dev/null +++ b/services/init/main.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021 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 "init.h" +#include "init_log.h" +#include "init_utils.h" +#include "device.h" +#ifdef EROFS_OVERLAY +#include "erofs_remount_overlay.h" +#endif + +static const pid_t INIT_PROCESS_PID = 1; + +int main(int argc, char * const argv[]) +{ + const char *uptime = NULL; + long long upTimeInMicroSecs = 0; + int isSecondStage = 0; + (void)signal(SIGPIPE, SIG_IGN); + // Number of command line parameters is 2 + if (argc > 1 && (strcmp(argv[1], "--second-stage") == 0)) { + isSecondStage = 1; + if (argc > 2) { + uptime = argv[2]; + } + } else { + upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL); + } + if (getpid() != INIT_PROCESS_PID) { + INIT_LOGE("Process id error %d!", getpid()); + return 0; + } + EnableInitLog(INIT_INFO); + + // Updater mode + if (isSecondStage == 0) { + SystemPrepare(upTimeInMicroSecs); + } else { + LogInit(); +#ifdef EROFS_OVERLAY + if (IsOverlayEnable()) { + RemountOverlay(); + } +#endif + } + + SystemInit(); + SystemExecuteRcs(); + SystemConfig(uptime); + SystemRun(); + return 0; +} diff --git a/services/init/standard/BUILD.gn b/services/init/standard/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..800f8106dde6cdcaab1c2a478cd2ee4d2816a0b1 --- /dev/null +++ b/services/init/standard/BUILD.gn @@ -0,0 +1,241 @@ +# 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/begetd.gni") + +init_common_sources = [ + "../init_capability.c", + "../init_common_cmds.c", + "../init_common_service.c", + "../init_config.c", + "../init_group_manager.c", + "../init_service_file.c", + "../init_service_manager.c", + "../init_service_socket.c", + "../main.c", +] + +import("//build/ohos.gni") +import("//build/ohos/native_stub/native_stub.gni") + +ohos_executable("init_early") { + sources = [ + "//base/startup/init/interfaces/innerkits/hookmgr/hookmgr.c", + "//base/startup/init/services/log/init_commlog.c", + "bootstagehooker.c", + "device.c", + "init_firststage.c", + "init_mount.c", + "main_early.c", + ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/init/include", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + ] + configs = [ "//build/config/gcc:symbol_visibility_hidden" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson_static", + ] + deps = [ + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/services/log:init_log", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + if (init_extra_static_modules != "") { + deps += [ init_extra_static_modules ] + } + defines = [] + if (is_asan) { + defines += [ "INIT_ASAN" ] + } + if (asan_detector) { + defines += [ "ASAN_DETECTOR" ] + } + install_images = [ "ramdisk" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" +} + +ohos_executable("init") { + sources = [ + "../adapter/init_adapter.c", + "../standard/device.c", + "../standard/fd_holder_service.c", + "../standard/init.c", + "../standard/init_cmdexecutor.c", + "../standard/init_cmds.c", + "../standard/init_control_fd_service.c", + "../standard/init_firststage.c", + "../standard/init_jobs.c", + "../standard/init_mount.c", + "../standard/init_reboot.c", + "../standard/init_service.c", + "../standard/init_signal_handler.c", + "bootstagehooker.c", + ] + + if (init_startup_feature_system_call_switch) { + sources += [ "../standard/system_call_wrap.c" ] + } + modulemgr_sources = [ + "//base/startup/init/interfaces/innerkits/hookmgr/hookmgr.c", + "//base/startup/init/interfaces/innerkits/modulemgr/modulemgr.c", + ] + sources += modulemgr_sources + sources += init_common_sources + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/init/include", + "//base/startup/init/services/modules/reboot", + "//base/startup/init/services/modules/init_context", + "//base/startup/init/services/loopevent/task", + "//base/startup/init/services/loopevent/loop", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/loopevent/utils", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd", + "//base/startup/init/interfaces/innerkits/fd_holder:fdholder", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/services/loopevent:loopevent", + "//base/startup/init/services/param/linux:param_init", + "//base/startup/init/services/sandbox:sandbox", + "//base/startup/init/services/utils:libinit_utils", + ] + deps += [ "//base/startup/init/services/param/base:param_base" ] + external_deps = [ + "config_policy:configpolicy_util_for_init_static", + "storage_service:libfscryptutils_static", + ] + + deps += [ "//base/startup/init/ueventd:libueventd_ramdisk_static" ] + external_deps += [ "storage_service:libfscryptutils_static" ] + external_deps += [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson_static", + ] + + deps += [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_stub_versionscript" ] + deps += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_sources" ] + deps += [ "//base/startup/init/services/modules:static_modules" ] + external_deps += [ + "hilog:libhilog", + "storage_service:libfscryptutils_static", + ] + defines = [] + if (defined(global_parts_info) && + defined(global_parts_info.security_access_token)) { + external_deps += [ + "access_token:libnativetoken", + "access_token:libtoken_setproc", + ] + defines += [ "INIT_SUPPORT_ACCESS_TOKEN" ] + } + cflags = [] + if (init_startup_feature_system_call_switch) { + ldflags = [ + "-Wl,--wrap=getuid", + "-Wl,--wrap=mkdir", + "-Wl,--wrap=rmdir", + "-Wl,--wrap=fork", + "-Wl,--wrap=mount", + "-Wl,--wrap=chown", + "-Wl,--wrap=chmod", + "-Wl,--wrap=kill", + "-Wl,--wrap=fopen", + ] + + include_dirs += [ "//base/startup/init/services/modules/bootevent" ] + } + if (use_musl) { + external_deps += [ + "mksh:sh", + "toybox:toybox", + ] + } + + if (build_seccomp) { + cflags += [ "-DWITH_SECCOMP" ] + } + + if (build_variant == "root") { + cflags += [ "-DIS_DEBUG_VERSION" ] + } + + if (build_selinux) { + external_deps += [ "selinux:libselinux" ] + external_deps += [ + "selinux_adapter:libload_policy", + "selinux_adapter:librestorecon", + ] + cflags += [ "-DWITH_SELINUX" ] + } + + defines += [ "PARAM_SUPPORT_TRIGGER" ] + if (param_test) { + defines += [ + "OHOS_SERVICE_DUMP", + "INIT_TEST", + ] + } + + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines += [ "SUPPORT_64BIT" ] + } + + if (defined(global_parts_info) && + defined(global_parts_info.developtools_hiprofiler)) { + defines += [ "SUPPORT_PROFILER_HIDEBUG" ] + external_deps += [ "hiprofiler:libhidebug_init" ] + } + if (is_asan) { + defines += [ "INIT_ASAN" ] + } + if (asan_detector) { + defines += [ "ASAN_DETECTOR" ] + } + if (init_extra_static_modules != "") { + deps += [ init_extra_static_modules ] + } + + version_script = get_label_info( + "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_stub_versionscript", + "target_gen_dir") + "/" + get_label_info( + "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_stub_versionscript", + "name") + stub_version_script_suffix + defines += [ "_GNU_SOURCE" ] + + if (init_startup_feature_erofs_overlay) { + defines += [ "EROFS_OVERLAY" ] + } + if (use_musl) { + defines += [ "__MUSL__" ] + } + + install_images = [ + "system", + "updater", + ] + + deps += + [ "//base/startup/init/services/modules/crashhandler:libcrashhandler" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/init/standard/bootstagehooker.c b/services/init/standard/bootstagehooker.c new file mode 100755 index 0000000000000000000000000000000000000000..c241aaef7c2681874bef516769c9a6bad2a3d59e --- /dev/null +++ b/services/init/standard/bootstagehooker.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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 "bootstage.h" + +#define INIT_BOOTSTAGE_HOOK_NAME "bootstage" +static HOOK_MGR *bootStageHookMgr = NULL; + +HOOK_MGR *GetBootStageHookMgr() +{ + if (bootStageHookMgr != NULL) { + return bootStageHookMgr; + } + + /* + * Create bootstage hook manager for booting only. + * When boot completed, this manager will be destroyed. + */ + bootStageHookMgr = HookMgrCreate(INIT_BOOTSTAGE_HOOK_NAME); + return bootStageHookMgr; +} diff --git a/services/src/device.c b/services/init/standard/device.c similarity index 33% rename from services/src/device.c rename to services/init/standard/device.c index 1c8a864745598be922c1e8d93f64f7af8638dc0b..e01ce5dc09f324ec59d5d70a28117240b03dd58a 100644 --- a/services/src/device.c +++ b/services/init/standard/device.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 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 @@ -12,44 +12,59 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "device.h" + +#include #include #include -#include #include #include #include + +#include #include "init_log.h" #define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) #define DEFAULT_NO_AUTHORITY_MODE (S_IWUSR | S_IRUSR) -#define STDERR_HANDLE 2 -void CloseStdio(void) +static void MountBasicFs(void) { - int fd = open("/dev/null", O_RDWR | O_CLOEXEC); - if (fd < 0) { - return; + if (access("dev/null", F_OK) != 0) { + INIT_LOGI("mount dev tmpfs"); + if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755") != 0) { + INIT_LOGE("Mount tmpfs failed. %s", strerror(errno)); + } + } else { + INIT_LOGI("dev already mounted"); } - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, STDERR_HANDLE); - close(fd); -} - -void MountBasicFs(void) -{ - if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755") != 0) { + if (mount("tmpfs", "/mnt", "tmpfs", MS_NOSUID, "mode=0755") != 0) { + INIT_LOGE("Mount tmpfs failed. %s", strerror(errno)); + } + if (mount(NULL, "/mnt", NULL, MS_SLAVE, NULL) != 0) { + INIT_LOGE("Mount tmpfs slave failed. %s", strerror(errno)); + } + if (mkdir("/mnt/data", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + INIT_LOGE("mkdir /mnt/data failed. %s", strerror(errno)); + } + if (mount("tmpfs", "/mnt/data", "tmpfs", MS_NOSUID, "mode=0755") != 0) { INIT_LOGE("Mount tmpfs 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)); + if (mount(NULL, "/mnt/data", NULL, MS_SHARED, NULL) != 0) { + INIT_LOGE("Mount tmpfs shared failed. %s", strerror(errno)); } - if (mount("devpts", "/dev/pts", "devpts", 0, NULL) != 0) { - INIT_LOGE("Mount devpts 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("proc", "/proc", "proc", 0, "hidepid=2") != 0) { + struct stat st; + if (!(stat("/dev/pts", &st) == 0 && S_ISDIR(st.st_mode))) { + if (mkdir("/dev/pts", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + INIT_LOGE("mkdir /dev/pts failed. %s", strerror(errno)); + } + if (mount("devpts", "/dev/pts", "devpts", 0, NULL) != 0) { + INIT_LOGE("Mount devpts failed. %s", strerror(errno)); + } + } + if (mount("proc", "/proc", "proc", 0, "gid=3009,hidepid=2") != 0) { INIT_LOGE("Mount procfs failed. %s", strerror(errno)); } if (mount("sysfs", "/sys", "sysfs", 0, NULL) != 0) { @@ -60,35 +75,44 @@ void MountBasicFs(void) } } -void CreateDeviceNode(void) +static void CreateDeviceNode(void) { - if (mknod("/dev/kmsg", S_IFCHR | DEFAULT_NO_AUTHORITY_MODE, makedev(MEM_MAJOR, DEV_KMSG_MINOR)) != 0) { - INIT_LOGE("Create /dev/kmsg device node failed. %s", strerror(errno)); - } - if (mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_NULL_MINOR)) != 0) { - INIT_LOGE("Create /dev/null device node failed. %s", strerror(errno)); + if (access("/dev/null", F_OK) != 0) { + if (mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_NULL_MINOR)) != 0) { + INIT_LOGE("Create /dev/null device node failed. %s", strerror(errno)); + } } - if (mknod("/dev/random", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_RANDOM_MINOR)) != 0) { - INIT_LOGE("Create /dev/random device node failed. %s", strerror(errno)); + + if (access("/dev/random", F_OK) != 0) { + if (mknod("/dev/random", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_RANDOM_MINOR)) != 0) { + INIT_LOGE("Create /dev/random device node failed. %s", strerror(errno)); + } } - if (mknod("/dev/urandom", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_URANDOM_MINOR)) != 0) { - INIT_LOGE("Create /dev/urandom device node failed. %s", strerror(errno)); + if (access("/dev/urandom", F_OK) != 0) { + if (mknod("/dev/urandom", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_URANDOM_MINOR)) != 0) { + INIT_LOGW("Create /dev/urandom device node failed. %s", strerror(errno)); + } } } -int MakeSocketDir(const char *path, mode_t mode) +static void EnableDevKmsg(void) { - int rc = mkdir("/dev/unix/", mode); - if (rc < 0 && errno != EEXIST) { - INIT_LOGE("Create %s failed. %d", path, errno); - return -1; - } - rc = mkdir("/dev/unix/socket/", mode); - if (rc < 0 && errno != EEXIST) { - INIT_LOGE("Create %s failed. %d", path, errno); - return -1; + /* printk_devkmsg default value is ratelimit, We need to set "on" and remove the restrictions */ + int fd = open("/proc/sys/kernel/printk_devkmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd < 0) { + return; } - return rc; + char *kmsgStatus = "on"; + write(fd, kmsgStatus, strlen(kmsgStatus) + 1); + close(fd); + fd = -1; + return; } +void CreateFsAndDeviceNode(void) +{ + MountBasicFs(); + CreateDeviceNode(); + EnableDevKmsg(); +} diff --git a/services/init/standard/fd_holder_service.c b/services/init/standard/fd_holder_service.c new file mode 100644 index 0000000000000000000000000000000000000000..f7ded4d1abdfc53ed092e0c74df9a1ef45888783 --- /dev/null +++ b/services/init/standard/fd_holder_service.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2021 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 "fd_holder_internal.h" +#include "init_log.h" +#include "init_service.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "loop_event.h" +#include "securec.h" + +#define MSG_ARRAY_INDEX 2 + +static void FreeFds(int *fds) +{ + if (fds != NULL) { + free(fds); + } +} + +static int HandlerHoldFds(Service *service, int *fds, size_t fdCount, const char *pollStr) +{ + if (fds == NULL || fdCount == 0 || fdCount > MAX_HOLD_FDS) { + INIT_LOGE("Service %s request hold fds with invalid fds", service->name); + return -1; + } + + INIT_LOGI("Hold service \' %s \' fds:", service->name); + for (size_t i = 0; i < fdCount; i++) { + INIT_LOGI("fd = %d", fds[i]); + } + if (UpdaterServiceFds(service, fds, fdCount) < 0) { + INIT_LOGE("Failed to update service \' %s \' fds", service->name); + return -1; + } + + if (strcmp(pollStr, WITHPOLL) == 0) { + // poll service fds if service asked for + INIT_LOGI("Service \' %s \' asked init to poll fds, not implement yet.", service->name); + } + return 0; +} + +static void SendErrorInfo(int sock, const char *errInfo, const char *serviceName) +{ + int ret = 0; + char errBuffer[MAX_FD_HOLDER_BUFFER] = {}; + if (UNLIKELY(errInfo == NULL)) { // Should not happen. + char *defaultError = "Unknonw error"; + ret = strncpy_s(errBuffer, MAX_FD_HOLDER_BUFFER, defaultError, strlen(defaultError)); + } else { + ret = strncpy_s(errBuffer, MAX_FD_HOLDER_BUFFER, errInfo, strlen(errInfo)); + } + if (ret != 0) { + INIT_LOGE("Failed to copy, err = %d", errno); + return; + } + + struct iovec iovec = { + .iov_base = errBuffer, + .iov_len = strlen(errBuffer), + }; + + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0, + }; + + if (TEMP_FAILURE_RETRY(sendmsg(sock, &msghdr, MSG_NOSIGNAL)) < 0) { + INIT_LOGE("Failed to send err info to service \' %s \', err = %d", serviceName, errno); + } +} + +static int CheckFdHolderPermission(Service *service, pid_t requestPid) +{ + if (service == NULL) { + INIT_LOGE("Invalid service"); + return -1; + } + + INIT_LOGI("received service pid = %d", requestPid); + if (service->pid < 0 || requestPid != service->pid) { + INIT_LOGE("Service \' %s \'(pid = %d) is not valid or request with unexpected process(pid = %d)", + service->name, service->pid, requestPid); + return -1; + } + INIT_LOGI("CheckFdHolderPermission done"); + return 0; +} + +static inline void CloseFds(int *fds, size_t fdCount) +{ + if (fds == NULL) { + return; + } + for (size_t i = 0; i < fdCount; i++) { + close(fds[i]); + } +} + +static void HandlerFdHolder(int sock) +{ + char buffer[MAX_FD_HOLDER_BUFFER + 1] = {}; + size_t fdCount = 0; + pid_t requestPid = -1; + struct iovec iovec = { + .iov_base = buffer, + .iov_len = MAX_FD_HOLDER_BUFFER, + }; + int *fds = ReceiveFds(sock, iovec, &fdCount, true, &requestPid); + // Check what client want, is it want init to hold fds or return fds. + INIT_LOGI("Received buffer: [%s]", buffer); + int msgCount = 0; + int maxMsgCount = 3; + char **msg = SplitStringExt(buffer, "|", &msgCount, maxMsgCount); + if (msg == NULL || msgCount != maxMsgCount) { + INIT_LOGE("Invalid message received: %s", buffer); + CloseFds(fds, fdCount); + FreeFds(fds); + return; + } + char *serviceName = msg[0]; + char *action = msg[1]; + char *pollStr = msg[MSG_ARRAY_INDEX]; + + Service *service = GetServiceByName(serviceName); + if (CheckFdHolderPermission(service, requestPid) < 0) { + SendErrorInfo(sock, "Invalid service", serviceName); + // Permission check failed. + // But fds may already dup to init, so close them. + CloseFds(fds, fdCount); + FreeFds(fds); + FreeStringVector(msg, msgCount); + return; + } + if (strcmp(action, ACTION_HOLD) == 0) { + INIT_LOGI("Service \' %s \' request init to %s fds", serviceName, action); + if (HandlerHoldFds(service, fds, fdCount, pollStr) < 0) { + CloseFds(fds, fdCount); + } + } else { + INIT_LOGE("Unexpected action: %s", action); + CloseFds(fds, fdCount); + } + FreeFds(fds); + FreeStringVector(msg, msgCount); +} + +void ProcessFdHoldEvent(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) +{ + HandlerFdHolder(fd); + *events = EVENT_READ; +} + +void RegisterFdHoldWatcher(int sock) +{ + if (sock < 0) { + INIT_LOGE("Invalid fd holder socket"); + return; + } + + WatcherHandle watcher = NULL; + LE_WatchInfo info = {}; + info.fd = sock; + info.flags = 0; // WATCHER_ONCE; + info.events = EVENT_READ; + info.processEvent = ProcessFdHoldEvent; + LE_StartWatcher(LE_GetDefaultLoop(), &watcher, &info, NULL); +} diff --git a/services/init/standard/init.c b/services/init/standard/init.c new file mode 100755 index 0000000000000000000000000000000000000000..5d7542b21e2a30f7c25cf99a3da2693ce2a3951e --- /dev/null +++ b/services/init/standard/init.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2021-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 "init.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config_policy_utils.h" +#include "device.h" +#include "fd_holder_service.h" +#include "key_control.h" +#include "init_control_fd_service.h" +#include "init_log.h" +#include "init_mount.h" +#include "init_group_manager.h" +#include "init_param.h" +#include "init_service.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "securec.h" +#include "fd_holder_internal.h" +#include "bootstage.h" + +static int FdHolderSockInit(void) +{ + int sock = -1; + int on = 1; + int fdHolderBufferSize = FD_HOLDER_BUFFER_SIZE; // 4KiB + sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (sock < 0) { + INIT_LOGE("Failed to create fd holder socket, err = %d", errno); + return -1; + } + + setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, &fdHolderBufferSize, sizeof(fdHolderBufferSize)); + setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); + + if (access(INIT_HOLDER_SOCKET_PATH, F_OK) == 0) { + INIT_LOGI("%s exist, remove it", INIT_HOLDER_SOCKET_PATH); + unlink(INIT_HOLDER_SOCKET_PATH); + } + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + if (strncpy_s(addr.sun_path, sizeof(addr.sun_path), + INIT_HOLDER_SOCKET_PATH, strlen(INIT_HOLDER_SOCKET_PATH)) != 0) { + INIT_LOGE("Failed to copy fd hoder socket path"); + close(sock); + return -1; + } + socklen_t len = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1); + if (bind(sock, (struct sockaddr *)&addr, len) < 0) { + INIT_LOGE("Failed to binder fd folder socket %d", errno); + close(sock); + return -1; + } + + // Owned by root + if (lchown(addr.sun_path, 0, 0)) { + INIT_LOGW("Failed to change owner of fd holder socket, err = %d", errno); + } + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + if (fchmodat(AT_FDCWD, addr.sun_path, mode, AT_SYMLINK_NOFOLLOW)) { + INIT_LOGW("Failed to change mode of fd holder socket, err = %d", errno); + } + INIT_LOGI("Init fd holder socket done"); + return sock; +} + +void SystemInit(void) +{ + CloseStdio(); +#ifndef STARTUP_INIT_TEST + // Set up a session keyring that all processes will have access to. + KeyCtrlGetKeyringId(KEY_SPEC_SESSION_KEYRING, 1); +#endif + // umask call always succeeds and return the previous mask value which is not needed here + (void)umask(DEFAULT_UMASK_INIT); + MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + int sock = FdHolderSockInit(); + if (sock >= 0) { + RegisterFdHoldWatcher(sock); + } + InitControlFd(); + + // sysclktz 0 + struct timezone tz = { 0 }; + if (settimeofday(NULL, &tz) == -1) { + INIT_LOGE("Set time of day failed, err = %d", errno); + } +} + +void LogInit(void) +{ + int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR, + makedev(MEM_MAJOR, DEV_KMSG_MINOR)); + if (ret == 0) { + OpenLogDevice(); + } +} + +static void WriteUptimeSysParam(const char *param, const char *uptime) +{ + char buf[64]; + + if (uptime == NULL) { + snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, + "%lld", GetUptimeInMicroSeconds(NULL)); + uptime = buf; + } + SystemWriteParam(param, uptime); +} + +INIT_TIMING_STAT g_bootJob = {{0}, {0}}; + +static void RecordInitBootEvent(const char *initBootEvent) +{ + const char *bootEventArgv[] = {"init", initBootEvent}; + PluginExecCmd("bootevent", ARRAY_LENGTH(bootEventArgv), bootEventArgv); + return; +} + +INIT_STATIC void BootStateChange(int start, const char *content) +{ + if (start == 0) { + clock_gettime(CLOCK_MONOTONIC, &(g_bootJob.startTime)); + RecordInitBootEvent(content); + INIT_LOGI("boot job %s start.", content); + } else { + clock_gettime(CLOCK_MONOTONIC, &(g_bootJob.endTime)); + RecordInitBootEvent(content); + long long diff = InitDiffTime(&g_bootJob); + INIT_LOGI("boot job %s finish diff %lld us.", content, diff); + if (strcmp(content, "boot") == 0) { + WriteUptimeSysParam("ohos.boot.time.init", NULL); + } + } +} + +static void InitLoadParamFiles(void) +{ + if (InUpdaterMode() != 0) { + LoadDefaultParams("/etc/param/ohos_const", LOAD_PARAM_NORMAL); + LoadDefaultParams("/etc/param", LOAD_PARAM_ONLY_ADD); + LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_ONLY_ADD); + return; + } + + // Load developer mode param + LoadDefaultParams("/proc/dsmm/developer", LOAD_PARAM_NORMAL); + + // Load const params, these can't be override! + LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL); + CfgFiles *files = GetCfgFiles("etc/param"); + for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) { + if (files->paths[i]) { + LoadDefaultParams(files->paths[i], LOAD_PARAM_ONLY_ADD); + } + } + FreeCfgFiles(files); +} + +INIT_STATIC void InitPreHook(const HOOK_INFO *hookInfo, void *executionContext) +{ + INIT_TIMING_STAT *stat = (INIT_TIMING_STAT *)executionContext; + clock_gettime(CLOCK_MONOTONIC, &(stat->startTime)); +} + +INIT_STATIC void InitPostHook(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal) +{ + INIT_TIMING_STAT *stat = (INIT_TIMING_STAT *)executionContext; + clock_gettime(CLOCK_MONOTONIC, &(stat->endTime)); + long long diff = InitDiffTime(stat); + INIT_LOGI("Executing hook [%d:%d] cost [%lld]us, result %d.", + hookInfo->stage, hookInfo->prio, diff, executionRetVal); +} + +static void InitSysAdj(void) +{ + const char* path = "/proc/self/oom_score_adj"; + const char* content = "-1000"; + int fd = open(path, O_RDWR); + if (fd == -1) { + return; + } + if (write(fd, content, strlen(content)) < 0) { + close(fd); + return; + } + close(fd); + return; +} + +INIT_STATIC void TriggerServices(int startMode) +{ + int index = 0; + int jobNum = 0; + char jobName[64] = {0}; // 64 job name + char cmd[64] = {0}; // 64 job name + const int maxServiceInJob = 4; // 4 service in job + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + Service *service = node->data.service; + if (service == NULL || service->startMode != startMode) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + if (IsOnDemandService(service)) { + if (CreateSocketForService(service) != 0) { + INIT_LOGE("service %s exit! create socket failed!", service->name); + } + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + if (sprintf_s(cmd, sizeof(cmd), "start %s", service->name) <= 0) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + if (index == 0) { + if (sprintf_s(jobName, sizeof(jobName), "boot-service:service-%d-%03d", startMode, jobNum) <= 0) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + jobNum++; + } + index++; + AddCompleteJob(jobName, NULL, cmd); + INIT_LOGV("Add %s to job %s", service->name, jobName); + if (index == maxServiceInJob) { + PostTrigger(EVENT_TRIGGER_BOOT, jobName, strlen(jobName)); + index = 0; + } + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } + if (index > 0) { + PostTrigger(EVENT_TRIGGER_BOOT, jobName, strlen(jobName)); + } +} + +void ParseInitCfgByPriority(void) +{ + CfgFiles *files = GetCfgFiles("etc/init"); + for (int i = 0; files && i < MAX_CFG_POLICY_DIRS_CNT; i++) { + if (files->paths[i]) { + if (ReadFileInDir(files->paths[i], ".cfg", ParseInitCfg, NULL) < 0) { + break; + } + } + } + FreeCfgFiles(files); +} + +void SystemConfig(const char *uptime) +{ + INIT_TIMING_STAT timingStat; + + InitSysAdj(); + + HOOK_EXEC_OPTIONS options; + + options.flags = 0; + options.preHook = InitPreHook; + options.postHook = InitPostHook; + InitServiceSpace(); + HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, (void *)&timingStat, (void *)&options); + RecordInitBootEvent("init.prepare"); + + HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, (void *)&timingStat, (void *)&options); + if (InitParamService() != 0) { + INIT_LOGE("[startup_failed]Init param service failed %d", SYS_PARAM_INIT_FAILED); + ExecReboot("panic"); + } + InitParseGroupCfg(); + RegisterBootStateChange(BootStateChange); + + INIT_LOGI("boot stage: init finish."); + + // The cgroupv1 hierarchy may be created asynchronously in the early stage, + // so make sure it has been done before loading SELinux. + struct stat sourceInfo = {0}; + if (stat("/dev/cgroup", &sourceInfo) == 0) { + WaitForFile("/dev/memcg/procs", WAIT_MAX_SECOND); + } + + // load SELinux context and policy + // Do not move position! + PluginExecCmdByName("loadSelinuxPolicy", ""); + RecordInitBootEvent("init.prepare"); + + // after selinux loaded + SignalInit(); + + RecordInitBootEvent("init.ParseCfg"); + LoadSpecialParam(); + + // parse parameters + HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, (void *)&timingStat, (void *)&options); + InitLoadParamFiles(); + + // Write kernel uptime into system parameter + WriteUptimeSysParam("ohos.boot.time.kernel", uptime); + + // read config + HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, (void *)&timingStat, (void *)&options); + ReadConfig(); + RecordInitBootEvent("init.ParseCfg"); + INIT_LOGI("boot stage: parse config file finish.cfg count %d", g_serviceSpace.serviceCount); + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, (void *)&timingStat, (void *)&options); + + IsEnableSandbox(); + // execute init + PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init")); + PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init")); + TriggerServices(START_MODE_BOOT); + PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init")); + TriggerServices(START_MODE_NORMAL); + clock_gettime(CLOCK_MONOTONIC, &(g_bootJob.startTime)); +} + +void SystemRun(void) +{ + StartParamService(); +} diff --git a/services/init/standard/init_cmdexecutor.c b/services/init/standard/init_cmdexecutor.c new file mode 100644 index 0000000000000000000000000000000000000000..20b5718cd835040f74e8358da3db48cc75bc5fa1 --- /dev/null +++ b/services/init/standard/init_cmdexecutor.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2021 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 "cJSON.h" +#include "init_param.h" +#include "init_utils.h" +#include "init_log.h" +#include "init_group_manager.h" +#include "init_service_manager.h" +#include "securec.h" +#include "modulemgr.h" +#include "init_module_engine.h" + +#define MAX_CMD_ARGC 10 +static int g_cmdExecutorId = 0; +static int g_cmdId = 0; +int AddCmdExecutor_(const char *cmdName, CmdExecutor execCmd, int careContext) +{ + INIT_ERROR_CHECK(cmdName != NULL, return -1, "Invalid input param"); + INIT_LOGV("Add command '%s' executor.", cmdName); + PluginCmd *cmd = NULL; + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName); + if (groupNode == NULL) { + groupNode = AddGroupNode(NODE_TYPE_CMDS, cmdName); + INIT_ERROR_CHECK(groupNode != NULL, return -1, "Failed to create group node"); + } + cmd = groupNode->data.cmd; + if (cmd == NULL) { + cmd = (PluginCmd *)calloc(1, sizeof(PluginCmd)); + INIT_ERROR_CHECK(cmd != NULL, return -1, "Failed to create cmd condition"); + groupNode->data.cmd = cmd; + cmd->cmdId = g_cmdId++; + cmd->name = groupNode->name; + cmd->careContext = careContext; + OH_ListInit(&cmd->cmdExecutor); + } + if (execCmd == NULL) { + return 0; + } + PluginCmdExecutor *cmdExec = (PluginCmdExecutor *)calloc(1, sizeof(PluginCmdExecutor)); + INIT_ERROR_CHECK(cmdExec != NULL, return -1, "Failed to create cmd listener"); + OH_ListInit(&cmdExec->node); + cmdExec->id = ++g_cmdExecutorId; + cmdExec->execCmd = execCmd; + OH_ListAddTail(&cmd->cmdExecutor, &cmdExec->node); + return cmdExec->id; +} + +int AddCareContextCmdExecutor(const char *cmdName, CmdExecutor execCmd) +{ + return AddCmdExecutor_(cmdName, execCmd, 1); +} + +int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) +{ + return AddCmdExecutor_(cmdName, execCmd, 0); +} + +void RemoveCmdExecutor(const char *cmdName, int id) +{ + INIT_ERROR_CHECK(cmdName != NULL, return, "Invalid input param"); + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName); + INIT_ERROR_CHECK(groupNode != NULL && groupNode->data.cmd != NULL, + return, "Can not find cmd %s", cmdName); + + PluginCmd *cmd = groupNode->data.cmd; + ListNode *node = cmd->cmdExecutor.next; + while (node != &cmd->cmdExecutor) { + PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node); + if (cmdExec->id == id) { + OH_ListRemove(&cmdExec->node); + free(cmdExec); + break; + } + node = node->next; + } + if (cmd->cmdExecutor.next != &cmd->cmdExecutor) { + return; + } + DelGroupNode(NODE_TYPE_CMDS, cmdName); + free(cmd); +} + +static void PluginExecCmd_(PluginCmd *cmd, const char *cmdContent) +{ + const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", MAX_CMD_ARGC); + if (ctx == NULL) { + INIT_LOGE("Invalid arguments cmd: %s content: %s", cmd->name, cmdContent); + return; + } else if (ctx->argc > MAX_CMD_ARGC) { + INIT_LOGE("Invalid arguments cmd: %s content: %s argc: %d ", + cmd->name, cmdContent, ctx->argc); + FreeCmdArg((struct CmdArgs *)ctx); + return; + } + INIT_LOGV("PluginExecCmd_ index %s content: %s", cmd->name, cmdContent); + ListNode *node = cmd->cmdExecutor.next; + while (node != &cmd->cmdExecutor) { + PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node); + cmdExec->execCmd(cmdExec->id, cmd->name, ctx->argc, (const char **)ctx->argv); + node = node->next; + } + FreeCmdArg((struct CmdArgs *)ctx); +} + +void PluginExecCmdByName(const char *name, const char *cmdContent) +{ + INIT_ERROR_CHECK(name != NULL, return, "Invalid cmd for %s", cmdContent); + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, name); + if (groupNode == NULL || groupNode->data.cmd == NULL) { + return; + } + PluginCmd *cmd = groupNode->data.cmd; + PluginExecCmd_(cmd, cmdContent); +} + +int PluginExecCmd(const char *name, int argc, const char **argv) +{ + INIT_ERROR_CHECK(name != NULL, return -1, "Invalid cmd "); + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, name); + if (groupNode == NULL || groupNode->data.cmd == NULL) { + return -1; + } + PluginCmd *cmd = groupNode->data.cmd; + INIT_LOGV("PluginExecCmd index %s", cmd->name); + int ret = 0; + ListNode *node = cmd->cmdExecutor.next; + while (node != &cmd->cmdExecutor) { + PluginCmdExecutor *cmdExec = ListEntry(node, PluginCmdExecutor, node); + ret = cmdExec->execCmd(cmdExec->id, cmd->name, argc, argv); + node = node->next; + } + return ret; +} + +static int CompareCmdId(const HashNode *node, const void *key) +{ + InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode); + if (groupNode == NULL || groupNode->data.cmd == NULL) { + return 1; + } + PluginCmd *cmd = groupNode->data.cmd; + return cmd->cmdId - *(int *)key; +} + +static PluginCmd *GetPluginCmdByIndex(int index) +{ + int hashCode = (((unsigned int)index >> 16) & 0x0000ffff) - 1; // 16 left shift + int cmdId = ((unsigned int)index & 0x0000ffff); + HashNode *node = OH_HashMapFind(GetGroupHashMap(NODE_TYPE_CMDS), + hashCode, (const void *)&cmdId, CompareCmdId); + if (node == NULL) { + return NULL; + } + InitGroupNode *groupNode = HASHMAP_ENTRY(node, InitGroupNode, hashNode); + if (groupNode == NULL || groupNode->data.cmd == NULL) { + return NULL; + } + return groupNode->data.cmd; +} + +const char *GetPluginCmdNameByIndex(int index) +{ + PluginCmd *cmd = GetPluginCmdByIndex(index); + if (cmd == NULL) { + return NULL; + } + return cmd->name; +} + +void PluginExecCmdByCmdIndex(int index, const char *cmdContent, const ConfigContext *context) +{ + PluginCmd *cmd = GetPluginCmdByIndex(index); + if (cmd == NULL) { + INIT_LOGW("Cannot find plugin command with index %d", index); + return; + } + INIT_LOGV("Command: %s cmdContent: %s %d", cmd->name, cmdContent, cmd->careContext); + if (!cmd->careContext || !CheckExecuteInSubInit(context)) { + PluginExecCmd_(cmd, cmdContent); + } else { + ExecuteCmdInSubInit(context, cmd->name, cmdContent); + } +} + +const char *PluginGetCmdIndex(const char *cmdStr, int *index) +{ + char cmdName[MAX_CMD_NAME_LEN] = {}; + int i = 0; + while ((i < MAX_CMD_NAME_LEN) && (*(cmdStr + i) != '\0') && (*(cmdStr + i) != ' ')) { + cmdName[i] = *(cmdStr + i); + i++; + } + if (i >= MAX_CMD_NAME_LEN) { + return NULL; + } + cmdName[i] = '\0'; + InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName); + if (groupNode == NULL || groupNode->data.cmd == NULL) { + AddCmdExecutor(cmdName, NULL); + } + groupNode = GetGroupNode(NODE_TYPE_CMDS, cmdName); + INIT_ERROR_CHECK(groupNode != NULL && groupNode->data.cmd != NULL, + return NULL, "Failed to create pluginCmd %s", cmdName); + + PluginCmd *cmd = groupNode->data.cmd; + int hashCode = GenerateHashCode(cmdName); + hashCode = (hashCode < 0) ? -hashCode : hashCode; + hashCode = hashCode % GROUP_HASHMAP_BUCKET; + *index = ((hashCode + 1) << 16) | cmd->cmdId; // 16 left shift + return cmd->name; +} diff --git a/services/init/standard/init_cmds.c b/services/init/standard/init_cmds.c new file mode 100755 index 0000000000000000000000000000000000000000..011e061ae78d1639fffb279fe9b8196960ed4288 --- /dev/null +++ b/services/init/standard/init_cmds.c @@ -0,0 +1,646 @@ +/* + * Copyright (c) 2021-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 "init_cmds.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bootstage.h" +#include "fs_manager/fs_manager.h" +#include "init_cmdexecutor.h" +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_param.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "sandbox.h" +#include "sandbox_namespace.h" +#include "securec.h" +#include "fscrypt_utils.h" + +#ifdef SUPPORT_PROFILER_HIDEBUG +#include +#endif + +#define FSCRYPT_POLICY_BUF_SIZE (60) +#define DECIMAL 10 +#define OCTAL 8 +#define BOOT_DETECTOR_IOCTL_BASE 'B' +#define SET_SHUT_STAGE _IOW(BOOT_DETECTOR_IOCTL_BASE, 106, int) +#define SHUT_STAGE_FRAMEWORK_START 1 + +int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen) +{ + INIT_CHECK_RETURN_VALUE((symValue != NULL) && (paramValue != NULL) && (paramLen != 0), -1); + char tmpName[PARAM_NAME_LEN_MAX] = { 0 }; + int ret; + uint32_t curr = 0; + char *start = (char *)symValue; + if (symLen > strlen(symValue)) { + return -1; + } + char *end = (char *)symValue + symLen; + do { + char *begin = strchr(start, '$'); + if (begin == NULL || begin >= end) { // not has '$' copy the original string + ret = strncpy_s(paramValue + curr, paramLen - curr, start, symLen); + INIT_ERROR_CHECK(ret == EOK, return -1, "Failed to copy start %s", start); + break; + } else { + ret = memcpy_s(paramValue + curr, paramLen - curr, start, begin - start); + INIT_ERROR_CHECK(ret == 0, return -1, "Failed to copy first value %s", symValue); + curr += begin - start; + } + while (*begin != '{') { + INIT_CHECK_RETURN_VALUE(*begin != '\0', -1); + begin++; + } + begin++; + char *left = strchr(begin, '}'); + INIT_CHECK_RETURN_VALUE(left != NULL, -1); + + // copy param name + ret = strncpy_s(tmpName, PARAM_NAME_LEN_MAX, begin, left - begin); + INIT_ERROR_CHECK(ret == EOK, return -1, "Invalid param name %s", symValue); + if (paramLen < curr) { + INIT_LOGE("Failed to get param value over max length"); + return -1; + } + uint32_t valueLen = paramLen - curr; + ret = SystemReadParam(tmpName, paramValue + curr, &valueLen); + INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get param %s", tmpName); + curr += valueLen; + left++; + if ((unsigned int)(left - symValue) >= symLen) { + break; + } + start = left; + } while (1); + return 0; +} + +static int SyncExecCommand(int argc, char * const *argv) +{ + INIT_LOGI("Sync exec: %s", argv[0]); + pid_t pid = fork(); + INIT_ERROR_CHECK(!(pid < 0), return -1, "Fork new process to format failed: %d", errno); + if (pid == 0) { + INIT_CHECK_ONLY_ELOG(execv(argv[0], argv) == 0, "execv %s failed! err %d.", argv[0], errno); + exit(-1); + } + int status; + pid_t ret = waitpid(pid, &status, 0); + if (ret != pid) { + INIT_LOGE("Failed to wait pid %d, errno %d", pid, errno); + return -1; + } + INIT_LOGI("Sync exec: %s result %d %d", argv[0], WEXITSTATUS(status), WIFEXITED(status)); + return WEXITSTATUS(status); +} + +static void DoIfup(const struct CmdArgs *ctx) +{ + struct ifreq interface; + INIT_ERROR_CHECK(strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) == EOK, + return, "DoIfup failed to copy interface name"); + INIT_LOGV("interface name: %s", interface.ifr_name); + + int fd = socket(AF_INET, SOCK_DGRAM, 0); + INIT_ERROR_CHECK(fd >= 0, return, "DoIfup failed to create socket, err = %d", errno); + + if (ioctl(fd, SIOCGIFFLAGS, &interface) >= 0) { + interface.ifr_flags |= IFF_UP; + INIT_CHECK_ONLY_ELOG(ioctl(fd, SIOCSIFFLAGS, &interface) >= 0, + "DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno); + } + close(fd); +} + +// format insmod [-f] [options] +static void DoInsmod(const struct CmdArgs *ctx) +{ + int index = 0; + int flags = 0; + char *fileName = NULL; + if (ctx->argc > index) { + fileName = ctx->argv[index]; + index++; + } + INIT_ERROR_CHECK(fileName != NULL, return, "Can not find file name from param %s", ctx->argv[0]); + INIT_LOGV("Install mode %s ", fileName); + char *realPath = GetRealPath(fileName); + INIT_ERROR_CHECK(realPath != NULL, return, "Can not get real file name from param %s", ctx->argv[0]); + if (ctx->argc > 1 && ctx->argv[1] != NULL && strcmp(ctx->argv[1], "-f") == 0) { // [-f] + flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS; + index++; + } + char *options = BuildStringFromCmdArg(ctx, index); // [options] + int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); + if (fd >= 0) { + int rc = syscall(__NR_finit_module, fd, options, flags); + if (rc == -1) { + INIT_LOGE("Failed to install kernel module for %s failed options %s err: %d", realPath, options, errno); + } + } + if (options != NULL) { + free(options); + } + if (fd >= 0) { + close(fd); + } + free(realPath); + return; +} + +static void DoSetParam(const struct CmdArgs *ctx) +{ + INIT_LOGV("set param name: %s, value %s ", ctx->argv[0], ctx->argv[1]); + SystemWriteParam(ctx->argv[0], ctx->argv[1]); +} + +static void DoLoadPersistParams(const struct CmdArgs *ctx) +{ + INIT_LOGV("LoadPersistParams"); + LoadPersistParams(); +} + +static void DoLoadPrivatePersistParams(const struct CmdArgs *ctx) +{ + INIT_LOGV("LoadPersistParams"); + LoadPrivatePersistParams(); + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL, NULL); +} + +static void DoTriggerCmd(const struct CmdArgs *ctx) +{ + INIT_LOGV("DoTrigger :%s", ctx->argv[0]); + DoTriggerExec(ctx->argv[0]); +} + +static void DoLoadDefaultParams(const struct CmdArgs *ctx) +{ + int mode = 0; + if (ctx->argc > 1 && strcmp(ctx->argv[1], "onlyadd") == 0) { + mode = LOAD_PARAM_ONLY_ADD; + } + INIT_LOGV("DoLoadDefaultParams args : %s %d", ctx->argv[0], mode); + LoadDefaultParams(ctx->argv[0], mode); +} + +static void DoSyncExec(const struct CmdArgs *ctx) +{ + // format: syncexec /xxx/xxx/xxx xxx + INIT_ERROR_CHECK(ctx != NULL && ctx->argv[0] != NULL, return, "DoSyncExec: invalid arguments"); + SyncExecCommand(ctx->argc, ctx->argv); + return; +} + +static void DoExec(const struct CmdArgs *ctx) +{ + // format: exec /xxx/xxx/xxx xxx + INIT_ERROR_CHECK(ctx != NULL && ctx->argv[0] != NULL, return, "DoExec: invalid arguments"); + pid_t pid = fork(); + INIT_ERROR_CHECK(pid >= 0, return, "DoExec: failed to fork child process to exec \"%s\"", ctx->argv[0]); + + if (pid == 0) { + OpenHidebug(ctx->argv[0]); + int ret = execv(ctx->argv[0], ctx->argv); + INIT_CHECK_ONLY_ELOG(ret != -1, "DoExec: execute \"%s\" failed: %d.", ctx->argv[0], errno); + _exit(0x7f); + } + return; +} + +static void DoSymlink(const struct CmdArgs *ctx) +{ + // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx + int ret = symlink(ctx->argv[0], ctx->argv[1]); + if (ret != 0 && errno != EEXIST) { + INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno); + } +} + +static mode_t GetDeviceMode(const char *deviceStr) +{ + switch (*deviceStr) { + case 'b': + case 'B': + return S_IFBLK; + case 'c': + case 'C': + return S_IFCHR; + case 'f': + case 'F': + return S_IFIFO; + default: + return -1; + } +} + +static void DoMakeNode(const struct CmdArgs *ctx) +{ + // format: mknod path b 0644 1 9 + const int deviceTypePos = 1; + const int authorityPos = 2; + const int majorDevicePos = 3; + const int minorDevicePos = 4; + INIT_ERROR_CHECK(access(ctx->argv[1], F_OK), return, "DoMakeNode failed, path has sexisted"); + mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]); + errno = 0; + unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, DECIMAL); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[majorDevicePos]); + unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, DECIMAL); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[minorDevicePos]); + mode_t authority = strtoul(ctx->argv[authorityPos], NULL, OCTAL); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[authorityPos]); + int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor)); + if (ret != 0) { + INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno); + } +} + +static void DoMakeDevice(const struct CmdArgs *ctx) +{ + // format: makedev major minor + errno = 0; + unsigned int major = strtoul(ctx->argv[0], NULL, DECIMAL); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[0]); + unsigned int minor = strtoul(ctx->argv[1], NULL, DECIMAL); + INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[1]); + dev_t deviceId = makedev(major, minor); + INIT_CHECK_ONLY_ELOG(deviceId >= 0, "DoMakedevice \" major:%s, minor:%s \" failed :%d ", ctx->argv[0], + ctx->argv[1], errno); + return; +} + +static void DoMountFstabFile(const struct CmdArgs *ctx) +{ + INIT_LOGI("Mount partitions from fstab file \" %s \"", ctx->argv[0]); + int ret = MountAllWithFstabFile(ctx->argv[0], 0); + INIT_LOGI("Mount partitions from fstab file \" %s \" finish ret %d", ctx->argv[0], ret); + HookMgrExecute(GetBootStageHookMgr(), INIT_MOUNT_STAGE, NULL, NULL); +} + +static void DoUmountFstabFile(const struct CmdArgs *ctx) +{ + INIT_LOGI("Umount partitions from fstab file \" %s \"", ctx->argv[0]); + int rc = UmountAllWithFstabFile(ctx->argv[0]); + if (rc < 0) { + INIT_LOGE("Run command umount_fstab failed"); + } else { + INIT_LOGI("Umount partitions from fstab done"); + } +} + +static void DoRestorecon(const struct CmdArgs *ctx) +{ + int ret; + INIT_CMD_INFO cmdInfo; + cmdInfo.cmdName = "restorecon"; + cmdInfo.cmdContent = ctx->argv[0]; + cmdInfo.reserved = NULL; + if (ctx->argc > 1) { + if (strcmp(ctx->argv[0], "-F") == 0) { + cmdInfo.cmdContent = ctx->argv[1]; + } + if (strcmp(ctx->argv[ctx->argc - 1], "--skip-ELX") == 0) { + cmdInfo.reserved = ctx->argv[ctx->argc - 1]; + } + } + + HOOK_EXEC_OPTIONS options; + options.flags = TRAVERSE_STOP_WHEN_ERROR; + options.preHook = NULL; + options.postHook = NULL; + ret = HookMgrExecute(GetBootStageHookMgr(), INIT_RESTORECON, (void*)(&cmdInfo), (void*)(&options)); + if (ret == 0) { + return; + } + if (ctx->argc > 1) { + if (strcmp(ctx->argv[0], "-F") == 0) { + PluginExecCmdByName("restoreContentRecurseForce", ctx->argv[1]); + } else if (strcmp(ctx->argv[ctx->argc - 1], "--skip-ELX") == 0) { + PluginExecCmdByName("restoreContentRecurseSkipElx", ctx->argv[0]); + } + } else { + PluginExecCmdByName("restoreContentRecurse", ctx->argv[0]); + } + return; +} + +static void DoLoadAccessTokenId(const struct CmdArgs *ctx) +{ + LoadAccessTokenId(); +} + +static int FilterService(const Service *service, const char **exclude, int size) +{ + for (int i = 0; i < size; i++) { + if (exclude[i] != NULL && strcmp(service->name, exclude[i]) == 0) { + return 1; + } + } + return 0; +} + +static void DoStopAllServices(const struct CmdArgs *ctx) +{ + int flags = SERVICE_ATTR_INVALID; + if (ctx->argc >= 1 && strcmp(ctx->argv[0], "true") == 0) { + flags |= SERVICE_ATTR_NEEDWAIT; + StopAllServices(flags, (const char **)(&ctx->argv[1]), ctx->argc - 1, FilterService); + } else { + StopAllServices(flags, (const char **)ctx->argv, ctx->argc, FilterService); + } + return; +} + +static void DoUmount(const struct CmdArgs *ctx) +{ + INIT_LOGI("DoUmount %s", ctx->argv[0]); + MountStatus status = GetMountStatusForMountPoint(ctx->argv[0]); + if (status == MOUNT_MOUNTED) { + int ret = umount(ctx->argv[0]); + if ((ret != 0) && (ctx->argc > 1) && (strcmp(ctx->argv[1], "MNT_FORCE") == 0)) { + ret = umount2(ctx->argv[0], MNT_FORCE); + } + INIT_CHECK_ONLY_ELOG(ret == 0, "Failed to umount %s, errno %d", ctx->argv[0], errno); + } else if (status == MOUNT_UMOUNTED) { + INIT_LOGI("%s is already umounted", ctx->argv[0]); + } else { + INIT_LOGE("Failed to get %s mount status", ctx->argv[0]); + } +} + +static void DoRemoveDmDevice(const struct CmdArgs *ctx) +{ + INIT_LOGI("DoRemoveDmDevice %s", ctx->argv[0]); + int ret = FsManagerDmRemoveDevice(ctx->argv[0]); + if (ret < 0) { + INIT_LOGE("Failed to remove dm device %s", ctx->argv[0]); + } else { + INIT_LOGI("Successed to remove dm device %s", ctx->argv[0]); + } +} + +static void DoMountOneFstabFile(const struct CmdArgs *ctx) +{ + INIT_LOGI("Mount %s from fstab file \" %s \"", ctx->argv[1], ctx->argv[0]); + int ret = MountOneWithFstabFile(ctx->argv[0], ctx->argv[1], 1); + if (ret < 0) { + INIT_LOGE("Failed to mount dm device %d", ret); + } else { + INIT_LOGI("Successed to mount dm device %d", ret); + } +} + +static void DoSync(const struct CmdArgs *ctx) +{ + sync(); +} + +static void DoTimerStart(const struct CmdArgs *ctx) +{ + INIT_LOGI("Timer start service with arg = %s", ctx->argv[0]); + char *arg = ctx->argv[0]; + int count = 0; + int expectedCount = 2; + char **splitArgs = SplitStringExt(ctx->argv[0], "|", &count, expectedCount); + if (splitArgs == NULL) { + INIT_LOGE("Call timer_start with invalid arguments"); + return; + } + + if (count != expectedCount) { + INIT_LOGE("Call timer_start with unexpected arguments %s", arg); + FreeStringVector(splitArgs, count); + return; + } + + Service *service = GetServiceByName(splitArgs[0]); + if (service == NULL) { + INIT_LOGE("Cannot find service in timer_start command"); + FreeStringVector(splitArgs, count); + return; + } + + errno = 0; + uint64_t timeout = strtoull(splitArgs[1], NULL, DECIMAL_BASE); + if (errno != 0) { + INIT_LOGE("call timer_start with invalid timer"); + FreeStringVector(splitArgs, count); + return; + } + // not need this anymore , release memory. + FreeStringVector(splitArgs, count); + ServiceStartTimer(service, timeout); +} + +static void DoTimerStop(const struct CmdArgs *ctx) +{ + INIT_LOGI("Stop service timer with arg = %s", ctx->argv[0]); + const char *serviceName = ctx->argv[0]; + Service *service = GetServiceByName(serviceName); + if (service == NULL) { + INIT_LOGE("Cannot find service in timer_stop command"); + return; + } + ServiceStopTimer(service); +} + +static bool InitFscryptPolicy(void) +{ + char policy[FSCRYPT_POLICY_BUF_SIZE]; + if (LoadFscryptPolicy(policy, FSCRYPT_POLICY_BUF_SIZE) == 0) { + if (SetFscryptSysparam(policy) == 0) { + return true; + } + } + return false; +} + +static void DoInitGlobalKey(const struct CmdArgs *ctx) +{ + INIT_LOGV("Do init global key start"); + const char *dataDir = "/data"; + if (strncmp(ctx->argv[0], dataDir, strlen(dataDir)) != 0) { + INIT_LOGE("Not data partitation"); + return; + } + if (!InitFscryptPolicy()) { + INIT_LOGW("Init fscrypt failed, not enable fscrypt"); + return; + } + + char * const argv[] = { + "/system/bin/sdc", + "filecrypt", + "init_global_key", + NULL + }; + int argc = ARRAY_LENGTH(argv); + int ret = SyncExecCommand(argc, argv); + if (ret != 0) { + INIT_LOGE("[startup_failed]Init global key failed %d", INIT_GOLBALY_KEY_FAILED); + } + INIT_CMD_INFO cmdInfo; + cmdInfo.cmdName = "init_global_key"; + cmdInfo.cmdContent = (const char *)&ret; + cmdInfo.reserved = NULL; + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_DATA_UNENCRYPT, (void*)(&cmdInfo), NULL); +} + +static void DoInitMainUser(const struct CmdArgs *ctx) +{ + char * const argv[] = { + "/system/bin/sdc", + "filecrypt", + "init_main_user", + NULL + }; + int argc = ARRAY_LENGTH(argv); + int ret = SyncExecCommand(argc, argv); + INIT_CMD_INFO cmdInfo; + cmdInfo.cmdName = "init_main_user"; + cmdInfo.cmdContent = (const char *)&ret; + cmdInfo.reserved = NULL; + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_DATA_UNENCRYPT, (void*)(&cmdInfo), NULL); +} + +static void DoMkswap(const struct CmdArgs *ctx) +{ + char *const argv[] = { + "/system/bin/mkswap", + ctx->argv[0], + NULL + }; + int argc = ARRAY_LENGTH(argv); + SyncExecCommand(argc, argv); +} + +static void DoSwapon(const struct CmdArgs *ctx) +{ + char *const argv[] = { + "/system/bin/swapon", + ctx->argv[0], + NULL + }; + int argc = ARRAY_LENGTH(argv); + SyncExecCommand(argc, argv); +} + +static void DoMkSandbox(const struct CmdArgs *ctx) +{ + INIT_LOGV("Do make sandbox start"); + const char *sandbox = ctx->argv[0]; + InitDefaultNamespace(); + if (!InitSandboxWithName(sandbox)) { + INIT_LOGE("Failed to init sandbox with name %s.", sandbox); + } + + if (PrepareSandbox(sandbox) != 0) { + INIT_LOGE("Failed to prepare sandbox %s.", sandbox); + DestroySandbox(sandbox); + } + if (EnterDefaultNamespace() < 0) { + INIT_LOGE("Failed to set default namespace."); + } + CloseDefaultNamespace(); +} + +static void DoStopFeedHighdog(const struct CmdArgs *ctx) +{ + INIT_LOGI("stop feed highdog"); + int fd = open("/dev/bbox", O_WRONLY); + if (fd < 0) { + INIT_LOGE("open /dev/bbox failed"); + return; + } + int stage = SHUT_STAGE_FRAMEWORK_START; + int ret = ioctl(fd, SET_SHUT_STAGE, &stage); + if (ret < 0) { + INIT_LOGE("set shut stage failed"); + } + close(fd); + return; +} + +static const struct CmdTable g_cmdTable[] = { + { "syncexec ", 1, 10, 0, DoSyncExec }, + { "exec ", 1, 10, 0, DoExec }, + { "mknode ", 5, 5, 0, DoMakeNode }, + { "makedev ", 2, 2, 0, DoMakeDevice }, + { "symlink ", 2, 2, 1, DoSymlink }, + { "trigger ", 0, 1, 0, DoTriggerCmd }, + { "insmod ", 1, 10, 1, DoInsmod }, + { "setparam ", 2, 2, 0, DoSetParam }, + { "load_persist_params ", 0, 1, 0, DoLoadPersistParams }, + { "load_private_persist_params ", 0, 1, 0, DoLoadPrivatePersistParams }, + { "load_param ", 1, 2, 0, DoLoadDefaultParams }, + { "load_access_token_id ", 0, 1, 0, DoLoadAccessTokenId }, + { "ifup ", 1, 1, 1, DoIfup }, + { "mount_fstab ", 1, 1, 0, DoMountFstabFile }, + { "umount_fstab ", 1, 1, 0, DoUmountFstabFile }, + { "remove_dm_device", 1, 1, 0, DoRemoveDmDevice }, + { "mount_one_fstab", 2, 2, 0, DoMountOneFstabFile }, + { "restorecon ", 1, 2, 1, DoRestorecon }, + { "stopAllServices ", 0, 10, 0, DoStopAllServices }, + { "umount ", 1, 1, 0, DoUmount }, + { "sync ", 0, 1, 0, DoSync }, + { "timer_start", 1, 1, 0, DoTimerStart }, + { "timer_stop", 1, 1, 0, DoTimerStop }, + { "init_global_key ", 1, 1, 0, DoInitGlobalKey }, + { "init_main_user ", 0, 1, 0, DoInitMainUser }, + { "mkswap", 1, 1, 0, DoMkswap}, + { "swapon", 1, 1, 0, DoSwapon}, + { "mksandbox", 1, 1, 0, DoMkSandbox}, + { "stop_feed_highdog", 0, 1, 0, DoStopFeedHighdog}, +}; + +const struct CmdTable *GetCmdTable(int *number) +{ + *number = (int)ARRAY_LENGTH(g_cmdTable); + return g_cmdTable; +} + +void OpenHidebug(const char *name) +{ +#ifdef SUPPORT_PROFILER_HIDEBUG + InitEnvironmentParam(name); +#endif +} + +int SetFileCryptPolicy(const char *dir) +{ + if (dir == NULL) { + INIT_LOGE("SetFileCryptPolicy:dir is null"); + return -EINVAL; + } + return FscryptPolicyEnable(dir); +} diff --git a/services/init/standard/init_control_fd_service.c b/services/init/standard/init_control_fd_service.c new file mode 100755 index 0000000000000000000000000000000000000000..50d283f4bd12304ebbf4334bd8db37dca4b1fa09 --- /dev/null +++ b/services/init/standard/init_control_fd_service.c @@ -0,0 +1,294 @@ +/* + * 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 "control_fd.h" +#include "init_service.h" +#include "init_service_manager.h" +#include "init_modulemgr.h" +#include "init_utils.h" +#include "init_log.h" +#include "init_group_manager.h" +#include "init_param.h" +#include "hookmgr.h" +#include "bootstage.h" +#include "le_task.h" +#include "loop_event.h" +#include "init_hashmap.h" +#include "le_loop.h" + +static void DumpLoopNodeInfo(const HashNode *node, const void *context) +{ + INIT_CHECK(node != NULL, return); + BaseTask *baseTask = HASHMAP_ENTRY(node, BaseTask, hashNode); + INIT_CHECK(baseTask != NULL, return); + const TaskHandle task = (void*)baseTask; + if (baseTask->dumpTaskInfo != NULL) { + baseTask->dumpTaskInfo(task); + } +} + +static void DumpLoop() +{ + printf(" Dump Loop Info:\n"); + OH_HashMapTraverse(((EventLoop *)LE_GetDefaultLoop())->taskMap, DumpLoopNodeInfo, NULL); +} + +static void DumpServiceArgs(const char *info, const ServiceArgs *args) +{ + printf("\tservice %s count %d \n", info, args->count); + for (int j = 0; j < args->count; j++) { + if (args->argv[j] != NULL) { + printf("\t\tinfo [%d] %s \n", j, args->argv[j]); + } + } +} + +static void DumpServiceJobs(const Service *service) +{ + printf("\tservice job info \n"); + if (service->serviceJobs.jobsName[JOB_ON_BOOT] != NULL) { + printf("\t\tservice boot job %s \n", service->serviceJobs.jobsName[JOB_ON_BOOT]); + } + if (service->serviceJobs.jobsName[JOB_PRE_START]!= NULL) { + printf("\t\tservice pre-start job %s \n", service->serviceJobs.jobsName[JOB_PRE_START]); + } + if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) { + printf("\t\tservice start job %s \n", service->serviceJobs.jobsName[JOB_ON_START]); + } + if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) { + printf("\t\tservice stop job %s \n", service->serviceJobs.jobsName[JOB_ON_STOP]); + } + if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) { + printf("\t\tservice restart job %s \n", service->serviceJobs.jobsName[JOB_ON_RESTART]); + } +} + +static void DumpServiceSocket(const Service *service) +{ + printf("\tservice socket info \n"); + ServiceSocket *sockopt = service->socketCfg; + while (sockopt != NULL) { + printf("\t\tsocket fd: %d \n", sockopt->sockFd); + printf("\t\tsocket name: %s \n", sockopt->name); + printf("\t\tsocket type: %u \n", sockopt->type); + printf("\t\tsocket uid: %u \n", sockopt->uid); + printf("\t\tsocket gid: %u \n", sockopt->gid); + sockopt = sockopt->next; + } +} + +void DumpServiceHookExecute(const char *name, const char *info) +{ + SERVICE_INFO_CTX context; + context.serviceName = name; + context.reserved = info; + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&context), NULL); +} + +static void DumpOneService(const Service *service) +{ + static const struct InitErrMap initErrMaps[] = { + {INIT_OK, ""}, +#define XX(code, info) {INIT_ ## code, info}, + INIT_ERRNO_MAP(XX) +#undef XX + {INIT_OK, ""} + }; + + const InitArgInfo startModeMap[] = { + {"condition", START_MODE_CONDITION}, + {"boot", START_MODE_BOOT}, + {"normal", START_MODE_NORMAL} + }; + + const static char *serviceStatusMap[] = { + "created", "starting", "running", "ready", + "stopping", "stopped", "suspended", "freezed", "disabled", "critical" + }; + + printf("\tservice name: [%s] \n", service->name); + printf("\tservice pid: [%d] \n", service->pid); + int tmpCount = sizeof(initErrMaps) / sizeof(initErrMaps[0]); + if ((int)service->lastErrno < tmpCount) { + printf("\tservice last error: %s(%d) \n", initErrMaps[service->lastErrno].info, service->lastErrno); + } else { + printf("\tservice last error: %d \n", service->lastErrno); + } + printf("\tservice context : [%s] \n", (service->context.type == INIT_CONTEXT_CHIPSET) ? "chipset" : "system"); + printf("\tservice crashCnt: [%d] \n", service->crashCnt); + printf("\tservice attribute: [%u] \n", service->attribute); + printf("\tservice importance: [%d] \n", service->importance); + printf("\tservice startMode: [%s] \n", startModeMap[service->startMode].name); + printf("\tservice status: [%s] \n", serviceStatusMap[service->status]); + printf("\tservice perms uID [%u] \n", service->servPerm.uID); + printf("\tservice Timer ID [%d] \n", LE_GetSocketFd(service->timer)); + DumpServiceArgs("path arg", &service->pathArgs); + DumpServiceArgs("writepid file", &service->writePidArgs); + DumpServiceJobs(service); + DumpServiceSocket(service); + + printf("\tservice perms groupId %d \n", service->servPerm.gIDCnt); + for (int i = 0; i < service->servPerm.gIDCnt; i++) { + printf("\t\tservice perms groupId %u \n", service->servPerm.gIDArray[i]); + } + printf("\tservice perms capability %u \n", service->servPerm.capsCnt); + for (int i = 0; i < (int)service->servPerm.capsCnt; i++) { + printf("\t\tservice perms capability %u \n", service->servPerm.caps[i]); + } + + DumpServiceHookExecute(service->name, NULL); +} + +static void PrintBootEventHead(const char *cmd) +{ + if (strcmp(cmd, "bootevent") == 0) { + printf("\t%-20.20s\t%-50s\t%-20.20s\t%-20.20s\n", + "service-name", "bootevent-name", "fork", "ready"); + } + return; +} + +static void DumpAllExtData(const char *cmd) +{ + PrintBootEventHead(cmd); + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + if (node->data.service == NULL) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + DumpServiceHookExecute(node->name, cmd); + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } +} + +static void DumpAllServices(void) +{ + printf("Ready to dump all services: \n"); + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + if (node->data.service == NULL) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + Service *service = node->data.service; + DumpOneService(service); + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } + printf("Dump all services finished \n"); +} + +static void ProcessSandboxControlFd(uint16_t type, const char *serviceCmd) +{ + if ((type != ACTION_SANDBOX) || (serviceCmd == NULL)) { + INIT_LOGE("Invalid parameter"); + return; + } + Service *service = GetServiceByName(serviceCmd); + if (service == NULL) { + INIT_LOGE("Failed get service %s", serviceCmd); + return; + } + EnterServiceSandbox(service); + return; +} + +static void ProcessDumpServiceControlFd(uint16_t type, const char *serviceCmd) +{ + if ((type != ACTION_DUMP) || (serviceCmd == NULL)) { + return; + } + char *cmd = strrchr(serviceCmd, '#'); + if (cmd != NULL) { + cmd[0] = '\0'; + cmd++; + } + + if (strcmp(serviceCmd, "all") == 0) { + if (cmd != NULL) { + DumpAllExtData(cmd); + } else { + DumpAllServices(); + } + return; + } + if (strcmp(serviceCmd, "parameter_service") == 0) { + if (cmd != NULL && strcmp(cmd, "trigger") == 0) { + SystemDumpTriggers(0, printf); + } else { + SystemDumpParameters(0, 0, printf); + } + return; + } + if (strcmp(serviceCmd, "loop") == 0) { + DumpLoop(); + return; + } + Service *service = GetServiceByName(serviceCmd); + if (service != NULL) { + if (cmd != NULL) { + PrintBootEventHead(cmd); + DumpServiceHookExecute(serviceCmd, cmd); + } else { + DumpOneService(service); + } + } + return; +} + +static void ProcessModuleMgrControlFd(uint16_t type, const char *serviceCmd) +{ + if ((type != ACTION_MODULEMGR) || (serviceCmd == NULL)) { + return; + } + INIT_LOGE("ProcessModuleMgrControlFd argc [%s] \n", serviceCmd); + if (strcmp(serviceCmd, "list") == 0) { + InitModuleMgrDump(); + return; + } +} + +void ProcessControlFd(uint16_t type, const char *serviceCmd, const void *context) +{ + if ((type >= ACTION_MAX) || (serviceCmd == NULL)) { + INIT_LOGE("Invalid parameter:%s", serviceCmd == NULL ? "serviceCmd" : "type"); + return; + } + switch (type) { + case ACTION_SANDBOX : + ProcessSandboxControlFd(type, serviceCmd); + break; + case ACTION_DUMP : + ProcessDumpServiceControlFd(type, serviceCmd); + break; + case ACTION_MODULEMGR : + ProcessModuleMgrControlFd(type, serviceCmd); + break; + default : + INIT_LOGW("Unknown control fd type."); + break; + } +} + +void InitControlFd(void) +{ + CmdServiceInit(INIT_CONTROL_FD_SOCKET_PATH, ProcessControlFd, LE_GetDefaultLoop()); + return; +} diff --git a/services/init/standard/init_firststage.c b/services/init/standard/init_firststage.c new file mode 100755 index 0000000000000000000000000000000000000000..4f285a822cb93a64d8c75f31d67080f79f7785b9 --- /dev/null +++ b/services/init/standard/init_firststage.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2023 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 "securec.h" +#include "device.h" +#include "init.h" +#include "init_log.h" +#include "init_utils.h" +#include "init_mount.h" +#include "fs_manager/fs_manager.h" +#include "switch_root.h" +#include "ueventd.h" +#include "ueventd_socket.h" +#include "bootstage.h" + +static char **GetRequiredDevices(Fstab fstab, int *requiredNum) +{ + int num = 0; + FstabItem *item = fstab.head; + while (item != NULL) { + if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { + num++; + } +#ifdef EROFS_OVERLAY + if (item->next != NULL && strcmp(item->deviceName, item->next->deviceName) == 0) { + item = item->next->next; + } else { + item = item->next; + } +#else + item = item->next; +#endif + } + if (num == 0) { + return NULL; + } + char **devices = (char **)calloc(num, sizeof(char *)); + INIT_ERROR_CHECK(devices != NULL, return NULL, "Failed calloc err=%d", errno); + + int i = 0; + item = fstab.head; + while (item != NULL) { + if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) { + devices[i] = strdup(item->deviceName); + INIT_ERROR_CHECK(devices[i] != NULL, FreeStringVector(devices, num); return NULL, + "Failed strdup err=%d", errno); + i++; + } +#ifdef EROFS_OVERLAY + if (item->next != NULL && strcmp(item->deviceName, item->next->deviceName) == 0) { + item = item->next->next; + } else { + item = item->next; + } +#else + item = item->next; +#endif + } + *requiredNum = num; + return devices; +} + +static int StartUeventd(char **requiredDevices, int num) +{ + INIT_ERROR_CHECK(requiredDevices != NULL && num > 0, return -1, "Failed parameters"); + int ueventSockFd = UeventdSocketInit(); + if (ueventSockFd < 0) { + INIT_LOGE("Failed to create uevent socket"); + return -1; + } + RetriggerUevent(ueventSockFd, requiredDevices, num); + close(ueventSockFd); + return 0; +} + +static void MountRequiredPartitions(void) +{ + int requiredNum = 0; + Fstab *fstab = LoadRequiredFstab(); + char **devices = (fstab != NULL) ? GetRequiredDevices(*fstab, &requiredNum) : NULL; + if (devices != NULL && requiredNum > 0) { + int ret = StartUeventd(devices, requiredNum); + if (ret == 0) { + ret = MountRequriedPartitions(fstab); + } + FreeStringVector(devices, requiredNum); + devices = NULL; + ReleaseFstab(fstab); + fstab = NULL; + if (ret < 0) { + // If mount required partitions failure. + // There is no necessary to continue. + // Just abort + INIT_LOGE("[startup_failed]Mount required partitions failed; please check fstab file %d", + FSTAB_MOUNT_FAILED); +#ifndef STARTUP_INIT_TEST + abort(); +#endif + } + } + + if (fstab != NULL) { + ReleaseFstab(fstab); + fstab = NULL; + } +} + +#ifdef ASAN_DETECTOR +static void ChekcAndRunAsanInit(char * const args[]) +{ + const char* asanInitPath = "/system/asan/bin/init"; + char rebootReason[MAX_BUFFER_LEN] = {0}; + INIT_LOGI("ChekcAndRunAsan Begin"); + int ret = GetParameterFromCmdLine("reboot_reason", rebootReason, MAX_BUFFER_LEN); + if (ret) { + INIT_LOGE("Failed get reboot_reason from cmdline."); + return; + } + if (strcmp(rebootReason, "COLDBOOT") != 0) { + INIT_LOGE("rebootReason is not COLDBOOT, skip."); + return; + } + if (access(asanInitPath, X_OK) != 0) { + INIT_LOGE("%s not exit, skip.", asanInitPath); + return; + } + INIT_LOGI("redirect stdio to /dev/kmsg"); + OpenKmsg(); + + setenv("ASAN_OPTIONS", "include=/system/etc/asan.options", 1); + setenv("TSAN_OPTIONS", "include=/system/etc/asan.options", 1); + setenv("UBSAN_OPTIONS", "include=/system/etc/asan.options", 1); + setenv("HWASAN_OPTIONS", "include=/system/etc/asan.options", 1); + INIT_LOGI("Execute %s, process id %d.", asanInitPath, getpid()); + if (execv(asanInitPath, args) != 0) { + INIT_LOGE("Execute %s, execle failed! err %d.", asanInitPath, errno); + } +} +#endif +static void StartSecondStageInit(long long uptime) +{ + INIT_LOGI("Start init second stage."); + // It will panic if close stdio before execv("/bin/sh", NULL) + CloseStdio(); + + char buf[64]; + uptime = GetUptimeInMicroSeconds(NULL); + INIT_CHECK_ONLY_ELOG(snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime) >= 0, + "snprintf_s uptime to buf failed"); + // Execute init second stage + char * const args[] = { + "/bin/init", + "--second-stage", + buf, + NULL, + }; +#ifdef ASAN_DETECTOR + ChekcAndRunAsanInit(args); +#endif + if (execv("/bin/init", args) != 0) { + INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno); + exit(-1); + } +} + +static void EarlyLogInit(void) +{ + int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR, + makedev(MEM_MAJOR, DEV_KMSG_MINOR)); + if (ret == 0) { + OpenLogDevice(); + } +} + +void SystemPrepare(long long upTimeInMicroSecs) +{ + (void)signal(SIGPIPE, SIG_IGN); + + EnableInitLog(INIT_INFO); + EarlyLogInit(); + INIT_LOGI("Start init first stage."); + + CreateFsAndDeviceNode(); + + HookMgrExecute(GetBootStageHookMgr(), INIT_FIRST_STAGE, NULL, NULL); + + // Updater mode no need to mount and switch root + if (InUpdaterMode() != 0) { + return; + } + + MountRequiredPartitions(); + + StartSecondStageInit(upTimeInMicroSecs); +} diff --git a/services/init/standard/init_jobs.c b/services/init/standard/init_jobs.c new file mode 100644 index 0000000000000000000000000000000000000000..3086f6e85c7fbb2f79fe3da3f57cf9359014cd86 --- /dev/null +++ b/services/init/standard/init_jobs.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2021 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 "init_jobs_internal.h" +#include "init_group_manager.h" +#include "init_param.h" + +static int CheckJobValid(const char *jobName) +{ + // check job in group + return CheckNodeValid(NODE_TYPE_JOBS, jobName); +} + +void ParseAllJobs(const cJSON *fileRoot, const ConfigContext *context) +{ + ParseTriggerConfig(fileRoot, CheckJobValid, (void *)context); +} + +int DoJobNow(const char *jobName) +{ + DoJobExecNow(jobName); + return 0; +} diff --git a/services/init/standard/init_mount.c b/services/init/standard/init_mount.c new file mode 100644 index 0000000000000000000000000000000000000000..35ec0c409f5678ae3dbcd18b4ce5e0ec63320a42 --- /dev/null +++ b/services/init/standard/init_mount.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021-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 "init_mount.h" + +#include +#include +#include "fs_manager/fs_manager.h" +#include "init_log.h" +#include "init_utils.h" +#include "securec.h" + +int MountRequriedPartitions(const Fstab *fstab) +{ + INIT_ERROR_CHECK(fstab != NULL, return -1, "fstab is NULL"); + int rc; + INIT_LOGI("Mount required partitions"); + rc = MountAllWithFstab(fstab, 1); + return rc; +} + +Fstab *LoadRequiredFstab(void) +{ + Fstab *fstab = NULL; + fstab = LoadFstabFromCommandLine(); + if (fstab == NULL) { + INIT_LOGI("Cannot load fstab from command line, try read from fstab.required"); + const char *fstabFile = STARTUP_INIT_UT_PATH"/etc/fstab.required"; + INIT_CHECK(access(fstabFile, F_OK) == 0, fstabFile = "/system/etc/fstab.required"); + INIT_ERROR_CHECK(access(fstabFile, F_OK) == 0, return NULL, "Failed get fstab.required"); + fstab = ReadFstabFromFile(fstabFile, false); + } + if (fstab == NULL) { + INIT_LOGI("[startup_failed] LoadRequiredFstab failed %d", FSTAB_MOUNT_FAILED); + } + return fstab; +} diff --git a/services/init/standard/init_mount.h b/services/init/standard/init_mount.h new file mode 100644 index 0000000000000000000000000000000000000000..d3da2213e1bc608c4e8d44f9a0b8550f71cc0653 --- /dev/null +++ b/services/init/standard/init_mount.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021-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_MOUNT_H +#define BASE_STARTUP_INITLITE_MOUNT_H + +#include "fs_manager/fs_manager.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +Fstab *LoadRequiredFstab(void); +int MountRequriedPartitions(const Fstab *fstab); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif \ No newline at end of file diff --git a/services/init/standard/init_reboot.c b/services/init/standard/init_reboot.c new file mode 100644 index 0000000000000000000000000000000000000000..4df39d7abfd95a526aeb656a3c5ebd09d4a6501f --- /dev/null +++ b/services/init/standard/init_reboot.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 "reboot_adp.h" +#include "init_cmdexecutor.h" +#include "init_log.h" +#include "init_group_manager.h" +#include "init_modulemgr.h" + +void ExecReboot(const char *value) +{ + INIT_LOGI("ExecReboot %s", value); +#ifndef STARTUP_INIT_TEST + // install module + ModuleMgrScan("init/reboot"); + if ((value != NULL) && (strstr(value, "reboot") != NULL)) { + PluginExecCmdByName("reboot", value); + } else { + PluginExecCmdByName(value, value); + } +#endif + return; +} + +void clearMisc(void) +{ + (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); +} + +int GetBootModeFromMisc(void) +{ + char cmd[32] = {0}; // 32 cmd length + (void)GetRebootReasonFromMisc(cmd, sizeof(cmd)); + if (memcmp(cmd, "boot_charge", strlen("boot_charge")) == 0) { + return GROUP_CHARGE; + } + return 0; +} \ No newline at end of file diff --git a/services/init/standard/init_service.c b/services/init/standard/init_service.c new file mode 100644 index 0000000000000000000000000000000000000000..de77928a62013238cee4a66bc9468b1e93b52547 --- /dev/null +++ b/services/init/standard/init_service.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2020-2021 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 "init_service.h" + +#include +#include +#include +#include +#include +#include + +#include "init_group_manager.h" +#include "init.h" +#include "init_log.h" +#include "init_param.h" +#include "init_utils.h" +#include "securec.h" +#ifdef INIT_SUPPORT_ACCESS_TOKEN +#include "token_setproc.h" +#include "nativetoken_kit.h" +#endif +#include "sandbox.h" +#include "sandbox_namespace.h" +#include "service_control.h" + +#define MIN_IMPORTANT_LEVEL (-20) +#define MAX_IMPORTANT_LEVEL 19 + +static bool g_enableSandbox = false; + +static void WriteOomScoreAdjToService(Service *service) +{ + if (service == NULL) { + return; + } + if (IsOnDemandService(service)) { + char pidAdjPath[30]; + const char* content = "-900"; + int len = sprintf_s(pidAdjPath, sizeof(pidAdjPath), "/proc/%d/oom_score_adj", service->pid); + if (len <= 0) { + INIT_LOGE("Service(%s): format pidAdjPath (pid:%d) failed.", service->name, service->pid); + return; + } + int fd = open(pidAdjPath, O_RDWR); + if (fd < 0) { + INIT_LOGE("Service(%s): open path %s failed.", service->name, pidAdjPath); + return; + } + int ret = write(fd, content, strlen(content)); + if (ret < 0) { + INIT_LOGE("Service(%s): write content(%s) to path(%s) failed.", service->name, content, pidAdjPath); + } + close(fd); + } +} + +void NotifyServiceChange(Service *service, int status) +{ + INIT_LOGV("Notify service %s change from %d to %d", service->name, service->status, status); + service->status = status; + INIT_CHECK(status != SERVICE_IDLE, return); + char paramName[PARAM_NAME_LEN_MAX] = { 0 }; + int ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, + "%s.%s", STARTUP_SERVICE_CTL, service->name); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service name %s.", service->name); + char statusStr[MAX_INT_LEN] = {0}; + ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, "%d", status); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service status %s.", service->name); + SystemWriteParam(paramName, statusStr); + + // write pid + ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, + "%s.%s.pid", STARTUP_SERVICE_CTL, service->name); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid name %s.", service->name); + ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, + "%d", (service->pid == -1) ? 0 : service->pid); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid %s.", service->name); + if (status == SERVICE_STARTED) { + WriteOomScoreAdjToService(service); + } + SystemWriteParam(paramName, statusStr); +} + +int IsForbidden(const char *fieldStr) +{ + UNUSED(fieldStr); + return 0; +} + +int SetImportantValue(Service *service, const char *attrName, int value, int flag) +{ + UNUSED(attrName); + UNUSED(flag); + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr."); + if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19 + service->attribute |= SERVICE_ATTR_IMPORTANT; + service->importance = value; + } else { + INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value); + return SERVICE_FAILURE; + } + return SERVICE_SUCCESS; +} + +int ServiceExec(Service *service, const ServiceArgs *pathArgs) +{ + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr."); + INIT_LOGI("ServiceExec %s", service->name); + INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0, + return SERVICE_FAILURE, "Exec service failed! null ptr."); + + if (service->importance != 0) { + INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, + service->lastErrno = INIT_EPRIORITY; + return SERVICE_FAILURE, + "Service error %d %s, failed to set priority %d.", errno, service->name, service->importance); + } + OpenHidebug(service->name); + int isCritical = (service->attribute & SERVICE_ATTR_CRITICAL); + INIT_ERROR_CHECK(execv(pathArgs->argv[0], pathArgs->argv) == 0, + service->lastErrno = INIT_EEXEC; + return errno, "[startup_failed]failed to execv %d %d %s", isCritical, errno, service->name); + return SERVICE_SUCCESS; +} + +int SetAccessToken(const Service *service) +{ +#ifdef INIT_SUPPORT_ACCESS_TOKEN + INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null"); + return SetSelfTokenID(service->tokenId); +#else + INIT_LOGE("SetAccessToken is not supported"); + return SERVICE_FAILURE; +#endif +} + +void GetAccessToken(void) +{ + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + Service *service = node->data.service; + if (service != NULL) { + if (service->capsArgs.count == 0) { + service->capsArgs.argv = NULL; + } +#ifdef INIT_SUPPORT_ACCESS_TOKEN + const char *apl = "system_basic"; + if (service->apl != NULL) { + apl = service->apl; + } + NativeTokenInfoParams nativeTokenInfoParams = { + service->capsArgs.count, + service->permArgs.count, + service->permAclsArgs.count, + (const char **)service->capsArgs.argv, + (const char **)service->permArgs.argv, + (const char **)service->permAclsArgs.argv, + service->name, + apl, + }; + uint64_t tokenId = GetAccessTokenId(&nativeTokenInfoParams); + INIT_CHECK_ONLY_ELOG(tokenId != 0, + "gettotkenid failed, service \' %s \'", service->name); + service->tokenId = tokenId; +#else + INIT_LOGE("gettotkenid is not supported"); +#endif + } + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + } +} + +void IsEnableSandbox(void) +{ + char value[MAX_BUFFER_LEN] = {0}; + unsigned int len = MAX_BUFFER_LEN; + if (SystemReadParam("const.sandbox", value, &len) == 0) { + if (strcmp(value, "enable") == 0) { + g_enableSandbox = true; + } + } +} + +int SetServiceEnterSandbox(const Service *service, const char *execPath) +{ + if ((service->attribute & SERVICE_ATTR_WITHOUT_SANDBOX) == SERVICE_ATTR_WITHOUT_SANDBOX) { + return 0; + } + if (g_enableSandbox == false) { + return 0; + } + INIT_ERROR_CHECK(execPath != NULL, return INIT_EPARAMETER, "Service path is null."); + int ret = 0; + if (strncmp(execPath, "/system/bin/", strlen("/system/bin/")) == 0) { + ret = EnterSandbox("system"); + } else if (strncmp(execPath, "/vendor/bin/", strlen("/vendor/bin/")) == 0) { + ret = EnterSandbox("chipset"); + } + return ret; +} diff --git a/services/init/standard/init_signal_handler.c b/services/init/standard/init_signal_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..19f85f9528845385b1a3ad059493f770afd640b3 --- /dev/null +++ b/services/init/standard/init_signal_handler.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 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 "control_fd.h" +#include "init.h" +#include "init_adapter.h" +#include "init_log.h" +#include "init_param.h" +#include "init_context.h" +#include "init_service_manager.h" +#include "loop_event.h" +#include "crash_handler.h" + +static SignalHandle g_sigHandle = NULL; + +static pid_t HandleSigChild(const struct signalfd_siginfo *siginfo) +{ + int procStat = 0; + pid_t sigPID = waitpid(-1, &procStat, WNOHANG); + if (sigPID <= 0) { + return sigPID; + } + Service* service = GetServiceByPid(sigPID); + const char *serviceName = (service == NULL) ? "Unknown" : service->name; + + // check child process exit status + if (WIFSIGNALED(procStat)) { + INIT_LOGW("Child process %s(pid %d) exit with signal : %d", serviceName, sigPID, WTERMSIG(procStat)); + } else if (WIFEXITED(procStat)) { + INIT_LOGW("Child process %s(pid %d) exit with code : %d", serviceName, sigPID, WEXITSTATUS(procStat)); + if (service != NULL) { + service->lastErrno = WEXITSTATUS(procStat); + } + } + CmdServiceProcessDelClient(sigPID); + StopSubInit(sigPID); + INIT_LOGW("Service warning %s, SIGCHLD received, pid:%d uid:%d status:%d.", + serviceName, sigPID, siginfo->ssi_uid, procStat); + CheckWaitPid(sigPID); + ServiceReap(service); + return sigPID; +} + +INIT_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo) +{ + switch (siginfo->ssi_signo) { + case SIGCHLD: { + while (HandleSigChild(siginfo) > 0) { + ; + } + break; + } + case SIGTERM: { + INIT_LOGI("SigHandler, SIGTERM received."); + SystemWriteParam("startup.device.ctl", "stop"); + // exec reboot use toybox reboot cmd + ExecReboot("reboot"); + break; + } + default: + INIT_LOGI("SigHandler, unsupported signal %d.", siginfo->ssi_signo); + break; + } +} + +void SignalInit(void) +{ + if (LE_CreateSignalTask(LE_GetDefaultLoop(), &g_sigHandle, ProcessSignal) == 0) { + if (LE_AddSignal(LE_GetDefaultLoop(), g_sigHandle, SIGCHLD) != 0) { + INIT_LOGW("start SIGCHLD handler failed"); + } + if (LE_AddSignal(LE_GetDefaultLoop(), g_sigHandle, SIGTERM) != 0) { + INIT_LOGW("start SIGTERM handler failed"); + } + } + InstallLocalSignalHandler(); +} diff --git a/services/init/standard/main_early.c b/services/init/standard/main_early.c new file mode 100755 index 0000000000000000000000000000000000000000..a9f3739c3882df21dd4230aaf616f36ab60285b8 --- /dev/null +++ b/services/init/standard/main_early.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 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 "init.h" +#include "init_utils.h" + +int main(int argc, char * const argv[]) +{ + long long upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL); + + SystemPrepare(upTimeInMicroSecs); + return 0; +} diff --git a/services/init/standard/system_call_wrap.c b/services/init/standard/system_call_wrap.c new file mode 100644 index 0000000000000000000000000000000000000000..9e882c2d1095d517286741a1f58714db46a68040 --- /dev/null +++ b/services/init/standard/system_call_wrap.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2024-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 +#include +#include +#include +#include + +#include "init_log.h" +#include "bootevent.h" + +uid_t __real_getuid(); +uid_t __wrap_getuid() +{ + if (!IsBootCompleted()) { + return __real_getuid(); + } + + INIT_LOGI("getuid begin"); + uid_t uid = __real_getuid(); + INIT_LOGI("getuid end"); + return uid; +} + +int __real_mkdir(const char *pathname, mode_t mode); +int __wrap_mkdir(const char *pathname, mode_t mode) +{ + if (!IsBootCompleted()) { + return __real_mkdir(pathname, mode); + } + + INIT_LOGI("mkdir begin"); + int ret = __real_mkdir(pathname, mode); + INIT_LOGI("mkdir end"); + return ret; +} + +int __real_rmdir(const char *pathname); +int __wrap_rmdir(const char *pathname) +{ + if (!IsBootCompleted()) { + return __real_rmdir(pathname); + } + + INIT_LOGI("rmdir begin"); + int ret = __real_rmdir(pathname); + INIT_LOGI("rmdir end"); + return ret; +} + +pid_t __real_fork(void); +pid_t __wrap_fork(void) +{ + if (!IsBootCompleted()) { + return __real_fork(); + } + + INIT_LOGI("fork begin"); + pid_t pid = __real_fork(); + INIT_LOGI("fork end"); + return pid; +} + +int __real_mount(const char *source, const char *target, + const char *filesystemtype, unsigned long mountflags, + const void *data); +int __wrap_mount(const char *source, const char *target, + const char *filesystemtype, unsigned long mountflags, + const void *data) +{ + if (!IsBootCompleted()) { + return __real_mount(source, target, filesystemtype, mountflags, data); + } + + INIT_LOGI("mount begin"); + int ret = __real_mount(source, target, filesystemtype, mountflags, data); + INIT_LOGI("mount end"); + return ret; +} + +int __real_chown(const char *pathname, uid_t owner, gid_t group); +int __wrap_chown(const char *pathname, uid_t owner, gid_t group) +{ + if (!IsBootCompleted()) { + return __real_chown(pathname, owner, group); + } + + INIT_LOGI("chown begin"); + int ret = __real_chown(pathname, owner, group); + INIT_LOGI("chown end"); + return ret; +} + +int __real_chmod(const char *filename, int pmode); +int __wrap_chmod(const char *filename, int pmode) +{ + if (!IsBootCompleted()) { + return __real_chmod(filename, pmode); + } + + INIT_LOGI("chmod begin"); + int ret = __real_chmod(filename, pmode); + INIT_LOGI("chmod end"); + return ret; +} + +int __real_kill(pid_t pid, int sig); +int __wrap_kill(pid_t pid, int sig) +{ + if (!IsBootCompleted()) { + return __real_kill(pid, sig); + } + + INIT_LOGI("kill begin"); + int ret = __real_kill(pid, sig); + INIT_LOGI("kill end"); + return ret; +} + +FILE *__real_fopen(const char *filename, const char *mode); +FILE *__wrap_fopen(const char *filename, const char *mode) +{ + if (!IsBootCompleted()) { + return __real_fopen(filename, mode); + } + + INIT_LOGI("fopen begin"); + FILE *file = __real_fopen(filename, mode); + INIT_LOGI("fopen end"); + return file; +} \ No newline at end of file diff --git a/services/log/BUILD.gn b/services/log/BUILD.gn index 0603b625dc2e5602d97111f437712344ab40bf33..fe249792e2395c549a6dde4a7aab5c16180a0079 100644 --- a/services/log/BUILD.gn +++ b/services/log/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-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 @@ -10,19 +10,54 @@ # 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. +base_sources = [ "init_log.c" ] + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + ] +} + if (defined(ohos_lite)) { static_library("init_log") { - sources = [ "init_log.c" ] - public_deps = [ "//third_party/bounds_checking_function:libsec_static" ] + sources = base_sources + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + ] + public_configs = [ ":exported_header_files" ] + + if (ohos_kernel_type == "linux") { + defines += [ "INIT_DMESG" ] + } + if (ohos_kernel_type == "liteos_m") { + defines += [ "__LITEOS_M__" ] + } include_dirs = [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits" ] - deps = [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared" ] + external_deps = [ "bounds_checking_function:libsec_shared" ] } } else { import("//build/ohos.gni") ohos_static_library("init_log") { - sources = [ "init_log.c" ] - deps = [ "//third_party/bounds_checking_function:libsec_static" ] - part_name = "startup" + sources = base_sources + defines = [ "INIT_DMESG" ] + public_configs = [ ":exported_header_files" ] + + external_deps = [ "bounds_checking_function:libsec_static" ] + part_name = "init" + subsystem_name = "startup" + } + + ohos_static_library("agent_log") { + sources = base_sources + defines = [ "INIT_AGENT" ] + public_configs = [ ":exported_header_files" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog_base" ] + part_name = "init" subsystem_name = "startup" } } diff --git a/services/log/init_commlog.c b/services/log/init_commlog.c new file mode 100644 index 0000000000000000000000000000000000000000..f6993c214140421fc42faa584ebe2bd5ad08c611 --- /dev/null +++ b/services/log/init_commlog.c @@ -0,0 +1,32 @@ +/* + * 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 "init_log.h" + +static InitCommLog g_initCommLog = NULL; +INIT_LOCAL_API void SetInitCommLog(InitCommLog logFunc) +{ + g_initCommLog = logFunc; +} + +INIT_PUBLIC_API void StartupLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...) +{ + if (g_initCommLog != NULL) { + va_list vargs; + va_start(vargs, fmt); + g_initCommLog(logLevel, domain, tag, fmt, vargs); + va_end(vargs); + } +} \ No newline at end of file diff --git a/services/log/init_log.c b/services/log/init_log.c index 5c5719d9cb27e1bc4ea4c886f8b5073d0bd16f9a..ede47e114bfc6d3f95cf0a8e8fb6f4645d5561d7 100644 --- a/services/log/init_log.c +++ b/services/log/init_log.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -14,87 +14,66 @@ */ #include "init_log.h" + #include #include #include #include #include -#include "securec.h" +#include -#define UNUSED(x) \ - do { \ - (void)(x) \ - } while (0) +#include "init_utils.h" +#include "securec.h" +#ifdef OHOS_LITE +#ifndef INIT_LOG_INIT +#define INIT_LOG_INIT LOG_CORE +#endif +#include "hilog/log.h" +#endif +#ifdef INIT_AGENT +#include "hilog_base/log_base.h" +#endif -#define MAX_LOG_SIZE 1024 +#define DEF_LOG_SIZE 128 #define BASE_YEAR 1900 -#define UNLIKELY(x) __builtin_expect(!!(x), 0) static InitLogLevel g_logLevel = INIT_INFO; -static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; - -void SetLogLevel(InitLogLevel logLevel) -{ - g_logLevel = logLevel; -} - -#ifdef OHOS_LITE -static LogLevel g_hiLogLevel = LOG_INFO; - -void SetHiLogLevel(LogLevel logLevel) -{ - g_hiLogLevel = logLevel; -} - -void InitToHiLog(LogLevel logLevel, const char *fmt, ...) +#ifdef INIT_FILE +static void LogToFile(const char *logFile, const char *tag, const char *info) { - if (logLevel < g_hiLogLevel) { + struct timespec curr = {0}; + if (clock_gettime(CLOCK_REALTIME, &curr) != 0) { return; } - - va_list list; - va_start(list, fmt); - char tmpFmt[MAX_LOG_SIZE]; - if (vsnprintf_s(tmpFmt, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, fmt, list) == -1) { - va_end(list); - return; + FILE *outfile = NULL; + INIT_CHECK_ONLY_RETURN((outfile = fopen(logFile, "a+")) != NULL); + struct tm t; + char dateTime[80] = {"00-00-00 00:00:00"}; // 80 data time + if (localtime_r(&curr.tv_sec, &t) != NULL) { + strftime(dateTime, sizeof(dateTime), "%Y-%m-%d %H:%M:%S", &t); } - (void)HiLogPrint(LOG_CORE, logLevel, LOG_DOMAIN, INIT_LOG_TAG, "%{public}s", tmpFmt); - va_end(list); + (void)fprintf(outfile, "[%s.%ld][pid=%d %d][%s]%s \n", dateTime, curr.tv_nsec, getpid(), gettid(), tag, info); + (void)fflush(outfile); + (void)fclose(outfile); return; } #endif +#ifdef INIT_DMESG static int g_fd = -1; -void OpenLogDevice(void) +INIT_LOCAL_API void OpenLogDevice(void) { - int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IRGRP); + int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (fd >= 0) { g_fd = fd; } return; } -void EnableDevKmsg(void) -{ - /* printk_devkmsg default value is ratelimit, We need to set "on" and remove the restrictions */ - int fd = open("/proc/sys/kernel/printk_devkmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IRGRP); - if (fd < 0) { - return; - } - char *kmsgStatus = "on"; - write(fd, kmsgStatus, strlen(kmsgStatus) + 1); - close(fd); - fd = -1; - return; -} - -void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *kLevel, - const char *fmt, ...) +void LogToDmesg(InitLogLevel logLevel, const char *tag, const char *info) { - if (logLevel < g_logLevel) { - return; - } + static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; + static const char *LOG_KLEVEL_STR[] = { "<7>", "<6>", "<4>", "<3>", "<3>" }; if (UNLIKELY(g_fd < 0)) { OpenLogDevice(); @@ -102,27 +81,76 @@ void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char * return; } } - va_list vargs; - va_start(vargs, fmt); - char tmpFmt[MAX_LOG_SIZE]; - if (vsnprintf_s(tmpFmt, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, fmt, vargs) == -1) { - close(g_fd); - g_fd = -1; + char logInfo[DEF_LOG_SIZE + DEF_LOG_SIZE] = {0}; + if (snprintf_s(logInfo, sizeof(logInfo), sizeof(logInfo) - 1, "%s[pid=%d][%s][%s]%s", + LOG_KLEVEL_STR[logLevel], getpid(), tag, LOG_LEVEL_STR[logLevel], info) == -1) { + logInfo[sizeof(logInfo) - 2] = '\n'; // 2 add \n to tail + logInfo[sizeof(logInfo) - 1] = '\0'; return; } + if (write(g_fd, logInfo, strlen(logInfo)) < 0) { + printf("%s\n", logInfo); + } + return; +} + +INIT_PUBLIC_API int GetKmsgFd() +{ + return g_fd; +} +#endif + +static void PrintLog(InitLogLevel logLevel, unsigned int domain, const char *tag, const char *logInfo) +{ +#if defined(__LITEOS_A__) || defined(__LINUX__) + static const LogLevel LOG_LEVEL[] = { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; + (void)HiLogPrint(INIT_LOG_INIT, LOG_LEVEL[logLevel], domain, tag, "%s", logInfo); +#endif +#ifdef INIT_DMESG + LogToDmesg(logLevel, tag, logInfo); +#endif +#ifdef INIT_AGENT + static const LogLevel LOG_LEVEL[] = { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; + HiLogBasePrint(LOG_CORE, LOG_LEVEL[logLevel], domain, tag, "%{public}s", logInfo); +#endif +#ifdef INIT_FILE + LogToFile(INIT_LOG_PATH"begetctl.log", tag, logInfo); +#endif +} - char logInfo[MAX_LOG_SIZE]; - if (snprintf_s(logInfo, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, "%s[pid=%d][%s:%d][%s][%s] %s", - kLevel, getpid(), fileName, line, INIT_LOG_TAG, LOG_LEVEL_STR[logLevel], tmpFmt) == -1) { - close(g_fd); - g_fd = -1; +static void PrintLogFmt(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs) +{ + char tmpFmt[DEF_LOG_SIZE] = {0}; + if (vsnprintf_s(tmpFmt, sizeof(tmpFmt), sizeof(tmpFmt) - 1, fmt, vargs) == -1) { + tmpFmt[sizeof(tmpFmt) - 2] = '\n'; // 2 add \n to tail + tmpFmt[sizeof(tmpFmt) - 1] = '\0'; + } + PrintLog((InitLogLevel)logLevel, domain, tag, tmpFmt); +} + +INIT_LOCAL_API void InitLog(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs) +{ + if ((int)g_logLevel > logLevel) { return; } - va_end(vargs); + PrintLogFmt((InitLogLevel)logLevel, domain, tag, fmt, vargs); +} - if (write(g_fd, logInfo, strlen(logInfo)) < 0) { - close(g_fd); - g_fd = -1; +INIT_PUBLIC_API void SetInitLogLevel(InitLogLevel level) +{ + if (level <= INIT_FATAL) { + g_logLevel = level; } return; } + +INIT_LOCAL_API void EnableInitLog(InitLogLevel level) +{ + g_logLevel = level; + SetInitCommLog(InitLog); +} + +INIT_PUBLIC_API InitLogLevel GetInitLogLevel() +{ + return g_logLevel; +} diff --git a/services/log/init_log.h b/services/log/init_log.h index 37817237a777d7745bc24c6a8971a5c28761e4ae..9f0ef0453002721752442feca884a7d1c2d41b86 100644 --- a/services/log/init_log.h +++ b/services/log/init_log.h @@ -20,64 +20,65 @@ #include #include +#include "beget_ext.h" + #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -typedef enum InitLogLevel { - INIT_DEBUG = 0, - INIT_INFO, - INIT_WARN, - INIT_ERROR, - INIT_FATAL -} InitLogLevel; - -#ifdef LABEL -#define INIT_LOG_TAG LABEL -#endif - #ifndef INIT_LOG_TAG #define INIT_LOG_TAG "Init" #endif -#ifdef OHOS_LITE -#include "hilog/log.h" - -#undef LOG_DOMAIN -#define LOG_DOMAIN 0xD000719 - -#define INIT_LOGD(fmt, ...) InitToHiLog(LOG_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) -#define INIT_LOGI(fmt, ...) InitToHiLog(LOG_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) -#define INIT_LOGW(fmt, ...) InitToHiLog(LOG_WARN, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) -#define INIT_LOGE(fmt, ...) InitToHiLog(LOG_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) -#define INIT_LOGF(fmt, ...) InitToHiLog(LOG_FATAL, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) +#ifndef INIT_LOG_DOMAIN +#define INIT_LOG_DOMAIN (BASE_DOMAIN + 1) +#endif -#define STARTUP_LOGD(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) -#define STARTUP_LOGI(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) -#define STARTUP_LOGE(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__) +typedef void (*InitCommLog)(int logLevel, uint32_t domain, const char *tag, const char *fmt, va_list vargs); -void InitToHiLog(LogLevel logLevel, const char *fmt, ...); -void SetHiLogLevel(LogLevel logLevel); +INIT_LOCAL_API void OpenLogDevice(void); +INIT_LOCAL_API void InitLog(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs); +INIT_LOCAL_API void SetInitCommLog(InitCommLog logFunc); +INIT_PUBLIC_API int GetKmsgFd(); +#if defined(INIT_NO_LOG) || defined(PARAM_BASE) +#define EnableInitLog(level) ((void)level) +#define INIT_LOGV(fmt, ...) +#define INIT_LOGI(fmt, ...) +#define INIT_LOGW(fmt, ...) +#define INIT_LOGE(fmt, ...) +#define INIT_LOGF(fmt, ...) +#else +#ifdef __LITEOS_M__ +#define INIT_LOGV(fmt, ...) \ + HILOG_DEBUG(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define INIT_LOGI(fmt, ...) \ + HILOG_INFO(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define INIT_LOGW(fmt, ...) \ + HILOG_WARN(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define INIT_LOGE(fmt, ...) \ + HILOG_ERROR(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) +#define INIT_LOGF(fmt, ...) \ + HILOG_FATAL(HILOG_MODULE_INIT, fmt, ##__VA_ARGS__) #else -#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__)) -#define INIT_LOGD(fmt, ...) InitLog(INIT_DEBUG, (FILE_NAME), (__LINE__), "<7>", fmt"\n", ##__VA_ARGS__) -#define INIT_LOGI(fmt, ...) InitLog(INIT_INFO, (FILE_NAME), (__LINE__), "<6>", fmt"\n", ##__VA_ARGS__) -#define INIT_LOGW(fmt, ...) InitLog(INIT_WARN, (FILE_NAME), (__LINE__), "<4>", fmt"\n", ##__VA_ARGS__) -#define INIT_LOGE(fmt, ...) InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "<3>", fmt"\n", ##__VA_ARGS__) -#define INIT_LOGF(fmt, ...) InitLog(INIT_FATAL, (FILE_NAME), (__LINE__), "<3>", fmt"\n", ##__VA_ARGS__) - -#define STARTUP_LOGD(LABEL, fmt, ...) InitLog(INIT_DEBUG, (FILE_NAME), (__LINE__), "<7>", fmt "\n", ##__VA_ARGS__) -#define STARTUP_LOGI(LABEL, fmt, ...) InitLog(INIT_INFO, (FILE_NAME), (__LINE__), "<6>", fmt "\n", ##__VA_ARGS__) -#define STARTUP_LOGE(LABEL, fmt, ...) InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "<3>", fmt "\n", ##__VA_ARGS__) - - -void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *kLevel, const char *fmt, ...); -void SetLogLevel(InitLogLevel logLevel); -void OpenLogDevice(void); -void EnableDevKmsg(void); +INIT_LOCAL_API void EnableInitLog(InitLogLevel level); +#define INIT_LOGV(fmt, ...) \ + StartupLog(INIT_DEBUG, INIT_LOG_DOMAIN, INIT_LOG_TAG, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define INIT_LOGI(fmt, ...) \ + StartupLog(INIT_INFO, INIT_LOG_DOMAIN, INIT_LOG_TAG, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define INIT_LOGW(fmt, ...) \ + StartupLog(INIT_WARN, INIT_LOG_DOMAIN, INIT_LOG_TAG, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define INIT_LOGE(fmt, ...) \ + StartupLog(INIT_ERROR, INIT_LOG_DOMAIN, INIT_LOG_TAG, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define INIT_LOGF(fmt, ...) \ + StartupLog(INIT_FATAL, INIT_LOG_DOMAIN, INIT_LOG_TAG, "[%s:%d]" fmt, (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#endif +#endif + +#ifndef UNLIKELY +#define UNLIKELY(x) __builtin_expect(!!(x), 0) #endif #define INIT_ERROR_CHECK(ret, statement, format, ...) \ @@ -96,6 +97,14 @@ void EnableDevKmsg(void); } \ } while (0) +#define INIT_WARNING_CHECK(ret, statement, format, ...) \ + do { \ + if (!(ret)) { \ + INIT_LOGW(format, ##__VA_ARGS__); \ + statement; \ + } \ + } while (0) + #define INIT_CHECK(ret, statement) \ do { \ if (!(ret)) { \ @@ -117,6 +126,13 @@ void EnableDevKmsg(void); } \ } while (0) +#define INIT_CHECK_ONLY_ELOG(ret, format, ...) \ + do { \ + if (!(ret)) { \ + INIT_LOGE(format, ##__VA_ARGS__); \ + } \ + } while (0) + #ifdef __cplusplus #if __cplusplus } diff --git a/services/loopevent/BUILD.gn b/services/loopevent/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b2f2671100194682c17f1440ee4eb1c68e68b589 --- /dev/null +++ b/services/loopevent/BUILD.gn @@ -0,0 +1,77 @@ +# Copyright (c) 2021-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. + +common_sources = [ + "idle/le_idle.c", + "loop/le_epoll.c", + "loop/le_loop.c", + "signal/le_signal.c", + "socket/le_socket.c", + "task/le_asynctask.c", + "task/le_streamtask.c", + "task/le_task.c", + "task/le_watchtask.c", + "timer/le_timer.c", + "utils/le_utils.c", +] + +common_include = [ + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + "include", + "loop", + "socket", + "task", + "timer", + "utils", + "signal", + "idle", +] + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ "//base/startup/init/services/loopevent/include" ] +} + +if (defined(ohos_lite)) { + static_library("loopevent") { + sources = common_sources + cflags = [ "-fPIC" ] + include_dirs = common_include + external_deps = [ "bounds_checking_function:libsec_shared" ] + defines = [ "_GNU_SOURCE" ] + public_configs = [ ":exported_header_files" ] + } +} else { + import("//build/ohos.gni") + + ohos_static_library("loopevent") { + sources = common_sources + public_configs = [ ":exported_header_files" ] + include_dirs = common_include + external_deps = [ "bounds_checking_function:libsec_static" ] + defines = [ "_GNU_SOURCE" ] + part_name = "init" + subsystem_name = "startup" + } +} + +group("loopeventgroup") { + if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux") { + deps = [ ":loopevent" ] + } + } else { + deps = [ ":loopevent" ] + } +} diff --git a/services/loopevent/idle/le_idle.c b/services/loopevent/idle/le_idle.c new file mode 100755 index 0000000000000000000000000000000000000000..b230bb2ebc799f4eea5deb12aeeb80527a918c78 --- /dev/null +++ b/services/loopevent/idle/le_idle.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 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 "le_idle.h" + +#include +#include +#include + +#include "le_loop.h" +#include "le_task.h" +#include "loop_event.h" + +/** + * @brief Add a new idle handler + * + * @param loopHandle the running loop this idle will be attached + * @param idle optional output parameter for the created idle handler + * @param processIdle the idle handler function + * @param context optional idle handler context + * @param repeat if the idle function will be repeated forevent (non zero) or once (zero) + * @return status code, 0 means succeed + */ +LE_STATUS LE_AddIdle(const LoopHandle loopHandle, IdleHandle *idle, + LE_ProcessIdle processIdle, void *context, int repeat) +{ + LE_CHECK(loopHandle != NULL && processIdle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + IdleTask *task = (IdleTask *)calloc(1, sizeof(IdleTask)); + LE_CHECK(task != NULL, + return LE_NO_MEMORY, "Failed to create task"); + + task->loop = (EventLoop *)loopHandle; + task->processIdle = processIdle; + task->context = context; + task->repeat = repeat; + if (idle != NULL) { + *idle = (IdleHandle)task; + } + + // Add to list + OH_ListAddTail(&(task->loop->idleList), &(task->node)); + return LE_SUCCESS; +} + +/** + * @brief Delete an idle handler + * + * @param idle idle handler + * @return None + */ +void LE_DelIdle(IdleHandle idle) +{ + LE_CHECK(idle != NULL, return, "Invalid parameters"); + IdleTask *task = (IdleTask *)idle; + OH_ListRemove(&(task->node)); + free((void *)task); +} + +/** + * @brief Execute an function once in the next loop + * + * @param loopHandle the running loop this idle will be attached + * @param idle the function to be executed + * @param context optional idle handler context + * @return status code, 0 means succeed + */ +int LE_DelayProc(const LoopHandle loopHandle, LE_ProcessIdle idle, void *context) +{ + return LE_AddIdle(loopHandle, NULL, idle, context, 0); +} + +static int IdleListTraversalProc(ListNode *node, void *data) +{ + IdleTask *task = (IdleTask *)node; + + // Do idle proc + task->processIdle(task, task->context); + + if (task->repeat) { + return 0; + } + + // Remove if no need to repeat + LE_DelIdle((IdleHandle)task); + return 0; +} + +/** + * @brief Execute all idle functions + * + * @param loopHandle the running loop + * @return None + */ +void LE_RunIdle(const LoopHandle loopHandle) +{ + if (loopHandle == NULL) { + return; + } + EventLoop *loop = (EventLoop *)loopHandle; + + OH_ListTraversal(&(loop->idleList), NULL, IdleListTraversalProc, 0); +} diff --git a/services/loopevent/idle/le_idle.h b/services/loopevent/idle/le_idle.h new file mode 100755 index 0000000000000000000000000000000000000000..99a1442de6e608b0d6b20da53824f83e1ffa414f --- /dev/null +++ b/services/loopevent/idle/le_idle.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 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 LOOP_IDLE_H +#define LOOP_IDLE_H +#include "le_task.h" +#include "le_loop.h" +#include "loop_event.h" + +/** + * @brief Idle Task Structure + */ +typedef struct { + /* List Node */ + ListNode node; + + /* The loop handler this idle task belongs to */ + EventLoop *loop; + + /* The actual function to be executed */ + LE_ProcessIdle processIdle; + + /* The function context pointer */ + void *context; + + /* This task will be repeat forever or just once */ + int repeat; +} IdleTask; + +/** + * @brief Execute all idle functions + * + * @param loopHandle the running loop + * @return None + */ +void LE_RunIdle(const LoopHandle loopHandle); + +#endif diff --git a/services/loopevent/loop/le_epoll.c b/services/loopevent/loop/le_epoll.c new file mode 100644 index 0000000000000000000000000000000000000000..964440c94a2632e46c58dfde1f267fec44765ec9 --- /dev/null +++ b/services/loopevent/loop/le_epoll.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021 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 "le_epoll.h" +#include "le_idle.h" +#include "le_timer.h" + +#define MAX_TIMEOUT_MILLISECONDS (20 * 1000) // 20s + +static int IsValid_(const EventEpoll *loop) +{ + return loop->epollFd >= 0; +} + +static void GetEpollEvent_(int fd, int op, struct epoll_event *event) +{ + event->data.fd = fd; + if (LE_TEST_FLAGS(op, EVENT_READ)) { + event->events |= EPOLLIN; + } + if (LE_TEST_FLAGS(op, EVENT_WRITE)) { + event->events |= EPOLLOUT; + } +} + +static LE_STATUS Close_(const EventLoop *loop) +{ + LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); + EventEpoll *epoll = (EventEpoll *)loop; + LE_LOGV("Close_ epollFd %d", epoll->epollFd); + close(epoll->epollFd); + free(epoll); + return LE_SUCCESS; +} + +static LE_STATUS AddEvent_(const EventLoop *loop, const BaseTask *task, int op) +{ + LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); + EventEpoll *epoll = (EventEpoll *)loop; + + int ret = LE_FAILURE; + struct epoll_event event = {}; + int fd = GetSocketFd((const TaskHandle)task); + GetEpollEvent_(fd, op, &event); + if (IsValid_(epoll) && fd >= 0) { + ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_ADD, fd, &event); + } + LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add epoll_ctl %d ret %d", fd, errno); + return LE_SUCCESS; +} + +static LE_STATUS ModEvent_(const EventLoop *loop, const BaseTask *task, int op) +{ + LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); + EventEpoll *epoll = (EventEpoll *)loop; + + int ret = LE_FAILURE; + struct epoll_event event = {}; + int fd = GetSocketFd((const TaskHandle)task); + GetEpollEvent_(fd, op, &event); + if (IsValid_(epoll) && fd >= 0) { + ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_MOD, fd, &event); + } + LE_CHECK(ret == 0, return LE_FAILURE, "Failed to mod epoll_ctl %d ret %d", fd, errno); + return LE_SUCCESS; +} + +static LE_STATUS DelEvent_(const EventLoop *loop, int fd, int op) +{ + LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); + EventEpoll *epoll = (EventEpoll *)loop; + + int ret = LE_FAILURE; + struct epoll_event event = {}; + GetEpollEvent_(fd, op, &event); + if (IsValid_(epoll) && fd >= 0) { + ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_DEL, fd, &event); + } + LE_CHECK(ret == 0, return LE_FAILURE, "Failed to del epoll_ctl %d ret %d", fd, errno); + return LE_SUCCESS; +} + +static LE_STATUS RunLoop_(const EventLoop *loop) +{ + LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); + + EventEpoll *epoll = (EventEpoll *)loop; + if (!IsValid_(epoll)) { + return LE_FAILURE; + } + + while (1) { + LE_RunIdle((LoopHandle)&(epoll->loop)); + + uint64_t minTimePeriod = GetMinTimeoutPeriod(loop); + int timeout = 0; + if (minTimePeriod == 0) { + timeout = -1; + } else if (GetCurrentTimespec(0) >= minTimePeriod) { + timeout = 0; + } else { + timeout = (int)(minTimePeriod - GetCurrentTimespec(0)); + } + if (timeout < 0 || timeout > MAX_TIMEOUT_MILLISECONDS) { + LE_LOGW("timeout:%d", timeout); + } + + int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, timeout); + if (number > 1) { + LE_LOGI("RunLoop_ epoll_wait with number %d", number); + } + for (int index = 0; index < number; index++) { + if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) { + ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_READ); + } + if ((epoll->waitEvents[index].events & EPOLLOUT) == EPOLLOUT) { + ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_WRITE); + } + if (epoll->waitEvents[index].events & (EPOLLERR | EPOLLHUP)) { + LE_LOGW("RunLoop_ fd:%d, error:%d", epoll->waitEvents[index].data.fd, errno); + ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_ERROR); + } + } + if (number > 1) { + LE_LOGI("RunLoop_ epoll_wait finish"); + } + CheckTimeoutOfTimer((EventLoop *)loop, GetCurrentTimespec(0)); + + if (loop->stop) { + break; + } + } + return LE_SUCCESS; +} + +LE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout) +{ + LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); + EventEpoll *epoll = (EventEpoll *)malloc(sizeof(EventEpoll) + sizeof(struct epoll_event) * (maxevents)); + LE_CHECK(epoll != NULL, return LE_FAILURE, "Failed to alloc memory for epoll"); + epoll->epollFd = epoll_create(maxevents); + LE_CHECK(epoll->epollFd >= 0, free(epoll); + return LE_FAILURE, "Failed to create epoll"); + + *loop = (EventLoop *)epoll; + epoll->loop.maxevents = maxevents; + epoll->loop.timeout = timeout; + epoll->loop.close = Close_; + epoll->loop.runLoop = RunLoop_; + epoll->loop.delEvent = DelEvent_; + epoll->loop.addEvent = AddEvent_; + epoll->loop.modEvent = ModEvent_; + return LE_SUCCESS; +} diff --git a/services/loopevent/loop/le_epoll.h b/services/loopevent/loop/le_epoll.h new file mode 100644 index 0000000000000000000000000000000000000000..383d95042f573e258c90d9515ed58f1d2916cd54 --- /dev/null +++ b/services/loopevent/loop/le_epoll.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 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 EVENT_EPOLL_H +#define EVENT_EPOLL_H +#include +#include "le_utils.h" + +#include "le_loop.h" + +typedef struct { + EventLoop loop; + int epollFd; + struct epoll_event waitEvents[0]; +} EventEpoll; + +LE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout); + +#endif \ No newline at end of file diff --git a/services/loopevent/loop/le_loop.c b/services/loopevent/loop/le_loop.c new file mode 100644 index 0000000000000000000000000000000000000000..ec597b1f6df568c7f8700e520262d31f4b221167 --- /dev/null +++ b/services/loopevent/loop/le_loop.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021 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 "le_loop.h" +#include "le_epoll.h" + + +static int TaskNodeCompare(const HashNode *node1, const HashNode *node2) +{ + BaseTask *task1 = HASHMAP_ENTRY(node1, BaseTask, hashNode); + BaseTask *task2 = HASHMAP_ENTRY(node2, BaseTask, hashNode); + return (int)task1->taskId.fd - (int)task2->taskId.fd; +} + +static int TaskKeyCompare(const HashNode *node, const void *key) +{ + BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode); + TaskId *taskId = (TaskId *)key; + return (int)task->taskId.fd - taskId->taskId.fd; +} + +static int TaskGetNodeHasCode(const HashNode *node) +{ + BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode); + return task->taskId.fd; +} + +static int TaskGetKeyHasCode(const void *key) +{ + TaskId *taskId = (TaskId *)key; + return taskId->taskId.fd; +} + +static void TaskNodeFree(const HashNode *node, void *context) +{ + BaseTask *task = HASHMAP_ENTRY(node, BaseTask, hashNode); + CloseTask((const LoopHandle)context, task); + free(task); +} + +static LE_STATUS CreateLoop_(EventLoop **loop, uint32_t maxevents, uint32_t timeout) +{ +#ifdef LOOP_EVENT_USE_EPOLL + LE_STATUS ret = CreateEpollLoop(loop, maxevents, timeout); + LE_CHECK(ret == LE_SUCCESS, return ret, "Failed to create epoll loop"); +#endif + (*loop)->maxevents = maxevents; + (*loop)->timeout = timeout; + (*loop)->stop = 0; + LoopMutexInit(&(*loop)->mutex); + + OH_ListInit(&((*loop)->idleList)); + + HashInfo info = { + TaskNodeCompare, + TaskKeyCompare, + TaskGetNodeHasCode, + TaskGetKeyHasCode, + TaskNodeFree, + 128 + }; + ret = OH_HashMapCreate(&(*loop)->taskMap, &info); + LE_CHECK(ret == LE_SUCCESS, return ret, "failed to create hash map loop"); + OH_ListInit(&((*loop)->timerList)); + return ret; +} + +LE_STATUS CloseLoop(EventLoop *loop) +{ + if (!loop->stop) { + return LE_SUCCESS; + } + OH_HashMapDestory(loop->taskMap, loop); + if (loop->close) { + loop->close(loop); + } + return LE_SUCCESS; +} + +LE_STATUS ProcessEvent(const EventLoop *loop, int fd, uint32_t oper) +{ + BaseTask *task = GetTaskByFd((EventLoop *)loop, fd); + if (task != NULL) { + task->handleEvent((LoopHandle)loop, (TaskHandle)task, oper); + } else { + LE_LOGE("ProcessEvent with invalid fd %d", fd); + } + return LE_SUCCESS; +} + +LE_STATUS AddTask(EventLoop *loop, BaseTask *task) +{ + LoopMutexLock(&loop->mutex); + int ret = OH_HashMapAdd(loop->taskMap, &task->hashNode); + LoopMutexUnlock(&loop->mutex); +#ifndef STARTUP_INIT_TEST + return ret; +#else + ret = 0; + return ret; +#endif +} + +BaseTask *GetTaskByFd(EventLoop *loop, int fd) +{ + BaseTask *task = NULL; + LoopMutexLock(&loop->mutex); + TaskId id = {0, {fd}}; + HashNode *node = OH_HashMapGet(loop->taskMap, &id); + if (node != NULL) { + task = HASHMAP_ENTRY(node, BaseTask, hashNode); + } + LoopMutexUnlock(&loop->mutex); + return task; +} + +void DelTask(EventLoop *loop, BaseTask *task) +{ + loop->delEvent(loop, task->taskId.fd, + EVENT_READ | EVENT_WRITE | EVENT_ERROR | EVENT_FREE | EVENT_TIMEOUT | EVENT_SIGNAL); + LoopMutexLock(&loop->mutex); + OH_HashMapRemove(loop->taskMap, (TaskId *)task); + LoopMutexUnlock(&loop->mutex); + return; +} + +static EventLoop *g_defaultLoop = NULL; +LoopHandle LE_GetDefaultLoop(void) +{ + if (g_defaultLoop == NULL) { + LE_CreateLoop((LoopHandle *)&g_defaultLoop); + } + return (LoopHandle)g_defaultLoop; +} + +LE_STATUS LE_CreateLoop(LoopHandle *handle) +{ + EventLoop *loop = NULL; + LE_STATUS ret = CreateLoop_(&loop, LOOP_MAX_SOCKET, DEFAULT_TIMEOUT); + *handle = (LoopHandle)loop; + return ret; +} + +void LE_RunLoop(const LoopHandle handle) +{ + LE_CHECK(handle != NULL, return, "Invalid handle"); + EventLoop *loop = (EventLoop *)handle; + loop->runLoop(loop); +} + +void LE_CloseLoop(const LoopHandle loopHandle) +{ + LE_CHECK(loopHandle != NULL, return, "Invalid handle"); + CloseLoop((EventLoop *)loopHandle); + if ((LoopHandle)g_defaultLoop == loopHandle) { + g_defaultLoop = NULL; + } +} + +void LE_StopLoop(const LoopHandle handle) +{ + LE_CHECK(handle != NULL, return, "Invalid handle"); + EventLoop *loop = (EventLoop *)handle; + loop->stop = 1; +} \ No newline at end of file diff --git a/services/loopevent/loop/le_loop.h b/services/loopevent/loop/le_loop.h new file mode 100644 index 0000000000000000000000000000000000000000..ad84c0c790e00302d4a86b5b6efc9b7b794803bf --- /dev/null +++ b/services/loopevent/loop/le_loop.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 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 LE_EVENT_LOOP_H +#define LE_EVENT_LOOP_H +#include + +#include "le_task.h" +#include "le_utils.h" +#include "list.h" +#include "init_hashmap.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct EventLoop_ { + LE_STATUS (*close)(const struct EventLoop_ *loop); + LE_STATUS (*runLoop)(const struct EventLoop_ *loop); + LE_STATUS (*addEvent)(const struct EventLoop_ *loop, const BaseTask *task, int op); + LE_STATUS (*modEvent)(const struct EventLoop_ *loop, const BaseTask *task, int op); + LE_STATUS (*delEvent)(const struct EventLoop_ *loop, int fd, int op); + + uint32_t maxevents; + uint32_t timeout; + uint32_t stop; +#ifdef LOOP_EVENT_USE_MUTEX + LoopMutex mutex; +#else + char mutex; +#endif + HashMapHandle taskMap; + + ListNode idleList; + ListNode timerList; +} EventLoop; + +LE_STATUS CloseLoop(EventLoop *loop); +LE_STATUS AddTask(EventLoop *loop, BaseTask *task); +BaseTask *GetTaskByFd(EventLoop *loop, int fd); +void DelTask(EventLoop *loop, BaseTask *task); +LE_STATUS ProcessEvent(const EventLoop *loop, int fd, uint32_t oper); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif \ No newline at end of file diff --git a/services/loopevent/signal/le_signal.c b/services/loopevent/signal/le_signal.c new file mode 100644 index 0000000000000000000000000000000000000000..c56e3f68c68da403d0983b5c6feca8effc7f7da0 --- /dev/null +++ b/services/loopevent/signal/le_signal.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2021 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 "le_signal.h" + +#include +#include +#include +#include +#include + +#include "le_loop.h" +#include "le_task.h" +#include "loop_event.h" + +static LE_STATUS HandleSignalEvent_(const LoopHandle loop, const TaskHandle task, uint32_t oper) +{ + if (!LE_TEST_FLAGS(oper, EVENT_READ)) { + return LE_FAILURE; + } + struct signalfd_siginfo fdsi; + ssize_t s = read(GetSocketFd(task), &fdsi, sizeof(fdsi)); + LE_CHECK(s == sizeof(fdsi), return LE_FAILURE, "Failed to read sign %d %d", s, errno); + SignalTask *sigTask = (SignalTask *)task; + if (sigTask->processSignal) { + sigTask->processSignal(&fdsi); + } + return LE_SUCCESS; +} + +static void HandleSignalTaskClose_(const LoopHandle loopHandle, const TaskHandle signalHandle) +{ + BaseTask *task = (BaseTask *)signalHandle; + DelTask((EventLoop *)loopHandle, task); + CloseTask(loopHandle, task); + close(task->taskId.fd); +} + +static void PrintSigset(sigset_t mask) +{ + int cnt = 0; + for (int sig = 1; sig < NSIG; sig++) { + if (sigismember(&mask, sig)) { + cnt++; + printf("\t %d(%s)\n", sig, strsignal(sig)); + } + } + if (cnt == 0) { + printf("empty signal set\n"); + } +} + +static void DumpSignalTaskInfo_(const TaskHandle task) +{ + INIT_CHECK(task != NULL, return); + BaseTask *baseTask = (BaseTask *)task; + SignalTask *signalTask = (SignalTask *)baseTask; + printf("\tfd: %d \n", signalTask->base.taskId.fd); + printf("\t TaskType: %s \n", "SignalTask"); + printf("\t sigNumber: %d \n", signalTask->sigNumber); + printf("\t signal: \n"); + PrintSigset(signalTask->mask); +} + +LE_STATUS LE_CreateSignalTask(const LoopHandle loopHandle, SignalHandle *signalHandle, LE_ProcessSignal processSignal) +{ + LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(processSignal != NULL, return LE_FAILURE, "Invalid parameters processSignal"); + sigset_t mask; + sigemptyset(&mask); + int sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); + LE_CHECK(sfd > 0, return -1, "Failed to create signal fd"); + LE_BaseInfo info = {TASK_SIGNAL, NULL}; + SignalTask *task = (SignalTask *)CreateTask(loopHandle, sfd, &info, sizeof(SignalTask)); + LE_CHECK(task != NULL, return LE_NO_MEMORY, "Failed to create task"); + task->base.handleEvent = HandleSignalEvent_; + task->base.innerClose = HandleSignalTaskClose_; + task->base.dumpTaskInfo = DumpSignalTaskInfo_; + task->sigNumber = 0; + sigemptyset(&task->mask); + task->processSignal = processSignal; + *signalHandle = (SignalHandle)task; + return LE_SUCCESS; +} + +LE_STATUS LE_AddSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal) +{ + LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + EventLoop *loop = (EventLoop *)loopHandle; + SignalTask *task = (SignalTask *)signalHandle; + LE_LOGI("LE_AddSignal %d %d", signal, task->sigNumber); + if (sigismember(&task->mask, signal)) { + return LE_SUCCESS; + } + sigaddset(&task->mask, signal); + sigprocmask(SIG_BLOCK, &task->mask, NULL); + int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC); + LE_CHECK(sfd > 0, return -1, "Failed to create signal fd"); + if (task->sigNumber == 0) { + loop->addEvent(loop, (const BaseTask *)task, EVENT_READ); + } else { + loop->modEvent(loop, (const BaseTask *)task, EVENT_READ); + } + task->sigNumber++; + return LE_SUCCESS; +} + +LE_STATUS LE_RemoveSignal(const LoopHandle loopHandle, const SignalHandle signalHandle, int signal) +{ + LE_CHECK(loopHandle != NULL && signalHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + EventLoop *loop = (EventLoop *)loopHandle; + SignalTask *task = (SignalTask *)signalHandle; + LE_LOGI("LE_RemoveSignal %d %d", signal, task->sigNumber); + if (!sigismember(&task->mask, signal)) { + return LE_SUCCESS; + } + sigdelset(&task->mask, signal); + task->sigNumber--; + int sfd = signalfd(GetSocketFd(signalHandle), &task->mask, SFD_NONBLOCK | SFD_CLOEXEC); + LE_CHECK(sfd > 0, return -1, "Failed to create signal fd"); + if (task->sigNumber <= 0) { + loop->delEvent(loop, GetSocketFd(signalHandle), EVENT_READ); + } + return LE_SUCCESS; +} + +void LE_CloseSignalTask(const LoopHandle loopHandle, const SignalHandle signalHandle) +{ + LE_CHECK(loopHandle != NULL && signalHandle != NULL, return, "Invalid parameters"); + LE_CloseTask(loopHandle, signalHandle); +} diff --git a/services/loopevent/signal/le_signal.h b/services/loopevent/signal/le_signal.h new file mode 100644 index 0000000000000000000000000000000000000000..bad7c32e86a60292cdd2982711a787254f9c4ef4 --- /dev/null +++ b/services/loopevent/signal/le_signal.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 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 LOOP_SIGNAL_H +#define LOOP_SIGNAL_H +#include +#include +#include "loop_event.h" +#include "le_task.h" + +typedef struct { + BaseTask base; + sigset_t mask; + int sigNumber; + LE_ProcessSignal processSignal; +} SignalTask; + +#endif \ No newline at end of file diff --git a/services/loopevent/socket/le_socket.c b/services/loopevent/socket/le_socket.c new file mode 100644 index 0000000000000000000000000000000000000000..39fe4c40d0cca6494e2f84a5355d5cfb75fba7c1 --- /dev/null +++ b/services/loopevent/socket/le_socket.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2021 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 "le_socket.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "le_utils.h" + +static int SetSocketTimeout(int fd) +{ + struct timeval timeout; + timeout.tv_sec = SOCKET_TIMEOUT; + timeout.tv_usec = 0; + int ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + LE_CHECK(ret == 0, return ret, "Failed to set socket option"); + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + LE_CHECK(ret == 0, return ret, "Failed to set socket option"); + return ret; +} + +static int CreatePipeServerSocket_(const char *server, int maxClient, int public) +{ + int listenfd = socket(PF_UNIX, SOCK_STREAM, 0); + LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket errno %d", errno); + + int ret = SetSocketTimeout(listenfd); + LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); + + unlink(server); + struct sockaddr_un serverAddr; + ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)); + LE_CHECK(ret == 0, close(listenfd); + return ret, "Failed to memory set. error: %d", errno); + serverAddr.sun_family = AF_UNIX; + ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server); + LE_CHECK(ret == 0, close(listenfd); + return ret, "Failed to copy. error: %d", errno); + uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(server); + ret = bind(listenfd, (struct sockaddr *)&serverAddr, size); + LE_CHECK(ret >= 0, close(listenfd); + return ret, "Failed to bind socket. error: %d", errno); + + SetNoBlock(listenfd); + ret = listen(listenfd, maxClient); + LE_CHECK(ret >= 0, close(listenfd); + return ret, "Failed to listen socket error: %d", errno); + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + if (public) { + mode |= S_IROTH | S_IWOTH; + } + ret = chmod(server, mode); + LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno); + LE_LOGV("CreatePipeSocket listen fd: %d server:%s ", listenfd, serverAddr.sun_path); + return listenfd; +} + +static int CreatePipeSocket_(const char *server) +{ + int fd = socket(PF_UNIX, SOCK_STREAM, 0); + LE_CHECK(fd > 0, return fd, "Failed to create socket"); + SetNoBlock(fd); + + int on = 1; + int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); + LE_CHECK(ret == 0, return ret, "Failed to set socket option"); + + ret = SetSocketTimeout(fd); + LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); + + struct sockaddr_un serverAddr; + ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)); + LE_CHECK(ret == 0, close(fd); + return ret, "Failed to memset_s serverAddr"); + serverAddr.sun_family = AF_UNIX; + ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server); + LE_CHECK(ret == 0, close(fd); + return ret, "Failed to strcpy_s sun_path"); + uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path); + ret = connect(fd, (struct sockaddr *)&serverAddr, size); + LE_CHECK(ret >= 0, close(fd); + return ret, "Failed to connect socket"); + LE_LOGV("CreatePipeSocket connect fd: %d server: %s ", fd, serverAddr.sun_path); + return fd; +} + +static LE_STATUS GetSockaddrFromServer_(const char *server, struct sockaddr_in *addr) +{ + int ret = memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)); + LE_CHECK(ret == 0, return ret, "Failed to memory set. error: %s", strerror(errno)); + addr->sin_family = AF_INET; + const char *portStr = strstr(server, ":"); + LE_CHECK(portStr != NULL, return LE_FAILURE, "Failed to get addr %s", server); + uint16_t port = atoi(portStr + 1); + addr->sin_port = htons(port); + ret = inet_pton(AF_INET, server, &addr->sin_addr); + LE_CHECK(ret >= 0, return LE_FAILURE, "Failed to inet_pton addr %s", server); + LE_LOGV("CreateTcpSocket server: %s port: %d", server, port); + return LE_SUCCESS; +} + +static int CreateTcpServerSocket_(const char *server, int maxClient) +{ + int listenfd = socket(AF_INET, SOCK_STREAM, 0); + LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket"); + + int ret = SetSocketTimeout(listenfd); + LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); + + struct sockaddr_in serverAddr; + GetSockaddrFromServer_(server, &serverAddr); + ret = bind(listenfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); + LE_CHECK(ret >= 0, close(listenfd); + return ret, "Failed to bind socket"); + SetNoBlock(listenfd); + + ret = listen(listenfd, maxClient); + LE_CHECK(ret >= 0, close(listenfd); + return ret, "Failed to listen socket"); + return listenfd; +} + +static int CreateTcpSocket_(const char *server) +{ + int fd = socket(AF_INET, SOCK_STREAM, 0); + LE_CHECK(fd > 0, return fd, "Failed to create socket"); + SetNoBlock(fd); + + int on = 1; + int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); + LE_CHECK(ret == 0, return ret, "Failed to set socket option"); + + ret = SetSocketTimeout(fd); + LE_CHECK(ret == 0, return ret, "Failed to set socket timeout"); + + struct sockaddr_in serverAddr; + GetSockaddrFromServer_(server, &serverAddr); + ret = connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); + LE_CHECK(ret >= 0, close(fd); + return ret, "Failed to connect socket errno:%d", errno); + return fd; +} + +static int AcceptPipeSocket_(int serverFd) +{ + struct sockaddr_un clientAddr; + socklen_t addrlen = sizeof(clientAddr); + bzero(&clientAddr, addrlen); + int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen); + LE_CHECK(fd >= 0, return fd, "Failed to accept socket"); + LE_LOGV("AcceptPipeSocket client fd %d %s ", fd, clientAddr.sun_path); + return fd; +} + +static int AcceptTcpSocket_(int serverFd) +{ + struct sockaddr_in clientAddr; + socklen_t addrlen = sizeof(clientAddr); + bzero(&clientAddr, addrlen); + int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen); + LE_CHECK(fd >= 0, return fd, "Failed to accept socket"); + LE_LOGV("AcceptTcpSocket_ client: %s ", inet_ntoa(clientAddr.sin_addr)); + return fd; +} +INIT_LOCAL_API +int CreateSocket(int flags, const char *server) +{ + int fd = -1; + int type = flags & 0x0000ff00; + LE_LOGV("CreateSocket flags %x type %x server %s", flags, type, server); + if (type == TASK_TCP) { + if (LE_TEST_FLAGS(flags, TASK_SERVER)) { + fd = CreateTcpServerSocket_(server, LOOP_MAX_CLIENT); + } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) { + fd = CreateTcpSocket_(server); + } + } else if (type == TASK_PIPE) { + if (LE_TEST_FLAGS(flags, TASK_SERVER)) { + fd = CreatePipeServerSocket_(server, LOOP_MAX_CLIENT, + (int)LE_TEST_FLAGS(flags, TASK_PUBLIC)); + } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) { + fd = CreatePipeSocket_(server); + } + } + if (fd <= 0) { + LE_LOGE("Invalid flags 0x%08x for server %s", flags, server); + return -1; + } + return fd; +} +INIT_LOCAL_API +int AcceptSocket(int fd, int flags) +{ + int clientFd = -1; + int type = flags & 0x0000ff00; + if (type == TASK_TCP) { + clientFd = AcceptTcpSocket_(fd); + } else if (type == TASK_PIPE) { + clientFd = AcceptPipeSocket_(fd); + } else { + LE_LOGE("AcceptSocket invalid flags %#8x ", flags); + return -1; + } + SetNoBlock(clientFd); + return clientFd; +} + +INIT_LOCAL_API +int listenSocket(int fd, int flags, const char *server) +{ + unsigned int type = (unsigned int)flags & 0x0000ff00; + LE_LOGV("listenSocket flags %x type %x server %s", flags, type, server); + SetNoBlock(fd); + if (!LE_TEST_FLAGS((unsigned int)flags, TASK_SERVER)) { + return 0; + } + if (type == TASK_TCP) { + int ret = listen(fd, LOOP_MAX_CLIENT); + LE_CHECK(ret >= 0, close(fd); + return ret, "Failed to listen socket"); + } else if (type == TASK_PIPE) { + int ret = listen(fd, LOOP_MAX_CLIENT); + LE_CHECK(ret >= 0, close(fd); + return ret, "Failed to listen socket error: %d", errno); + ret = chmod(server, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + LE_CHECK(ret == 0, close(fd); + return -1, "Failed to chmod %s, err %d. ", server, errno); + } + return 0; +} diff --git a/services/include/init_utils.h b/services/loopevent/socket/le_socket.h similarity index 63% rename from services/include/init_utils.h rename to services/loopevent/socket/le_socket.h index 3dcdbcbdac7c0174f3224f518b55135cc3d8d435..f28532a3addf24b4c8d4238e36f70b728b76a5f8 100644 --- a/services/include/init_utils.h +++ b/services/loopevent/socket/le_socket.h @@ -13,8 +13,11 @@ * limitations under the License. */ -#ifndef INIT_UTILS_H -#define INIT_UTILS_H +#ifndef LE_SOCKET_H +#define LE_SOCKET_H +#include "le_utils.h" +#include "loop_event.h" +#include "beget_ext.h" #ifdef __cplusplus #if __cplusplus @@ -22,19 +25,18 @@ extern "C" { #endif #endif -#define BINARY_BASE 2 -#define OCTAL_BASE 8 -#define DECIMAL_BASE 10 +#define SOCKET_TIMEOUT 3 -int DecodeUid(const char *name); -void CheckAndCreateDir(const char *fileName); -char* ReadFileToBuf(const char *configFile); -int SplitString(char *srcPtr, char **dstPtr, int maxNum); -void WaitForFile(const char *source, unsigned int maxCount); +INIT_LOCAL_API +int CreateSocket(int flags, const char *server); +INIT_LOCAL_API +int AcceptSocket(int fd, int flags); +INIT_LOCAL_API +int listenSocket(int fd, int flags, const char *server); #ifdef __cplusplus #if __cplusplus } #endif #endif -#endif // INIT_UTILS_H +#endif \ No newline at end of file diff --git a/services/loopevent/task/le_asynctask.c b/services/loopevent/task/le_asynctask.c new file mode 100644 index 0000000000000000000000000000000000000000..154ce012d9f1446e001e63103947cb6046041c6c --- /dev/null +++ b/services/loopevent/task/le_asynctask.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021 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 "le_task.h" +#include +#include + +#include "le_loop.h" + +#define MILLION_MICROSECOND 1000000 +#define THOUSAND_MILLISECOND 1000 + +static void DoAsyncEvent_(const LoopHandle loopHandle, AsyncEventTask *asyncTask) +{ + LE_CHECK(loopHandle != NULL && asyncTask != NULL, return, "Invalid parameters"); +#ifdef LOOP_DEBUG + struct timespec startTime = {0}; + struct timespec endTime = {0}; + long long diff; + clock_gettime(CLOCK_MONOTONIC, &(startTime)); +#endif + StreamTask *task = &asyncTask->stream; + ListNode *node = task->buffHead.next; + if (node != &task->buffHead) { + LE_Buffer *buffer = ListEntry(node, LE_Buffer, node); + uint64_t eventId = *(uint64_t*)(buffer->data); + if (asyncTask->processAsyncEvent) { + asyncTask->processAsyncEvent((TaskHandle)asyncTask, eventId, + (uint8_t *)(buffer->data + sizeof(uint64_t)), buffer->dataSize); + } + OH_ListRemove(&buffer->node); + free(buffer); +#ifdef LOOP_DEBUG + clock_gettime(CLOCK_MONOTONIC, &(endTime)); + diff = (long long)(endTime.tv_sec - startTime.tv_sec) * MILLION_MICROSECOND; + if (endTime.tv_nsec > startTime.tv_nsec) { + diff += (endTime.tv_nsec - startTime.tv_nsec) / THOUSAND_MILLISECOND; // 1000 ms + } else { + diff -= (endTime.tv_nsec - startTime.tv_nsec) / THOUSAND_MILLISECOND; // 1000 ms + } + LE_LOGI("DoAsyncEvent_ diff %ld", diff); +#endif + } +} + +#ifdef STARTUP_INIT_TEST +void LE_DoAsyncEvent(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ + AsyncEventTask *asyncTask = (AsyncEventTask *)taskHandle; + while (!IsBufferEmpty(&asyncTask->stream)) { + DoAsyncEvent_(loopHandle, (AsyncEventTask *)taskHandle); + } +} +#endif + +static LE_STATUS HandleAsyncEvent_(const LoopHandle loopHandle, const TaskHandle taskHandle, uint32_t oper) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_LOGV("HandleAsyncEvent_ fd: %d oper 0x%x", GetSocketFd(taskHandle), oper); + EventLoop *loop = (EventLoop *)loopHandle; + AsyncEventTask *asyncTask = (AsyncEventTask *)taskHandle; + if (LE_TEST_FLAGS(oper, EVENT_READ)) { + uint64_t eventId = 0; + int ret = read(GetSocketFd(taskHandle), &eventId, sizeof(eventId)); + LE_LOGV("HandleAsyncEvent_ read fd:%d ret: %d eventId %llu", GetSocketFd(taskHandle), ret, eventId); + DoAsyncEvent_(loopHandle, asyncTask); + if (!IsBufferEmpty(&asyncTask->stream)) { + loop->modEvent(loop, (const BaseTask *)taskHandle, EVENT_WRITE); + return LE_SUCCESS; + } + } else { + static uint64_t eventId = 0; + (void)write(GetSocketFd(taskHandle), &eventId, sizeof(eventId)); + loop->modEvent(loop, (const BaseTask *)taskHandle, EVENT_READ); + eventId++; + } + return LE_SUCCESS; +} + +static void HandleAsyncTaskClose_(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ + BaseTask *task = (BaseTask *)taskHandle; + DelTask((EventLoop *)loopHandle, task); + CloseTask(loopHandle, task); + close(task->taskId.fd); +} + +static void DumpEventTaskInfo_(const TaskHandle task) +{ + INIT_CHECK(task != NULL, return); + BaseTask *baseTask = (BaseTask *)task; + AsyncEventTask *eventTask = (AsyncEventTask *)baseTask; + printf("\tfd: %d \n", eventTask->stream.base.taskId.fd); + printf("\t TaskType: %s\n", "EventTask"); +} + +LE_STATUS LE_CreateAsyncTask(const LoopHandle loopHandle, + TaskHandle *taskHandle, LE_ProcessAsyncEvent processAsyncEvent) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(processAsyncEvent != NULL, return LE_INVALID_PARAM, "Invalid parameters processAsyncEvent "); + + int fd = eventfd(1, EFD_NONBLOCK | EFD_CLOEXEC); + LE_CHECK(fd > 0, return LE_FAILURE, "Failed to event fd "); + LE_BaseInfo baseInfo = {TASK_EVENT | TASK_ASYNC_EVENT, NULL}; + AsyncEventTask *task = (AsyncEventTask *)CreateTask(loopHandle, fd, &baseInfo, sizeof(AsyncEventTask)); + LE_CHECK(task != NULL, close(fd); + return LE_NO_MEMORY, "Failed to create task"); + task->stream.base.handleEvent = HandleAsyncEvent_; + task->stream.base.innerClose = HandleAsyncTaskClose_; + task->stream.base.dumpTaskInfo = DumpEventTaskInfo_; + OH_ListInit(&task->stream.buffHead); + LoopMutexInit(&task->stream.mutex); + task->processAsyncEvent = processAsyncEvent; + EventLoop *loop = (EventLoop *)loopHandle; + loop->addEvent(loop, (const BaseTask *)task, EVENT_READ); + *taskHandle = (TaskHandle)task; + return LE_SUCCESS; +} + +LE_STATUS LE_StartAsyncEvent(const LoopHandle loopHandle, + const TaskHandle taskHandle, uint64_t eventId, const uint8_t *data, uint32_t buffLen) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + BufferHandle handle = LE_CreateBuffer(loopHandle, buffLen + 1 + sizeof(eventId)); + char *buff = (char *)LE_GetBufferInfo(handle, NULL, NULL); + LE_CHECK(buff != NULL, return LE_FAILURE, "Failed to get buff"); + int ret = memcpy_s(buff, sizeof(eventId), &eventId, sizeof(eventId)); + LE_CHECK(ret == 0, return -1, "Failed to copy data"); + if (data != NULL && buffLen > 0) { + ret = memcpy_s(buff + sizeof(eventId), buffLen, data, buffLen); + LE_CHECK(ret == 0, return -1, "Failed to copy data"); + buff[sizeof(eventId) + buffLen] = '\0'; + } + return LE_Send(loopHandle, taskHandle, handle, buffLen); +} + +void LE_StopAsyncTask(LoopHandle loopHandle, TaskHandle taskHandle) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL, return, "Invalid parameters"); + LE_CloseTask(loopHandle, taskHandle); +} \ No newline at end of file diff --git a/services/loopevent/task/le_streamtask.c b/services/loopevent/task/le_streamtask.c new file mode 100644 index 0000000000000000000000000000000000000000..b1184e15404b2660ba94b7c60af20e179a2cc079 --- /dev/null +++ b/services/loopevent/task/le_streamtask.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2021 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 "le_loop.h" + +#include +#include +#include "securec.h" + +#include "le_socket.h" +#include "le_task.h" + +static LE_STATUS HandleSendMsg_(const LoopHandle loopHandle, + const TaskHandle taskHandle, const LE_SendMessageComplete complete) +{ + EventLoop *loop = (EventLoop *)loopHandle; + StreamTask *stream = (StreamTask *)taskHandle; + LE_Buffer *buffer = GetFirstBuffer(stream); + while (buffer) { + int ret = write(GetSocketFd(taskHandle), buffer->data, buffer->dataSize); + if (ret < 0 || (size_t)ret < buffer->dataSize) { + LE_LOGE("HandleSendMsg_ fd:%d send data size %d %d, err:%d", GetSocketFd(taskHandle), + buffer->dataSize, ret, errno); + } + LE_LOGV("HandleSendMsg_ fd:%d send data size %d %d", GetSocketFd(taskHandle), buffer->dataSize, ret); + buffer->result = (ret == (int)buffer->dataSize) ? 0 : errno; + if (complete != NULL) { + complete(taskHandle, buffer); + } + FreeBuffer(loopHandle, stream, buffer); + buffer = GetFirstBuffer(stream); + } + if (IsBufferEmpty(stream)) { + LE_LOGV("HandleSendMsg_ fd:%d empty wait read", GetSocketFd(taskHandle)); + loop->modEvent(loop, (const BaseTask *)taskHandle, EVENT_READ); + return LE_SUCCESS; + } + return LE_SUCCESS; +} + +static LE_STATUS HandleRecvMsg_(const LoopHandle loopHandle, + const TaskHandle taskHandle, const LE_RecvMessage recvMessage, const LE_HandleRecvMsg handleRecvMsg) +{ + LE_STATUS status = LE_SUCCESS; + LE_Buffer *buffer = CreateBuffer(LOOP_DEFAULT_BUFFER); + LE_CHECK(buffer != NULL, return LE_NO_MEMORY, "Failed to create buffer"); + int readLen = 0; + while (1) { + if (handleRecvMsg != NULL) { + readLen = handleRecvMsg(taskHandle, buffer->data, LOOP_DEFAULT_BUFFER, 0); + } else { + readLen = recv(GetSocketFd(taskHandle), buffer->data, LOOP_DEFAULT_BUFFER, 0); + } + LE_LOGV("HandleRecvMsg fd:%d read msg len %d", GetSocketFd(taskHandle), readLen); + if (readLen < 0) { + if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { + continue; + } + status = LE_DIS_CONNECTED; + break; + } else if (readLen == 0) { + // 若另一端已关闭连接则返回0,这种关闭是对方主动且正常的关闭 + status = LE_DIS_CONNECTED; + break; + } else { + break; + } + } + if (status != LE_SUCCESS) { + FreeBuffer(loopHandle, NULL, buffer); + return status; + } + if (recvMessage) { + recvMessage(taskHandle, buffer->data, readLen); + } + FreeBuffer(loopHandle, NULL, buffer); + return status; +} + +static LE_STATUS HandleStreamEvent_(const LoopHandle loopHandle, const TaskHandle handle, uint32_t oper) +{ + StreamConnectTask *stream = (StreamConnectTask *)handle; + LE_LOGV("HandleStreamEvent_ fd:%d oper 0x%x", GetSocketFd(handle), oper); + + LE_STATUS status = LE_SUCCESS; + if (LE_TEST_FLAGS(oper, EVENT_WRITE)) { + status = HandleSendMsg_(loopHandle, handle, stream->sendMessageComplete); + } + if (LE_TEST_FLAGS(oper, EVENT_READ)) { + status = HandleRecvMsg_(loopHandle, handle, stream->recvMessage, stream->handleRecvMsg); + } + if (LE_TEST_FLAGS(oper, EVENT_ERROR)) { + if (stream->disConnectComplete) { + stream->disConnectComplete(handle); + } + LE_CloseStreamTask(loopHandle, handle); + } + return status; +} + +static LE_STATUS HandleClientEvent_(const LoopHandle loopHandle, const TaskHandle handle, uint32_t oper) +{ + StreamClientTask *client = (StreamClientTask *)handle; + LE_LOGI("HandleClientEvent_ fd:%d oper 0x%x", GetSocketFd(handle), oper); + + LE_STATUS status = LE_SUCCESS; + if (LE_TEST_FLAGS(oper, EVENT_WRITE)) { + LE_ONLY_CHECK(!(client->connected == 0 && client->connectComplete), client->connectComplete(handle)); + client->connected = 1; + status = HandleSendMsg_(loopHandle, handle, client->sendMessageComplete); + } + if (LE_TEST_FLAGS(oper, EVENT_READ)) { + status = HandleRecvMsg_(loopHandle, handle, client->recvMessage, client->handleRecvMsg); + } + if (status == LE_DIS_CONNECTED) { + if (client->disConnectComplete) { + client->disConnectComplete(handle); + } + client->connected = 0; + LE_CloseStreamTask(loopHandle, handle); + } + return status; +} + +static void HandleStreamTaskClose_(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ + BaseTask *task = (BaseTask *)taskHandle; + DelTask((EventLoop *)loopHandle, task); + CloseTask(loopHandle, task); + if (task->taskId.fd > 0) { + close(task->taskId.fd); + } +} + +static void DumpStreamServerTaskInfo_(const TaskHandle task) +{ + INIT_CHECK(task != NULL, return); + BaseTask *baseTask = (BaseTask *)task; + StreamServerTask *serverTask = (StreamServerTask *)baseTask; + printf("\tfd: %d \n", serverTask->base.taskId.fd); + printf("\t TaskType: %s \n", "ServerTask"); + if (strlen(serverTask->server) > 0) { + printf("\t Server socket:%s \n", serverTask->server); + } else { + printf("\t Server socket:%s \n", "NULL"); + } +} + +static void DumpStreamConnectTaskInfo_(const TaskHandle task) +{ + INIT_CHECK(task != NULL, return); + BaseTask *baseTask = (BaseTask *)task; + StreamConnectTask *connectTask = (StreamConnectTask *)baseTask; + TaskHandle taskHandle = (TaskHandle)connectTask; + printf("\tfd: %d \n", connectTask->stream.base.taskId.fd); + printf("\t TaskType: %s \n", "ConnectTask"); + printf("\t ServiceInfo: \n"); + struct ucred cred = {-1, -1, -1}; + socklen_t credSize = sizeof(struct ucred); + if (getsockopt(LE_GetSocketFd(taskHandle), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) == 0) { + printf("\t Service Pid: %d \n", cred.pid); + printf("\t Service Uid: %u \n", cred.uid); + printf("\t Service Gid: %u \n", cred.gid); + } else { + printf("\t Service Pid: %s \n", "NULL"); + printf("\t Service Uid: %s \n", "NULL"); + printf("\t Service Gid: %s \n", "NULL"); + } +} + +static LE_STATUS HandleServerEvent_(const LoopHandle loopHandle, const TaskHandle serverTask, uint32_t oper) +{ + LE_LOGV("HandleServerEvent_ fd %d oper 0x%x", GetSocketFd(serverTask), oper); + if (!LE_TEST_FLAGS(oper, EVENT_READ)) { + return LE_FAILURE; + } + StreamServerTask *server = (StreamServerTask *)serverTask; + LE_ONLY_CHECK(server->incommingConnect != NULL, return LE_SUCCESS); + + int ret = server->incommingConnect(loopHandle, serverTask); + if (ret != LE_SUCCESS) { + LE_LOGE("HandleServerEvent_ fd %d do not accept socket", GetSocketFd(serverTask)); + } + EventLoop *loop = (EventLoop *)loopHandle; + loop->modEvent(loop, (const BaseTask *)serverTask, EVENT_READ); + return LE_SUCCESS; +} + +LE_STATUS LE_CreateStreamServer(const LoopHandle loopHandle, + TaskHandle *taskHandle, const LE_StreamServerInfo *info) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL && info != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(info->server != NULL, return LE_INVALID_PARAM, "Invalid parameters server"); + LE_CHECK(info->incommingConnect != NULL, return LE_INVALID_PARAM, + "Invalid parameters incommingConnect %s", info->server); + + int fd = info->socketId; + int ret = 0; + if (info->socketId <= 0) { + fd = CreateSocket(info->baseInfo.flags, info->server); + LE_CHECK(fd > 0, return LE_FAILURE, "Failed to create socket %s", info->server); + } else { + ret = listenSocket(fd, info->baseInfo.flags, info->server); + LE_CHECK(ret == 0, return LE_FAILURE, "Failed to listen socket %s", info->server); + } + + EventLoop *loop = (EventLoop *)loopHandle; + StreamServerTask *task = (StreamServerTask *)CreateTask(loopHandle, fd, &info->baseInfo, + sizeof(StreamServerTask) + strlen(info->server) + 1); + LE_CHECK(task != NULL, close(fd); + return LE_NO_MEMORY, "Failed to create task"); + task->base.handleEvent = HandleServerEvent_; + task->base.innerClose = HandleStreamTaskClose_; + task->base.dumpTaskInfo = DumpStreamServerTaskInfo_; + task->incommingConnect = info->incommingConnect; + loop->addEvent(loop, (const BaseTask *)task, EVENT_READ); + ret = memcpy_s(task->server, strlen(info->server) + 1, info->server, strlen(info->server) + 1); + LE_CHECK(ret == 0, return LE_FAILURE, "Failed to copy server name %s", info->server); + *taskHandle = (TaskHandle)task; + return LE_SUCCESS; +} + +LE_STATUS LE_CreateStreamClient(const LoopHandle loopHandle, + TaskHandle *taskHandle, const LE_StreamInfo *info) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL && info != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(info->recvMessage != NULL, return LE_FAILURE, "Invalid parameters recvMessage %s", info->server); + + int fd = CreateSocket(info->baseInfo.flags, info->server); + LE_CHECK(fd > 0, return LE_FAILURE, "Failed to create socket %s", info->server); + + StreamClientTask *task = (StreamClientTask *)CreateTask(loopHandle, fd, &info->baseInfo, sizeof(StreamClientTask)); + LE_CHECK(task != NULL, close(fd); + return LE_NO_MEMORY, "Failed to create task"); + task->stream.base.handleEvent = HandleClientEvent_; + task->stream.base.innerClose = HandleStreamTaskClose_; + OH_ListInit(&task->stream.buffHead); + LoopMutexInit(&task->stream.mutex); + + task->connectComplete = info->connectComplete; + task->sendMessageComplete = info->sendMessageComplete; + task->recvMessage = info->recvMessage; + task->disConnectComplete = info->disConnectComplete; + task->handleRecvMsg = info->handleRecvMsg; + EventLoop *loop = (EventLoop *)loopHandle; + loop->addEvent(loop, (const BaseTask *)task, EVENT_READ); + *taskHandle = (TaskHandle)task; + return LE_SUCCESS; +} + +LE_STATUS LE_AcceptStreamClient(const LoopHandle loopHandle, const TaskHandle server, + TaskHandle *taskHandle, const LE_StreamInfo *info) +{ + LE_CHECK(loopHandle != NULL && info != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(server != NULL && taskHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(info->recvMessage != NULL, return LE_INVALID_PARAM, "Invalid parameters recvMessage"); + int fd = -1; + if ((info->baseInfo.flags & TASK_TEST) != TASK_TEST) { + fd = AcceptSocket(GetSocketFd(server), info->baseInfo.flags); + LE_CHECK(fd > 0, return LE_FAILURE, "Failed to accept socket %d", GetSocketFd(server)); + } + StreamConnectTask *task = (StreamConnectTask *)CreateTask( + loopHandle, fd, &info->baseInfo, sizeof(StreamConnectTask)); + LE_CHECK(task != NULL, close(fd); + return LE_NO_MEMORY, "Failed to create task"); + task->stream.base.handleEvent = HandleStreamEvent_; + task->stream.base.innerClose = HandleStreamTaskClose_; + task->stream.base.dumpTaskInfo = DumpStreamConnectTaskInfo_; + task->disConnectComplete = info->disConnectComplete; + task->sendMessageComplete = info->sendMessageComplete; + task->recvMessage = info->recvMessage; + task->serverTask = (StreamServerTask *)server; + task->handleRecvMsg = info->handleRecvMsg; + OH_ListInit(&task->stream.buffHead); + LoopMutexInit(&task->stream.mutex); + if ((info->baseInfo.flags & TASK_TEST) != TASK_TEST) { + EventLoop *loop = (EventLoop *)loopHandle; + loop->addEvent(loop, (const BaseTask *)task, EVENT_READ); + } + *taskHandle = (TaskHandle)task; + return 0; +} + +void LE_CloseStreamTask(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL, return, "Invalid parameters"); + LE_CloseTask(loopHandle, taskHandle); +} + +int LE_GetSocketFd(const TaskHandle taskHandle) +{ + LE_CHECK(taskHandle != NULL, return -1, "Invalid parameters"); + return GetSocketFd(taskHandle); +} diff --git a/services/loopevent/task/le_task.c b/services/loopevent/task/le_task.c new file mode 100644 index 0000000000000000000000000000000000000000..d91e14fa3147552cd9e0f802e3185cc21fb0ccbf --- /dev/null +++ b/services/loopevent/task/le_task.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2021 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 "le_task.h" + + +#include "le_loop.h" +#include "le_utils.h" + +int CheckTaskFlags(const BaseTask *task, uint32_t flags) +{ + if (task == NULL) { + return 0; + } + return ((task->flags & flags) == flags); +} + +int GetSocketFd(const TaskHandle task) +{ + BaseTask *stream = (BaseTask *)task; + return stream->taskId.fd; +} + +BaseTask *CreateTask(const LoopHandle loopHandle, int fd, const LE_BaseInfo *info, uint32_t size) +{ + if ((size >= LOOP_MAX_BUFFER) || ((size + info->userDataSize) >= LOOP_MAX_BUFFER)) { + return NULL; + } + BaseTask *task = (BaseTask *)calloc(1, size + info->userDataSize); + LE_CHECK(task != NULL, return NULL, "Failed to alloc for task"); + HASHMAPInitNode(&task->hashNode); + // key id + task->flags = info->flags; + task->taskId.fd = fd; + LE_STATUS ret = AddTask((EventLoop *)loopHandle, task); + LE_CHECK(ret == LE_SUCCESS, free(task); + return NULL, "Failed to alloc for task"); + task->userDataSize = info->userDataSize; + task->userDataOffset = size; + task->close = info->close; + return task; +} + +void CloseTask(const LoopHandle loopHandle, BaseTask *task) +{ + LE_CHECK(loopHandle != NULL && task != NULL, return, "Invalid parameters"); + LE_LOGV("CloseTask %d", task->taskId.fd); + if (CheckTaskFlags(task, TASK_STREAM | TASK_CONNECT) || + CheckTaskFlags(task, TASK_EVENT | TASK_ASYNC_EVENT)) { + StreamTask *stream = (StreamTask *)task; + LE_Buffer *buffer = GetFirstBuffer(stream); + while (buffer) { + FreeBuffer(loopHandle, stream, (BufferHandle)buffer); + buffer = GetFirstBuffer(stream); + } + } + if (task->close != NULL) { + task->close((TaskHandle)task); + } +} + +LE_Buffer *CreateBuffer(uint32_t bufferSize) +{ + LE_ONLY_CHECK(bufferSize < LOOP_MAX_BUFFER, return NULL); + LE_Buffer *buffer = NULL; + LE_CHECK((buffer = (LE_Buffer *)malloc(sizeof(LE_Buffer) + bufferSize)) != NULL, + return NULL, "Failed to alloc memory for buffer"); + OH_ListInit(&buffer->node); + buffer->buffSize = bufferSize; + buffer->dataSize = 0; + return buffer; +} + +int IsBufferEmpty(StreamTask *task) +{ + LoopMutexLock(&task->mutex); + int ret = ListEmpty(task->buffHead); + LoopMutexUnlock(&task->mutex); + return ret; +} + +LE_Buffer *GetFirstBuffer(StreamTask *task) +{ + LoopMutexLock(&task->mutex); + ListNode *node = task->buffHead.next; + LE_Buffer *buffer = NULL; + if (node != &task->buffHead) { + buffer = ListEntry(node, LE_Buffer, node); + } + LoopMutexUnlock(&task->mutex); + return buffer; +} + +void AddBuffer(StreamTask *task, LE_Buffer *buffer) +{ + LoopMutexLock(&task->mutex); + OH_ListAddTail(&task->buffHead, &buffer->node); + LoopMutexUnlock(&task->mutex); +} + +LE_Buffer *GetNextBuffer(StreamTask *task, const LE_Buffer *next) +{ + LoopMutexLock(&task->mutex); + LE_Buffer *buffer = NULL; + ListNode *node = NULL; + if (next == NULL) { + node = task->buffHead.next; + } else { + node = next->node.next; + } + if (node != &task->buffHead) { + buffer = ListEntry(node, LE_Buffer, node); + } + LoopMutexUnlock(&task->mutex); + return buffer; +} + +void FreeBuffer(const LoopHandle loop, StreamTask *task, LE_Buffer *buffer) +{ + LE_CHECK(buffer != NULL, return, "Invalid buffer"); + if (task == NULL) { + free(buffer); + return; + } + if (CheckTaskFlags((BaseTask *)task, TASK_STREAM | TASK_CONNECT) || + CheckTaskFlags((BaseTask *)task, TASK_EVENT | TASK_ASYNC_EVENT)) { + LoopMutexLock(&task->mutex); + OH_ListRemove(&buffer->node); + LoopMutexUnlock(&task->mutex); + } + free(buffer); +} + +BufferHandle LE_CreateBuffer(const LoopHandle loop, uint32_t bufferSize) +{ + return (BufferHandle)CreateBuffer(bufferSize); +} + +void LE_FreeBuffer(const LoopHandle loop, const TaskHandle taskHandle, const BufferHandle handle) +{ + FreeBuffer(loop, (StreamTask *)taskHandle, (LE_Buffer *)handle); +} + +uint8_t *LE_GetBufferInfo(const BufferHandle handle, uint32_t *dataSize, uint32_t *buffSize) +{ + LE_Buffer *buffer = (LE_Buffer *)handle; + LE_CHECK(buffer != NULL, return NULL, "Invalid buffer"); + if (dataSize) { + *dataSize = (uint32_t)buffer->dataSize; + } + if (buffSize) { + *buffSize = (uint32_t)buffer->buffSize; + } + return buffer->data; +} + +LE_STATUS LE_Send(const LoopHandle loopHandle, + const TaskHandle taskHandle, const BufferHandle buffHandle, uint32_t buffLen) +{ + LE_CHECK(loopHandle != NULL && buffHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(taskHandle != NULL, return LE_INVALID_TASK, "Invalid task"); + EventLoop *loop = (EventLoop *)loopHandle; + if (((BaseTask *)taskHandle)->flags & TASK_FLAGS_INVALID) { + LE_FreeBuffer(loopHandle, taskHandle, buffHandle); + return LE_INVALID_TASK; + } + LE_Buffer *buffer = (LE_Buffer *)buffHandle; + buffer->dataSize = buffLen; + if (CheckTaskFlags((BaseTask *)taskHandle, TASK_STREAM | TASK_CONNECT)) { + AddBuffer((StreamTask *)taskHandle, buffer); + } else if (CheckTaskFlags((BaseTask *)taskHandle, TASK_EVENT | TASK_ASYNC_EVENT)) { + AddBuffer((StreamTask *)taskHandle, buffer); + } + loop->modEvent(loop, (BaseTask *)taskHandle, EVENT_WRITE); + return LE_SUCCESS; +} + +void LE_CloseTask(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ + LE_CHECK(loopHandle != NULL && taskHandle != NULL, return, "Invalid parameters"); + if (((LoopBase*)taskHandle)->flags & TASK_TIME) { + LE_StopTimer(loopHandle, taskHandle); + return; + } + LE_LOGV("LE_CloseTask %d", GetSocketFd(taskHandle)); + BaseTask *task = (BaseTask *)taskHandle; + if (task->innerClose != NULL) { + task->innerClose(loopHandle, taskHandle); + } + free(task); +} + +void *LE_GetUserData(TaskHandle handle) +{ + LE_CHECK(handle != NULL, return NULL, "Invalid handle"); + BaseTask *stream = (BaseTask *)handle; + return (void *)(((char *)stream) + stream->userDataOffset); +} + +int32_t LE_GetSendResult(const BufferHandle handle) +{ + LE_CHECK(handle != NULL, return 0, "Invalid handle"); + return ((LE_Buffer *)handle)->result; +} \ No newline at end of file diff --git a/services/loopevent/task/le_task.h b/services/loopevent/task/le_task.h new file mode 100644 index 0000000000000000000000000000000000000000..6b422288d72cf4c639abe2c2b048c0c614e1b7b8 --- /dev/null +++ b/services/loopevent/task/le_task.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2021 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 LOOP_TASK_H +#define LOOP_TASK_H +#include + +#include "init_hashmap.h" +#include "le_utils.h" +#include "list.h" +#include "loop_event.h" + +#ifndef LOOP_EVENT_USE_MUTEX +#define LoopMutexInit(x) (void)(x) +#define LoopMutexLock(x) (void)(x) +#define LoopMutexUnlock(x) (void)(x) +#define LoopMutexDestroy(x) (void)(x) +#else +#include +#define LoopMutex pthread_mutex_t +#define LoopMutexInit(x) pthread_mutex_init(x, NULL) +#define LoopMutexLock(x) pthread_mutex_lock(x) +#define LoopMutexUnlock(x) pthread_mutex_unlock(x) +#define LoopMutexDestroy(x) pthread_mutex_destroy(x) +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct { + ListNode node; + uint32_t buffSize; + uint32_t dataSize; + int32_t result; + uint8_t data[0]; +} LE_Buffer; + +#define TASK_FLAGS_INVALID 0x80000000 +typedef LE_STATUS (*HandleTaskEvent)(const LoopHandle loop, const TaskHandle task, uint32_t oper); +typedef void (*HandleTaskClose)(const LoopHandle loop, const TaskHandle task); +typedef void (*DumpTaskInfo)(const TaskHandle task); +#define TASKINFO \ + uint32_t flags; \ + union { \ + int fd; \ + } taskId + +typedef struct { + TASKINFO; +} TaskId; + +typedef struct LiteTask_ { + TASKINFO; + HashNode hashNode; + LE_Close close; + DumpTaskInfo dumpTaskInfo; + HandleTaskEvent handleEvent; + HandleTaskClose innerClose; + uint16_t userDataOffset; + uint16_t userDataSize; +} BaseTask; + +typedef struct { + BaseTask base; + LE_IncommingConnect incommingConnect; + char server[0]; +} StreamServerTask; + +typedef struct { + BaseTask base; +#ifdef LOOP_EVENT_USE_MUTEX + LoopMutex mutex; +#else + char mutex; +#endif + ListHead buffHead; +} StreamTask; + +typedef struct { + StreamTask stream; + StreamServerTask *serverTask; + LE_SendMessageComplete sendMessageComplete; + LE_RecvMessage recvMessage; + LE_DisConnectComplete disConnectComplete; + LE_HandleRecvMsg handleRecvMsg; +} StreamConnectTask; + +typedef struct { + StreamTask stream; + LE_DisConnectComplete disConnectComplete; + LE_ConnectComplete connectComplete; + LE_SendMessageComplete sendMessageComplete; + LE_RecvMessage recvMessage; + LE_HandleRecvMsg handleRecvMsg; + uint32_t connected : 1; + char server[0]; +} StreamClientTask; + +typedef struct { + StreamTask stream; + LE_ProcessAsyncEvent processAsyncEvent; +} AsyncEventTask; + +typedef struct { + BaseTask base; + uint32_t events; + ProcessWatchEvent processEvent; +} WatcherTask; + +LE_Buffer *CreateBuffer(uint32_t bufferSize); +LE_Buffer *GetNextBuffer(StreamTask *task, const LE_Buffer *next); +LE_Buffer *GetFirstBuffer(StreamTask *task); +int IsBufferEmpty(StreamTask *task); + +void FreeBuffer(const LoopHandle loop, StreamTask *task, LE_Buffer *buffer); +void AddBuffer(StreamTask *task, LE_Buffer *buffer); + +BaseTask *CreateTask(const LoopHandle loopHandle, int fd, const LE_BaseInfo *info, uint32_t size); +void CloseTask(const LoopHandle loopHandle, BaseTask *task); +int GetSocketFd(const TaskHandle task); +int CheckTaskFlags(const BaseTask *task, uint32_t flags); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif diff --git a/services/loopevent/task/le_watchtask.c b/services/loopevent/task/le_watchtask.c new file mode 100644 index 0000000000000000000000000000000000000000..fff205c98952459170f02ccfc22561338c57da5d --- /dev/null +++ b/services/loopevent/task/le_watchtask.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 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 "le_task.h" +#include "le_loop.h" + +static void HandleWatcherTaskClose_(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ + LE_LOGV("HandleWatcherTaskClose_ fd: %d ", GetSocketFd(taskHandle)); + DelTask((EventLoop *)loopHandle, (BaseTask *)taskHandle); + CloseTask(loopHandle, (BaseTask *)taskHandle); +} + +static LE_STATUS HandleWatcherEvent_(const LoopHandle loopHandle, const TaskHandle taskHandle, uint32_t oper) +{ + LE_LOGV("HandleWatcherEvent_ fd: %d oper 0x%x", GetSocketFd(taskHandle), oper); + EventLoop *loop = (EventLoop *)loopHandle; + WatcherTask *watcher = (WatcherTask *)taskHandle; + int fd = GetSocketFd(taskHandle); + uint32_t events = oper; + uint64_t userData = *(uint64_t *)LE_GetUserData(taskHandle); + if (watcher->processEvent != NULL) { + watcher->processEvent(taskHandle, fd, &events, (void *)userData); + } + watcher = (WatcherTask *)GetTaskByFd((EventLoop *)loopHandle, fd); + LE_ONLY_CHECK(watcher != NULL, return 0); + if (watcher->base.flags & WATCHER_ONCE) { + HandleWatcherTaskClose_((LoopHandle)loop, (TaskHandle)watcher); + return 0; + } + if (events == 0) { + HandleWatcherTaskClose_((LoopHandle)loop, (TaskHandle)watcher); + return 0; + } + if (events != watcher->events) { + watcher->events = events; + loop->modEvent(loop, (const BaseTask *)taskHandle, watcher->events); + } + return LE_SUCCESS; +} + +static void DumpWatcherTaskInfo_(const TaskHandle task) +{ + INIT_CHECK(task != NULL, return); + BaseTask *baseTask = (BaseTask *)task; + + WatcherTask *watcherTask = (WatcherTask *)baseTask; + printf("\tfd: %d \n", watcherTask->base.taskId.fd); + printf("\t TaskType: %s \n", "WatcherTask"); +} + +LE_STATUS LE_StartWatcher(const LoopHandle loopHandle, + WatcherHandle *watcherHandle, const LE_WatchInfo *info, const void *context) +{ + LE_CHECK(loopHandle != NULL && watcherHandle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(info != NULL && info->processEvent != NULL, return LE_INVALID_PARAM, "Invuint64_talid processEvent"); + + LE_BaseInfo baseInfo = {TASK_WATCHER | (info->flags & WATCHER_ONCE), info->close, sizeof(uint64_t)}; + WatcherTask *task = (WatcherTask *)CreateTask(loopHandle, info->fd, &baseInfo, sizeof(WatcherTask)); + LE_CHECK(task != NULL, return LE_NO_MEMORY, "Failed to create task"); + task->base.handleEvent = HandleWatcherEvent_; + task->base.innerClose = HandleWatcherTaskClose_; + task->base.dumpTaskInfo = DumpWatcherTaskInfo_; + task->processEvent = info->processEvent; + task->events = info->events; + *(uint64_t *)(task + 1) = (uint64_t)context; + + EventLoop *loop = (EventLoop *)loopHandle; + loop->addEvent(loop, (const BaseTask *)task, info->events); + *watcherHandle = (WatcherHandle)task; + return LE_SUCCESS; +} + +void LE_RemoveWatcher(const LoopHandle loopHandle, const WatcherHandle watcherHandle) +{ + LE_CHECK(loopHandle != NULL && watcherHandle != NULL, return, "Invalid parameters"); + LE_CloseTask(loopHandle, watcherHandle); +} \ No newline at end of file diff --git a/services/loopevent/timer/le_timer.c b/services/loopevent/timer/le_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..cabce45d0711bc36690a07533e46933cf968e5f9 --- /dev/null +++ b/services/loopevent/timer/le_timer.c @@ -0,0 +1,190 @@ +/* + * 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 "le_timer.h" + +#include +#include + +#include "le_loop.h" +#include "le_task.h" +#include "le_utils.h" +#include "list.h" +#include "loop_event.h" + +#define TIMER_CANCELED 0x1000 +#define TIMER_PROCESSING 0x2000 + +uint64_t GetCurrentTimespec(uint64_t timeout) +{ + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + uint64_t ms = timeout; + ms += (uint64_t)start.tv_sec * LE_SEC_TO_MSEC + (uint64_t)start.tv_nsec / LE_MSEC_TO_NSEC; + return ms; +} + +static int TimerNodeCompareProc(ListNode *node, ListNode *newNode) +{ + TimerNode *timer1 = ListEntry(node, TimerNode, node); + TimerNode *timer2 = ListEntry(newNode, TimerNode, node); + if (timer1->endTime > timer2->endTime) { + return 1; + } else if (timer1->endTime == timer2->endTime) { + return 0; + } + + return -1; +} + +static void InsertTimerNode(EventLoop *loop, TimerNode *timer) +{ + timer->endTime = GetCurrentTimespec(timer->timeout); + LoopMutexLock(&timer->mutex); + timer->flags &= ~TIMER_PROCESSING; + timer->repeat--; + OH_ListAddWithOrder(&loop->timerList, &timer->node, TimerNodeCompareProc); + + LoopMutexUnlock(&timer->mutex); +} + +void CheckTimeoutOfTimer(EventLoop *loop, uint64_t currTime) +{ + const uint64_t faultTime = 10; // 10ms + ListNode timeoutList; + OH_ListInit(&timeoutList); + ListNode *node = loop->timerList.next; + while (node != &loop->timerList) { + TimerNode *timer = ListEntry(node, TimerNode, node); + if (timer->endTime > (currTime + faultTime)) { + break; + } + + LoopMutexLock(&timer->mutex); + OH_ListRemove(&timer->node); + OH_ListInit(&timer->node); + LoopMutexUnlock(&timer->mutex); + + OH_ListAddTail(&timeoutList, &timer->node); + timer->flags |= TIMER_PROCESSING; + + node = loop->timerList.next; + } + + node = timeoutList.next; + while (node != &timeoutList) { + TimerNode *timer = ListEntry(node, TimerNode, node); + + OH_ListRemove(&timer->node); + OH_ListInit(&timer->node); + timer->process((TimerHandle)timer, timer->context); + if ((timer->repeat == 0) || ((timer->flags & TIMER_CANCELED) == TIMER_CANCELED)) { + free(timer); + node = timeoutList.next; + continue; + } + + InsertTimerNode(loop, timer); + node = timeoutList.next; + } +} + +static TimerNode *CreateTimer(void) +{ + TimerNode *timer = (TimerNode *)malloc(sizeof(TimerNode)); + LE_CHECK(timer != NULL, return NULL, "Failed to create timer"); + OH_ListInit(&timer->node); + LoopMutexInit(&timer->mutex); + timer->timeout = 0; + timer->repeat = 1; + timer->flags = TASK_TIME; + + return timer; +} + +LE_STATUS LE_CreateTimer(const LoopHandle loopHandle, + TimerHandle *timer, LE_ProcessTimer processTimer, void *context) +{ + LE_CHECK(loopHandle != NULL, return LE_INVALID_PARAM, "loopHandle iS NULL"); + LE_CHECK(timer != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + LE_CHECK(processTimer != NULL, return LE_FAILURE, "Invalid parameters processTimer"); + + TimerNode *timerNode = CreateTimer(); + LE_CHECK(timerNode != NULL, return LE_FAILURE, "Failed to create timer"); + timerNode->process = processTimer; + timerNode->context = context; + *timer = (TimerHandle)timerNode; + + return LE_SUCCESS; +} + +LE_STATUS LE_StartTimer(const LoopHandle loopHandle, + const TimerHandle timer, uint64_t timeout, uint64_t repeat) +{ + LE_CHECK(loopHandle != NULL && timer != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + EventLoop *loop = (EventLoop *)loopHandle; + + TimerNode *timerNode = (TimerNode *)timer; + timerNode->timeout = timeout; + timerNode->repeat = repeat > 0 ? repeat : 1; + + InsertTimerNode(loop, timerNode); + return LE_SUCCESS; +} + +uint64_t GetMinTimeoutPeriod(const EventLoop *loop) +{ + LE_CHECK(loop != NULL, return 0, "Invalid loop"); + LE_ONLY_CHECK(loop->timerList.next != &(loop->timerList), return 0); + TimerNode *timerNode = ListEntry(loop->timerList.next, TimerNode, node); + LE_CHECK(timerNode != NULL, return 0, "Invalid timeNode"); + + return timerNode->endTime; +} + +static void TimerNodeDestroyProc(ListNode *node) +{ + TimerNode *timer = ListEntry(node, TimerNode, node); + OH_ListRemove(&timer->node); + OH_ListInit(&timer->node); + LoopMutexDestroy(timer->mutex); + free(timer); +} + +void DestroyTimerList(EventLoop *loop) +{ + OH_ListRemoveAll(&loop->timerList, TimerNodeDestroyProc); +} + +void CancelTimer(TimerHandle timerHandle) +{ + TimerNode *timer = (TimerNode *)timerHandle; + LE_CHECK(timer != NULL, return, "Invalid timer"); + + if ((timer->flags & TIMER_PROCESSING) == TIMER_PROCESSING) { + timer->flags |= TIMER_CANCELED; + return; + } + LoopMutexLock(&timer->mutex); + OH_ListRemove(&timer->node); + OH_ListInit(&timer->node); + LoopMutexUnlock(&timer->mutex); + free(timer); +} + +void LE_StopTimer(const LoopHandle loopHandle, const TimerHandle timer) +{ + CancelTimer(timer); +} \ No newline at end of file diff --git a/services/loopevent/timer/le_timer.h b/services/loopevent/timer/le_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..db236e955f251e36b8634831c2dbab50c8bcc921 --- /dev/null +++ b/services/loopevent/timer/le_timer.h @@ -0,0 +1,54 @@ +/* + * 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 LOOP_TIMER_H +#define LOOP_TIMER_H +#include +#include +#include "le_task.h" +#include "loop_event.h" +#include "le_loop.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LE_MSEC_TO_NSEC 1000000 +#define LE_SEC_TO_MSEC 1000 + +typedef struct TimeNode { + uint32_t flags; + ListNode node; +#ifdef LOOP_EVENT_USE_MUTEX + LoopMutex mutex; +#else + uint8_t mutex; +#endif + uint64_t timeout; + uint64_t repeat; + uint64_t endTime; + LE_ProcessTimer process; + void *context; +} TimerNode; + +uint64_t GetCurrentTimespec(uint64_t timeout); +void CheckTimeoutOfTimer(EventLoop *loop, uint64_t currTime); +void DestroyTimerList(EventLoop *loop); +uint64_t GetMinTimeoutPeriod(const EventLoop *loop); +void CancelTimer(TimerHandle timerHandle); +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/services/loopevent/utils/le_utils.c b/services/loopevent/utils/le_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..3b4df6accaa7548988ce2c2c112dc4b56e2f86a1 --- /dev/null +++ b/services/loopevent/utils/le_utils.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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 "le_utils.h" + +#include + +void SetNoBlock(int fd) +{ + int option = fcntl(fd, F_GETFD); + if (option < 0) { + return; + } + option = option | O_NONBLOCK | FD_CLOEXEC; + (void)fcntl(fd, F_SETFD, option); + return; +} \ No newline at end of file diff --git a/services/loopevent/utils/le_utils.h b/services/loopevent/utils/le_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..b9f96f211fd4e07a937f6e8441a4c81ec9954788 --- /dev/null +++ b/services/loopevent/utils/le_utils.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 LE_UTILS_ +#define LE_UTILS_ +#include +#include +#include + +#include "init_log.h" +#include "list.h" +#include "securec.h" + +#define LE_TEST_FLAGS(flags, flag) (((flags) & (flag)) == (flag)) +#define LE_SET_FLAGS(flags, flag) ((flags) |= (flag)) +#define LE_CLEAR_FLAGS(flags, flag) ((flags) &= ~(flag)) + +#ifndef LE_DOMAIN +#define LE_DOMAIN (BASE_DOMAIN + 4) +#endif +#define LE_LABEL "LoopEvent" +#define LE_LOGI(fmt, ...) STARTUP_LOGI(LE_DOMAIN, LE_LABEL, fmt, ##__VA_ARGS__) +#define LE_LOGE(fmt, ...) STARTUP_LOGE(LE_DOMAIN, LE_LABEL, fmt, ##__VA_ARGS__) +#define LE_LOGV(fmt, ...) STARTUP_LOGV(LE_DOMAIN, LE_LABEL, fmt, ##__VA_ARGS__) +#define LE_LOGW(fmt, ...) STARTUP_LOGW(LE_DOMAIN, LE_LABEL, fmt, ##__VA_ARGS__) + +#define LE_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + LE_LOGE(__VA_ARGS__); \ + exper; \ + } +#define LE_ONLY_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + exper; \ + } + +void SetNoBlock(int fd); +#endif \ No newline at end of file diff --git a/services/modules/BUILD.gn b/services/modules/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..4cb0dc386e52a2bb20a1a1266c3c324c66d1c979 --- /dev/null +++ b/services/modules/BUILD.gn @@ -0,0 +1,58 @@ +# Copyright (c) 2023 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/begetd.gni") +import("//build/ohos.gni") + +group("static_modules") { + if (!defined(ohos_lite)) { + deps = [ + "bootchart:libbootchart_static", + "bootevent:libbootevent_static", + "init_context:initcontext_static", + "init_eng:libiniteng_static", + "init_hook:inithook", + "reboot:libreboot_static", + "udid:libudid_static", + ] + if (build_seccomp) { + deps += [ "seccomp:libseccomp_static" ] + } + if (build_selinux) { + deps += [ "selinux:libselinuxadp_static" ] + } + if (init_use_encaps) { + deps += [ "encaps:libencaps_static" ] + } + deps += [ "trace:inittrace_cfg" ] + } +} + +group("modulesgroup") { + if (!defined(ohos_lite)) { + deps = [ + "bootchart:bootchart", + "init_context:init_context", + "init_eng:init_eng", + "reboot:rebootmodule", + "sysevent:eventmodule", + "trace:inittrace", + "udid:udidmodule", + ] + if (build_seccomp) { + deps += [ "seccomp:seccomp_filter" ] + } + if (build_selinux) { + deps += [ "selinux:selinuxadp" ] + } + } +} diff --git a/services/modules/bootchart/BUILD.gn b/services/modules/bootchart/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..ac9570a766547457d0a0eddfc09a2731a612ac99 --- /dev/null +++ b/services/modules/bootchart/BUILD.gn @@ -0,0 +1,52 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +ohos_shared_library("bootchart") { + sources = [ "bootchart.c" ] + + include_dirs = [ + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/bootchart", + "//base/startup/init/interfaces/innerkits/include/param", + ] + + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} + +config("libbootchart_static_config") { + include_dirs = [ + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/bootchart", + ] +} + +ohos_source_set("libbootchart_static") { + sources = [ "bootchart_static.c" ] + public_configs = [ ":libbootchart_static_config" ] + public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] +} diff --git a/services/modules/bootchart/bootchart.c b/services/modules/bootchart/bootchart.c new file mode 100644 index 0000000000000000000000000000000000000000..ea87d3e1d4af258e135dc7fad4cb13e6527d7fdc --- /dev/null +++ b/services/modules/bootchart/bootchart.c @@ -0,0 +1,307 @@ +/* + * 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 "bootchart.h" + +#include +#include +#include +#include +#include +#include + +#include "init_module_engine.h" +#include "init_param.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" + +#define NANO_PRE_JIFFY 10000000 +#define BOOTCHART_OUTPUT_PATH "/data/service/el0/startup/init/" + +static BootchartCtrl *g_bootchartCtrl = NULL; + +BOOTCHART_STATIC long long GetJiffies(void) +{ + struct timespec time1 = {0}; + clock_gettime(CLOCK_MONOTONIC, &time1); + long long jiffies1 = (long long)time1.tv_nsec / NANO_PRE_JIFFY; + long long jiffies2 = (long long)time1.tv_sec * (1000000000 / NANO_PRE_JIFFY); // 1000000000 to nsec + return jiffies1 + jiffies2; +} + +char *ReadFileToBuffer(const char *fileName, char *buffer, uint32_t bufferSize) +{ + PLUGIN_CHECK(buffer != NULL && fileName != NULL, return NULL, "Invalid param"); + int fd = -1; + ssize_t readLen = 0; + do { + buffer[0] = '\0'; + errno = 0; + fd = open(fileName, O_RDONLY); + if (fd > 0) { + readLen = read(fd, buffer, bufferSize - 1); + } + PLUGIN_CHECK(readLen >= 0, break, "Failed to read data for %s %d readLen %d", fileName, errno, readLen); + buffer[readLen] = '\0'; + } while (0); + if (fd != -1) { + close(fd); + } + return (readLen > 0) ? buffer : NULL; +} + +BOOTCHART_STATIC void BootchartLogHeader(void) +{ + char date[32]; // 32 data size + time_t tm = time(NULL); + PLUGIN_CHECK(tm >= 0, return, "Failed to get time"); + struct tm *now = localtime(&tm); + PLUGIN_CHECK(now != NULL, return, "Failed to get local time"); + size_t size = strftime(date, sizeof(date), "%F %T", now); + PLUGIN_CHECK(size > 0, return, "Failed to strftime"); + struct utsname uts; + if (uname(&uts) == -1) { + return; + } + + char release[PARAM_VALUE_LEN_MAX] = {}; + uint32_t len = sizeof(release); + (void)SystemReadParam("const.ohos.releasetype", release, &len); + char *cmdLine = ReadFileToBuffer("/proc/cmdline", g_bootchartCtrl->buffer, g_bootchartCtrl->bufferSize); + PLUGIN_CHECK(cmdLine != NULL, return, "Failed to open file "BOOTCHART_OUTPUT_PATH"header"); + + FILE *file = fopen(BOOTCHART_OUTPUT_PATH"header", "we"); + PLUGIN_CHECK(file != NULL, return, "Failed to open file "BOOTCHART_OUTPUT_PATH"header"); + + (void)fprintf(file, "version = openharmony init\n"); + (void)fprintf(file, "title = Boot chart for openharmony (%s)\n", date); + (void)fprintf(file, "system.uname = %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine); + if (strlen(release) > 0) { + (void)fprintf(file, "system.release = %s\n", release); + } + (void)fprintf(file, "system.cpu = %s\n", uts.machine); + (void)fprintf(file, "system.kernel.options = %s\n", cmdLine); + (void)fclose(file); +} + +BOOTCHART_STATIC void BootchartLogFile(FILE *log, const char *procfile) +{ + (void)fprintf(log, "%lld\n", GetJiffies()); + char *data = ReadFileToBuffer(procfile, g_bootchartCtrl->buffer, g_bootchartCtrl->bufferSize); + if (data != NULL) { + (void)fprintf(log, "%s\n", data); + } +} + +BOOTCHART_STATIC void BootchartLogProcessStat(FILE *log, pid_t pid) +{ + static char path[255] = { }; // 255 path length + static char nameBuffer[255] = { }; // 255 path length + int ret = sprintf_s(path, sizeof(path) - 1, "/proc/%d/cmdline", pid); + PLUGIN_CHECK(ret > 0, return, "Failed to format path %d", pid); + path[ret] = '\0'; + + char *name = ReadFileToBuffer(path, nameBuffer, sizeof(nameBuffer)); + // Read process stat line + ret = sprintf_s(path, sizeof(path) - 1, "/proc/%d/stat", pid); + PLUGIN_CHECK(ret > 0, return, "Failed to format path %d", pid); + path[ret] = '\0'; + + char *stat = ReadFileToBuffer(path, g_bootchartCtrl->buffer, g_bootchartCtrl->bufferSize); + if (stat == NULL) { + return; + } + if (name != NULL && strlen(name) > 0) { + char *end = NULL; + char *start = strstr(stat, "("); + if (start != NULL) { + end = strstr(start, ")"); + } + if (end != NULL) { + stat[start - stat + 1] = '\0'; + (void)fputs(stat, log); + (void)fputs(name, log); + (void)fputs(end, log); + } else { + (void)fputs(stat, log); + } + } else { + (void)fputs(stat, log); + } +} + +BOOTCHART_STATIC void bootchartLogProcess(FILE *log) +{ + (void)fprintf(log, "%lld\n", GetJiffies()); + DIR *pDir = opendir("/proc"); + PLUGIN_CHECK(pDir != NULL, return, "Read dir /proc failed.%d", errno); + struct dirent *entry; + while ((entry = readdir(pDir)) != NULL) { + pid_t pid = (pid_t)atoi(entry->d_name); // Only process processor + if (pid == 0) { + continue; + } + BootchartLogProcessStat(log, pid); + } + closedir(pDir); + (void)fputc('\n', log); +} + +BOOTCHART_STATIC void *BootchartThreadMain(void *data) +{ + PLUGIN_LOGI("bootcharting start"); + FILE *statFile = fopen(BOOTCHART_OUTPUT_PATH"proc_stat.log", "w"); + FILE *procFile = fopen(BOOTCHART_OUTPUT_PATH"proc_ps.log", "w"); + FILE *diskFile = fopen(BOOTCHART_OUTPUT_PATH"proc_diskstats.log", "w"); + do { + if (statFile == NULL || procFile == NULL || diskFile == NULL) { + PLUGIN_LOGE("Failed to open file"); + break; + } + BootchartLogHeader(); + while (1) { + pthread_mutex_lock(&(g_bootchartCtrl->mutex)); + struct timespec abstime = {0}; + struct timeval now = {0}; + const long timeout = 200; // wait time 200ms + gettimeofday(&now, NULL); + long nsec = now.tv_usec * 1000 + (timeout % 1000) * 1000000; // 1000 unit 1000000 unit nsec + abstime.tv_sec = now.tv_sec + nsec / 1000000000 + timeout / 1000; // 1000 unit 1000000000 unit nsec + abstime.tv_nsec = nsec % 1000000000; // 1000000000 unit nsec + pthread_cond_timedwait(&(g_bootchartCtrl->cond), &(g_bootchartCtrl->mutex), &abstime); + if (g_bootchartCtrl->stop) { + pthread_mutex_unlock(&(g_bootchartCtrl->mutex)); + break; + } + pthread_mutex_unlock(&(g_bootchartCtrl->mutex)); + PLUGIN_LOGV("bootcharting running"); + BootchartLogFile(statFile, "/proc/stat"); + BootchartLogFile(diskFile, "/proc/diskstats"); + bootchartLogProcess(procFile); + } + } while (0); + + if (statFile != NULL) { + (void)fflush(statFile); + (void)fclose(statFile); + } + if (procFile != NULL) { + (void)fflush(procFile); + (void)fclose(procFile); + } + if (diskFile != NULL) { + (void)fflush(diskFile); + (void)fclose(diskFile); + } + PLUGIN_LOGI("bootcharting stop"); + return NULL; +} + +BOOTCHART_STATIC void BootchartDestory(void) +{ + pthread_mutex_destroy(&(g_bootchartCtrl->mutex)); + pthread_cond_destroy(&(g_bootchartCtrl->cond)); + free(g_bootchartCtrl); + g_bootchartCtrl = NULL; +} + +BOOTCHART_STATIC int DoBootchartStart(void) +{ + if (g_bootchartCtrl != NULL) { + PLUGIN_LOGI("bootcharting has been start"); + return 0; + } + g_bootchartCtrl = malloc(sizeof(BootchartCtrl)); + PLUGIN_CHECK(g_bootchartCtrl != NULL, return -1, "Failed to alloc mem for bootchart"); + g_bootchartCtrl->bufferSize = DEFAULT_BUFFER; + + int ret = pthread_mutex_init(&(g_bootchartCtrl->mutex), NULL); + PLUGIN_CHECK(ret == 0, BootchartDestory(); + return -1, "Failed to init mutex"); + ret = pthread_cond_init(&(g_bootchartCtrl->cond), NULL); + PLUGIN_CHECK(ret == 0, BootchartDestory(); + return -1, "Failed to init cond"); + + g_bootchartCtrl->stop = 0; + ret = pthread_create(&(g_bootchartCtrl->threadId), NULL, BootchartThreadMain, (void *)g_bootchartCtrl); + PLUGIN_CHECK(ret == 0, BootchartDestory(); + return -1, "Failed to init cond"); + + pthread_mutex_lock(&(g_bootchartCtrl->mutex)); + pthread_cond_signal(&(g_bootchartCtrl->cond)); + pthread_mutex_unlock(&(g_bootchartCtrl->mutex)); + g_bootchartCtrl->start = 1; + return 0; +} + +BOOTCHART_STATIC int DoBootchartStop(void) +{ + if (g_bootchartCtrl == NULL || !g_bootchartCtrl->start) { + PLUGIN_LOGI("bootcharting not start"); + return 0; + } + pthread_mutex_lock(&(g_bootchartCtrl->mutex)); + g_bootchartCtrl->stop = 1; + pthread_cond_signal(&(g_bootchartCtrl->cond)); + pthread_mutex_unlock(&(g_bootchartCtrl->mutex)); + pthread_join(g_bootchartCtrl->threadId, NULL); + BootchartDestory(); + PLUGIN_LOGI("bootcharting stopped"); + return 0; +} + +BOOTCHART_STATIC int DoBootchartCmd(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_LOGI("DoBootchartCmd argc %d %s", argc, name); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + if (strcmp(argv[0], "start") == 0) { + return DoBootchartStart(); + } else if (strcmp(argv[0], "stop") == 0) { + return DoBootchartStop(); + } + return 0; +} + +static int32_t g_executorId = -1; +BOOTCHART_STATIC int BootchartInit(void) +{ + if (g_executorId == -1) { + g_executorId = AddCmdExecutor("bootchart", DoBootchartCmd); + PLUGIN_LOGI("BootchartInit executorId %d", g_executorId); + } + return 0; +} + +BOOTCHART_STATIC void BootchartExit(void) +{ + PLUGIN_LOGI("BootchartExit executorId %d", g_executorId); + if (g_executorId != -1) { + RemoveCmdExecutor("bootchart", g_executorId); + } +} + +MODULE_CONSTRUCTOR(void) +{ + PLUGIN_LOGI("DoBootchartStart now ..."); + BootchartInit(); +} + +MODULE_DESTRUCTOR(void) +{ + PLUGIN_LOGI("DoBootchartStop now ..."); + DoBootchartStop(); + BootchartExit(); +} diff --git a/services/modules/bootchart/bootchart.h b/services/modules/bootchart/bootchart.h new file mode 100644 index 0000000000000000000000000000000000000000..9bf1de23a39218f0e857942a051ab0d736a73eb3 --- /dev/null +++ b/services/modules/bootchart/bootchart.h @@ -0,0 +1,38 @@ +/* + * 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 _PLUGIN_BOOTCHART_H +#define _PLUGIN_BOOTCHART_H +#include +#include + +#define DEFAULT_BUFFER 2048 +typedef struct { + int start; + int stop; + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_t threadId; + uint32_t bufferSize; + char buffer[DEFAULT_BUFFER]; +} BootchartCtrl; + +#ifdef STARTUP_INIT_TEST +#define BOOTCHART_STATIC +#else +#define BOOTCHART_STATIC static +#endif + +#endif /* _PLUGIN_BOOTCHART_H */ diff --git a/services/modules/bootchart/bootchart_static.c b/services/modules/bootchart/bootchart_static.c new file mode 100644 index 0000000000000000000000000000000000000000..69046bf5479cab6bcb0592814cb71dd27d98022e --- /dev/null +++ b/services/modules/bootchart/bootchart_static.c @@ -0,0 +1,38 @@ +/* + * 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 "init_module_engine.h" +#include "plugin_adapter.h" + +static int bootchartEarlyHook(const HOOK_INFO *info, void *cookie) +{ + char enable[4] = {}; // 4 enable size + uint32_t size = sizeof(enable); + SystemReadParam("persist.init.bootchart.enabled", enable, &size); + if (strcmp(enable, "1") != 0) { + PLUGIN_LOGI("bootchart disabled."); + return 0; + } + + InitModuleMgrInstall("bootchart"); + PLUGIN_LOGI("bootchart enabled."); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + // Depends on parameter service + InitAddPostPersistParamLoadHook(0, bootchartEarlyHook); +} diff --git a/services/modules/bootevent/BUILD.gn b/services/modules/bootevent/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..7a11d4632f5fac082fdddfd8c68f9517fd1814e8 --- /dev/null +++ b/services/modules/bootevent/BUILD.gn @@ -0,0 +1,42 @@ +# Copyright (c) 2020-2021 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("//build/ohos.gni") + +config("bootevent_static_config") { + include_dirs = [ + "//base/startup/init/services/param/linux", + "//base/startup/init/services/init/include", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + ] +} + +ohos_source_set("libbootevent_static") { + sources = [ "bootevent.c" ] + include_dirs = [ ".." ] + public_configs = [ ":bootevent_static_config" ] + public_external_deps = [ "config_policy:configpolicy_util" ] + public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + public_external_deps += [ "bounds_checking_function:libsec_static" ] + if (build_selinux) { + include_dirs += [ "//base/startup/init/interfaces/innerkits/include/param" ] + external_deps = [ + "selinux:libselinux", + "selinux_adapter:librestorecon", + ] + defines = [ "WITH_SELINUX" ] + } +} diff --git a/services/modules/bootevent/bootevent.c b/services/modules/bootevent/bootevent.c new file mode 100755 index 0000000000000000000000000000000000000000..de455563fbe7f3f871e9ab67fd165b6709c5f070 --- /dev/null +++ b/services/modules/bootevent/bootevent.c @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2021-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 "bootevent.h" + +#include +#include "init_module_engine.h" +#include "init_group_manager.h" +#include "init_cmdexecutor.h" +#include "trigger_manager.h" +#include "init_log.h" +#include "plugin_adapter.h" +#include "init_hook.h" +#include "init_service.h" +#include "bootstage.h" +#include "securec.h" +#include "init_utils.h" +#include "init_cmds.h" +#include "config_policy_utils.h" + +#ifdef WITH_SELINUX +#include +#endif + +static int GetBootSwitchEnable(const char *paramName) +{ + char bootEventOpen[6] = ""; // 6 is length of bool value + uint32_t len = sizeof(bootEventOpen); + SystemReadParam(paramName, bootEventOpen, &len); + if (strcmp(bootEventOpen, "true") == 0 || strcmp(bootEventOpen, "1") == 0) { + return 1; + } + return 0; +} + +static int g_bootEventNum = 0; + +static bool g_isBootCompleted = false; + +static ListNode bootEventList = {&bootEventList, &bootEventList}; + +static int BootEventParaListCompareProc(ListNode *node, void *data) +{ + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node; + if (strncmp(item->paramName, BOOT_EVENT_PARA_PREFIX, BOOT_EVENT_PARA_PREFIX_LEN) != 0) { + return -1; + } + if (strcmp(item->paramName + BOOT_EVENT_PARA_PREFIX_LEN, (const char *)data) == 0) { + return 0; + } + return -1; +} + +static int ParseBooteventCompareProc(ListNode *node, void *data) +{ + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node; + if (strcmp(item->paramName, (const char *)data) == 0) { + return 0; + } + return -1; +} + +static int AddBootEventItem(BOOT_EVENT_PARAM_ITEM *item, const char *paramName) +{ + OH_ListInit(&item->node); + for (int i = 0; i < BOOTEVENT_MAX; i++) { + item->timestamp[i].tv_nsec = 0; + item->timestamp[i].tv_sec = 0; + } + item->paramName = strdup(paramName); + if (item->paramName == NULL) { + free(item); + return -1; + } + item->flags = BOOTEVENT_TYPE_SERVICE; + OH_ListAddTail(&bootEventList, (ListNode *)&item->node); + g_bootEventNum++; + return 0; +} + +static int AddBootEventItemByName(const char *paramName) +{ + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM)); + if (item == NULL) { + return -1; + } + + return AddBootEventItem(item, paramName); +} + +static void SetServiceBooteventHookMgr(const char *serviceName, const char *paramName, int state) +{ +#ifndef STARTUP_INIT_TEST + SERVICE_BOOTEVENT_CTX context; + context.serviceName = serviceName; + context.reserved = paramName; + context.state = state; + HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_BOOTEVENT, (void*)(&context), NULL); +#endif +} + + +static int AddServiceBootEvent(const char *serviceName, const char *paramName) +{ + ServiceExtData *extData = NULL; + ListNode *found = NULL; + if ((paramName == NULL) || (strncmp(paramName, BOOT_EVENT_PARA_PREFIX, BOOT_EVENT_PARA_PREFIX_LEN) != 0)) { + return -1; + } + found = OH_ListFind(&bootEventList, (void *)paramName, ParseBooteventCompareProc); + if (found != NULL) { + return -1; + } + // Find an empty bootevent data position + for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) { + extData = AddServiceExtData(serviceName, i, NULL, sizeof(BOOT_EVENT_PARAM_ITEM)); + if (extData != NULL) { + break; + } + } + + INIT_CHECK(extData != NULL, return -1); + + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)extData->data; + + if (AddBootEventItem(item, paramName) != 0) { + DelServiceExtData(serviceName, extData->dataId); + return -1; + } + + SetServiceBooteventHookMgr(serviceName, paramName, 1); + return 0; +} + +static void AddInitBootEvent(const char *bootEventName) +{ + BOOT_EVENT_PARAM_ITEM *found = NULL; + found = (BOOT_EVENT_PARAM_ITEM *)OH_ListFind(&bootEventList, (void *)bootEventName, ParseBooteventCompareProc); + if (found != NULL) { + (void)clock_gettime(CLOCK_MONOTONIC, &(found->timestamp[BOOTEVENT_READY])); + return; + } + + BOOT_EVENT_PARAM_ITEM *item = calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM)); + INIT_CHECK(item != NULL, return); + + OH_ListInit(&item->node); + + (void)clock_gettime(CLOCK_MONOTONIC, &(item->timestamp[BOOTEVENT_FORK])); + + item->paramName = strdup(bootEventName); + INIT_CHECK(item->paramName != NULL, free(item); + return); + + item->flags = BOOTEVENT_TYPE_JOB; + OH_ListAddTail(&bootEventList, (ListNode *)&item->node); + return; +} + +#define BOOT_EVENT_BOOT_COMPLETED "bootevent.boot.completed" + +static void BootEventDestroy(ListNode *node) +{ + BOOT_EVENT_PARAM_ITEM *bootEvent = (BOOT_EVENT_PARAM_ITEM *)node; + INIT_CHECK(bootEvent->paramName == NULL, free((void *)bootEvent->paramName)); + free((void *)bootEvent); +} + +static int AddItemToJson(cJSON *root, const char *name, double startTime, int pid, double durTime) +{ + cJSON *obj = cJSON_CreateObject(); // release obj at traverse done + INIT_CHECK_RETURN_VALUE(obj != NULL, -1); + cJSON_AddStringToObject(obj, "name", name); + cJSON_AddNumberToObject(obj, "ts", startTime); + cJSON_AddStringToObject(obj, "ph", "X"); + cJSON_AddNumberToObject(obj, "pid", pid); + cJSON_AddNumberToObject(obj, "tid", pid); + cJSON_AddNumberToObject(obj, "dur", durTime); + cJSON_AddItemToArray(root, obj); + return 0; +} + +static int BootEventTraversal(ListNode *node, void *root) +{ + static int start = 0; + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node; + double forkTime = (double)item->timestamp[BOOTEVENT_FORK].tv_sec * MSECTONSEC + + (double)item->timestamp[BOOTEVENT_FORK].tv_nsec / USTONSEC; + double readyTime = (double)item->timestamp[BOOTEVENT_READY].tv_sec * MSECTONSEC + + (double)item->timestamp[BOOTEVENT_READY].tv_nsec / USTONSEC; + double durTime = readyTime - forkTime; + if (item->pid == 0) { + if (durTime < SAVEINITBOOTEVENTMSEC) { + return 0; + } + item->pid = 1; // 1 is init pid + } + if (start == 0) { + // set trace start time 0 + INIT_CHECK_RETURN_VALUE(AddItemToJson((cJSON *)root, item->paramName, 0, + 1, 0) == 0, -1); + start++; + } + INIT_CHECK_RETURN_VALUE(AddItemToJson((cJSON *)root, item->paramName, forkTime, + item->pid, durTime > 0 ? durTime : 0) == 0, -1); + return 0; +} + +static int CreateBootEventFile(const char *file, mode_t mode) +{ + if (access(file, F_OK) == 0) { + INIT_LOGW("File %s already exist", file); + return 0; + } + if (errno != ENOENT) { + INIT_LOGW("Failed to access %s, err = %d", file, errno); + return -1; + } + CheckAndCreateDir(file); + int fd = open(file, O_CREAT, mode); + if (fd < 0) { + INIT_LOGE("Failed create %s, err=%d", file, errno); + return -1; + } + close(fd); +#ifdef WITH_SELINUX + INIT_LOGI("start to restorecon selinux"); + (void)RestoreconRecurse(BOOTEVENT_OUTPUT_PATH); +#endif + return 0; +} + +static int SaveServiceBootEvent() +{ + INIT_CHECK(GetBootSwitchEnable("persist.init.bootuptrace.enable"), return 0); + + int ret = CreateBootEventFile(BOOTEVENT_OUTPUT_PATH "bootup.trace", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + INIT_CHECK_RETURN_VALUE(ret == 0, -1); + FILE *tmpFile = fopen(BOOTEVENT_OUTPUT_PATH "bootup.trace", "wr"); + INIT_CHECK_RETURN_VALUE(tmpFile != NULL, -1); + cJSON *root = cJSON_CreateArray(); + INIT_CHECK(root != NULL, (void)fclose(tmpFile); + return -1); + + OH_ListTraversal(&bootEventList, (void *)root, BootEventTraversal, 0); + char *buff = cJSON_Print(root); + if (buff == NULL) { + cJSON_Delete(root); + (void)fclose(tmpFile); + return -1; + } + INIT_CHECK_ONLY_ELOG(fprintf(tmpFile, "%s\n", buff) >= 0, "save boot event file failed"); + free(buff); + cJSON_Delete(root); + (void)fflush(tmpFile); + (void)fclose(tmpFile); + return 0; +} + +static void ReportSysEvent(void) +{ + INIT_CHECK(GetBootSwitchEnable("persist.init.bootevent.enable"), return); +#ifndef STARTUP_INIT_TEST + InitModuleMgrInstall("eventmodule"); + InitModuleMgrUnInstall("eventmodule"); +#endif + return; +} + +static void BootCompleteClearAll(void) +{ + InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); + while (node != NULL) { + if (node->data.service == NULL) { + node = GetNextGroupNode(NODE_TYPE_SERVICES, node); + continue; + } + for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) { + ServiceExtData *extData = GetServiceExtData(node->name, i); + if (extData == NULL) { + return; + } + free(((BOOT_EVENT_PARAM_ITEM *)extData->data)->paramName); + OH_ListRemove(&((BOOT_EVENT_PARAM_ITEM *)extData->data)->node); + DelServiceExtData(node->name, i); + } + } + + // clear init boot event + OH_ListRemoveAll(&bootEventList, BootEventDestroy); + g_bootEventNum = 0; +} + +static void WriteBooteventSysParam(const char *paramName) +{ + char buf[64]; + long long uptime; + char name[PARAM_NAME_LEN_MAX]; + + uptime = GetUptimeInMicroSeconds(NULL); + + INIT_CHECK_ONLY_ELOG(snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime) >= 0, + "snprintf_s buf failed"); + INIT_CHECK_ONLY_ELOG(snprintf_s(name, sizeof(name), sizeof(name) - 1, "ohos.boot.time.%s", paramName) >= 0, + "snprintf_s name failed"); + SystemWriteParam(name, buf); +} + +static int BootEventParaFireByName(const char *paramName) +{ + BOOT_EVENT_PARAM_ITEM *found = NULL; + + char *bootEventValue = strrchr(paramName, '.'); + INIT_CHECK(bootEventValue != NULL, return 0); + bootEventValue[0] = '\0'; + + WriteBooteventSysParam(paramName); + + found = (BOOT_EVENT_PARAM_ITEM *)OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc); + if (found == NULL) { + return 0; + } + + // Already fired + if (found->timestamp[BOOTEVENT_READY].tv_sec > 0) { + return 0; + } + INIT_CHECK_RETURN_VALUE(clock_gettime(CLOCK_MONOTONIC, + &(found->timestamp[BOOTEVENT_READY])) == 0, 0); + + g_bootEventNum--; + SetServiceBooteventHookMgr(NULL, paramName, 2); // 2: bootevent service has ready + // Check if all boot event params are fired + if (g_bootEventNum > 0) { + return 0; + } + // All parameters are fired, set boot completed now ... + INIT_LOGI("All boot events are fired, boot complete now ..."); + SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "true"); + g_isBootCompleted = true; + SaveServiceBootEvent(); + // report complete event + ReportSysEvent(); + BootCompleteClearAll(); +#ifndef STARTUP_INIT_TEST + HookMgrExecute(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, NULL, NULL); +#endif + RemoveCmdExecutor("bootevent", -1); + return 1; +} + +#define BOOT_EVENT_FIELD_NAME "bootevents" +static void ServiceParseBootEventHook(SERVICE_PARSE_CTX *serviceParseCtx) +{ + int cnt; + cJSON *bootEvents = cJSON_GetObjectItem(serviceParseCtx->serviceNode, BOOT_EVENT_FIELD_NAME); + + // No boot events in config file + if (bootEvents == NULL) { + return; + } + SERVICE_INFO_CTX ctx = {0}; + ctx.serviceName = serviceParseCtx->serviceName; + HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL); + // Single boot event in config file + if (!cJSON_IsArray(bootEvents)) { + if (AddServiceBootEvent(serviceParseCtx->serviceName, + cJSON_GetStringValue(bootEvents)) != 0) { + INIT_LOGI("Add service bootEvent failed %s", serviceParseCtx->serviceName); + return; + } + return; + } + + // Multiple boot events in config file + cnt = cJSON_GetArraySize(bootEvents); + for (int i = 0; i < cnt; i++) { + cJSON *item = cJSON_GetArrayItem(bootEvents, i); + if (AddServiceBootEvent(serviceParseCtx->serviceName, + cJSON_GetStringValue(item)) != 0) { + INIT_LOGI("Add service bootEvent failed %s", serviceParseCtx->serviceName); + continue; + } + } +} + +static int g_finished = 0; +static int DoBootEventCmd(int id, const char *name, int argc, const char **argv) +{ + if (g_finished) { + return 0; + } + + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + if (strcmp(argv[0], "init") == 0) { + if (argc < 2) { // 2 args + return 0; + } + AddInitBootEvent(argv[1]); + } else { + // argv[0] samgr.ready.true + g_finished = BootEventParaFireByName(argv[0]); + } + return 0; +} + +static void AddReservedBooteventsByFile(const char *name) +{ + char buf[MAX_PATH_LEN]; + + FILE *file = fopen(name, "r"); + if (file == NULL) { + return; + } + + while (fgets((void *)buf, sizeof(buf) - 1, file)) { + buf[sizeof(buf) - 1] = '\0'; + char *end = strchr(buf, '\r'); + if (end != NULL) { + *end = '\0'; + } + end = strchr(buf, '\n'); + if (end != NULL) { + *end = '\0'; + } + INIT_LOGI("Got priv-app bootevent: %s", buf); + AddBootEventItemByName(buf); + } + (void)fclose(file); +} + +static void AddReservedBootevents(void) +{ + CfgFiles *files = GetCfgFiles("etc/init/priv_app.bootevents"); + for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) { + if (files->paths[i]) { + AddReservedBooteventsByFile(files->paths[i]); + } + } + FreeCfgFiles(files); +} + +static int DoUnsetBootEventCmd(int id, const char *name, int argc, const char **argv) +{ + if ((argc < 1) || (argv[0] == NULL) || (strlen(argv[0]) <= strlen(BOOT_EVENT_PARA_PREFIX)) || + (strncmp(argv[0], BOOT_EVENT_PARA_PREFIX, strlen(BOOT_EVENT_PARA_PREFIX)) != 0)) { + return INIT_EPARAMETER; + } + const char *eventName = argv[0] + strlen(BOOT_EVENT_PARA_PREFIX); + BOOT_EVENT_PARAM_ITEM *item = + (BOOT_EVENT_PARAM_ITEM *)OH_ListFind(&bootEventList, (void *)eventName, BootEventParaListCompareProc); + PLUGIN_CHECK(item != NULL, return INIT_EPARAMETER, "item NULL"); + + if (item->timestamp[BOOTEVENT_READY].tv_sec == 0) { + INIT_LOGW("%s not set", argv[0]); + return INIT_OK; + } + + SystemWriteParam(argv[0], "false"); + if (g_finished != 0) { + SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "false"); + g_isBootCompleted = false; + g_finished = 0; + } + + item->timestamp[BOOTEVENT_READY].tv_sec = 0; + g_bootEventNum++; + INIT_LOGI("UnsetBootEvent %s g_bootEventNum:%d", argv[0], g_bootEventNum); + return INIT_OK; +} + +static int ParamSetBootEventHook(const HOOK_INFO *hookInfo, void *cookie) +{ + AddReservedBootevents(); + AddCmdExecutor("bootevent", DoBootEventCmd); + AddCmdExecutor("unset_bootevent", DoUnsetBootEventCmd); + return 0; +} + +static void SetServiceBootEventFork(SERVICE_INFO_CTX *serviceCtx) +{ + BOOT_EVENT_PARAM_ITEM *item; + for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) { + ServiceExtData *extData = GetServiceExtData(serviceCtx->serviceName, i); + if (extData == NULL) { + return; + } + item = (BOOT_EVENT_PARAM_ITEM *)extData->data; + if (serviceCtx->reserved != NULL) { + item->pid = *((int *)serviceCtx->reserved); + } + INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC, + &(item->timestamp[BOOTEVENT_FORK])) == 0); + } +} + +ListNode *GetBootEventList(void) +{ + return &bootEventList; +} + +bool IsBootCompleted(void) +{ + return g_isBootCompleted; +} + +static void AddCmdBootEvent(INIT_CMD_INFO *cmdCtx) +{ + INIT_TIMING_STAT *timeStat = (INIT_TIMING_STAT *)cmdCtx->reserved; + long long diff = InitDiffTime(timeStat); + // If not time cost, just ignore + if (diff < SAVEINITBOOTEVENTMSEC) { + return; + } + BOOT_EVENT_PARAM_ITEM *item = calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM)); + if (item == NULL) { + return; + } + OH_ListInit(&item->node); + item->timestamp[BOOTEVENT_FORK] = timeStat->startTime; + item->timestamp[BOOTEVENT_READY] = timeStat->endTime; + int cmdLen = strlen(cmdCtx->cmdName) + strlen(cmdCtx->cmdContent) + 1; // 2 args 1 '\0' + item->paramName = calloc(1, cmdLen); + if (item->paramName == NULL) { + free(item); + return; + } + INIT_CHECK_ONLY_ELOG(snprintf_s(item->paramName, cmdLen, cmdLen - 1, "%s%s", + cmdCtx->cmdName, cmdCtx->cmdContent) >= 0, + "combine cmd args failed"); + item->flags = BOOTEVENT_TYPE_CMD; + OH_ListAddTail(&bootEventList, (ListNode *)&item->node); +} + +static int RecordInitCmd(const HOOK_INFO *info, void *cookie) +{ + if (cookie == NULL) { + return 0; + } + AddCmdBootEvent((INIT_CMD_INFO *)cookie); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + // Add hook to record time-cost commands + HOOK_INFO info = {INIT_CMD_RECORD, 0, RecordInitCmd, NULL}; + HookMgrAddEx(GetBootStageHookMgr(), &info); + + // Add hook to parse all services with bootevents + InitAddServiceParseHook(ServiceParseBootEventHook); + + // Add hook to record start time for services with bootevents + InitAddServiceHook(SetServiceBootEventFork, INIT_SERVICE_FORK_AFTER); + + InitAddGlobalInitHook(0, ParamSetBootEventHook); +} diff --git a/services/modules/bootevent/bootevent.h b/services/modules/bootevent/bootevent.h new file mode 100755 index 0000000000000000000000000000000000000000..3f9efdd0632522640e15c6bfd84024673862a021 --- /dev/null +++ b/services/modules/bootevent/bootevent.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 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 PLUGIN_BOOT_EVENT_H +#define PLUGIN_BOOT_EVENT_H +#include +#include "init_module_engine.h" +#include "list.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define BOOTEVENT_TYPE_CMD 1 +#define BOOTEVENT_TYPE_JOB 2 +#define BOOTEVENT_TYPE_SERVICE 3 + +#define BOOT_EVENT_PARA_PREFIX "bootevent." +#define BOOT_EVENT_PARA_PREFIX_LEN 10 +#define BOOT_EVENT_TIMESTAMP_MAX_LEN 50 +#define BOOT_EVENT_FILEPATH_MAX_LEN 60 +#define BOOT_EVENT_FINISH 2 +#define MSECTONSEC 1000000 +#define SECTONSEC 1000000000 +#define USTONSEC 1000 +#define SAVEINITBOOTEVENTMSEC 100000 +#define BOOTEVENT_OUTPUT_PATH "/data/log/startup/" + +enum { + BOOTEVENT_FORK, + BOOTEVENT_READY, + BOOTEVENT_MAX +}; + +typedef struct tagBOOT_EVENT_PARAM_ITEM { + ListNode node; + char *paramName; + int pid; + struct timespec timestamp[BOOTEVENT_MAX]; + int flags; +} BOOT_EVENT_PARAM_ITEM; + +ListNode *GetBootEventList(void); + +bool IsBootCompleted(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif /* PLUGIN_BOOT_EVENT_H */ diff --git a/services/modules/crashhandler/BUILD.gn b/services/modules/crashhandler/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9ce86ba04af727a7f5435154a522b2733f693eff --- /dev/null +++ b/services/modules/crashhandler/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2023 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/begetd.gni") +import("//build/ohos.gni") + +config("libcrashhandler_config") { + include_dirs = [ "." ] +} + +ohos_source_set("libcrashhandler") { + sources = [ "crash_handler.c" ] + include_dirs = [ + ".", + "../../../interfaces/innerkits/include", + "../../init/include", + ] + public_configs = [ ":libcrashhandler_config" ] + deps = [ "../../log:init_log" ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "libunwind:libunwind", + ] + + public_configs += [ "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/modules/crashhandler/crash_handler.c b/services/modules/crashhandler/crash_handler.c new file mode 100644 index 0000000000000000000000000000000000000000..6d5d0f4a473b04481a026587573d9a10db22a332 --- /dev/null +++ b/services/modules/crashhandler/crash_handler.c @@ -0,0 +1,86 @@ + +/* + * Copyright (c) 2021 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "beget_ext.h" +#include "securec.h" +#include "init_cmds.h" +#include "init_log.h" +#include "crash_handler.h" + +static const SignalInfo g_platformSignals[] = { + { SIGABRT, "SIGABRT" }, + { SIGBUS, "SIGBUS" }, + { SIGFPE, "SIGFPE" }, + { SIGILL, "SIGILL" }, + { SIGSEGV, "SIGSEGV" }, +#if defined(SIGSTKFLT) + { SIGSTKFLT, "SIGSTKFLT" }, +#endif + { SIGSYS, "SIGSYS" }, + { SIGTRAP, "SIGTRAP" }, +}; + +static void SignalHandler(int sig, siginfo_t *si, void *context) +{ + int32_t pid = getpid(); + if (pid == 1) { + sleep(2); + ExecReboot("panic"); + } else { + exit(-1); + } +} + +void InstallLocalSignalHandler(void) +{ + sigset_t set; + sigemptyset(&set); + struct sigaction action; + memset_s(&action, sizeof(action), 0, sizeof(action)); + action.sa_sigaction = SignalHandler; + action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; + + for (size_t i = 0; i < sizeof(g_platformSignals) / sizeof(g_platformSignals[0]); i++) { + int32_t sig = g_platformSignals[i].sigNo; + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, sig); + + sigaddset(&set, sig); + if (sigaction(sig, &action, NULL) != 0) { + BEGET_LOGE("Failed to register signal(%d)", sig); + } + } + sigprocmask(SIG_UNBLOCK, &set, NULL); +} \ No newline at end of file diff --git a/services/modules/crashhandler/crash_handler.h b/services/modules/crashhandler/crash_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..623d6f4441cd559f91075ea496ed508b0011aa79 --- /dev/null +++ b/services/modules/crashhandler/crash_handler.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 INIT_SIGNAL_HANDLER_H +#define INIT_SIGNAL_HANDLER_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SignalInfo_ { + int sigNo; + const char *name; +} SignalInfo; + +void InstallLocalSignalHandler(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/services/cmds/reboot/BUILD.gn b/services/modules/encaps/BUILD.gn old mode 100755 new mode 100644 similarity index 57% rename from services/cmds/reboot/BUILD.gn rename to services/modules/encaps/BUILD.gn index d7bd52bcc1301898538e9a0dda36098bc5e07cde..321a742e55d0cd3ffab441156664852ce1664bae --- a/services/cmds/reboot/BUILD.gn +++ b/services/modules/encaps/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Huawei Device Co., Ltd. +# 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 @@ -13,14 +13,24 @@ import("//build/ohos.gni") -ohos_executable("reboot") { - sources = [ "init_cmd_reboot.c" ] - include_dirs = [ - "//base/startup/init_lite/interfaces/innerkits/include", - "//base/startup/init_lite/services/include/param/", - "//third_party/bounds_checking_function/include", +config("libencaps_static_config") { + include_dirs = [ ".." ] +} + +ohos_source_set("libencaps_static") { + sources = [ "encaps_static.c" ] + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + public_configs = [ + ":libencaps_static_config", + "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config", ] - deps = [ "//base/startup/init_lite/interfaces/innerkits/reboot:libreboot" ] - install_enable = true + part_name = "init" + subsystem_name = "startup" } diff --git a/services/modules/encaps/encaps_static.c b/services/modules/encaps/encaps_static.c new file mode 100644 index 0000000000000000000000000000000000000000..7988bc61bd8056fd0b87c17ffa3218fa12a8037d --- /dev/null +++ b/services/modules/encaps/encaps_static.c @@ -0,0 +1,65 @@ +/* + * 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 +#include +#include +#include +#include "bootstage.h" +#include "init_log.h" +#include "init_module_engine.h" + +#define SA_MAIN_PATH ("/system/bin/sa_main") + +#define OH_ENCAPS_PROC_TYPE_BASE 0x18 +#define OH_ENCAPS_MAGIC 'E' +#define OH_PROC_SYS 3 +#define SET_PROC_TYPE_CMD _IOW(OH_ENCAPS_MAGIC, OH_ENCAPS_PROC_TYPE_BASE, uint32_t) + +static void SetEncapsFlag(uint32_t flag) +{ + int fd = 0; + int ret = 0; + + fd = open("/dev/encaps", O_RDWR); + if (fd < 0) { + INIT_LOGI("SetEncapsFlag open failed, maybe this device is not supported"); + return; + } + + ret = ioctl(fd, SET_PROC_TYPE_CMD, &flag); + if (ret != 0) { + close(fd); + INIT_LOGE("SetEncapsFlag ioctl failed"); + return; + } + + close(fd); +} + +static void SetEncapsProcType(SERVICE_INFO_CTX *serviceCtx) +{ + if (serviceCtx->reserved == NULL) { + return; + } + if (strncmp(SA_MAIN_PATH, serviceCtx->reserved, strlen(SA_MAIN_PATH)) == 0) { + SetEncapsFlag(OH_PROC_SYS); + } +} + +MODULE_CONSTRUCTOR(void) +{ + // Add hook to set encaps flag + InitAddServiceHook(SetEncapsProcType, INIT_SERVICE_SET_PERMS_BEFORE); +} diff --git a/services/modules/init_context/BUILD.gn b/services/modules/init_context/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..17ad61a8f3a9836641d4489f8b55e87c20bbf0df --- /dev/null +++ b/services/modules/init_context/BUILD.gn @@ -0,0 +1,73 @@ +# Copyright (c) 2023 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/begetd.gni") +import("//build/ohos.gni") + +comm_include = [ + ".", + "..", + "../../init/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", +] + +ohos_shared_library("init_context") { + sources = [ "init_context.c" ] + + include_dirs = comm_include + + include_dirs += [ "../../init/include" ] + + external_deps = [] + + defines = [ "INIT_SUPPORT_CHIPSET_INIT" ] + if (build_selinux) { + external_deps += [ + "selinux_adapter:libload_policy", + "selinux_adapter:librestorecon", + ] + defines += [ "WITH_SELINUX" ] + } + + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + + external_deps += [ + "bounds_checking_function:libsec_shared", + "selinux:libselinux", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} + +config("initcontext_static_config") { + include_dirs = comm_include +} + +ohos_source_set("initcontext_static") { + sources = [ "init_context_static.c" ] + include_dirs = comm_include + defines = [ "INIT_SUPPORT_CHIPSET_INIT" ] + public_configs = [ ":initcontext_static_config" ] + public_configs += [ "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + external_deps = [ "bounds_checking_function:libsec_shared" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/modules/init_context/init_context.c b/services/modules/init_context/init_context.c new file mode 100644 index 0000000000000000000000000000000000000000..99ee93d3f52e78e720f3fa45f4b3a6efbc0fb2fa --- /dev/null +++ b/services/modules/init_context/init_context.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2023 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 "init_context.h" + +#include +#ifdef WITH_SELINUX +#include +#include +#endif +#include +#include +#include +#include + +#include "init_module_engine.h" +#include "plugin_adapter.h" +#include "init_cmds.h" +#include "init_utils.h" +#include "securec.h" + +#ifdef STARTUP_INIT_TEST +#define TIMEOUT_DEF 2 +#else +#define TIMEOUT_DEF 5 +#endif + +static SubInitInfo g_subInitInfo[INIT_CONTEXT_MAIN] = {}; +static const char *g_subContext[INIT_CONTEXT_MAIN] = { + "u:r:chipset_init:s0" +}; + +static void SubInitMain(InitContextType type, int readFd, int writeFd); +static void HandleRecvMessage(SubInitInfo *subInfo, char *buffer, uint32_t size); +static int CreateSocketPair(int socket[2]); +static int SubInitSetSelinuxContext(InitContextType type); + +static int SubInitRun(const SubInitForkArg *arg) +{ + PLUGIN_LOGW("SubInitRun %d ", arg->type); + SubInitSetSelinuxContext(arg->type); +#ifndef STARTUP_INIT_TEST + close(arg->socket[0]); +#endif + SubInitMain(arg->type, arg->socket[1], arg->socket[1]); + close(arg->socket[1]); +#ifndef STARTUP_INIT_TEST + _exit(PROCESS_EXIT_CODE); +#else + return 0; +#endif +} + +#ifndef STARTUP_INIT_TEST +pid_t SubInitFork(int (*childFunc)(const SubInitForkArg *arg), const SubInitForkArg *args) +{ + pid_t pid = fork(); + if (pid == 0) { + childFunc(args); + } + return pid; +} +#endif + +static int SubInitStart(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + SubInitInfo *subInfo = &g_subInitInfo[type]; + if (subInfo->state != SUB_INIT_STATE_IDLE) { + return 0; + } + SubInitForkArg arg = { 0 }; + arg.type = type; + int ret = CreateSocketPair(arg.socket); + PLUGIN_CHECK(ret == 0, return -1, "Failed to create socket for %d", type); + + subInfo->state = SUB_INIT_STATE_STARTING; + pid_t pid = SubInitFork(SubInitRun, &arg); + if (pid < 0) { + close(arg.socket[0]); + close(arg.socket[1]); + subInfo->state = SUB_INIT_STATE_IDLE; + return -1; + } +#ifndef STARTUP_INIT_TEST + close(arg.socket[1]); +#endif + subInfo->sendFd = arg.socket[0]; + subInfo->recvFd = arg.socket[0]; + subInfo->state = SUB_INIT_STATE_RUNNING; + subInfo->subPid = pid; + return 0; +} + +static void SubInitStop(pid_t pid) +{ + for (size_t i = 0; i < ARRAY_LENGTH(g_subInitInfo); i++) { + if (g_subInitInfo[i].subPid == pid) { + close(g_subInitInfo[i].sendFd); + g_subInitInfo[i].subPid = 0; + g_subInitInfo[i].state = SUB_INIT_STATE_IDLE; + } + } +} + +static int SubInitExecuteCmd(InitContextType type, const char *name, const char *cmdContent) +{ + static char buffer[MAX_CMD_LEN] = {0}; + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + PLUGIN_CHECK(name != NULL, return -1, "Invalid cmd name"); + SubInitInfo *subInfo = &g_subInitInfo[type]; + PLUGIN_CHECK(subInfo->state == SUB_INIT_STATE_RUNNING, return -1, "Sub init %d is not running ", type); + + int len = 0; + if (cmdContent != NULL) { + len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%s %s", name, cmdContent); + } else { + len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%s ", name); + } + PLUGIN_CHECK(len > 0, return -1, "Failed to format cmd %s", name); + buffer[len] = '\0'; + PLUGIN_LOGV("send cmd '%s'", buffer); + int ret = send(subInfo->sendFd, buffer, len, 0); + if (ret < 0 && errno == EPIPE) { + PLUGIN_LOGI("Failed to send cmd %s to %d, need fork new chip init process", name, subInfo->type); + SubInitStop(subInfo->subPid); + SubInitStart(type); + ret = send(subInfo->sendFd, buffer, len, 0); + } + PLUGIN_CHECK(ret > 0, return errno, "Failed to send cmd %s to %d errno %d", name, subInfo->type, errno); + + // block and wait result + ssize_t rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, sizeof(buffer))); + while ((rLen < 0) && (errno == EAGAIN)) { + rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, sizeof(buffer))); + } + PLUGIN_CHECK(rLen >= 0 && (size_t)rLen < sizeof(buffer), return errno, + "Failed to read result from %d for cmd %s errno %d", subInfo->type, name, errno); + // change to result + buffer[rLen] = '\0'; + PLUGIN_LOGV("recv cmd result %s", buffer); + return atoi(buffer); +} + +static int CreateSocketPair(int socket[2]) +{ + int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, socket); + PLUGIN_CHECK(ret == 0, return -1, "Create socket fail errno %d", errno); + + int opt = 1; + struct timeval timeout = {TIMEOUT_DEF, 0}; + do { + ret = setsockopt(socket[0], SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); + PLUGIN_CHECK(ret == 0, break, "Failed to set opt for %d errno %d", socket[0], errno); + ret = setsockopt(socket[1], SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + PLUGIN_CHECK(ret == 0, break, "Failed to set opt for %d errno %d", socket[1], errno); + ret = setsockopt(socket[0], SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + PLUGIN_CHECK(ret == 0, break, "Failed to set opt for %d errno %d", socket[0], errno); + } while (0); + if (ret != 0) { + close(socket[0]); + close(socket[1]); + } + return ret; +} + +static int CheckSocketPermission(const SubInitInfo *subInfo) +{ + struct ucred uc = {-1, -1, -1}; + socklen_t len = sizeof(uc); + // Only root is permitted to use control fd of init. + if (getsockopt(subInfo->recvFd, SOL_SOCKET, SO_PEERCRED, &uc, &len) < 0 || uc.uid != 0) { + INIT_LOGE("Failed to get socket option. err = %d", errno); + errno = EPERM; + return -1; + } + return 0; +} + +static int HandleRecvMessage_(SubInitInfo *subInfo, char *buffer, uint32_t size) +{ + if (CheckSocketPermission(subInfo) != 0) { + return -1; + } + ssize_t rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, size)); + while ((rLen < 0) && (errno == EAGAIN)) { + rLen = TEMP_FAILURE_RETRY(read(subInfo->recvFd, buffer, size)); + } + PLUGIN_CHECK(rLen >= 0 && rLen < size, return errno, + "Read message for %d fail errno %d rLen %d", subInfo->type, errno, rLen); + buffer[rLen] = '\0'; + PLUGIN_LOGI("Exec cmd '%s' in sub init %s", buffer, g_subContext[subInfo->type]); + int index = 0; + const char *cmd = GetMatchCmd(buffer, &index); + PLUGIN_CHECK(cmd != NULL, return -1, "Can not find cmd %s", buffer); + DoCmdByIndex(index, buffer + strlen(cmd) + 1, NULL); + return 0; +} + +static void HandleRecvMessage(SubInitInfo *subInfo, char *buffer, uint32_t size) +{ + int ret = HandleRecvMessage_(subInfo, buffer, size); + int len = snprintf_s(buffer, size, size - 1, "%d", ret); + PLUGIN_CHECK(len > 0, return, "Failed to format result %d", ret); + buffer[len] = '\0'; + ret = send(subInfo->sendFd, buffer, len, 0); + PLUGIN_CHECK(ret > 0, return, "Failed to send result to %d errno %d", subInfo->type, errno); +} + +static void SubInitMain(InitContextType type, int readFd, int writeFd) +{ + PLUGIN_LOGI("SubInitMain, sub init %s[%d] enter", g_subContext[type], getpid()); +#ifndef STARTUP_INIT_TEST + (void)prctl(PR_SET_NAME, "chipset_init"); + const int timeout = 30000; // 30000 30s +#else + const int timeout = 1000; // 1000 1s +#endif + char buffer[MAX_CMD_LEN] = {0}; + struct pollfd pfd = {}; + pfd.events = POLLIN; + pfd.fd = readFd; + SubInitInfo subInfo = {}; + subInfo.type = type; + subInfo.recvFd = readFd; + subInfo.sendFd = writeFd; + while (1) { + pfd.revents = 0; + int ret = poll(&pfd, 1, timeout); + if (ret == 0) { + PLUGIN_LOGI("Poll sub init timeout, sub init %d exit", type); + return; + } else if (ret < 0) { + PLUGIN_LOGE("Failed to poll sub init socket!"); + return; + } + if ((unsigned int)pfd.revents & POLLIN) { + HandleRecvMessage(&subInfo, buffer, sizeof(buffer)); + } + } +} + +static int SubInitSetSelinuxContext(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); +#ifdef INIT_SUPPORT_CHIPSET_INIT +#ifdef WITH_SELINUX + setcon(g_subContext[type]); +#endif +#endif + return 0; +} + +#ifdef STARTUP_INIT_TEST +SubInitInfo *GetSubInitInfo(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return NULL, "Invalid type %d", type); + return &g_subInitInfo[type]; +} +#endif + +MODULE_CONSTRUCTOR(void) +{ + for (size_t i = 0; i < ARRAY_LENGTH(g_subContext); i++) { + SubInitContext context = { + (InitContextType)i, + SubInitStart, + SubInitStop, + SubInitExecuteCmd, + SubInitSetSelinuxContext + }; + InitSubInitContext((InitContextType)i, &context); + } +} diff --git a/services/modules/init_context/init_context.h b/services/modules/init_context/init_context.h new file mode 100644 index 0000000000000000000000000000000000000000..3dd13c8603c1fc12d2daa212a39ffee54fe336cd --- /dev/null +++ b/services/modules/init_context/init_context.h @@ -0,0 +1,69 @@ +/* + * 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 STARTUP_INIT_CONTEXT +#define STARTUP_INIT_CONTEXT +#include +#include +#include + +#include "init_cmds.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MAX_CMD_LEN 512 +typedef enum { + SUB_INIT_STATE_IDLE, + SUB_INIT_STATE_STARTING, + SUB_INIT_STATE_RUNNING +} SubInitState; + +typedef struct { + InitContextType type; + int sendFd; + int recvFd; + pid_t subPid; + SubInitState state; +} SubInitInfo; + +typedef struct { + InitContextType type; + int (*startSubInit)(InitContextType type); + void (*stopSubInit)(pid_t pid); + int (*executeCmdInSubInit)(InitContextType type, const char *, const char *); + int (*setSubInitContext)(InitContextType type); +} SubInitContext; + +int StartSubInit(InitContextType type); +int InitSubInitContext(InitContextType type, const SubInitContext *context); +#ifdef STARTUP_INIT_TEST +SubInitInfo *GetSubInitInfo(InitContextType type); +#endif + +typedef struct { + int socket[2]; + InitContextType type; +} SubInitForkArg; +pid_t SubInitFork(int (*childFunc)(const SubInitForkArg *arg), const SubInitForkArg *args); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/services/modules/init_context/init_context_static.c b/services/modules/init_context/init_context_static.c new file mode 100644 index 0000000000000000000000000000000000000000..82bf664b535b31649188f9c6612dcdd563cf0c41 --- /dev/null +++ b/services/modules/init_context/init_context_static.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023 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 "init_context.h" + +#include "init_module_engine.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" + +static SubInitContext g_subInitContext[INIT_CONTEXT_MAIN] = { 0 }; +static ConfigContext g_currContext = { INIT_CONTEXT_MAIN }; +static int g_subInitRunning = 0; + +int InitSubInitContext(InitContextType type, const SubInitContext *context) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + PLUGIN_CHECK(context != NULL, return -1, "Invalid context %d", type); + g_subInitContext[type].type = type; + g_subInitContext[type].startSubInit = context->startSubInit; + g_subInitContext[type].stopSubInit = context->stopSubInit; + g_subInitContext[type].executeCmdInSubInit = context->executeCmdInSubInit; + g_subInitContext[type].setSubInitContext = context->setSubInitContext; + return 0; +} + +void StopSubInit(pid_t pid) +{ + if (g_subInitContext[0].stopSubInit != NULL) { + g_subInitContext[0].stopSubInit(pid); + } +} + +int StartSubInit(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", type); + if (!g_subInitRunning) { + // install init context +#ifndef STARTUP_INIT_TEST + InitModuleMgrInstall("init_context"); +#endif + } + PLUGIN_CHECK(g_subInitContext[type].startSubInit != NULL, return -1, "Invalid context %d", type); + g_subInitRunning = 1; + return g_subInitContext[type].startSubInit(type); +} + +int ExecuteCmdInSubInit(const ConfigContext *context, const char *name, const char *cmdContent) +{ + PLUGIN_CHECK(context != NULL, return -1, "Invalid context"); + PLUGIN_CHECK(name != NULL, return -1, "Invalid name"); + PLUGIN_CHECK(context->type < INIT_CONTEXT_MAIN, return -1, "Invalid type %d", context->type); + PLUGIN_LOGV("Execute command '%s %s' in context %d", name, cmdContent, context->type); + StartSubInit(context->type); + PLUGIN_CHECK(g_subInitContext[context->type].executeCmdInSubInit != NULL, + return -1, "Invalid context %d", context->type); + return g_subInitContext[context->type].executeCmdInSubInit(context->type, name, cmdContent); +} + +int SetSubInitContext(const ConfigContext *context, const char *service) +{ + if (InUpdaterMode() == 1) { // not support sub init in update mode + return 0; + } + PLUGIN_CHECK(context != NULL, return -1, "Invalid context"); + if (context->type >= INIT_CONTEXT_MAIN) { + g_currContext.type = INIT_CONTEXT_MAIN; + return 0; + } + g_currContext.type = context->type; + PLUGIN_CHECK(g_subInitContext[context->type].setSubInitContext != NULL, + return -1, "Invalid context %d", context->type); + PLUGIN_LOGI("Set selinux context %d for %s", context->type, service); + return g_subInitContext[context->type].setSubInitContext(context->type); +} + +int CheckExecuteInSubInit(const ConfigContext *context) +{ + if (InUpdaterMode() == 1) { // not support sub init in update mode + return 0; + } +#ifdef INIT_SUPPORT_CHIPSET_INIT + return !(context == NULL || context->type == INIT_CONTEXT_MAIN || g_currContext.type != INIT_CONTEXT_MAIN); +#else + return 0; +#endif +} + +#ifdef STARTUP_INIT_TEST +SubInitContext *GetSubInitContext(InitContextType type) +{ + PLUGIN_CHECK(type < INIT_CONTEXT_MAIN, return NULL, "Invalid type %d", type); + return &g_subInitContext[type]; +} +#endif diff --git a/services/modules/init_eng/BUILD.gn b/services/modules/init_eng/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..57be0e6ae384f5d3c8aa1537b76aaed4adc41e75 --- /dev/null +++ b/services/modules/init_eng/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2023 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/begetd.gni") +import("//build/ohos.gni") + +comm_include = [ + ".", + "..", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", +] + +ohos_shared_library("init_eng") { + sources = [ "init_eng.c" ] + + include_dirs = comm_include + + include_dirs += [ "../../init/include" ] + + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + + external_deps = [ "bounds_checking_function:libsec_shared" ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} + +config("initeng_static_config") { + include_dirs = comm_include +} + +ohos_source_set("libiniteng_static") { + sources = [ "init_eng_static.c" ] + include_dirs = comm_include + public_configs = [ ":initeng_static_config" ] + public_configs += [ "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/modules/init_eng/init_eng.c b/services/modules/init_eng/init_eng.c new file mode 100644 index 0000000000000000000000000000000000000000..974198bb71fcfe1caae3803198138bbd2319efd3 --- /dev/null +++ b/services/modules/init_eng/init_eng.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2023 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 "init_eng.h" + +#include +#include +#include + +#include "plugin_adapter.h" +#include "init_cmds.h" +#include "init_utils.h" +#include "init_module_engine.h" +#include "securec.h" + +#define ENG_SYSTEM_DEVICE_PATH "/dev/block/by-name/eng_system" +#define ENG_CHIPSET_DEVICE_PATH "/dev/block/by-name/eng_chipset" + +ENG_STATIC bool IsFileExistWithType(const char *file, FileType type) +{ + bool isExist = false; + struct stat st = {}; + if (lstat(file, &st) == 0) { + switch (type) { + case TYPE_DIR: + if (S_ISDIR(st.st_mode)) { + isExist = true; + } + break; + case TYPE_REG: + if (S_ISREG(st.st_mode)) { + isExist = true; + } + break; + case TYPE_LINK: + if (S_ISLNK(st.st_mode)) { + isExist = true; + } + break; + case TYPE_ANY: // fallthrough + default: + isExist = true; + break; + } + } + return isExist; +} + +static bool IsRegularFile(const char *file) +{ + return file == NULL ? false : IsFileExistWithType(file, TYPE_REG); +} + +static bool IsExistFile(const char *file) +{ + return file == NULL ? false : IsFileExistWithType(file, TYPE_ANY); +} + +ENG_STATIC void BuildMountCmd(char *buffer, size_t len, const char *mp, const char *dev, const char *fstype) +{ + int ret = snprintf_s(buffer, len, len - 1, "%s %s %s ro barrier=1", + fstype, dev, mp); + if (ret == -1) { + *buffer = '\0'; + } +} + +ENG_STATIC void MountEngPartitions(void) +{ + char mountCmd[MOUNT_CMD_MAX_LEN] = {}; + // Mount eng_system + BuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng_system", + "/dev/block/by-name/eng_system", "ext4"); + WaitForFile(ENG_SYSTEM_DEVICE_PATH, WAIT_MAX_SECOND); + int cmdIndex = 0; + (void)GetMatchCmd("mount ", &cmdIndex); + DoCmdByIndex(cmdIndex, mountCmd, NULL); + + // Mount eng_chipset + BuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng_chipset", + "/dev/block/by-name/eng_chipset", "ext4"); + WaitForFile(ENG_CHIPSET_DEVICE_PATH, WAIT_MAX_SECOND); + DoCmdByIndex(cmdIndex, mountCmd, NULL); +} + +ENG_STATIC void BindMountFile(const char *source, const char *target) +{ + char targetFullPath[PATH_MAX] = {}; + const char *p = source; + char *q = NULL; + const char *end = source + strlen(source); + + if (*p != '/') { // source must start with '/' + return; + } + + // Get next '/' + q = strchr(p + 1, '/'); + if (q == NULL) { + PLUGIN_LOGI("path \' %s \' without extra slash, ignore it", source); + return; + } + + if (*(end - 1) == '/') { + PLUGIN_LOGI("path \' %s \' ends with slash, ignore it", source); + return; + } + // OK, now get sub dir and combine it with target + int ret = snprintf_s(targetFullPath, PATH_MAX, PATH_MAX - 1, "%s%s", strcmp(target, "/") == 0 ? "" : target, q); + if (ret == -1) { + PLUGIN_LOGE("Failed to build target path"); + return; + } + PLUGIN_LOGI("target full path is %s", targetFullPath); + if (IsRegularFile(targetFullPath)) { + if (mount(source, targetFullPath, NULL, MS_BIND, NULL) != 0) { + PLUGIN_LOGE("Failed to bind mount %s to %s, err = %d", source, targetFullPath, errno); + } else { + PLUGIN_LOGI("Bind mount %s to %s done", source, targetFullPath); + } + } else { + if (!IsExistFile(targetFullPath)) { + if (symlink(source, targetFullPath) < 0) { + PLUGIN_LOGE("Failed to link %s to %s, err = %d", source, targetFullPath, errno); + } + } else { + PLUGIN_LOGW("%s without expected type, skip overlay", targetFullPath); + } + } +} + +ENG_STATIC void DebugFilesOverlay(const char *source, const char *target) +{ + DIR *dir = NULL; + struct dirent *de = NULL; + + if ((dir = opendir(source)) == NULL) { + PLUGIN_LOGE("Open path \' %s \' failed. err = %d", source, errno); + return; + } + int dfd = dirfd(dir); + char srcPath[PATH_MAX] = {}; + while ((de = readdir(dir)) != NULL) { + if (de->d_name[0] == '.') { + continue; + } + if (snprintf_s(srcPath, PATH_MAX, PATH_MAX - 1, "%s/%s", source, de->d_name) == -1) { + PLUGIN_LOGE("Failed to build path for overlaying"); + break; + } + + // Determine file type + struct stat st = {}; + if (fstatat(dfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + continue; + } + if (S_ISDIR(st.st_mode)) { + DebugFilesOverlay(srcPath, target); + } else if (S_ISREG(st.st_mode)) { + BindMountFile(srcPath, target); + } else { // Ignore any other file types + PLUGIN_LOGI("Ignore %s while overlaying", srcPath); + } + } + closedir(dir); + dir = NULL; +} + +ENG_STATIC void EngineerOverlay(void) +{ + PLUGIN_LOGI("system overlay..."); + DebugFilesOverlay("/eng_system", "/"); + PLUGIN_LOGI("vendor overlay..."); + DebugFilesOverlay("/eng_chipset", "/chipset"); +} + +MODULE_CONSTRUCTOR(void) +{ + PLUGIN_LOGI("Start eng mode now ..."); + MountEngPartitions(); + EngineerOverlay(); +} diff --git a/services/modules/init_eng/init_eng.h b/services/modules/init_eng/init_eng.h new file mode 100644 index 0000000000000000000000000000000000000000..4a5ea6f702da37631648dc97533e935c4d20d0c0 --- /dev/null +++ b/services/modules/init_eng/init_eng.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 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 _PLUGIN_INITENG_H +#define _PLUGIN_INITENG_H + +typedef enum { + TYPE_DIR = 0, + TYPE_REG, + TYPE_LINK, + TYPE_ANY +} FileType; + +#define MOUNT_CMD_MAX_LEN 128U + +#ifdef STARTUP_INIT_TEST +#define ENG_STATIC +#else +#define ENG_STATIC static +#endif + +#endif /* _PLUGIN_INITENG_H */ diff --git a/services/modules/init_eng/init_eng_static.c b/services/modules/init_eng/init_eng_static.c new file mode 100644 index 0000000000000000000000000000000000000000..b5c084f41963e490bae5e5d4fdd7b8d979d5ef45 --- /dev/null +++ b/services/modules/init_eng/init_eng_static.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 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 "init_module_engine.h" +#include "plugin_adapter.h" +#include "init_utils.h" + +static int InitEngEarlyHook(const HOOK_INFO *info, void *cookie) +{ + char value[MAX_BUFFER_LEN] = {0}; + int ret = GetParameterFromCmdLine("ohos.boot.root_package", value, MAX_BUFFER_LEN); + if (ret == 0 && strcmp(value, "on") == 0) { +#ifndef STARTUP_INIT_TEST + InitModuleMgrInstall("init_eng"); + InitModuleMgrUnInstall("init_eng"); +#endif + PLUGIN_LOGI("eng_mode enable."); + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + InitAddGlobalInitHook(0, InitEngEarlyHook); +} diff --git a/services/modules/init_hook/BUILD.gn b/services/modules/init_hook/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..a1272307621214075a6f7bbfe7b4b376c0f46711 --- /dev/null +++ b/services/modules/init_hook/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("//build/ohos.gni") + +config("inithook_config") { + include_dirs = [ "//base/startup/init/services/modules/init_hook" ] +} +comm_include = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/init/include", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", +] +if (defined(ohos_lite)) { + static_library("inithook") { + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + ] + include_dirs = comm_include + include_dirs += [ + "//base/hiviewdfx/hilog_lite/interfaces/native/kits", + "//third_party/cJSON", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + sources = [ "param_hook.c" ] + public_configs = [ ":inithook_config" ] + } +} else { + ohos_source_set("inithook") { + defines = [ + "_GNU_SOURCE", + "PARAM_SUPPORT_TRIGGER", + ] + include_dirs = comm_include + sources = [ + "init_hook.c", + "param_hook.c", + ] + public_external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ "cJSON:cjson" ] + if (build_selinux) { + public_external_deps += [ + "selinux:libselinux", + "selinux_adapter:libselinux_parameter_static", + ] + defines += [ "WITH_SELINUX" ] + } + public_configs = [ ":inithook_config" ] + public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + } +} diff --git a/services/modules/init_hook/init_hook.c b/services/modules/init_hook/init_hook.c new file mode 100755 index 0000000000000000000000000000000000000000..abf3513078fbebd75bcda5609b681afcc98592c8 --- /dev/null +++ b/services/modules/init_hook/init_hook.c @@ -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 "init_hook.h" +#include "init_service.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" +#include "init_module_engine.h" +#include "init_group_manager.h" +#include "init_param.h" +#include "hookmgr.h" +#include "bootstage.h" + +static int ServiceExtDataCompareProc(ListNode *node, void *data) +{ + ServiceExtData *item = ListEntry(node, ServiceExtData, node); + if (item->dataId == *(uint32_t *)data) { + return 0; + } + return -1; +} + +static ServiceExtData *GetServiceExtData_(Service *service, uint32_t id) +{ + ListNode *node = OH_ListFind(&service->extDataNode, (void *)&id, ServiceExtDataCompareProc); + return (ServiceExtData *)node; +} + +ServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen) +{ + Service *service = GetServiceByName(serviceName); + PLUGIN_CHECK(service != NULL, return NULL, "Can not find service for %s", serviceName); + ServiceExtData *extData = GetServiceExtData_(service, id); + if (extData != NULL) { + return NULL; + } + extData = calloc(1, sizeof(ServiceExtData) + dataLen); + PLUGIN_CHECK(extData != NULL, return NULL, "Can not alloc extData for %d", id); + OH_ListInit(&extData->node); + extData->dataId = id; + if (data != NULL) { + int ret = memcpy_s(extData->data, dataLen, data, dataLen); + if (ret == 0) { + OH_ListAddTail(&service->extDataNode, &extData->node); + return extData; + } + } else { + OH_ListAddTail(&service->extDataNode, &extData->node); + return extData; + } + free(extData); + return NULL; +} + +void DelServiceExtData(const char *serviceName, uint32_t id) +{ + Service *service = GetServiceByName(serviceName); + PLUGIN_CHECK(service != NULL, return, "Can not find service for %s", serviceName); + ServiceExtData *extData = GetServiceExtData_(service, id); + if (extData == NULL) { + return; + } + OH_ListRemove(&extData->node); + free(extData); +} + +ServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id) +{ + Service *service = GetServiceByName(serviceName); + PLUGIN_CHECK (service != NULL, return NULL, "Can not find service for %s", serviceName); + return GetServiceExtData_(service, id); +} + +static int JobParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + JOB_PARSE_CTX *jobParseContext = (JOB_PARSE_CTX *)executionContext; + JobParseHook realHook = (JobParseHook)hookInfo->hookCookie; + realHook(jobParseContext); + return 0; +}; + +int InitAddJobParseHook(JobParseHook hook) +{ + HOOK_INFO info; + info.stage = INIT_JOB_PARSE; + info.prio = 0; + info.hook = JobParseHookWrapper; + info.hookCookie = (void *)hook; + + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +static void SetLogLevelFunc(const char *value) +{ + unsigned int level; + int ret = StringToUint(value, &level); + PLUGIN_CHECK(ret == 0, return, "Failed make %s to unsigned int", value); + PLUGIN_LOGI("Set log level is %d", level); + SetInitLogLevel(level); +} + +static int CmdSetLogLevel(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + UNUSED(name); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid input args"); + const char *value = strrchr(argv[0], '.'); + PLUGIN_CHECK(value != NULL, return -1, "Failed get \'.\' from string %s", argv[0]); + SetLogLevelFunc(value + 1); + return 0; +} + +static int InitCmd(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + // process cmd by name + PLUGIN_LOGI("InitCmd %s argc %d", name, argc); + if (argc > 1 && strcmp(argv[0], "setloglevel") == 0) { + SetLogLevelFunc(argv[1]); + } + return 0; +} + +static int ParamSetInitCmdHook(const HOOK_INFO *hookInfo, void *cookie) +{ + AddCmdExecutor("setloglevel", CmdSetLogLevel); + AddCmdExecutor("initcmd", InitCmd); + return 0; +} + +static int DumpTrigger(const char *fmt, ...) +{ + va_list vargs; + va_start(vargs, fmt); + InitLog(INIT_INFO, INIT_LOG_DOMAIN, INIT_LOG_TAG, fmt, vargs); + va_end(vargs); + return 0; +} + +static void DumpServiceHook(void) +{ + // check and dump all jobs + char dump[8] = {0}; // 8 len + uint32_t len = sizeof(dump); + (void)SystemReadParam("persist.init.debug.dump.trigger", dump, &len); + PLUGIN_LOGV("boot dump trigger %s", dump); + if (strcmp(dump, "1") == 0) { + SystemDumpTriggers(1, DumpTrigger); + } + return; +} + +static void InitLogLevelFromPersist(void) +{ + char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length. + uint32_t len = sizeof(logLevel); + int ret = SystemReadParam(INIT_DEBUG_LEVEL, logLevel, &len); + INIT_INFO_CHECK(ret == 0, return, "Can not get log level from param, keep the original loglevel."); + SetLogLevelFunc(logLevel); + return; +} + +static int InitDebugHook(const HOOK_INFO *info, void *cookie) +{ + UNUSED(info); + UNUSED(cookie); + InitLogLevelFromPersist(); + DumpServiceHook(); + return 0; +} + +// clear extend memory +static int BootCompleteCmd(const HOOK_INFO *hookInfo, void *executionContext) +{ + PLUGIN_LOGI("boot start complete"); + UNUSED(hookInfo); + UNUSED(executionContext); + + // clear hook + HookMgrDel(GetBootStageHookMgr(), INIT_GLOBAL_INIT, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_SERVICE, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_SERVICE_PARSE, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, NULL); + HookMgrDel(GetBootStageHookMgr(), INIT_JOB_PARSE, NULL); + // clear cmd + RemoveCmdExecutor("loadSelinuxPolicy", -1); + + PluginExecCmdByName("init_trace", "stop"); + // uninstall module of inittrace + InitModuleMgrUnInstall("inittrace"); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + HookMgrAdd(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, 0, BootCompleteCmd); + InitAddGlobalInitHook(0, ParamSetInitCmdHook); + // Depends on parameter service + InitAddPostPersistParamLoadHook(0, InitDebugHook); +} diff --git a/services/include/init_service_manager.h b/services/modules/init_hook/init_hook.h old mode 100644 new mode 100755 similarity index 40% rename from services/include/init_service_manager.h rename to services/modules/init_hook/init_hook.h index 3e680d3a9b7787e01a473348b8e279d34ed6aa12..87441514fe8d14ddf999927fd712d36e9d3aa9b4 --- a/services/include/init_service_manager.h +++ b/services/modules/init_hook/init_hook.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * 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 @@ -13,11 +13,12 @@ * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_SERVICEMANAGER_H -#define BASE_STARTUP_INITLITE_SERVICEMANAGER_H +#ifndef STARTUP_INIT_PARAM_HOOK +#define STARTUP_INIT_PARAM_HOOK +#include +#include -#include "init_service.h" -#include "cJSON.h" +#include "list.h" #ifdef __cplusplus #if __cplusplus @@ -25,31 +26,31 @@ extern "C" { #endif #endif -#define UID_STR_IN_CFG "uid" -#define GID_STR_IN_CFG "gid" -#define ONCE_STR_IN_CFG "once" -#define IMPORTANT_STR_IN_CFG "importance" -#define BIN_SH_NOT_ALLOWED "/bin/sh" -#define CRITICAL_STR_IN_CFG "critical" -#define DISABLED_STR_IN_CFG "disabled" -#define CONSOLE_STR_IN_CFG "console" - -#define MAX_SERVICES_CNT_IN_FILE 100 - -void RegisterServices(Service* services, int servicesCnt); -void StartServiceByName(const char* serviceName); -void StopServiceByName(const char* serviceName); -void StopAllServices(); -void StopAllServicesBeforeReboot(); -void ReapServiceByPID(int pid); -void ParseAllServices(const cJSON* fileRoot); -#ifdef OHOS_SERVICE_DUMP -void DumpAllServices(); -#endif +#define SERVICE_CTL_CMD_INDEX 2 +typedef struct { + char *name; // system parameter partial name + char *replace; // replace content if filed name match system parameter + char *cmd; // command name +} ParamCmdInfo; + +const ParamCmdInfo *GetServiceStartCtrl(size_t *size); +const ParamCmdInfo *GetServiceCtl(size_t *size); +const ParamCmdInfo *GetStartupPowerCtl(size_t *size); +const ParamCmdInfo *GetOtherSpecial(size_t *size); + +typedef struct { + struct ListNode node; + uint32_t dataId; + uint8_t data[0]; +} ServiceExtData; + +ServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen); +void DelServiceExtData(const char *serviceName, uint32_t id); +ServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id); + #ifdef __cplusplus #if __cplusplus } #endif #endif - -#endif // BASE_STARTUP_INITLITE_SERVICEMANAGER_H +#endif \ No newline at end of file diff --git a/services/modules/init_hook/param_hook.c b/services/modules/init_hook/param_hook.c new file mode 100755 index 0000000000000000000000000000000000000000..dc0e8741d454dbc38bd860fc8f4a59838c498b4d --- /dev/null +++ b/services/modules/init_hook/param_hook.c @@ -0,0 +1,101 @@ + +/* + * 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 "init_hook.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" + +/** +系统参数转化规则 + 1,ohos.ctl.start.{start|stop} = servicename + 转化后系统参数,用来进行dac/mac校验 + ohos.servicectrl.{servicename} + 对应的处理命令 + start + 2,ohos.startup.powerctrl = reboot,[bootcharge | shutdown | flashd | updater] + 转化后系统参数,用来进行dac/mac校验 + ohos.servicectrl.reboot.[bootcharge | shutdown | flashd | updater] + 对应的处理命令 + reboot.[bootcharge | shutdown | flashd | updater] + 3,ohos.servicectrl.{cmdName} = {arg} + 转化后系统参数,用来进行dac/mac校验 + ohos.servicectrl.{cmd} + 对应的处理命令 + cmd + 4,普通系统参数,根据定义的ParamCmdInfo进行处理 + {xxxx.xxxx.xxxx, xxxx.xxxx.xxxx, cmdname} + 例如: + xxxx.xxxx.xxxx = {args} + 转化后系统参数,用来进行dac/mac校验 + xxxx.xxxx.xxxx.{args} + 对应的处理命令 + cmdname + 命令输入参数(跳过replace部分的剩余值) + xxxx.xxxx.xxxx.{args} + strlen(name) +*/ + +const ParamCmdInfo *GetServiceStartCtrl(size_t *size) +{ + static const ParamCmdInfo ctrlParam[] = { + {"ohos.ctl.start", "start", "start "}, + {"ohos.ctl.stop", "stop", "stop "}, + }; + *size = ARRAY_LENGTH(ctrlParam); + return ctrlParam; +} + +const ParamCmdInfo *GetServiceCtl(size_t *size) +{ + static const ParamCmdInfo installParam[] = { + {"ohos.servicectrl.install", "install", "install" }, + {"ohos.servicectrl.uninstall", "uninstall", "uninstall" }, + {"ohos.servicectrl.bootchart", "bootchart", "bootchart" }, + {"ohos.servicectrl.init_trace", "init_trace", "init_trace" }, + {"ohos.servicectrl.timer_start", "timer_start", "timer_start " }, + {"ohos.servicectrl.timer_stop", "timer_stop", "timer_stop" }, + {"ohos.servicectrl.cmd", "cmd", "initcmd"}, + }; + *size = ARRAY_LENGTH(installParam); + return installParam; +} + +#ifdef OHOS_LITE +const ParamCmdInfo *GetStartupPowerCtl(size_t *size) +{ + static const ParamCmdInfo powerCtrlArg[] = { + {"reboot,shutdown", "reboot.shutdown", "reboot.shutdown"}, + {"reboot,updater", "reboot.updater", "reboot.updater"}, + {"reboot,flashd", "reboot.flashd", "reboot.flashd"}, + {"reboot,charge", "reboot.charge", "reboot.charge"}, + {"reboot", "reboot", "reboot"}, + }; + *size = ARRAY_LENGTH(powerCtrlArg); + return powerCtrlArg; +} +#endif + +const ParamCmdInfo *GetOtherSpecial(size_t *size) +{ + static const ParamCmdInfo other[] = { + {"bootevent.", "bootevent.", "bootevent"}, + {"persist.init.debug.", "persist.init.debug.", "setloglevel"}, + // for hitrace start, need interrupt init trace + {"debug.hitrace.enable.state", "debug.hitrace.enable.state.", "init_trace"}, + }; + *size = ARRAY_LENGTH(other); + return other; +} diff --git a/services/modules/plugin_adapter.h b/services/modules/plugin_adapter.h new file mode 100755 index 0000000000000000000000000000000000000000..77b8790b98fdf0742d4b93f31586561f5fbb7287 --- /dev/null +++ b/services/modules/plugin_adapter.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 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 PLUGIN_ADAPTER_ +#define PLUGIN_ADAPTER_ +#include +#include +#include + +#include "init_log.h" + +#define PROCESS_EXIT_CODE 0x7f // 0x7f: user specified + +#ifndef UNUSED +#define UNUSED(x) (void)(x) +#endif + +#ifndef PLUGIN_DOMAIN +#define PLUGIN_DOMAIN (BASE_DOMAIN + 6) +#endif +#define READ_DURATION 100000 +#define PLUGIN_LABEL "PLUGIN" +#define PLUGIN_LOGI(fmt, ...) STARTUP_LOGI(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) +#define PLUGIN_LOGE(fmt, ...) STARTUP_LOGE(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) +#define PLUGIN_LOGV(fmt, ...) STARTUP_LOGV(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) +#define PLUGIN_LOGW(fmt, ...) STARTUP_LOGW(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) + +#define PLUGIN_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + PLUGIN_LOGE(__VA_ARGS__); \ + exper; \ + } +#define PLUGIN_ONLY_LOG(ret, ...) \ + if (!(ret)) { \ + PLUGIN_LOGE(__VA_ARGS__); \ + } + +#define HOOKID(name) HOOK_ID_##name +enum HOOK_ID_ { + HOOKID(BOOTCHART), + HOOKID(SELINUX), + HOOKID(BOOTEVENT), + HOOKID(BOOTEVENT_MAX) = HOOK_ID_BOOTEVENT + 10, +}; + +#ifdef STARTUP_INIT_TEST +#define PLUGIN_STATIC +#else +#define PLUGIN_STATIC static +#endif + +#endif diff --git a/services/modules/reboot/BUILD.gn b/services/modules/reboot/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..5e9947a3e44fb024ecff521406dce5e1559cf6b9 --- /dev/null +++ b/services/modules/reboot/BUILD.gn @@ -0,0 +1,63 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +ohos_shared_library("rebootmodule") { + sources = [ "reboot.c" ] + cflags = [ "-fstack-protector-all" ] + include_dirs = [ + ".", + "..", + "../init_hook", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + ] + deps = [ + "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine", + "//base/startup/init/services/utils:libinit_utils", + ] + + external_deps = [ "bounds_checking_function:libsec_shared" ] + + defines = [] + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init/reboot" + } else { + module_install_dir = "lib/init/reboot" + } + install_images = [ + "system", + "updater", + ] +} + +ohos_source_set("libreboot_static") { + sources = [ + "reboot_misc.c", + "reboot_static.c", + ] + cflags = [ "-fstack-protector-all" ] + include_dirs = [ + ".", + "..", + "../init_hook", + "//base/startup/init/interfaces/innerkits/include/param", + ] + public_external_deps = [ "bounds_checking_function:libsec_static" ] + public_configs = [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] +} diff --git a/services/modules/reboot/reboot.c b/services/modules/reboot/reboot.c new file mode 100644 index 0000000000000000000000000000000000000000..0687b1a38c2b19c2f0c82645089a40242f544a37 --- /dev/null +++ b/services/modules/reboot/reboot.c @@ -0,0 +1,247 @@ +/* + * 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 "reboot_adp.h" +#include "init_cmdexecutor.h" +#include "init_module_engine.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" + +#define BUFF_SIZE 256 +#define POWEROFF_REASON_DEV_PATH "/proc/poweroff_reason" + +static int WritePowerOffReason(const char* reason) +{ + PLUGIN_CHECK(reason != NULL, return -1, "WritePowerOffReason: reason is NULL\n"); + PLUGIN_CHECK(access(POWEROFF_REASON_DEV_PATH, F_OK) == 0, return -1, + "WritePowerOffReason: access %s failed, errno = %d, %s\n", + POWEROFF_REASON_DEV_PATH, errno, strerror(errno)); + int fd = open(POWEROFF_REASON_DEV_PATH, O_RDWR); + PLUGIN_CHECK(fd > 0, return -1, "WritePowerOffReason: errno = %d, %s\n", errno, strerror(errno)); + int writeBytes = strlen(reason); + int ret = write(fd, reason, writeBytes); + PLUGIN_CHECK(ret == writeBytes, writeBytes = -1, "WritePowerOffReason: write poweroff reason failed\n"); + close(fd); + return writeBytes; +} + +static void ParseRebootReason(const char *name, int argc, const char **argv) +{ + char str[BUFF_SIZE] = {0}; + int len = sizeof(str); + char *tmp = str; + int ret; + for (int i = 0; i < argc; i++) { + if (i != argc - 1) { + ret = sprintf_s(tmp, len - 1, "%s ", argv[i]); + } else { + ret = sprintf_s(tmp, len - 1, "%s", argv[i]); + } + if (ret <= 0) { + PLUGIN_LOGW("ParseRebootReason: sprintf_s arg %s failed!", argv[i]); + break; + } + len -= ret; + tmp += ret; + } + ret = WritePowerOffReason(str); + PLUGIN_CHECK(ret >= 0, return, "ParseRebootReason: write poweroff reason failed\n"); +} + +PLUGIN_STATIC int DoRoot_(const char *jobName, int type) +{ + // by job to stop service and unmount + if (jobName != NULL) { + DoJobNow(jobName); + } +#ifndef STARTUP_INIT_TEST + return reboot(type); +#else + return 0; +#endif +} + +static int DoReboot(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + ParseRebootReason(name, argc, argv); + // clear misc + (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); + return DoRoot_("reboot", RB_AUTOBOOT); +} + +static int DoRebootPanic(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + char str[BUFF_SIZE] = {0}; + int ret = sprintf_s(str, sizeof(str) - 1, "panic caused by %s:", name); + if (ret <= 0) { + PLUGIN_LOGW("DoRebootPanic sprintf_s name %s failed!", name); + } + + int len = ret > 0 ? (sizeof(str) - ret) : sizeof(str); + char *tmp = str + (sizeof(str) - len); + for (int i = 0; i < argc; ++i) { + ret = sprintf_s(tmp, len - 1, " %s", argv[i]); + if (ret <= 0) { + PLUGIN_LOGW("DoRebootPanic sprintf_s arg %s failed!", argv[i]); + break; + } else { + len -= ret; + tmp += ret; + } + } + PLUGIN_LOGI("DoRebootPanic %s", str); + ParseRebootReason(name, argc, argv); + if (InRescueMode() == 0) { + PLUGIN_LOGI("Don't panic in resuce mode!"); + return 0; + } + // clear misc + (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); + DoJobNow("reboot"); +#ifndef STARTUP_INIT_TEST + FILE *panic = fopen("/proc/sysrq-trigger", "wb"); + if (panic == NULL) { + return reboot(RB_AUTOBOOT); + } + if (fwrite((void *)"c", 1, 1, panic) != 1) { + (void)fclose(panic); + PLUGIN_LOGI("fwrite to panic failed"); + return -1; + } + (void)fclose(panic); +#endif + return 0; +} + +PLUGIN_STATIC int DoRebootShutdown(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + ParseRebootReason(name, argc, argv); + // clear misc + (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); + const size_t len = strlen("reboot,"); + const char *cmd = strstr(argv[0], "reboot,"); + if (cmd != NULL && strlen(cmd) > len) { + PLUGIN_LOGI("DoRebootShutdown argv %s", cmd + len); + // by job to stop service and unmount + DoJobNow("reboot"); +#ifndef STARTUP_INIT_TEST + return syscall(__NR_reboot, + LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, cmd + len); +#else + return 0; +#endif + } + return DoRoot_("reboot", RB_POWER_OFF); +} + +static int DoRebootUpdater(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + PLUGIN_LOGI("DoRebootUpdater argc %d %s", argc, name); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGI("DoRebootUpdater argv %s", argv[0]); + ParseRebootReason(name, argc, argv); + int ret = UpdateMiscMessage(argv[0], "updater", "updater:", "boot_updater"); + if (ret == 0) { + return DoRoot_("reboot", RB_AUTOBOOT); + } + return ret; +} + +PLUGIN_STATIC int DoRebootFlashed(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + PLUGIN_LOGI("DoRebootFlashed argc %d %s", argc, name); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGI("DoRebootFlashd argv %s", argv[0]); + ParseRebootReason(name, argc, argv); + int ret = UpdateMiscMessage(argv[0], "flash", "flash:", "boot_flash"); + if (ret == 0) { + return DoRoot_("reboot", RB_AUTOBOOT); + } + return ret; +} + +PLUGIN_STATIC int DoRebootCharge(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + ParseRebootReason(name, argc, argv); + int ret = UpdateMiscMessage(NULL, "charge", "charge:", "boot_charge"); + if (ret == 0) { + return DoRoot_("reboot", RB_AUTOBOOT); + } + return ret; +} + +static int DoRebootSuspend(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + ParseRebootReason(name, argc, argv); + return DoRoot_("suspend", RB_AUTOBOOT); +} + +PLUGIN_STATIC int DoRebootOther(int id, const char *name, int argc, const char **argv) +{ + UNUSED(id); + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter argc %d", argc); + const char *cmd = strstr(argv[0], "reboot,"); + PLUGIN_CHECK(cmd != NULL, return -1, "Invalid parameter argc %s", argv[0]); + PLUGIN_LOGI("DoRebootOther argv %s", argv[0]); + ParseRebootReason(name, argc, argv); + // clear misc + (void)UpdateMiscMessage(NULL, "reboot", NULL, NULL); + DoJobNow("reboot"); +#ifndef STARTUP_INIT_TEST + return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, cmd + strlen("reboot,")); +#else + return 0; +#endif +} + +static void RebootAdpInit(void) +{ + // add default reboot cmd + (void)AddCmdExecutor("reboot", DoReboot); + (void)AddCmdExecutor("reboot.other", DoRebootOther); + AddRebootCmdExecutor("shutdown", DoRebootShutdown); + AddRebootCmdExecutor("flashd", DoRebootFlashed); + AddRebootCmdExecutor("updater", DoRebootUpdater); + AddRebootCmdExecutor("charge", DoRebootCharge); + AddRebootCmdExecutor("suspend", DoRebootSuspend); + AddRebootCmdExecutor("panic", DoRebootPanic); + (void)AddCmdExecutor("panic", DoRebootPanic); +} + +MODULE_CONSTRUCTOR(void) +{ + PLUGIN_LOGI("Reboot adapter plug-in init now ..."); + RebootAdpInit(); +} + +MODULE_DESTRUCTOR(void) +{ + PLUGIN_LOGI("Reboot adapter plug-in exit now ..."); +} diff --git a/services/modules/reboot/reboot_adp.h b/services/modules/reboot/reboot_adp.h new file mode 100644 index 0000000000000000000000000000000000000000..f8cbd99764fc3826cebbee45daafd767d8a1731e --- /dev/null +++ b/services/modules/reboot/reboot_adp.h @@ -0,0 +1,34 @@ +/* + * 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 MODULE_REBOOT_ADP_H +#define MODULE_REBOOT_ADP_H +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int GetRebootReasonFromMisc(char *reason, size_t size); +int UpdateMiscMessage(const char *valueData, const char *cmd, const char *cmdExt, const char *boot); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif /* MODULE_REBOOT_ADP_H */ diff --git a/services/modules/reboot/reboot_misc.c b/services/modules/reboot/reboot_misc.c new file mode 100644 index 0000000000000000000000000000000000000000..6a2cd55d4cc1e27e031aa10b3fb56a06878afff2 --- /dev/null +++ b/services/modules/reboot/reboot_misc.c @@ -0,0 +1,121 @@ +/* + * 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 "reboot_adp.h" +#include "fs_manager/fs_manager.h" +#include "init_utils.h" +#include "securec.h" + +#define MAX_COMMAND_SIZE 32 +#define MAX_UPDATE_SIZE 1280 +#define MAX_RESERVED_SIZE 736 + +struct RBMiscUpdateMessage { + char command[MAX_COMMAND_SIZE]; + char update[MAX_UPDATE_SIZE]; + char reserved[MAX_RESERVED_SIZE]; +}; + +static int RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot) +{ + char *realPath = GetRealPath(path); + BEGET_CHECK_RETURN_VALUE(realPath != NULL, -1); + int ret = -1; + FILE *fp = fopen(realPath, "rb+"); + free(realPath); + realPath = NULL; + if (fp != NULL) { + size_t writeLen = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp); + BEGET_ERROR_CHECK(writeLen == 1, ret = -1, "Failed to write misc for reboot"); + (void)fclose(fp); + ret = 0; + } + return ret; +} + +static int RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot) +{ + int ret = -1; + FILE *fp = NULL; + char *realPath = GetRealPath(path); + if (realPath != NULL) { + fp = fopen(realPath, "rb"); + free(realPath); + realPath = NULL; + } else { + fp = fopen(path, "rb"); + } + if (fp != NULL) { + size_t readLen = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp); + (void)fclose(fp); + BEGET_ERROR_CHECK(readLen > 0, ret = -1, "Failed to read misc for reboot"); + ret = 0; + } + return ret; +} + +int GetRebootReasonFromMisc(char *reason, size_t size) +{ + char miscFile[PATH_MAX] = {0}; + int ret = GetBlockDevicePath("/misc", miscFile, PATH_MAX); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc path"); + struct RBMiscUpdateMessage msg; + ret = RBMiscReadUpdaterMessage(miscFile, &msg); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info"); + return strcpy_s(reason, size, msg.command); +} + +int UpdateMiscMessage(const char *valueData, const char *cmd, const char *cmdExt, const char *boot) +{ + char miscFile[PATH_MAX] = {0}; + int ret = GetBlockDevicePath("/misc", miscFile, PATH_MAX); + // no misc do not updater, so return ok + BEGET_ERROR_CHECK(ret == 0, return 0, "Failed to get misc path for %s.", valueData); + + // "updater" or "updater:" + struct RBMiscUpdateMessage msg; + ret = RBMiscReadUpdaterMessage(miscFile, &msg); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info for %s.", cmd); + + if (boot != NULL) { + ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot); + BEGET_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd); + msg.command[MAX_COMMAND_SIZE - 1] = 0; + } else { + ret = memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to format cmd for %s.", cmd); + } + + if (strncmp(cmd, "updater", strlen("updater")) != 0) { + if ((cmdExt != NULL) && (valueData != NULL) && (strncmp(valueData, cmdExt, strlen(cmdExt)) == 0)) { + const char *p = valueData + strlen(cmdExt); + ret = snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p); + BEGET_ERROR_CHECK(ret > 0, return -1, "Failed to format param for %s.", cmd); + msg.update[MAX_UPDATE_SIZE - 1] = 0; + } else { + ret = memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE); + BEGET_ERROR_CHECK(ret == 0, return -1, "Failed to format update for %s.", cmd); + } + } + + if (RBMiscWriteUpdaterMessage(miscFile, &msg) == 0) { + return 0; + } + return -1; +} diff --git a/services/modules/reboot/reboot_static.c b/services/modules/reboot/reboot_static.c new file mode 100644 index 0000000000000000000000000000000000000000..0478dbfe59ae6a3f2cf0e2168fa060367e6899c8 --- /dev/null +++ b/services/modules/reboot/reboot_static.c @@ -0,0 +1,188 @@ +/* + * 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 "bootstage.h" +#include "hookmgr.h" +#include "init_hook.h" +#include "init_module_engine.h" +#include "plugin_adapter.h" +#include "securec.h" + +#define REBOOT_NAME_PREFIX "reboot," +#define REBOOT_CMD_PREFIX "reboot." +#define REBOOT_REPLACE_PREFIX "reboot." +#define PARAM_CMD_MAX 100 + +static int RebootHookWrapper(const HOOK_INFO *hookInfo, void *executionContext) +{ + RebootHookCtx *ctx = (RebootHookCtx *)executionContext; + InitRebootHook realHook = (InitRebootHook)hookInfo->hookCookie; + realHook(ctx); + return 0; +}; + +int InitAddRebootHook(InitRebootHook hook) +{ + HOOK_INFO info; + info.stage = INIT_REBOOT; + info.prio = 0; + info.hook = RebootHookWrapper; + info.hookCookie = (void *)hook; + return HookMgrAddEx(GetBootStageHookMgr(), &info); +} + +static ParamCmdInfo *g_rebootParamCmdInfos = NULL; +static int g_rebootParamCmdMaxNumber = 0; +static int g_rebootParamCmdValidNumber = 0; +static char *Dup2String(const char *prefix, const char *str) +{ + if (str == NULL) { + char *tmpstr = strdup("reboot"); + PLUGIN_CHECK(tmpstr != NULL, return NULL, "Failed to get str"); + return tmpstr; + } + size_t len = strlen(prefix) + strlen(str) + 1; + char *tmp = calloc(1, len); + PLUGIN_CHECK(tmp != NULL, return NULL, "Failed to alloc %s %s", prefix, str); + int ret = sprintf_s(tmp, len, "%s%s", prefix, str); + PLUGIN_CHECK(ret > 0, free(tmp); + return NULL, "Failed to sprintf %s %s", prefix, str); + return tmp; +} + +static int CheckParamCmdExist(const char *cmd) +{ + if (g_rebootParamCmdInfos == NULL) { + return 0; + } + char *cmdName = Dup2String(REBOOT_CMD_PREFIX, cmd); + PLUGIN_CHECK(cmdName != NULL, return 0, "Failed to copy %s", cmd); + for (int i = 0; i < g_rebootParamCmdValidNumber; i++) { + if (strcmp(g_rebootParamCmdInfos[i].cmd, cmdName) == 0) { + free(cmdName); + return 1; + } + } + free(cmdName); + return 0; +} + +static int SetParamCmdInfo(ParamCmdInfo *currInfo, CmdExecutor executor, const char *cmd) +{ + do { + currInfo->name = Dup2String(REBOOT_NAME_PREFIX, cmd); + PLUGIN_CHECK(currInfo->name != NULL, break, "Failed to copy %s", cmd); + currInfo->replace = Dup2String(REBOOT_REPLACE_PREFIX, cmd); + PLUGIN_CHECK(currInfo->replace != NULL, break, "Failed to copy %s", cmd); + currInfo->cmd = Dup2String(REBOOT_CMD_PREFIX, cmd); + PLUGIN_CHECK(currInfo->cmd != NULL, break, "Failed to copy %s", cmd); + if (executor != NULL) { + int cmdId = AddCmdExecutor(currInfo->cmd, executor); + PLUGIN_CHECK(cmdId > 0, break, "Failed to add cmd %s", cmd); + } + PLUGIN_LOGV("SetParamCmdInfo '%s' '%s' '%s' ", currInfo->name, currInfo->cmd, currInfo->replace); + currInfo = NULL; + g_rebootParamCmdValidNumber++; + return 0; + } while (0); + if (currInfo != NULL) { + if (currInfo->name != NULL) { + free(currInfo->name); + } + if (currInfo->cmd != NULL) { + free(currInfo->cmd); + } + if (currInfo->replace != NULL) { + free(currInfo->replace); + } + } + return -1; +} + +static int AddRebootCmdExecutor_(const char *cmd, CmdExecutor executor) +{ + PLUGIN_CHECK(g_rebootParamCmdMaxNumber <= PARAM_CMD_MAX, return -1, "Param cmd max number exceed limit"); + if (g_rebootParamCmdMaxNumber == 0 || g_rebootParamCmdMaxNumber <= g_rebootParamCmdValidNumber) { + g_rebootParamCmdMaxNumber += 5; // inc 5 once time + ParamCmdInfo *cmdInfos = calloc(1, sizeof(ParamCmdInfo) * g_rebootParamCmdMaxNumber); + PLUGIN_CHECK(cmdInfos != NULL, return -1, "Failed to add reboot cmd %s", cmd); + if (g_rebootParamCmdInfos != NULL) { // delete old + // copy from old + for (int i = 0; i < g_rebootParamCmdValidNumber; i++) { + cmdInfos[i].name = g_rebootParamCmdInfos[i].name; + cmdInfos[i].replace = g_rebootParamCmdInfos[i].replace; + cmdInfos[i].cmd = g_rebootParamCmdInfos[i].cmd; + } + free(g_rebootParamCmdInfos); + } + g_rebootParamCmdInfos = cmdInfos; + } + PLUGIN_CHECK(g_rebootParamCmdValidNumber >= 0 && g_rebootParamCmdValidNumber < g_rebootParamCmdMaxNumber, + return -1, "Param cmd number exceed limit"); + return SetParamCmdInfo(&g_rebootParamCmdInfos[g_rebootParamCmdValidNumber], executor, cmd); +} + +int AddRebootCmdExecutor(const char *cmd, CmdExecutor executor) +{ + PLUGIN_CHECK(cmd != NULL && executor != NULL, return EINVAL, "Invalid input parameter"); + int ret = CheckParamCmdExist(cmd); + if (ret != 0) { + PLUGIN_LOGI("Cmd %s exist", cmd); + return EEXIST; + } + return AddRebootCmdExecutor_(cmd, executor); +} + +const ParamCmdInfo *GetStartupPowerCtl(size_t *size) +{ + RebootHookCtx context; + context.reason = ""; + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_REBOOT, (void *)(&context), NULL); + PLUGIN_LOGI("After install reboot module"); + *size = g_rebootParamCmdValidNumber; + return g_rebootParamCmdInfos; +} + +static void InitRebootHook_(RebootHookCtx *ctx) +{ +#ifndef STARTUP_INIT_TEST // do not install + ModuleMgrScan("init/reboot"); +#endif + PLUGIN_LOGI("Install rebootmodule."); +} + +MODULE_CONSTRUCTOR(void) +{ + // 执行reboot时调用,安装reboot模块 + InitAddRebootHook(InitRebootHook_); +} + +MODULE_DESTRUCTOR(void) +{ + for (int i = 0; i < g_rebootParamCmdValidNumber; i++) { + if (g_rebootParamCmdInfos[i].name != NULL) { + free(g_rebootParamCmdInfos[i].name); + } + if (g_rebootParamCmdInfos[i].replace != NULL) { + free(g_rebootParamCmdInfos[i].replace); + } + if (g_rebootParamCmdInfos[i].cmd != NULL) { + free(g_rebootParamCmdInfos[i].cmd); + } + } + free(g_rebootParamCmdInfos); + g_rebootParamCmdInfos = NULL; +} \ No newline at end of file diff --git a/services/modules/seccomp/BUILD.gn b/services/modules/seccomp/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..f871deb319cb6fe3762a27f1e282e5014a859e2a --- /dev/null +++ b/services/modules/seccomp/BUILD.gn @@ -0,0 +1,171 @@ +# 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/begetd.gni") +import( + "//base/startup/init/services/modules/seccomp/scripts/seccomp_policy_fixer.gni") +import("//build/config/clang/clang.gni") +import("//build/ohos.gni") +import("//build/ohos/kernel/kernel.gni") + +INIT_PART = "init" +declare_args() { + appspawn_featrue = false + + if (defined(global_parts_info) && + defined(global_parts_info.startup_appspawn)) { + appspawn_featrue = true + } +} + +if (build_variant == "root") { + seccomp_enable_debug = true +} else { + seccomp_enable_debug = false +} + +ohos_prebuilt_seccomp("system_filter") { + sources = [ "seccomp_policy/system.seccomp.policy" ] + + filtername = "system" + process_type = "system" + + part_name = INIT_PART + subsystem_name = "startup" + + install_enable = true + install_images = [ "system" ] +} + +ohos_prebuilt_seccomp("appspawn_filter") { + sources = [ "seccomp_policy/spawn.seccomp.policy" ] + + filtername = "appspawn" + process_type = "system" + + part_name = INIT_PART + subsystem_name = "startup" + + include_dirs = [ "." ] + + install_enable = true + install_images = [ "system" ] +} + +ohos_prebuilt_seccomp("nwebspawn_filter") { + sources = [ "seccomp_policy/nwebspawn.seccomp.policy" ] + + filtername = "nwebspawn" + process_type = "system" + + part_name = INIT_PART + subsystem_name = "startup" + + include_dirs = [ "." ] + + install_enable = true + install_images = [ "system" ] +} + +ohos_prebuilt_seccomp("app_filter") { + sources = [ "seccomp_policy/app.seccomp.policy" ] + + filtername = "app" + process_type = "app" + + part_name = INIT_PART + subsystem_name = "startup" + + install_enable = true + install_images = [ "system" ] +} + +ohos_prebuilt_seccomp("app_privilege_filter") { + sources = [ "seccomp_policy/app_privilege.seccomp.policy" ] + + filtername = "app_privilege" + process_type = "system" + uid_is_root = true + + part_name = INIT_PART + subsystem_name = "startup" + + install_enable = true + install_images = [ "system" ] +} + +ohos_prebuilt_seccomp("updater_filter") { + sources = [ "seccomp_policy/updater.seccomp.policy" ] + + filtername = "updater" + process_type = "system" + uid_is_root = true + + part_name = INIT_PART + subsystem_name = "startup" + + install_enable = true + install_images = [ "updater" ] +} + +config("libseccomp_static_config") { + include_dirs = [ + "..", + "../../../interfaces/innerkits/seccomp/include", + ] + + if (seccomp_enable_debug) { + include_dirs += [ + "../../../interfaces/innerkits/include", + "../../../interfaces/innerkits/include/param", + ] + + defines = [ "WITH_SECCOMP_DEBUG" ] + } +} + +ohos_source_set("libseccomp_static") { + sources = [ + "seccomp_policy.c", + "seccomp_policy_static.c", + ] + public_configs = [ + ":libseccomp_static_config", + "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config", + ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "config_policy:configpolicy_util", + ] + + part_name = INIT_PART + subsystem_name = "startup" +} + +group("seccomp_filter") { + deps = [ + ":app_filter", + ":system_filter", + ":updater_filter", + ] + if (appspawn_featrue) { + deps += [ + ":appspawn_filter", + ":nwebspawn_filter", + ] + if (init_feature_seccomp_privilege) { + deps += [ ":app_privilege_filter" ] + } + } +} diff --git a/services/include/init_import.h b/services/modules/seccomp/gen_syscall_name_nrs.c similarity index 74% rename from services/include/init_import.h rename to services/modules/seccomp/gen_syscall_name_nrs.c index 48b6c01dd4ec79018b48140176110913bf140d59..f742989c7d5856ca98b3e39eeb3423d846c7adfb 100644 --- a/services/include/init_import.h +++ b/services/modules/seccomp/gen_syscall_name_nrs.c @@ -1,19 +1,16 @@ -/* - * Copyright (c) 2021 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_IMPORT_H - #define BASE_STARTUP_INITLITE_IMPORT_H - #include "cJSON.h" - void ParseAllImports(cJSON *root); - #endif \ No newline at end of file +/* + * 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 \ No newline at end of file diff --git a/services/modules/seccomp/scripts/generate_code_from_policy.py b/services/modules/seccomp/scripts/generate_code_from_policy.py new file mode 100755 index 0000000000000000000000000000000000000000..db7a0f00e6e6d221bcab8fc434fa4bc6f975f770 --- /dev/null +++ b/services/modules/seccomp/scripts/generate_code_from_policy.py @@ -0,0 +1,1079 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# 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 sys +import argparse +import textwrap +import re +import os +import stat + +supported_parse_item = ['labelName', 'priority', 'allowList', 'blockList', 'priorityWithArgs', \ + 'allowListWithArgs', 'headFiles', 'selfDefineSyscall', 'returnValue', \ + 'mode', 'privilegedProcessName', 'allowBlockList'] + +supported_architecture = ['arm', 'arm64', 'riscv64'] + +BPF_JGE = 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, {}, {}, {}),' +BPF_JGT = 'BPF_JUMP(BPF_JMP|BPF_JGT|BPF_K, {}, {}, {}),' +BPF_JEQ = 'BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, {}, {}, {}),' +BPF_JSET = 'BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, {}, {}, {}),' +BPF_JA = 'BPF_JUMP(BPF_JMP|BPF_JA, {}, 0, 0),' +BPF_LOAD = 'BPF_STMT(BPF_LD|BPF_W|BPF_ABS, {}),' +BPF_LOAD_MEM = 'BPF_STMT(BPF_LD|BPF_MEM, {}),' +BPF_ST = 'BPF_STMT(BPF_ST, {}),' +BPF_AND = 'BPF_STMT(BPF_ALU|BPF_AND|BPF_K, {}),' +BPF_RET_VALUE = 'BPF_STMT(BPF_RET|BPF_K, {}),' + +operation = ['<', '<=', '!=', '==', '>', '>=', '&'] + +ret_str_to_bpf = { + 'KILL_PROCESS': 'SECCOMP_RET_KILL_PROCESS', + 'KILL_THREAD': 'SECCOMP_RET_KILL_THREAD', + 'TRAP': 'SECCOMP_RET_TRAP', + 'ERRNO': 'SECCOMP_RET_ERRNO', + 'USER_NOTIF': 'SECCOMP_RET_USER_NOTIF', + 'TRACE': 'SECCOMP_RET_TRACE', + 'LOG' : 'SECCOMP_RET_LOG', + 'ALLOW': 'SECCOMP_RET_ALLOW' +} + +mode_str = { + 'DEFAULT': 0, + 'ONLY_CHECK_ARGS': 1 +} + +architecture_to_number = { + 'arm': 'AUDIT_ARCH_ARM', + 'arm64': 'AUDIT_ARCH_AARCH64', + 'riscv64': 'AUDIT_ARCH_RISCV64' +} + + +class ValidateError(Exception): + def __init__(self, msg): + super().__init__(msg) + + +def print_info(info): + print("[INFO] %s" % info) + + +def is_hex_digit(s): + try: + int(s, 16) + return True + + except ValueError: + return False + + +def str_convert_to_int(s): + number = -1 + digit_flag = False + + if s.isdigit() : + number = int(s) + digit_flag = True + + elif is_hex_digit(s): + number = int(s, 16) + digit_flag = True + + return number, digit_flag + + +def is_function_name_exist(arch, function_name, func_name_nr_table): + if function_name in func_name_nr_table: + return True + else: + raise ValidateError('{} not exsit in {} function_name_nr_table Table'.format(function_name, arch)) + + +def is_errno_in_valid_range(errno): + if int(errno) > 0 and int(errno) <= 255 and errno.isdigit(): + return True + else: + raise ValidateError('{} not within the legal range of errno values.'.format(errno)) + + +def is_return_errno(return_str): + if return_str[0:len('ERRNO')] == 'ERRNO': + errno_no = return_str[return_str.find('(') + 1 : return_str.find(')')] + return_string = return_str[0:len('ERRNO')] + return_string += ' | ' + if is_errno_in_valid_range(errno_no): + return_string += errno_no + return True, return_string + return False, 'not_return_errno' + + +def function_name_to_nr(function_name_list, func_name_nr_table): + return set(func_name_nr_table[function_name] for function_name \ + in function_name_list if function_name in func_name_nr_table) + + +def filter_syscalls_nr(name_to_nr): + syscalls = {} + for syscall_name, nr in name_to_nr.items(): + if not syscall_name.startswith("__NR_") and not syscall_name.startswith("__ARM_NR_"): + continue + + if syscall_name.startswith("__NR_arm_"): + syscall_name = syscall_name[len("__NR_arm_"):] + elif syscall_name.startswith("__NR_riscv_"): + syscall_name = syscall_name[len("__NR_riscv_"):] + elif syscall_name.startswith("__NR_"): + syscall_name = syscall_name[len("__NR_"):] + elif syscall_name.startswith("__ARM_NR_"): + syscall_name = syscall_name[len("__ARM_NR_"):] + elif syscall_name.startswith("__RISCV_NR_"): + syscall_name = syscall_name[len("__RISCV_NR_"):] + syscalls[syscall_name] = nr + + return syscalls + + +def parse_syscall_file(file_name): + const_pattern = re.compile( + r'^\s*#define\s+([A-Za-z_][A-Za-z0-9_]+)\s+(.+)\s*$') + mark_pattern = re.compile(r'\b[A-Za-z_][A-Za-z0-9_]+\b') + name_to_nr = {} + with open(file_name) as f: + for line in f: + k = const_pattern.match(line) + if k is None: + continue + try: + name = k.group(1) + nr = eval(mark_pattern.sub(lambda x: str(name_to_nr.get(x.group(0))), + k.group(2))) + + name_to_nr[name] = nr + except(KeyError, SyntaxError, NameError, TypeError): + continue + + return filter_syscalls_nr(name_to_nr) + + +def gen_syscall_nr_table(file_name, func_name_nr_table): + s = re.search(r"libsyscall_to_nr_([^/]+)", file_name) + func_name_nr_table[str(s.group(1))] = parse_syscall_file(file_name) + if str(s.group(1)) not in func_name_nr_table.keys(): + raise ValidateError("parse syscall file failed") + return func_name_nr_table + + +class SeccompPolicyParam: + def __init__(self, arch, function_name_nr_table, is_debug): + self.arch = arch + self.priority = set() + self.allow_list = set() + self.blocklist = set() + self.priority_with_args = set() + self.allow_list_with_args = set() + self.head_files = set() + self.self_define_syscall = set() + self.final_allow_list = set() + self.final_priority = set() + self.final_priority_with_args = set() + self.final_allow_list_with_args = set() + self.return_value = '' + self.mode = 'DEFAULT' + self.is_debug = is_debug + self.function_name_nr_table = function_name_nr_table + self.value_function = { + 'priority': self.update_priority, + 'allowList': self.update_allow_list, + 'blockList': self.update_blocklist, + 'allowListWithArgs': self.update_allow_list_with_args, + 'priorityWithArgs': self.update_priority_with_args, + 'headFiles': self.update_head_files, + 'selfDefineSyscall': self.update_self_define_syscall, + 'returnValue': self.update_return_value, + 'mode': self.update_mode + } + + def clear_list(self): + self.priority.clear() + self.allow_list.clear() + self.allow_list_with_args.clear() + self.priority_with_args.clear() + if self.mode == 'ONLY_CHECK_ARGS': + self.final_allow_list.clear() + self.final_priority.clear() + + def update_list(self, function_name, to_update_list): + if is_function_name_exist(self.arch, function_name, self.function_name_nr_table): + to_update_list.add(function_name) + return True + return False + + def update_priority(self, function_name): + return self.update_list(function_name, self.priority) + + def update_allow_list(self, function_name): + return self.update_list(function_name, self.allow_list) + + def update_blocklist(self, function_name): + return self.update_list(function_name, self.blocklist) + + def update_priority_with_args(self, function_name_with_args): + function_name = function_name_with_args[:function_name_with_args.find(':')] + function_name = function_name.strip() + if is_function_name_exist(self.arch, function_name, self.function_name_nr_table): + self.priority_with_args.add(function_name_with_args) + return True + return False + + def update_allow_list_with_args(self, function_name_with_args): + function_name = function_name_with_args[:function_name_with_args.find(':')] + function_name = function_name.strip() + if is_function_name_exist(self.arch, function_name, self.function_name_nr_table): + self.allow_list_with_args.add(function_name_with_args) + return True + return False + + def update_head_files(self, head_files): + if len(head_files) > 2 and (head_files[0] == '\"' and head_files[-1] == '\"') or \ + (head_files[0] == '<' and head_files[-1] == '>'): + self.head_files.add(head_files) + return True + + raise ValidateError('{} is not legal by headFiles format'.format(head_files)) + + def update_self_define_syscall(self, self_define_syscall): + nr, digit_flag = str_convert_to_int(self_define_syscall) + if digit_flag and nr not in self.function_name_nr_table.values(): + self.self_define_syscall.add(nr) + return True + + raise ValidateError('{} is not a number or {} is already used by ohter \ + syscall'.format(self_define_syscall, self_define_syscall)) + + def update_return_value(self, return_str): + is_ret_errno, return_string = is_return_errno(return_str) + if is_ret_errno == True: + self.return_value = return_string + return True + if return_str in ret_str_to_bpf: + if self.is_debug == 'false' and return_str == 'LOG': + raise ValidateError("LOG return value is not allowed in user mode") + self.return_value = return_str + return True + + raise ValidateError('{} not in {}'.format(return_str, ret_str_to_bpf.keys())) + + def update_mode(self, mode): + if mode in mode_str.keys(): + self.mode = mode + return True + raise ValidateError('{} not in [DEFAULT, ONLY_CHECK_ARGS]'.format(mode_str)) + + def check_allow_list(self, allow_list): + for item in allow_list: + pos = item.find(':') + syscall = item + if pos != -1: + syscall = item[:pos] + if syscall in self.blocklist: + raise ValidateError('{} of allow list is in block list'.format(syscall)) + return True + + def check_all_allow_list(self): + flag = self.check_allow_list(self.final_allow_list) \ + and self.check_allow_list(self.final_priority) \ + and self.check_allow_list(self.final_priority_with_args) \ + and self.check_allow_list(self.final_allow_list_with_args) + block_nr_list = function_name_to_nr(self.blocklist, self.function_name_nr_table) + for nr in self.self_define_syscall: + if nr in block_nr_list: + return False + return flag + + def update_final_list(self): + #remove duplicate function_name + self.final_allow_list |= self.allow_list + self.final_priority |= self.priority + self.final_allow_list_with_args |= self.allow_list_with_args + self.final_priority_with_args |= self.priority_with_args + final_priority_function_name_list_with_args = set(item[:item.find(':')] + for item in self.final_priority_with_args) + final_function_name_list_with_args = set(item[:item.find(':')] + for item in self.final_allow_list_with_args) + self.final_allow_list = self.final_allow_list - self.final_priority - \ + final_priority_function_name_list_with_args - final_function_name_list_with_args + self.final_priority = self.final_priority - final_priority_function_name_list_with_args - \ + final_function_name_list_with_args + self.clear_list() + + +class GenBpfPolicy: + def __init__(self): + self.arch = '' + self.syscall_nr_range = [] + self.bpf_policy = [] + self.syscall_nr_policy_list = [] + self.function_name_nr_table_dict = {} + self.gen_mode = 0 + self.flag = True + self.return_value = '' + self.operate_func_table = { + '<' : self.gen_bpf_lt, + '<=': self.gen_bpf_le, + '==': self.gen_bpf_eq, + '!=': self.gen_bpf_ne, + '>' : self.gen_bpf_gt, + '>=': self.gen_bpf_ge, + '&' : self.gen_bpf_set, + } + + @staticmethod + def gen_bpf_eq32(const_str, jt, jf): + bpf_policy = [] + bpf_policy.append(BPF_JEQ.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_eq64(const_str, jt, jf): + bpf_policy = [] + bpf_policy.append(BPF_JEQ.format('((unsigned long)' + const_str + ') >> 32', 0, jf + 2)) + bpf_policy.append(BPF_LOAD_MEM.format(0)) + bpf_policy.append(BPF_JEQ.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_gt32(const_str, jt, jf): + bpf_policy = [] + bpf_policy.append(BPF_JGT.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_gt64(const_str, jt, jf): + bpf_policy = [] + number, digit_flag = str_convert_to_int(const_str) + + hight = int(number / (2**32)) + low = number & 0xffffffff + + if digit_flag and hight == 0: + bpf_policy.append(BPF_JGT.format('((unsigned long)' + const_str + ') >> 32', jt + 2, 0)) + else: + bpf_policy.append(BPF_JGT.format('((unsigned long)' + const_str + ') >> 32', jt + 3, 0)) + bpf_policy.append(BPF_JEQ.format('((unsigned long)' + const_str + ') >> 32', 0, jf + 2)) + + bpf_policy.append(BPF_LOAD_MEM.format(0)) + bpf_policy.append(BPF_JGT.format(const_str + ' & 0xffffffff', jt, jf)) + + return bpf_policy + + @staticmethod + def gen_bpf_ge32(const_str, jt, jf): + bpf_policy = [] + bpf_policy.append(BPF_JGE.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_ge64(const_str, jt, jf): + bpf_policy = [] + number, digit_flag = str_convert_to_int(const_str) + + hight = int(number / (2**32)) + low = number & 0xffffffff + + if digit_flag and hight == 0: + bpf_policy.append(BPF_JGT.format('((unsigned long)' + const_str + ') >> 32', jt + 2, 0)) + else: + bpf_policy.append(BPF_JGT.format('((unsigned long)' + const_str + ') >> 32', jt + 3, 0)) + bpf_policy.append(BPF_JEQ.format('((unsigned long)' + const_str + ') >> 32', 0, jf + 2)) + bpf_policy.append(BPF_LOAD_MEM.format(0)) + bpf_policy.append(BPF_JGE.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_set32(const_str, jt, jf): + bpf_policy = [] + bpf_policy.append(BPF_JSET.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_set64(const_str, jt, jf): + bpf_policy = [] + bpf_policy.append(BPF_JSET.format('((unsigned long)' + const_str + ') >> 32', jt + 2, 0)) + bpf_policy.append(BPF_LOAD_MEM.format(0)) + bpf_policy.append(BPF_JSET.format(const_str + ' & 0xffffffff', jt, jf)) + return bpf_policy + + @staticmethod + def gen_bpf_valid_syscall_nr(syscall_nr, cur_size): + bpf_policy = [] + bpf_policy.append(BPF_LOAD.format(0)) + bpf_policy.append(BPF_JEQ.format(syscall_nr, 0, cur_size)) + return bpf_policy + + @staticmethod + def check_arg_str(arg_atom): + arg_str = arg_atom[0:3] + if arg_str != 'arg': + raise ValidateError('format ERROR, {} is not equal to arg'.format(arg_atom)) + + arg_id = int(arg_atom[3]) + if arg_id not in range(6): + raise ValidateError('arg num out of the scope 0~5') + + return arg_id, True + + @staticmethod + def check_operation_str(operation_atom): + operation_str = operation_atom + if operation_str not in operation: + operation_str = operation_atom[0] + if operation_str not in operation: + raise ValidateError('operation not in [<, <=, !=, ==, >, >=, &]') + return operation_str, True + + #gen bpf (argn & mask) == value + @staticmethod + def gen_mask_equal_bpf(arg_id, mask, value, cur_size): + bpf_policy = [] + #high 4 bytes + bpf_policy.append(BPF_LOAD.format(20 + arg_id * 8)) + bpf_policy.append(BPF_AND.format('((uint64_t)' + mask + ') >> 32')) + bpf_policy.append(BPF_JEQ.format('((uint64_t)' + value + ') >> 32', 0, cur_size + 4)) + + #low 4 bytes + bpf_policy.append(BPF_LOAD.format(16 + arg_id * 8)) + bpf_policy.append(BPF_AND.format(mask)) + bpf_policy.append(BPF_JEQ.format(value, cur_size, cur_size + 1)) + + return bpf_policy + + def update_arch(self, arch): + self.arch = arch + self.syscall_nr_range = [] + self.syscall_nr_policy_list = [] + + def update_function_name_nr_table(self, func_name_nr_table): + self.function_name_nr_table_dict = func_name_nr_table + + def clear_bpf_policy(self): + self.bpf_policy.clear() + + def get_gen_flag(self): + return self.flag + + def set_gen_flag(self, flag): + if flag: + self.flag = True + else: + self.flag = False + + def set_gen_mode(self, mode): + self.gen_mode = mode_str.get(mode) + + def set_return_value(self, return_value): + is_ret_errno, return_string = is_return_errno(return_value) + if is_ret_errno == True: + self.return_value = return_string + return + if return_value not in ret_str_to_bpf: + self.set_gen_mode(False) + return + + self.return_value = return_value + + def gen_bpf_eq(self, const_str, jt, jf): + if self.arch == 'arm': + return self.gen_bpf_eq32(const_str, jt, jf) + elif self.arch == 'arm64' or self.arch == 'riscv64': + return self.gen_bpf_eq64(const_str, jt, jf) + return [] + + def gen_bpf_ne(self, const_str, jt, jf): + return self.gen_bpf_eq(const_str, jf, jt) + + def gen_bpf_gt(self, const_str, jt, jf): + if self.arch == 'arm': + return self.gen_bpf_gt32(const_str, jt, jf) + elif self.arch == 'arm64' or self.arch == 'riscv64': + return self.gen_bpf_gt64(const_str, jt, jf) + return [] + + def gen_bpf_le(self, const_str, jt, jf): + return self.gen_bpf_gt(const_str, jf, jt) + + def gen_bpf_ge(self, const_str, jt, jf): + if self.arch == 'arm': + return self.gen_bpf_ge32(const_str, jt, jf) + elif self.arch == 'arm64' or self.arch == 'riscv64': + return self.gen_bpf_ge64(const_str, jt, jf) + return [] + + def gen_bpf_lt(self, const_str, jt, jf): + return self.gen_bpf_ge(const_str, jf, jt) + + def gen_bpf_set(self, const_str, jt, jf): + if self.arch == 'arm': + return self.gen_bpf_set32(const_str, jt, jf) + elif self.arch == 'arm64' or self.arch == 'riscv64': + return self.gen_bpf_set64(const_str, jt, jf) + return [] + + def gen_range_list(self, syscall_nr_list): + if len(syscall_nr_list) == 0: + return + self.syscall_nr_range.clear() + + syscall_nr_list_order = sorted(list(syscall_nr_list)) + range_temp = [syscall_nr_list_order[0], syscall_nr_list_order[0]] + + for i in range(len(syscall_nr_list_order) - 1): + if syscall_nr_list_order[i + 1] != syscall_nr_list_order[i] + 1: + range_temp[1] = syscall_nr_list_order[i] + self.syscall_nr_range.append(range_temp) + range_temp = [syscall_nr_list_order[i + 1], syscall_nr_list_order[i + 1]] + + range_temp[1] = syscall_nr_list_order[-1] + self.syscall_nr_range.append(range_temp) + + def gen_policy_syscall_nr(self, min_index, max_index, cur_syscall_nr_range): + middle_index = (int)((min_index + max_index + 1) / 2) + + if middle_index == min_index: + self.syscall_nr_policy_list.append(cur_syscall_nr_range[middle_index][1] + 1) + return + else: + self.syscall_nr_policy_list.append(cur_syscall_nr_range[middle_index][0]) + + self.gen_policy_syscall_nr(min_index, middle_index - 1, cur_syscall_nr_range) + self.gen_policy_syscall_nr(middle_index, max_index, cur_syscall_nr_range) + + def gen_policy_syscall_nr_list(self, cur_syscall_nr_range): + if not cur_syscall_nr_range: + return + self.syscall_nr_policy_list.clear() + self.syscall_nr_policy_list.append(cur_syscall_nr_range[0][0]) + self.gen_policy_syscall_nr(0, len(cur_syscall_nr_range) - 1, cur_syscall_nr_range) + + def calculate_step(self, index): + for i in range(index + 1, len(self.syscall_nr_policy_list)): + if self.syscall_nr_policy_list[index] < self.syscall_nr_policy_list[i]: + step = i - index + break + return step - 1 + + def nr_range_to_bpf_policy(self, cur_syscall_nr_range): + self.gen_policy_syscall_nr_list(cur_syscall_nr_range) + syscall_list_len = len(self.syscall_nr_policy_list) + + if syscall_list_len == 0: + return + + self.bpf_policy.append(BPF_JGE.format(self.syscall_nr_policy_list[0], 0, syscall_list_len)) + + range_max_list = [k[1] for k in cur_syscall_nr_range] + + for i in range(1, syscall_list_len): + if self.syscall_nr_policy_list[i] - 1 in range_max_list: + self.bpf_policy.append(BPF_JGE.format(self.syscall_nr_policy_list[i], \ + syscall_list_len - i, syscall_list_len - i - 1)) + else: + step = self.calculate_step(i) + self.bpf_policy.append(BPF_JGE.format(self.syscall_nr_policy_list[i], step, 0)) + + if self.syscall_nr_policy_list: + self.bpf_policy.append(BPF_RET_VALUE.format('SECCOMP_RET_ALLOW')) + + def count_alone_range(self): + cnt = 0 + for item in self.syscall_nr_range: + if item[0] == item[1]: + cnt = cnt + 1 + return cnt + + def gen_transverse_bpf_policy(self): + if not self.syscall_nr_range: + return + cnt = self.count_alone_range() + total_instruction_num = cnt + (len(self.syscall_nr_range) - cnt) * 2 + i = 0 + for item in self.syscall_nr_range: + if item[0] == item[1]: + if i == total_instruction_num - 1: + self.bpf_policy.append(BPF_JEQ.format(item[0], total_instruction_num - i - 1, 1)) + else: + self.bpf_policy.append(BPF_JEQ.format(item[0], total_instruction_num - i - 1, 0)) + i += 1 + else: + self.bpf_policy.append(BPF_JGE.format(item[0], 0, total_instruction_num - i)) + i += 1 + if i == total_instruction_num - 1: + self.bpf_policy.append(BPF_JGE.format(item[1] + 1, 1, total_instruction_num - i - 1)) + else: + self.bpf_policy.append(BPF_JGE.format(item[1] + 1, 0, total_instruction_num - i - 1)) + i += 1 + + self.bpf_policy.append(BPF_RET_VALUE.format('SECCOMP_RET_ALLOW')) + + def gen_bpf_policy(self, syscall_nr_list): + self.gen_range_list(syscall_nr_list) + range_size = (int)((len(self.syscall_nr_range) - 1) / 127) + 1 + alone_range_cnt = self.count_alone_range() + if alone_range_cnt == len(self.syscall_nr_range): + #Scattered distribution + self.gen_transverse_bpf_policy() + return + + if range_size == 1: + self.nr_range_to_bpf_policy(self.syscall_nr_range) + else: + for i in range(0, range_size): + if i == 0: + self.nr_range_to_bpf_policy(self.syscall_nr_range[-127 * (i + 1):]) + elif i == range_size - 1: + self.nr_range_to_bpf_policy(self.syscall_nr_range[:-127 * i]) + else: + self.nr_range_to_bpf_policy(self.syscall_nr_range[-127 * (i + 1): -127 * i]) + + def load_arg(self, arg_id): + # little endian + bpf_policy = [] + if self.arch == 'arm': + bpf_policy.append(BPF_LOAD.format(16 + arg_id * 8)) + elif self.arch == 'arm64' or self.arch == 'riscv64': + #low 4 bytes + bpf_policy.append(BPF_LOAD.format(16 + arg_id * 8)) + bpf_policy.append(BPF_ST.format(0)) + #high 4 bytes + bpf_policy.append(BPF_LOAD.format(20 + arg_id * 8)) + bpf_policy.append(BPF_ST.format(1)) + + return bpf_policy + + def compile_atom(self, atom, cur_size): + bpf_policy = [] + if len(atom) < 6: + raise ValidateError('{} format ERROR '.format(atom)) + + if atom[0] == '(': + bpf_policy += self.compile_mask_equal_atom(atom, cur_size) + else: + bpf_policy += self.compile_single_operation_atom(atom, cur_size) + + return bpf_policy + + def compile_mask_equal_atom(self, atom, cur_size): + bpf_policy = [] + left_brace_pos = atom.find('(') + right_brace_pos = atom.rfind(')') + inside_brace_content = atom[left_brace_pos + 1: right_brace_pos] + outside_brace_content = atom[right_brace_pos + 1:] + + arg_res = self.check_arg_str(inside_brace_content[0:4]) + if not arg_res[1]: + return bpf_policy + + operation_res_inside = self.check_operation_str(inside_brace_content[4:6]) + if operation_res_inside[0] != '&' or not operation_res_inside[1]: + return bpf_policy + + mask = inside_brace_content[4 + len(operation_res_inside[0]):] + + operation_res_outside = self.check_operation_str(outside_brace_content[0:2]) + if operation_res_outside[0] != '==' or not operation_res_outside[1]: + return bpf_policy + + value = outside_brace_content[len(operation_res_outside[0]):] + + return self.gen_mask_equal_bpf(arg_res[0], mask, value, cur_size) + + def compile_single_operation_atom(self, atom, cur_size): + bpf_policy = [] + arg_res = self.check_arg_str(atom[0:4]) + if not arg_res[1]: + return bpf_policy + + operation_res = self.check_operation_str(atom[4:6]) + if not operation_res[1]: + return bpf_policy + + const_str = atom[4 + len(operation_res[0]):] + + if not const_str: + return bpf_policy + + bpf_policy += self.load_arg(arg_res[0]) + bpf_policy += self.operate_func_table.get(operation_res[0])(const_str, 0, cur_size + 1) + + return bpf_policy + + def parse_args_with_condition(self, group): + #the priority of && higher than || + atoms = group.split('&&') + bpf_policy = [] + for atom in reversed(atoms): + bpf_policy = self.compile_atom(atom, len(bpf_policy)) + bpf_policy + return bpf_policy + + def parse_sub_group(self, group): + bpf_policy = [] + group_info = group.split(';') + operation_part = group_info[0] + return_part = group_info[1] + if not return_part.startswith('return'): + raise ValidateError('allow list with args do not have return part') + + self.set_return_value(return_part[len('return'):]) + and_cond_groups = operation_part.split('||') + for and_condition_group in and_cond_groups: + bpf_policy += self.parse_args_with_condition(and_condition_group) + bpf_policy.append(BPF_RET_VALUE.format(ret_str_to_bpf.get(self.return_value))) + return bpf_policy + + def parse_else_part(self, else_part): + return_value = else_part.split(';')[0][else_part.find('return') + len('return'):] + self.set_return_value(return_value) + + def parse_args(self, function_name, line, skip): + bpf_policy = [] + group_info = line.split('else') + else_part = group_info[-1] + group = group_info[0].split('elif') + for sub_group in group: + bpf_policy += self.parse_sub_group(sub_group) + self.parse_else_part(else_part) + if self.return_value[0:len('ERRNO')] == 'ERRNO': + bpf_policy.append(BPF_RET_VALUE.format(self.return_value.replace('ERRNO', ret_str_to_bpf.get('ERRNO')))) + else: + bpf_policy.append(BPF_RET_VALUE.format(ret_str_to_bpf.get(self.return_value))) + syscall_nr = self.function_name_nr_table_dict.get(self.arch).get(function_name) + #load syscall nr + bpf_policy = self.gen_bpf_valid_syscall_nr(syscall_nr, len(bpf_policy) - skip) + bpf_policy + return bpf_policy + + def gen_bpf_policy_with_args(self, allow_list_with_args, mode, return_value): + self.set_gen_mode(mode) + skip = 0 + for line in allow_list_with_args: + if self.gen_mode == 1 and line == list(allow_list_with_args)[-1]: + skip = 2 + line = line.replace(' ', '') + pos = line.find(':') + function_name = line[:pos] + + left_line = line[pos + 1:] + if not left_line.startswith('if'): + continue + + self.bpf_policy += self.parse_args(function_name, left_line[2:], skip) + + def add_load_syscall_nr(self): + self.bpf_policy.append(BPF_LOAD.format(0)) + + def add_return_value(self, return_value): + if return_value[0:len('ERRNO')] == 'ERRNO': + self.bpf_policy.append(BPF_RET_VALUE.format(return_value.replace('ERRNO', ret_str_to_bpf.get('ERRNO')))) + else: + self.bpf_policy.append(BPF_RET_VALUE.format(ret_str_to_bpf.get(return_value))) + + def add_validate_arch(self, arches, skip_step): + if not self.bpf_policy or not self.flag: + return + bpf_policy = [] + #load arch + bpf_policy.append(BPF_LOAD.format(4)) + if len(arches) == 2: + bpf_policy.append(BPF_JEQ.format(architecture_to_number.get(arches[0]), 3, 0)) + bpf_policy.append(BPF_JEQ.format(architecture_to_number.get(arches[1]), 0, 1)) + bpf_policy.append(BPF_JA.format(skip_step)) + bpf_policy.append(BPF_RET_VALUE.format('SECCOMP_RET_TRAP')) + elif len(arches) == 1: + bpf_policy.append(BPF_JEQ.format(architecture_to_number.get(arches[0]), 1, 0)) + bpf_policy.append(BPF_RET_VALUE.format('SECCOMP_RET_TRAP')) + else: + self.bpf_policy = [] + + self.bpf_policy = bpf_policy + self.bpf_policy + + +class AllowBlockList: + def __init__(self, filter_name, arch, function_name_nr_table): + self.is_valid = False + self.arch = arch + self.filter_name = filter_name + self.reduced_block_list = set() + self.function_name_nr_table = function_name_nr_table + self.value_function = { + 'privilegedProcessName': self.update_flag, + 'allowBlockList': self.update_reduced_block_list, + } + + def update_flag(self, name): + if self.filter_name == name: + self.is_valid = True + else: + self.is_valid = False + + def update_reduced_block_list(self, function_name): + if self.is_valid and is_function_name_exist(self.arch, function_name, self.function_name_nr_table): + self.reduced_block_list.add(function_name) + return True + return False + + +class SeccompPolicyParser: + def __init__(self): + self.cur_parse_item = '' + self.arches = set() + self.bpf_generator = GenBpfPolicy() + self.seccomp_policy_param = dict() + self.reduced_block_list_parm = dict() + self.key_process_flag = False + self.is_debug = False + + def update_is_debug(self, is_debug): + if is_debug == 'false': + self.is_debug = False + else: + self.is_debug = True + + def update_arch(self, target_cpu): + if target_cpu == "arm": + self.arches.add(target_cpu) + elif target_cpu == "arm64": + self.arches.add("arm") + self.arches.add(target_cpu) + elif target_cpu == "riscv64": + self.arches.add(target_cpu) + + def update_block_list(self): + for arch in supported_architecture: + self.seccomp_policy_param.get(arch).blocklist -= self.reduced_block_list_parm.get(arch).reduced_block_list + + def update_parse_item(self, line): + item = line[1:] + if item in supported_parse_item: + self.cur_parse_item = item + print_info('start deal with {}'.format(self.cur_parse_item)) + + def check_allow_list(self): + for arch in self.arches: + if not self.seccomp_policy_param.get(arch).check_all_allow_list(): + self.bpf_generator.set_gen_flag(False) + + def clear_file_syscall_list(self): + for arch in self.arches: + self.seccomp_policy_param.get(arch).update_final_list() + self.cur_parse_item = '' + self.cur_arch = '' + + def parse_line(self, line): + if not self.cur_parse_item : + return + line = line.replace(' ', '') + pos = line.rfind(';') + if pos < 0: + for arch in self.arches: + if self.key_process_flag: + self.reduced_block_list_parm.get(arch).value_function.get(self.cur_parse_item)(line) + else: + self.seccomp_policy_param.get(arch).value_function.get(self.cur_parse_item)(line) + else: + arches = line[pos + 1:].split(',') + if arches[0] == 'all': + arches = supported_architecture + for arch in arches: + if self.key_process_flag: + self.reduced_block_list_parm.get(arch).value_function.get(self.cur_parse_item)(line[:pos]) + else: + self.seccomp_policy_param.get(arch).value_function.get(self.cur_parse_item)(line[:pos]) + + def parse_open_file(self, fp): + for line in fp: + line = line.strip() + if not line: + continue + if line[0] == '#': + continue + if line[0] == '@': + self.update_parse_item(line) + continue + if line[0] != '@' and self.cur_parse_item == '': + continue + self.parse_line(line) + self.clear_file_syscall_list() + self.check_allow_list() + + def parse_file(self, file_path): + with open(file_path) as fp: + self.parse_open_file(fp) + + def gen_seccomp_policy_of_arch(self, arch): + cur_policy_param = self.seccomp_policy_param.get(arch) + + if not cur_policy_param.return_value: + raise ValidateError('return value not defined') + + #get final allow_list + syscall_nr_allow_list = function_name_to_nr(cur_policy_param.final_allow_list, \ + cur_policy_param.function_name_nr_table) \ + | cur_policy_param.self_define_syscall + syscall_nr_priority = function_name_to_nr(cur_policy_param.final_priority, \ + cur_policy_param.function_name_nr_table) + self.bpf_generator.update_arch(arch) + + #load syscall nr + if syscall_nr_allow_list or syscall_nr_priority: + self.bpf_generator.add_load_syscall_nr() + self.bpf_generator.gen_bpf_policy(syscall_nr_priority) + self.bpf_generator.gen_bpf_policy_with_args(sorted(list(cur_policy_param.final_priority_with_args)), \ + cur_policy_param.mode, cur_policy_param.return_value) + self.bpf_generator.gen_bpf_policy(syscall_nr_allow_list) + self.bpf_generator.gen_bpf_policy_with_args(sorted(list(cur_policy_param.final_allow_list_with_args)), \ + cur_policy_param.mode, cur_policy_param.return_value) + + self.bpf_generator.add_return_value(cur_policy_param.return_value) + for line in self.bpf_generator.bpf_policy: + if 'SECCOMP_RET_LOG' in line and self.is_debug == False: + raise ValidateError("LOG return value is not allowed in user mode") + + def gen_seccomp_policy(self): + arches = sorted(list(self.arches)) + if not arches: + return + self.gen_seccomp_policy_of_arch(arches[0]) + skip_step = len(self.bpf_generator.bpf_policy) + 1 + if len(arches) == 2: + self.gen_seccomp_policy_of_arch(arches[1]) + + self.bpf_generator.add_validate_arch(arches, skip_step) + + def gen_output_file(self, args): + if not self.bpf_generator.bpf_policy: + raise ValidateError("bpf_policy is empty!") + + header = textwrap.dedent('''\ + + #include + #include + #include + #include + ''') + extra_header = set() + for arch in self.arches: + extra_header |= self.seccomp_policy_param.get(arch).head_files + extra_header_list = ['#include ' + i for i in sorted(list(extra_header))] + filter_name = 'g_' + args.filter_name + 'SeccompFilter' + + array_name = textwrap.dedent(''' + + const struct sock_filter {}[] = {{ + ''').format(filter_name) + + footer = textwrap.dedent('''\ + + }}; + + const size_t {} = sizeof({}) / sizeof(struct sock_filter); + ''').format(filter_name + 'Size', filter_name) + + content = header + '\n'.join(extra_header_list) + array_name + \ + ' ' + '\n '.join(self.bpf_generator.bpf_policy) + footer + + flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + modes = stat.S_IWUSR | stat.S_IRUSR | stat.S_IWGRP | stat.S_IRGRP + with os.fdopen(os.open(args.dst_file, flags, modes), 'w') as output_file: + output_file.write(content) + + def gen_seccomp_policy_code(self, args): + if args.target_cpu not in supported_architecture: + raise ValidateError('target cpu not supported') + function_name_nr_table_dict = {} + for file_name in args.src_files: + file_name_tmp = file_name.split('/')[-1] + if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): + continue + function_name_nr_table_dict = gen_syscall_nr_table(file_name, function_name_nr_table_dict) + + + for arch in supported_architecture: + self.seccomp_policy_param.update( + {arch: SeccompPolicyParam(arch, function_name_nr_table_dict.get(arch), args.is_debug)}) + self.reduced_block_list_parm.update( + {arch: AllowBlockList(args.filter_name, arch, function_name_nr_table_dict.get(arch))}) + + self.bpf_generator.update_function_name_nr_table(function_name_nr_table_dict) + + self.update_arch(args.target_cpu) + self.update_is_debug(args.is_debug) + + for file_name in args.blocklist_file: + if file_name.lower().endswith('blocklist.seccomp.policy'): + self.parse_file(file_name) + + for file_name in args.keyprocess_file: + if file_name.lower().endswith('privileged_process.seccomp.policy'): + self.key_process_flag = True + self.parse_file(file_name) + self.key_process_flag = False + + self.update_block_list() + + for file_name in args.src_files: + if file_name.lower().endswith('.policy'): + self.parse_file(file_name) + + if self.bpf_generator.get_gen_flag(): + self.gen_seccomp_policy() + + if self.bpf_generator.get_gen_flag(): + self.gen_output_file(args) + + +def main(): + parser = argparse.ArgumentParser( + description='Generates a seccomp-bpf policy') + parser.add_argument('--src-files', type=str, action='append', + help=('The input files\n')) + + parser.add_argument('--blocklist-file', type=str, action='append', + help=('input basic blocklist file(s)\n')) + + parser.add_argument('--keyprocess-file', type=str, action='append', + help=('input key process file(s)\n')) + + parser.add_argument('--dst-file', + help='The output path for the policy files') + + parser.add_argument('--filter-name', type=str, + help='Name of seccomp bpf array generated by this script') + + parser.add_argument('--target-cpu', type=str, + help=('please input target cpu arm or arm64\n')) + + parser.add_argument('--is-debug', type=str, + help=('please input is_debug true or false\n')) + + args = parser.parse_args() + + generator = SeccompPolicyParser() + generator.gen_seccomp_policy_code(args) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/modules/seccomp/scripts/seccomp_policy_fixer.gni b/services/modules/seccomp/scripts/seccomp_policy_fixer.gni new file mode 100755 index 0000000000000000000000000000000000000000..6825cea066e73695020e3fb8d0589ee7596ec235 --- /dev/null +++ b/services/modules/seccomp/scripts/seccomp_policy_fixer.gni @@ -0,0 +1,199 @@ +# 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("//build/config/python.gni") +import("//build/ohos.gni") + +template("ohos_prebuilt_seccomp") { + if (!build_seccomp) { + group(target_name) { + not_needed(invoker, "*") + } + } else { + assert(defined(invoker.sources), + "source must be defined for ${target_name}.") + assert(defined(invoker.filtername), + "source must be defined for ${target_name}.") + assert( + defined(invoker.process_type) && + (invoker.process_type == "app" || invoker.process_type == "system"), + "process_type must be defined for ${target_name}, and the type must be app or system") + + _seccomp_filter_target = "gen_${target_name}" + _output_name = "${invoker.filtername}_filter" + _seccomp_filter_file = target_gen_dir + "/${_output_name}.c" + _syscall_to_nr_arm_name = "${target_name}_syscall_to_nr_arm" + _syscall_to_nr_arm64_name = "${target_name}_syscall_to_nr_arm64" + _syscall_to_nr_riscv64_name = "${target_name}_syscall_to_nr_riscv64" + _blocklist_file_name = "//base/startup/init/services/modules/seccomp/seccomp_policy/${invoker.process_type}.blocklist.seccomp.policy" + _key_process_file_name = "//base/startup/init/services/modules/seccomp/seccomp_policy/privileged_process.seccomp.policy" + + action(_syscall_to_nr_arm_name) { + script = "${clang_base_path}/bin/clang" + output_dir = + target_gen_dir + "/${_seccomp_filter_target}/libsyscall_to_nr_arm" + args = [ + "-I", + rebase_path( + "//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include/asm-arm"), + "-I", + rebase_path( + "//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include"), + "-dD", + "-E", + "-Wall", + "-nostdinc", + "-o", + rebase_path(output_dir), + rebase_path( + "//base/startup/init/services/modules/seccomp/gen_syscall_name_nrs.c"), + ] + + outputs = [ output_dir ] + } + + action(_syscall_to_nr_arm64_name) { + script = "${clang_base_path}/bin/clang" + output_dir = + target_gen_dir + "/${_seccomp_filter_target}/libsyscall_to_nr_arm64" + args = [ + "-I", + rebase_path( + "//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include/asm-arm64"), + "-I", + rebase_path( + "//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include"), + "-dD", + "-E", + "-Wall", + "-nostdinc", + "-o", + rebase_path(output_dir), + rebase_path( + "//base/startup/init/services/modules/seccomp/gen_syscall_name_nrs.c"), + ] + + outputs = [ output_dir ] + } + action(_syscall_to_nr_riscv64_name) { + script = "${clang_base_path}/bin/clang" + output_dir = + target_gen_dir + "/${_seccomp_filter_target}/libsyscall_to_nr_riscv64" + args = [ + "-I", + rebase_path( + "//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include/asm-riscv"), + "-I", + rebase_path( + "//kernel/linux/patches/${linux_kernel_version}/prebuilts/usr/include"), + "-dD", + "-E", + "-Wall", + "-nostdinc", + "-o", + rebase_path(output_dir), + rebase_path( + "//base/startup/init/services/modules/seccomp/gen_syscall_name_nrs.c"), + ] + outputs = [ output_dir ] + } + action(_seccomp_filter_target) { + script = "//base/startup/init/services/modules/seccomp/scripts/generate_code_from_policy.py" + + sources = invoker.sources + sources += get_target_outputs(":${_syscall_to_nr_arm_name}") + sources += get_target_outputs(":${_syscall_to_nr_arm64_name}") + sources += get_target_outputs(":${_syscall_to_nr_riscv64_name}") + uid_is_root = false + if (defined(invoker.uid_is_root)) { + uid_is_root = invoker.uid_is_root + } else { + uid_is_root = false + } + if (invoker.process_type == "system" && + invoker.filtername != "appspawn" && + invoker.filtername != "nwebspawn" && uid_is_root == false) { + sources += [ "//base/startup/init/services/modules/seccomp/seccomp_policy/system_uid_filter.seccomp.policy" ] + } + + deps = [ + ":${_syscall_to_nr_arm64_name}", + ":${_syscall_to_nr_arm_name}", + ":${_syscall_to_nr_riscv64_name}", + ] + + if (build_variant == "root") { + seccomp_is_debug = "true" + } else { + seccomp_is_debug = "false" + } + + args = [] + foreach(source, sources) { + args += [ + "--src-files", + rebase_path(source), + ] + } + args += [ + "--blocklist-file", + rebase_path(_blocklist_file_name), + "--dst-file", + rebase_path(_seccomp_filter_file), + "--filter-name", + invoker.filtername, + "--target-cpu", + invoker.target_cpu, + "--keyprocess-file", + rebase_path(_key_process_file_name), + "--is-debug", + seccomp_is_debug, + ] + + outputs = [ _seccomp_filter_file ] + } + + ohos_shared_library(target_name) { + output_name = _output_name + deps = [ ":${_seccomp_filter_target}" ] + sources = get_target_outputs(":${_seccomp_filter_target}") + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + relative_install_dir = "seccomp" + + if (defined(invoker.include_dirs)) { + include_dirs = invoker.include_dirs + } + + if (defined(invoker.install_enable)) { + install_enable = invoker.install_enable + } + + if (defined(invoker.part_name)) { + part_name = invoker.part_name + } + + if (defined(invoker.subsystem_name)) { + subsystem_name = invoker.subsystem_name + } + + if (defined(invoker.install_images)) { + install_images = invoker.install_images + } + } + } +} diff --git a/services/modules/seccomp/scripts/tools/audit_log_analysis.py b/services/modules/seccomp/scripts/tools/audit_log_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..e5ab88a7015c5272e2823ebabd27aca6e9be8576 --- /dev/null +++ b/services/modules/seccomp/scripts/tools/audit_log_analysis.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2023 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 argparse +import sys +import os +import stat +import generate_code_from_policy as gen_policy + + +def parse_line(fp, arch_nr): + arch_id_map = { + '40000028': 'arm', + 'c00000b7': 'arm64', + 'c00000f3': 'riscv64' + } + for line in fp: + line = line.strip() + if 'audit' not in line or 'type=1326' not in line: + continue + + pos = line.find(' syscall=') + arch_id = line[line.find('arch=') + 5 : pos] + syscall, _ = gen_policy.str_convert_to_int(line[pos + 9: line.find(' compat')]) + arch_nr.get(arch_id_map.get(arch_id)).add(syscall) + + +def get_item_content(name_nr_table, arch_nr_table): + content = '@allowList\n' + syscall_name_dict = { + 'arm': list(), + 'arm64': list(), + 'riscv64': list() + } + supported_architecture = ['arm64', 'arm', 'riscv64'] + for arch in supported_architecture: + for nr in sorted(list(arch_nr_table.get(arch))): + syscall_name = name_nr_table.get(arch).get(nr) + if not syscall_name: + raise ValueError('nr is not ilegal') + syscall_name_dict.get(arch).append(syscall_name) + + for func_name in syscall_name_dict.get('arm64'): + if func_name in syscall_name_dict.get('arm'): + content = '{}{};all\n'.format(content, func_name) + syscall_name_dict.get('arm').remove(func_name) + else: + content = '{}{};arm64\n'.format(content, func_name) + if syscall_name_dict.get('arm'): + content = '{}{};arm\n'.format(content, ';arm\n'.join( + [func_name for func_name in syscall_name_dict.get('arm')])) + if syscall_name_dict.get('riscv64'): + content = '{}{};riscv64\n'.format(content, ';riscv64\n'.join( + [func_name for func_name in syscall_name_dict.get('riscv64')])) + + return content + + +def gen_output_file(filter_name, content): + flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + modes = stat.S_IWUSR | stat.S_IRUSR | stat.S_IWGRP | stat.S_IRGRP + with os.fdopen(os.open(filter_name + '.seccomp.policy', flags, modes), 'w') as output_file: + output_file.write(content) + + +def parse_file(file_name, arch_nr): + with open(file_name) as f: + parse_line(f, arch_nr) + + +def converse_fuction_name_nr(dict_dst, dict_src): + for arch in dict_src.keys(): + dict_dst.update({arch: dict()}) + + for arch in dict_src.keys(): + for key, value in dict_src.get(arch).items(): + dict_dst.get(arch).update({value: key}) + return dict_dst + + +def parse_audit_log_to_policy(args): + file_list = extract_file_from_path(args.src_path) + function_name_nr_table_dict_tmp = {} + function_name_nr_table_dict = {} + arch_nr = { + 'arm': set(), + 'arm64': set(), + 'riscv64': set() + } + for file_name in file_list: + file_name_tmp = file_name.split('/')[-1] + if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): + continue + function_name_nr_table_dict_tmp = gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict_tmp) + + converse_fuction_name_nr(function_name_nr_table_dict, function_name_nr_table_dict_tmp) + + for file_name in file_list: + if file_name.lower().endswith('.audit.log'): + parse_file(file_name, arch_nr) + + content = get_item_content(function_name_nr_table_dict, arch_nr) + gen_output_file(args.filter_name, content) + + +def extract_file_from_path(dir_path): + file_list = [] + for path in dir_path: + if path[-1] == '/': + print('input dir path can not end with /') + return [] + + if os.path.isdir(path): + # get file list + file_list_tmp = os.listdir(path) + file_list += ['{}/{}'.format(path, item) for item in file_list_tmp] + + return file_list + + +def main(): + parser = argparse.ArgumentParser( + description='Generates a seccomp-bpf policy') + parser.add_argument('--src-path', action='append', + help='path to syscall to nr files') + parser.add_argument('--filter-name', type=str, + help=('The input files\n')) + + + args = parser.parse_args() + parse_audit_log_to_policy(args) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/modules/seccomp/scripts/tools/collect_elf_syscall.py b/services/modules/seccomp/scripts/tools/collect_elf_syscall.py new file mode 100644 index 0000000000000000000000000000000000000000..d79f74eafc4079e94cd07e207c320eea18de7cf2 --- /dev/null +++ b/services/modules/seccomp/scripts/tools/collect_elf_syscall.py @@ -0,0 +1,351 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2023 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 os +import sys +import argparse +import subprocess +import stat +import libc_static_analysis as gen_libc +import audit_log_analysis as audit_policy +import generate_code_from_policy as gen_policy + + +#modified the path of objdump and readelf path +def get_obj_dump_path(): + obj_dump_path = '' + return obj_dump_path + + +def get_read_elf_path(): + read_elf_path = '' + return read_elf_path + + +def create_needed_file(elf_path, locate_path, cmd, suffix): + if locate_path[-1] != '/': + locate_path = '{}/'.format(locate_path) + elf_file_name = elf_path.split('/')[-1].split('.')[0] + suffix + target_path = '{}{}'.format(locate_path, elf_file_name) + flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + modes = stat.S_IWUSR | stat.S_IRUSR | stat.S_IWGRP | stat.S_IRGRP + with os.fdopen(os.open(target_path, flags, modes), 'w') as output_file: + process = subprocess.Popen(cmd.split(' '), stdout=output_file) + process.communicate(timeout=3) + return target_path + + +def generate_libc_asm(target_cpu, elf_path, locate_path): + if target_cpu == 'arm': + cmd_obj_dump = 'arm-linux-musleabi-objdump' + elif target_cpu == 'arm64': + cmd_obj_dump = 'aarch64-linux-musl-objdump' + elif target_cpu == 'riscv64': + cmd_obj_dump = 'riscv64-linux-musl-objdump' + else: + raise ValueError("target cpu error") + + cmd = '{} -d {}'.format(cmd_obj_dump, elf_path) + return create_needed_file(elf_path, locate_path, cmd, '.asm') + + +def get_lib_path(elf_path, elf_name, cmd_extra): + grep_unstrip = ' | grep unstripped | grep -v _x64 {}'.format(cmd_extra) + + if elf_name == 'libc++.so': + grep_unstrip = '| grep aarch64-linux' + cmd = 'find {} -name {}{}'.format(elf_path, elf_name, grep_unstrip) + result_list = os.popen(cmd).read().split('\n') + result = result_list[0].strip() + for item in result_list: + item = item.strip() + if len(item) > len(result): + result = item + return result + + +def extract_elf_name(elf_path): + cmd = '{} -d {} | grep \'Shared library\''.format(get_read_elf_path(), elf_path) + result = os.popen(cmd).read().strip() + elf_name = set() + for item in result.split('\n'): + name = item[item.find('[') + 1: item.find(']')] + if name == 'libc.so' or name == '': + continue + elf_name.add(name) + + return elf_name + + +def extract_undef_name(elf_path): + cmd = '{} -sW {} | grep UND'.format(get_read_elf_path(), elf_path) + result = os.popen(cmd).read().strip() + func_name = set() + for item in result.split('\n'): + name = item[item.find('UND') + 3:].strip() + if name != '': + func_name.add(name) + + return func_name + + +def collect_elf(elf_path, elf_name): + elf_list = set(elf_name) + elf_path_list = set() + current_elf_name = set(elf_name) + while current_elf_name: + elf_path_list_tmp = set() + elf_list |= current_elf_name + for lib_name in current_elf_name: + elf_path_list_tmp.add(get_lib_path(elf_path, lib_name, '')) + + current_elf_name.clear() + for lib_path in elf_path_list_tmp: + current_elf_name |= extract_elf_name(lib_path) + elf_path_list |= elf_path_list_tmp + elf_path_list_tmp.clear() + + return elf_path_list + + +def collect_undef_func_name(elf_path_list): + func_name = set() + for elf_path in elf_path_list: + func_name |= extract_undef_name(elf_path) + + return func_name + + +def collect_syscall(undef_func_name, libc_func_map): + syscall_nr = set() + + for libc_func in libc_func_map: + for func_name in undef_func_name: + if func_name == libc_func.func_name: + syscall_nr |= libc_func.nr + break + + return syscall_nr + + +def get_item_content(arch, nr_set, name_nr_table): + func_name_list = list() + for nr in sorted(list(nr_set)): + func_name_list.append(name_nr_table.get(arch).get(nr)) + content = '@allowList\n{};{}\n'.format(';{}\n'.format(arch).join(func_name_list), arch) + + return content + + +def get_und_func_except_libc(elf_path, libc_func_list): + und_func = extract_undef_name(elf_path) + und_func_except_libc = [item for item in und_func if item not in libc_func_list] + return und_func_except_libc + + +def get_und_libc_func(elf_path, libc_func_list): + und_func = extract_undef_name(elf_path) + und_func_only_libc = [item for item in und_func if item in libc_func_list] + return und_func_only_libc + + +def create_disassemble_file(elf_path, locate_path, section): + cmd = '{} -d --section={} {}'.format(get_obj_dump_path(), section, elf_path) + return create_needed_file(elf_path, locate_path, cmd, section + '.asm') + + +def remove_disassemble_file(path): + file_list = [item for item in os.listdir(path) if item.endswith('.asm')] + subprocess.call(['rm'] + file_list) + + +class FuncCallee: + def __init__(self, func_name): + self.func_name = func_name + self.func_callee = set() + + def print_info(self): + print('{} call function {}'.format(self.func_name, self.func_callee)) + + +def parse_line(fp): + func_list = [] + func_call_tmp = None + for line in fp: + if '>:' in line: + if func_call_tmp: + func_list.append(func_call_tmp) + func_call_tmp = FuncCallee(line[line.find('<') + 1: line.find('>:')]) + continue + + if '<' in line and ">" in line: + func_name_callee = line[line.find('<') + 1: line.find('>')] + if '@plt' in func_name_callee: + func_call_tmp.func_callee.add(func_name_callee[:func_name_callee.find('@plt')]) + elif '+0x' in func_name_callee: + continue + else: + func_call_tmp.func_callee.add(func_name_callee) + func_list.append(func_call_tmp) + return func_list + + +def parse_text_asm_file(elf_asm_path): + func_list = list() + with open(elf_asm_path) as fp: + func_list = parse_line(fp) + + return func_list + + +def generate_libc_dict(libc_func): + libc_dict = dict() + for item in libc_func: + libc_dict.update({item: set({item})}) + + return libc_dict + + +def add_caller(callee, func_map): + caller = set() + for item in func_map: + if callee in item.func_callee: + caller.add(item.func_name) + return caller + + +def update_libc_func_caller(caller_list, func_map): + caller_list_old_len = -1 + caller_list_new_len = len(caller_list) + current_caller_list = caller_list + + while caller_list_old_len != caller_list_new_len: + caller_list_old_len = caller_list_new_len + add_current_caller_list = set() + for callee in current_caller_list: + add_current_caller_list |= add_caller(callee, func_map) + current_caller_list = add_current_caller_list + caller_list |= add_current_caller_list + caller_list_new_len = len(caller_list) + + return caller_list + + +def generate_libc_func_map(libc_dict, func_map): + for key in libc_dict.keys(): + update_libc_func_caller(libc_dict.get(key), func_map) + + +def get_lib_func_to_other_func_maps(elf_path, libc_func_list): + libc_func = get_und_libc_func(elf_path, libc_func_list) + elf_asm_path = create_disassemble_file(elf_path, '.', '.text') + func_map = parse_text_asm_file(elf_asm_path) + libc_dict = generate_libc_dict(libc_func) + generate_libc_func_map(libc_dict, func_map) + return libc_dict + + +def extract_libc_func(callee_und_func_name, libc_func_maps): + libc_func = set() + for func_name in callee_und_func_name: + for key in libc_func_maps.keys(): + if func_name in libc_func_maps.get(key): + libc_func.add(key) + return libc_func + + +def get_function_name_nr_table(src_syscall_path): + function_name_nr_table_dict = {} + for file_name in src_syscall_path: + file_name_tmp = file_name.split('/')[-1] + if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): + continue + gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict) + + return function_name_nr_table_dict + + +def collect_concrete_syscall(args): + if args.target_cpu == 'arm64': + arch_str = 'aarch64-linux' + elif args.target_cpu == 'arm': + arch_str = 'arm-linux' + elif args.target_cpu == 'riscv64': + arch_str = 'riscv64-linux' + libc_path = get_lib_path(args.src_elf_path, 'libc.so', ' | grep ' + arch_str) + libc_asm_path = generate_libc_asm(args.target_cpu, libc_path, '.') + + # get the map of libc function to syscall nr used by the function + libc_func_map = gen_libc.get_syscall_map(args.target_cpu, args.src_syscall_path, libc_asm_path) + + libc_func_used = set() + # get libc function list + libc_func_list = [item.func_name for item in libc_func_map] + + for elf_name in args.elf_name: + elf_name_path = get_lib_path(args.src_elf_path, elf_name, '') + # get libc function symbols used by the elf files + libc_func_used |= set(get_und_libc_func(elf_name_path, libc_func_list)) + current_elf_name_list = args.elf_name + while len(current_elf_name_list) != 0: + for elf_name in current_elf_name_list: + elf_name_path = get_lib_path(args.src_elf_path, elf_name, '') + deps_elf_name_list = extract_elf_name(elf_name_path) + callee_und_func_name = get_und_func_except_libc(elf_name_path, libc_func_list) + + for deps_elf_name in deps_elf_name_list: + deps_elf_path = get_lib_path(args.src_elf_path, deps_elf_name, '') + # get the direct caller and indirect caller of libc function + libc_func_maps = get_lib_func_to_other_func_maps(deps_elf_path, libc_func_list) + libc_func_used |= extract_libc_func(callee_und_func_name, libc_func_maps) + current_elf_name_list = deps_elf_name_list + syscall_nr_list = collect_syscall(libc_func_used, libc_func_map) + + nr_to_func_dict = dict() + function_name_nr_table_dict = get_function_name_nr_table(args.src_syscall_path) + audit_policy.converse_fuction_name_nr(nr_to_func_dict, function_name_nr_table_dict) + content = get_item_content(args.target_cpu, syscall_nr_list, nr_to_func_dict) + + audit_policy.gen_output_file(args.filter_name, content) + remove_disassemble_file('.') + + +def main(): + parser = argparse.ArgumentParser( + description='Generates a seccomp-bpf policy') + parser.add_argument('--src-elf-path', type=str, + help='the drectory of the elf file') + parser.add_argument('--elf-name', action='append', + help='path to syscall to nr files') + parser.add_argument('--src-syscall-path', type=str, action='append', + help=('path to syscall to nr files\n')) + parser.add_argument('--target-cpu', type=str, + help='input arm or arm64 or riscv64') + parser.add_argument('--filter-name', type=str, + help=('consist of output file name\n')) + + args = parser.parse_args() + if args.target_cpu not in gen_policy.supported_architecture: + raise ValueError("target_cpu must int {}".format(gen_policy.supported_architecture)) + + collect_concrete_syscall(args) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/modules/seccomp/scripts/tools/libc_static_analysis.py b/services/modules/seccomp/scripts/tools/libc_static_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..819dcb5b0da768b7f97fd78fec960d4bfdb05865 --- /dev/null +++ b/services/modules/seccomp/scripts/tools/libc_static_analysis.py @@ -0,0 +1,276 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2023 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 argparse +import sys +import generate_code_from_policy as gen_policy + + +class LibcFuncUnit: + def __init__(self, arch, addr, func_name, nr): + self.nr = set() + self.nr |= nr + self.func_name = func_name + self.addr = addr + self.use_function = set() + self.arch = arch + + def merge_nr(self, nr): + self.nr |= nr + + def update_func_name(self, func_name): + self.func_name = func_name + + def update_addr(self, addr): + self.addr = addr + + def update_use_function(self, new_function): + self.use_function.add(new_function) + + def print_info(self, name_nr_table_dict): + keys = list(name_nr_table_dict.get(self.arch).keys()) + values = list(name_nr_table_dict.get(self.arch).values()) + nrs = [keys[values.index(nr_item)] for nr_item in self.nr] + print('{}\t{}\t{} use function is {}'.format(self.addr, self.func_name, nrs, self.use_function)) + + +def remove_head_zero(addr): + pos = 0 + for ch in addr: + if ch != '0': + break + pos += 1 + return addr[pos:] + + +def line_find_syscall_nr(line, nr_set, nr_last): + nr = nr_last + is_find_nr = False + is_find_svc = True + if ';' in line: + nr_tmp, is_digit = gen_policy.str_convert_to_int(line[line.find('0x'):]) + else: + nr_tmp, is_digit = gen_policy.str_convert_to_int(line[line.rfind('#') + 1:]) + if is_digit and 'movt' in line: + nr = nr_tmp * 256 * 256 + return nr, is_find_nr, is_find_svc + + if is_digit and 'movw' in line: + nr = nr + nr_tmp + nr_tmp = nr + nr = nr_tmp + if is_digit: + nr_set.add(nr) + nr_tmp = 0 + nr = 0 + is_find_nr = True + is_find_svc = False + else: + is_find_nr = False + is_find_svc = False + + return nr, is_find_nr, is_find_svc + + +def get_direct_use_syscall_of_svc(arch, lines, func_list): + is_find_nr = False + is_find_svc = False + nr_set = set() + nr = 0 + if arch == 'arm': + svc_reg = 'r7,' + svc_reg1 = 'r7, ' + elif arch == 'arm64': + svc_reg = 'x8,' + svc_reg1 = 'w8,' + elif arch == 'riscv64': + svc_reg = 'x5,' + svc_reg1 = 'x5,' + for line in reversed(lines): + line = line.strip() + if not line: + is_find_nr = False + is_find_svc = False + continue + + if not is_find_svc and ('svc\t' in line or 'svc ' in line): + is_find_nr = False + is_find_svc = True + continue + + if is_find_svc and 'mov' in line and (svc_reg in line or svc_reg1 in line): + nr, is_find_nr, is_find_svc = line_find_syscall_nr(line, nr_set, nr) + continue + + if is_find_nr and line[-1] == ':': + addr = line[:line.find(' ')] + addr = remove_head_zero(addr) + func_name = line[line.find('<') + 1: line.rfind('>')] + func_list.append(LibcFuncUnit(arch, addr, func_name, nr_set)) + nr_set.clear() + is_find_nr = False + is_find_svc = False + + +def get_direct_use_syscall_of_syscall(arch, lines, func_list): + is_find_syscall_nr = False + is_find_syscall = False + nr_tmp = set() + addr_list = [func.addr for func in func_list] + if arch == 'arm': + syscall_reg = 'r0,' + syscall_reg1 = 'r0,' + elif arch == 'arm64': + syscall_reg = 'x0,' + syscall_reg1 = 'w0,' + elif arch == 'riscv64': + syscall_reg = 'x17,' + syscall_reg1 = 'x17,' + + for line in reversed(lines): + line = line.strip() + if not line: + is_find_syscall = False + is_find_syscall_nr = False + continue + + if not is_find_syscall and ('' in line or '<__syscall_cp>' in line): + is_find_syscall = True + is_find_syscall_nr = False + continue + + if is_find_syscall and 'mov' in line and (syscall_reg in line or syscall_reg1 in line): + if ';' in line: + nr, is_digit = gen_policy.str_convert_to_int(line[line.find('0x'):]) + else: + nr, is_digit = gen_policy.str_convert_to_int(line[line.rfind('#') + 1:]) + if is_digit: + nr_tmp.add(nr) + is_find_syscall_nr = True + is_find_syscall = False + continue + + if is_find_syscall_nr and line[-1] == ':': + addr = line[:line.find(' ')] + addr = remove_head_zero(addr) + func_name = line[line.find('<') + 1: line.rfind('>')] + + try: + inedx = addr_list.index(addr) + func_list[inedx].merge_nr(nr_tmp) + except(ValueError): + func_list.append(LibcFuncUnit(arch, addr, func_name, nr_tmp)) + + nr_tmp.clear() + is_find_syscall_nr = False + is_find_syscall = False + + +def get_direct_use_syscall(arch, lines): + func_list = [] + get_direct_use_syscall_of_svc(arch, lines, func_list) + get_direct_use_syscall_of_syscall(arch, lines, func_list) + + return func_list + + +def get_call_graph(arch, lines, func_list): + is_find_function = False + addr_list = [func.addr for func in func_list] + for line in lines: + line = line.strip() + if not line: + is_find_function = False + continue + if not is_find_function and '<' in line and '>:' in line: + is_find_function = True + caller_addr = line[:line.find(' ')] + caller_addr = remove_head_zero(caller_addr) + caller_func_name = line[line.find('<') + 1: line.rfind('>')] + continue + + if is_find_function: + line_info = line.split('\t') + if len(line_info) < 4: + continue + + if not ('b' in line_info[2] and '<' in line_info[3]): + continue + + addr = line_info[3][:line_info[3].find(' ')] + + try: + callee_inedx = addr_list.index(addr) + except(ValueError): + continue + + try: + caller_inedx = addr_list.index(caller_addr) + func_list[caller_inedx].merge_nr(func_list[callee_inedx].nr) + func_list[caller_inedx].update_use_function(func_list[callee_inedx].func_name) + except(ValueError): + func_list.append(LibcFuncUnit(arch, caller_addr, caller_func_name, func_list[callee_inedx].nr)) + func_list[-1].update_use_function(func_list[callee_inedx].func_name) + addr_list.append(caller_addr) + + +def parse_file(arch, file_name): + with open(file_name) as fp: + lines = fp.readlines() + func_list = get_direct_use_syscall(arch, lines) + func_list_old_len = len(func_list) + func_list_new_len = -1 + + while func_list_old_len != func_list_new_len: + func_list_old_len = len(func_list) + get_call_graph(arch, lines, func_list) + func_list_new_len = len(func_list) + + return func_list + + +def get_syscall_map(arch, src_syscall_path, libc_path): + function_name_nr_table_dict = {} + for file_name in src_syscall_path: + file_name_tmp = file_name.split('/')[-1] + if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): + continue + gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict) + func_map = [] + if libc_path.lower().endswith('libc.asm'): + func_map = parse_file(arch, libc_path) + return func_map + + +def main(): + parser = argparse.ArgumentParser( + description='Generates a seccomp-bpf policy') + parser.add_argument('--src-syscall-path', type=str, action='append', + help=('The input files\n')) + parser.add_argument('--libc-asm-path', type=str, + help=('The input files\n')) + parser.add_argument('--target-cpu', type=str, + help=('The input files\n')) + + args = parser.parse_args() + get_syscall_map(args.target_cpu, args.src_syscall_path, args.libc_asm_path) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/modules/seccomp/scripts/tools/merge_policy.py b/services/modules/seccomp/scripts/tools/merge_policy.py new file mode 100644 index 0000000000000000000000000000000000000000..c5bcddbb95f2f1a78513134825ebe0cb4d1e7fcb --- /dev/null +++ b/services/modules/seccomp/scripts/tools/merge_policy.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2023 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 sys +import argparse +import audit_log_analysis as audit_policy +import generate_code_from_policy as gen_policy + + +class MergePolicy: + def __init__(self): + self.cur_parse_item = '' + self.arches = set() + self.seccomp_policy_param = dict() + + @staticmethod + def get_item_content(name_nr_table, item_str, itme_dict): + syscall_name_dict = {} + flag = False + for arch in gen_policy.supported_architecture: + func_name_to_nr = dict() + for item in itme_dict.get(arch): + if ':' in item: + func_name = item[:item.find(':')].strip() + else: + func_name = item + func_name_to_nr.update({item: name_nr_table.get(arch).get(func_name)}) + func_name_to_nr_list = sorted(func_name_to_nr.items(), key=lambda x : x[1]) + + syscall_name_dict.update({arch: func_name_to_nr_list}) + for arch in gen_policy.supported_architecture: + if syscall_name_dict.get(arch): + flag = True + if not flag: + return '' + content = '{}\n'.format(item_str) + + for func_name, _ in syscall_name_dict.get('arm64'): + flag = False + for func_name_arm, nr_arm in syscall_name_dict.get('arm'): + if func_name == func_name_arm: + content = '{}{};all\n'.format(content, func_name) + syscall_name_dict.get('arm').remove((func_name, nr_arm)) + flag = True + break + if not flag: + content = '{}{};arm64\n'.format(content, func_name) + if (syscall_name_dict.get('arm')): + content = '{}{};arm\n'.format(content, ';arm\n'.join( + [func_name for func_name, _ in syscall_name_dict.get('arm')])) + if (syscall_name_dict.get('riscv64')): + content = '{}{};riscv64\n'.format(content, ';riscv64\n'.join( + [func_name for func_name, _ in syscall_name_dict.get('riscv64')])) + return content + + def update_parse_item(self, line): + item = line[1:] + if item in gen_policy.supported_parse_item: + self.cur_parse_item = item + print('start deal with {}'.format(self.cur_parse_item)) + + def parse_line(self, line): + if not self.cur_parse_item : + return + line = line.replace(' ', '') + pos = line.rfind(';') + if pos < 0: + for arch in self.arches: + self.seccomp_policy_param.get(arch).value_function.get(self.cur_parse_item)(line) + else: + arches = line[pos + 1:].split(',') + if arches[0] == 'all': + arches = gen_policy.supported_architecture + for arch in arches: + self.seccomp_policy_param.get(arch).value_function.get(self.cur_parse_item)(line[:pos]) + + + def parse_open_file(self, fp): + for line in fp: + line = line.strip() + if not line: + continue + if line[0] == '#': + continue + if line[0] == '@': + self.update_parse_item(line) + continue + if line[0] != '@' and self.cur_parse_item == '': + continue + self.parse_line(line) + + def parse_file(self, file_path): + with open(file_path) as fp: + self.parse_open_file(fp) + + def merge_policy(self, args): + function_name_nr_table_dict = {} + for file_name in args.src_files: + file_name_tmp = file_name.split('/')[-1] + if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): + continue + gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict) + + for arch in gen_policy.supported_architecture: + self.seccomp_policy_param.update(\ + {arch: gen_policy.SeccompPolicyParam(arch, function_name_nr_table_dict.get(arch))}) + + for file_name in args.src_files: + if file_name.lower().endswith('.policy'): + self.parse_file(file_name) + + dict_priority = dict() + dict_allow_list = dict() + dict_priority_with_args = dict() + dict_allow_list_with_args = dict() + dict_blocklist = dict() + + for arch in gen_policy.supported_architecture: + dict_priority.update({arch: self.seccomp_policy_param.get(arch).priority}) + dict_allow_list.update({arch: self.seccomp_policy_param.get(arch).allow_list}) + dict_priority_with_args.update({arch: self.seccomp_policy_param.get(arch).priority_with_args}) + dict_allow_list_with_args.update({arch: self.seccomp_policy_param.get(arch).allow_list_with_args}) + dict_blocklist.update({arch: self.seccomp_policy_param.get(arch).blocklist}) + + content = self.get_item_content(function_name_nr_table_dict, "@priority", dict_priority) + content += self.get_item_content(function_name_nr_table_dict, "@allowList", dict_allow_list) + content += self.get_item_content(function_name_nr_table_dict, "@priorityWithArgs", dict_priority_with_args) + content += self.get_item_content(function_name_nr_table_dict, "@allowListWithArgs", dict_allow_list_with_args) + content += self.get_item_content(function_name_nr_table_dict, "@blockList", dict_blocklist) + audit_policy.gen_output_file(args.filter_name, content) + + +def main(): + parser = argparse.ArgumentParser( + description='Generates a seccomp-bpf policy') + parser.add_argument('--src-files', type=str, action='append', + help=('input libsyscall_to_nr files and policy filse\n')) + + parser.add_argument('--filter-name', type=str, + help='Name of seccomp bpf array generated by this script') + + args = parser.parse_args() + + generator = MergePolicy() + generator.merge_policy(args) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/modules/seccomp/scripts/tools/strace_log_analysis.py b/services/modules/seccomp/scripts/tools/strace_log_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..57df611749ea2c68412746d84c08d01fe8c2ba9e --- /dev/null +++ b/services/modules/seccomp/scripts/tools/strace_log_analysis.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2023 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 argparse +import sys +import os +import audit_log_analysis as audit_policy +import generate_code_from_policy as gen_policy + + + +def parse_line(fp): + func_name_set = set() + for line in fp: + line = line.strip() + func_name = line[:line.find('(')] + if ' ' in func_name: + func_name = func_name.split(' ')[-1].strip() + func_name_set.add(func_name) + + return func_name_set + + +def get_item_content(arch, func_name_set, name_nr_table): + func_name_to_nr = dict() + for func_name in func_name_set: + if func_name.startswith('arm_'): + func_name = func_name[len('arm_'):] + if func_name in name_nr_table.get(arch).keys(): + func_name_to_nr.update({func_name: name_nr_table.get(arch).get(func_name)}) + + func_name_to_nr_list = sorted(func_name_to_nr.items(), key=lambda x : x[1]) + content = '@allowList\n' + func_name_list = [func_name for func_name, _ in func_name_to_nr_list] + + content = '{}{};{}\n'.format(content, ';{}\n'.format(arch).join(func_name_list), arch) + + return content + + +def parse_file(file_name): + with open(file_name) as f: + return parse_line(f) + + +def parse_strace_log_to_policy(args): + file_list = extract_file_from_path(args.src_path) + function_name_nr_table_dict = {} + for file_name in file_list: + file_name_tmp = file_name.split('/')[-1] + if not file_name_tmp.lower().startswith('libsyscall_to_nr_'): + continue + gen_policy.gen_syscall_nr_table(file_name, function_name_nr_table_dict) + + func_name_set = set() + for file_name in file_list: + if '.strace.log' in file_name.lower(): + func_name_set |= parse_file(file_name) + + content = get_item_content(args.target_cpu, func_name_set, function_name_nr_table_dict) + audit_policy.gen_output_file(args.filter_name, content) + + +def extract_file_from_path(dir_path): + file_list = [] + for path in dir_path: + if path[-1] == '/': + print('input dir path can not end with /') + return [] + + if os.path.isdir(path): + # get file list + file_list_tmp = os.listdir(path) + file_list += ['{}/{}'.format(path, item) for item in file_list_tmp] + + return file_list + + +def main(): + parser = argparse.ArgumentParser( + description='Generates a seccomp-bpf policy') + parser.add_argument('--src-path', action='append', + help='the path of directory which includes strace log and libsyscall_to_nr files') + parser.add_argument('--target-cpu', type=str, + help='input arm or arm64 or riscv64') + parser.add_argument('--filter-name', type=str, + help=('consist of output file name\n')) + + args = parser.parse_args() + if args.target_cpu not in gen_policy.supported_architecture: + raise ValueError("target_cpu must int {}".format(gen_policy.supported_architecture)) + parse_strace_log_to_policy(args) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/services/modules/seccomp/seccomp_policy.c b/services/modules/seccomp/seccomp_policy.c new file mode 100644 index 0000000000000000000000000000000000000000..8db694595790357c18b49ddb4f6b7222c3ddafdc --- /dev/null +++ b/services/modules/seccomp/seccomp_policy.c @@ -0,0 +1,255 @@ +/* + * 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 "seccomp_policy.h" +#include "plugin_adapter.h" +#include "securec.h" +#include "config_policy_utils.h" + +#ifdef WITH_SECCOMP_DEBUG +#include "init_utils.h" +#include "init_param.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef SECCOMP_SET_MODE_FILTER +#define SECCOMP_SET_MODE_FILTER (1) +#endif + +#ifdef __aarch64__ +#define FILTER_LIB_PATH_FORMAT "lib64/seccomp/lib%s_filter.z.so" +#define FILTER_LIB_PATH_PART "lib64/seccomp/lib" +#else +#define FILTER_LIB_PATH_FORMAT "lib/seccomp/lib%s_filter.z.so" +#define FILTER_LIB_PATH_PART "lib/seccomp/lib" +#endif +#define FILTER_NAME_FORMAT "g_%sSeccompFilter" +#define FILTER_SIZE_STRING "Size" + +typedef enum { + SECCOMP_SUCCESS, + INPUT_ERROR, + RETURN_NULL, + RETURN_ERROR, + RETURN_LENGTH_CHECK +} SeccompErrorCode; + +static bool IsSupportFilterFlag(unsigned int filterFlag) +{ + errno = 0; + long ret = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, filterFlag, NULL); + if (ret != -1 || errno != EFAULT) { + PLUGIN_LOGE("not support seccomp flag %u", filterFlag); + return false; + } + + return true; +} + +static bool InstallSeccompPolicy(const struct sock_filter* filter, size_t filterSize, unsigned int filterFlag) +{ + if (filter == NULL) { + return false; + } + + unsigned int flag = 0; + struct sock_fprog prog = { + (unsigned short)filterSize, + (struct sock_filter*)filter + }; + + if (IsSupportFilterFlag(SECCOMP_FILTER_FLAG_TSYNC) && (filterFlag & SECCOMP_FILTER_FLAG_TSYNC)) { + flag |= SECCOMP_FILTER_FLAG_TSYNC; + } + + if (IsSupportFilterFlag(SECCOMP_FILTER_FLAG_LOG) && (filterFlag & SECCOMP_FILTER_FLAG_LOG)) { + flag |= SECCOMP_FILTER_FLAG_LOG; + } + + if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, flag, &prog) != 0) { + PLUGIN_LOGE("SetSeccompFilter failed"); + return false; + } + + return true; +} + +static bool GetFilterFileByName(const char *filterName, char *filterLibRealPath, unsigned int pathSize) +{ + size_t maxFilterNameLen = PATH_MAX - strlen(FILTER_LIB_PATH_FORMAT) + strlen("%s") - 1; + if (filterName == NULL || strlen(filterName) > maxFilterNameLen) { + return false; + } + + bool flag = false; + char filterLibPath[PATH_MAX] = {0}; + + int rc = snprintf_s(filterLibPath, sizeof(filterLibPath), \ + strlen(filterName) + strlen(FILTER_LIB_PATH_FORMAT) - strlen("%s"), \ + FILTER_LIB_PATH_FORMAT, filterName); + if (rc == -1) { + return false; + } + + int seccompPathNum = 0; + CfgFiles *files = GetCfgFiles(filterLibPath); + for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) { + if (files->paths[i]) { + seccompPathNum++; + } + } + + // allow only one path to a seccomp shared library to avoid shared library replaced + if (seccompPathNum == 1 && files && files->paths[0]) { + if (memcpy_s(filterLibRealPath, pathSize, files->paths[0], strlen(files->paths[0]) + 1) == EOK) { + flag = true; + } + } + FreeCfgFiles(files); + + return flag; +} + +static int GetSeccompPolicy(const char *filterName, int **handler, + const char *filterLibRealPath, struct sock_fprog *prog) +{ + if (filterName == NULL || filterLibRealPath == NULL || handler == NULL || prog == NULL) { + return INPUT_ERROR; + } + + if (strstr(filterLibRealPath, FILTER_LIB_PATH_PART) == NULL) { + return INPUT_ERROR; + } + + char filterVaribleName[PATH_MAX] = {0}; + struct sock_filter *filter = NULL; + size_t *filterSize = NULL; + void *policyHanlder = NULL; + int ret = SECCOMP_SUCCESS; + do { + int rc = snprintf_s(filterVaribleName, sizeof(filterVaribleName), \ + strlen(filterName) + strlen(FILTER_NAME_FORMAT) - strlen("%s"), FILTER_NAME_FORMAT, filterName); + if (rc == -1) { + return RETURN_ERROR; + } + char realPath[PATH_MAX] = { 0 }; + realpath(filterLibRealPath, realPath); + policyHanlder = dlopen(realPath, RTLD_LAZY); + PLUGIN_CHECK(policyHanlder != NULL, return RETURN_ERROR, "dlopen error policyHanlder:NULL"); + + filter = (struct sock_filter *)dlsym(policyHanlder, filterVaribleName); + if (filter == NULL) { + ret = RETURN_NULL; + break; + } + + size_t filterVaribleNameLen = strlen(filterVaribleName) + strlen(FILTER_SIZE_STRING) + 1; + if (filterVaribleNameLen > sizeof(filterVaribleName)) { + ret = RETURN_LENGTH_CHECK; + break; + } + rc = strcat_s(filterVaribleName, filterVaribleNameLen, FILTER_SIZE_STRING); + if (rc != 0) { + ret = RETURN_ERROR; + break; + } + + filterSize = (size_t *)dlsym(policyHanlder, filterVaribleName); + if (filterSize == NULL) { + ret = RETURN_NULL; + break; + } + } while (0); + + *handler = (int *)policyHanlder; + prog->filter = filter; + if (filterSize != NULL) { + prog->len = (unsigned short)(*filterSize); + } + + return ret; +} + + +bool IsEnableSeccomp(void) +{ + bool isEnableSeccompFlag = true; +#ifdef WITH_SECCOMP_DEBUG + char value[MAX_BUFFER_LEN] = {0}; + unsigned int len = MAX_BUFFER_LEN; + if (SystemReadParam("persist.init.debug.seccomp.enable", value, &len) == 0) { + if (strncmp(value, "0", len) == 0) { + isEnableSeccompFlag = false; + } + } +#endif + return isEnableSeccompFlag; +} + +bool SetSeccompPolicyWithName(SeccompFilterType type, const char *filterName) +{ + if (filterName == NULL) { + return false; + } + +#ifdef WITH_SECCOMP_DEBUG + if (!IsEnableSeccomp()) { + return true; + } +#endif + + void *handler = NULL; + char filterLibRealPath[PATH_MAX] = {0}; + struct sock_fprog prog; + bool ret = false; + const char *filterNamePtr = filterName; + + bool flag = GetFilterFileByName(filterNamePtr, filterLibRealPath, sizeof(filterLibRealPath)); + if (!flag) { + if (type == SYSTEM_SA) { + filterNamePtr = SYSTEM_NAME; + flag = GetFilterFileByName(filterNamePtr, filterLibRealPath, sizeof(filterLibRealPath)); + PLUGIN_CHECK(flag == true, return ret, "get filter name failed"); + } else if (type == SYSTEM_OTHERS) { + return true; + } else { + PLUGIN_LOGE("get filter name failed"); + return ret; + } + } + + int retCode = GetSeccompPolicy(filterNamePtr, (int **)&handler, filterLibRealPath, &prog); + if (retCode == SECCOMP_SUCCESS) { + ret = InstallSeccompPolicy(prog.filter, prog.len, SECCOMP_FILTER_FLAG_LOG); + } else { + PLUGIN_LOGE("get seccomp policy failed return is %d and path is %s", retCode, filterLibRealPath); + } +#ifndef COVERAGE_TEST + if (handler != NULL) { + dlclose(handler); + } +#endif + return ret; +} diff --git a/services/modules/seccomp/seccomp_policy/app.blocklist.seccomp.policy b/services/modules/seccomp/seccomp_policy/app.blocklist.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..f8e6b8a70d7ff125f729927cde0348c6506a1fb0 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/app.blocklist.seccomp.policy @@ -0,0 +1,53 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@blockList +umount2;all +mount;all +chroot;all +acct;all +init_module;all +finit_module;all +delete_module;all +clock_settime;all +syslog;all +reboot;all +setregid;arm64 +setregid;riscv64 +setgid;arm64 +setgid;riscv64 +setreuid;arm64 +setreuid;riscv64 +setuid;arm64 +setuid;riscv64 +setfsuid;all +setfsgid;all +sethostname;all +setdomainname;all +settimeofday;all +adjtimex;all +swapon;all +swapoff;all +clock_adjtime;all +setreuid32;arm +setregid32;arm +setuid32;arm +setgid32;arm +setgroups;arm64 +setgroups;riscv64 +setgroups32;arm +setresgid;arm64 +setresgid;riscv64 +setresgid32;arm diff --git a/services/modules/seccomp/seccomp_policy/app.seccomp.policy b/services/modules/seccomp/seccomp_policy/app.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..8ac9c348f5a4110774b07bdb80390fa5b0ba0419 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/app.seccomp.policy @@ -0,0 +1,332 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@headFiles + + + +@priority +ioctl;all +futex;all + +@allowList +io_setup;all +io_destroy;all +io_submit;all +io_cancel;all +io_getevents;all +setxattr;all +lsetxattr;all +fsetxattr;all +getxattr;all +lgetxattr;all +fgetxattr;all +listxattr;all +llistxattr;all +flistxattr;all +removexattr;all +lremovexattr;all +fremovexattr;all +getcwd;all +eventfd2;all +epoll_create1;all +epoll_ctl;all +epoll_pwait;all +dup;all +dup3;all +fcntl;all +inotify_init1;all +inotify_add_watch;all +inotify_rm_watch;all +ioctl;all +ioprio_set;arm64 +ioprio_set;riscv64 +ioprio_get;arm64 +ioprio_get;riscv64 +flock;all +mknodat;all +mkdirat;all +unlinkat;all +symlinkat;all +linkat;all +renameat;arm +renameat;arm64 +pivot_root;riscv64 +statfs;arm64 +statfs;riscv64 +fstatfs;arm64 +fstatfs;riscv64 +truncate;all +ftruncate;arm64 +ftruncate;riscv64 +fallocate;all +faccessat;all +chdir;all +fchdir;all +fchmod;all +fchmodat;all +fchownat;all +fchown;arm64 +fchown;riscv64 +openat;all +close;all +pipe2;all +quotactl;all +getdents64;all +lseek;all +read;all +write;all +readv;all +writev;all +pread64;all +pwrite64;all +preadv;all +pwritev;all +sendfile;all +pselect6;all +ppoll;all +signalfd4;all +vmsplice;all +splice;all +tee;all +readlinkat;all +newfstatat;arm64 +newfstatat;riscv64 +fstat;arm64 +fstat;riscv64 +sync;all +fsync;all +fdatasync;all +sync_file_range;arm64 +sync_file_range;riscv64 +timerfd_create;all +timerfd_settime;all +timerfd_gettime;all +utimensat;all +capget;all +capset;all +personality;all +exit;all +exit_group;all +waitid;all +set_tid_address;all +futex;all +nanosleep;all +getitimer;all +setitimer;all +timer_create;all +timer_gettime;all +timer_getoverrun;all +timer_settime;all +timer_delete;all +clock_gettime;all +clock_getres;all +clock_nanosleep;all +ptrace;all +sched_setparam;all +sched_setscheduler;all +sched_getscheduler;all +sched_getparam;all +sched_setaffinity;all +sched_getaffinity;all +sched_yield;all +sched_get_priority_max;all +sched_get_priority_min;all +sched_rr_get_interval;all +restart_syscall;all +kill;all +tkill;all +tgkill;all +sigaltstack;all +rt_sigsuspend;all +rt_sigaction;all +rt_sigprocmask;all +rt_sigpending;all +rt_sigtimedwait;all +rt_sigqueueinfo;all +rt_sigreturn;all +setpriority;all +getpriority;all +setresuid;arm64 +setresuid;riscv64 +getresuid;arm64 +getresuid;riscv64 +getresgid;arm64 +getresgid;riscv64 +times;all +setpgid;all +getpgid;all +getsid;all +setsid;all +getgroups;arm64 +getgroups;riscv64 +uname;all +getrlimit;arm64 +getrlimit;riscv64 +setrlimit;all +getrusage;all +umask;all +prctl;all +getcpu;all +gettimeofday;all +getpid;all +getppid;all +getuid;all +geteuid;arm64 +geteuid;riscv64 +getgid;arm64 +getgid;riscv64 +getegid;arm64 +getegid;riscv64 +gettid;all +sysinfo;all +socket;all +socketpair;all +bind;all +listen;all +accept;all +connect;all +getsockname;all +getpeername;all +sendto;all +recvfrom;all +setsockopt;all +getsockopt;all +shutdown;all +sendmsg;all +recvmsg;all +readahead;all +brk;all +munmap;all +mremap;all +execve;all +mmap;arm64 +mmap;riscv64 +fadvise64;arm64 +fadvise64;riscv64 +mprotect;all +msync;all +mlock;all +munlock;all +mlockall;all +munlockall;all +mincore;all +madvise;all +rt_tgsigqueueinfo;all +perf_event_open;all +accept4;all +recvmmsg;all +wait4;all +prlimit64;all +syncfs;all +sendmmsg;all +process_vm_readv;all +process_vm_writev;all +sched_setattr;all +sched_getattr;all +renameat2;all +seccomp;all +getrandom;all +memfd_create;all +execveat;all +userfaultfd;all +membarrier;all +mlock2;all +copy_file_range;all +preadv2;all +pwritev2;all +statx;all +pidfd_send_signal;all +pidfd_open;all +pidfd_getfd;all +faccessat2;all +process_madvise;all +set_robust_list;all +fork;arm +open;arm +creat;arm +link;arm +unlink;arm +chmod;arm +access;arm +rename;arm +mkdir;arm +rmdir;arm +pipe;arm +dup2;arm +sigaction;arm +symlink;arm +readlink;arm +sigreturn;arm +_llseek;arm +getdents;arm +_newselect;arm +poll;arm +vfork;arm +ugetrlimit;arm +mmap2;arm +truncate64;arm +ftruncate64;arm +stat64;arm +lstat64;arm +fstat64;arm +lchown32;arm +getuid32;arm +getgid32;arm +geteuid32;arm +getegid32;arm +getgroups32;arm +fchown32;arm +setresuid32;arm +getresuid32;arm +getresgid32;arm +chown32;arm +fcntl64;arm +sendfile64;arm +epoll_create;arm +epoll_wait;arm +remap_file_pages;arm +statfs64;arm +fstatfs64;arm +fadvise64_64;arm +inotify_init;arm +fstatat64;arm +sync_file_range2;arm +eventfd;arm +clock_gettime64;arm +clock_settime64;arm +clock_adjtime64;arm +clock_getres_time64;arm +clock_nanosleep_time64;arm +timer_gettime64;arm +timer_settime64;arm +timerfd_gettime64;arm +timerfd_settime64;arm +utimensat_time64;arm +pselect6_time64;arm +ppoll_time64;arm +recvmmsg_time64;arm +semtimedop_time64;arm +rt_sigtimedwait_time64;arm +futex_time64;arm +sched_rr_get_interval_time64;arm +cacheflush;arm +set_tls;arm + +@allowListWithArgs +clone: if (arg0 & (CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWCGROUP | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)) == 0 ; return ALLOW; else return TRAP;all diff --git a/services/modules/seccomp/seccomp_policy/app_privilege.seccomp.policy b/services/modules/seccomp/seccomp_policy/app_privilege.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..84e433348fac6802c76ff494d9c18e7ec721bdb6 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/app_privilege.seccomp.policy @@ -0,0 +1,344 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@headFiles + + + +@priority +ioctl;all +futex;all + +@allowList +io_setup;all +io_destroy;all +io_submit;all +io_cancel;all +io_getevents;all +setxattr;all +lsetxattr;all +fsetxattr;all +getxattr;all +lgetxattr;all +fgetxattr;all +listxattr;all +llistxattr;all +flistxattr;all +removexattr;all +lremovexattr;all +fremovexattr;all +getcwd;all +eventfd2;all +epoll_create1;all +epoll_ctl;all +epoll_pwait;all +dup;all +dup3;all +fcntl;all +inotify_init1;all +inotify_add_watch;all +inotify_rm_watch;all +ioctl;all +ioprio_set;arm64 +ioprio_set;riscv64 +ioprio_get;arm64 +ioprio_get;riscv64 +flock;all +mknodat;all +mkdirat;all +unlinkat;all +symlinkat;all +linkat;all +renameat;arm +renameat;arm64 +pivot_root;riscv64 +statfs;arm64 +statfs;riscv64 +fstatfs;arm64 +fstatfs;riscv64 +truncate;all +ftruncate;arm64 +ftruncate;riscv64 +fallocate;all +faccessat;all +chdir;all +fchdir;all +fchmod;all +fchmodat;all +fchownat;all +fchown;arm64 +fchown;riscv64 +openat;all +close;all +pipe2;all +quotactl;all +getdents64;all +lseek;all +read;all +write;all +readv;all +writev;all +pread64;all +pwrite64;all +preadv;all +pwritev;all +sendfile;all +pselect6;all +ppoll;all +signalfd4;all +vmsplice;all +splice;all +tee;all +readlinkat;all +newfstatat;arm64 +newfstatat;riscv64 +fstat;arm64 +fstat;riscv64 +sync;all +fsync;all +fdatasync;all +sync_file_range;arm64 +sync_file_range;riscv64 +timerfd_create;all +timerfd_settime;all +timerfd_gettime;all +utimensat;all +capget;all +capset;all +personality;all +exit;all +exit_group;all +waitid;all +set_tid_address;all +futex;all +nanosleep;all +getitimer;all +setitimer;all +timer_create;all +timer_gettime;all +timer_getoverrun;all +timer_settime;all +timer_delete;all +clock_gettime;all +clock_getres;all +clock_nanosleep;all +ptrace;all +sched_setparam;all +sched_setscheduler;all +sched_getscheduler;all +sched_getparam;all +sched_setaffinity;all +sched_getaffinity;all +sched_yield;all +sched_get_priority_max;all +sched_get_priority_min;all +sched_rr_get_interval;all +restart_syscall;all +kill;all +tkill;all +tgkill;all +sigaltstack;all +rt_sigsuspend;all +rt_sigaction;all +rt_sigprocmask;all +rt_sigpending;all +rt_sigtimedwait;all +rt_sigqueueinfo;all +rt_sigreturn;all +setpriority;all +getpriority;all +setresgid;arm64 +setresgid;riscv64 +setgid;arm64 +setgid;riscv64 +setuid;arm64 +setuid;riscv64 +setresuid;arm64 +setresuid;riscv64 +getresuid;arm64 +getresuid;riscv64 +getresgid;arm64 +getresgid;riscv64 +times;all +setpgid;all +getpgid;all +getsid;all +setsid;all +getgroups;arm64 +getgroups;riscv64 +setgroups;arm64 +setgroups;riscv64 +uname;all +getrlimit;arm64 +getrlimit;riscv64 +setrlimit;all +getrusage;all +umask;all +prctl;all +getcpu;all +gettimeofday;all +getpid;all +getppid;all +getuid;all +geteuid;arm64 +geteuid;riscv64 +getgid;arm64 +getgid;riscv64 +getegid;arm64 +getegid;riscv64 +gettid;all +sysinfo;all +socket;all +socketpair;all +bind;all +listen;all +accept;all +connect;all +getsockname;all +getpeername;all +sendto;all +recvfrom;all +setsockopt;all +getsockopt;all +shutdown;all +sendmsg;all +recvmsg;all +readahead;all +brk;all +munmap;all +mremap;all +execve;all +mmap;arm64 +mmap;riscv64 +fadvise64;arm64 +fadvise64;riscv64 +mprotect;all +msync;all +mlock;all +munlock;all +mlockall;all +munlockall;all +mincore;all +madvise;all +rt_tgsigqueueinfo;all +perf_event_open;all +accept4;all +recvmmsg;all +wait4;all +prlimit64;all +syncfs;all +sendmmsg;all +process_vm_readv;all +process_vm_writev;all +sched_setattr;all +sched_getattr;all +renameat2;all +seccomp;all +getrandom;all +memfd_create;all +execveat;all +userfaultfd;all +membarrier;all +mlock2;all +copy_file_range;all +preadv2;all +pwritev2;all +statx;all +pidfd_send_signal;all +pidfd_open;all +pidfd_getfd;all +faccessat2;all +process_madvise;all +set_robust_list;all +fork;arm +open;arm +creat;arm +link;arm +unlink;arm +chmod;arm +access;arm +rename;arm +mkdir;arm +rmdir;arm +pipe;arm +dup2;arm +sigaction;arm +symlink;arm +readlink;arm +sigreturn;arm +_llseek;arm +getdents;arm +_newselect;arm +poll;arm +vfork;arm +ugetrlimit;arm +mmap2;arm +truncate64;arm +ftruncate64;arm +stat64;arm +lstat64;arm +fstat64;arm +lchown32;arm +getuid32;arm +getgid32;arm +geteuid32;arm +getegid32;arm +getgroups32;arm +fchown32;arm +setgroups32;arm +setresuid32;arm +setresgid32;arm +getresuid32;arm +getresgid32;arm +chown32;arm +setuid32;arm +setgid32;arm +fcntl64;arm +sendfile64;arm +epoll_create;arm +epoll_wait;arm +remap_file_pages;arm +statfs64;arm +fstatfs64;arm +fadvise64_64;arm +inotify_init;arm +fstatat64;arm +sync_file_range2;arm +eventfd;arm +clock_gettime64;arm +clock_settime64;arm +clock_adjtime64;arm +clock_getres_time64;arm +clock_nanosleep_time64;arm +timer_gettime64;arm +timer_settime64;arm +timerfd_gettime64;arm +timerfd_settime64;arm +utimensat_time64;arm +pselect6_time64;arm +ppoll_time64;arm +recvmmsg_time64;arm +semtimedop_time64;arm +rt_sigtimedwait_time64;arm +futex_time64;arm +sched_rr_get_interval_time64;arm +cacheflush;arm +set_tls;arm + +@allowListWithArgs +clone: if (arg0 & (CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWCGROUP | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)) == 0 ; return ALLOW; else return TRAP;all diff --git a/services/modules/seccomp/seccomp_policy/nwebspawn.seccomp.policy b/services/modules/seccomp/seccomp_policy/nwebspawn.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..853b6b95ac8fa910ea5f3e52ef9aaef0353cb23a --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/nwebspawn.seccomp.policy @@ -0,0 +1,42 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@headFiles +"seccomp_policy_constants.h" + +@mode +ONLY_CHECK_ARGS + +@allowListWithArgs +setresuid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS && arg2 >= START_UID_FOR_RENDER_PROCESS && arg2 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setresgid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS && arg2 >= START_UID_FOR_RENDER_PROCESS && arg2 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setresuid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS && arg2 >= START_UID_FOR_RENDER_PROCESS && arg2 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setresgid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS && arg2 >= START_UID_FOR_RENDER_PROCESS && arg2 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setuid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setgid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setuid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setgid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setreuid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setregid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setreuid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setregid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS && arg1 >= START_UID_FOR_RENDER_PROCESS && arg1 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setfsuid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setfsgid: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;all +setfsuid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm +setfsgid32: if arg0 >= START_UID_FOR_RENDER_PROCESS && arg0 <= END_UID_FOR_RENDER_PROCESS; return ALLOW; else return TRAP;arm + diff --git a/services/modules/seccomp/seccomp_policy/privileged_process.seccomp.policy b/services/modules/seccomp/seccomp_policy/privileged_process.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..76093ee2093f4532d438ed80192b529b46e34805 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/privileged_process.seccomp.policy @@ -0,0 +1,14 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. diff --git a/services/modules/seccomp/seccomp_policy/spawn.seccomp.policy b/services/modules/seccomp/seccomp_policy/spawn.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..881a953127644d69e43b52ff45dda0513387eeb9 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/spawn.seccomp.policy @@ -0,0 +1,41 @@ +# Copyright (c) 2023 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. + +@returnValue +TRAP + +@headFiles +"seccomp_policy_constants.h" + +@mode +ONLY_CHECK_ARGS + +@allowListWithArgs +setresuid: if arg0 >= APP_UID_START && arg1 >= APP_UID_START && arg2 >= APP_UID_START; return ALLOW; else return TRAP;arm64 +setresgid: if arg0 >= APP_UID_START && arg1 >= APP_UID_START && arg2 >= APP_UID_START; return ALLOW; else return TRAP;arm64 +setresuid: if arg0 >= APP_UID_START && arg1 >= APP_UID_START && arg2 >= APP_UID_START; return ALLOW; else return TRAP;riscv64 +setresgid: if arg0 >= APP_UID_START && arg1 >= APP_UID_START && arg2 >= APP_UID_START; return ALLOW; else return TRAP;riscv64 +setresuid32: if arg0 >= APP_UID_START && arg1 >= APP_UID_START && arg2 >= APP_UID_START; return ALLOW; else return TRAP;arm +setresgid32: if arg0 >= APP_UID_START && arg1 >= APP_UID_START && arg2 >= APP_UID_START; return ALLOW; else return TRAP;arm +setuid: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;all +setgid: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;all +setuid32: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;arm +setgid32: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;arm +setreuid: if arg0 >= APP_UID_START && arg1 >= APP_UID_START; return ALLOW; else return TRAP;all +setregid: if arg0 >= APP_UID_START && arg1 >= APP_UID_START; return ALLOW; else return TRAP;all +setreuid32: if arg0 >= APP_UID_START && arg1 >= APP_UID_START; return ALLOW; else return TRAP;arm +setregid32: if arg0 >= APP_UID_START && arg1 >= APP_UID_START; return ALLOW; else return TRAP;arm +setfsuid: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;all +setfsgid: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;all +setfsuid32: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;arm +setfsgid32: if arg0 >= APP_UID_START; return ALLOW; else return TRAP;arm diff --git a/services/modules/seccomp/seccomp_policy/system.blocklist.seccomp.policy b/services/modules/seccomp/seccomp_policy/system.blocklist.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..21057777c895d830bcf37a3085359789570eab1f --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/system.blocklist.seccomp.policy @@ -0,0 +1,18 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@blockList +swapon;all +swapoff;all diff --git a/services/modules/seccomp/seccomp_policy/system.seccomp.policy b/services/modules/seccomp/seccomp_policy/system.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..0a78136ee8084e462ac9284b46eaef11a5a9ff46 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/system.seccomp.policy @@ -0,0 +1,365 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@allowList +io_setup;all +io_destroy;all +io_submit;all +io_cancel;all +io_getevents;all +setxattr;all +lsetxattr;all +fsetxattr;all +getxattr;all +lgetxattr;all +fgetxattr;all +listxattr;all +llistxattr;all +flistxattr;all +removexattr;all +lremovexattr;all +fremovexattr;all +getcwd;all +eventfd2;all +epoll_create1;all +epoll_ctl;all +epoll_pwait;all +dup;all +dup3;all +fcntl;arm64 +fcntl;riscv64 +inotify_init1;all +inotify_add_watch;all +inotify_rm_watch;all +ioctl;all +ioprio_set;arm64 +ioprio_set;riscv64 +ioprio_get;arm64 +ioprio_get;riscv64 +flock;all +mknodat;all +mkdirat;all +unlinkat;all +symlinkat;all +linkat;all +renameat;arm +renameat;arm64 +umount2;all +mount;all +pivot_root;all +statfs;arm64 +statfs;riscv64 +fstatfs;arm64 +fstatfs;riscv64 +truncate;all +ftruncate;arm64 +ftruncate;riscv64 +fallocate;all +faccessat;all +faccessat2;all +chdir;all +fchdir;all +chroot;all +fchmod;all +fchmodat;all +fchownat;all +fchown;arm64 +fchown;riscv64 +openat;all +close;all +pipe2;all +quotactl;all +getdents64;all +lseek;all +read;all +write;all +readv;all +writev;all +pread64;all +pwrite64;all +preadv;all +pwritev;all +sendfile;all +pselect6;all +ppoll;all +signalfd4;all +vmsplice;all +splice;all +tee;all +readlinkat;all +newfstatat;arm64 +newfstatat;riscv64 +fstat;arm64 +fstat;riscv64 +sync;all +fsync;all +fdatasync;all +sync_file_range;arm64 +sync_file_range;riscv64 +timerfd_create;all +timerfd_settime;all +timerfd_gettime;all +utimensat;all +acct;all +capget;all +capset;all +personality;all +exit;all +exit_group;all +waitid;all +set_tid_address;all +unshare;all +futex;all +set_robust_list;all +get_robust_list;all +nanosleep;all +getitimer;all +setitimer;all +init_module;all +delete_module;all +timer_create;all +timer_gettime;all +timer_getoverrun;all +timer_settime;all +timer_delete;all +clock_settime;all +clock_gettime;all +clock_getres;all +clock_nanosleep;all +syslog;all +ptrace;all +sched_setparam;all +sched_setscheduler;all +sched_getscheduler;all +sched_getparam;all +sched_setaffinity;all +sched_getaffinity;all +sched_yield;all +sched_get_priority_max;all +sched_get_priority_min;all +sched_rr_get_interval;all +restart_syscall;all +kill;all +tkill;all +tgkill;all +sigaltstack;all +rt_sigsuspend;all +rt_sigaction;all +rt_sigprocmask;all +rt_sigpending;all +rt_sigtimedwait;all +rt_sigqueueinfo;all +rt_sigreturn;all +setpriority;all +getpriority;all +reboot;all +setregid;arm64 +setregid;riscv64 +setgid;arm64 +setgid;riscv64 +setreuid;arm64 +setreuid;riscv64 +setuid;arm64 +setuid;riscv64 +setresuid;arm64 +setresuid;riscv64 +getresuid;arm64 +getresuid;riscv64 +setresgid;arm64 +setresgid;riscv64 +getresgid;arm64 +getresgid;riscv64 +setfsuid;all +setfsgid;all +times;all +setpgid;all +getpgid;all +getsid;all +setsid;all +getgroups;arm64 +getgroups;riscv64 +setgroups;arm64 +setgroups;riscv64 +uname;all +sethostname;all +setdomainname;all +getrlimit;arm64 +getrlimit;riscv64 +setrlimit;all +getrusage;all +umask;all +prctl;all +getcpu;all +gettimeofday;all +settimeofday;all +adjtimex;all +getpid;all +getppid;all +getuid;arm64 +getuid;riscv64 +geteuid;arm64 +geteuid;riscv64 +getgid;arm64 +getgid;riscv64 +getegid;arm64 +getegid;riscv64 +gettid;all +sysinfo;all +semget;all +shmget;all +shmctl;all +shmat;all +shmdt;all +socket;all +socketpair;all +bind;all +listen;all +accept;all +connect;all +getsockname;all +getpeername;all +sendto;all +recvfrom;all +setsockopt;all +getsockopt;all +shutdown;all +sendmsg;all +recvmsg;all +readahead;all +brk;all +munmap;all +mremap;all +add_key;all +keyctl;all +clone;all +execve;all +mmap;arm64 +mmap;riscv64 +fadvise64;arm64 +fadvise64;riscv64 +mprotect;all +msync;all +mlock;all +munlock;all +mlockall;all +munlockall;all +mincore;all +madvise;all +rt_tgsigqueueinfo;all +perf_event_open;all +accept4;all +recvmmsg;all +wait4;all +prlimit64;all +clock_adjtime;all +syncfs;all +setns;all +sendmmsg;all +process_vm_readv;all +process_vm_writev;all +finit_module;all +sched_setattr;all +sched_getattr;all +renameat2;all +seccomp;all +getrandom;all +memfd_create;all +bpf;all +execveat;all +userfaultfd;all +membarrier;all +mlock2;all +copy_file_range;all +preadv2;all +pwritev2;all +statx;all +pidfd_send_signal;all +pidfd_open;all +close_range;all +pidfd_getfd;all +process_madvise;all +fork;arm +open;arm +unlink;arm +mknod;arm +chmod;arm +access;arm +rename;arm +mkdir;arm +rmdir;arm +pipe;arm +dup2;arm +sigaction;arm +symlink;arm +readlink;arm +stat;arm +sigreturn;arm +_llseek;arm +_newselect;arm +poll;arm +vfork;arm +ugetrlimit;arm +mmap2;arm +truncate64;arm +ftruncate64;arm +stat64;arm +fstat64;arm +lchown32;arm +getuid32;arm +getgid32;arm +geteuid32;arm +getegid32;arm +setreuid32;arm +setregid32;arm +chown32;arm +getgroups32;arm +setgroups32;arm +fchown32;arm +setresuid32;arm +getresuid32;arm +setresgid32;arm +getresgid32;arm +setuid32;arm +setgid32;arm +fcntl64;arm +sendfile64;arm +statfs64;arm +fstatfs64;arm +fadvise64_64;arm +fstatat64;arm +sync_file_range2;arm +clock_gettime64;arm +clock_settime64;arm +clock_adjtime64;arm +clock_getres_time64;arm +clock_nanosleep_time64;arm +timer_gettime64;arm +timer_settime64;arm +timerfd_gettime64;arm +timerfd_settime64;arm +utimensat_time64;arm +pselect6_time64;arm +ppoll_time64;arm +recvmmsg_time64;arm +semtimedop_time64;arm +rt_sigtimedwait_time64;arm +futex_time64;arm +sched_rr_get_interval_time64;arm +cacheflush;arm +set_tls;arm +mbind;all diff --git a/services/modules/seccomp/seccomp_policy/system_uid_filter.seccomp.policy b/services/modules/seccomp/seccomp_policy/system_uid_filter.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..423f20c83b39854edcaad4b3c76042194e95aef2 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/system_uid_filter.seccomp.policy @@ -0,0 +1,27 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@allowListWithArgs +setuid: if arg0 != 0; return ALLOW; else return TRAP;all +setreuid: if arg0 != 0 && arg1 != 0; return ALLOW; else return TRAP;all +setfsuid: if arg0 != 0; return ALLOW; else return TRAP;all +setresuid: if arg0 != 0 && arg1 != 0 && arg2 != 0; return ALLOW; else return TRAP;all +setuid32: if arg0 != 0; return ALLOW; else return TRAP;arm +setreuid32: if arg0 != 0 && arg1 != 0; return ALLOW; else return TRAP;arm +setfsuid32: if arg0 != 0; return ALLOW; else return TRAP;arm +setresuid32: if arg0 != 0 && arg1 != 0 && arg2 != 0; return ALLOW; else return TRAP;arm diff --git a/services/modules/seccomp/seccomp_policy/updater.seccomp.policy b/services/modules/seccomp/seccomp_policy/updater.seccomp.policy new file mode 100644 index 0000000000000000000000000000000000000000..32aa92aa015b461098707bc196ba10f3a9a7173e --- /dev/null +++ b/services/modules/seccomp/seccomp_policy/updater.seccomp.policy @@ -0,0 +1,331 @@ +# Copyright (c) 2023 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. + +# For now, it supports architechture of ['arm', 'arm64', 'riscv64']. + +@returnValue +TRAP + +@allowList +setxattr;all +lsetxattr;all +fsetxattr;all +getxattr;all +lgetxattr;all +fgetxattr;all +getcwd;all +eventfd2;all +epoll_create1;all +epoll_ctl;all +epoll_pwait;all +dup;all +dup3;all +fcntl;arm64 +fcntl;riscv64 +inotify_init1;all +inotify_add_watch;all +inotify_rm_watch;all +ioctl;all +ioprio_set;arm64 +ioprio_set;riscv64 +ioprio_get;arm64 +ioprio_get;riscv64 +flock;all +mknodat;all +mkdirat;all +unlinkat;all +symlinkat;all +linkat;all +renameat;arm +renameat;arm64 +umount2;all +mount;all +statfs;arm64 +statfs;riscv64 +fstatfs;arm64 +fstatfs;riscv64 +truncate;all +ftruncate;arm64 +ftruncate;riscv64 +fallocate;all +faccessat;all +chdir;all +fchdir;all +chroot;all +fchmod;all +fchmodat;all +fchownat;all +fchown;arm64 +fchown;riscv64 +openat;all +close;all +pipe2;all +quotactl;all +getdents64;all +lseek;all +read;all +write;all +readv;all +writev;all +pread64;all +pwrite64;all +preadv;all +pwritev;all +sendfile;all +pselect6;all +ppoll;all +signalfd4;all +vmsplice;all +splice;all +tee;all +readlinkat;all +newfstatat;arm64 +newfstatat;riscv64 +fstat;arm64 +fstat;riscv64 +sync;all +fsync;all +fdatasync;all +sync_file_range;arm64 +sync_file_range;riscv64 +utimensat;all +acct;all +capget;all +capset;all +personality;all +exit;all +exit_group;all +waitid;all +set_tid_address;all +unshare;all +futex;all +set_robust_list;all +get_robust_list;all +nanosleep;all +timer_create;all +timer_gettime;all +timer_getoverrun;all +timer_settime;all +timer_delete;all +clock_gettime;all +clock_getres;all +clock_nanosleep;all +syslog;all +ptrace;all +sched_setparam;all +sched_setscheduler;all +sched_getscheduler;all +sched_getparam;all +sched_setaffinity;all +sched_getaffinity;all +sched_yield;all +sched_get_priority_max;all +sched_get_priority_min;all +sched_rr_get_interval;all +restart_syscall;all +kill;all +tkill;all +tgkill;all +sigaltstack;all +rt_sigsuspend;all +rt_sigaction;all +rt_sigprocmask;all +rt_sigpending;all +rt_sigtimedwait;all +rt_sigqueueinfo;all +rt_sigreturn;all +setpriority;all +getpriority;all +reboot;all +setregid;arm64 +setregid;riscv64 +setgid;arm64 +setgid;riscv64 +setreuid;arm64 +setreuid;riscv64 +setuid;arm64 +setuid;riscv64 +setresuid;arm64 +setresuid;riscv64 +getresuid;arm64 +getresuid;riscv64 +setresgid;arm64 +setresgid;riscv64 +getresgid;arm64 +getresgid;riscv64 +setfsuid;all +setfsgid;all +times;all +setpgid;all +getpgid;all +getsid;all +setsid;all +getgroups;arm64 +getgroups;riscv64 +setgroups;arm64 +setgroups;riscv64 +uname;all +sethostname;all +setdomainname;all +getrlimit;arm64 +getrlimit;riscv64 +setrlimit;all +getrusage;all +umask;all +prctl;all +getcpu;all +gettimeofday;all +settimeofday;all +adjtimex;all +getpid;all +getppid;all +getuid;arm64 +getuid;riscv64 +geteuid;arm64 +geteuid;riscv64 +getgid;arm64 +getgid;riscv64 +getegid;arm64 +getegid;riscv64 +gettid;all +sysinfo;all +semget;all +shmget;all +shmctl;all +shmat;all +shmdt;all +socket;all +socketpair;all +bind;all +listen;all +accept;all +connect;all +getsockname;all +getpeername;all +sendto;all +recvfrom;all +setsockopt;all +getsockopt;all +shutdown;all +sendmsg;all +recvmsg;all +readahead;all +brk;all +munmap;all +mremap;all +add_key;all +keyctl;all +clone;all +execve;all +mmap;arm64 +mmap;riscv64 +fadvise64;arm64 +fadvise64;riscv64 +mprotect;all +msync;all +mlock;all +munlock;all +mlockall;all +munlockall;all +mincore;all +madvise;all +rt_tgsigqueueinfo;all +perf_event_open;all +accept4;all +recvmmsg;all +wait4;all +prlimit64;all +clock_adjtime;all +syncfs;all +setns;all +sendmmsg;all +process_vm_readv;all +process_vm_writev;all +finit_module;all +sched_setattr;all +sched_getattr;all +renameat2;all +seccomp;all +getrandom;all +memfd_create;all +bpf;all +execveat;all +userfaultfd;all +membarrier;all +mlock2;all +copy_file_range;all +preadv2;all +pwritev2;all +statx;all +pidfd_send_signal;all +pidfd_open;all +close_range;all +pidfd_getfd;all +process_madvise;all +fork;arm +open;arm +unlink;arm +mknod;arm +chmod;arm +access;arm +rename;arm +mkdir;arm +rmdir;arm +pipe;arm +dup2;arm +sigaction;arm +symlink;arm +readlink;arm +stat;arm +sigreturn;arm +_llseek;arm +_newselect;arm +poll;arm +vfork;arm +ugetrlimit;arm +mmap2;arm +truncate64;arm +ftruncate64;arm +stat64;arm +fstat64;arm +lchown32;arm +getuid32;arm +getgid32;arm +geteuid32;arm +getegid32;arm +setreuid32;arm +setregid32;arm +chown32;arm +getgroups32;arm +setgroups32;arm +fchown32;arm +setresuid32;arm +getresuid32;arm +setresgid32;arm +getresgid32;arm +setuid32;arm +setgid32;arm +fcntl64;arm +sendfile64;arm +statfs64;arm +fstatfs64;arm +fadvise64_64;arm +fstatat64;arm +sync_file_range2;arm +clock_gettime64;arm +cacheflush;arm +set_tls;arm +setitimer;all +timerfd_create;all +timerfd_gettime;all +timerfd_settime;all diff --git a/services/param/include/param_service.h b/services/modules/seccomp/seccomp_policy_constants.h similarity index 59% rename from services/param/include/param_service.h rename to services/modules/seccomp/seccomp_policy_constants.h index 8a0d8554937c2b103626963113db0b6364832152..359ccdb1490d58959d557c8a74500503d50d7be5 100644 --- a/services/param/include/param_service.h +++ b/services/modules/seccomp/seccomp_policy_constants.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2023 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 @@ -13,25 +13,24 @@ * limitations under the License. */ -#ifndef BASE_STARTUP_PARAM_SERVICE_H -#define BASE_STARTUP_PARAM_SERVICE_H -#include -#include "sys_param.h" -#include "param_manager.h" +#ifndef SECCOMP_POLICY_CONSTANTS_H +#define SECCOMP_POLICY_CONSTANTS_H + #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -int InitPersistParamWorkSpace(const char *context); -int RefreshPersistParams(ParamWorkSpace *workSpace, const char *context); -void ClosePersistParamWorkSpace(); -int WritePersistParam(const char *name, const char *value); +#define START_UID_FOR_RENDER_PROCESS (1000000) +#define END_UID_FOR_RENDER_PROCESS (1099999) + +#define APP_UID_START (10000) #ifdef __cplusplus #if __cplusplus } #endif #endif -#endif \ No newline at end of file + +#endif // SECCOMP_POLICY_CONSTANTS_H \ No newline at end of file diff --git a/services/modules/seccomp/seccomp_policy_static.c b/services/modules/seccomp/seccomp_policy_static.c new file mode 100644 index 0000000000000000000000000000000000000000..bccc31e71347fa2e622ad4ff26f6006a3dfff121 --- /dev/null +++ b/services/modules/seccomp/seccomp_policy_static.c @@ -0,0 +1,55 @@ +/* + * 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 "init_module_engine.h" +#include "plugin_adapter.h" +#include "seccomp_policy.h" + +#define SA_MAIN_PATH ("/system/bin/sa_main") + +static int SetSystemSeccompPolicy(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(argc == 2, return -1, "Invalid parameter"); + SeccompFilterType type = SYSTEM_SA; + if (strncmp(SA_MAIN_PATH, argv[1], strlen(SA_MAIN_PATH)) != 0) { + type = SYSTEM_OTHERS; + } + bool ret = SetSeccompPolicyWithName(type, argv[0]); + PLUGIN_CHECK(ret == true, return -1; + exit(PROCESS_EXIT_CODE), "Set system seccomp spolicy failed and exit"); + + return 0; +} + +static int32_t g_executorId = -1; +static int SetSeccompPolicyInit(void) +{ + if (g_executorId == -1) { + g_executorId = AddCmdExecutor("SetSeccompPolicy", SetSystemSeccompPolicy); + } + return 0; +} + +static int SeccompHook(const HOOK_INFO *info, void *cookie) +{ + SetSeccompPolicyInit(); + PLUGIN_LOGI("seccomp enabled."); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + InitAddPostCfgLoadHook(0, SeccompHook); +} diff --git a/services/modules/selinux/BUILD.gn b/services/modules/selinux/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..235ce5bc85ecc3e4eb36b30144f2488de65e42f5 --- /dev/null +++ b/services/modules/selinux/BUILD.gn @@ -0,0 +1,69 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +ohos_shared_library("selinuxadp") { + sources = [ "selinux_adp.c" ] + defines = [ "_GNU_SOURCE" ] + include_dirs = [ + ".", + "..", + "../init_hook", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + ] + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "selinux:libselinux", + "selinux_adapter:libload_policy", + "selinux_adapter:librestorecon", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } + install_images = [ + "system", + "updater", + ] +} + +config("selinux_static_config") { + include_dirs = [ "." ] +} + +ohos_source_set("libselinuxadp_static") { + sources = [ "selinux_static.c" ] + defines = [ "_GNU_SOURCE" ] + include_dirs = [ + ".", + "..", + "../init_hook", + "//base/startup/init/interfaces/innerkits/include/param", + ] + public_external_deps = [ + "selinux:libselinux", + "selinux_adapter:libselinux_parameter_static", + ] + public_configs = [ ":selinux_static_config" ] + public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] +} diff --git a/services/modules/selinux/selinux_adp.c b/services/modules/selinux/selinux_adp.c new file mode 100755 index 0000000000000000000000000000000000000000..90276a03ae8a49a3c21d62eb27883b7755db9937 --- /dev/null +++ b/services/modules/selinux/selinux_adp.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2022-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 "selinux_adp.h" + +#include + +#include "init_error.h" +#include "init_hook.h" +#include "init_module_engine.h" +#include "plugin_adapter.h" +#include "securec.h" + +#include +#include +#include + +enum { + CMD_LOAD_POLICY = 0, + CMD_SET_SERVICE_CONTEXTS = 1, + CMD_SET_SOCKET_CONTEXTS = 2, + CMD_RESTORE_INDEX = 3, + CMD_RESTORE_INDEX_FORCE = 4, + CMD_RESTORE_INDEX_SKIP = 5, +}; + +extern char *__progname; + +static int LoadSelinuxPolicy(int id, const char *name, int argc, const char **argv) +{ + int ret; + char processContext[MAX_SECON_LEN]; + + UNUSED(id); + UNUSED(name); + UNUSED(argc); + UNUSED(argv); + PLUGIN_LOGI("LoadSelinuxPolicy "); + // load selinux policy and context + if (LoadPolicy() < 0) { + PLUGIN_LOGE("main, load_policy failed."); + } else { + PLUGIN_LOGI("main, load_policy success."); + } + + ret = snprintf_s(processContext, sizeof(processContext), sizeof(processContext) - 1, "u:r:%s:s0", __progname); + if (ret == -1) { + setcon("u:r:init:s0"); + } else { + setcon(processContext); + } + (void)RestoreconRecurse("/dev"); + return 0; +} + +static int SetServiceContent(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); + ServiceExtData *data = GetServiceExtData(argv[0], HOOK_ID_SELINUX); + char *label = "u:r:limit_domain:s0"; + if (data != NULL) { + label = (char *)data->data; + } else { + PLUGIN_LOGE("Please set secon field in service %s's cfg file, limit_domain will be blocked", argv[0]); + } + + if (setexeccon(label) < 0) { + PLUGIN_LOGE("Service error %d %s, failed to set secon %s.", errno, argv[0], label); +#ifndef STARTUP_INIT_TEST + _exit(INIT_EEXEC_CONTENT); +#endif + } else { + PLUGIN_LOGV("Service info %s, set secon %s.", argv[0], label); + } + return 0; +} + +static int SetSockCreateCon(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(name != NULL, return -1, "Invalid parameter"); + if (argc == 0) { + setsockcreatecon(NULL); + return 0; + } + PLUGIN_CHECK(argc >= 1 && argv != NULL, return -1, "Invalid parameter"); + ServiceExtData *data = GetServiceExtData(argv[0], HOOK_ID_SELINUX); + if (data != NULL) { + if (setsockcreatecon((char *)data->data) < 0) { + PLUGIN_LOGE("failed to set socket context %s's secon (%s).", argv[0], (char *)data->data); +#ifndef STARTUP_INIT_TEST + _exit(PROCESS_EXIT_CODE); +#endif + } + } + + return 0; +} + +static int RestoreContentRecurse(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); + PLUGIN_LOGV("RestoreContentRecurse path %s", argv[0]); + if (RestoreconRecurse(argv[0]) && errno != 0) { + PLUGIN_LOGE("restoreContentRecurse failed for '%s', err %d.", argv[0], errno); + } + return 0; +} + +static int RestoreContentRecurseForce(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); + PLUGIN_LOGV("RestoreContentRecurseForce path %s", argv[0]); + if (RestoreconRecurseForce(argv[0]) && errno != 0) { + PLUGIN_LOGE("RestoreContentRecurseForce failed for '%s', err %d.", argv[0], errno); + } + return 0; +} + +static int RestoreContentRecurseSkipElx(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); + PLUGIN_LOGV("RestoreContentRecurseSkipElx path %s", argv[0]); + if (RestoreconCommon(argv[0], SELINUX_RESTORECON_REALPATH | + SELINUX_RESTORECON_RECURSE | SELINUX_RESTORECON_SKIPELX, 1) && errno != 0) { + PLUGIN_LOGE("RestoreContentRecurseSkipElx failed for '%s', err %d.", argv[0], errno); + } + return 0; +} + +static int32_t g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP + 1] = {0}; // 6 cmd count +static void SelinuxAdpInit(void) +{ + g_selinuxAdpCmdIds[CMD_LOAD_POLICY] = AddCmdExecutor("loadSelinuxPolicy", LoadSelinuxPolicy); + g_selinuxAdpCmdIds[CMD_SET_SERVICE_CONTEXTS] = AddCmdExecutor("setServiceContent", SetServiceContent); + g_selinuxAdpCmdIds[CMD_SET_SOCKET_CONTEXTS] = AddCmdExecutor("setSockCreateCon", SetSockCreateCon); + g_selinuxAdpCmdIds[CMD_RESTORE_INDEX] = AddCmdExecutor("restoreContentRecurse", RestoreContentRecurse); + g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_FORCE] = + AddCmdExecutor("restoreContentRecurseForce", RestoreContentRecurseForce); + g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP] = + AddCmdExecutor("restoreContentRecurseSkipElx", RestoreContentRecurseSkipElx); +} + +static void SelinuxAdpExit(void) +{ + if (g_selinuxAdpCmdIds[CMD_LOAD_POLICY] != -1) { + RemoveCmdExecutor("loadSelinuxPolicy", g_selinuxAdpCmdIds[CMD_LOAD_POLICY]); + } + if (g_selinuxAdpCmdIds[CMD_SET_SERVICE_CONTEXTS] != -1) { + RemoveCmdExecutor("setServiceContent", g_selinuxAdpCmdIds[CMD_SET_SERVICE_CONTEXTS]); + } + if (g_selinuxAdpCmdIds[CMD_SET_SOCKET_CONTEXTS] != -1) { + RemoveCmdExecutor("setSockCreateCon", g_selinuxAdpCmdIds[CMD_SET_SOCKET_CONTEXTS]); + } + if (g_selinuxAdpCmdIds[CMD_RESTORE_INDEX] != -1) { + RemoveCmdExecutor("restoreContentRecurse", g_selinuxAdpCmdIds[CMD_RESTORE_INDEX]); + } + if (g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_FORCE] != -1) { + RemoveCmdExecutor("restoreContentRecurseForce", g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_FORCE]); + } + if (g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP] != -1) { + RemoveCmdExecutor("restoreContentRecurseSkipElx", g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP]); + } +} + +MODULE_CONSTRUCTOR(void) +{ + PLUGIN_LOGI("Selinux adapter plug-in init now ..."); + SelinuxAdpInit(); +} + +MODULE_DESTRUCTOR(void) +{ + if (getpid() != 1) { + return; + } + PLUGIN_LOGI("Selinux adapter plug-in exit now ..."); + SelinuxAdpExit(); +} diff --git a/services/modules/selinux/selinux_adp.h b/services/modules/selinux/selinux_adp.h new file mode 100755 index 0000000000000000000000000000000000000000..f92a9b9233a42f66a3b5264d61eb3a30ac8f758d --- /dev/null +++ b/services/modules/selinux/selinux_adp.h @@ -0,0 +1,23 @@ +/* + * 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 PLUGIN_SELINUX_ADP_H +#define PLUGIN_SELINUX_ADP_H + +# define SECON_STR_IN_CFG ("secon") +// https://github.com/xelerance/Openswan/blob/86dff2b/include/pluto/state.h#L222 +# define MAX_SECON_LEN (257) + +#endif /* PLUGIN_SELINUX_ADP_H */ diff --git a/services/modules/selinux/selinux_static.c b/services/modules/selinux/selinux_static.c new file mode 100755 index 0000000000000000000000000000000000000000..933374beae2a91b5daec7e41527d6328292c8844 --- /dev/null +++ b/services/modules/selinux/selinux_static.c @@ -0,0 +1,43 @@ +/* + * 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 "selinux_adp.h" + +#include "init_hook.h" +#include "init_module_engine.h" +#include "plugin_adapter.h" + +static int SelinuxHook(const HOOK_INFO *hookInfo, void *cookie) +{ + PLUGIN_LOGI("Install selinuxadp."); +#ifndef STARTUP_INIT_TEST // do not install + InitModuleMgrInstall("selinuxadp"); +#endif + return 0; +} + +static void ServiceParseSelinuxHook(SERVICE_PARSE_CTX *serviceParseCtx) +{ + char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(serviceParseCtx->serviceNode, SECON_STR_IN_CFG)); + PLUGIN_CHECK(fieldStr != NULL, return, "No secon item in %s", serviceParseCtx->serviceName); + PLUGIN_LOGV("Cfg %s for %s", fieldStr, serviceParseCtx->serviceName); + DelServiceExtData(serviceParseCtx->serviceName, HOOK_ID_SELINUX); + AddServiceExtData(serviceParseCtx->serviceName, HOOK_ID_SELINUX, fieldStr, strlen(fieldStr) + 1); +} + +MODULE_CONSTRUCTOR(void) +{ + InitAddServiceParseHook(ServiceParseSelinuxHook); + InitAddGlobalInitHook(0, SelinuxHook); +} diff --git a/services/modules/sysevent/BUILD.gn b/services/modules/sysevent/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3b1a1af884d24268199f41a170b8f3e5514348c2 --- /dev/null +++ b/services/modules/sysevent/BUILD.gn @@ -0,0 +1,45 @@ +# Copyright (c) 2023 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("//build/ohos.gni") + +ohos_shared_library("eventmodule") { + sources = [ + "startup_time_event.c", + "sys_event.c", + ] + + include_dirs = [ + ".", + "..", + "../bootevent", + "../init_hook", + "//base/startup/init/interfaces/innerkits/include/param", + ] + + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "hisysevent:libhisysevent", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} diff --git a/services/modules/sysevent/init_events.yaml b/services/modules/sysevent/init_events.yaml new file mode 100644 index 0000000000000000000000000000000000000000..77fd52b5f5180cf94b0270b92847413660b76cb8 --- /dev/null +++ b/services/modules/sysevent/init_events.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 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. + +domain: INIT + +STARTUP_TIME: + __BASE: {type: BEHAVIOR, level: CRITICAL, tag: PERFORMANCE, desc: Startup Time} + TOTAL_TIME: {type: INT64, desc: Total Time Required} + DETAILED_TIME: {type: STRING, desc: Time required by each phase} + REASON : {type: STRING, desc: Startup Reason} + ISFRIST: {type: STRING, desc: use time} diff --git a/services/modules/sysevent/startup_time_event.c b/services/modules/sysevent/startup_time_event.c new file mode 100644 index 0000000000000000000000000000000000000000..ca1e32c3871edb4d12b15d8f15a9831ce304e64f --- /dev/null +++ b/services/modules/sysevent/startup_time_event.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2023 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 "sys_event.h" + +#include +#include +#include + +#include "bootevent.h" +#include "init_module_engine.h" +#include "init_param.h" +#include "plugin_adapter.h" +#include "securec.h" +#include "init_utils.h" + +typedef struct { + char *buffer; + uint32_t bufferLen; + uint32_t currLen; +} EventArgs; + +static int GetServiceName(const char *paramName, char *buffer, size_t buffSize) +{ + size_t len = strlen(paramName); + size_t i = 0; + for (size_t index = strlen("bootevent."); index < len; index++) { + PLUGIN_CHECK(i <= buffSize, return -1); + if (*(paramName + index) == '.') { + break; + } + buffer[i++] = *(paramName + index); + } + return (int)i; +} + +static int TraversalEvent(ListNode *node, void *root) +{ + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node; + if (item->flags != BOOTEVENT_TYPE_SERVICE) { + return 0; + } + EventArgs *args = (EventArgs *)root; + int len = GetServiceName(item->paramName, args->buffer + args->currLen, args->bufferLen - args->currLen); + PLUGIN_CHECK(len > 0 && (((uint32_t)len + args->currLen) < args->bufferLen), return -1, + "Failed to format service name %s", item->paramName); + args->currLen += (uint32_t)len; + + len = sprintf_s(args->buffer + args->currLen, args->bufferLen - args->currLen, ",%u:%u,%u:%u;", + (uint32_t)item->timestamp[BOOTEVENT_FORK].tv_sec, + (uint32_t)(item->timestamp[BOOTEVENT_FORK].tv_nsec / USTONSEC), + (uint32_t)item->timestamp[BOOTEVENT_READY].tv_sec, + (uint32_t)(item->timestamp[BOOTEVENT_READY].tv_nsec / USTONSEC)); + PLUGIN_CHECK(len > 0 && (((uint32_t)len + args->currLen) < args->bufferLen), return -1, + "Failed to format service time %s", item->paramName); + args->currLen += (uint32_t)len; + return 0; +} + +static void InsertBootTimeParam(char *buffer, const char *name) +{ + char bufKernel[MAX_BUFFER_LEN] = {0}; + char buf[MAX_BUFFER_LEN] = {0}; + char bootName[MAX_BUFFER_LEN] = {0}; + uint32_t bufLen = MAX_BUFFER_LEN; + uint32_t kernelLen = MAX_BUFFER_LEN; + int len = sprintf_s(bootName, MAX_BUFFER_LEN, "ohos.boot.time.%s", name); + PLUGIN_CHECK(len > 0 && ((uint32_t)len < MAX_BUFFER_LEN), return, "Failed to format boot name "); + int ret = SystemReadParam(bootName, buf, &bufLen); + PLUGIN_CHECK(ret == 0, return, "Failed to read boot time "); + char time[MAX_BUFFER_LEN] = {0}; + if (strcmp(name, "kernel") == 0) { + len = sprintf_s(time, MAX_BUFFER_LEN, ";kernel,0,%s", buf); + } else { + int result = SystemReadParam("ohos.boot.time.kernel", bufKernel, &kernelLen); + if (result == 0) { + len = sprintf_s(time, MAX_BUFFER_LEN, ";init,%s,%s", bufKernel, buf); + } + } + PLUGIN_CHECK(len > 0 && ((uint32_t)len < MAX_BUFFER_LEN), return, "Failed to format boot time "); + ret = strcat_s(buffer, MAX_BUFFER_FOR_EVENT + PARAM_VALUE_LEN_MAX + MAX_BUFFER_LEN + 1, time); + PLUGIN_CHECK(ret == 0, return, "Failed to format boot time "); +} + +PLUGIN_STATIC void ReportBootEventComplete(ListNode *events) +{ + PLUGIN_CHECK(events != NULL, return, "Invalid events"); + struct timespec curr = {0}; + int ret = clock_gettime(CLOCK_MONOTONIC, &curr); + PLUGIN_CHECK(ret == 0, return); + + char *buffer = (char *)calloc(MAX_BUFFER_FOR_EVENT + PARAM_VALUE_LEN_MAX, 1); + PLUGIN_CHECK(buffer != NULL, return, "Failed to get memory for sys event "); + EventArgs args = { buffer, MAX_BUFFER_FOR_EVENT, 0 }; + OH_ListTraversal(events, (void *)&args, TraversalEvent, 0); + if ((args.currLen > 1) && (args.currLen < MAX_BUFFER_FOR_EVENT)) { + buffer[args.currLen - 1] = '\0'; + } + InsertBootTimeParam(buffer, "kernel"); + InsertBootTimeParam(buffer, "init"); + + StartupTimeEvent startupTime = {}; + startupTime.event.type = STARTUP_TIME; + startupTime.totalTime = curr.tv_sec; + startupTime.totalTime = startupTime.totalTime * MSECTONSEC; + startupTime.totalTime += curr.tv_nsec / USTONSEC; + startupTime.detailTime = buffer; + char *reason = buffer + MAX_BUFFER_FOR_EVENT; + uint32_t size = PARAM_VALUE_LEN_MAX; + ret = SystemReadParam("ohos.boot.bootreason", reason, &size); + if (ret == 0) { + startupTime.reason = reason; + startupTime.firstStart = 1; + } else { + startupTime.reason = ""; + startupTime.firstStart = 0; + } + PLUGIN_LOGI("SysEventInit %u.%u detailTime len %u '%s'", + (uint32_t)curr.tv_sec, (uint32_t)(curr.tv_nsec / USTONSEC), args.currLen, startupTime.detailTime); + ReportSysEvent(&startupTime.event); + free(buffer); +} + +#ifndef STARTUP_INIT_TEST // do not install +MODULE_CONSTRUCTOR(void) +{ + ReportBootEventComplete(GetBootEventList()); +} +#endif diff --git a/services/modules/sysevent/sys_event.c b/services/modules/sysevent/sys_event.c new file mode 100644 index 0000000000000000000000000000000000000000..acb73ec6eb56ba6acfab801d10d62d3cca302f2c --- /dev/null +++ b/services/modules/sysevent/sys_event.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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 "sys_event.h" + +#include "init_module_engine.h" +#include "hisysevent_c.h" +#include "plugin_adapter.h" + +#define STARTUP_DOMAIN "INIT" + +#define KEY_TOTAL_TIME "TOTAL_TIME" +#define KEY_DETAILED_TIME "DETAILED_TIME" +#define KEY_REASON "REASON" +#define KEY_FIRST "ISFIRST" + +static void ReportStartupTimeEvent(const StartupTimeEvent *startupTime) +{ + HiSysEventParam params[] = { + { + .name = KEY_TOTAL_TIME, + .t = HISYSEVENT_INT64, + .v = { .i64 = startupTime->totalTime }, + .arraySize = 0, + }, + { + .name = KEY_DETAILED_TIME, + .t = HISYSEVENT_STRING, + .v = { .s = startupTime->detailTime }, + .arraySize = 0, + }, + { + .name = KEY_REASON, + .t = HISYSEVENT_STRING, + .v = { .s = startupTime->reason }, + .arraySize = 0, + }, + { + .name = KEY_FIRST, + .t = HISYSEVENT_INT32, + .v = { .i32 = startupTime->firstStart }, + .arraySize = 0, + } + }; + int ret = OH_HiSysEvent_Write(STARTUP_DOMAIN, "STARTUP_TIME", + HISYSEVENT_BEHAVIOR, params, sizeof(params) / sizeof(params[0])); + PLUGIN_ONLY_LOG(ret == 0, "Failed to write event ret %d", ret); +} + +void ReportSysEvent(const StartupEvent *event) +{ + PLUGIN_CHECK(event != NULL, return, "Invalid events"); + if (event->type == STARTUP_TIME) { + StartupTimeEvent *startupTime = (StartupTimeEvent *)(event); + ReportStartupTimeEvent(startupTime); + } +} diff --git a/services/modules/sysevent/sys_event.h b/services/modules/sysevent/sys_event.h new file mode 100644 index 0000000000000000000000000000000000000000..cfef8b08233021a04adeb0a8a067afcede5f73a0 --- /dev/null +++ b/services/modules/sysevent/sys_event.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 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 PLUGIN_SYS_EVENT_H +#define PLUGIN_SYS_EVENT_H + +#include +#include +#include "init_module_engine.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define MAX_BUFFER_FOR_EVENT 1024 +typedef enum { + STARTUP_TIME = 0, + STARTUP_EVENT_MAX +} StartupEventType; + +typedef struct { + StartupEventType type; +} StartupEvent; + +typedef struct { + StartupEvent event; + int64_t totalTime; + char *detailTime; + char *reason; + int firstStart; + char *page; +} StartupTimeEvent; + +void ReportSysEvent(const StartupEvent *event); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif /* PLUGIN_SYS_EVENT_H */ diff --git a/services/modules/trace/BUILD.gn b/services/modules/trace/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9e9e9cbf58942d6b9e89ac3989f9ee535d6d3fce --- /dev/null +++ b/services/modules/trace/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2023 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/begetd.gni") +import("//build/ohos.gni") + +comm_include = [ + ".", + "..", + "../bootevent", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", +] + +ohos_shared_library("inittrace") { + sources = [ "init_trace.c" ] + include_dirs = comm_include + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson", + "zlib:libz", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } +} + +config("inittrace_static_config") { + include_dirs = comm_include +} + +ohos_prebuilt_etc("inittrace_cfg") { + source = "init_trace.cfg" + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/modules/trace/init_trace.c b/services/modules/trace/init_trace.c new file mode 100644 index 0000000000000000000000000000000000000000..4eb29bd3537c640df1aeb41f44fc29051aab3e97 --- /dev/null +++ b/services/modules/trace/init_trace.c @@ -0,0 +1,570 @@ +/* + * Copyright (C) 2023 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 + +#include +#include + +#include "cJSON.h" +#include "init_module_engine.h" +#include "init_param.h" +#include "init_utils.h" +#include "plugin_adapter.h" +#include "securec.h" + +#define MAX_SYS_FILES 11 +#define CHUNK_SIZE 65536 +#define BLOCK_SIZE 4096 +#define WAIT_MILLISECONDS 10 +#define BUFFER_SIZE_KB 10240 // 10M + +#define TRACE_CFG_KERNEL "KERNEL" +#define TRACE_CFG_USER "USER" +#define TRACE_TAG_PARAMETER "debug.hitrace.tags.enableflags" +#define TRACE_DEBUG_FS_PATH "/sys/kernel/debug/tracing/" +#define TRACE_FS_PATH "/sys/kernel/tracing/" +#define TRACE_CFG_PATH STARTUP_INIT_UT_PATH"/system/etc/init_trace.cfg" +#define TRACE_OUTPUT_PATH "/data/service/el0/startup/init/init_trace.log" +#define TRACE_OUTPUT_PATH_ZIP "/data/service/el0/startup/init/init_trace.zip" + +#define TRACE_CMD "ohos.servicectrl.init_trace" + +// various operating paths of ftrace +#define TRACING_ON_PATH "tracing_on" +#define TRACE_PATH "trace" +#define TRACE_MARKER_PATH "trace_marker" +#define TRACE_CURRENT_TRACER "current_tracer" +#define TRACE_BUFFER_SIZE_KB "buffer_size_kb" +#define TRACE_CLOCK "trace_clock" +#define TRACE_DEF_CLOCK "boot" + +typedef enum { + TRACE_STATE_IDLE, + TRACE_STATE_STARTED, + TRACE_STATE_STOPED, + TRACE_STATE_INTERRUPT +} TraceState; + +typedef struct { + char *traceRootPath; + char buffer[PATH_MAX]; + cJSON *jsonRootNode; + TraceState traceState; + uint32_t compress : 1; +} TraceWorkspace; + +static TraceWorkspace g_traceWorkspace = {NULL, {0}, NULL, 0, 0}; +static TraceWorkspace *GetTraceWorkspace(void) +{ + return &g_traceWorkspace; +} + +static char *ReadFile(const char *path) +{ + struct stat fileStat = {0}; + if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0) { + PLUGIN_LOGE("Invalid file %s or buffer %zu", path, fileStat.st_size); + return NULL; + } + char realPath[PATH_MAX] = ""; + realpath(path, realPath); + FILE *fd = fopen(realPath, "r"); + PLUGIN_CHECK(fd != NULL, return NULL, "Failed to fopen path %s", path); + char *buffer = NULL; + do { + buffer = (char*)calloc((size_t)(fileStat.st_size + 1), sizeof(char)); + PLUGIN_CHECK(buffer != NULL, break, "Failed to alloc memory for path %s", path); + if (fread(buffer, fileStat.st_size, 1, fd) != 1) { + PLUGIN_LOGE("Failed to read file %s errno:%d", path, errno); + free(buffer); + buffer = NULL; + } else { + buffer[fileStat.st_size] = '\0'; + } + } while (0); + (void)fclose(fd); + return buffer; +} + +static int InitTraceWorkspace(TraceWorkspace *workspace) +{ + workspace->traceRootPath = NULL; + workspace->traceState = TRACE_STATE_IDLE; + workspace->compress = 0; + char *fileBuf = ReadFile(TRACE_CFG_PATH); + PLUGIN_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", TRACE_CFG_PATH); + workspace->jsonRootNode = cJSON_Parse(fileBuf); + PLUGIN_CHECK(workspace->jsonRootNode != NULL, free(fileBuf); + return -1, "Failed to parse json file %s", TRACE_CFG_PATH); + workspace->compress = cJSON_IsTrue(cJSON_GetObjectItem(workspace->jsonRootNode, "compress")) ? 1 : 0; + PLUGIN_LOGI("InitTraceWorkspace compress :%d", workspace->compress); + free(fileBuf); + return 0; +} + +static void DestroyTraceWorkspace(TraceWorkspace *workspace) +{ + if (workspace->traceRootPath) { + free(workspace->traceRootPath); + workspace->traceRootPath = NULL; + } + if (workspace->jsonRootNode) { + cJSON_Delete(workspace->jsonRootNode); + workspace->jsonRootNode = NULL; + } + workspace->traceState = TRACE_STATE_IDLE; +} + +static bool IsTraceMountedInner(TraceWorkspace *workspace, const char *fsPath) +{ + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), + "%s%s", fsPath, TRACE_MARKER_PATH); + PLUGIN_CHECK(len > 0, return false, "Failed to format path %s", fsPath); + if (access(workspace->buffer, F_OK) != -1) { + workspace->traceRootPath = strdup(fsPath); + PLUGIN_CHECK(workspace->traceRootPath != NULL, return false, "Failed to dup fsPath"); + return true; + } + return false; +} + +static bool IsTraceMounted(TraceWorkspace *workspace) +{ + return IsTraceMountedInner(workspace, TRACE_DEBUG_FS_PATH) || + IsTraceMountedInner(workspace, TRACE_FS_PATH); +} + +static bool IsWritableFile(const char *filename) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), + "%s%s", workspace->traceRootPath, filename); + PLUGIN_CHECK(len > 0, return false, "Failed to format path %s", filename); + return access(workspace->buffer, W_OK) != -1; +} + +static bool WriteStrToFile(const char *filename, const char *str) +{ + PLUGIN_LOGV("WriteStrToFile filename %s %s", filename, str); + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), + "%s%s", workspace->traceRootPath, filename); + PLUGIN_CHECK(len > 0, return false, "Failed to format path %s", filename); + char realPath[PATH_MAX] = ""; + realpath(workspace->buffer, realPath); + FILE *outfile = fopen(realPath, "w"); + PLUGIN_CHECK(outfile != NULL, return false, "Failed to open file %s.", workspace->buffer); + (void)fprintf(outfile, "%s", str); + (void)fflush(outfile); + (void)fclose(outfile); + return true; +} + +static bool SetTraceEnabled(const char *path, bool enabled) +{ + return WriteStrToFile(path, enabled ? "1" : "0"); +} + +static bool SetBufferSize(int bufferSize) +{ + if (!WriteStrToFile(TRACE_CURRENT_TRACER, "nop")) { + PLUGIN_LOGE("%s", "Error: write \"nop\" to %s\n", TRACE_CURRENT_TRACER); + } + char buffer[20] = {0}; // 20 max int number + int len = sprintf_s((char *)buffer, sizeof(buffer), "%d", bufferSize); + PLUGIN_CHECK(len > 0, return false, "Failed to format int %d", bufferSize); + PLUGIN_LOGE("SetBufferSize path %s %s", TRACE_BUFFER_SIZE_KB, buffer); + return WriteStrToFile(TRACE_BUFFER_SIZE_KB, buffer); +} + +static bool SetClock(const char *timeClock) +{ + return WriteStrToFile(TRACE_CLOCK, timeClock); +} + +static bool SetOverWriteEnable(bool enabled) +{ + return SetTraceEnabled("options/overwrite", enabled); +} + +static bool SetTgidEnable(bool enabled) +{ + return SetTraceEnabled("options/record-tgid", enabled); +} + +static bool SetTraceTagsEnabled(uint64_t tags) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), "%" PRIu64 "", tags); + PLUGIN_CHECK(len > 0, return false, "Failed to format tags %" PRId64 "", tags); + return SystemWriteParam(TRACE_TAG_PARAMETER, workspace->buffer) == 0; +} + +static bool RefreshServices() +{ + return true; +} + +static cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName) +{ + cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName); + PLUGIN_CHECK(cJSON_IsArray(arrItem), return NULL); + *arrSize = cJSON_GetArraySize(arrItem); + return *arrSize > 0 ? arrItem : NULL; +} + +static bool SetUserSpaceSettings(void) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + int size = 0; + cJSON *userItem = GetArrayItem(workspace->jsonRootNode, &size, TRACE_CFG_USER); + PLUGIN_CHECK(userItem != NULL, return false, "Failed to get user info"); + + PLUGIN_LOGI("SetUserSpaceSettings: %d", size); + uint64_t enabledTags = 0; + for (int i = 0; i < size; i++) { + cJSON *item = cJSON_GetArrayItem(userItem, i); + PLUGIN_LOGI("Tag name = %s ", cJSON_GetStringValue(cJSON_GetObjectItem(item, "name"))); + int tag = cJSON_GetNumberValue(cJSON_GetObjectItem(item, "tag")); + enabledTags |= 1ULL << tag; + } + PLUGIN_LOGI("User enabledTags: %" PRId64 "", enabledTags); + return SetTraceTagsEnabled(enabledTags) && RefreshServices(); +} + +static bool ClearUserSpaceSettings(void) +{ + return SetTraceTagsEnabled(0) && RefreshServices(); +} + +static bool SetKernelTraceEnabled(const TraceWorkspace *workspace, bool enabled) +{ + bool result = true; + PLUGIN_LOGI("SetKernelTraceEnabled %s", enabled ? "enable" : "disable"); + int size = 0; + cJSON *kernelItem = GetArrayItem(workspace->jsonRootNode, &size, TRACE_CFG_KERNEL); + PLUGIN_CHECK(kernelItem != NULL, return false, "Failed to get user info"); + for (int i = 0; i < size; i++) { + cJSON *tagJson = cJSON_GetArrayItem(kernelItem, i); + const char *name = cJSON_GetStringValue(cJSON_GetObjectItem(tagJson, "name")); + int pathCount = 0; + cJSON *paths = GetArrayItem(tagJson, &pathCount, "sys-files"); + if (paths == NULL) { + continue; + } + PLUGIN_LOGV("Kernel tag name: %s sys-files %d", name, pathCount); + for (int j = 0; j < pathCount; j++) { + char *path = cJSON_GetStringValue(cJSON_GetArrayItem(paths, j)); + PLUGIN_CHECK(path != NULL, continue); + if (!IsWritableFile(path)) { + PLUGIN_LOGW("Path %s is not writable for %s", path, name); + continue; + } + result = result && SetTraceEnabled(path, enabled); + } + } + return result; +} + +static bool DisableAllTraceEvents(void) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + return SetKernelTraceEnabled(workspace, false); +} + +static bool SetKernelSpaceSettings(void) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + bool ret = SetBufferSize(BUFFER_SIZE_KB); + PLUGIN_CHECK(ret, return false, "Failed to set buffer"); + ret = SetClock(TRACE_DEF_CLOCK); + PLUGIN_CHECK(ret, return false, "Failed to set clock"); + ret = SetOverWriteEnable(true); + PLUGIN_CHECK(ret, return false, "Failed to set write enable"); + ret = SetTgidEnable(true); + PLUGIN_CHECK(ret, return false, "Failed to set tgid enable"); + ret = SetKernelTraceEnabled(workspace, false); + PLUGIN_CHECK(ret, return false, "Pre-clear kernel tracers failed"); + return SetKernelTraceEnabled(workspace, true); +} + +static bool ClearKernelSpaceSettings(void) +{ + return DisableAllTraceEvents() && SetOverWriteEnable(true) && SetBufferSize(1) && SetClock("boot"); +} + +static bool ClearTrace(void) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), + "%s%s", workspace->traceRootPath, TRACE_PATH); + PLUGIN_CHECK(len > 0, return false, "Failed to format path %s", TRACE_PATH); + char realPath[PATH_MAX] = ""; + realpath(workspace->buffer, realPath); + // clear old trace file + int fd = open(realPath, O_RDWR); + PLUGIN_CHECK(fd >= 0, return false, "Failed to open file %s errno %d", workspace->buffer, errno); + (void)ftruncate(fd, 0); + close(fd); + return true; +} + +static void DumpCompressedTrace(int traceFd, int outFd) +{ + int flush = Z_NO_FLUSH; + uint8_t *inBuffer = calloc(1, CHUNK_SIZE); + PLUGIN_CHECK(inBuffer != NULL, return, "Error: couldn't allocate buffers\n"); + uint8_t *outBuffer = malloc(CHUNK_SIZE); + PLUGIN_CHECK(outBuffer != NULL, free(inBuffer); + return, "Error: couldn't allocate buffers\n"); + + z_stream zs = {}; + int ret = 0; + deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY); // 16 8 bit + do { + // read data + ssize_t bytesRead = TEMP_FAILURE_RETRY(read(traceFd, inBuffer, CHUNK_SIZE)); + PLUGIN_CHECK(bytesRead >= 0, break, "Error: reading trace, errno: %d\n", errno); + zs.avail_in = (uInt)bytesRead; + flush = zs.avail_in == 0 ? Z_FINISH : Z_NO_FLUSH; + zs.next_in = inBuffer; + do { + zs.next_out = outBuffer; + zs.avail_out = CHUNK_SIZE; + ret = deflate(&zs, flush); + PLUGIN_CHECK(ret != Z_STREAM_ERROR, break, "Error: deflate trace, errno: %d\n", errno); + size_t have = CHUNK_SIZE - zs.avail_out; + size_t bytesWritten = (size_t)TEMP_FAILURE_RETRY(write(outFd, outBuffer, have)); + PLUGIN_CHECK(bytesWritten >= have, flush = Z_FINISH; break, + "Error: writing deflated trace, errno: %d\n", errno); + } while (zs.avail_out == 0); + } while (flush != Z_FINISH); + + ret = deflateEnd(&zs); + PLUGIN_ONLY_LOG(ret == Z_OK, "error cleaning up zlib: %d\n", ret); + free(inBuffer); + free(outBuffer); +} + +static void DumpTrace(const TraceWorkspace *workspace, int outFd, const char *path) +{ + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), "%s%s", workspace->traceRootPath, path); + PLUGIN_CHECK(len > 0, return, "Failed to format path %s", path); + char realPath[PATH_MAX] = ""; + realpath(workspace->buffer, realPath); + int traceFd = open(realPath, O_RDWR); + PLUGIN_CHECK(traceFd >= 0, return, "Failed to open file %s errno %d", workspace->buffer, errno); + + ssize_t bytesWritten; + ssize_t bytesRead; + if (workspace->compress) { + DumpCompressedTrace(traceFd, outFd); + } else { + char buffer[BLOCK_SIZE]; + do { + bytesRead = TEMP_FAILURE_RETRY(read(traceFd, buffer, BLOCK_SIZE)); + if ((bytesRead == 0) || (bytesRead == -1)) { + break; + } + bytesWritten = TEMP_FAILURE_RETRY(write(outFd, buffer, bytesRead)); + } while (bytesWritten > 0); + } + close(traceFd); +} + +static bool MarkOthersClockSync(void) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return false, "Failed to get trace workspace"); + int len = sprintf_s((char *)workspace->buffer, sizeof(workspace->buffer), "%s%s", + workspace->traceRootPath, TRACE_MARKER_PATH); + PLUGIN_CHECK(len > 0, return false, "Failed to format path %s", TRACE_MARKER_PATH); + + struct timespec mts = {0, 0}; + struct timespec rts = {0, 0}; + if (clock_gettime(CLOCK_REALTIME, &rts) == -1) { + PLUGIN_LOGE("Error: get realtime, errno: %d", errno); + return false; + } else if (clock_gettime(CLOCK_MONOTONIC, &mts) == -1) { + PLUGIN_LOGE("Error: get monotonic, errno: %d\n", errno); + return false; + } + const unsigned int nanoSeconds = 1000000000; // seconds converted to nanoseconds + const unsigned int nanoToMill = 1000000; // millisecond converted to nanoseconds + const float nanoToSecond = 1000000000.0f; // consistent with the ftrace timestamp format + + PLUGIN_LOGE("MarkOthersClockSync %s", workspace->buffer); + char realPath[PATH_MAX] = { 0 }; + realpath(workspace->buffer, realPath); + FILE *file = fopen(realPath, "wt+"); + PLUGIN_CHECK(file != NULL, return false, "Error: opening %s, errno: %d", TRACE_MARKER_PATH, errno); + do { + int64_t realtime = ((int64_t)rts.tv_sec * nanoSeconds + rts.tv_nsec) / nanoToMill; + float parentTs = (float)((((float)mts.tv_sec) * nanoSeconds + mts.tv_nsec) / nanoToSecond); + int ret = fprintf(file, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime); + PLUGIN_CHECK(ret > 0, break, "Warning: writing clock sync marker, errno: %d", errno); + ret = fprintf(file, "trace_event_clock_sync: parent_ts=%f\n", parentTs); + PLUGIN_CHECK(ret > 0, break, "Warning: writing clock sync marker, errno: %d", errno); + } while (0); + (void)fclose(file); + return true; +} + +static int InitStartTrace(void) +{ + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return 0, "Failed to get trace workspace"); + PLUGIN_CHECK(workspace->traceState == TRACE_STATE_IDLE, return 0, + "Invalid state for trace %d", workspace->traceState); + + InitTraceWorkspace(workspace); + PLUGIN_CHECK(IsTraceMounted(workspace), return -1); + + PLUGIN_CHECK(workspace->traceRootPath != NULL && workspace->jsonRootNode != NULL, + return -1, "No trace root path or config"); + + // load json init_trace.cfg + if (!SetKernelSpaceSettings() || !SetTraceEnabled(TRACING_ON_PATH, true)) { + PLUGIN_LOGE("Failed to enable kernel space setting"); + ClearKernelSpaceSettings(); + return -1; + } + ClearTrace(); + PLUGIN_LOGI("capturing trace..."); + if (!SetUserSpaceSettings()) { + PLUGIN_LOGE("Failed to enable user space setting"); + ClearKernelSpaceSettings(); + ClearUserSpaceSettings(); + return -1; + } + workspace->traceState = TRACE_STATE_STARTED; + return 0; +} + +static int InitStopTrace(void) +{ + PLUGIN_LOGI("Stop trace now ..."); + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return 0, "Failed to get trace workspace"); + PLUGIN_CHECK(workspace->traceState == TRACE_STATE_STARTED, return 0, "Invalid state for trace %d", + workspace->traceState); + workspace->traceState = TRACE_STATE_STOPED; + + MarkOthersClockSync(); + // clear user tags first and sleep a little to let apps already be notified. + ClearUserSpaceSettings(); + usleep(WAIT_MILLISECONDS); + SetTraceEnabled(TRACING_ON_PATH, false); + + const char *path = workspace->compress ? TRACE_OUTPUT_PATH_ZIP : TRACE_OUTPUT_PATH; + int outFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (outFd >= 0) { + DumpTrace(workspace, outFd, TRACE_PATH); + close(outFd); + } else { + PLUGIN_LOGE("Failed to open file '%s', err=%d", path, errno); + } + + ClearTrace(); + // clear kernel setting including clock type after dump(MUST) and tracing_on is off. + ClearKernelSpaceSettings(); + // init hitrace config + DoJobNow("init-hitrace"); + DestroyTraceWorkspace(workspace); + return 0; +} + +static int InitInterruptTrace(void) +{ + PLUGIN_LOGI("Interrupt trace now ..."); + TraceWorkspace *workspace = GetTraceWorkspace(); + PLUGIN_CHECK(workspace != NULL, return 0, "Failed to get trace workspace"); + PLUGIN_CHECK(workspace->traceState == TRACE_STATE_STARTED, return 0, + "Invalid state for trace %d", workspace->traceState); + + workspace->traceState = TRACE_STATE_INTERRUPT; + MarkOthersClockSync(); + // clear user tags first and sleep a little to let apps already be notified. + ClearUserSpaceSettings(); + SetTraceEnabled(TRACING_ON_PATH, false); + ClearTrace(); + // clear kernel setting including clock type after dump(MUST) and tracing_on is off. + ClearKernelSpaceSettings(); + // init hitrace config + DoJobNow("init-hitrace"); + DestroyTraceWorkspace(workspace); + return 0; +} + +static int DoInitTraceCmd(int id, const char *name, int argc, const char **argv) +{ + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGI("DoInitTraceCmd argc %d cmd %s", argc, argv[0]); + if (strcmp(argv[0], "start") == 0) { + return InitStartTrace(); + } else if (strcmp(argv[0], "stop") == 0) { + return InitStopTrace(); + } else if (strcmp(argv[0], "1") == 0) { + return InitInterruptTrace(); + } + return 0; +} + +static int g_executorId = -1; +static int InitTraceInit(void) +{ + if (g_executorId == -1) { + g_executorId = AddCmdExecutor("init_trace", DoInitTraceCmd); + PLUGIN_LOGI("InitTraceInit executorId %d", g_executorId); + } + return 0; +} + +static void InitTraceExit(void) +{ + PLUGIN_LOGI("InitTraceExit executorId %d", g_executorId); + if (g_executorId != -1) { + RemoveCmdExecutor("init_trace", g_executorId); + } +} + +MODULE_CONSTRUCTOR(void) +{ + PLUGIN_LOGI("Start trace now ..."); + InitTraceInit(); +} + +MODULE_DESTRUCTOR(void) +{ + InitTraceExit(); +} diff --git a/services/modules/trace/init_trace.cfg b/services/modules/trace/init_trace.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7ca8c429ac947459664c95dcce45b744b478c0b1 --- /dev/null +++ b/services/modules/trace/init_trace.cfg @@ -0,0 +1,596 @@ +{ + "compress" : false, + "KERNEL" : [ + { + "name" : "disk", + "description" : "Disk I/O", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/f2fs/f2fs_sync_file_enter/enable", + "events/f2fs/f2fs_sync_file_exit/enable", + "events/f2fs/f2fs_write_begin/enable", + "events/f2fs/f2fs_write_end/enable", + "events/ext4/ext4_da_write_begin/enable", + "events/ext4/ext4_da_write_end/enable", + "events/ext4/ext4_sync_file_enter/enable", + "events/ext4/ext4_sync_file_exit/enable", + "events/block/block_rq_issue/enable", + "events/block/block_rq_complete/enable" + ] + }, + { + "name" : "mmc", + "description" : "eMMC commands", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/mmc/enable" + ] + }, + { + "name" : "zbinder", + "description" : "OpenHarmony binder communication", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/zbinder/enable" + ] + }, + { + "name" : "ufs", + "description" : "UFS commands", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/ufs/enable" + ] + }, + { + "name" : "irq", + "description" : "IRQ Events", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/irq/enable", + "events/ipi/enable" + ] + }, + { + "name" : "irqoff", + "description" : "IRQ-disabled code section tracing", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/preemptirq/irq_enable/enable", + "events/preemptirq/irq_disable/enable" + ] + }, + { + "name" : "i2c", + "description" : "I2C Events", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/i2c/enable" , + "events/i2c/i2c_read/enable" , + "events/i2c/i2c_write/enable" , + "events/i2c/i2c_result/enable" , + "events/i2c/i2c_reply/enable" , + "events/i2c/smbus_read/enable" , + "events/i2c/smbus_write/enable" , + "events/i2c/smbus_result/enable" , + "events/i2c/smbus_reply/enable" + ] + }, + { + "name" : "regulators", + "description" : "Voltage and Current Regulators", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/regulator/enable" + ] + }, + { + "name" : "membus", + "description" : "Memory Bus Utilization", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/memory_bus/enable" + ] + }, + { + "name" : "freq", + "description" : "CPU Frequency", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/power/cpu_frequency/enable", + "events/power/clock_set_rate/enable", + "events/power/clock_disable/enable", + "events/power/clock_enable/enable", + "events/clk/clk_set_rate/enable", + "events/clk/clk_disable/enable", + "events/clk/clk_enable/enable", + "events/power/cpu_frequency_limits/enable" + ] + }, + { + "name" : "idle", + "description" : "CPU Idle", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/power/cpu_idle/enable" + ] + }, + { + "name" : "load", + "description" : "CPU Load", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/cpufreq_interactive/enable" + ] + }, + { + "name" : "sched", + "description" : "CPU Scheduling", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/sched/sched_switch/enable", + "events/sched/sched_wakeup/enable", + "events/sched/sched_wakeup_new/enable", + "events/sched/sched_waking/enable", + "events/sched/sched_blocked_reason/enable", + "events/sched/sched_pi_setprio/enable", + "events/sched/sched_process_exit/enable", + "events/cgroup/enable", + "events/oom/oom_score_adj_update/enable", + "events/task/task_rename/enable", + "events/task/task_newtask/enable" + ] + }, + { + "name" : "preemptoff", + "description" : "Preempt-disabled code section tracing", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/preemptirq/preempt_enable/enable", + "events/preemptirq/preempt_disable/enable" + ] + }, + { + "name" : "binder", + "description" : "Binder kernel Info", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/binder/binder_transaction/enable", + "events/binder/binder_transaction_received/enable", + "events/binder/binder_transaction_alloc_buf/enable", + "events/binder/binder_set_priority/enable", + "events/binder/binder_lock/enable", + "events/binder/binder_locked/enable", + "events/binder/binder_unlock/enable" + ] + }, + { + "name" : "sync", + "description" : "Synchronization", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/dma_fence/enable" + ] + }, + { + "name" : "workq", + "description" : "Kernel Workqueues", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/workqueue/enable" + ] + }, + { + "name" : "memreclaim", + "description" : "Kernel Memory Reclaim", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/vmscan/mm_vmscan_direct_reclaim_begin/enable", + "events/vmscan/mm_vmscan_direct_reclaim_end/enable", + "events/vmscan/mm_vmscan_kswapd_wake/enable", + "events/vmscan/mm_vmscan_kswapd_sleep/enable", + "events/lowmemorykiller/enable" + ] + }, + { + "name" : "pagecache", + "description" : "Page cache", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/filemap/enable" + ] + }, + { + "name" : "memory", + "description" : "memory", + "tag" : 0, + "type" : "KERNEL", + "sys-files" : [ + "events/kmem/rss_stat/enable", + "events/kmem/ion_heap_grow/enable", + "events/kmem/ion_heap_shrink/enable" + ] + } + ], + "USER" : [ + { + "name" : "ohos", + "description" : "OpenHarmony", + "tag" : 30, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "ability", + "description" : "Ability Manager", + "tag" : 31, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "zcamera", + "description" : "OpenHarmony Camera Module", + "tag" : 32, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "zmedia", + "description" : "OpenHarmony Media Module", + "tag" : 33, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "zimage", + "description" : "OpenHarmony Image Module", + "tag" : 34, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "zaudio", + "description" : "OpenHarmony Audio Module", + "tag" : 35, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "distributeddatamgr", + "description" : "Distributed Data Manager", + "tag" : 36, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "mdfs", + "description" : "Mobile Distributed File System", + "tag" : 37, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "graphic", + "description" : "Graphic Module", + "tag" : 38, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "ace", + "description" : "ACE development framework", + "tag" : 39, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "notification", + "description" : "Notification Module", + "tag" : 40, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "misc", + "description" : "misc Module", + "tag" : 41, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "multimodalinput", + "description" : "Multimodal Input Module", + "tag" : 42, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "sensors", + "description" : "Sensors Module", + "tag" : 43, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "msdp", + "description" : "Multimodal Sensor Data Platform", + "tag" : 44, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dsoftbus", + "description" : "Distributed Softbus", + "tag" : 45, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "rpc", + "description" : "RPC and IPC", + "tag" : 46, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "ark", + "description" : "ARK Module", + "tag" : 47, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "window", + "description" : "Window Manager", + "tag" : 48, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "accessibility", + "description" : "Accessibility Manager", + "tag" : 61, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "account", + "description" : "Account Manager", + "tag" : 49, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dhfwk", + "description" : "Distributed Hardware FWK", + "tag" : 52, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dscreen", + "description" : "Distributed Screen", + "tag" : 50, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "daudio", + "description" : "Distributed Audio", + "tag" : 27, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dinput", + "description" : "Distributed Input", + "tag" : 59, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "devicemanager", + "description" : "Device Manager", + "tag" : 54, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "samgr", + "description" : "samgr", + "tag" : 55, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dsched", + "description" : "Distributed Schedule", + "tag" : 57, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "deviceprofile", + "description" : "Device Profile", + "tag" : 58, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "huks", + "description" : "Universal KeyStore", + "tag" : 25, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dlpcre", + "description" : "Dlp Credential Service", + "tag" : 21, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "app", + "description" : "APP Module", + "tag" : 62, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dcamera", + "description" : "Distributed Camera", + "tag" : 51, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "gresource", + "description" : "Global Resource Manager", + "tag" : 53, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "power", + "description" : "power Manager", + "tag" : 56, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "bluetooth", + "description" : "communicatio bluetooth", + "tag" : 60, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "filemanagement", + "description" : "filemanagement", + "tag" : 29, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "dslm", + "description" : "device security level", + "tag" : 28, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "useriam", + "description" : "useriam", + "tag" : 26, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "nweb", + "description" : "nweb", + "tag" : 24, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "net", + "description" : "net", + "tag" : 23, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "accesscontrol", + "description" : "Access Control Module", + "tag" : 22, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "interconn", + "description" : "Interconnection subsystem", + "tag" : 20, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "usb", + "description" : "usb subsystem", + "tag" : 19, + "type" : "USER", + "sys-files" : [ + ] + }, + { + "name" : "hdf", + "description" : "hdf subsystem", + "tag" : 18, + "type" : "USER", + "sys-files" : [ + ] + } + ] +} diff --git a/services/modules/udid/BUILD.gn b/services/modules/udid/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..6c7dbfb7829e8a46a61c8e0abdd2195d79cceb71 --- /dev/null +++ b/services/modules/udid/BUILD.gn @@ -0,0 +1,138 @@ +# Copyright (c) 2023 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/begetd.gni") +import("//build/ohos.gni") + +comm_include = [ + ".", + "..", + "../init_hook", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/syspara", +] + +if (defined(ohos_lite)) { + static_library("libudidcomm") { + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + ] + if (init_lite_no_log) { + defines += [ "INIT_NO_LOG" ] + } + include_dirs = comm_include + include_dirs += [ + "../../../interfaces/innerkits/init_module_engine/include", + "../../../interfaces/hals", + "//base/hiviewdfx/hilog_lite/interfaces/native/kits", + "mbedtls/include", + ] + sources = [ + "udid_adp.c", + "udid_comm.c", + ] + + deps = [] + external_deps = [] + if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + external_deps += [ + "bounds_checking_function:libsec_shared", + "mbedtls:mbedtls_shared", + ] + } else if (ohos_kernel_type == "liteos_m") { + external_deps += [ "bounds_checking_function:libsec_static" ] + if (init_lite_use_thirdparty_mbedtls) { + external_deps += [ "mbedtls:mbedtls_static" ] + } + } + + #if product exit, use product + if (init_feature_begetctl_liteos) { + PRODUCT_HAL_SYSPARAM_PATH = + rebase_path("${ohos_product_adapter_dir}/utils/sys_param") + cmd = "if [ -f ${PRODUCT_HAL_SYSPARAM_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + PRODUCT_HAL_SYSPARAM_EXISTS = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (PRODUCT_HAL_SYSPARAM_EXISTS) { + deps += [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ] + } + deps += [ "../../../interfaces/hals/utils/sys_param:hal_sys_param" ] + } + } +} else { + ohos_shared_library("udidmodule") { + sources = [ + "udid_adp.c", + "udid_comm.c", + ] + defines = [ "_GNU_SOURCE" ] + include_dirs = comm_include + deps = [ "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine" ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "mbedtls:mbedtls_shared", + ] + + part_name = "init" + subsystem_name = "startup" + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + module_install_dir = "lib64/init" + } else { + module_install_dir = "lib/init" + } + install_images = [ + "system", + "updater", + ] + } + + config("udid_static_config") { + include_dirs = [ "." ] + } + + ohos_source_set("libudid_static") { + sources = [ "udid_static.c" ] + defines = [ "_GNU_SOURCE" ] + include_dirs = comm_include + public_configs = [ ":udid_static_config" ] + public_configs += [ "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] + part_name = "init" + subsystem_name = "startup" + } + + # for begetutil + ohos_static_library("libudidcomm") { + sources = [ "udid_comm.c" ] + defines = [ "_GNU_SOURCE" ] + include_dirs = comm_include + external_deps = [ "bounds_checking_function:libsec_shared" ] + + part_name = "init" + subsystem_name = "startup" + } + + ohos_static_library("libudidcomm_static") { + sources = [ "udid_comm.c" ] + defines = [ "_GNU_SOURCE" ] + include_dirs = comm_include + external_deps = [ "bounds_checking_function:libsec_static" ] + + part_name = "init" + subsystem_name = "startup" + } +} diff --git a/services/modules/udid/udid.h b/services/modules/udid/udid.h new file mode 100644 index 0000000000000000000000000000000000000000..bae37e2ab7cfd71d601bae5001835d4a488e4c2a --- /dev/null +++ b/services/modules/udid/udid.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 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 PLUGIN_UDID_H +#define PLUGIN_UDID_H + +#include "beget_ext.h" + +#ifdef STARTUP_INIT_TEST +#define INIT_UDID_LOCAL_API +#else +#define INIT_UDID_LOCAL_API INIT_LOCAL_API +#endif + +INIT_UDID_LOCAL_API int GetUdidFromParam(char *udid, uint32_t size); +INIT_UDID_LOCAL_API int CalcDevUdid(char *udid, uint32_t size); + +#endif /* PLUGIN_UDID_H */ diff --git a/services/modules/udid/udid_adp.c b/services/modules/udid/udid_adp.c new file mode 100644 index 0000000000000000000000000000000000000000..c8a5d5fa59129895a0c13cae60c34ec9a247d9bc --- /dev/null +++ b/services/modules/udid/udid_adp.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 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 "udid.h" +#ifndef OHOS_LITE +#include "init_module_engine.h" +#endif +#include "init_param.h" +#include "param_comm.h" +#include "securec.h" +#include "sysparam_errno.h" + +#include "mbedtls/sha256.h" + +#define BUF_MAX_LEN 132 +#define PARAM_VALUE_MAX_LEN 36 + +INIT_UDID_LOCAL_API int GetSha256Value(const char *input, char *udid, uint32_t udidSize) +{ + if (input == NULL) { + return EC_FAILURE; + } + char buf[DEV_BUF_LENGTH] = { 0 }; + unsigned char hash[HASH_LENGTH] = { 0 }; + + mbedtls_sha256_context context; + mbedtls_sha256_init(&context); + mbedtls_sha256_starts(&context, 0); + mbedtls_sha256_update(&context, (const unsigned char *)input, strlen(input)); + mbedtls_sha256_finish(&context, hash); + + for (size_t i = 0; i < HASH_LENGTH; i++) { + unsigned char value = hash[i]; + memset_s(buf, DEV_BUF_LENGTH, 0, DEV_BUF_LENGTH); + int len = sprintf_s(buf, sizeof(buf), "%02X", value); + if (len > 0 && strcat_s(udid, udidSize, buf) != 0) { + return EC_FAILURE; + } + } + return EC_SUCCESS; +} + +INIT_UDID_LOCAL_API int CalcDevUdid(char *udid, uint32_t size) +{ + char tmp[BUF_MAX_LEN] = {0}; + uint32_t manufactureLen = PARAM_VALUE_MAX_LEN; + int ret = SystemReadParam("const.product.manufacturer", tmp, &manufactureLen); + BEGET_ERROR_CHECK(ret == 0, return -1, "Read param const.product.manufacturer failed!"); + + uint32_t modelLen = PARAM_VALUE_MAX_LEN; + ret = SystemReadParam("const.product.model", tmp + manufactureLen, &modelLen); + BEGET_ERROR_CHECK(ret == 0, return -1, "Read param const.product.model failed!"); + const char *serial = GetSerial_(); + BEGET_ERROR_CHECK(serial != NULL, return -1, "Read param serial failed!"); + ret = strcat_s(tmp, BUF_MAX_LEN, serial); + BEGET_ERROR_CHECK(ret != -1, return -1, "Cat serial failed!"); + ret = GetSha256Value(tmp, udid, size); + return ret; +} + +#ifndef OHOS_LITE +INIT_UDID_LOCAL_API void SetDevUdid() +{ + BEGET_LOGI("Begin set udid param"); + char udid[UDID_LEN] = {0}; + uint32_t size = (uint32_t)sizeof(udid); + int ret = GetUdidFromParam(udid, size); + if (ret != 0) { + BEGET_LOGI("Get udid from param failed, calculate udid from other param"); + ret = CalcDevUdid(udid, size); + BEGET_ERROR_CHECK(ret == 0, return, "calculate udid is failed!") + } + ret = SystemWriteParam("const.product.devUdid", udid); + BEGET_ERROR_CHECK(ret == 0, return, "write param const.product.devUdid failed!"); +} + +MODULE_CONSTRUCTOR(void) +{ + SetDevUdid(); +} +#endif diff --git a/services/modules/udid/udid_comm.c b/services/modules/udid/udid_comm.c new file mode 100644 index 0000000000000000000000000000000000000000..ab05cb6cee8ccf2c896ab96f61d36bd58d6cb29f --- /dev/null +++ b/services/modules/udid/udid_comm.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 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 "udid.h" + +#ifdef OHOS_LITE +#include "hal_sys_param.h" +#endif +#include "init_param.h" +#include "param_comm.h" +#include "securec.h" +#include "sysparam_errno.h" +#include + +INIT_LOCAL_API const char *GetSerial_(void) +{ +#ifdef OHOS_LITE + return HalGetSerial(); +#else + static _Atomic (char *)ohosSerial = NULL; + if (ohosSerial != NULL) { + return ohosSerial; + } + + char *value; + BEGET_CHECK((value = (char *)calloc(1, PARAM_VALUE_LEN_MAX)) != NULL, return NULL); + uint32_t len = PARAM_VALUE_LEN_MAX; + int ret = SystemGetParameter("ohos.boot.sn", value, &len); + BEGET_CHECK(ret == 0, free(value); + return NULL); + if (ohosSerial != NULL) { + free(value); + return ohosSerial; + } + atomic_store_explicit(&ohosSerial, value, memory_order_release); + return ohosSerial; +#endif +} + +INIT_LOCAL_API int GetUdidFromParam(char *udid, uint32_t size) +{ + uint32_t len = size; + int ret = SystemGetParameter("const.product.udid", udid, &len); + BEGET_CHECK(ret != 0, return ret); + + len = size; + ret = SystemGetParameter("const.product.devUdid", udid, &len); + BEGET_CHECK(ret != 0, return ret); + return ret; +} + +INIT_LOCAL_API int GetDevUdid_(char *udid, int size) +{ + if (size < UDID_LEN || udid == NULL) { + return EC_FAILURE; + } + + int ret = GetUdidFromParam(udid, (uint32_t)size); + BEGET_CHECK(ret != 0, return ret); + +#ifdef OHOS_LITE + ret = CalcDevUdid(udid, size); +#endif + return ret; +} \ No newline at end of file diff --git a/services/modules/udid/udid_static.c b/services/modules/udid/udid_static.c new file mode 100644 index 0000000000000000000000000000000000000000..8fc371a62695c7bbfaf1e9751b1a9036dd117627 --- /dev/null +++ b/services/modules/udid/udid_static.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 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 "init_hook.h" +#include "init_module_engine.h" +#include "plugin_adapter.h" + +static int UDidCalc(const HOOK_INFO *hookInfo, void *cookie) +{ + PLUGIN_LOGI("Begin install udidmodule."); + + InitModuleMgrInstall("udidmodule"); + PLUGIN_LOGI("Begin uninstall udidmodule."); + InitModuleMgrUnInstall("udidmodule"); + + PLUGIN_LOGI("Uninstall udidmodule finished."); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + InitAddPreCfgLoadHook(0, UDidCalc); +} diff --git a/services/param/BUILD.gn b/services/param/BUILD.gn old mode 100644 new mode 100755 index 07e1d27849151a38ed8427a639bcd9d523f8f6be..c2a36bbcbd36c8524186153327187cdb179a6796 --- a/services/param/BUILD.gn +++ b/services/param/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Huawei Device Co., Ltd. +# Copyright (c) 2021-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 @@ -10,95 +10,30 @@ # 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("//build/ohos.gni") - -ohos_static_library("paramservice") { - sources = [ - "//base/startup/init_lite/services/src/init_utils.c", - "manager/param_cache.c", - "manager/param_manager.c", - "manager/param_trie.c", - "service/param_persist.c", - "service/param_service.c", - "trigger/trigger_checker.c", - "trigger/trigger_manager.c", - "trigger/trigger_processor.c", - ] - - include_dirs = [ - "include", - "//base/startup/init_lite/services/include/param", - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/log", - "//third_party/libuv/include", - "//third_party/cJSON", - ] - - deps = [ - "//third_party/bounds_checking_function:libsec_static", - "//third_party/libuv:uv_static", - ] - part_name = "init" - subsystem_name = "startup" -} - -ohos_static_library("paramclient") { - sources = [ - "//base/startup/init_lite/services/src/init_utils.c", - "client/param_request.c", - "manager/param_cache.c", - "manager/param_manager.c", - "manager/param_trie.c", - ] - - include_dirs = [ - "include", - "//base/startup/init_lite/services/include/param", - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/log", - "//third_party/libuv/include", - "//third_party/cJSON", - ] - - deps = [ - "//base/startup/init_lite/services/log:init_log", - "//third_party/bounds_checking_function:libsec_static", - "//third_party/libuv:uv_static", - ] - part_name = "init" - subsystem_name = "startup" -} - -ohos_executable("getparam") { - sources = [ "cmd/param_get.c" ] - include_dirs = [ - "include", - "//base/startup/init_lite/services/include/param", - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/log", - ] - deps = [ - "//base/startup/init_lite/services/param:paramclient", - "//third_party/bounds_checking_function:libsec_static", - "//third_party/cJSON:cjson_static", - ] - install_enable = true - part_name = "init" -} - -ohos_executable("setparam") { - sources = [ "cmd/param_set.c" ] - include_dirs = [ - "include", - "//base/startup/init_lite/services/include/param", - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/log", - ] - deps = [ - "//base/startup/init_lite/services/param:paramclient", - "//third_party/bounds_checking_function:libsec_static", - "//third_party/cJSON:cjson_static", - ] - install_enable = true - part_name = "init" +import("//base/startup/init/begetd.gni") + +group("parameter") { + deps = [] + + # parameter only support linux for l2 and l1 + if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux") { + deps += [ + "base:param_base", + "linux:param_client", + "linux:param_init", + ] + } else if (ohos_kernel_type == "liteos_a") { + deps += [ + "liteos:param_client_lite", + "liteos:param_init_lite", + ] + } + } else { + deps += [ + "base:param_base", + "linux:param_client", + "linux:param_init", + ] + } } diff --git a/services/param/adapter/param_dac.c b/services/param/adapter/param_dac.c new file mode 100644 index 0000000000000000000000000000000000000000..fe1991681fb79a23218f6270895e11ace3840057 --- /dev/null +++ b/services/param/adapter/param_dac.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2021-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 "param_manager.h" +#include "param_security.h" +#include "param_trie.h" +#include "param_utils.h" +#include "param_base.h" + +#define MAX_MEMBER_IN_GROUP 128 +#define MAX_BUF_SIZE 1024 +#define INVALID_MODE 0550 +#ifdef STARTUP_INIT_TEST +#define GROUP_FILE_PATH STARTUP_INIT_UT_PATH "/etc/group" +#else +#define GROUP_FILE_PATH "/etc/group" +#endif +#define OCT_BASE 8 +#define INVALID_UID(uid) ((uid) == (uid_t)-1) + +static void GetUserIdByName(uid_t *uid, const char *name) +{ + struct passwd *data = getpwnam(name); + if (data == NULL) { + *uid = -1; + return ; + } + *uid = data->pw_uid; +} + +static void GetGroupIdByName(gid_t *gid, const char *name) +{ + *gid = -1; + struct group *data = getgrnam(name); + if (data != NULL) { + *gid = data->gr_gid; + return; + } + while ((data = getgrent()) != NULL) { + if ((data->gr_name != NULL) && (strcmp(data->gr_name, name) == 0)) { + *gid = data->gr_gid; + break; + } + } + endgrent(); +} + +// user:group:r|w +static int GetParamDacData(ParamDacData *dacData, const char *value) +{ + static const struct { + const char *name; + int value; + } paramTypes[] = { + { "int", PARAM_TYPE_INT }, + { "string", PARAM_TYPE_STRING }, + { "bool", PARAM_TYPE_BOOL }, + }; + + char *groupName = strstr(value, ":"); + if (groupName == NULL) { + return -1; + } + char *mode = strstr(groupName + 1, ":"); + if (mode == NULL) { + return -1; + } + + uint32_t nameLen = groupName - value; + char *name = (char *)value; + name[nameLen] = '\0'; + GetUserIdByName(&dacData->uid, name); + nameLen = mode - groupName - 1; + name = (char *)groupName + 1; + name[nameLen] = '\0'; + GetGroupIdByName(&dacData->gid, name); + + dacData->paramType = PARAM_TYPE_STRING; + char *type = strstr(mode + 1, ":"); + if (type != NULL) { + *type = '\0'; + type++; + for (size_t i = 0; (type != NULL) && (i < ARRAY_LENGTH(paramTypes)); i++) { + if (strcmp(paramTypes[i].name, type) == 0) { + dacData->paramType = paramTypes[i].value; + } + } + } + dacData->mode = (uint16_t)strtol(mode + 1, NULL, OCT_BASE); + return 0; +} + +static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit) +{ + UNUSED(isInit); + PARAM_CHECK(security != NULL, return -1, "Invalid security"); + security->cred.pid = getpid(); + security->cred.uid = geteuid(); + security->cred.gid = getegid(); + // support check write permission in client + security->flags[PARAM_SECURITY_DAC] |= LABEL_CHECK_IN_ALL_PROCESS; + return 0; +} + +static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel) +{ + return 0; +} + +static int DacGetGroupMember(gid_t gid, uid_t *member, uint32_t *memberSize) +{ + int32_t inputLen = (int32_t)*memberSize; + *memberSize = 0; + struct group *data = getgrgid(gid); + if (data == NULL || data->gr_mem == NULL) { + return 0; + } + int i = 0; + int memIndex = 0; + while (data->gr_mem[i]) { + uid_t uid; + GetUserIdByName(&uid, data->gr_mem[i]); + if (INVALID_UID(uid)) { + i++; + continue; + } + if ((memIndex + 1) > inputLen) { + PARAM_LOGE("Not enough memory for uid member %u", gid); + break; + } + member[memIndex++] = uid; + i++; + } + uid_t uid = 0; + GetUserIdByName(&uid, data->gr_name); + if (!INVALID_UID(uid) && ((memIndex + 1) < inputLen)) { + member[memIndex++] = uid; + } + *memberSize = memIndex; + return 0; +} + +static int LoadOneParam_(const uint32_t *context, const char *name, const char *value) +{ + ParamAuditData *auditData = (ParamAuditData *)context; + auditData->dacData.gid = -1; + auditData->dacData.uid = -1; + auditData->name = name; + int ret = GetParamDacData(&auditData->dacData, value); + PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name); + if (INVALID_UID(auditData->dacData.gid) || INVALID_UID(auditData->dacData.uid)) { + PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData->dacData.gid, auditData->dacData.uid); + } + // get uid from group + auditData->memberNum = MAX_MEMBER_IN_GROUP; + ret = DacGetGroupMember(auditData->dacData.gid, auditData->members, &auditData->memberNum); + if (ret != 0) { + auditData->memberNum = 1; + auditData->members[0] = auditData->dacData.gid; + } + + return AddSecurityLabel(auditData); +} + +static int LoadParamLabels(const char *fileName) +{ + int result = 0; + ParamAuditData *auditData = (ParamAuditData *)calloc(1, + sizeof(ParamAuditData) + sizeof(uid_t) * MAX_MEMBER_IN_GROUP); + if (auditData == NULL) { + PARAM_LOGE("Failed to alloc memory %s", fileName); + return result; + } + uint32_t infoCount = 0; + FILE *fp = fopen(fileName, "r"); + const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 size + char *buff = (char *)calloc(1, buffSize); + while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { + buff[buffSize - 1] = '\0'; + result = SplitParamString(buff, NULL, 0, LoadOneParam_, (const uint32_t *)auditData); + if (result != 0) { + PARAM_LOGE("Failed to split string %s fileName %s, result is:%d", buff, fileName, result); + break; + } + infoCount++; + } + + if (result == 0) { + PARAM_LOGI("Load parameter label total %u success %s", infoCount, fileName); + } + + if (fp != NULL) { + (void)fclose(fp); + } + if (buff != NULL) { + free(buff); + } + if (auditData != NULL) { + free(auditData); + } + return result; +} + +static int ProcessParamFile(const char *fileName, void *context) +{ + UNUSED(context); + return LoadParamLabels(fileName); +} + +static int DacGetParamSecurityLabel(const char *path) +{ + PARAM_CHECK(path != NULL, return -1, "Invalid param"); + struct stat st; + if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) { + return ProcessParamFile(path, NULL); + } + + PARAM_LOGV("DacGetParamSecurityLabel %s ", path); + DIR *pDir = opendir(path); + PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", path, errno); + char *fileName = calloc(1, MAX_BUF_SIZE); + PARAM_CHECK(fileName != NULL, closedir(pDir); + return -1, "Failed to malloc for %s", path); + + struct dirent *dp; + uint32_t count = 0; + while ((dp = readdir(pDir)) != NULL) { + if (dp->d_type == DT_DIR) { + continue; + } + char *tmp = strstr(dp->d_name, ".para.dac"); + if (tmp == NULL) { + continue; + } + if (strcmp(tmp, ".para.dac") != 0) { + continue; + } + int ret = PARAM_SPRINTF(fileName, MAX_BUF_SIZE, "%s/%s", path, dp->d_name); + if (ret <= 0) { + PARAM_LOGE("Failed to get file name for %s", dp->d_name); + continue; + } + if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) { + count++; + ret = ProcessParamFile(fileName, NULL); + if (ret != 0) { + free(fileName); + closedir(pDir); + return ret; + }; + } + } + PARAM_LOGV("Get parameter security label dac number is %d, from %s.", count, path); + free(fileName); + closedir(pDir); + return 0; +} + +static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags) +{ + UNUSED(flags); + PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param"); + return 0; +} + +INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit) +{ + PARAM_CHECK(ops != NULL, return -1, "Invalid param"); + PARAM_LOGV("RegisterSecurityDacOps %d", isInit); + int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "dac"); + ops->securityInitLabel = InitLocalSecurityLabel; + ops->securityCheckFilePermission = CheckFilePermission; +#ifdef STARTUP_INIT_TEST + ops->securityCheckParamPermission = DacCheckParamPermission; +#endif + ops->securityFreeLabel = FreeLocalSecurityLabel; + if (isInit) { + ops->securityGetLabel = DacGetParamSecurityLabel; + } + return ret; +} diff --git a/services/param/adapter/param_persistadp.c b/services/param/adapter/param_persistadp.c new file mode 100644 index 0000000000000000000000000000000000000000..9af456d03ddb1c5efe102a4789fa5c2731b77a6e --- /dev/null +++ b/services/param/adapter/param_persistadp.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2021 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 "init_utils.h" +#include "param_manager.h" +#include "param_persist.h" +#include "param_utils.h" +#if !(defined __LITEOFS_A__ || defined __LITEOS_M__) +#include "trigger_manager.h" +#endif + +// for linux, no mutex +static ParamMutex g_saveMutex = {}; + +static int LoadOnePersistParam_(const uint32_t *context, const char *name, const char *value) +{ + if (strncmp(name, "persist", strlen("persist")) != 0) { + PARAM_LOGE("%s is not persist param, do not load", name); + return 0; + } + bool clearFactoryPersistParams = *(bool*)context; + uint32_t dataIndex = 0; + unsigned int mode = 0; + int result = 0; + do { + if (!clearFactoryPersistParams) { + mode |= LOAD_PARAM_PERSIST; + result = WriteParam(name, value, &dataIndex, mode); + break; + } + + char persetValue[PARAM_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_VALUE_LEN_MAX; + int ret = SystemReadParam(name, persetValue, &len); + if (ret != 0) { + mode |= LOAD_PARAM_PERSIST; + result = WriteParam(name, value, &dataIndex, mode); + break; + } + + if ((strcmp(persetValue, value) != 0)) { + PARAM_LOGI("%s value is different, preset value is:%s, persist value is:%s", name, persetValue, value); + mode |= LOAD_PARAM_PERSIST; + result = WriteParam(name, value, &dataIndex, mode); + } + } while (0); +#if !(defined __LITEOFS_A__ || defined __LITEOS_M__) + if (result == 0) { + PostParamTrigger(EVENT_TRIGGER_PARAM_WATCH, name, value); + } +#endif + return result; +} + +static bool IsPublicParam(const char *param) +{ + const char *publicPersistParams[] = { + "persist.arkui.libace.og", "persist.ddgr.opinctype", + "persist.dfx.leak.threshold", "persist.rosen.animationtrace.enabled", + "persist.rosen.ddgr.opinctype.debugtype", "persist.sys.graphic.blurEnabled", + "persist.sys.graphic.drawing.test", "persist.sys.graphic.filterCacheEnabled", + "persist.sys.graphic.foregroundFilterEnabled", "persist.sys.graphic.GpuApitype", + "persist.sys.graphic.hmsymbolcfg.enable", "persist.sys.graphic.hmsymboltxt.enable", + "persist.sys.graphic.HpsBlurEnable", "persist.sys.graphic.kawaseEnable", + "persist.sys.graphic.openDebugTrace", "persist.sys.graphic.subSurface", + "persist.sys.text.autospacing.enable", "persist.sys.hilog.binary.forhota.on", + "persist.sys.hilog.fuse.on", "persist.sys.xlog.debug", + "persist.sys.hiview.testtype", "persist.security.jitfort.disabled", + "persist.sys.prefork.enable", "persist.time.timezone", + "persist.global.tz_override", "persist.dupdate_engine.update_type", + "persist.update.hmos_to_next_flag", "persist.hiview.leak_detector", + "persist.hiviewdfx.debugenv", "persist.swing.switch_enable", + "persist.hiviewdfx.priv.diagnosis.time.deadline", "persist.hmos_fusion_mgr.ctl.support_hmos", + "persist.init.debug.dump.trigger", "persist.init.bootchart.enabled", + "persist.init.debug.loglevel", "persist.samgr.cache.sa", + "persist.sys.hilog.binary.on", "persist.sys.hilog.debug.on", + "persist.bluetooth.collaboration_service", "persist.bluetooth.switch_enable", + "persist.edc.proxy_ap_startup", "persist.edm.edm_enable", + "persist.moduleupdate.bms.scan", "persist.nearlink.switch_enable", + "persist.parentcontrol.enable", "persist.samgr.moduleupdate.start", + }; + int size = sizeof(publicPersistParams) / sizeof(char*); + for (int i = 0; i < size; i++) { + if (strncmp(param, publicPersistParams[i], strlen(publicPersistParams[i])) == 0) { + return true; + } + } + return false; +} + +static int LoadOnePublicPersistParam_(const uint32_t *context, const char *name, const char *value) +{ + if (IsPublicParam(name)) { + return LoadOnePersistParam_(context, name, value); + } + PARAM_LOGI("%s is private, ignore", name); + return 0; +} + +static void LoadPersistParam_(const bool clearFactoryPersistParams, const char *fileName, + char *buffer, uint32_t buffSize, bool isFullLoad) +{ + FILE *fp = fopen(fileName, "r"); + PARAM_WARNING_CHECK(fp != NULL, return, "No valid persist parameter file %s", fileName); + int ret = 0; + uint32_t paramNum = 0; + while (fgets(buffer, buffSize, fp) != NULL) { + buffer[buffSize - 1] = '\0'; + if (isFullLoad) { + ret = SplitParamString(buffer, NULL, 0, LoadOnePersistParam_, (uint32_t*)&clearFactoryPersistParams); + } else { + ret = SplitParamString(buffer, NULL, 0, LoadOnePublicPersistParam_, (uint32_t*)&clearFactoryPersistParams); + } + PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buffer); + paramNum++; + } + (void)fclose(fp); + PARAM_LOGI("LoadPersistParam from file %s paramNum %d", fileName, paramNum); +} + +static bool GetPersistFilePath(char **path, char **tmpPath, int fileType) +{ + bool isFullLoad = true; + if (InUpdaterMode() == 1) { + *path = "/param/persist_parameters"; + *tmpPath = "/param/tmp_persist_paramters"; + return isFullLoad; + } + if (fileType == PUBLIC_PERSIST_FILE) { + isFullLoad = false; + if (access(PARAM_PERSIST_SAVE_PATH, F_OK) == 0 && access(PARAM_PUBLIC_PERSIST_SAVE_PATH, F_OK) != 0) { + int ret = rename(PARAM_PERSIST_SAVE_PATH, PARAM_PUBLIC_PERSIST_SAVE_PATH); + if (ret != 0) { + PARAM_LOGE("rename failed %s", PARAM_PERSIST_SAVE_PATH); + } + } else { + CheckAndCreateDir(PARAM_PUBLIC_PERSIST_SAVE_PATH); + } + *path = PARAM_PUBLIC_PERSIST_SAVE_PATH; + *tmpPath = PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH; + return isFullLoad; + } + if (access(PARAM_OLD_PERSIST_SAVE_PATH, F_OK) == 0 && access(PARAM_PRIVATE_PERSIST_SAVE_PATH, F_OK) != 0) { + int ret = rename(PARAM_OLD_PERSIST_SAVE_PATH, PARAM_PRIVATE_PERSIST_SAVE_PATH); + if (ret != 0) { + PARAM_LOGE("rename failed %s", PARAM_OLD_PERSIST_SAVE_PATH); + } + } else { + CheckAndCreateDir(PARAM_PRIVATE_PERSIST_SAVE_PATH); + } + *path = PARAM_PRIVATE_PERSIST_SAVE_PATH; + *tmpPath = PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH; + return isFullLoad; +} + +static int LoadPersistParam(int fileType) +{ + bool clearFactoryPersistParams = false; + char value[PARAM_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_VALUE_LEN_MAX; + int ret = SystemReadParam("const.startup.param.version", value, &len); + if ((ret != 0 || strcmp(value, "1") != 0) && + (access(PERSIST_PARAM_FIXED_FLAGS, F_OK) != 0)) { + clearFactoryPersistParams = true; + } + const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 max len + char *buffer = calloc(1, buffSize); + PARAM_CHECK(buffer != NULL, return -1, "Failed to alloc"); + + char *tmpPath = ""; + char *path = ""; + bool isFullLoad = GetPersistFilePath(&path, &tmpPath, fileType); + LoadPersistParam_(clearFactoryPersistParams, path, buffer, buffSize, isFullLoad); + LoadPersistParam_(clearFactoryPersistParams, tmpPath, buffer, buffSize, isFullLoad); + free(buffer); + if (clearFactoryPersistParams) { + FILE *fp = fopen(PERSIST_PARAM_FIXED_FLAGS, "w"); + PARAM_CHECK(fp != NULL, return -1, "create file %s fail error %d", PERSIST_PARAM_FIXED_FLAGS, errno); + (void)fclose(fp); + } + return 0; +} + +static int SavePersistParam(const char *name, const char *value) +{ + ParamMutexPend(&g_saveMutex); + int ret = -1; + if (InUpdaterMode() == 1) { + char *path = "/param/persist_parameters"; + FILE *fp = fopen(path, "a+"); + if (fp != NULL) { + ret = fprintf(fp, "%s=%s\n", name, value); + (void)fclose(fp); + } + ParamMutexPost(&g_saveMutex); + return ret; + } + const char *path[PERSIST_HANDLE_MAX] = { PARAM_PUBLIC_PERSIST_SAVE_PATH, PARAM_PRIVATE_PERSIST_SAVE_PATH }; + for (int i = 0; i < PERSIST_HANDLE_MAX; i++) { + FILE *fp = fopen(path[i], "a+"); + if (fp != NULL) { + ret = fprintf(fp, "%s=%s\n", name, value); + (void)fclose(fp); + } + } + ParamMutexPost(&g_saveMutex); + if (ret <= 0) { + PARAM_LOGE("Failed to save persist param %s", name); + } + return ret; +} + +static int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle) +{ + ParamMutexPend(&g_saveMutex); + if (InUpdaterMode() == 1) { + char *path = "/param/tmp_persist_parameters"; + unlink(path); + FILE *fp = fopen(path, "w"); + if (fp == NULL) { + ParamMutexPost(&g_saveMutex); + PARAM_LOGE("Open file %s fail error %d", path, errno); + return -1; + } + handle[0] = (PERSIST_SAVE_HANDLE)fp; + return 0; + } + const char *path[PERSIST_HANDLE_MAX] = { + PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH, + PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH + }; + for (int i = 0; i < PERSIST_HANDLE_MAX; i++) { + unlink(path[i]); + FILE *fp = fopen(path[i], "w"); + if (fp == NULL) { + PARAM_LOGE("Open file %s fail error %d", path[i], errno); + } else { + handle[i] = (PERSIST_SAVE_HANDLE)fp; + } + } + return 0; +} + +static int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle[], const char *name, const char *value) +{ + int ret = 0; + for (int i = 0; i < PERSIST_HANDLE_MAX; i++) { + FILE *fp = (FILE*)handle[i]; + if (fp != NULL) { + ret = fprintf(fp, "%s=%s\n", name, value); + PARAM_CHECK(ret > 0, return -1, "Batchsavepersistparam fail, error %d", errno); + } + } + return (ret > 0) ? 0 : -1; +} + +static void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle[]) +{ + int ret = 0; + if (InUpdaterMode() == 1) { + FILE *fp = (FILE *)handle[0]; + (void)fflush(fp); + (void)fsync(fileno(fp)); + (void)fclose(fp); + unlink("/param/persist_parameters"); + ret = rename("/param/tmp_persist_parameters", "/param/persist_parameters"); + ParamMutexPost(&g_saveMutex); + return; + } + const char *tmpPath[PERSIST_HANDLE_MAX] = { + PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH, + PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH + }; + const char *path[PERSIST_HANDLE_MAX] = { + PARAM_PUBLIC_PERSIST_SAVE_PATH, + PARAM_PRIVATE_PERSIST_SAVE_PATH + }; + for (int i = 0; i < PERSIST_HANDLE_MAX; i++) { + if (handle[i] != NULL) { + FILE *fp = (FILE *)handle[i]; + (void)fflush(fp); + (void)fsync(fileno(fp)); + (void)fclose(fp); + } + unlink(path[i]); + ret = rename(tmpPath[i], path[i]); + } + ParamMutexPost(&g_saveMutex); +} + +int RegisterPersistParamOps(PersistParamOps *ops) +{ + ParamMutexCreate(&g_saveMutex); + PARAM_CHECK(ops != NULL, return -1, "Invalid ops"); + ops->save = SavePersistParam; + ops->load = LoadPersistParam; + ops->batchSaveBegin = BatchSavePersistParamBegin; + ops->batchSave = BatchSavePersistParam; + ops->batchSaveEnd = BatchSavePersistParamEnd; + return 0; +} \ No newline at end of file diff --git a/services/param/adapter/param_selinux.c b/services/param/adapter/param_selinux.c new file mode 100644 index 0000000000000000000000000000000000000000..fdab03645e622d4f56bf4ef43bf38af8dbea8fb0 --- /dev/null +++ b/services/param/adapter/param_selinux.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2021 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 "init_utils.h" +#include "param_manager.h" +#include "param_security.h" +#include "param_utils.h" +#include "param_base.h" +#ifdef PARAM_SUPPORT_SELINUX +#include "selinux_parameter.h" +#endif + +#if defined (__aarch64__) || defined(__x86_64__) || (defined(__riscv) && __riscv_xlen == 64) +#define CHECKER_LIB_NAME "/system/lib64/libparaperm_checker.z.so" +#define CHECKER_UPDATER_LIB "/lib64/libparaperm_checker.z.so" +#else +#define CHECKER_LIB_NAME "/system/lib/libparaperm_checker.z.so" +#define CHECKER_UPDATER_LIB "/lib/libparaperm_checker.z.so" +#endif +typedef int (*SelinuxSetParamCheck)(const char *paraName, const char *destContext, const SrcInfo *info); + +static int InitSelinuxOpsForInit(SelinuxSpace *selinuxSpace) +{ + if (selinuxSpace->selinuxHandle == NULL) { + const char *libname = (GetParamWorkSpace()->ops.updaterMode == 1) ? CHECKER_UPDATER_LIB : CHECKER_LIB_NAME; + selinuxSpace->selinuxHandle = dlopen(libname, RTLD_LAZY); + PARAM_CHECK(selinuxSpace->selinuxHandle != NULL, + return 0, "Failed to dlsym selinuxHandle, %s", dlerror()); + } + void *handle = selinuxSpace->selinuxHandle; + if (selinuxSpace->setParamCheck == NULL) { + selinuxSpace->setParamCheck = (SelinuxSetParamCheck)dlsym(handle, "SetParamCheck"); + PARAM_CHECK(selinuxSpace->setParamCheck != NULL, return -1, "Failed to dlsym setParamCheck %s", dlerror()); + } + if (selinuxSpace->getParamList == NULL) { + selinuxSpace->getParamList = (ParamContextsList *(*)()) dlsym(handle, "GetParamList"); + PARAM_CHECK(selinuxSpace->getParamList != NULL, return -1, "Failed to dlsym getParamList %s", dlerror()); + } + if (selinuxSpace->getParamLabel == NULL) { + selinuxSpace->getParamLabel = (const char *(*)(const char *))dlsym(handle, "GetParamLabel"); + PARAM_CHECK(selinuxSpace->getParamLabel != NULL, return -1, "Failed to dlsym getParamLabel %s", dlerror()); + } + if (selinuxSpace->initParamSelinux == NULL) { + selinuxSpace->initParamSelinux = (int (*)(int))dlsym(handle, "InitParamSelinux"); + PARAM_CHECK(selinuxSpace->initParamSelinux != NULL, return -1, "Failed to dlsym initParamSelinux "); + } + if (selinuxSpace->getParamLabelIndex == NULL) { + selinuxSpace->getParamLabelIndex = (int (*)(const char *))dlsym(handle, "GetParamLabelIndex"); + PARAM_CHECK(selinuxSpace->getParamLabelIndex != NULL, return -1, "Failed to dlsym getParamLabelIndex "); + } + if (selinuxSpace->setSelinuxLogCallback == NULL) { + selinuxSpace->setSelinuxLogCallback = (void (*)())dlsym(handle, "SetInitSelinuxLog"); + } + if (selinuxSpace->destroyParamList == NULL) { + selinuxSpace->destroyParamList = + (void (*)(ParamContextsList **))dlsym(handle, "DestroyParamList"); + PARAM_CHECK(selinuxSpace->destroyParamList != NULL, + return -1, "Failed to dlsym destroyParamList %s", dlerror()); + } + + // init and open avc log + int ret = selinuxSpace->initParamSelinux(1); + if (selinuxSpace->setSelinuxLogCallback != NULL) { + selinuxSpace->setSelinuxLogCallback(); + } + return ret; +} + +static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit) +{ + PARAM_CHECK(GetParamWorkSpace() != NULL, return -1, "Invalid workspace"); + UNUSED(isInit); + PARAM_CHECK(security != NULL, return -1, "Invalid security"); + security->cred.pid = getpid(); + security->cred.uid = geteuid(); + security->cred.gid = getegid(); + security->flags[PARAM_SECURITY_SELINUX] = 0; + PARAM_LOGV("InitLocalSecurityLabel"); +#if !(defined STARTUP_INIT_TEST || defined LOCAL_TEST) + if ((bool)isInit) { + int ret = InitSelinuxOpsForInit(&GetParamWorkSpace()->selinuxSpace); + PARAM_CHECK(ret == 0, return -1, "Failed to init selinux ops"); + } else { + SelinuxSpace *selinuxSpace = &GetParamWorkSpace()->selinuxSpace; + selinuxSpace->initParamSelinux = InitParamSelinux; + selinuxSpace->getParamList = GetParamList; + selinuxSpace->getParamLabel = GetParamLabel; + selinuxSpace->destroyParamList = DestroyParamList; + selinuxSpace->getParamLabelIndex = GetParamLabelIndex; + // init + selinuxSpace->initParamSelinux(isInit); + } +#endif + PARAM_LOGV("Load selinux lib success."); + return 0; +} + +static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel) +{ + return 0; +} + +static void SetSelinuxFileCon(const char *name, const char *context) +{ + PARAM_CHECK(GetParamWorkSpace() != NULL && GetParamWorkSpace()->ops.setfilecon != NULL, + return, "Invalid workspace or setfilecon"); + static char buffer[FILENAME_LEN_MAX] = {0}; + int len = PARAM_SPRINTF(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, context); + if (len > 0) { + buffer[len] = '\0'; + PARAM_LOGV("setfilecon name %s path: %s %s ", name, context, buffer); + if (GetParamWorkSpace()->ops.setfilecon(buffer, context) < 0) { + PARAM_LOGE("Failed to setfilecon %s ", context); + } + } +} + +static void HandleSelinuxLabelForOpen(const ParameterNode *paramNode, int readOnly) +{ + uint32_t labelIndex = paramNode->index + WORKSPACE_INDEX_BASE; + int ret = OpenWorkSpace(labelIndex, readOnly); + if (ret != 0) { + PARAM_LOGE("Forbid to add selinux workspace %s %s", paramNode->paraName, paramNode->paraContext); + return; + } + if (!readOnly) { + // set selinux label + SetSelinuxFileCon(paramNode->paraName, paramNode->paraContext); + } +} + +static void HandleSelinuxLabelForInit(const ParameterNode *paramNode, int readOnly) +{ + uint32_t labelIndex = paramNode->index + WORKSPACE_INDEX_BASE; + int ret = AddWorkSpace(paramNode->paraContext, labelIndex, readOnly, 0); + PARAM_CHECK(ret == 0, return, "Not enough memory for %s", paramNode->paraContext); + + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return, "Invalid workspace"); + if (paramSpace->maxLabelIndex < labelIndex) { + paramSpace->maxLabelIndex = labelIndex; + } +} + +int SelinuxGetAllLabel(int readOnly, + void (*handleSelinuxLabel)(const ParameterNode *paramNode, int readOnly)) +{ + SelinuxSpace *selinuxSpace = &GetParamWorkSpace()->selinuxSpace; + PARAM_CHECK(selinuxSpace->getParamList != NULL, return DAC_RESULT_FORBIDED, "Invalid getParamList"); + ParamContextsList *node = selinuxSpace->getParamList(); + int count = 0; + while (node != NULL) { + PARAM_LOGV("SelinuxGetAllLabel index %d name %s content %s", + node->info.index, node->info.paraName, node->info.paraContext); + if (node->info.paraContext == NULL || node->info.paraName == NULL) { + node = node->next; + continue; + } + handleSelinuxLabel(&node->info, readOnly); + count++; + node = node->next; + } + ParameterNode tmpNode = {WORKSPACE_NAME_DEF_SELINUX, WORKSPACE_NAME_DEF_SELINUX, 0}; + handleSelinuxLabel(&tmpNode, readOnly); + PARAM_LOGV("Selinux get all label counts %d.", count); + return 0; +} + +static void HandleSelinuxLabelForPermission(const ParameterNode *paramNode, int readOnly) +{ + uint32_t labelIndex = paramNode->index + WORKSPACE_INDEX_BASE; + if (labelIndex == WORKSPACE_INDEX_BASE) { + return; + } + if (*(paramNode->paraName + strlen(paramNode->paraName) - 1) != '.') { + return; + } + // save selinux index + ParamWorkSpace *paramWorkspace = GetParamWorkSpace(); + PARAM_CHECK(paramWorkspace != NULL && paramWorkspace->workSpace != NULL, return, "Invalid workspace"); + WorkSpace *space = paramWorkspace->workSpace[WORKSPACE_INDEX_DAC]; + PARAM_CHECK(space != NULL && space->area != NULL, return, "Failed to get dac space %s", paramNode->paraName); + uint32_t index = 0; + (void)FindTrieNode(space, paramNode->paraName, strlen(paramNode->paraName), &index); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, index); + PARAM_CHECK(node != NULL, return, "Can not get security label for %s", paramNode->paraName); + PARAM_LOGV("HandleSelinuxLabelForPermission %s selinuxIndex [ %u %u] dac %u %s ", + paramNode->paraName, labelIndex, node->selinuxIndex, index, paramNode->paraContext); + ParamAuditData auditData = {0}; + auditData.dacData.gid = node->gid; + auditData.dacData.uid = node->uid; + auditData.dacData.mode = node->mode; + auditData.dacData.paramType = node->type; + auditData.selinuxIndex = labelIndex; + auditData.name = paramNode->paraName; + auditData.memberNum = 1; + auditData.members[0] = node->gid; + AddSecurityLabel(&auditData); +} + +static int SelinuxGetParamSecurityLabel(const char *cmd, int readOnly) +{ + if (cmd == NULL || strcmp(cmd, "create") == 0) { // for init and other processor + return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForInit); + } + if ((strcmp(cmd, "init") == 0) && (!readOnly)) { // only for init + return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForOpen); + } + if ((strcmp(cmd, "permission") == 0) && (!readOnly)) { // only for init + return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForPermission); + } + if ((strcmp(cmd, "open") == 0) && readOnly) { // for read only + static int loadLabels = 0; + if (loadLabels) { + return 0; + } + loadLabels = 1; + return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForOpen); + } + return 0; +} + +static int SelinuxGetParamSecurityLabelForInit(const char *path) +{ + return SelinuxGetParamSecurityLabel(path, 0); +} + +static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags) +{ + UNUSED(flags); + UNUSED(localLabel); + UNUSED(fileName); + return 0; +} + +static int UpdaterCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ + return DAC_RESULT_PERMISSION; +} + +static int SelinuxGetParamSecurityLabelForOther(const char *path) +{ + return SelinuxGetParamSecurityLabel(path, 1); +} + +INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit) +{ + PARAM_CHECK(GetParamWorkSpace() != NULL, return -1, "Invalid workspace"); + PARAM_CHECK(ops != NULL, return -1, "Invalid param"); + int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "selinux"); + ops->securityGetLabel = NULL; + ops->securityInitLabel = InitLocalSecurityLabel; + ops->securityCheckFilePermission = CheckFilePermission; + if (GetParamWorkSpace()->ops.updaterMode == 1) { + ops->securityCheckParamPermission = UpdaterCheckParamPermission; + } else { +#ifdef STARTUP_INIT_TEST + ops->securityCheckParamPermission = SelinuxCheckParamPermission; +#endif + } + ops->securityFreeLabel = FreeLocalSecurityLabel; + if (isInit != 0) { + ops->securityGetLabel = SelinuxGetParamSecurityLabelForInit; + } else { + ops->securityGetLabel = SelinuxGetParamSecurityLabelForOther; + } + return ret; +} diff --git a/services/param/base/BUILD.gn b/services/param/base/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..67988934c9acaaca48e603901563dacffe790752 --- /dev/null +++ b/services/param/base/BUILD.gn @@ -0,0 +1,233 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/log", + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/base", + ] +} + +config("exported_header_files_for_lite") { + visibility = [ ":*" ] + include_dirs = [ "//base/hiviewdfx/hilog_lite/interfaces/native/kits" ] +} + +comm_sources = [ + "//base/startup/init/services/param/base/param_comm.c", + "//base/startup/init/services/param/base/param_trie.c", + "//base/startup/init/services/utils/init_hashmap.c", + "//base/startup/init/services/utils/list.c", +] + +base_include_dirs = [ + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/adapter", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/param/base", + "//base/startup/init/services/loopevent/include", +] + +declare_args() { + parameterbase_use_flto = false +} + +template("lib_parameterbase_template") { + __use_flto = invoker.parameterbase_use_flto + if (defined(ohos_lite)) { + static_library(target_name) { + cflags = [ "-fPIC" ] + if (!__use_flto) { + cflags_c = [ "-fno-lto" ] + } + if (ohos_kernel_type == "liteos_m") { + sources = [] + not_needed([ "comm_sources" ]) + } else { + sources = comm_sources + sources += [ + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/services/param/base/param_base.c", + ] + } + include_dirs = base_include_dirs + external_deps = [ "bounds_checking_function:libsec_static" ] + defines = [ "_GNU_SOURCE" ] + public_configs = [ ":exported_header_files" ] + public_configs += [ ":exported_header_files_for_lite" ] + + if (ohos_kernel_type == "linux") { + sources += [ + "//base/startup/init/services/param/adapter/param_dac.c", + "//base/startup/init/services/param/linux/param_osadp.c", + ] + defines += [ "__LINUX__" ] + } else if (ohos_kernel_type == "liteos_a") { + sources += [ + "//base/startup/init/services/param/liteos/param_litedac.c", + "//base/startup/init/services/param/liteos/param_osadp.c", + ] + defines += [ + "__LITEOS_A__", + "WORKSPACE_AREA_NEED_MUTEX", + "PARAM_PERSIST_SAVE_MUTEX", + "PARAMWORKSPACE_NEED_MUTEX", + ] + } + if (defined(init_lite_memory_size)) { + defines += [ "PARAM_WORKSPACE_MAX=${init_lite_memory_size}" ] + } + } + } else { + if (!startup_init_with_param_base) { + inherited_configs = [ + "//build/config/compiler:afdo", + "//build/config/compiler:afdo_optimize_size", + "//build/config/compiler:compiler_arm_fpu", + "//build/config/compiler:compiler_arm_thumb", + "//build/config/compiler:chromium_code", + "//build/config/compiler:default_include_dirs", + "//build/config/compiler:default_optimization", + "//build/config/compiler:default_stack_frames", + "//build/config/compiler:default_symbols", + "//build/config/compiler:export_dynamic", + "//build/config/compiler:no_exceptions", + "//build/config/compiler:no_rtti", + "//build/config/compiler:runtime_library", + "//build/config/sanitizers:default_sanitizer_flags", + ] + } + if (build_selinux) { + if (target_name == "") { + selinux_parameter_external_deps = + [ "selinux_adapter:libselinux_parameter_static" ] + } else { + selinux_parameter_external_deps = + [ "selinux_adapter:libselinux_parameter_static_noflto" ] + } + } + + ohos_static_library(target_name) { + sources = comm_sources + sources += [ + "//base/startup/init/services/param/adapter/param_dac.c", + "//base/startup/init/services/param/base/param_base.c", + "//base/startup/init/services/param/linux/param_osadp.c", + ] + cflags = [ "-fPIC" ] + if (!__use_flto) { + cflags_c = [ "-fno-lto" ] + } + + include_dirs = base_include_dirs + public_configs = [ ":exported_header_files" ] + defines = [ "_GNU_SOURCE" ] + deps = [] + external_deps = [] + + if (startup_init_feature_decode_group_file) { + defines += [ "PARAM_DECODE_GROUPID_FROM_FILE" ] + } + if (use_musl) { + defines += [ "__MUSL__" ] + } + + if (startup_init_test_performance) { + defines += [ "PARAM_TEST_PERFORMANCE" ] + } + if (!startup_init_with_param_base) { + ldflags = [ "-nostdlib" ] + remove_configs = inherited_configs + defines += [ "PARAM_BASE" ] + } else { + sources += [ "//base/startup/init/services/log/init_commlog.c" ] + external_deps += [ "bounds_checking_function:libsec_shared" ] + } + if (build_selinux) { + sources += + [ "//base/startup/init/services/param/adapter/param_selinux.c" ] + defines += [ + "PARAM_SUPPORT_SELINUX", + "PARAMWORKSPACE_NEED_MUTEX", + ] + external_deps += selinux_parameter_external_deps + } + if (param_base_log) { + defines += [ "PARAM_BASE_LOG" ] + } + part_name = "init" + subsystem_name = "startup" + } + } +} + +lib_parameterbase_template("parameterbase") { + parameterbase_use_flto = true +} + +lib_parameterbase_template("parameterbase_noflto") { + parameterbase_use_flto = false +} + +if (!defined(ohos_lite)) { + # extend for base + ohos_static_library("parameterbase_ext") { + sources = comm_sources + sources += [ + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/services/param/linux/param_osadp.c", + ] + cflags = [ "-fPIC" ] + include_dirs = base_include_dirs + public_configs = [ ":exported_header_files" ] + defines = [ "_GNU_SOURCE" ] + deps = [] + + include_dirs += [ "//base/startup/init/services/init/include" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + if (build_selinux) { + defines += [ + "PARAM_SUPPORT_SELINUX", + "PARAMWORKSPACE_NEED_MUTEX", + ] + external_deps += [ + "selinux:libselinux_static", + "selinux_adapter:libselinux_parameter_static", + ] + } + if (param_base_log) { + defines += [ "PARAM_BASE_LOG" ] + } + part_name = "init" + subsystem_name = "startup" + } +} + +group("param_base") { + if (defined(ohos_lite)) { + deps = [ ":parameterbase" ] + } else { + if (startup_init_with_param_base) { + deps = [ ":parameterbase" ] + } else { + deps = [ ":parameterbase_ext" ] + } + } +} diff --git a/services/param/base/param_base.c b/services/param/base/param_base.c new file mode 100644 index 0000000000000000000000000000000000000000..10f125b9540bf4818e3a2a8898ebfc7cd72b2c75 --- /dev/null +++ b/services/param/base/param_base.c @@ -0,0 +1,689 @@ +/* + * 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 "param_base.h" + +#include +#include +#include + +#include "init_param.h" +#ifndef STARTUP_INIT_TEST +#include "param_include.h" +#endif +#include "param_manager.h" +#include "param_security.h" +#include "param_trie.h" + +#define PUBLIC_APP_BEGIN_UID 10000 + +static ParamWorkSpace g_paramWorkSpace = {0}; + +static int CheckParamPermission_(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); +STATIC_INLINE int CheckAndExtendSpace(ParamWorkSpace *workSpace, const char *name, uint32_t labelIndex); +STATIC_INLINE ParamTrieNode *BaseFindTrieNode(WorkSpace *workSpace, + const char *key, uint32_t keyLen, uint32_t *matchLabel); +STATIC_INLINE const char *CachedParameterCheck(CachedParameter *param, int *changed); + +static int InitParamSecurity(ParamWorkSpace *workSpace, + RegisterSecurityOpsPtr registerOps, ParamSecurityType type, int isInit, int op) +{ + PARAM_CHECK(workSpace != NULL && type < PARAM_SECURITY_MAX, return -1, "Invalid param"); + registerOps(&workSpace->paramSecurityOps[type], isInit); + PARAM_CHECK(workSpace->paramSecurityOps[type].securityInitLabel != NULL, + return -1, "Invalid securityInitLabel"); + int ret = workSpace->paramSecurityOps[type].securityInitLabel(&workSpace->securityLabel, isInit); + PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to init security"); + + ParamSecurityOps *paramSecurityOps = GetParamSecurityOps(type); + PARAM_CHECK(paramSecurityOps != NULL, return -1, "Invalid paramSecurityOps"); + PARAM_CHECK(paramSecurityOps->securityFreeLabel != NULL, return -1, "Invalid securityFreeLabel"); + PARAM_CHECK(paramSecurityOps->securityCheckFilePermission != NULL, return -1, "Invalid securityCheck"); + if (isInit == LABEL_INIT_FOR_INIT) { + PARAM_CHECK(paramSecurityOps->securityGetLabel != NULL, return -1, "Invalid securityGetLabel"); + } + ret = paramSecurityOps->securityCheckFilePermission(&workSpace->securityLabel, PARAM_STORAGE_PATH, op); + PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "No permission to read file %s", PARAM_STORAGE_PATH); + PARAM_LOGV("Init parameter %s success", paramSecurityOps->name); + return 0; +} + +INIT_LOCAL_API int RegisterSecurityOps(int onlyRead) +{ + int isInit = 0; + int op = DAC_READ; + if (onlyRead == 0) { + isInit = LABEL_INIT_FOR_INIT; + op = DAC_WRITE; + } + int ret = InitParamSecurity(&g_paramWorkSpace, RegisterSecurityDacOps, PARAM_SECURITY_DAC, isInit, op); + PARAM_CHECK(ret == 0, return -1, "Failed to get security operations"); +#ifdef PARAM_SUPPORT_SELINUX + ret = InitParamSecurity(&g_paramWorkSpace, RegisterSecuritySelinuxOps, PARAM_SECURITY_SELINUX, isInit, op); + PARAM_CHECK(ret == 0, return -1, "Failed to get security operations"); +#endif + return ret; +} + +static int CheckNeedInit(int onlyRead, const PARAM_WORKSPACE_OPS *ops) +{ + if (ops != NULL) { + g_paramWorkSpace.ops.updaterMode = ops->updaterMode; + if (ops->getServiceGroupIdByPid != NULL) { + g_paramWorkSpace.ops.getServiceGroupIdByPid = ops->getServiceGroupIdByPid; + } + if (ops->logFunc != NULL) { + if (onlyRead == 0) { + g_paramWorkSpace.ops.logFunc = ops->logFunc; + } else if (g_paramWorkSpace.ops.logFunc == NULL) { + g_paramWorkSpace.ops.logFunc = ops->logFunc; + } + } +#ifdef PARAM_SUPPORT_SELINUX + g_paramWorkSpace.ops.setfilecon = ops->setfilecon; +#endif + } + if (PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { + PARAM_LOGV("Param workspace has been init"); + if (PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_FOR_INIT)) { + return 0; // init has been init workspace, do not init + } + if (onlyRead == 0) { // init not init workspace, do init it + CloseParamWorkSpace(); + return 1; + } + return 0; + } + if (onlyRead == 0) { + return 1; + } +#ifdef STARTUP_INIT_TEST + // for ut, do not init workspace + char path[PATH_MAX] = { 0 }; + (void)readlink("/proc/self/exe", path, sizeof(path) - 1); + char *name = strstr(path, "/init_unittest"); + if (name != NULL) { + PARAM_LOGW("Can not init client for init_test"); + return 0; + } +#endif + return 1; +} + +static int AllocSpaceMemory(uint32_t maxLabel) +{ + WorkSpace *workSpace = GetWorkSpace(WORKSPACE_INDEX_SIZE); + PARAM_CHECK(workSpace != NULL, return PARAM_CODE_ERROR, "Invalid dac workspace"); + if (workSpace->area->spaceSizeOffset != 0) { + return 0; + } + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid workspace"); + uint32_t realLen = PARAM_ALIGN(sizeof(WorkSpaceSize) + sizeof(uint32_t) * maxLabel); + PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, return 0, + "Failed to allocate currOffset %u, dataSize %u datalen %u", + workSpace->area->currOffset, workSpace->area->dataSize, realLen); + WorkSpaceSize *node = (WorkSpaceSize *)(workSpace->area->data + workSpace->area->currOffset); + node->maxLabelIndex = maxLabel; + node->spaceSize[WORKSPACE_INDEX_DAC] = PARAM_WORKSPACE_DAC; + node->spaceSize[WORKSPACE_INDEX_BASE] = PARAM_WORKSPACE_MAX; + for (uint32_t i = WORKSPACE_INDEX_BASE + 1; i < maxLabel; i++) { + node->spaceSize[i] = PARAM_WORKSPACE_MIN; + PARAM_LOGV("AllocSpaceMemory spaceSize index %u %u", i, node->spaceSize[i]); + if (paramSpace->workSpace[i] != NULL) { + paramSpace->workSpace[i]->spaceSize = PARAM_WORKSPACE_MIN; + } + } + workSpace->area->spaceSizeOffset = workSpace->area->currOffset; + workSpace->area->currOffset += realLen; + return 0; +} + +static int CreateWorkSpace(int onlyRead) +{ + int ret = 0; + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid workspace"); +#ifdef PARAM_SUPPORT_SELINUX + ret = AddWorkSpace(WORKSPACE_NAME_DAC, WORKSPACE_INDEX_DAC, 0, PARAM_WORKSPACE_DAC); + PARAM_CHECK(ret == 0, return -1, "Failed to add dac workspace"); + ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, WORKSPACE_INDEX_BASE, onlyRead, PARAM_WORKSPACE_MAX); + PARAM_CHECK(ret == 0, return -1, "Failed to add default workspace"); + + // open dac workspace + ret = OpenWorkSpace(WORKSPACE_INDEX_DAC, onlyRead); + PARAM_CHECK(ret == 0, return -1, "Failed to open dac workspace"); + + // for other workspace + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); + if (ops != NULL && ops->securityGetLabel != NULL) { + ret = ops->securityGetLabel("create"); + } + paramSpace->maxLabelIndex++; +#else + ret = AddWorkSpace(WORKSPACE_NAME_NORMAL, WORKSPACE_INDEX_DAC, onlyRead, PARAM_WORKSPACE_MAX); + PARAM_CHECK(ret == 0, return -1, "Failed to add dac workspace"); + ret = OpenWorkSpace(WORKSPACE_INDEX_DAC, onlyRead); + PARAM_CHECK(ret == 0, return -1, "Failed to open dac workspace"); + paramSpace->maxLabelIndex = 1; +#endif + return ret; +} + +INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops) +{ + PARAM_ONLY_CHECK(CheckNeedInit(onlyRead, ops) != 0, return 0); + + paramMutexEnvInit(); + if (!PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { + g_paramWorkSpace.maxSpaceCount = PARAM_DEF_SELINUX_LABEL; + g_paramWorkSpace.workSpace = (WorkSpace **)calloc(g_paramWorkSpace.maxSpaceCount, sizeof(WorkSpace *)); + PARAM_CHECK(g_paramWorkSpace.workSpace != NULL, return -1, "Failed to alloc memory for workSpace"); + } + PARAM_SET_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT); + + int ret = RegisterSecurityOps(onlyRead); + PARAM_CHECK(ret == 0, return -1, "Failed to get security operations"); + g_paramWorkSpace.checkParamPermission = CheckParamPermission_; + ret = CreateWorkSpace(onlyRead); + PARAM_CHECK(ret == 0, return -1, "Failed to create workspace"); + + if (onlyRead == 0) { + PARAM_LOGI("Max selinux label %u %u", g_paramWorkSpace.maxSpaceCount, g_paramWorkSpace.maxLabelIndex); + // alloc space size memory from dac + ret = AllocSpaceMemory(g_paramWorkSpace.maxLabelIndex); + PARAM_CHECK(ret == 0, return -1, "Failed to alloc space size"); + + // add default dac policy + ParamAuditData auditData = {0}; + auditData.name = "#"; + auditData.dacData.gid = DAC_DEFAULT_GROUP; + auditData.dacData.uid = DAC_DEFAULT_USER; + auditData.dacData.mode = DAC_DEFAULT_MODE; // 0774 default mode + auditData.dacData.paramType = PARAM_TYPE_STRING; + auditData.memberNum = 1; + auditData.members[0] = DAC_DEFAULT_GROUP; +#ifdef PARAM_SUPPORT_SELINUX + auditData.selinuxIndex = INVALID_SELINUX_INDEX; +#endif + ret = AddSecurityLabel(&auditData); + PARAM_CHECK(ret == 0, return ret, "Failed to add default dac label"); + PARAM_SET_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_FOR_INIT); + } + return ret; +} + +INIT_LOCAL_API void CloseParamWorkSpace(void) +{ + PARAM_LOGI("CloseParamWorkSpace %x", g_paramWorkSpace.flags); + if (!PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { + return; + } + for (uint32_t i = 0; i < g_paramWorkSpace.maxSpaceCount; i++) { + if (g_paramWorkSpace.workSpace[i] != NULL) { + CloseWorkSpace(g_paramWorkSpace.workSpace[i]); + free(g_paramWorkSpace.workSpace[i]); + } + g_paramWorkSpace.workSpace[i] = NULL; + } + free(g_paramWorkSpace.workSpace); + g_paramWorkSpace.workSpace = NULL; + for (int i = 0; i < PARAM_SECURITY_MAX; i++) { + if (g_paramWorkSpace.paramSecurityOps[i].securityFreeLabel != NULL) { + g_paramWorkSpace.paramSecurityOps[i].securityFreeLabel(&g_paramWorkSpace.securityLabel); + } + } + g_paramWorkSpace.flags = 0; +} + +INIT_LOCAL_API void ParamWorBaseLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...) +{ + if (g_paramWorkSpace.ops.logFunc != NULL) { + va_list vargs; + va_start(vargs, fmt); + g_paramWorkSpace.ops.logFunc(logLevel, domain, tag, fmt, vargs); + va_end(vargs); + } +} + +INIT_INNER_API ParamWorkSpace *GetParamWorkSpace(void) +{ + return &g_paramWorkSpace; +} + +void InitParameterClient(void) +{ + PARAM_WORKSPACE_OPS ops = {0}; + ops.updaterMode = 0; + InitParamWorkSpace(1, &ops); +} + +INIT_LOCAL_API int AddWorkSpace(const char *name, uint32_t labelIndex, int onlyRead, uint32_t spaceSize) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid workspace"); +#ifdef PARAM_SUPPORT_SELINUX + const char *realName = name; +#else + const char *realName = WORKSPACE_NAME_NORMAL; + labelIndex = 0; +#endif + int ret = CheckAndExtendSpace(paramSpace, name, labelIndex); + PARAM_CHECK(ret == 0, return -1, "Not enough memory for %s", realName); + if (paramSpace->workSpace[labelIndex] != NULL) { + return 0; + } + const size_t size = strlen(realName) + 1; + WorkSpace *workSpace = (WorkSpace *)malloc(sizeof(WorkSpace) + size); + PARAM_CHECK(workSpace != NULL, return -1, "Failed to create workspace for %s", realName); + workSpace->flags = 0; + workSpace->spaceSize = spaceSize; + workSpace->area = NULL; + workSpace->spaceIndex = labelIndex; + ATOMIC_INIT(&workSpace->rwSpaceLock, 0); + PARAMSPACE_AREA_INIT_LOCK(workSpace); + ret = PARAM_STRCPY(workSpace->fileName, size, realName); + PARAM_CHECK(ret == 0, free(workSpace); + return -1, "Failed to copy file name %s", realName); + paramSpace->workSpace[labelIndex] = workSpace; + PARAM_LOGV("AddWorkSpace %s index %d onlyRead %s", paramSpace->workSpace[labelIndex]->fileName, + paramSpace->workSpace[labelIndex]->spaceIndex, onlyRead ? "true" : "false"); + + if (spaceSize != 0) { + return ret; + } + // get size + WorkSpaceSize *workSpaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE)); + if (workSpaceSize != NULL) { + paramSpace->workSpace[labelIndex]->spaceSize = workSpaceSize->spaceSize[labelIndex]; + } + return ret; +} + +STATIC_INLINE int CheckAndExtendSpace(ParamWorkSpace *paramSpace, const char *name, uint32_t labelIndex) +{ + if (paramSpace->maxSpaceCount > labelIndex) { + return 0; + } + if (labelIndex >= PARAM_MAX_SELINUX_LABEL) { + PARAM_LOGE("Not enough memory for label index %u", labelIndex); + return -1; + } + PARAM_LOGW("Not enough memory for label index %u need to extend memory %u", labelIndex, paramSpace->maxSpaceCount); + WorkSpace **space = (WorkSpace **)calloc(sizeof(WorkSpace *), + paramSpace->maxSpaceCount + PARAM_DEF_SELINUX_LABEL); + PARAM_CHECK(space != NULL, return -1, "Failed to realloc memory for %s", name); + int ret = PARAM_MEMCPY(space, sizeof(WorkSpace *) * paramSpace->maxSpaceCount, + paramSpace->workSpace, sizeof(WorkSpace *) * paramSpace->maxSpaceCount); + PARAM_CHECK(ret == 0, free(space); + return -1, "Failed to copy memory for %s", name); + paramSpace->maxSpaceCount += PARAM_DEF_SELINUX_LABEL; + free(paramSpace->workSpace); + paramSpace->workSpace = space; + return 0; +} + +INIT_LOCAL_API int OpenWorkSpace(uint32_t index, int readOnly) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL && paramSpace->workSpace != NULL, return -1, "Invalid workspace index %u", index); + WorkSpace *workSpace = NULL; + PARAM_ONLY_CHECK(index >= paramSpace->maxSpaceCount, workSpace = paramSpace->workSpace[index]); + PARAM_CHECK(workSpace != NULL, return 0, "Invalid index %d", index); + int ret = 0; + uint32_t rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, MEMORY_ORDER_ACQUIRE); + while (rwSpaceLock & WORKSPACE_STATUS_IN_PROCESS) { + futex_wait_private(&workSpace->rwSpaceLock, rwSpaceLock); + rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, MEMORY_ORDER_ACQUIRE); + } + + ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock | WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE); + if (workSpace->area == NULL) { + ret = InitWorkSpace(workSpace, readOnly, workSpace->spaceSize); + if (ret != 0) { + PARAM_LOGE("Forbid to open workspace for %s error %d", workSpace->fileName, errno); + } +#ifndef PARAM_SUPPORT_SELINUX + } + ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock & ~WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE); +#else + } else if (readOnly) { + if ((rwSpaceLock & WORKSPACE_STATUS_VALID) == WORKSPACE_STATUS_VALID) { + ret = 0; + } else if ((paramSpace->flags & WORKSPACE_FLAGS_NEED_ACCESS) == WORKSPACE_FLAGS_NEED_ACCESS) { + char buffer[FILENAME_LEN_MAX] = {0}; + int size = PARAM_SPRINTF(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, workSpace->fileName); + if (size > 0 && access(buffer, R_OK) == 0) { + PARAM_LOGW("Open workspace %s access ok ", workSpace->fileName); + rwSpaceLock |= WORKSPACE_STATUS_VALID; + ret = 0; + } else { + ret = -1; + PARAM_LOGE("Forbid to open workspace for %s error %d", workSpace->fileName, errno); + rwSpaceLock &= ~WORKSPACE_STATUS_VALID; + } + } + } + ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock & ~WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE); + futex_wake_private(&workSpace->rwSpaceLock, INT_MAX); +#endif + return ret; +} + +STATIC_INLINE int ReadParamWithCheck(WorkSpace **workspace, const char *name, uint32_t op, ParamTrieNode **node) +{ + ParamLabelIndex labelIndex = {0}; + WorkSpace *dacSpace = g_paramWorkSpace.workSpace[0]; + PARAM_CHECK(dacSpace != NULL && dacSpace->area != NULL, + return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name); + *node = BaseFindTrieNode(dacSpace, name, strlen(name), &labelIndex.dacLabelIndex); + labelIndex.workspace = GetWorkSpaceByName(name); + PARAM_CHECK(labelIndex.workspace != NULL, return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name); + labelIndex.selinuxLabelIndex = labelIndex.workspace->spaceIndex; + + int ret = CheckParamPermission_(&labelIndex, &g_paramWorkSpace.securityLabel, name, op); + PARAM_CHECK(ret == 0, return ret, "Forbid to read parameter %s", name); +#ifdef PARAM_SUPPORT_SELINUX + // search from real workspace + *node = BaseFindTrieNode(labelIndex.workspace, name, strlen(name), NULL); +#endif + *workspace = labelIndex.workspace; + return ret; +} + +static int CheckUserInGroup(WorkSpace *space, const ParamSecurityNode *node, uid_t uid) +{ + for (uint32_t i = 0; i < node->memberNum; i++) { + if (node->members[i] == uid) { + return 0; + } + } + return -1; +} + +STATIC_INLINE int DacCheckGroupPermission(const ParamSecurityLabel *srcLabel, uint32_t mode, ParamSecurityNode *node) +{ + uint32_t localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START; + if (srcLabel->cred.gid == node->gid) { + if ((node->mode & localMode) != 0) { + return DAC_RESULT_PERMISSION; + } + } + if (mode != DAC_WRITE || g_paramWorkSpace.ops.getServiceGroupIdByPid == NULL) { + return DAC_RESULT_FORBIDED; + } + gid_t gids[64] = { 0 }; // max gid number + const uint32_t gidNumber = (uint32_t)g_paramWorkSpace.ops.getServiceGroupIdByPid( + srcLabel->cred.pid, gids, sizeof(gids) / sizeof(gids[0])); + for (uint32_t index = 0; index < gidNumber; index++) { + PARAM_LOGV("DacCheckGroupPermission gid %u", gids[index]); + if (gids[index] != node->gid) { + continue; + } + if ((node->mode & localMode) != 0) { + return DAC_RESULT_PERMISSION; + } + } + return DAC_RESULT_FORBIDED; +} + +STATIC_INLINE int DacCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ +#ifndef STARTUP_INIT_TEST + if (srcLabel->cred.uid == 0) { + return DAC_RESULT_PERMISSION; + } +#endif + // get dac label + WorkSpace *space = g_paramWorkSpace.workSpace[WORKSPACE_INDEX_DAC]; + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex->dacLabelIndex); + PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %u selinuxLabelIndex %u for %s", + labelIndex->dacLabelIndex, labelIndex->selinuxLabelIndex, name); + /** + * DAC group + * user:group:read|write|watch + */ + uint32_t localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_OTHER_START; + // 1, check other + if ((node->mode & localMode) != 0) { + return DAC_RESULT_PERMISSION; + } + // 2, check uid + if (srcLabel->cred.uid == node->uid) { + localMode = mode & (DAC_READ | DAC_WRITE | DAC_WATCH); + if ((node->mode & localMode) != 0) { + return DAC_RESULT_PERMISSION; + } + } + // 3, check gid + if (DacCheckGroupPermission(srcLabel, mode, node) == DAC_RESULT_PERMISSION) { + return DAC_RESULT_PERMISSION; + } + // 4, check user in group + if (CheckUserInGroup(space, node, srcLabel->cred.uid) == 0) { + localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START; + if ((node->mode & localMode) != 0) { + return DAC_RESULT_PERMISSION; + } + } + // forbid + PARAM_LOGW("Param '%s' label gid:%d uid:%d mode 0%x", name, srcLabel->cred.gid, srcLabel->cred.uid, mode); + PARAM_LOGW("Cfg label %u gid:%d uid:%d mode 0%x ", labelIndex->dacLabelIndex, node->gid, node->uid, node->mode); + + int ret = DAC_RESULT_FORBIDED; +#ifndef __MUSL__ +#ifndef STARTUP_INIT_TEST + ret = DAC_RESULT_PERMISSION; +#endif +#endif + return ret; +} + +#ifdef PARAM_SUPPORT_SELINUX +STATIC_INLINE const char *GetSelinuxContent(const char *name) +{ + SelinuxSpace *selinuxSpace = &g_paramWorkSpace.selinuxSpace; + const char *content = WORKSPACE_NAME_DEF_SELINUX; + if (selinuxSpace->getParamLabel != NULL) { + content = selinuxSpace->getParamLabel(name); + } + return content; +} + +STATIC_INLINE int SelinuxCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ + SelinuxSpace *selinuxSpace = &g_paramWorkSpace.selinuxSpace; + int ret = SELINUX_RESULT_FORBIDED; + if (mode == DAC_WRITE) { + PARAM_CHECK(selinuxSpace->setParamCheck != NULL, return ret, "Invalid setParamCheck"); + // check + SrcInfo info; + info.uc.pid = srcLabel->cred.pid; + info.uc.uid = srcLabel->cred.uid; + info.uc.gid = srcLabel->cred.gid; + info.sockFd = srcLabel->sockFd; + const char *context = GetSelinuxContent(name); + ret = selinuxSpace->setParamCheck(name, context, &info); + } else { +#ifdef STARTUP_INIT_TEST + return selinuxSpace->readParamCheck(name); +#endif + ret = OpenWorkSpace(labelIndex->selinuxLabelIndex, 1); + } + if (ret != 0) { + ret = SELINUX_RESULT_FORBIDED; + PARAM_LOGE("Selinux check name %s in %s info [%d %d %d] failed!", + name, GetSelinuxContent(name), srcLabel->cred.pid, srcLabel->cred.uid, srcLabel->cred.gid); + } + return ret; +} +#endif + +#if defined(STARTUP_INIT_TEST) || defined(__LITEOS_A__) || defined(__LITEOS_M__) +static int CheckParamPermission_(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ + // for root, all permission, but for appspawn must to check + if (srcLabel->cred.uid == 0 && srcLabel->cred.pid == 1) { + return DAC_RESULT_PERMISSION; + } + int ret = DAC_RESULT_PERMISSION; + for (int i = 0; i < PARAM_SECURITY_MAX; i++) { + if (PARAM_TEST_FLAG(g_paramWorkSpace.securityLabel.flags[i], LABEL_ALL_PERMISSION)) { + continue; + } + ParamSecurityOps *ops = &g_paramWorkSpace.paramSecurityOps[i]; + if (ops->securityCheckParamPermission == NULL) { + continue; + } + ret = ops->securityCheckParamPermission(labelIndex, srcLabel, name, mode); + if (ret == DAC_RESULT_FORBIDED) { + PARAM_LOGW("CheckParamPermission %s %s FORBID", ops->name, name); + break; + } + } + return ret; +} +#else +static int CheckParamPermission_(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ + // only for root and write, all permission, but for appspawn must to check + // for clod start in new namespace, pid==1 and uid==root + if (srcLabel->cred.uid == 0 && srcLabel->cred.pid == 1 && mode == DAC_WRITE) { + return DAC_RESULT_PERMISSION; + } + int ret = 0; + if (srcLabel->cred.uid < PUBLIC_APP_BEGIN_UID) { + ret = DacCheckParamPermission(labelIndex, srcLabel, name, mode); + } +#ifdef PARAM_SUPPORT_SELINUX + if (ret == DAC_RESULT_PERMISSION) { + ret = SelinuxCheckParamPermission(labelIndex, srcLabel, name, mode); + } +#endif + return ret; +} +#endif + +STATIC_INLINE ParamTrieNode *BaseFindTrieNode(WorkSpace *workSpace, + const char *key, uint32_t keyLen, uint32_t *matchLabel) +{ + PARAM_CHECK(key != NULL && keyLen > 0, return NULL, "Invalid key "); + uint32_t tmpMatchLen = 0; + ParamTrieNode *node = FindTrieNode_(workSpace, key, keyLen, &tmpMatchLen); + if (matchLabel != NULL) { + *matchLabel = tmpMatchLen; + } + if (node != NULL && node->dataIndex != 0) { + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); + if (entry != NULL && entry->keyLength == keyLen) { + return node; + } + return NULL; + } + return node; +} + +CachedHandle CachedParameterCreate(const char *name, const char *defValue) +{ + if (name == NULL || defValue == NULL) { + return NULL; + } + PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return NULL, "Invalid param workspace"); + uint32_t nameLen = strlen(name); + PARAM_CHECK(nameLen < PARAM_NAME_LEN_MAX, return NULL, "Invalid name %s", name); + uint32_t valueLen = strlen(defValue); + if (IS_READY_ONLY(name)) { + PARAM_CHECK(valueLen < PARAM_CONST_VALUE_LEN_MAX, return NULL, "Illegal param value %s", defValue); + } else { + PARAM_CHECK(valueLen < PARAM_VALUE_LEN_MAX, return NULL, "Illegal param value %s length", defValue); + } + + ParamTrieNode *node = NULL; + WorkSpace *workspace = NULL; + int ret = ReadParamWithCheck(&workspace, name, DAC_READ, &node); + PARAM_CHECK(ret == 0, return NULL, "Forbid to access parameter %s", name); + PARAM_CHECK(workspace != NULL && workspace->area != NULL, return NULL, "Forbid to access parameter %s", name); + + CachedParameter *param = (CachedParameter *)malloc( + sizeof(CachedParameter) + PARAM_ALIGN(nameLen) + 1 + PARAM_VALUE_LEN_MAX); + PARAM_CHECK(param != NULL, return NULL, "Failed to create CachedParameter for %s", name); + ret = PARAM_STRCPY(param->data, nameLen + 1, name); + PARAM_CHECK(ret == 0, free(param); + return NULL, "Failed to copy name %s", name); + param->cachedParameterCheck = CachedParameterCheck; + param->workspace = workspace; + param->nameLen = nameLen; + param->paramValue = ¶m->data[PARAM_ALIGN(nameLen) + 1]; + param->bufferLen = PARAM_VALUE_LEN_MAX; + param->dataCommitId = (uint32_t)-1; + if (node != NULL && node->dataIndex != 0) { + param->dataIndex = node->dataIndex; + ParamNode *entry = (ParamNode *)GetTrieNode(workspace, node->dataIndex); + PARAM_CHECK(entry != NULL, free(param); + return NULL, "Failed to get trie node %s", name); + uint32_t length = param->bufferLen; + param->dataCommitId = ReadCommitId(entry); + ret = ReadParamValue_(entry, ¶m->dataCommitId, param->paramValue, &length); + PARAM_CHECK(ret == 0, free(param); + return NULL, "Failed to read parameter value %s", name); + } else { + param->dataIndex = 0; + ret = PARAM_STRCPY(param->paramValue, param->bufferLen, defValue); + PARAM_CHECK(ret == 0, free(param); + return NULL, "Failed to copy name %s", name); + } + param->spaceCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&workspace->area->commitId, MEMORY_ORDER_ACQUIRE); + PARAM_LOGV("CachedParameterCreate %u %u %lld \n", param->dataIndex, param->dataCommitId, param->spaceCommitId); + return (CachedHandle)param; +} + +STATIC_INLINE const char *CachedParameterCheck(CachedParameter *param, int *changed) +{ + *changed = 0; + if (param->dataIndex == 0) { + ParamTrieNode *node = BaseFindTrieNode(param->workspace, param->data, param->nameLen, NULL); + if (node != NULL) { + param->dataIndex = node->dataIndex; + } else { + return param->paramValue; + } + } + ParamNode *entry = (ParamNode *)GetTrieNode(param->workspace, param->dataIndex); + PARAM_CHECK(entry != NULL, return param->paramValue, "Failed to get trie node %s", param->data); + uint32_t dataCommitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); + dataCommitId &= PARAM_FLAGS_COMMITID; + if (param->dataCommitId == dataCommitId) { + return param->paramValue; + } + uint32_t length = param->bufferLen; + param->dataCommitId = dataCommitId; + int ret = ReadParamValue_(entry, ¶m->dataCommitId, param->paramValue, &length); + PARAM_CHECK(ret == 0, return NULL, "Failed to copy value %s", param->data); + PARAM_LOGV("CachedParameterCheck %u", param->dataCommitId); + *changed = 1; + return param->paramValue; +} + +void CachedParameterDestroy(CachedHandle handle) +{ + if (handle != NULL) { + free(handle); + handle = NULL; + } +} diff --git a/services/param/base/param_base.h b/services/param/base/param_base.h new file mode 100644 index 0000000000000000000000000000000000000000..a7a259d553436deb978e0957b62d11e5b46f32fb --- /dev/null +++ b/services/param/base/param_base.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 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_PARAM_BASE_H +#define BASE_STARTUP_PARAM_BASE_H + +#include "param_osadp.h" +#include "param_trie.h" + +#ifndef PARAM_BASE +#include "securec.h" +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define WORKSPACE_STATUS_IN_PROCESS 0x01 +#define WORKSPACE_STATUS_VALID 0x02 + +#define READ_COMMIT_ID_LOOP_RETRY_TIME_WARNING 50 +#ifndef PARAM_BASE +#define PARAM_SPRINTF(buffer, buffSize, format, ...) \ + snprintf_s((buffer), (buffSize), (buffSize) - 1, (format), ##__VA_ARGS__) +#define PARAM_MEMCPY(dest, destMax, src, count) memcpy_s((dest), (destMax), (src), (count)) +#define PARAM_STRCPY(strDest, destMax, strSrc) strcpy_s((strDest), (destMax), (strSrc)) +#else +#define PARAM_SPRINTF(buffer, buffSize, format, ...) snprintf((buffer), (buffSize), (format), ##__VA_ARGS__) +#define PARAM_MEMCPY(dest, destMax, src, count) (memcpy((dest), (src), (count)) != NULL) ? 0 : 1 +#define PARAM_STRCPY(strDest, destMax, strSrc) (strcpy((strDest), (strSrc)) != NULL) ? 0 : 1 +#endif + +static inline uint32_t ReadCommitId(ParamNode *entry) +{ + uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); + uint32_t retryTimes = 0; + while (commitId & PARAM_FLAGS_MODIFY) { + futex_wait(&entry->commitId, commitId); + commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); + if (retryTimes++ % READ_COMMIT_ID_LOOP_RETRY_TIME_WARNING == 0) { + PARAM_LOGW("ReadCommitId warning, too many retry times, %{public}d", retryTimes); + } + } + return commitId & PARAM_FLAGS_COMMITID; +} + +static inline int ReadParamValue_(ParamNode *entry, uint32_t *commitId, char *value, uint32_t *length) +{ + uint32_t id = *commitId; + do { + *commitId = id; + int ret = PARAM_MEMCPY(value, *length, entry->data + entry->keyLength + 1, entry->valueLength); + PARAM_CHECK(ret == 0, return -1, "Failed to copy value"); + value[entry->valueLength] = '\0'; + *length = entry->valueLength; + id = ReadCommitId(entry); + } while (*commitId != id); // if change,must read + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_PARAM_BASE_H \ No newline at end of file diff --git a/services/param/base/param_comm.c b/services/param/base/param_comm.c new file mode 100644 index 0000000000000000000000000000000000000000..29f299edd4dee8c2e5b86b7d60610f3a6e54127e --- /dev/null +++ b/services/param/base/param_comm.c @@ -0,0 +1,151 @@ +/* + * 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 "param_manager.h" +#include "param_trie.h" +#include "param_base.h" + +INIT_LOCAL_API WorkSpace *GetWorkSpaceByName(const char *name) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); +#ifdef PARAM_SUPPORT_SELINUX + if (paramSpace->selinuxSpace.getParamLabelIndex == NULL) { + return NULL; + } + uint32_t labelIndex = (uint32_t)paramSpace->selinuxSpace.getParamLabelIndex(name) + WORKSPACE_INDEX_BASE; + if (labelIndex < paramSpace->maxSpaceCount) { + return paramSpace->workSpace[labelIndex]; + } + return NULL; +#else + return paramSpace->workSpace[WORKSPACE_INDEX_DAC]; +#endif +} + +INIT_LOCAL_API WorkSpace *GetWorkSpace(uint32_t labelIndex) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); + PARAM_CHECK(paramSpace->workSpace != NULL, return NULL, "Invalid paramSpace->workSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space"); +#ifdef PARAM_SUPPORT_SELINUX + if (labelIndex == 0) { + return paramSpace->workSpace[0]; + } + WorkSpace *workSpace = NULL; + if (labelIndex < paramSpace->maxSpaceCount) { + workSpace = paramSpace->workSpace[labelIndex]; + } + if (workSpace == NULL) { + return NULL; + } + uint32_t rwSpaceLock = ATOMIC_LOAD_EXPLICIT(&workSpace->rwSpaceLock, MEMORY_ORDER_ACQUIRE); + if (rwSpaceLock & WORKSPACE_STATUS_IN_PROCESS) { + return NULL; + } + if (workSpace->area != NULL) { + return workSpace; + } + return NULL; +#else + return paramSpace->workSpace[0]; +#endif +} + +INIT_LOCAL_API ParamSecurityOps *GetParamSecurityOps(int type) +{ + PARAM_CHECK(type < PARAM_SECURITY_MAX, return NULL, "Invalid type"); + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); + return ¶mSpace->paramSecurityOps[type]; +} + +INIT_LOCAL_API ParamSecurityLabel *GetParamSecurityLabel() +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); + return ¶mSpace->securityLabel; +} + +INIT_LOCAL_API int SplitParamString(char *line, const char *exclude[], uint32_t count, + int (*result)(const uint32_t *context, const char *name, const char *value), const uint32_t *context) +{ + PARAM_CHECK(line != NULL, return 0, "Empty line"); + // Skip spaces + char *name = line; + while (isspace(*name) && (*name != '\0')) { + name++; + } + // Empty line or Comment line + if (*name == '\0' || *name == '#') { + return 0; + } + + char *value = name; + // find the first delimiter '=' + while (*value != '\0') { + if (*value == '=') { + (*value) = '\0'; + value = value + 1; + break; + } + value++; + } + + // Skip spaces + char *tmp = name; + while ((tmp < value) && (*tmp != '\0')) { + if (isspace(*tmp)) { + (*tmp) = '\0'; + break; + } + tmp++; + } + + // empty name, just ignore this line + if (*value == '\0') { + return 0; + } + + // Filter excluded parameters + for (uint32_t i = 0; i < count; i++) { + if (strncmp(name, exclude[i], strlen(exclude[i])) == 0) { + return 0; + } + } + + // Skip spaces for value + while (isspace(*value) && (*value != '\0')) { + value++; + } + + // Trim the ending spaces of value + char *pos = value + strlen(value); + pos--; + while (isspace(*pos) && pos > value) { + (*pos) = '\0'; + pos--; + } + + // Strip starting and ending " for value + if ((*value == '"') && (pos > value) && (*pos == '"')) { + value = value + 1; + *pos = '\0'; + } + return result(context, name, value); +} diff --git a/services/param/base/param_include.h b/services/param/base/param_include.h new file mode 100644 index 0000000000000000000000000000000000000000..c768aa7709b38eaf2f9281a7b8049d0b50697085 --- /dev/null +++ b/services/param/base/param_include.h @@ -0,0 +1,110 @@ +/* + * 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_PARAM_INCLUDE_H +#define BASE_STARTUP_PARAM_INCLUDE_H +#include + +#include "param_osadp.h" +#include "param_trie.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +STATIC_INLINE void GetNextKey(const char **remainingKey, char **subKey, uint32_t *subKeyLen, const char *end) +{ + *subKey = strchr(*remainingKey, '.'); + if (*subKey != NULL) { + *subKeyLen = *subKey - *remainingKey; + } else { + *subKeyLen = end - *remainingKey; + } +} + +STATIC_INLINE ParamTrieNode *FindSubTrie(const WorkSpace *workSpace, + ParamTrieNode *current, const char *key, uint32_t keyLen, uint32_t *matchLabel) +{ + ParamTrieNode *subTrie = current; + int ret = 0; + while (subTrie != NULL) { + if (subTrie->length > keyLen) { + ret = -1; + } else if (subTrie->length < keyLen) { + ret = 1; + } else { + ret = memcmp(subTrie->key, key, keyLen); + if (ret == 0) { + PARAM_CHECK(matchLabel != NULL, return NULL, "Invalid matchLabel"); + *matchLabel = (subTrie->labelIndex != 0) ? subTrie->labelIndex : *matchLabel; + return subTrie; + } + } + + uint32_t offset = 0; + if (ret < 0) { + offset = subTrie->left; + } else { + offset = subTrie->right; + } + if (offset == 0 || offset > workSpace->area->dataSize) { + return NULL; + } + subTrie = (ParamTrieNode *)(workSpace->area->data + offset); + } + return NULL; +} + +STATIC_INLINE ParamTrieNode *FindTrieNode_( + const WorkSpace *workSpace, const char *key, uint32_t keyLen, uint32_t *matchLabel) +{ + const char *remainingKey = key; + ParamTrieNode *current = GetTrieRoot(workSpace); + PARAM_CHECK(current != NULL, return NULL, "Invalid current param %s", key); + *matchLabel = current->labelIndex; + const char *end = key + keyLen; + while (1) { + uint32_t subKeyLen = 0; + char *subKey = NULL; + GetNextKey(&remainingKey, &subKey, &subKeyLen, end); + if (!subKeyLen) { + return NULL; + } + if (current->child != 0) { + ParamTrieNode *next = GetTrieNode(workSpace, current->child); + current = FindSubTrie(workSpace, next, remainingKey, subKeyLen, matchLabel); + } else { + current = FindSubTrie(workSpace, current, remainingKey, subKeyLen, matchLabel); + } + if (current == NULL) { + return NULL; + } else if (current->labelIndex != 0) { + *matchLabel = current->labelIndex; + } + if (subKey == NULL || strcmp(subKey, ".") == 0) { + break; + } + remainingKey = subKey + 1; + } + return current; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_PARAM_INCLUDE_H \ No newline at end of file diff --git a/services/param/base/param_trie.c b/services/param/base/param_trie.c new file mode 100644 index 0000000000000000000000000000000000000000..99dd6328c8f7aaba0c99ad3dcb0e0a32971b0203 --- /dev/null +++ b/services/param/base/param_trie.c @@ -0,0 +1,417 @@ +/* + * 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 "param_trie.h" + +#include + +#include "init_param.h" +#include "param_base.h" +#include "param_manager.h" +#include "param_osadp.h" +#include "param_utils.h" +#include "param_include.h" + +#define OFFSET_ERR 0 + +static uint32_t AllocateParamTrieNode(WorkSpace *workSpace, const char *key, uint32_t keyLen); + +static int GetRealFileName(WorkSpace *workSpace, char *buffer, uint32_t size) +{ + int ret = PARAM_SPRINTF(buffer, size, "%s/%s", PARAM_STORAGE_PATH, workSpace->fileName); + PARAM_CHECK(ret > 0, return -1, "Failed to copy file name %s", workSpace->fileName); + buffer[ret] = '\0'; + return 0; +} + +static int InitWorkSpace_(WorkSpace *workSpace, uint32_t spaceSize, int readOnly) +{ + PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace"); + PARAM_CHECK(sizeof(ParamTrieHeader) < spaceSize, + return PARAM_CODE_INVALID_PARAM, "Invalid spaceSize %u name %s", spaceSize, workSpace->fileName); + + char buffer[FILENAME_LEN_MAX] = {0}; + int ret = GetRealFileName(workSpace, buffer, sizeof(buffer)); + PARAM_CHECK(ret == 0, return -1, "Failed to get file name %s", workSpace->fileName); + void *areaAddr = GetSharedMem(buffer, &workSpace->memHandle, spaceSize, readOnly); + PARAM_ONLY_CHECK(areaAddr != NULL, return PARAM_CODE_MEMORY_MAP_FAILED); + if (!readOnly) { + workSpace->area = (ParamTrieHeader *)areaAddr; + ATOMIC_UINT64_INIT(&workSpace->area->commitId, 0); + ATOMIC_UINT64_INIT(&workSpace->area->commitPersistId, 0); + workSpace->area->trieNodeCount = 0; + workSpace->area->paramNodeCount = 0; + workSpace->area->securityNodeCount = 0; + workSpace->area->dataSize = spaceSize - sizeof(ParamTrieHeader); + workSpace->area->spaceSizeOffset = 0; + workSpace->area->currOffset = 0; + uint32_t offset = AllocateParamTrieNode(workSpace, "#", 1); + workSpace->area->firstNode = offset; + } else { + workSpace->area = (ParamTrieHeader *)areaAddr; + } + PARAM_LOGV("InitWorkSpace success, readOnly %d currOffset %u firstNode %u dataSize %u", + readOnly, workSpace->area->currOffset, workSpace->area->firstNode, workSpace->area->dataSize); + return 0; +} + +static uint32_t AllocateParamTrieNode(WorkSpace *workSpace, const char *key, uint32_t keyLen) +{ + uint32_t len = keyLen + sizeof(ParamTrieNode) + 1; + len = PARAM_ALIGN(len); + PARAM_CHECK((workSpace->area->currOffset + len) < workSpace->area->dataSize, return 0, + "Failed to allocate currOffset %d, dataSize %d space %s", + workSpace->area->currOffset, workSpace->area->dataSize, workSpace->fileName); + ParamTrieNode *node = (ParamTrieNode *)(workSpace->area->data + workSpace->area->currOffset); + node->length = keyLen; + int ret = PARAM_MEMCPY(node->key, keyLen, key, keyLen); + PARAM_CHECK(ret == 0, return 0, "Failed to copy key"); + node->key[keyLen] = '\0'; + node->left = 0; + node->right = 0; + node->child = 0; + node->dataIndex = 0; + node->labelIndex = 0; + uint32_t offset = workSpace->area->currOffset; + workSpace->area->currOffset += len; + workSpace->area->trieNodeCount++; + return offset; +} + +INIT_LOCAL_API int InitWorkSpace(WorkSpace *workSpace, int onlyRead, uint32_t spaceSize) +{ + PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_NAME, "Invalid workSpace"); + if (PARAM_TEST_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT)) { + return 0; + } + int ret = InitWorkSpace_(workSpace, spaceSize, onlyRead); + PARAM_ONLY_CHECK(ret == 0, return ret); + PARAM_SET_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT); + PARAM_LOGV("InitWorkSpace %s for %s", workSpace->fileName, (onlyRead == 0) ? "init" : "other"); + return ret; +} + +INIT_LOCAL_API void CloseWorkSpace(WorkSpace *workSpace) +{ + PARAM_CHECK(workSpace != NULL, return, "The workspace is null"); + PARAM_LOGV("CloseWorkSpace %s", workSpace->fileName); + if (!PARAM_TEST_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT)) { + return; + } + PARAM_CHECK(workSpace->area != NULL, return, "The workspace area is null"); +#ifdef WORKSPACE_AREA_NEED_MUTEX + ParamRWMutexDelete(&workSpace->rwlock); +#endif + FreeSharedMem(&workSpace->memHandle, workSpace->area, workSpace->area->dataSize); + workSpace->area = NULL; +} + +static int CheckWorkSpace(const WorkSpace *workSpace) +{ + PARAM_CHECK(workSpace != NULL && workSpace->area != NULL, return PARAM_WORKSPACE_NOT_INIT, "The workspace is null"); + if (!PARAM_TEST_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT)) { + return PARAM_WORKSPACE_NOT_INIT; + } + return 0; +} + +static int CompareParamTrieNode(const ParamTrieNode *node, const char *key, uint32_t keyLen) +{ + if (node->length > keyLen) { + return -1; + } else if (node->length < keyLen) { + return 1; + } + return memcmp(node->key, key, keyLen); +} + +static ParamTrieNode *AddToSubTrie(WorkSpace *workSpace, ParamTrieNode *current, const char *key, uint32_t keyLen) +{ + if (current == NULL) { + return NULL; + } + ParamTrieNode *subTrie = NULL; + int ret = CompareParamTrieNode(current, key, keyLen); + if (ret == 0) { + return current; + } + if (ret < 0) { + subTrie = GetTrieNode(workSpace, current->left); + if (subTrie == NULL) { + uint32_t offset = AllocateParamTrieNode(workSpace, key, keyLen); + PARAM_CHECK(offset != 0, return NULL, + "Failed to allocate key '%s' in space '%s'", key, workSpace->fileName); + SaveIndex(¤t->left, offset); + return GetTrieNode(workSpace, current->left); + } + } else { + subTrie = GetTrieNode(workSpace, current->right); + if (subTrie == NULL) { + uint32_t offset = AllocateParamTrieNode(workSpace, key, keyLen); + PARAM_CHECK(offset != 0, return NULL, + "Failed to allocate key '%s' in space '%s'", key, workSpace->fileName); + SaveIndex(¤t->right, offset); + return GetTrieNode(workSpace, current->right); + } + } + return AddToSubTrie(workSpace, subTrie, key, keyLen); +} + +ParamTrieNode *AddTrieNode(WorkSpace *workSpace, const char *key, uint32_t keyLen) +{ + PARAM_CHECK(key != NULL && keyLen > 0, return NULL, "Invalid param "); + PARAM_CHECK(CheckWorkSpace(workSpace) == 0, return NULL, "Invalid workSpace %s", key); + const char *remainingKey = key; + ParamTrieNode *current = GetTrieRoot(workSpace); + PARAM_CHECK(current != NULL, return NULL, "Invalid current param %s", key); + while (1) { + uint32_t subKeyLen = 0; + char *subKey = NULL; + GetNextKey(&remainingKey, &subKey, &subKeyLen, key + keyLen); + if (!subKeyLen) { + return NULL; + } + if (current->child != 0) { // 如果child存在,则检查是否匹配 + ParamTrieNode *next = GetTrieNode(workSpace, current->child); + current = AddToSubTrie(workSpace, next, remainingKey, subKeyLen); + } else { + uint32_t dataOffset = AllocateParamTrieNode(workSpace, remainingKey, subKeyLen); + PARAM_CHECK(dataOffset != 0, return NULL, + "Failed to allocate key '%s' in space '%s'", key, workSpace->fileName); + SaveIndex(¤t->child, dataOffset); + current = (ParamTrieNode *)GetTrieNode(workSpace, current->child); + } + if (current == NULL) { + return NULL; + } + if (subKey == NULL || strcmp(subKey, ".") == 0) { + break; + } + remainingKey = subKey + 1; + } + return current; +} + +static int TraversalSubTrieNode(const WorkSpace *workSpace, + const ParamTrieNode *current, TraversalTrieNodePtr walkFunc, const void *cookie) +{ + if (current == NULL) { + return 0; + } + + walkFunc(workSpace, (ParamTrieNode *)current, cookie); + TraversalSubTrieNode(workSpace, GetTrieNode(workSpace, current->child), walkFunc, cookie); + TraversalSubTrieNode(workSpace, GetTrieNode(workSpace, current->left), walkFunc, cookie); + TraversalSubTrieNode(workSpace, GetTrieNode(workSpace, current->right), walkFunc, cookie); + return 0; +} + +INIT_LOCAL_API int TraversalTrieNode(const WorkSpace *workSpace, + const ParamTrieNode *root, TraversalTrieNodePtr walkFunc, const void *cookie) +{ + PARAM_CHECK(walkFunc != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); + PARAM_CHECK(CheckWorkSpace(workSpace) == 0, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace"); + ParamTrieNode *current = (ParamTrieNode *)root; + if (root == NULL) { + current = GetTrieRoot(workSpace); + } + PARAM_CHECK(current != NULL, return 0, "Invalid current node"); + walkFunc(workSpace, (ParamTrieNode *)current, cookie); + TraversalSubTrieNode(workSpace, GetTrieNode(workSpace, current->child), walkFunc, cookie); + if (root == NULL) { + TraversalSubTrieNode(workSpace, GetTrieNode(workSpace, current->left), walkFunc, cookie); + TraversalSubTrieNode(workSpace, GetTrieNode(workSpace, current->right), walkFunc, cookie); + } + return 0; +} + +INIT_LOCAL_API uint32_t AddParamSecurityNode(WorkSpace *workSpace, const ParamAuditData *auditData) +{ + PARAM_CHECK(CheckWorkSpace(workSpace) == 0, return OFFSET_ERR, "Invalid workSpace"); + PARAM_CHECK(auditData != NULL, return OFFSET_ERR, "Invalid auditData"); + uint32_t realLen = PARAM_ALIGN(sizeof(ParamSecurityNode) + sizeof(uid_t) * auditData->memberNum); + PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, + return OFFSET_ERR, "Failed to allocate currOffset %u, dataSize %u datalen %u", + workSpace->area->currOffset, workSpace->area->dataSize, realLen); + ParamSecurityNode *node = (ParamSecurityNode *)(workSpace->area->data + workSpace->area->currOffset); + node->uid = auditData->dacData.uid; + node->gid = auditData->dacData.gid; + node->mode = auditData->dacData.mode; + node->type = auditData->dacData.paramType & PARAM_TYPE_MASK; +#ifdef PARAM_SUPPORT_SELINUX + node->selinuxIndex = auditData->selinuxIndex; +#else + node->selinuxIndex = 0; +#endif + if (auditData->memberNum > 0) { + // copy member + int ret = PARAM_MEMCPY(node->members, + realLen - sizeof(ParamSecurityNode), auditData->members, auditData->memberNum * sizeof(uid_t)); + PARAM_CHECK(ret == 0, return OFFSET_ERR, "Failed to copy members"); + } + node->memberNum = auditData->memberNum; + uint32_t offset = workSpace->area->currOffset; + workSpace->area->currOffset += realLen; + workSpace->area->securityNodeCount++; + return offset; +} + +INIT_LOCAL_API uint32_t AddParamNode(WorkSpace *workSpace, uint8_t type, + const char *key, uint32_t keyLen, const char *value, uint32_t valueLen, int mode) +{ + PARAM_CHECK(key != NULL && value != NULL, return OFFSET_ERR, "Invalid param"); + PARAM_CHECK(CheckWorkSpace(workSpace) == 0, return OFFSET_ERR, "Invalid workSpace %s", key); + + uint32_t realLen = sizeof(ParamNode) + 1 + 1; + // for const parameter, alloc memory on demand + if ((valueLen > PARAM_VALUE_LEN_MAX) || IS_READY_ONLY(key)) { + realLen += keyLen + valueLen; + } else { + realLen += keyLen + GetParamMaxLen(type); + } + realLen = PARAM_ALIGN(realLen); + PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, + return OFFSET_ERR, "Failed to allocate currOffset %u, dataSize %u datalen %u", + workSpace->area->currOffset, workSpace->area->dataSize, realLen); + + ParamNode *node = (ParamNode *)(workSpace->area->data + workSpace->area->currOffset); + ATOMIC_INIT(&node->commitId, 0); + + node->type = type; + node->keyLength = keyLen; + node->valueLength = valueLen; + int ret = PARAM_SPRINTF(node->data, realLen, "%s=%s", key, value); + PARAM_CHECK(ret > 0, return OFFSET_ERR, "Failed to sprint key and value"); + + if (((unsigned int)mode & LOAD_PARAM_PERSIST) != 0) { + node->commitId |= PARAM_FLAGS_PERSIST; + } + uint32_t offset = workSpace->area->currOffset; + workSpace->area->currOffset += realLen; + workSpace->area->paramNodeCount++; + return offset; +} + +INIT_LOCAL_API void SaveIndex(uint32_t *index, uint32_t offset) +{ + PARAM_ONLY_CHECK(index != NULL, return); + *index = offset; +} + +INIT_LOCAL_API ParamTrieNode *FindTrieNode(WorkSpace *workSpace, + const char *key, uint32_t keyLen, uint32_t *matchLabel) +{ + PARAM_ONLY_CHECK(key != NULL && keyLen > 0, return NULL); + PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workspace for %s", key); + uint32_t tmpMatchLen = 0; + ParamTrieNode *node = NULL; + PARAMSPACE_AREA_RD_LOCK(workSpace); + node = FindTrieNode_(workSpace, key, keyLen, &tmpMatchLen); + PARAMSPACE_AREA_RW_UNLOCK(workSpace); + if (matchLabel != NULL) { + *matchLabel = tmpMatchLen; + } + if (node != NULL && node->dataIndex != 0) { + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); + if (entry != NULL && entry->keyLength == keyLen) { + return node; + } + return NULL; + } + return node; +} + +INIT_LOCAL_API uint32_t GetParamMaxLen(uint8_t type) +{ + static const uint32_t typeLengths[] = { + PARAM_VALUE_LEN_MAX, 32, 8 // 8 max bool length 32 max int length + }; + if (type >= ARRAY_LENGTH(typeLengths)) { + return PARAM_VALUE_LEN_MAX; + } + return typeLengths[type]; +} + +INIT_LOCAL_API ParamNode *GetParamNode(uint32_t index, const char *name) +{ + uint32_t labelIndex = 0; + WorkSpace *space = GetWorkSpace(index); + ParamTrieNode *entry = FindTrieNode(space, name, strlen(name), &labelIndex); + if (entry == NULL || entry->dataIndex == 0) { + return NULL; + } + return (ParamNode *)GetTrieNode(space, entry->dataIndex); +} + +INIT_LOCAL_API int AddParamEntry(uint32_t index, uint8_t type, const char *name, const char *value) +{ + WorkSpace *workSpace = GetWorkSpace(WORKSPACE_INDEX_BASE); + PARAM_CHECK(workSpace != NULL, return PARAM_CODE_ERROR, "Invalid workspace"); + ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL); + if (node != NULL && node->dataIndex != 0) { + return 0; + } + node = AddTrieNode(workSpace, name, strlen(name)); + PARAM_CHECK(node != NULL, return PARAM_CODE_REACHED_MAX, "Failed to add node"); + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); + if (entry == NULL) { + uint32_t offset = AddParamNode(workSpace, type, name, strlen(name), value, strlen(value), 0); + PARAM_CHECK(offset > 0, return PARAM_CODE_REACHED_MAX, "Failed to allocate name %s", name); + SaveIndex(&node->dataIndex, offset); + } + return 0; +} + +INIT_LOCAL_API int AddSecurityLabel(const ParamAuditData *auditData) +{ + PARAM_CHECK(auditData != NULL && auditData->name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid auditData"); + WorkSpace *workSpace = GetWorkSpace(WORKSPACE_INDEX_DAC); + PARAM_CHECK(workSpace != NULL, return PARAM_WORKSPACE_NOT_INIT, "Invalid workSpace"); + ParamTrieNode *node = GetTrieRoot(workSpace); + if ((node == NULL) || (CompareParamTrieNode(node, auditData->name, strlen(auditData->name)) != 0)) { + node = FindTrieNode(workSpace, auditData->name, strlen(auditData->name), NULL); + if (node == NULL) { + node = AddTrieNode(workSpace, auditData->name, strlen(auditData->name)); + } + PARAM_CHECK(node != NULL, return PARAM_CODE_REACHED_MAX, "Failed to add node %s", auditData->name); + } + uint32_t offset = node->labelIndex; + if (node->labelIndex == 0) { // can not support update for label + offset = AddParamSecurityNode(workSpace, auditData); + PARAM_CHECK(offset > 0, return PARAM_CODE_REACHED_MAX, "Failed to add label"); + SaveIndex(&node->labelIndex, offset); + } else { + ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, node->labelIndex); + PARAM_CHECK(label != NULL, return -1, "Failed to get trie node"); +#ifdef PARAM_SUPPORT_SELINUX + if (auditData->selinuxIndex != 0) { + label->selinuxIndex = auditData->selinuxIndex; + } else +#endif + { +#ifdef STARTUP_INIT_TEST + label->mode = auditData->dacData.mode; + label->uid = auditData->dacData.uid; + label->gid = auditData->dacData.gid; + label->type = auditData->dacData.paramType & PARAM_TYPE_MASK; +#endif + PARAM_LOGV("Repeat to add label for name %s", auditData->name); + } + } + PARAM_LOGV("AddSecurityLabel label %d gid %d uid %d mode %o type:%d name: %s", offset, + auditData->dacData.gid, auditData->dacData.uid, auditData->dacData.mode, + auditData->dacData.paramType, auditData->name); + return 0; +} diff --git a/services/param/client/param_request.c b/services/param/client/param_request.c deleted file mode 100644 index ebed012fc40fa1c7e18b1a2239505afeec026d4c..0000000000000000000000000000000000000000 --- a/services/param/client/param_request.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2021 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 "param_request.h" - -#include -#include -#include - -#include "param_manager.h" -#include "uv.h" - -#define LABEL "Client" -#define BUFFER_SIZE 200 -#define ParamEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member)) - -static ParamWorkSpace g_paramWorkSpaceReadOnly = {ATOMIC_VAR_INIT(0), {}, {}, {}}; - -static void OnWrite(uv_write_t *req, int status) -{ - PARAM_LOGD("OnWrite status %d", status); -} - -static void OnReceiveAlloc(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf) -{ - // 这里需要按实际回复大小申请内存,不需要大内存 - buf->base = (char *)malloc(sizeof(ResponseMsg)); - PARAM_CHECK(buf->base != NULL, return, "OnReceiveAlloc malloc failed"); - buf->len = sizeof(ResponseMsg); - PARAM_LOGD("OnReceiveAlloc handle %p %zu", handle, suggestedSize); -} - -static void OnReceiveResponse(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) -{ - RequestNode *req = ParamEntry(handle, RequestNode, handle); - PARAM_LOGD("OnReceiveResponse %p", handle); - if (nread <= 0 || buf == NULL || handle == NULL || buf->base == NULL) { - if (buf != NULL && buf->base != NULL) { - free(buf->base); - } - if (handle != NULL) { - uv_close((uv_handle_t*)handle, NULL); - uv_stop(req->loop); - } - return; - } - ResponseMsg *response = (ResponseMsg *)(buf->base); - PARAM_CHECK(response != NULL, return, "The response is null"); - PARAM_LOGD("OnReceiveResponse %p cmd %d result: %d", handle, response->type, response->result); - switch (response->type) { - case SET_PARAM: - req->result = response->result; - break; - default: - PARAM_LOGE("not supported the command: %d", response->type); - break; - } - PARAM_LOGD("Close handle %p", handle); - free(buf->base); - uv_close((uv_handle_t*)handle, NULL); - uv_stop(req->loop); -} - -static void OnConnection(uv_connect_t *connect, int status) -{ - PARAM_CHECK(status >= 0, return, "Failed to conntect status %s", uv_strerror(status)); - RequestNode *request = ParamEntry(connect, RequestNode, connect); - PARAM_LOGD("Connect to server handle %p", &(request->handle)); - uv_buf_t buf = uv_buf_init((char*)&request->msg, request->msg.contentSize + sizeof(request->msg)); - int ret = uv_write2(&request->wr, (uv_stream_t*)&(request->handle), &buf, 1, (uv_stream_t*)&(request->handle), OnWrite); - PARAM_CHECK(ret >= 0, return, "Failed to uv_write2 porperty"); - - // read result - ret = uv_read_start((uv_stream_t*)&(request->handle), OnReceiveAlloc, OnReceiveResponse); - PARAM_CHECK(ret >= 0, return, "Failed to uv_read_start response"); -} - -static int StartRequest(int cmd, RequestNode *request) -{ - PARAM_CHECK(request != NULL, return -1, "Invalid request"); - request->result = -1; - request->msg.type = cmd; - request->loop = uv_loop_new(); - PARAM_CHECK(request->loop != NULL, return -1, "StartRequest uv_loop_new failed"); - uv_pipe_init(request->loop, &request->handle, 1); - uv_pipe_connect(&request->connect, &request->handle, PIPE_NAME, OnConnection); - uv_run(request->loop, UV_RUN_DEFAULT); - uv_loop_delete(request->loop); - int result = request->result; - free(request); - return result; -} - -int SystemSetParameter(const char *name, const char *value) -{ - PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid param"); - int ret = CheckParamName(name, 0); - PARAM_CHECK(ret == 0, return ret, "Illegal param name"); - - PARAM_LOGD("StartRequest %s", name); - u_int32_t msgSize = sizeof(RequestMsg) + strlen(name) + strlen(value) + 2; - RequestNode *request = (RequestNode *)malloc(sizeof(RequestNode) + msgSize); - PARAM_CHECK(request != NULL, return -1, "Failed to malloc for connect"); - - memset_s(request, sizeof(RequestNode), 0, sizeof(RequestNode)); - // 带字符串结束符 - int contentSize = BuildParamContent(request->msg.content, msgSize - sizeof(RequestMsg), name, value); - PARAM_CHECK(contentSize > 0, free(request); return -1, "Failed to copy porperty"); - request->msg.contentSize = contentSize; - return StartRequest(SET_PARAM, request); -} - -int SystemGetParameter(const char *name, char *value, unsigned int *len) -{ - PARAM_CHECK(name != NULL && len != NULL, return -1, "The name or value is null"); - InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL); - - ParamHandle handle = 0; - int ret = ReadParamWithCheck(&g_paramWorkSpaceReadOnly, name, &handle); - PARAM_CHECK(ret == 0, return ret, "Can not get param for %s", name); - return ReadParamValue(&g_paramWorkSpaceReadOnly, handle, value, len); -} - -int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len) -{ - PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null"); - InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL); - return ReadParamName(&g_paramWorkSpaceReadOnly, handle, name, len); -} - -int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len) -{ - PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null"); - InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL); - return ReadParamValue(&g_paramWorkSpaceReadOnly, handle, value, len); -} - -int SystemTraversalParameter(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie) -{ - PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null"); - InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL); - return TraversalParam(&g_paramWorkSpaceReadOnly, traversalParameter, cookie); -} - -const char *SystemDetectParamChange(ParamCache *cache, - ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2]) -{ - PARAM_CHECK(cache != NULL && evaluate != NULL && parameters != NULL, return NULL, "The param is null"); - return DetectParamChange(&g_paramWorkSpaceReadOnly, cache, evaluate, count, parameters); -} diff --git a/services/param/include/param_atomic.h b/services/param/include/param_atomic.h new file mode 100644 index 0000000000000000000000000000000000000000..ecd5ea3278b3c3de4c81b6059dc75c369fd5036e --- /dev/null +++ b/services/param/include/param_atomic.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 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_PARAM_ATOMIC_H +#define BASE_STARTUP_PARAM_ATOMIC_H +#include +#include +#include +#include +#include + +#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__)) +#include +#include +#endif +#if defined FUTEX_WAIT || defined FUTEX_WAKE +#include +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef __LITEOS_M__ +#define ATOMIC_UINT32 uint32_t +#define ATOMIC_LLONG long long +#define ATOMIC_INIT(commitId, value) *(commitId) = (value) +#define ATOMIC_LOAD_EXPLICIT(commitId, order) *(commitId) +#define ATOMIC_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value) +#define ATOMIC_UINT64_INIT(commitId, value) *(commitId) = (value) +#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) *(commitId) +#define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) *(commitId) = (value) +#define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) *(commitId) |= (value) +#define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) *(commitId) += (value) + +#define futex_wake(ftx, count) (void)(ftx) +#define futex_wait(ftx, value) (void)(ftx) +#define futex_wake_private(ftx, count) (void)(ftx) +#define futex_wait_private(ftx, value) (void)(ftx) +#else + +// support futex +#ifndef __NR_futex +#define PARAM_NR_FUTEX 202 /* syscall number */ +#else +#define PARAM_NR_FUTEX __NR_futex +#endif + +#if !(defined FUTEX_WAIT || defined FUTEX_WAKE) +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) +#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) + +#define PARAM_FUTEX(ftx, op, value, timeout, bitset) \ + do { \ + struct timespec d_timeout = { 0, 1000 * 1000 * (timeout) }; \ + syscall(PARAM_NR_FUTEX, ftx, op, value, &d_timeout, NULL, bitset); \ + } while (0) + +#define futex_wake(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE, count, 0, 0) +#define futex_wait(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT, value, 100, 0) +#define futex_wake_private(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE_PRIVATE, count, 0, 0) +#define futex_wait_private(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT_PRIVATE, value, 100, 0) +#endif + +#if (defined(PARAM_SUPPORT_STDATOMIC) || defined(__LITEOS_A__)) +#define MEMORY_ORDER_RELAXED memory_order_relaxed +#define MEMORY_ORDER_CONSUME memory_order_consume +#define MEMORY_ORDER_ACQUIRE memory_order_acquire +#define MEMORY_ORDER_RELEASE memory_order_release + +#define ATOMIC_UINT32 atomic_uint +#define ATOMIC_LLONG atomic_llong +#define ATOMIC_INIT(commitId, value) atomic_init((commitId), (value)) +#define ATOMIC_UINT64_INIT(commitId, value) atomic_init((commitId), (value)) +#define ATOMIC_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), (order)) +#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) atomic_load_explicit((commitId), order) +#define ATOMIC_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order)) +#define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) atomic_store_explicit((commitId), (value), (order)) +#define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) atomic_fetch_or_explicit((commitId), (value), (order)) +#define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) atomic_fetch_add_explicit((commitId), (value), (order)) + +#else + +#define MEMORY_ORDER_RELAXED 0 +#define MEMORY_ORDER_CONSUME 1 +#define MEMORY_ORDER_ACQUIRE 2 +#define MEMORY_ORDER_RELEASE 3 + +#define ATOMIC_UINT32 uint32_t +#define ATOMIC_LLONG int64_t + +static inline void param_atomic_store(ATOMIC_UINT32 *ptr, uint32_t value, int order) +{ + __sync_lock_test_and_set(ptr, value); + if (order == MEMORY_ORDER_RELEASE) { + __sync_synchronize(); + } +} + +static inline void param_atomic_uint64_store(ATOMIC_LLONG *ptr, int64_t value, int order) +{ + __sync_lock_test_and_set(ptr, value); + if (order == MEMORY_ORDER_RELEASE) { + __sync_synchronize(); + } +} + +static inline void param_atomic_init(ATOMIC_UINT32 *ptr, uint32_t value) +{ + *ptr = 0; + __sync_fetch_and_add(ptr, value, 0); +} + +static inline void param_atomic_uint64_init(ATOMIC_LLONG *ptr, int64_t value) +{ + *ptr = 0; + __sync_fetch_and_add(ptr, value, 0); +} + +static inline ATOMIC_UINT32 param_atomic_load(ATOMIC_UINT32 *ptr, int order) +{ + return *((volatile ATOMIC_UINT32 *)ptr); +} + +static inline ATOMIC_LLONG param_atomic_uint64_load(ATOMIC_LLONG *ptr, int order) +{ + return *((volatile ATOMIC_LLONG *)ptr); +} + +#define ATOMIC_INIT(commitId, value) param_atomic_init((commitId), (value)) +#define ATOMIC_UINT64_INIT(commitId, value) param_atomic_uint64_init((commitId), (value)) +#define ATOMIC_LOAD_EXPLICIT(commitId, order) param_atomic_load((commitId), order) +#define ATOMIC_UINT64_LOAD_EXPLICIT(commitId, order) param_atomic_uint64_load((commitId), order) +#define ATOMIC_STORE_EXPLICIT(commitId, value, order) param_atomic_store((commitId), (value), (order)) +#define ATOMIC_UINT64_STORE_EXPLICIT(commitId, value, order) param_atomic_uint64_store((commitId), (value), (order)) +#define ATOMIC_SYNC_OR_AND_FETCH(commitId, value, order) __sync_or_and_fetch((commitId), (value)) +#define ATOMIC_SYNC_ADD_AND_FETCH(commitId, value, order) __sync_add_and_fetch((commitId), (value)) +#endif +#endif // __LITEOS_M__ +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_PARAM_ATOMIC_H \ No newline at end of file diff --git a/services/param/include/param_common.h b/services/param/include/param_common.h new file mode 100644 index 0000000000000000000000000000000000000000..350f5d9e62bfaf42289afcb9624a63fddb4606e7 --- /dev/null +++ b/services/param/include/param_common.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 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_PARAM_COMMON_H +#define BASE_STARTUP_PARAM_COMMON_H +#include +#include +#include +#ifndef __LITEOS_M__ +#include +#endif +#include "param_atomic.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +// support mutex +#ifndef __LITEOS_M__ +typedef struct { + pthread_rwlock_t rwlock; +} ParamRWMutex; + +typedef struct { + pthread_mutex_t mutex; +} ParamMutex; +#else +typedef struct { + uint32_t mutex; +} ParamRWMutex; + +typedef struct { + uint32_t mutex; +} ParamMutex; +#endif + +typedef struct { + int shmid; +} MemHandle; + +typedef struct { + uint32_t left; + uint32_t right; + uint32_t child; + uint32_t labelIndex; + uint32_t dataIndex; + uint16_t selinuxLabel; + uint16_t length; + char key[0]; +} ParamTrieNode; + +#define PARAM_FLAGS_MODIFY 0x80000000 +#define PARAM_FLAGS_TRIGGED 0x40000000 +#define PARAM_FLAGS_WAITED 0x20000000 +#define PARAM_FLAGS_PERSIST 0x10000000 +#define PARAM_FLAGS_COMMITID 0x0000ffff + +#define PARAM_TYPE_MASK 0x0f +#define PARAM_TYPE_STRING 0x00 +#define PARAM_TYPE_INT 0x01 +#define PARAM_TYPE_BOOL 0x02 + +typedef struct { + ATOMIC_UINT32 commitId; + uint8_t type; + uint8_t keyLength; + uint16_t valueLength; + char data[0]; +} ParamNode; + +typedef struct { + uid_t uid; + gid_t gid; + uint32_t selinuxIndex; + uint16_t mode; + uint8_t type; + uint8_t length; + uint32_t memberNum; + uid_t members[0]; +} ParamSecurityNode; + +typedef struct { + ATOMIC_LLONG commitId; + ATOMIC_LLONG commitPersistId; + uint32_t trieNodeCount; + uint32_t paramNodeCount; + uint32_t securityNodeCount; + uint32_t currOffset; + uint32_t spaceSizeOffset; + uint32_t firstNode; + uint32_t dataSize; + char data[0]; +} ParamTrieHeader; + +typedef struct WorkSpace_ { + unsigned int flags; + MemHandle memHandle; + ParamTrieHeader *area; + ATOMIC_UINT32 rwSpaceLock; + uint32_t spaceSize; + uint32_t spaceIndex; + ParamRWMutex rwlock; + char fileName[0]; +} WorkSpace; + +typedef struct { + uint8_t updaterMode; + void (*logFunc)(int logLevel, uint32_t domain, const char *tag, const char *fmt, va_list vargs); + int (*setfilecon)(const char *name, const char *content); + int (*getServiceGroupIdByPid)(pid_t pid, gid_t *gids, uint32_t gidSize); +} PARAM_WORKSPACE_OPS; + +typedef struct CachedParameter_ { + struct WorkSpace_ *workspace; + const char *(*cachedParameterCheck)(struct CachedParameter_ *param, int *changed); + long long spaceCommitId; + uint32_t dataCommitId; + uint32_t dataIndex; + uint32_t bufferLen; + uint32_t nameLen; + char *paramValue; + char data[0]; +} CachedParameter; + +typedef void *CachedHandle; + +typedef struct _SpaceSize { + uint32_t maxLabelIndex; + uint32_t spaceSize[0]; +} WorkSpaceSize; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_PARAM_COMMON_H \ No newline at end of file diff --git a/services/include/param/sys_param.h b/services/param/include/param_init.h similarity index 50% rename from services/include/param/sys_param.h rename to services/param/include/param_init.h index f5b030bdbcfc13c62a8b1fa4c99846dc914ebee5..eb7c971a60d4b8c44019caaf259ed4f1ceb61b29 100644 --- a/services/include/param/sys_param.h +++ b/services/param/include/param_init.h @@ -1,91 +1,77 @@ -/* - * Copyright (c) 2020 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_SYS_PARAM_H -#define BASE_STARTUP_SYS_PARAM_H -#include -#include -#include - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -#define PARAM_VALUE_LEN_MAX 96 -#define PARAM_NAME_LEN_MAX 96 -typedef u_int32_t ParamHandle; - -typedef struct { - u_int32_t serial; - ParamHandle handle; - char value[PARAM_VALUE_LEN_MAX]; -} ParamCacheNode; - -typedef const char *(*ParamEvaluatePtr)(u_int32_t cacheCount, ParamCacheNode *node); - -typedef struct { - pthread_mutex_t lock; - u_int32_t serial; - u_int32_t cacheCount; - ParamEvaluatePtr evaluate; - ParamCacheNode *cacheNode; -} ParamCache; - -/** - * 对外接口 - * 设置参数,主要用于其他进程使用,通过管道修改参数。 - * - */ -int SystemSetParameter(const char *name, const char *value); - -/** - * 对外接口 - * 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。 - * 如果 value == null,获取value的长度 - * 否则value的大小认为是len - * - */ -int SystemGetParameter(const char *name, char *value, unsigned int *len); - -/** - * 外部接口 - * 遍历参数。 - * - */ -int SystemTraversalParameter(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie); - -/** - * 外部接口 - * 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。 - * 如果 value == null,获取value的长度 - * 否则value的大小认为是len - * - */ -int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len); - -/** - * 外部接口 - * 获取参数值。 - * - */ -int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len); -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif +/* + * Copyright (c) 2023 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_PARAM_INIT_H +#define BASE_STARTUP_PARAM_INIT_H +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef BASE_STARTUP_INIT_PARAM_H +typedef uint32_t ParamHandle; +#endif + +/** + * 外部接口 + * 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。 + * 如果 value == null,获取value的长度 + * 否则value的大小认为是len + * + */ +int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len); + +/** + * 外部接口 + * 遍历参数。 + * + */ +int SystemTraversalParameter(const char *prefix, + void (*traversalParameter)(ParamHandle handle, void *cookie), void *cookie); + +long long GetSystemCommitId(void); + +/** + * 外部接口 + * 获取参数值。 + * + */ +int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len); + +/** + * 对外接口 + * 根据handle获取对应数据的修改标识。 + * commitId 获取计数变化 + * + */ +int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId); + +/** + * 对外接口 + * 查询参数,主要用于其他进程使用,找到对应属性的handle。 + * + */ +int SystemFindParameter(const char *name, ParamHandle *handle); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif #endif \ No newline at end of file diff --git a/services/param/include/param_manager.h b/services/param/include/param_manager.h index dc969651fa10cb078bbd1e773c5b287b16d695df..e2aeeb931a2d09417c70f2e4c307e0d29556b979 100644 --- a/services/param/include/param_manager.h +++ b/services/param/include/param_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -15,143 +15,161 @@ #ifndef BASE_STARTUP_PARAM_MANAGER_H #define BASE_STARTUP_PARAM_MANAGER_H +#include #include #include +#include -#include "init_log.h" -#include "sys_param.h" +#include "init_param.h" +#include "list.h" + +#include "param_osadp.h" +#include "param_persist.h" +#include "param_security.h" #include "param_trie.h" -#include "securec.h" +#include "param_utils.h" + #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif -typedef enum { - PARAM_CODE_INVALID_PARAM = 100, - PARAM_CODE_INVALID_NAME, - PARAM_CODE_INVALID_VALUE, - PARAM_CODE_REACHED_MAX, - PARAM_CODE_PERMISSION_DENIED, - PARAM_CODE_READ_ONLY_PROPERTY, - PARAM_CODE_NOT_SUPPORT, - PARAM_CODE_ERROR_MAP_FILE, - PARAM_CODE_NOT_FOUND_PROP, - PARAM_CODE_NOT_INIT -} PARAM_CODE; - -#define IS_READY_ONLY(name) strncmp((name), "ro.", strlen("ro.")) == 0 -#define LABEL_STRING_LEN 128 - -#ifdef STARTUP_LOCAL -#define PIPE_NAME "/tmp/paramservice" -#define PARAM_STORAGE_PATH "/media/sf_ubuntu/test/__parameters__/param_storage" -#define PARAM_PERSIST_PATH "/media/sf_ubuntu/test/param/persist_parameters" -#define PARAM_INFO_PATH "/media/sf_ubuntu/test/__parameters__/param_info" +#define PARAM_MAX_SELINUX_LABEL 256 +#ifdef PARAM_SUPPORT_SELINUX +#define PARAM_DEF_SELINUX_LABEL 64 #else -#define PIPE_NAME "/dev/unix/socket/paramservice" -#define PARAM_STORAGE_PATH "/dev/__parameters__/param_storage" -#define PARAM_PERSIST_PATH "/data/param/persist_parameters" -#define PARAM_INFO_PATH "/dev/__parameters__/param_info" +#define PARAM_DEF_SELINUX_LABEL 1 #endif -#define SUBSTR_INFO_NAME 0 -#define SUBSTR_INFO_LABEL 1 -#define SUBSTR_INFO_TYPE 2 -#define SUBSTR_INFO_MAX 4 +#define WORKSPACE_INDEX_DAC 0 +#define WORKSPACE_INDEX_BASE 1 +#define WORKSPACE_INDEX_SIZE WORKSPACE_INDEX_DAC -#define WORKSPACE_FLAGS_INIT 0x01 -#define WORKSPACE_FLAGS_LOADED 0x02 +#define WORKSPACE_NAME_DAC "param_sec_dac" +#define WORKSPACE_NAME_DEF_SELINUX "u:object_r:default_param:s0" +#ifndef PARAM_SUPPORT_SELINUX +#define WORKSPACE_NAME_NORMAL "param_storage" +#else +#define WORKSPACE_NAME_NORMAL WORKSPACE_NAME_DEF_SELINUX +#endif -#define PARAM_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__) -#define PARAM_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__) -#define PARAM_LOGD(fmt, ...) STARTUP_LOGD(LABEL, fmt, ##__VA_ARGS__) +#define PARAM_NEED_CHECK_IN_SERVICE 0x2 +#define PARAM_CTRL_SERVICE 0x1 +#ifndef OHOS_LITE +#define PERSIST_PARAM_FIXED_FLAGS "/data/service/el1/startup/persist_param_fixed" +#else +#define PERSIST_PARAM_FIXED_FLAGS "/storage/data/system/param/persist_param_fixed" +#endif -#define PARAM_CHECK(retCode, exper, ...) \ - if (!(retCode)) { \ - PARAM_LOGE(__VA_ARGS__); \ - exper; \ +#define PARAM_WORKSPACE_CHECK(space, exper, ...) \ + if (((*space).flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) { \ + PARAM_LOGE(__VA_ARGS__); \ + exper; \ } -#define futex(addr1, op, val, rel, addr2, val3) \ - syscall(SYS_futex, addr1, op, val, rel, addr2, val3) -#define futex_wait_always(addr1) \ - syscall(SYS_futex, addr1, FUTEX_WAIT, *(int*)(addr1), 0, 0, 0) -#define futex_wake_single(addr1) \ - syscall(SYS_futex, addr1, FUTEX_WAKE, 1, 0, 0, 0) - -typedef struct UserCred { - pid_t pid; - uid_t uid; - gid_t gid; -} UserCred; - typedef struct { - char label[LABEL_STRING_LEN]; - UserCred cred; -} ParamSecurityLabel; - -typedef struct ParamAuditData { - const UserCred *cr; - const char *name; -} ParamAuditData; + uint32_t flags; + ParamSecurityLabel securityLabel; + ParamSecurityOps paramSecurityOps[PARAM_SECURITY_MAX]; + PARAM_WORKSPACE_OPS ops; +#ifdef PARAM_SUPPORT_SELINUX + SelinuxSpace selinuxSpace; +#endif + int (*checkParamPermission)(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); + uint32_t maxSpaceCount; + uint32_t maxLabelIndex; + WorkSpace **workSpace; +} ParamWorkSpace; typedef struct { - atomic_uint_least32_t flags; - WorkSpace paramLabelSpace; - WorkSpace paramSpace; - ParamSecurityLabel label; -} ParamWorkSpace; + ParamTaskPtr serverTask; + ParamTaskPtr timer; + ParamTaskPtr watcherTask; +} ParamService; typedef struct { - atomic_uint_least32_t flags; - WorkSpace persistWorkSpace; + uint32_t flags; + long long commitId; + ParamTaskPtr saveTimer; + struct timespec lastSaveTimer; + PersistParamOps persistParamOps; } ParamPersistWorkSpace; typedef struct { - char value[128]; -} SubStringInfo; - -int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead, const char *context); -void CloseParamWorkSpace(ParamWorkSpace *workSpace); - -int ReadParamWithCheck(ParamWorkSpace *workSpace, const char *name, ParamHandle *handle); -int ReadParamValue(ParamWorkSpace *workSpace, ParamHandle handle, char *value, u_int32_t *len); -int ReadParamName(ParamWorkSpace *workSpace, ParamHandle handle, char *name, u_int32_t len); -u_int32_t ReadParamSerial(ParamWorkSpace *workSpace, ParamHandle handle); - -int AddParam(WorkSpace *workSpace, const char *name, const char *value); -int WriteParam(WorkSpace *workSpace, const char *name, const char *value); -int WriteParamWithCheck(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const char *name, const char *value); -int WriteParamInfo(ParamWorkSpace *workSpace, SubStringInfo *info, int subStrNumber); - -int CheckParamValue(WorkSpace *workSpace, const TrieDataNode *node, const char *name, const char *value); -int CheckParamName(const char *name, int paramInfo); -int CanReadParam(ParamWorkSpace *workSpace, u_int32_t labelIndex, const char *name); -int CanWriteParam(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const TrieDataNode *node, const char *name, const char *value); - -int CheckMacPerms(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const char *name, u_int32_t labelIndex); -int CheckControlParamPerms(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const char *name, const char *value); - -int GetSubStringInfo(const char *buff, u_int32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber); -int BuildParamContent(char *content, u_int32_t contentSize, const char *name, const char *value); -ParamWorkSpace *GetParamWorkSpace(); - -typedef void (*TraversalParamPtr)(ParamHandle handle, void* context); + char realKey[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 1]; + char cmdName[32]; + uint32_t valueOffset; + uint8_t ctrlParam; +} ServiceCtrlInfo; + +typedef void (*TraversalParamPtr)(ParamHandle handle, void *context); typedef struct { TraversalParamPtr traversalParamPtr; void *context; + char *prefix; } ParamTraversalContext; -int TraversalParam(ParamWorkSpace *workSpace, TraversalParamPtr walkFunc, void *cookie); - -const char *DetectParamChange(ParamWorkSpace *workSpace, ParamCache *cache, - ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2]); +typedef struct { + uint8_t type; + uint8_t mode; + const char *name; + const char *value; +} ParamInfos; + +#define PARAM_HANDLE(workSpace, index) (ParamHandle)((workSpace)->spaceIndex << 24 | (index)) +#define PARAM_GET_HANDLE_INFO(handle, label, index) \ + do { \ + (label) = (((handle) >> 24) & 0x000000ff); \ + (index) = (handle) & 0x00ffffff; \ + if (((index) & 0x03) != 0) { \ + (index) = 0; \ + } \ + } while (0) + +INIT_LOCAL_API int AddWorkSpace(const char *name, uint32_t labelIndex, int onlyRead, uint32_t spacesize); +INIT_LOCAL_API int OpenWorkSpace(uint32_t index, int readOnly); + +INIT_LOCAL_API WorkSpace *GetNextWorkSpace(WorkSpace *curr); +INIT_LOCAL_API WorkSpace *GetWorkSpace(uint32_t labelIndex); +INIT_LOCAL_API WorkSpace *GetWorkSpaceByName(const char *name); + +INIT_LOCAL_API int CheckParamValue(const ParamTrieNode *node, const char *name, const char *value, uint8_t paramType); +INIT_LOCAL_API int CheckParamName(const char *name, int paramInfo); +INIT_LOCAL_API uint8_t GetParamValueType(const char *name); + +INIT_LOCAL_API ParamNode *SystemCheckMatchParamWait(const char *name, const char *value); +INIT_LOCAL_API int WriteParam(const char *name, const char *value, uint32_t *dataIndex, int onlyAdd); +INIT_LOCAL_API int AddSecurityLabel(const ParamAuditData *auditData); +INIT_LOCAL_API ParamSecurityLabel *GetParamSecurityLabel(void); + +INIT_LOCAL_API void LoadParamFromBuild(void); +INIT_LOCAL_API int LoadParamFromCmdLine(void); +INIT_LOCAL_API void LoadParamAreaSize(void); +INIT_LOCAL_API int InitPersistParamWorkSpace(void); +INIT_LOCAL_API void ClosePersistParamWorkSpace(void); +INIT_LOCAL_API int WritePersistParam(const char *name, const char *value); + +INIT_LOCAL_API int CheckParameterSet(const char *name, const char *value, + const ParamSecurityLabel *srcLabel, int *ctrlService); + +INIT_LOCAL_API int CheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); + +INIT_LOCAL_API int SysCheckParamExist(const char *name); +INIT_LOCAL_API int GenerateKeyHasCode(const char *buff, size_t len); + +INIT_INNER_API ParamWorkSpace *GetParamWorkSpace(void); +INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData); +INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo); + +INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops); +INIT_LOCAL_API void CloseParamWorkSpace(void); +INIT_LOCAL_API int CheckIfUidInGroup(const gid_t groupId, const char *groupCheckName); + +#ifdef STARTUP_INIT_TEST +ParamService *GetParamService(); +#endif #ifdef __cplusplus #if __cplusplus } diff --git a/services/param/include/param_osadp.h b/services/param/include/param_osadp.h new file mode 100755 index 0000000000000000000000000000000000000000..190ee44503b1c79b40ad7a110f5ba7a759f9e6c9 --- /dev/null +++ b/services/param/include/param_osadp.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2021 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_PARAM_OS_ADAPTER_H +#define BASE_STARTUP_PARAM_OS_ADAPTER_H +#include +#include +#include +#include +#include +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) +#include +#include "loop_event.h" +#else +#include +#endif + +#ifndef __LITEOS_M__ +#include +#endif +#include "param_utils.h" +#include "param_common.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifndef STATIC_INLINE +#ifdef STARTUP_INIT_TEST +#define STATIC_INLINE +#else +#define STATIC_INLINE static inline +#endif +#endif + +#define PARAM_WORKSPACE_INVALID ((uint32_t)-1) +#define PARAM_WORKSPACE_MIN (1024) +/* + length for parameter = node size + data size + xxxx.xxxx.xxxx.xxxx + node size: + 24 * (count(.) + 1) + strlen(xxxx.xxxx.xxxx.xxxx) + data size + strlen(xxxx.xxxx.xxxx.xxxx) + 96 + + dac size + 24 * (count(.) + 1) + sizeof(ParamSecurityNode) +*/ +#define DAC_DEFAULT_GROUP 0 +#define DAC_DEFAULT_USER 0 + +#ifdef STARTUP_INIT_TEST +#define DAC_DEFAULT_MODE 0777 +#define PARAM_WORKSPACE_DEF (1024 * 80) +#define PARAM_WORKSPACE_MAX (1024 * 100) +#define PARAM_WORKSPACE_SMALL PARAM_WORKSPACE_DEF +#else + +#ifdef __LITEOS_M__ +#define DAC_DEFAULT_MODE 0777 +#ifndef PARAM_WORKSPACE_MAX +#define PARAM_WORKSPACE_MAX (1024 * 5) +#endif +#define PARAM_WORKSPACE_SMALL PARAM_WORKSPACE_MAX +#define PARAM_WORKSPACE_DEF PARAM_WORKSPACE_MAX +#else // __LITEOS_M__ + +#ifdef __LITEOS_A__ +#define DAC_DEFAULT_MODE 0777 +#define PARAM_WORKSPACE_MAX (1024 * 10) +#define PARAM_WORKSPACE_SMALL PARAM_WORKSPACE_MAX +#define PARAM_WORKSPACE_DEF PARAM_WORKSPACE_MAX +#else // __LITEOS_A__ +#define DAC_DEFAULT_MODE 0774 +#ifdef PARAM_TEST_PERFORMANCE +#define PARAM_WORKSPACE_MAX (1024 * 1024 * 10) +#else +#define PARAM_WORKSPACE_MAX (80 * 1024) +#endif +#define PARAM_WORKSPACE_SMALL (1024 * 10) +#define PARAM_WORKSPACE_DEF (1024 * 30) +#define PARAM_WORKSPACE_DAC (1024 * 1024 * 2) +#endif // __LITEOS_A__ +#endif // __LITEOS_M__ +#endif // STARTUP_INIT_TEST + +#ifndef PARAM_WORKSPACE_DAC +#define PARAM_WORKSPACE_DAC PARAM_WORKSPACE_SMALL +#endif + +// support timer +#if defined __LITEOS_A__ || defined __LITEOS_M__ +struct ParamTimer_; +typedef void (*ProcessTimer)(const struct ParamTimer_ *taskHandle, void *context); +typedef struct ParamTimer_ { + timer_t timerId; + uint64_t repeat; + ProcessTimer timeProcessor; + void *context; +} ParamTimer; + +typedef ParamTimer *ParamTaskPtr; +#else +typedef LoopBase *ParamTaskPtr; +typedef void (*ProcessTimer)(const ParamTaskPtr taskHandle, void *context); +#endif + +int ParamTimerCreate(ParamTaskPtr *timer, ProcessTimer process, void *context); +int ParamTimerStart(const ParamTaskPtr timer, uint64_t timeout, uint64_t repeat); +void ParamTimerClose(ParamTaskPtr timer); + +INIT_LOCAL_API void paramMutexEnvInit(void); +INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock); +INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock); +INIT_LOCAL_API int ParamRWMutexRDLock(ParamRWMutex *lock); +INIT_LOCAL_API int ParamRWMutexUnlock(ParamRWMutex *lock); +INIT_LOCAL_API int ParamRWMutexDelete(ParamRWMutex *lock); + +INIT_LOCAL_API int ParamMutexCreate(ParamMutex *mutex); +INIT_LOCAL_API int ParamMutexPend(ParamMutex *mutex); +INIT_LOCAL_API int ParamMutexPost(ParamMutex *mutex); +INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex); + +#ifdef WORKSPACE_AREA_NEED_MUTEX +#define PARAMSPACE_AREA_INIT_LOCK(workspace) ParamRWMutexCreate(&workspace->rwlock) +#define PARAMSPACE_AREA_RW_LOCK(workspace) ParamRWMutexWRLock(&workspace->rwlock) +#define PARAMSPACE_AREA_RD_LOCK(workspace) ParamRWMutexRDLock(&workspace->rwlock) +#define PARAMSPACE_AREA_RW_UNLOCK(workspace) ParamRWMutexUnlock(&workspace->rwlock) +#else +#define PARAMSPACE_AREA_INIT_LOCK(rwlock) (void)(rwlock) +#define PARAMSPACE_AREA_RW_LOCK(rwlock) (void)(rwlock) +#define PARAMSPACE_AREA_RD_LOCK(rwlock) (void)(rwlock) +#define PARAMSPACE_AREA_RW_UNLOCK(rwlock) (void)(rwlock) +#endif + +INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly); +INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_PARAM_OS_ADAPTER_H \ No newline at end of file diff --git a/services/include/init_cmds.h b/services/param/include/param_persist.h similarity index 33% rename from services/include/init_cmds.h rename to services/param/include/param_persist.h index 232f24a3d3a515cca0eb3217a1b7bcfffada763e..735bc6024a2b3a7e655a049b12c41ea615724892 100644 --- a/services/include/init_cmds.h +++ b/services/param/include/param_persist.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * 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 @@ -13,8 +13,14 @@ * limitations under the License. */ -#ifndef BASE_STARTUP_INITLITE_CMDS_H -#define BASE_STARTUP_INITLITE_CMDS_H +#ifndef BASE_STARTUP_PARAM_PERSIST_H +#define BASE_STARTUP_PARAM_PERSIST_H +#include +#include + +#include "param_osadp.h" +#define PUBLIC_PERSIST_FILE 0 +#define PRIVATE_PERSIST_FILE 1 #ifdef __cplusplus #if __cplusplus @@ -22,47 +28,42 @@ extern "C" { #endif #endif -#define MAX_CMD_NAME_LEN 32 -#define MAX_CMD_CONTENT_LEN 256 -#define MAX_CMD_CNT_IN_ONE_JOB 200 -#define MAX_COPY_BUF_SIZE 256 -#define DEFAULT_COPY_ARGS_CNT 2 +typedef int (*PersistParamGetPtr)(const char *name, const char *value, void *context); +typedef void *PERSIST_SAVE_HANDLE; +typedef struct { + void *context; + PersistParamGetPtr persistParamGet; +} PersistAdpContext; -#ifndef OHOS_LITE -// Limit max length of parameter value to 96 -#define MAX_PARAM_VALUE_LEN 96 -// Limit max length of parameter name to 96 -#define MAX_PARAM_NAME_LEN 96 +typedef struct { +#if defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__) + int (*load)(void); + int (*batchSaveBegin)(PERSIST_SAVE_HANDLE *handle); + int (*batchSave)(PERSIST_SAVE_HANDLE handle, const char *name, const char *value); + void (*batchSaveEnd)(PERSIST_SAVE_HANDLE handle); #else -// For lite ohos, do not support parameter operation -#define MAX_PARAM_VALUE_LEN 0 -#define MAX_PARAM_NAME_LEN 0 + int (*load)(int fileType); + int (*batchSaveBegin)(PERSIST_SAVE_HANDLE *handle); + int (*batchSave)(PERSIST_SAVE_HANDLE handle[], const char *name, const char *value); + void (*batchSaveEnd)(PERSIST_SAVE_HANDLE handle[]); #endif + int (*save)(const char *name, const char *value); +} PersistParamOps; -// one cmd line -typedef struct { - char name[MAX_CMD_NAME_LEN + 1]; - char cmdContent[MAX_CMD_CONTENT_LEN + 1]; -} CmdLine; - -struct CmdArgs { - int argc; - char **argv; -}; +int RegisterPersistParamOps(PersistParamOps *ops); -int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen); -struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount); -void FreeCmd(struct CmdArgs **cmd); +#ifndef STARTUP_INIT_TEST +#define PARAM_MUST_SAVE_PARAM_DIFF 1 // 1s +#else +#define PARAM_MUST_SAVE_PARAM_DIFF 1 +void TimerCallbackForSave(ParamTaskPtr timer, void *context); +#endif -void ParseCmdLine(const char* cmdStr, CmdLine* resCmd); -void DoCmd(const CmdLine* curCmd); +void CheckAndSavePersistParam(void); -void DoCmdByName(const char *name, const char *cmdContent); -const char *GetMatchCmd(const char *cmdStr); #ifdef __cplusplus #if __cplusplus } #endif #endif - -#endif // BASE_STARTUP_INITLITE_CMDS_H +#endif \ No newline at end of file diff --git a/services/param/include/param_security.h b/services/param/include/param_security.h new file mode 100644 index 0000000000000000000000000000000000000000..17fcd72ce93f6d19b99b11ccdb3dca22c920d06f --- /dev/null +++ b/services/param/include/param_security.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2021 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_PARAM_SECURITY_H +#define BASE_STARTUP_PARAM_SECURITY_H +#include +#ifndef __LINUX__ +#include +#endif +#include +#ifdef PARAM_SUPPORT_SELINUX +#include "selinux_parameter.h" +#endif + +#include "beget_ext.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define DAC_GROUP_START 3 +#define DAC_OTHER_START 6 +#define DAC_READ 0x0100 // 4 +#define DAC_WRITE 0x0080 // 2 +#define DAC_WATCH 0x0040 // 1 +#define DAC_ALL_PERMISSION 0777 + +#define LABEL_ALL_PERMISSION 0x04 +#define LABEL_CHECK_IN_ALL_PROCESS 0x02 +#define LABEL_INIT_FOR_INIT 0x01 + +#define SELINUX_CONTENT_LEN 64 +#define SYS_UID_INDEX 1000 + +#define DAC_RESULT_PERMISSION 0 + +#define USER_BUFFER_LEN 64 +#define GROUP_FORMAT "const.%u_%u" + +#define INVALID_SELINUX_INDEX ((uint32_t)-1) + +typedef struct UserCred { + pid_t pid; + uid_t uid; + gid_t gid; +} UserCred; + +typedef enum { + PARAM_SECURITY_DAC = 0, +#ifdef PARAM_SUPPORT_SELINUX + PARAM_SECURITY_SELINUX, +#endif + PARAM_SECURITY_MAX +} ParamSecurityType; + +typedef struct { + int32_t sockFd; + UserCred cred; + uint32_t flags[PARAM_SECURITY_MAX]; +} ParamSecurityLabel; + +typedef struct { + pid_t pid; + uid_t uid; + gid_t gid; + uint16_t mode; + uint8_t paramType; +} ParamDacData; + +typedef struct { + ParamDacData dacData; + const char *name; +#ifdef PARAM_SUPPORT_SELINUX + char label[SELINUX_CONTENT_LEN]; + uint32_t selinuxIndex; +#endif + uint32_t memberNum; + uid_t members[1]; +} ParamAuditData; + +struct WorkSpace_; +typedef struct ParamLabelIndex_ { + uint32_t selinuxLabelIndex; + uint32_t dacLabelIndex; + struct WorkSpace_ *workspace; +} ParamLabelIndex; + +typedef struct { + char name[10]; + int (*securityInitLabel)(ParamSecurityLabel *label, int isInit); + int (*securityGetLabel)(const char *path); + int (*securityCheckFilePermission)(const ParamSecurityLabel *label, const char *fileName, int flags); + int (*securityCheckParamPermission)(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); + int (*securityFreeLabel)(ParamSecurityLabel *srcLabel); +} ParamSecurityOps; + +typedef int (*RegisterSecurityOpsPtr)(ParamSecurityOps *ops, int isInit); +typedef struct SelinuxSpace_ { + void *selinuxHandle; +#ifdef PARAM_SUPPORT_SELINUX + void (*setSelinuxLogCallback)(void); + int (*setParamCheck)(const char *paraName, const char *destContext, const SrcInfo *info); + const char *(*getParamLabel)(const char *paraName); + int (*initParamSelinux)(int isInit); + int (*readParamCheck)(const char *paraName); + ParamContextsList *(*getParamList)(void); + void (*destroyParamList)(ParamContextsList **list); + int (*getParamLabelIndex)(const char *paraName); +#endif +} SelinuxSpace; + +#ifdef PARAM_SUPPORT_SELINUX +INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit); +#endif + +INIT_LOCAL_API ParamSecurityOps *GetParamSecurityOps(int type); +INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit); +INIT_LOCAL_API int RegisterSecurityOps(int onlyRead); + +#ifdef STARTUP_INIT_TEST +STATIC_INLINE int DacCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); +STATIC_INLINE int SelinuxCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_PARAM_SECURITY_H diff --git a/services/param/include/param_trie.h b/services/param/include/param_trie.h index 8c3e3f9848e10b76d58ac90c1f23f8561ab15385..03c6c760efe5a07aa17f85e78e44469f6a44814f 100644 --- a/services/param/include/param_trie.h +++ b/services/param/include/param_trie.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * Copyright (c) 2023 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 @@ -15,15 +15,14 @@ #ifndef BASE_STARTUP_PARAM_TRIE_H #define BASE_STARTUP_PARAM_TRIE_H -#include -#include #include -#include -#include -#include "init_log.h" -#include "sys_param.h" -#include "securec.h" +#include "init_hashmap.h" +#include "init_param.h" +#include "list.h" +#include "param_common.h" +#include "param_osadp.h" +#include "param_security.h" #ifdef __cplusplus #if __cplusplus @@ -31,108 +30,49 @@ extern "C" { #endif #endif -#define PARAM_WORKSPACE_MAX 64*1024 -#define TRIE_SERIAL_DIRTY_OFFSET 1 -#define TRIE_SERIAL_KEY_LEN_OFFSET 24 -#define TRIE_SERIAL_DATA_LEN_OFFSET 16 +#define PARAM_TRIE_STACK_SIZE 25 -#define FILENAME_LEN_MAX 255 -#define TRIE_DATA_LEN_MAX 128 +INIT_LOCAL_API int InitWorkSpace(WorkSpace *workSpace, int onlyRead, uint32_t spaceSize); +INIT_LOCAL_API void CloseWorkSpace(WorkSpace *workSpace); -#define NODE_INDEX unsigned int +#define GetTrieNode(workSpace, offset) (ParamTrieNode *)(((offset) == 0 || (offset) > (workSpace)->area->dataSize) ? \ + NULL : (workSpace)->area->data + (offset)) -#define TRIE_NODE_HEADER \ - atomic_uint_least32_t serial; \ - NODE_INDEX left; \ - NODE_INDEX right; +#define GetTrieRoot(workSpace) \ + (ParamTrieNode *)(((workSpace)->area == NULL) ? NULL : (workSpace)->area->data + (workSpace)->area->firstNode) -#define DATA_ENTRY_KEY_LEN(entry) (entry)->dataLength >> TRIE_SERIAL_KEY_LEN_OFFSET -#define DATA_ENTRY_DATA_LEN(entry) (((entry)->dataLength >> TRIE_SERIAL_DATA_LEN_OFFSET) & 0x00FF) -#define DATA_ENTRY_DIRTY(serial) ((serial) & 1) +INIT_LOCAL_API void SaveIndex(uint32_t *index, uint32_t offset); -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 -#define __futex(ftx, op, value, timeout, bitset) \ - syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset) -#define futex_wake(ftx, count) __futex(ftx, FUTEX_WAKE, count, NULL, 0) -#define futex_wait(ftx, value, timeout) __futex(ftx, FUTEX_WAIT, value, timeout, 0) +INIT_LOCAL_API ParamTrieNode *AddTrieNode(WorkSpace *workSpace, const char *key, uint32_t keyLen); +INIT_LOCAL_API ParamTrieNode *FindTrieNode( + WorkSpace *workSpace, const char *key, uint32_t keyLen, uint32_t *matchLabel); -typedef struct { - TRIE_NODE_HEADER; - char key[0]; -} TrieNode; +typedef int (*TraversalTrieNodePtr)(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie); +INIT_LOCAL_API int TraversalTrieNode(const WorkSpace *workSpace, + const ParamTrieNode *subTrie, TraversalTrieNodePtr walkFunc, const void *cookie); -typedef struct { - TRIE_NODE_HEADER; - NODE_INDEX child; - NODE_INDEX labelIndex; - NODE_INDEX dataIndex; - char key[0]; -} TrieDataNode; +INIT_LOCAL_API uint32_t AddParamSecurityNode(WorkSpace *workSpace, const ParamAuditData *auditData); +INIT_LOCAL_API uint32_t AddParamNode(WorkSpace *workSpace, uint8_t type, + const char *key, uint32_t keyLen, const char *value, uint32_t valueLen, int mode); -typedef struct { - atomic_uint_least32_t serial; - atomic_uint_least32_t dataLength; - char data[0]; -} DataEntry; +INIT_LOCAL_API uint32_t GetParamMaxLen(uint8_t type); +INIT_LOCAL_API ParamNode *GetParamNode(uint32_t index, const char *name); +INIT_LOCAL_API int AddParamEntry(uint32_t index, uint8_t type, const char *name, const char *value); -typedef struct { - atomic_uint_least32_t serial; - u_int32_t currOffset; - u_int32_t firstNode; - u_int32_t dataSize; - u_int32_t reserved_[28]; - char data[0]; -} WorkArea; - -struct WorkSpace_; -typedef u_int32_t (*AllocTrieNodePtr)(struct WorkSpace_ *workSpace, const char *key, u_int32_t keyLen); -typedef int (*CompareTrieNodePtr)(TrieNode *node, const char *key2, u_int32_t key2Len); - -typedef struct WorkSpace_ { - char fileName[FILENAME_LEN_MAX + 1]; - WorkArea *area; - TrieNode *rootNode; - AllocTrieNodePtr allocTrieNode; - CompareTrieNodePtr compareTrieNode; -} WorkSpace; - -u_int32_t GetWorkSpaceSerial(WorkSpace *workSpace); -int CompareTrieNode(TrieNode *node, const char *key, u_int32_t keyLen); -u_int32_t AllocateTrieNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen); -int CompareTrieDataNode(TrieNode *node, const char *key, u_int32_t keyLen); -u_int32_t AllocateTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen); - -u_int32_t GetTrieNodeOffset(WorkSpace *workSpace, const TrieNode *current); -TrieNode *GetTrieNode(WorkSpace *workSpace, NODE_INDEX *index); -u_int32_t GetTrieKeyLen(TrieNode *current); -void SaveIndex(NODE_INDEX *index, u_int32_t offset); -TrieDataNode *AddTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen); -TrieDataNode *AddToSubTrie(WorkSpace *workSpace, TrieDataNode *dataNode, const char *key, u_int32_t keyLen); -TrieDataNode *FindSubTrie(WorkSpace *workSpace, TrieDataNode *dataNode, const char *key, u_int32_t keyLen); -TrieDataNode *FindTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen, int matchPrefix); - -TrieNode *AddTrieNode(WorkSpace *workSpace, TrieNode *root, const char *key, u_int32_t keyLen); -TrieNode *FindTrieNode(WorkSpace *workSpace, TrieNode *tree, const char *key, u_int32_t keyLen); - -int InitWorkSpace_(WorkSpace *workSpace, int mode, int prot, u_int32_t spaceSize, int readOnly); -int InitPersistWorkSpace(const char *fileName, WorkSpace *workSpace); -int InitWorkSpace(const char *fileName, WorkSpace *workSpace, int onlyRead); -void CloseWorkSpace(WorkSpace *workSpace); - -typedef int (*TraversalTrieNodePtr)(WorkSpace *workSpace, TrieNode *node, void *cookie); -int TraversalTrieNode(WorkSpace *workSpace, TrieNode *root, TraversalTrieNodePtr walkFunc, void *cookie); -int TraversalTrieDataNode(WorkSpace *workSpace, TrieDataNode *current, TraversalTrieNodePtr walkFunc, void *cookie); +#ifdef STARTUP_INIT_TEST +STATIC_INLINE ParamTrieNode *FindTrieNode_( + const WorkSpace *workSpace, const char *key, uint32_t keyLen, uint32_t *matchLabel); +#endif -u_int32_t AddData(WorkSpace *workSpace, const char *key, u_int32_t keyLen, const char *value, u_int32_t valueLen); -int UpdateDataValue(DataEntry *entry, const char *value); -int GetDataName(const DataEntry *entry, char *name, u_int32_t len); -int GetDataValue(const DataEntry *entry, char *value, u_int32_t len); -u_int32_t GetDataSerial(const DataEntry *entry); +#define GetWorkSpaceSize(workSpace) \ + ((workSpace == NULL) || (workSpace->area == NULL) || \ + (workSpace->area->spaceSizeOffset == 0) || \ + (workSpace->area->spaceSizeOffset >= workSpace->area->dataSize)) ? NULL : \ + (WorkSpaceSize*)(workSpace->area->data + workSpace->area->spaceSizeOffset) #ifdef __cplusplus #if __cplusplus } #endif #endif -#endif // BASE_STARTUP_PARAM_TRIE_H \ No newline at end of file +#endif // BASE_STARTUP_PARAM_TRIE_H \ No newline at end of file diff --git a/services/param/include/param_utils.h b/services/param/include/param_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..63f03e55aafedd99bf51fadb6f952feab79ce2eb --- /dev/null +++ b/services/param/include/param_utils.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 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_PARAM_UTILS_H +#define BASE_STARTUP_PARAM_UTILS_H +#include +#include + +#include "beget_ext.h" +#include "init_param.h" +#include "init_utils.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef enum { + PARAM_CODE_NOT_INIT = PARAM_CODE_MAX + 1, + PARAM_CODE_ERROR_MAP_FILE, +} PARAM_INNER_CODE; + +#ifndef PARAM_BUFFER_MAX +#define PARAM_BUFFER_MAX (0x01 << 16) +#endif + +#define FILENAME_LEN_MAX 255 +#define MS_UNIT 1000 +#ifndef UNUSED +#define UNUSED(x) (void)(x) +#endif +#define PARAM_ALIGN(len) (((len) + 0x03) & (~0x03)) +#define PARAM_IS_ALIGNED(x) (((x) & 0x03) == 0) +#define PARAM_ENTRY(ptr, type, member) (type *)((char *)(ptr)-offsetof(type, member)) + +#define IS_READY_ONLY(name) \ + ((strncmp((name), "const.", strlen("const.")) == 0) || \ + (strncmp((name), "ro.", strlen("ro.")) == 0) || \ + (strncmp((name), "ohos.boot.", strlen("ohos.boot.")) == 0)) + +#define PARAM_PERSIST_PREFIX "persist." + +#define SYS_POWER_CTRL "ohos.startup.powerctrl=" +#define OHOS_CTRL_START "ohos.ctl.start=" +#define OHOS_CTRL_STOP "ohos.ctl.stop=" +#define OHOS_SERVICE_CTRL_PREFIX "ohos.servicectrl." + +#ifdef STARTUP_INIT_TEST +#define PARAM_STATIC +#else +#define PARAM_STATIC static +#endif + +#ifdef __LITEOS_M__ +#ifndef DATA_PATH +#define DATA_PATH "/" +#endif +#elif defined __LITEOS_A__ +#define DATA_PATH STARTUP_INIT_UT_PATH"/storage/data/system/param/" +#elif defined __LINUX__ +#define DATA_PATH STARTUP_INIT_UT_PATH"/storage/data/system/param/" +#else +#define DATA_PATH STARTUP_INIT_UT_PATH"/data/service/el1/startup/parameters/" +#endif +#define PARAM_AREA_SIZE_CFG STARTUP_INIT_UT_PATH"/etc/param/ohos.para.size" +#define CLIENT_PIPE_NAME "/dev/unix/socket/paramservice" +#define PIPE_NAME STARTUP_INIT_UT_PATH "/dev/unix/socket/paramservice" +#define PARAM_STORAGE_PATH STARTUP_INIT_UT_PATH "/dev/__parameters__" +#define PARAM_PERSIST_SAVE_PATH DATA_PATH "persist_parameters" +#define PARAM_PERSIST_SAVE_TMP_PATH DATA_PATH "tmp_persist_parameters" +#define PRIVATE_DATA_PATH STARTUP_INIT_UT_PATH "/data/service/el1/public/startup/parameters/" +#define PARAM_OLD_PERSIST_SAVE_PATH PRIVATE_DATA_PATH "persist_parameters" +#define PARAM_PUBLIC_PERSIST_SAVE_PATH DATA_PATH "public_persist_parameters" +#define PARAM_PUBLIC_PERSIST_SAVE_TMP_PATH DATA_PATH "tmp_public_persist_parameters" +#define PARAM_PRIVATE_PERSIST_SAVE_PATH PRIVATE_DATA_PATH "private_persist_parameters" +#define PARAM_PRIVATE_PERSIST_SAVE_TMP_PATH PRIVATE_DATA_PATH "tmp_private_persist_parameters" +#define PERSIST_HANDLE_MAX 2 + +#define WORKSPACE_FLAGS_INIT 0x01 +#define WORKSPACE_FLAGS_LOADED 0x02 +#define WORKSPACE_FLAGS_UPDATE 0x04 +#define WORKSPACE_FLAGS_LABEL_LOADED 0x08 +#define WORKSPACE_FLAGS_NEED_ACCESS 0x10 +#define WORKSPACE_FLAGS_FOR_INIT 0x20 + +#define PARAM_SET_FLAG(node, flag) ((node) |= (flag)) +#define PARAM_CLEAR_FLAG(node, flag) ((node) &= ~(flag)) +#define PARAM_TEST_FLAG(node, flag) (((node) & (flag)) == (flag)) + +#ifndef PARAN_DOMAIN +#define PARAN_DOMAIN (BASE_DOMAIN + 2) +#endif +#define PARAN_LABEL "PARAM" +#ifdef PARAM_BASE +INIT_LOCAL_API void ParamWorBaseLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...); +#define PARAM_LOGV(fmt, ...) \ + ParamWorBaseLog(INIT_DEBUG, PARAN_DOMAIN, PARAN_LABEL, "[%s:%d]" fmt, \ + (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define PARAM_LOGI(fmt, ...) \ + ParamWorBaseLog(INIT_INFO, PARAN_DOMAIN, PARAN_LABEL, "[%s:%d]" fmt, \ + (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define PARAM_LOGW(fmt, ...) \ + ParamWorBaseLog(INIT_WARN, PARAN_DOMAIN, PARAN_LABEL, "[%s:%d]" fmt, \ + (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#define PARAM_LOGE(fmt, ...) \ + ParamWorBaseLog(INIT_ERROR, PARAN_DOMAIN, PARAN_LABEL, "[%s:%d]" fmt, \ + (STARTUP_FILE_NAME), (__LINE__), ##__VA_ARGS__) +#else +#define PARAM_LOGI(fmt, ...) STARTUP_LOGI(PARAN_DOMAIN, PARAN_LABEL, fmt, ##__VA_ARGS__) +#define PARAM_LOGE(fmt, ...) STARTUP_LOGE(PARAN_DOMAIN, PARAN_LABEL, fmt, ##__VA_ARGS__) +#define PARAM_LOGV(fmt, ...) STARTUP_LOGV(PARAN_DOMAIN, PARAN_LABEL, fmt, ##__VA_ARGS__) +#define PARAM_LOGW(fmt, ...) STARTUP_LOGW(PARAN_DOMAIN, PARAN_LABEL, fmt, ##__VA_ARGS__) +#endif + +#define PARAM_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + PARAM_LOGE(__VA_ARGS__); \ + exper; \ + } + +#define PARAM_INFO_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + PARAM_LOGI(__VA_ARGS__); \ + exper; \ + } + +#define PARAM_WARNING_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + PARAM_LOGW(__VA_ARGS__); \ + exper; \ + } + +#define PARAM_ONLY_CHECK(retCode, exper) \ + if (!(retCode)) { \ + exper; \ + } + +typedef int (*DUMP_PRINTF)(const char *fmt, ...); +#define PARAM_DUMP g_printf +#define MAX_LABEL_LEN 256 +#define PARAM_BUFFER_SIZE 256 + +#define SUBSTR_INFO_NAME 0 +#define SUBSTR_INFO_VALUE 1 +#ifdef PARAM_SUPPORT_SELINUX +#define SUBSTR_INFO_LABEL 1 +#define SUBSTR_INFO_DAC 2 +#else +#define SUBSTR_INFO_LABEL 1 +#define SUBSTR_INFO_DAC 1 +#endif + +INIT_LOCAL_API int SplitParamString(char *line, const char *exclude[], uint32_t count, + int (*result)(const uint32_t *context, const char *name, const char *value), const uint32_t *context); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif \ No newline at end of file diff --git a/services/param/include/trigger_checker.h b/services/param/include/trigger_checker.h index 8bba9e1e40eca25a95b76bf0797c82b1759c6814..e4ac21e4be441f5607c48f12ad9f06c3f318aea5 100644 --- a/services/param/include/trigger_checker.h +++ b/services/param/include/trigger_checker.h @@ -15,9 +15,7 @@ #ifndef STARTUP_TRIGER_CHECKER_H #define STARTUP_TRIGER_CHECKER_H - -#include -#include +#include #include #ifdef __cplusplus @@ -31,6 +29,7 @@ extern "C" { #define MAX_TRIGGER_TYPE_LEN 16 #define SUPPORT_DATA_BUFFER_MAX 128 +#define MAX_DATA_BUFFER_MAX (SUPPORT_DATA_BUFFER_MAX * 5) #define CONDITION_EXTEND_LEN 32 #define LOGIC_DATA_FLAGS_ORIGINAL 0x1 @@ -41,16 +40,16 @@ extern "C" { #define LOGIC_DATA_CLEAR_FLAG(data, flag) (data)->flags &= ~(flag) typedef struct { - u_int32_t flags; - u_int32_t startIndex; - u_int32_t endIndex; + uint32_t flags; + uint32_t startIndex; + uint32_t endIndex; } LogicData; -struct tagTriggerNode; - +struct tagTriggerNode_; +typedef int (*PARAM_CHECK_DONE)(struct tagTriggerNode_ *trigger, const char *content, uint32_t size); typedef struct { char triggerContent[MAX_TRIGGER_NAME_LEN]; - int (*triggerExecuter)(struct tagTriggerNode *trigger, u_int32_t index); + PARAM_CHECK_DONE triggerCheckDone; int dataNumber; int endIndex; int dataUnit; @@ -64,10 +63,10 @@ typedef struct { int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition); void CalculatorFree(LogicCalculator *calculator); -int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLen); +int ConvertInfixToPrefix(const char *condition, char *prefix, uint32_t prefixLen); int ComputeCondition(LogicCalculator *calculator, const char *condition); -int GetValueFromContent(const char *content, u_int32_t contentSize, u_int32_t start, char *value, u_int32_t valueSize); -char *GetMatchedSubCondition(const char *condition, const char *input, int length); +int GetValueFromContent(const char *content, uint32_t contentSize, uint32_t start, char *value, uint32_t valueSize); +int CheckMatchSubCondition(const char *condition, const char *input, int length); #ifdef __cplusplus #if __cplusplus diff --git a/services/param/include/trigger_manager.h b/services/param/include/trigger_manager.h index 6e32fa5d36c86ee15e2c80bd40b08c8dcb56ba96..0121a67aa3c8828eaf23f7a2e261af30d5cd5cc7 100644 --- a/services/param/include/trigger_manager.h +++ b/services/param/include/trigger_manager.h @@ -15,16 +15,15 @@ #ifndef STARTUP_TRIGER_MANAGER_H #define STARTUP_TRIGER_MANAGER_H -#include -#include -#include -#include +#include #include "cJSON.h" -#include "init_log.h" -#include "param_manager.h" +#include "init_cmds.h" +#include "init_hashmap.h" +#include "list.h" +#include "param_message.h" +#include "param_utils.h" #include "trigger_checker.h" -#include "securec.h" #ifdef __cplusplus #if __cplusplus @@ -35,89 +34,172 @@ extern "C" { #define TRIGGER_CMD "trigger " #define TRIGGER_ARR_NAME_IN_JSON "jobs" #define CMDS_ARR_NAME_IN_JSON "cmds" +#define TRIGGER_MAX_CMD 4096 -#define TRIGGER_NODE_IN_QUEUE(trigger) \ - (atomic_load_explicit(&(trigger)->serial, memory_order_relaxed) & 0x01) -#define TRIGGER_NODE_SET_QUEUE_FLAG(trigger) \ - atomic_store_explicit(&(trigger)->serial, (trigger)->serial | 0x01, memory_order_relaxed) -#define TRIGGER_NODE_CLEAR_QUEUE_FLAG(trigger) \ - atomic_store_explicit(&(trigger)->serial, (trigger)->serial & ~0x01, memory_order_relaxed) +#define TRIGGER_EXECUTE_QUEUE 64 +#define MAX_CONDITION_NUMBER 64 + +#define TRIGGER_FLAGS_QUEUE 0x01 +#define TRIGGER_FLAGS_RELATED 0x02 +#define TRIGGER_FLAGS_ONCE 0x04 // 执行完成后释放 +#define TRIGGER_FLAGS_SUBTRIGGER 0x08 // 对init执行后,需要执行的init:xxx=aaa的trigger + +#define CMD_INDEX_FOR_PARA_WAIT 0xfffE +#define CMD_INDEX_FOR_PARA_WATCH 0xffff +#define CMD_INDEX_FOR_PARA_TEST 0x10000 + +#define TRIGGER_IN_QUEUE(trigger) (((trigger)->flags & TRIGGER_FLAGS_QUEUE) == TRIGGER_FLAGS_QUEUE) +#define TRIGGER_SET_FLAG(trigger, flag) ((trigger)->flags |= (flag)) +#define TRIGGER_CLEAR_FLAG(trigger, flag) ((trigger)->flags &= ~(flag)) +#define TRIGGER_TEST_FLAG(trigger, flag) (((trigger)->flags & (flag)) == (flag)) typedef enum { TRIGGER_BOOT = 0, TRIGGER_PARAM, TRIGGER_UNKNOW, - TRIGGER_MAX -}TriggerType; + TRIGGER_PARAM_WAIT, + TRIGGER_PARAM_WATCH, + TRIGGER_MAX, +} TriggerType; + +#define PARAM_TRIGGER_FOR_WAIT 0 +#define PARAM_TRIGGER_FOR_WATCH 1 + +struct tagTriggerNode_; +struct TriggerWorkSpace_; +typedef struct TriggerExtInfo_ { + int8_t type; + ParamTaskPtr stream; + union { + char *name; + struct { + uint32_t watchId; + } watchInfo; + struct { + uint32_t timeout; + uint32_t waitId; + } waitInfo; + } info; + int32_t (*addNode)(struct tagTriggerNode_ *, const struct TriggerExtInfo_ *); +} TriggerExtInfo; + +typedef struct TriggerHeader_ { + ListNode triggerList; + uint32_t triggerCount; + uint32_t cmdNodeCount; + struct tagTriggerNode_ *(*addTrigger)(const struct TriggerWorkSpace_ *workSpace, + const char *condition, const TriggerExtInfo *extInfo); + struct tagTriggerNode_ *(*nextTrigger)(const struct TriggerHeader_ *, const struct tagTriggerNode_ *); + int32_t (*executeTrigger)(const struct tagTriggerNode_ *trigger, const char *content, uint32_t size); + + int32_t (*checkAndMarkTrigger)(const struct TriggerWorkSpace_ *workSpace, int type, const char *name); + int32_t (*checkTriggerMatch)(const struct TriggerWorkSpace_ *workSpace, int type, + LogicCalculator *calculator, const char *content, uint32_t contentSize); + int32_t (*checkCondition)(LogicCalculator *calculator, + const char *condition, const char *content, uint32_t contentSize); + + const char *(*getTriggerName)(const struct tagTriggerNode_ *trigger); + const char *(*getCondition)(const struct tagTriggerNode_ *trigger); + void (*delTrigger)(const struct TriggerWorkSpace_ *workSpace, struct tagTriggerNode_ *trigger); + void (*dumpTrigger)(const struct TriggerWorkSpace_ *workSpace, + const struct tagTriggerNode_ *trigger); + int32_t (*compareData)(const struct tagTriggerNode_ *trigger, const void *data); +} TriggerHeader; -// Command对象列表,主要存储每个triger需要执行那些Command操作。 -typedef struct CommandNode { - atomic_uint_least32_t next; - char name[MAX_TRIGGER_CMD_NAME_LEN]; +typedef struct CommandNode_ { + struct CommandNode_ *next; + ConfigContext cfgContext; + uint32_t cmdKeyIndex; char content[0]; } CommandNode; -typedef struct tagTriggerNode { - atomic_uint_least32_t serial; - atomic_uint_least32_t next; - atomic_uint_least32_t firstCmd; - atomic_uint_least32_t lastCmd; - int type; - char name[MAX_TRIGGER_NAME_LEN]; - char condition[0]; +#define NODE_BASE \ + ListNode node; \ + uint32_t flags : 24; \ + uint32_t type : 4; \ + char *condition + +typedef struct tagTriggerNode_ { + NODE_BASE; } TriggerNode; -typedef struct { - atomic_uint_least32_t serial; - u_int32_t dataSize; - u_int32_t startSize; - u_int32_t currOffset; - char data[0]; -} TriggerArea; +typedef struct tagTriggerJobNode_ { + NODE_BASE; + CommandNode *firstCmd; + CommandNode *lastCmd; + HashNode hashNode; + char name[0]; +} JobNode; + +typedef struct WatchNode_ { + NODE_BASE; + ListNode item; + uint32_t watchId; +} WatchNode; + +typedef struct WaitNode_ { + NODE_BASE; + ListNode item; + uint32_t timeout; + uint32_t waitId; + ParamTaskPtr stream; +} WaitNode; typedef struct { - atomic_uint_least32_t firstTrigger; - atomic_uint_least32_t lastTrigger; -} TriggerHeader; + uint32_t queueCount; + uint32_t startIndex; + uint32_t endIndex; + TriggerNode **executeQueue; +} TriggerExecuteQueue; typedef struct { - u_int32_t *executeQueue; - u_int32_t queueCount; - u_int32_t startIndex; - u_int32_t endIndex; - pthread_mutex_t mutex; -} TriggerExecuteQueue; + ListHead triggerHead; + ParamTaskPtr stream; +} ParamWatcher; -typedef struct TriggerWorkSpace { +typedef struct TriggerWorkSpace_ { TriggerExecuteQueue executeQueue; - TriggerHeader header[TRIGGER_MAX]; - TriggerArea *area; + TriggerHeader triggerHead[TRIGGER_MAX]; + HashMapHandle hashMap; + ParamTaskPtr eventHandle; + void (*bootStateChange)(int start, const char *); + char cache[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX]; } TriggerWorkSpace; -int InitTriggerWorkSpace(TriggerWorkSpace *workSpace); -int ParseTrigger(TriggerWorkSpace *workSpace, cJSON *triggerItem); - -typedef int (*TRIGGER_MATCH)(LogicCalculator *calculator, TriggerNode *trigger, const char *content, u_int32_t contentSize); -typedef int (*PARAM_CHECK_DONE)(TriggerNode *trigger, u_int32_t index); -typedef int (*CMD_EXECUTE) (TriggerNode *trigger, const char *cmdName, const char *command); +int InitTriggerWorkSpace(void); +void CloseTriggerWorkSpace(void); +TriggerWorkSpace *GetTriggerWorkSpace(void); +char *GetTriggerCache(uint32_t *size); +TriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type); +void InitTriggerHead(const TriggerWorkSpace *workSpace); -TriggerNode *GetTriggerByName(TriggerWorkSpace *workSpace, const char *triggerName, u_int32_t *triggerIndex); -int ExecuteTrigger(TriggerWorkSpace *workSpace, TriggerNode *trigger, CMD_EXECUTE cmdExecuter); -int CheckTrigger(const TriggerWorkSpace *workSpace, - int type, void *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter); -int CheckParamTrigger(TriggerWorkSpace *workSpace, - const char *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter); -int CheckAndExecuteTrigger(TriggerWorkSpace *workSpace, const char *content, PARAM_CHECK_DONE triggerExecuter); +int CheckTrigger(TriggerWorkSpace *workSpace, int type, + const char *content, uint32_t contentSize, PARAM_CHECK_DONE triggerCheckDone); +int CheckAndMarkTrigger(int type, const char *name); TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace); -int ExecuteQueuePush(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t index); -int ExecuteQueueSize(TriggerWorkSpace *workSpace); +int ExecuteQueuePush(TriggerWorkSpace *workSpace, const TriggerNode *trigger); -u_int32_t AddTrigger(TriggerWorkSpace *workSpace, int type, const char *name, const char *condition); -u_int32_t AddCommand(TriggerWorkSpace *workSpace, TriggerNode *trigger, const char *cmdName, const char *content); +JobNode *UpdateJobTrigger(const TriggerWorkSpace *workSpace, + int type, const char *condition, const char *name); +JobNode *GetTriggerByName(const TriggerWorkSpace *workSpace, const char *triggerName); +void FreeTrigger(const TriggerWorkSpace *workSpace, TriggerNode *trigger); +void ClearTrigger(const TriggerWorkSpace *workSpace, int8_t type); +int AddCommand(JobNode *trigger, uint32_t cmdIndex, const char *content, const ConfigContext *cfgContext); +CommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr); -TriggerWorkSpace *GetTriggerWorkSpace(); +void PostParamTrigger(int type, const char *name, const char *value); +void ClearWatchTrigger(ParamWatcher *watcher, int type); +void DelWatchTrigger(int type, const void *data); +int CheckWatchTriggerTimeout(void); + +const char *GetTriggerName(const TriggerNode *trigger); +void RegisterTriggerExec(int type, int32_t (*executeTrigger)(const TriggerNode *, const char *, uint32_t)); + +#ifdef STARTUP_INIT_TEST +void ProcessBeforeEvent(const ParamTaskPtr stream, uint64_t eventId, const uint8_t *content, uint32_t size); +#endif #ifdef __cplusplus #if __cplusplus } diff --git a/services/param/linux/BUILD.gn b/services/param/linux/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..ba33b79eee3c8c549ad1588d4176a76c104eca4a --- /dev/null +++ b/services/param/linux/BUILD.gn @@ -0,0 +1,200 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/service/param/include", + ] +} + +config("exported_header_files_for_lite") { + visibility = [ ":*" ] +} + +param_include_dirs = [ + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/adapter", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/param/base", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + "//base/startup/init/services/loopevent/include", +] + +param_service_sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/linux/param_msgadp.c", + "//base/startup/init/services/param/linux/param_service.c", + "//base/startup/init/services/param/manager/param_manager.c", + "//base/startup/init/services/param/manager/param_persist.c", + "//base/startup/init/services/param/manager/param_server.c", +] + +param_trigger_sources = [ + "//base/startup/init/services/param/trigger/trigger_checker.c", + "//base/startup/init/services/param/trigger/trigger_manager.c", + "//base/startup/init/services/param/trigger/trigger_processor.c", +] + +param_client_sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/linux/param_request.c", + "//base/startup/init/services/param/manager/param_manager.c", +] + +# only for linux +if (defined(ohos_lite)) { + static_library("param_init") { + defines = [] + sources = param_service_sources + sources += param_trigger_sources + sources += + [ "//base/startup/init/services/param/liteos/param_persistadp.c" ] + include_dirs = param_include_dirs + include_dirs += [ + "//base/security/selinux_adapter/interfaces/policycoreutils/include", + "//commonlibrary/utils_lite/include", + "//third_party/cJSON", + ] + public_configs = [ ":exported_header_files" ] + public_configs += [ ":exported_header_files_for_lite" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + defines += [ + "_GNU_SOURCE", + "__LINUX__", + "OHOS_LITE", + "PARAM_SUPPORT_REAL_CHECK", + "INCREMENTAL_VERSION=\"${ohos_version}\"", + "BUILD_TYPE=\"${ohos_build_type}\"", + "BUILD_USER=\"${ohos_build_user}\"", + "BUILD_TIME=\"${ohos_build_time}\"", + "BUILD_HOST=\"${ohos_build_host}\"", + "BUILD_ROOTHASH=\"${ohos_build_roothash}\"", + ] + } + + static_library("param_client") { + include_dirs = param_include_dirs + include_dirs += [ + "//base/security/selinux_adapter/interfaces/policycoreutils/include", + "//commonlibrary/utils_lite/include", + "//third_party/cJSON", + ] + sources = param_client_sources + public_configs = [ ":exported_header_files" ] + public_configs += [ ":exported_header_files_for_lite" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + cflags = [ "-fPIC" ] + defines = [ + "_GNU_SOURCE", + "__LINUX__", + ] + } +} else { + ohos_static_library("param_init") { + sources = param_service_sources + sources += param_trigger_sources + sources += + [ "//base/startup/init/services/param/adapter/param_persistadp.c" ] + include_dirs = param_include_dirs + public_configs = [ ":exported_header_files" ] + defines = [ + "_GNU_SOURCE", + "PARAM_SUPPORT_REAL_CHECK", + "SUPPORT_PARAM_LOAD_HOOK", + ] + if (is_asan) { + defines += [ "INIT_ASAN" ] + } + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson", + ] + public_external_deps = [ "selinux:libselinux" ] + + if (param_base_log) { + defines += [ "PARAM_BASE_LOG" ] + } + if (defined(ohos_build_type)) { + defines += [ "BUILD_TYPE=\"${ohos_build_type}\"" ] + } + if (defined(ohos_version)) { + defines += [ "INCREMENTAL_VERSION=\"${ohos_version}\"" ] + } + if (defined(ohos_build_user)) { + defines += [ "BUILD_USER=\"${ohos_build_user}\"" ] + } + if (defined(ohos_build_time)) { + defines += [ "BUILD_TIME=\"${ohos_build_time}\"" ] + } + if (defined(ohos_build_host)) { + defines += [ "BUILD_HOST=\"${ohos_build_host}\"" ] + } + + if (build_selinux) { + defines += [ + "PARAM_SUPPORT_SELINUX", + "PARAMWORKSPACE_NEED_MUTEX", + ] + external_deps += [ "selinux_adapter:libselinux_parameter_static" ] + } + + deps = [ "//base/startup/init/services/param/base:param_base" ] + part_name = "init" + subsystem_name = "startup" + } + + ohos_static_library("param_client") { + sources = param_client_sources + include_dirs = param_include_dirs + public_configs = [ ":exported_header_files" ] + deps = [ + "//base/startup/init/services/log:agent_log", + "//base/startup/init/services/param/base:param_base", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson_static", + ] + if (build_selinux) { + external_deps += [ "selinux_adapter:libselinux_parameter_static" ] + } + + cflags = [ "-Wno-deprecated-pragma" ] + defines = [ + "_GNU_SOURCE", + "INIT_AGENT", + ] + if (build_selinux) { + defines += [ + "PARAM_SUPPORT_SELINUX", + "PARAMWORKSPACE_NEED_MUTEX", + ] + } + if (param_base_log) { + defines += [ "PARAM_BASE_LOG" ] + } + part_name = "init" + subsystem_name = "startup" + } +} diff --git a/services/param/linux/param_message.c b/services/param/linux/param_message.c new file mode 100644 index 0000000000000000000000000000000000000000..e0365b161651f83a9556760aefc20a0e0f817cdd --- /dev/null +++ b/services/param/linux/param_message.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 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 "param_message.h" + +#include +#include + +#include "param_utils.h" +#include "securec.h" + +int ConnectServer(int fd, const char *servername) +{ + PARAM_CHECK(fd >= 0, return -1, "Invalid fd %d", fd); + PARAM_CHECK(servername != NULL, return -1, "Invalid servername"); + int opt = 1; + int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); + PARAM_CHECK(ret == 0, return -1, "Failed to set socket option"); + struct sockaddr_un addr; + /* fill socket address structure with server's address */ + ret = memset_s(&addr, sizeof(addr), 0, sizeof(addr)); + PARAM_CHECK(ret == 0, return -1, "Failed to memset server address"); + addr.sun_family = AF_UNIX; + ret = sprintf_s(addr.sun_path, sizeof(addr.sun_path) - 1, "%s", servername); + PARAM_CHECK(ret > EOK, return -1, "Failed to sprintf_s server address"); + socklen_t len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path); + ret = connect(fd, (struct sockaddr *)&addr, len); + PARAM_CHECK(ret != -1, return -1, "Failed to connect server %s %d", servername, errno); + PARAM_LOGV("ConnectServer %s success", servername); + return 0; +} + +int FillParamMsgContent(const ParamMessage *request, uint32_t *start, int type, const char *value, uint32_t length) +{ + PARAM_CHECK(request != NULL && start != NULL, return -1, "Invalid param"); + PARAM_CHECK(value != NULL, return -1, "Invalid value"); + uint32_t bufferSize = request->msgSize - sizeof(ParamMessage); + uint32_t offset = *start; + PARAM_CHECK((offset + sizeof(ParamMsgContent) + length) <= bufferSize, + return -1, "Invalid msgSize %u offset %u %d", request->msgSize, offset, type); + ParamMsgContent *content = (ParamMsgContent *)(request->data + offset); + content->type = type; + content->contentSize = length + 1; + if (length > 0) { + int ret = memcpy_s(content->content, content->contentSize - 1, value, length); + PARAM_CHECK(ret == EOK, return -1, "Failed to copy value for %d", type); + } + content->content[length] = '\0'; + offset += sizeof(ParamMsgContent) + PARAM_ALIGN(content->contentSize); + *start = offset; + return 0; +} + +ParamMessage *CreateParamMessage(int type, const char *name, uint32_t msgSize) +{ + PARAM_CHECK(name != NULL, return NULL, "Invalid name"); + PARAM_CHECK(msgSize < PARAM_BUFFER_MAX, return NULL, "Invalid msg size %u", msgSize); + uint32_t size = msgSize; + if (msgSize < sizeof(ParamMessage)) { + size = sizeof(ParamMessage); + } + ParamMessage *msg = (ParamMessage *)calloc(1, size); + PARAM_CHECK(msg != NULL, return NULL, "Failed to malloc message"); + msg->type = type; + msg->id.msgId = 0; + msg->msgSize = size; + int ret = strcpy_s(msg->key, sizeof(msg->key) - 1, name); + PARAM_CHECK(ret == EOK, free(msg); + return NULL, "Failed to fill name"); + return msg; +} + +ParamMsgContent *GetNextContent(const ParamMessage *request, uint32_t *offset) +{ + PARAM_CHECK(request != NULL, return NULL, "Invalid request"); + PARAM_CHECK(offset != NULL, return NULL, "Invalid offset"); + ParamMessage *msg = (ParamMessage *)request; + if ((*offset + sizeof(ParamMessage) + sizeof(ParamMsgContent)) >= msg->msgSize) { + return NULL; + } + ParamMsgContent *content = (ParamMsgContent *)(msg->data + *offset); + *offset += sizeof(ParamMsgContent) + PARAM_ALIGN(content->contentSize); + return content; +} diff --git a/services/param/linux/param_message.h b/services/param/linux/param_message.h new file mode 100755 index 0000000000000000000000000000000000000000..706129bb2c2ee30b4290dd6265d07770ab7ef4d8 --- /dev/null +++ b/services/param/linux/param_message.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 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_PARAM_MESSAGE_H +#define BASE_STARTUP_PARAM_MESSAGE_H +#include +#include +#include + +#include "loop_event.h" +#include "param_osadp.h" +#include "param_utils.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define PARAM_TEST_FLAGS 0x01 +typedef enum { + MSG_SET_PARAM, + MSG_WAIT_PARAM, + MSG_ADD_WATCHER, + MSG_DEL_WATCHER, + MSG_NOTIFY_PARAM, + MSG_SAVE_PARAM +} ParamMsgType; + +typedef enum ContentType { + PARAM_NAME, + PARAM_VALUE, + PARAM_LABEL, + PARAM_WAIT_TIMEOUT, + PARAM_NAME_VALUE, +} ContentType; + +typedef struct { + uint8_t type; + uint8_t rev; + uint16_t contentSize; + char content[0]; +} ParamMsgContent; + +typedef struct { + uint32_t type; + uint32_t msgSize; + union { + uint32_t msgId; + uint32_t watcherId; + uint32_t waitId; + } id; + char key[PARAM_NAME_LEN_MAX + 4]; + char data[0]; +} ParamMessage; + +typedef struct { + ParamMessage msg; + int32_t result; +} ParamResponseMessage; + +typedef int (*RecvMessage)(const ParamTaskPtr stream, const ParamMessage *msg); + +typedef struct { + uint32_t flags; + char *server; + LE_IncommingConnect incomingConnect; + RecvMessage recvMessage; + LE_Close close; +} ParamStreamInfo; + +int ParamServiceStop(void); +int ParamServiceStart(void); + +int ParamTaskClose(const ParamTaskPtr stream); +int ParamServerCreate(ParamTaskPtr *stream, const ParamStreamInfo *streamInfo); +int ParamStreamCreate(ParamTaskPtr *stream, ParamTaskPtr server, + const ParamStreamInfo *streamInfo, uint16_t userDataSize); +int ParamTaskSendMsg(const ParamTaskPtr stream, const ParamMessage *msg); + +int ParamEventTaskCreate(ParamTaskPtr *stream, LE_ProcessAsyncEvent eventProcess); +int ParamEventSend(const ParamTaskPtr stream, uint64_t eventId, const char *content, uint32_t size); + +void *ParamGetTaskUserData(const ParamTaskPtr stream); + +int FillParamMsgContent(const ParamMessage *request, uint32_t *start, int type, const char *value, uint32_t length); +ParamMsgContent *GetNextContent(const ParamMessage *request, uint32_t *offset); +ParamMessage *CreateParamMessage(int type, const char *name, uint32_t msgSize); + +int ConnectServer(int fd, const char *servername); + +#ifdef STARTUP_INIT_TEST +int ProcessMessage(const ParamTaskPtr worker, const ParamMessage *msg); +int OnIncomingConnect(LoopHandle loop, TaskHandle server); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_PARAM_MESSAGE_H \ No newline at end of file diff --git a/services/param/linux/param_msgadp.c b/services/param/linux/param_msgadp.c new file mode 100644 index 0000000000000000000000000000000000000000..e8650724bafcba46971c78681ab5e3c6cc5ea904 --- /dev/null +++ b/services/param/linux/param_msgadp.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2021 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 "param_osadp.h" + +#include +#include +#include +#include + +#include "param_message.h" +#include "param_utils.h" +#include "securec.h" + +static const uint32_t RECV_BUFFER_MAX = 5 * 1024; + +static RecvMessage g_recvMessage; +static void OnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread) +{ + if (nread == 0 || buffer == NULL || g_recvMessage == NULL) { + return; + } + uint32_t curr = 0; + while (curr < nread) { + const ParamMessage *msg = (const ParamMessage *)(buffer + curr); + if ((nread - curr < msg->msgSize) || + (nread - curr < sizeof(ParamMessage)) || + (msg->msgSize < sizeof(ParamMessage))) { + break; + } + curr += msg->msgSize; + g_recvMessage(task, msg); + } +} + +int ParamServerCreate(ParamTaskPtr *stream, const ParamStreamInfo *streamInfo) +{ + PARAM_CHECK(stream != NULL && streamInfo != NULL, return -1, "Invalid param"); + PARAM_CHECK(streamInfo->incomingConnect != NULL, return -1, "Invalid incomingConnect"); + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER | TASK_PUBLIC; + info.server = streamInfo->server; + info.baseInfo.close = streamInfo->close; + info.incommingConnect = streamInfo->incomingConnect; + return LE_CreateStreamServer(LE_GetDefaultLoop(), stream, &info); +} + +int ParamStreamCreate(ParamTaskPtr *stream, ParamTaskPtr server, + const ParamStreamInfo *streamInfo, uint16_t userDataSize) +{ + PARAM_CHECK(stream != NULL && streamInfo != NULL, return -1, "Invalid stream"); + PARAM_CHECK(streamInfo->recvMessage != NULL, return -1, "Invalid recvMessage"); + PARAM_CHECK(streamInfo->close != NULL, return -1, "Invalid close"); + LE_StreamInfo info = {}; + info.baseInfo.userDataSize = userDataSize; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; + if (streamInfo->flags & PARAM_TEST_FLAGS) { + info.baseInfo.flags |= TASK_TEST; + } + info.baseInfo.close = streamInfo->close; + info.disConnectComplete = NULL; + info.sendMessageComplete = NULL; + info.recvMessage = OnReceiveRequest; + g_recvMessage = streamInfo->recvMessage; + LE_STATUS status = LE_AcceptStreamClient(LE_GetDefaultLoop(), server, stream, &info); + PARAM_CHECK(status == 0, return -1, "Failed to create client"); + return 0; +} + +void *ParamGetTaskUserData(const ParamTaskPtr stream) +{ + PARAM_CHECK(stream != NULL, return NULL, "Invalid stream"); + return LE_GetUserData(stream); +} + +int ParamTaskSendMsg(const ParamTaskPtr stream, const ParamMessage *msg) +{ + PARAM_CHECK(msg != NULL, return -1, "Invalid stream"); + PARAM_CHECK(stream != NULL, free((void *)msg); + return -1, "Invalid stream"); + uint32_t dataSize = msg->msgSize; + BufferHandle bufferHandle = LE_CreateBuffer(LE_GetDefaultLoop(), dataSize); + PARAM_CHECK(bufferHandle != NULL, return -1, "Failed to create request"); + uint8_t *buffer = LE_GetBufferInfo(bufferHandle, NULL, NULL); + int ret = memcpy_s(buffer, dataSize, msg, dataSize); + free((void *)msg); + PARAM_CHECK(ret == EOK, LE_FreeBuffer(LE_GetDefaultLoop(), NULL, bufferHandle); + return -1, "Failed to copy message"); + return LE_Send(LE_GetDefaultLoop(), stream, bufferHandle, dataSize); +} + +int ParamEventTaskCreate(ParamTaskPtr *stream, LE_ProcessAsyncEvent eventProcess) +{ + PARAM_CHECK(stream != NULL && eventProcess != NULL, return -1, "Invalid info or stream"); + return LE_CreateAsyncTask(LE_GetDefaultLoop(), stream, eventProcess); +} + +int ParamEventSend(const ParamTaskPtr stream, uint64_t eventId, const char *content, uint32_t size) +{ + PARAM_CHECK(stream != NULL, return -1, "Invalid stream"); + PARAM_CHECK(size <= RECV_BUFFER_MAX, return -1, "Invalid stream"); + return LE_StartAsyncEvent(LE_GetDefaultLoop(), stream, eventId, (const uint8_t *)content, size); +} + +int ParamTaskClose(const ParamTaskPtr stream) +{ + PARAM_CHECK(stream != NULL, return -1, "Invalid param"); + LE_CloseTask(LE_GetDefaultLoop(), stream); + return 0; +} + + +int ParamTimerCreate(ParamTaskPtr *timer, ProcessTimer process, void *context) +{ + PARAM_CHECK(timer != NULL && process != NULL, return -1, "Invalid timer"); + LE_STATUS status = LE_CreateTimer(LE_GetDefaultLoop(), timer, (LE_ProcessTimer)process, context); + return (int)status; +} + +int ParamTimerStart(const ParamTaskPtr timer, uint64_t timeout, uint64_t repeat) +{ + PARAM_CHECK(timer != NULL, return -1, "Invalid timer"); + return LE_StartTimer(LE_GetDefaultLoop(), timer, timeout, repeat); +} + +void ParamTimerClose(ParamTaskPtr timer) +{ + PARAM_CHECK(timer != NULL, return, "Invalid param"); + LE_CloseTask(LE_GetDefaultLoop(), (ParamTaskPtr)timer); +} + +int ParamServiceStart(void) +{ + LE_RunLoop(LE_GetDefaultLoop()); + return 0; +} + +int ParamServiceStop(void) +{ + LE_StopLoop(LE_GetDefaultLoop()); + return 0; +} \ No newline at end of file diff --git a/services/param/linux/param_osadp.c b/services/param/linux/param_osadp.c new file mode 100644 index 0000000000000000000000000000000000000000..b633f7080cda777ae4be3289228dfeb584afef92 --- /dev/null +++ b/services/param/linux/param_osadp.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 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 "param_osadp.h" + +#include +#include + +#include "param_message.h" +#include "param_utils.h" + +INIT_LOCAL_API void paramMutexEnvInit(void) +{ +} + +INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlockattr_t rwlockatt; + pthread_rwlockattr_init(&rwlockatt); + pthread_rwlockattr_setpshared(&rwlockatt, PTHREAD_PROCESS_SHARED); + pthread_rwlock_init(&lock->rwlock, &rwlockatt); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlock_wrlock(&lock->rwlock); + return 0; +} +INIT_LOCAL_API int ParamRWMutexRDLock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlock_rdlock(&lock->rwlock); + return 0; +} +INIT_LOCAL_API int ParamRWMutexUnlock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlock_unlock(&lock->rwlock); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexDelete(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + int ret = pthread_rwlock_destroy(&lock->rwlock); + PARAM_CHECK(ret == 0, return -1, "Failed to mutex lock ret %d", ret); + return 0; +} + +INIT_LOCAL_API int ParamMutexCreate(ParamMutex *mutex) +{ + return 0; +} +INIT_LOCAL_API int ParamMutexPend(ParamMutex *mutex) +{ + return 0; +} +INIT_LOCAL_API int ParamMutexPost(ParamMutex *mutex) +{ + return 0; +} +INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex) +{ + return 0; +} + +INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly) +{ + PARAM_CHECK(fileName != NULL, return NULL, "Invalid filename or handle"); + int mode = readOnly ? O_RDONLY : O_CREAT | O_RDWR | O_TRUNC; + int fd = open(fileName, mode, S_IRWXU | S_IRWXG | S_IROTH); + PARAM_ONLY_CHECK(fd >= 0, return NULL); + + int prot = PROT_READ; + if (!readOnly) { + prot = PROT_READ | PROT_WRITE; + ftruncate(fd, spaceSize); + } + void *areaAddr = (void *)mmap(NULL, spaceSize, prot, MAP_SHARED, fd, 0); + PARAM_CHECK(areaAddr != MAP_FAILED && areaAddr != NULL, close(fd); + return NULL, "Failed to map memory error %d fileName %s ", errno, fileName); + close(fd); + return areaAddr; +} + +INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize) +{ + PARAM_CHECK(mem != NULL && handle != NULL, return, "Invalid mem or handle"); + munmap((char *)mem, dataSize); +} diff --git a/services/param/linux/param_request.c b/services/param/linux/param_request.c new file mode 100644 index 0000000000000000000000000000000000000000..2e21ba84d396b9250640477c28cedf36238180de --- /dev/null +++ b/services/param/linux/param_request.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2021-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 "init_param.h" + +#include +#include +#include +#include +#include + +#include "init_log.h" +#include "init_utils.h" +#include "param_atomic.h" +#include "param_manager.h" +#include "param_message.h" +#include "param_security.h" + +#define INVALID_SOCKET (-1) +static const uint32_t RECV_BUFFER_MAX = 5 * 1024; +static ATOMIC_UINT32 g_requestId; +static int g_clientFd = INVALID_SOCKET; +static pthread_mutex_t g_clientMutex = PTHREAD_MUTEX_INITIALIZER; + +__attribute__((constructor)) static void ParameterInit(void) +{ + ATOMIC_INIT(&g_requestId, 1); + EnableInitLog(INIT_INFO); + + PARAM_WORKSPACE_OPS ops = {0}; + ops.updaterMode = 0; + ops.logFunc = InitLog; +#ifdef PARAM_SUPPORT_SELINUX + ops.setfilecon = NULL; +#endif + InitParamWorkSpace(1, &ops); + + // modify log level + char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length. + uint32_t len = sizeof(logLevel); + int ret = SystemReadParam(INIT_DEBUG_LEVEL, logLevel, &len); + if (ret == 0) { + errno = 0; + int level = atoi(logLevel); + if (errno != 0) { + return; + } + SetInitLogLevel((InitLogLevel)level); + } +} + +__attribute__((destructor)) static void ParameterDeinit(void) +{ + if (g_clientFd != INVALID_SOCKET) { + close(g_clientFd); + g_clientFd = INVALID_SOCKET; + } + pthread_mutex_destroy(&g_clientMutex); +} + +static int ProcessRecvMsg(const ParamMessage *recvMsg) +{ + PARAM_LOGV("ProcessRecvMsg type: %u msgId: %u name %s", recvMsg->type, recvMsg->id.msgId, recvMsg->key); + int result = PARAM_CODE_INVALID_PARAM; + switch (recvMsg->type) { + case MSG_SET_PARAM: + case MSG_SAVE_PARAM: + result = ((ParamResponseMessage *)recvMsg)->result; + break; + case MSG_NOTIFY_PARAM: { + uint32_t offset = 0; + ParamMsgContent *valueContent = GetNextContent(recvMsg, &offset); + PARAM_CHECK(valueContent != NULL, return PARAM_CODE_TIMEOUT, "Invalid msg"); + result = 0; + break; + } + default: + break; + } + return result; +} + +static int ReadMessage(int fd, char *buffer, uint32_t timeout) +{ + int ret = 0; + uint32_t diff = 0; + struct timespec startTime = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &startTime); + do { + ssize_t recvLen = recv(fd, (char *)buffer, RECV_BUFFER_MAX, 0); + if (recvLen <= 0) { + PARAM_LOGE("ReadMessage failed! errno %d", errno); + struct timespec finishTime = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &finishTime); + diff = IntervalTime(&finishTime, &startTime); + if (diff >= timeout) { + ret = PARAM_CODE_TIMEOUT; + break; + } + if (errno == EAGAIN || errno == EINTR) { + usleep(10*1000); // 10*1000 wait 10ms + continue; + } + } + + if ((size_t)recvLen > sizeof(ParamMessage)) { + PARAM_LOGV("recv message len is %d", recvLen); + break; + } + } while (1); + + if (ret != 0) { + PARAM_LOGE("ReadMessage errno %d diff %u timeout %d ret %d", errno, diff, timeout, ret); + } + return ret; +} + +static int GetClientSocket(int timeout) +{ + struct timeval time = {0}; + time.tv_sec = timeout; + time.tv_usec = 0; + int clientFd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + PARAM_CHECK(clientFd >= 0, return INVALID_SOCKET, "Failed to create socket"); + int ret = ConnectServer(clientFd, CLIENT_PIPE_NAME); + if (ret == 0) { + setsockopt(clientFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&time, sizeof(struct timeval)); + setsockopt(clientFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&time, sizeof(struct timeval)); + } else { + close(clientFd); + clientFd = INVALID_SOCKET; + } + return clientFd; +} + +static int StartRequest(int clientFd, ParamMessage *request, int timeout) +{ + errno = 0; + ssize_t sendLen = send(clientFd, (char *)request, request->msgSize, 0); + if (errno == EINVAL || errno == EACCES) { + PARAM_LOGE("send Message failed!"); + return PARAM_CODE_IPC_ERROR; + } + PARAM_CHECK(sendLen >= 0, return PARAM_CODE_IPC_ERROR, "Failed to send message err: %d", errno); + PARAM_LOGV("sendMessage sendLen fd %d %zd", clientFd, sendLen); + if (timeout <= 0) { + return 0; + } + int ret = ReadMessage(clientFd, (char *)request, timeout); + if (ret == 0) { + ret = ProcessRecvMsg(request); + } + return ret; +} + +static int SystemSetParameter_(const char *name, const char *value, int timeout) +{ + PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value"); + int ret = CheckParamName(name, 0); + PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name); + ret = CheckParamValue(NULL, name, value, GetParamValueType(name)); + PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value); + + size_t msgSize = sizeof(ParamMsgContent); + msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize; + + ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, name, msgSize); + PARAM_CHECK(request != NULL, return PARAM_CODE_ERROR, "Failed to create Param Message"); + uint32_t offset = 0; + ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value)); + PARAM_CHECK(ret == 0, free(request); + return PARAM_CODE_ERROR, "Failed to fill value"); + request->msgSize = offset + sizeof(ParamMessage); + request->id.msgId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED); + + pthread_mutex_lock(&g_clientMutex); + int retryCount = 0; + while (retryCount < 2) { // max retry 2 + if (g_clientFd == INVALID_SOCKET) { + g_clientFd = GetClientSocket(DEFAULT_PARAM_SET_TIMEOUT); + } + + if (g_clientFd < 0) { + ret = PARAM_CODE_FAIL_CONNECT; + PARAM_LOGE("connect param server failed!"); + break; + } + ret = StartRequest(g_clientFd, request, timeout); + if (ret == PARAM_CODE_IPC_ERROR) { + close(g_clientFd); + g_clientFd = INVALID_SOCKET; + retryCount++; + } else { + break; + } + } + PARAM_LOGI("SystemSetParameter name %s msgid:%d ret: %d ", name, request->id.msgId, ret); + pthread_mutex_unlock(&g_clientMutex); + free(request); + return ret; +} + +int SystemSetParameter(const char *name, const char *value) +{ + int ret = SystemSetParameter_(name, value, DEFAULT_PARAM_SET_TIMEOUT); + BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemSetParameter failed! name is :%s, the errNum is:%d", name, ret); + return ret; +} + +int SystemSetParameterNoWait(const char *name, const char *value) +{ + int ret = SystemSetParameter_(name, value, 0); + BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemSetParameterNoWait failed! name is:%s, the errNum is:%d", name, ret); + return ret; +} + +int SystemSaveParameters(void) +{ + const char *name = "persist.all"; + size_t msgSize = RECV_BUFFER_MAX; + uint32_t offset = 0; + ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SAVE_PARAM, name, msgSize); + PARAM_CHECK(request != NULL, return -1, "SystemSaveParameters failed! name is:%s, the errNum is:-1", name); + int ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1); + PARAM_CHECK(ret == 0, free(request); + return -1, "SystemSaveParameters failed! the errNum is:-1"); + int fd = GetClientSocket(DEFAULT_PARAM_WAIT_TIMEOUT); + PARAM_CHECK(fd >= 0, free(request); + return fd, "SystemSaveParameters failed! the errNum is:%d", ret); + request->msgSize = offset + sizeof(ParamMessage); + request->id.msgId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED); + ret = StartRequest(fd, request, DEFAULT_PARAM_WAIT_TIMEOUT); + close(fd); + free(request); + BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemSaveParameters failed! the errNum is:%d", ret); + return ret; +} + +int SystemWaitParameter(const char *name, const char *value, int32_t timeout) +{ + PARAM_CHECK(name != NULL, return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); + int ret = CheckParamName(name, 0); + PARAM_CHECK(ret == 0, return ret, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); + ret = CheckParamPermission(GetParamSecurityLabel(), name, DAC_READ); + PARAM_CHECK(ret == 0, return ret, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); + if (timeout <= 0) { + timeout = DEFAULT_PARAM_WAIT_TIMEOUT; + } + uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + sizeof(ParamMsgContent) + sizeof(uint32_t); + msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize; + uint32_t offset = 0; + ParamMessage *request = NULL; + if (value != NULL && strlen(value) > 0) { + msgSize += PARAM_ALIGN(strlen(value) + 1); + request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize); + PARAM_CHECK(request != NULL, return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); + ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value)); + } else { + msgSize += PARAM_ALIGN(1); + request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize); + PARAM_CHECK(request != NULL, return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); + ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1); + } + PARAM_CHECK(ret == 0, free(request); + return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); + ParamMsgContent *content = (ParamMsgContent *)(request->data + offset); + content->type = PARAM_WAIT_TIMEOUT; + content->contentSize = sizeof(uint32_t); + *((uint32_t *)(content->content)) = timeout; + offset += sizeof(ParamMsgContent) + sizeof(uint32_t); + + request->msgSize = offset + sizeof(ParamMessage); + request->id.waitId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED); +#ifdef STARTUP_INIT_TEST + timeout = 1; +#endif + int fd = GetClientSocket(timeout); + PARAM_CHECK(fd >= 0, free(request); + return fd, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); + ret = StartRequest(fd, request, timeout); + close(fd); + free(request); + PARAM_LOGI("SystemWaitParameter %s value %s result %d ", name, value, ret); + BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); + return ret; +} + +int SystemCheckParamExist(const char *name) +{ + return SysCheckParamExist(name); +} + +int WatchParamCheck(const char *keyprefix) +{ + PARAM_CHECK(keyprefix != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid keyprefix"); + int ret = CheckParamName(keyprefix, 0); + PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", keyprefix); + ret = CheckParamPermission(GetParamSecurityLabel(), keyprefix, DAC_WATCH); + PARAM_CHECK(ret == 0, return ret, "Forbid to watcher parameter %s", keyprefix); + return 0; +} + +void ResetParamSecurityLabel(void) +{ +#ifdef RESET_CHILD_FOR_VERIFY + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace"); +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + paramSpace->securityLabel.cred.pid = getpid(); + paramSpace->securityLabel.cred.uid = geteuid(); + paramSpace->securityLabel.cred.gid = getegid(); + paramSpace->flags |= WORKSPACE_FLAGS_NEED_ACCESS; +#endif +#endif + PARAM_LOGI("ResetParamSecurityLabel g_clientFd: %d ", g_clientFd); + pthread_mutex_lock(&g_clientMutex); + if (g_clientFd != INVALID_SOCKET) { + close(g_clientFd); + g_clientFd = INVALID_SOCKET; + } + pthread_mutex_unlock(&g_clientMutex); +} diff --git a/services/param/linux/param_service.c b/services/param/linux/param_service.c new file mode 100755 index 0000000000000000000000000000000000000000..8576ed9c656424d05a0124045229f7948edeb3b6 --- /dev/null +++ b/services/param/linux/param_service.c @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2021 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 "init_log.h" +#include "init_param.h" +#include "init_utils.h" +#include "loop_event.h" +#include "param_manager.h" +#include "param_message.h" +#include "trigger_manager.h" +#include "securec.h" +#ifdef PARAM_SUPPORT_SELINUX +#include "selinux_parameter.h" +#include +#include +#endif + +static ParamService g_paramService = {}; + +PARAM_STATIC void OnClose(ParamTaskPtr client) +{ + ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(client); + if (client == g_paramService.watcherTask) { + ClearWatchTrigger(watcher, TRIGGER_PARAM_WATCH); + g_paramService.watcherTask = NULL; + } else { + ClearWatchTrigger(watcher, TRIGGER_PARAM_WAIT); + } +} + +static void TimerCallback(const ParamTaskPtr timer, void *context) +{ + UNUSED(context); + UNUSED(timer); + int ret = CheckWatchTriggerTimeout(); + // no wait node + if (ret == 0 && g_paramService.timer != NULL) { + ParamTaskClose(g_paramService.timer); + g_paramService.timer = NULL; + } +} + +static void CheckAndSendTrigger(uint32_t dataIndex, const char *name, const char *value) +{ + WorkSpace *workspace = GetWorkSpaceByName(name); + PARAM_CHECK(workspace != NULL, return, "Failed to get workspace %s ", name); + ParamNode *entry = (ParamNode *)GetTrieNode(workspace, dataIndex); + PARAM_CHECK(entry != NULL, return, "Failed to get data %s ", name); + uint32_t trigger = 1; + if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED) & PARAM_FLAGS_TRIGGED) != PARAM_FLAGS_TRIGGED) { + trigger = (CheckAndMarkTrigger(TRIGGER_PARAM, name) != 0) ? 1 : 0; + } + if (trigger) { + ATOMIC_SYNC_OR_AND_FETCH(&entry->commitId, PARAM_FLAGS_TRIGGED, MEMORY_ORDER_RELEASE); + // notify event to process trigger + PostParamTrigger(EVENT_TRIGGER_PARAM, name, value); + } + + int wait = 1; + if ((ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED) & PARAM_FLAGS_WAITED) != PARAM_FLAGS_WAITED) { + wait = (CheckAndMarkTrigger(TRIGGER_PARAM_WAIT, name) != 0) ? 1 : 0; + } + if (wait) { + ATOMIC_SYNC_OR_AND_FETCH(&entry->commitId, PARAM_FLAGS_WAITED, MEMORY_ORDER_RELEASE); + PostParamTrigger(EVENT_TRIGGER_PARAM_WAIT, name, value); + } + PostParamTrigger(EVENT_TRIGGER_PARAM_WATCH, name, value); +} + +static int SendResponseMsg(ParamTaskPtr worker, const ParamMessage *msg, int result) +{ + ParamResponseMessage *response = NULL; + response = (ParamResponseMessage *)CreateParamMessage(msg->type, msg->key, sizeof(ParamResponseMessage)); + PARAM_CHECK(response != NULL, return PARAM_CODE_ERROR, "Failed to alloc memory for response"); + response->msg.id.msgId = msg->id.msgId; + response->result = result; + response->msg.msgSize = sizeof(ParamResponseMessage); + ParamTaskSendMsg(worker, (ParamMessage *)response); + PARAM_LOGV("Send response msg msgId %d result %d", msg->id.msgId, result); + return 0; +} + +static int SendWatcherNotifyMessage(const TriggerExtInfo *extData, const char *content, uint32_t size) +{ + PARAM_CHECK(content != NULL, return -1, "Invalid content"); + PARAM_CHECK(extData != NULL && extData->stream != NULL, return -1, "Invalid extData"); + uint32_t msgSize = sizeof(ParamMessage) + PARAM_ALIGN(strlen(content) + 1); + ParamMessage *msg = (ParamMessage *)CreateParamMessage(MSG_NOTIFY_PARAM, "*", msgSize); + PARAM_CHECK(msg != NULL, return -1, "Failed to create msg "); + + uint32_t offset = 0; + int ret; + char *tmp = strstr(content, "="); + if (tmp != NULL) { + ret = strncpy_s(msg->key, sizeof(msg->key) - 1, content, tmp - content); + PARAM_CHECK(ret == 0, free(msg); + return -1, "Failed to fill value"); + tmp++; + ret = FillParamMsgContent(msg, &offset, PARAM_VALUE, tmp, strlen(tmp)); + PARAM_CHECK(ret == 0, free(msg); + return -1, "Failed to fill value"); + } else if (content != NULL && strlen(content) > 0) { + ret = FillParamMsgContent(msg, &offset, PARAM_VALUE, content, strlen(content)); + PARAM_CHECK(ret == 0, free(msg); + return -1, "Failed to fill value"); + } + + msg->id.msgId = 0; + if (extData->type == TRIGGER_PARAM_WAIT) { + msg->id.msgId = extData->info.waitInfo.waitId; + } else { + msg->id.msgId = extData->info.watchInfo.watchId; + } + msg->msgSize = sizeof(ParamMessage) + offset; + PARAM_LOGV("SendWatcherNotifyMessage cmd %s, id %d msgSize %d para: %s", + (extData->type == TRIGGER_PARAM_WAIT) ? "wait" : "watcher", + msg->id.msgId, msg->msgSize, content); + ParamTaskSendMsg(extData->stream, msg); + return 0; +} + +static int SystemSetParam(const char *name, const char *value, const ParamSecurityLabel *srcLabel) +{ + PARAM_LOGV("SystemWriteParam name %s value: %s", name, value); + int ctrlService = 0; + int ret = CheckParameterSet(name, value, srcLabel, &ctrlService); + PARAM_CHECK(ret == 0, return ret, "Forbid to set parameter %s", name); + + unsigned int mode = 0; + if (strncmp(name, PARAM_PERSIST_PREFIX, strlen(PARAM_PERSIST_PREFIX)) == 0) { + mode |= LOAD_PARAM_PERSIST; + } + if ((ctrlService & PARAM_CTRL_SERVICE) != PARAM_CTRL_SERVICE) { // ctrl param + uint32_t dataIndex = 0; + ret = WriteParam(name, value, &dataIndex, mode); + PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value); + ret = WritePersistParam(name, value); + PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name); + CheckAndSendTrigger(dataIndex, name, value); + } + return ret; +} + +static int HandleParamSet(const ParamTaskPtr worker, const ParamMessage *msg) +{ + uint32_t offset = 0; + ParamMsgContent *valueContent = GetNextContent(msg, &offset); + PARAM_CHECK(valueContent != NULL, return -1, "Invalid msg for %s", msg->key); + ParamSecurityLabel srcLabel = {0}; + struct ucred cr = {-1, -1, -1}; + socklen_t crSize = sizeof(cr); + if (getsockopt(LE_GetSocketFd(worker), SOL_SOCKET, SO_PEERCRED, &cr, &crSize) < 0) { + PARAM_LOGE("Failed to get opt %d", errno); +#ifndef STARTUP_INIT_TEST + return SendResponseMsg(worker, msg, -1); +#endif + } + srcLabel.sockFd = LE_GetSocketFd(worker); + srcLabel.cred.uid = cr.uid; + srcLabel.cred.pid = cr.pid; + srcLabel.cred.gid = cr.gid; + PARAM_LOGI("Handle set param msgId %d pid %d key: %s", msg->id.msgId, cr.pid, msg->key); + int ret = SystemSetParam(msg->key, valueContent->content, &srcLabel); + return SendResponseMsg(worker, msg, ret); +} + +static int32_t AddWatchNode(struct tagTriggerNode_ *trigger, const struct TriggerExtInfo_ *extInfo) +{ + ParamWatcher *watcher = NULL; + if (extInfo != NULL && extInfo->stream != NULL) { + watcher = (ParamWatcher *)ParamGetTaskUserData(extInfo->stream); + } + PARAM_CHECK(watcher != NULL, return -1, "Failed to get param watcher data"); + if (extInfo->type == TRIGGER_PARAM_WAIT) { + WaitNode *node = (WaitNode *)trigger; + OH_ListInit(&node->item); + node->timeout = extInfo->info.waitInfo.timeout; + node->stream = extInfo->stream; + node->waitId = extInfo->info.waitInfo.waitId; + OH_ListAddTail(&watcher->triggerHead, &node->item); + } else { + WatchNode *node = (WatchNode *)trigger; + OH_ListInit(&node->item); + node->watchId = extInfo->info.watchInfo.watchId; + OH_ListAddTail(&watcher->triggerHead, &node->item); + } + return 0; +} + +static TriggerNode *AddWatcherTrigger(int triggerType, const char *condition, const TriggerExtInfo *extData) +{ + TriggerWorkSpace *workSpace = GetTriggerWorkSpace(); + TriggerHeader *header = (TriggerHeader *)&workSpace->triggerHead[extData->type]; + return header->addTrigger(workSpace, condition, extData); +} + +static int32_t ExecuteWatchTrigger_(const struct tagTriggerNode_ *trigger, const char *content, uint32_t size) +{ + TriggerExtInfo extData = {}; + extData.type = trigger->type; + if (trigger->type == TRIGGER_PARAM_WAIT) { + WaitNode *node = (WaitNode *)trigger; + extData.stream = node->stream; + extData.info.waitInfo.waitId = node->waitId; + extData.info.waitInfo.timeout = node->timeout; + } else { + WatchNode *node = (WatchNode *)trigger; + extData.stream = g_paramService.watcherTask; + extData.info.watchInfo.watchId = node->watchId; + } + if (content == NULL) { + return SendWatcherNotifyMessage(&extData, "", 0); + } + return SendWatcherNotifyMessage(&extData, content, size); +} + +static int HandleParamWaitAdd(const ParamTaskPtr worker, const ParamMessage *msg) +{ + PARAM_CHECK(msg != NULL, return -1, "Invalid message"); + uint32_t offset = 0; +#ifndef STARTUP_INIT_TEST + uint32_t timeout = DEFAULT_PARAM_WAIT_TIMEOUT; +#else + uint32_t timeout = 0; +#endif + ParamMsgContent *valueContent = GetNextContent(msg, &offset); + PARAM_CHECK(valueContent != NULL, return -1, "Invalid msg"); + PARAM_CHECK(valueContent->contentSize <= PARAM_CONST_VALUE_LEN_MAX, return -1, "Invalid msg"); + ParamMsgContent *timeoutContent = GetNextContent(msg, &offset); + if (timeoutContent != NULL) { + timeout = *((uint32_t *)(timeoutContent->content)); + } + + PARAM_LOGV("HandleParamWaitAdd name %s timeout %d", msg->key, timeout); + TriggerExtInfo extData = {}; + extData.addNode = AddWatchNode; + extData.type = TRIGGER_PARAM_WAIT; + extData.stream = worker; + extData.info.waitInfo.waitId = msg->id.watcherId; + extData.info.waitInfo.timeout = timeout; + // first check match, if match send response to client + ParamNode *param = SystemCheckMatchParamWait(msg->key, valueContent->content); + if (param != NULL) { + SendWatcherNotifyMessage(&extData, param->data, param->valueLength); + return 0; + } + + uint32_t buffSize = strlen(msg->key) + valueContent->contentSize + 1 + 1; + char *condition = calloc(1, buffSize); + PARAM_CHECK(condition != NULL, return -1, "Failed to create condition for %s", msg->key); + int ret = sprintf_s(condition, buffSize - 1, "%s=%s", msg->key, valueContent->content); + PARAM_CHECK(ret > EOK, free(condition); + return -1, "Failed to copy name for %s", msg->key); + TriggerNode *trigger = AddWatcherTrigger(TRIGGER_PARAM_WAIT, condition, &extData); + PARAM_CHECK(trigger != NULL, free(condition); + return -1, "Failed to add trigger for %s", msg->key); + free(condition); + if (g_paramService.timer == NULL) { + ret = ParamTimerCreate(&g_paramService.timer, TimerCallback, &g_paramService); + PARAM_CHECK(ret == 0, return 0, "Failed to create timer %s", msg->key); + ret = ParamTimerStart(g_paramService.timer, MS_UNIT, (uint64_t)-1); + PARAM_CHECK(ret == 0, + ParamTaskClose(g_paramService.timer); + g_paramService.timer = NULL; + return 0, "Failed to set timer %s", msg->key); + } + return 0; +} + +static int HandleParamWatcherAdd(const ParamTaskPtr worker, const ParamMessage *msg) +{ + PARAM_CHECK(msg != NULL, return -1, "Invalid message"); + PARAM_CHECK((g_paramService.watcherTask == NULL) || + (g_paramService.watcherTask == worker), return -1, "Invalid watcher worker"); + g_paramService.watcherTask = worker; + TriggerExtInfo extData = {}; + extData.type = TRIGGER_PARAM_WATCH; + extData.addNode = AddWatchNode; + extData.stream = worker; + extData.info.watchInfo.watchId = msg->id.watcherId; + TriggerNode *trigger = AddWatcherTrigger(TRIGGER_PARAM_WATCH, msg->key, &extData); + if (trigger == NULL) { + PARAM_LOGE("Failed to add trigger for %s", msg->key); + return SendResponseMsg(worker, msg, -1); + } + PARAM_LOGV("HandleParamWatcherAdd name %s watcher: %d", msg->key, msg->id.watcherId); + return SendResponseMsg(worker, msg, 0); +} + +static int HandleParamWatcherDel(const ParamTaskPtr worker, const ParamMessage *msg) +{ + PARAM_CHECK(msg != NULL, return -1, "Invalid message"); + PARAM_LOGV("HandleParamWatcherDel name %s watcher: %d", msg->key, msg->id.watcherId); + DelWatchTrigger(TRIGGER_PARAM_WATCH, (const void *)&msg->id.watcherId); + return SendResponseMsg(worker, msg, 0); +} + +static int HandleParamSave(const ParamTaskPtr worker, const ParamMessage *msg) +{ + PARAM_CHECK(msg != NULL, return -1, "Invalid message"); + struct ucred cr = {-1, -1, -1}; + socklen_t crSize = sizeof(cr); + if (getsockopt(LE_GetSocketFd(worker), SOL_SOCKET, SO_PEERCRED, &cr, &crSize) < 0) { + PARAM_LOGE("Failed to get opt %d", errno); +#ifndef STARTUP_INIT_TEST + return SendResponseMsg(worker, msg, -1); +#endif + } + PARAM_LOGI("process info:pid = %d, uid = %d, gid = %d", cr.pid, cr.uid, cr.gid); + int ret = CheckIfUidInGroup(cr.uid, "servicectrl"); + PARAM_CHECK(ret == 0, return SendResponseMsg(worker, msg, -1), "Failed to process save parameters : ret %d", ret); + CheckAndSavePersistParam(); + return SendResponseMsg(worker, msg, 0); +} + +PARAM_STATIC int ProcessMessage(const ParamTaskPtr worker, const ParamMessage *msg) +{ + PARAM_CHECK((msg != NULL) && (msg->msgSize >= sizeof(ParamMessage)), return -1, "Invalid msg"); + PARAM_CHECK(worker != NULL, return -1, "Invalid worker"); + int ret = PARAM_CODE_INVALID_PARAM; + switch (msg->type) { + case MSG_SET_PARAM: + ret = HandleParamSet(worker, msg); + break; + case MSG_WAIT_PARAM: + ret = HandleParamWaitAdd(worker, msg); + break; + case MSG_ADD_WATCHER: + ret = HandleParamWatcherAdd(worker, msg); + break; + case MSG_DEL_WATCHER: + ret = HandleParamWatcherDel(worker, msg); + break; + case MSG_SAVE_PARAM: + ret = HandleParamSave(worker, msg); + break; + default: + break; + } + PARAM_CHECK(ret == 0, return -1, "Failed to process message ret %d", ret); + return 0; +} + +PARAM_STATIC int OnIncomingConnect(LoopHandle loop, TaskHandle server) +{ + ParamStreamInfo info = {}; +#ifdef STARTUP_INIT_TEST + info.flags = PARAM_TEST_FLAGS; +#endif + info.server = NULL; + info.close = OnClose; + info.recvMessage = ProcessMessage; + info.incomingConnect = NULL; + ParamTaskPtr client = NULL; + int ret = ParamStreamCreate(&client, server, &info, sizeof(ParamWatcher)); + PARAM_CHECK(ret == 0, return -1, "Failed to create client"); + + ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(client); + PARAM_CHECK(watcher != NULL, return -1, "Failed to get watcher"); + OH_ListInit(&watcher->triggerHead); + watcher->stream = client; +#ifdef STARTUP_INIT_TEST + g_paramService.watcherTask = client; +#endif + return 0; +} + +static void LoadSelinuxLabel(const char *op) +{ + // load security label +#ifdef PARAM_SUPPORT_SELINUX + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); + if (ops != NULL && ops->securityGetLabel != NULL) { + ops->securityGetLabel(op); + } +#endif +} + +int InitParamService(void) +{ +#ifdef INIT_ASAN + // Because the old paramWorkSpace' memory is malloced in libc.so's construction function, + // which is before the asan enabled, some error will happen if the memory free after with asan detection. + // So, we just reset the flag of the old paramWorkSpace to drop it. + PARAM_LOGI("INIT_ASAN is defined, begin to reset global paramWorkSpace"); + ParamWorkSpace *paramWorkSpace = GetParamWorkSpace(); + paramWorkSpace->flags = 0; +#endif + PARAM_LOGI("InitParamService pipe: %s.", PIPE_NAME); + CheckAndCreateDir(PIPE_NAME); + CheckAndCreateDir(PARAM_STORAGE_PATH"/"); + // param space + PARAM_WORKSPACE_OPS ops = {0}; + ops.updaterMode = InUpdaterMode(); + // init open log + ops.logFunc = InitLog; + ops.getServiceGroupIdByPid = GetServiceGroupIdByPid; +#ifdef PARAM_SUPPORT_SELINUX + ops.setfilecon = setfilecon; +#endif + int ret = InitParamWorkSpace(0, &ops); + PARAM_CHECK(ret == 0, return ret, "Init parameter workspace fail"); + ret = InitPersistParamWorkSpace(); + PARAM_CHECK(ret == 0, return ret, "Init persist parameter workspace fail"); + // param server + if (g_paramService.serverTask == NULL) { + ParamStreamInfo info = {}; + info.server = PIPE_NAME; + info.close = NULL; + info.recvMessage = NULL; + info.incomingConnect = OnIncomingConnect; + ret = ParamServerCreate(&g_paramService.serverTask, &info); + PARAM_CHECK(ret == 0, return ret, "Failed to create server"); + } + + // init trigger space + ret = InitTriggerWorkSpace(); + PARAM_CHECK(ret == 0, return ret, "Failed to init trigger"); + RegisterTriggerExec(TRIGGER_PARAM_WAIT, ExecuteWatchTrigger_); + RegisterTriggerExec(TRIGGER_PARAM_WATCH, ExecuteWatchTrigger_); + + return 0; +} + +void LoadSpecialParam(void) +{ + // read param area size from cfg and save to dac + LoadParamAreaSize(); + // read selinux label + LoadSelinuxLabel("init"); + // from cmdline + LoadParamFromCmdLine(); + // from build + LoadParamFromBuild(); +} + +int StartParamService(void) +{ +#ifdef STARTUP_INIT_TEST + return 0; +#endif + // read selinux label + LoadSelinuxLabel("permission"); + return ParamServiceStart(); +} + +void StopParamService(void) +{ + PARAM_LOGI("StopParamService."); + ClosePersistParamWorkSpace(); + CloseParamWorkSpace(); + CloseTriggerWorkSpace(); + ParamTaskClose(g_paramService.serverTask); + g_paramService.serverTask = NULL; + ParamServiceStop(); +} + +int SystemWriteParam(const char *name, const char *value) +{ + return SystemSetParam(name, value, GetParamSecurityLabel()); +} + +#ifdef STARTUP_INIT_TEST +ParamService *GetParamService() +{ + return &g_paramService; +} +#endif diff --git a/services/param/liteos/BUILD.gn b/services/param/liteos/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..bffab2ad21caa1e808d6b2ed6bbef59f662c6751 --- /dev/null +++ b/services/param/liteos/BUILD.gn @@ -0,0 +1,162 @@ +# 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/begetd.gni") + +param_include_dirs = [ + "//base/hiviewdfx/hilog_lite/interfaces/native/kits", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/adapter", + "//base/startup/init/services/param/base", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/loopevent/include", + "//third_party/cJSON", + "//commonlibrary/utils_lite/include", +] + +param_build_defines = [ + "_GNU_SOURCE", + "INCREMENTAL_VERSION=\"${ohos_version}\"", + "BUILD_TYPE=\"${ohos_build_type}\"", + "BUILD_USER=\"${ohos_build_user}\"", + "BUILD_TIME=\"${ohos_build_time}\"", + "BUILD_HOST=\"${ohos_build_host}\"", + "BUILD_ROOTHASH=\"${ohos_build_roothash}\"", +] + +action("lite_ohos_param_to") { + script = "//base/startup/init/scripts/param_cfg_to_code.py" + args = [ + "--source", + rebase_path( + "//base/startup/init/services/etc_lite/param/ohos_const/ohos.para"), + "--source", + rebase_path("$ohos_product_adapter_dir/utils/sys_param/vendor.para"), + "--source", + rebase_path("//base/startup/init/services/etc/param/ohos.para"), + "--dest_dir", + rebase_path("$root_out_dir/gen/init/"), + ] + outputs = [ "$target_gen_dir/${target_name}_param_cfg_to_code.log" ] +} + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/service/param/include", + ] +} + +base_sources = [ + "//base/startup/init/services/param/base/param_base.c", + "//base/startup/init/services/param/base/param_comm.c", + "//base/startup/init/services/param/base/param_trie.c", + "//base/startup/init/services/param/liteos/param_client.c", + "//base/startup/init/services/param/liteos/param_litedac.c", + "//base/startup/init/services/param/liteos/param_osadp.c", + "//base/startup/init/services/param/manager/param_manager.c", + "//base/startup/init/services/param/manager/param_persist.c", + "//base/startup/init/services/utils/init_hashmap.c", + "//base/startup/init/services/utils/list.c", +] + +static_library("param_init_lite") { + defines = [] + deps = [] + sources = [ + "//base/startup/init/services/param/manager/param_manager.c", + "//base/startup/init/services/param/manager/param_server.c", + ] + include_dirs = param_include_dirs + defines += param_build_defines + public_configs = [ ":exported_header_files" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + if (ohos_kernel_type == "liteos_a") { + sources += [ + "//base/startup/init/services/param/liteos/param_persistadp.c", + "//base/startup/init/services/param/liteos/param_service.c", + "//base/startup/init/services/param/manager/param_persist.c", + ] + defines += [ + "WORKSPACE_AREA_NEED_MUTEX", + "PARAM_PERSIST_SAVE_MUTEX", + "PARAMWORKSPACE_NEED_MUTEX", + "__LITEOS_A__", + "PARAM_SUPPORT_CYCLE_CHECK", + ] + } + if (defined(init_lite_memory_size)) { + defines += [ "PARAM_WORKSPACE_MAX=${init_lite_memory_size}" ] + } +} + +static_library("param_client_lite") { + sources = base_sources + include_dirs = param_include_dirs + defines = param_build_defines + public_configs = [ ":exported_header_files" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + if (init_lite_no_log) { + defines += [ "INIT_NO_LOG" ] + } else { + sources += [ "//base/startup/init/services/log/init_commlog.c" ] + } + + if (ohos_kernel_type == "liteos_a") { + sources += + [ "//base/startup/init/services/param/liteos/param_persistadp.c" ] + defines += [ + "__LITEOS_A__", + "WORKSPACE_AREA_NEED_MUTEX", + "PARAM_PERSIST_SAVE_MUTEX", + "PARAMWORKSPACE_NEED_MUTEX", + "PARAM_SUPPORT_CYCLE_CHECK", + ] + } else if (ohos_kernel_type == "liteos_m") { + sources += [ + "//base/startup/init/services/param/liteos/param_hal.c", + "//base/startup/init/services/param/liteos/param_service.c", + "//base/startup/init/services/param/manager/param_server.c", + ] + if (init_lite_use_posix_file_api) { + defines += [ "PARAM_SUPPORT_POSIX" ] + } + defines += [ + "__LITEOS_M__", + "WORKSPACE_AREA_NEED_MUTEX", + "PARAM_PERSIST_SAVE_MUTEX", + "PARAMWORKSPACE_NEED_MUTEX", + ] + if (config_ohos_startup_init_lite_data_path != "") { + defines += [ "DATA_PATH=\"${config_ohos_startup_init_lite_data_path}\"" ] + } + if (init_feature_begetctl_liteos) { + deps = [ ":lite_ohos_param_to" ] + include_dirs += [ "$root_out_dir/gen/init" ] + defines += [ "PARAM_LOAD_CFG_FROM_CODE" ] + } + + if (defined(init_lite_memory_size)) { + defines += [ "PARAM_WORKSPACE_MAX=${init_lite_memory_size}" ] + } + } +} diff --git a/services/param/liteos/param_client.c b/services/param/liteos/param_client.c new file mode 100644 index 0000000000000000000000000000000000000000..4569fd8a2c0af50561bc65e4a3235ddda55c3a8a --- /dev/null +++ b/services/param/liteos/param_client.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2021 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 "init_log.h" +#include "init_param.h" +#include "param_init.h" +#include "param_manager.h" + +#define MIN_SLEEP (100 * 1000) + +#ifdef __LITEOS_A__ +static int g_flags = 0; +__attribute__((constructor)) static int ClientInit(void) +{ + if (PARAM_TEST_FLAG(g_flags, WORKSPACE_FLAGS_INIT)) { + return 0; + } + EnableInitLog(INIT_INFO); + PARAM_LOGV("InitParamClient"); + int ret = InitParamWorkSpace(1, NULL); + PARAM_CHECK(ret == 0, return -1, "Failed to init param workspace"); + PARAM_SET_FLAG(g_flags, WORKSPACE_FLAGS_INIT); + // init persist to save + InitPersistParamWorkSpace(); + return 0; +} + +__attribute__((destructor)) static void ClientDeinit(void) +{ + if (PARAM_TEST_FLAG(g_flags, WORKSPACE_FLAGS_INIT)) { + CloseParamWorkSpace(); + } + PARAM_SET_FLAG(g_flags, 0); +} +#endif + +int SystemSetParameter(const char *name, const char *value) +{ + PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value %s", name); + int ctrlService = 0; + int ret = CheckParameterSet(name, value, GetParamSecurityLabel(), &ctrlService); + PARAM_CHECK(ret == 0, return ret, "Forbid to set parameter %s", name); + PARAM_LOGV("SystemSetParameter name %s value: %s ctrlService %d", name, value, ctrlService); + if ((ctrlService & PARAM_CTRL_SERVICE) != PARAM_CTRL_SERVICE) { // ctrl param + uint32_t dataIndex = 0; + ret = WriteParam(name, value, &dataIndex, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value); + ret = WritePersistParam(name, value); + PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name); + } else { + PARAM_LOGE("SystemSetParameter can not support service ctrl parameter name %s", name); + } + return ret; +} + +int SystemWaitParameter(const char *name, const char *value, int32_t timeout) +{ + PARAM_CHECK(name != NULL && value != NULL, return PARAM_CODE_INVALID_PARAM, + "SystemWaitParameter failed! name is: %s, errNum is: %d", name, PARAM_CODE_INVALID_PARAM); + long long globalCommit = 0; + // first check permission + int ret = CheckParamPermission(GetParamSecurityLabel(), name, DAC_READ); + PARAM_CHECK(ret == 0, return ret, "SystemWaitParameter failed! name is: %s, errNum is: %d", name, ret); + uint32_t diff = 0; + struct timespec startTime = {0}; + if (timeout <= 0) { + timeout = DEFAULT_PARAM_WAIT_TIMEOUT; + } + (void)clock_gettime(CLOCK_MONOTONIC, &startTime); + do { + long long commit = GetSystemCommitId(); + if (commit != globalCommit) { + ParamNode *param = SystemCheckMatchParamWait(name, value); + if (param != NULL) { + ret = 0; + break; + } + } + globalCommit = commit; + + usleep(MIN_SLEEP); + struct timespec finishTime = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &finishTime); + diff = IntervalTime(&finishTime, &startTime); + if (diff >= timeout) { + ret = PARAM_CODE_TIMEOUT; + break; + } + } while (1); + PARAM_LOGI("SystemWaitParameter name %s value: %s diff %d timeout %d", name, value, diff, diff); + if (ret != 0) { + PARAM_LOGE("SystemWaitParameter failed! name is:%s, errNum is %d", name, ret); + } + return ret; +} + +int SystemSaveParameters(void) +{ + CheckAndSavePersistParam(); + return PARAM_CODE_SUCCESS; +} + +int WatchParamCheck(const char *keyprefix) +{ + (void)keyprefix; + return PARAM_CODE_NOT_SUPPORT; +} + +int SystemCheckParamExist(const char *name) +{ + return SysCheckParamExist(name); +} diff --git a/services/param/liteos/param_hal.c b/services/param/liteos/param_hal.c new file mode 100644 index 0000000000000000000000000000000000000000..6f54489ffad6fefdacc124f15b7373f81e06dc08 --- /dev/null +++ b/services/param/liteos/param_hal.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2021 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 "init_utils.h" +#include "param_manager.h" +#include "param_persist.h" +#include "param_utils.h" +#include "securec.h" +#include "utils_file.h" + +// for linux, no mutex +static ParamMutex g_saveMutex = {0}; +#ifdef PARAM_SUPPORT_POSIX +#define MODE_READ O_RDONLY +#define MODE_APPEND (O_RDWR | O_CREAT | O_APPEND) +#define MODE_CREATE (O_RDWR | O_CREAT | O_TRUNC) +#else +#define MODE_READ O_RDONLY_FS +#define MODE_APPEND (O_RDWR_FS | O_CREAT_FS | O_APPEND_FS) +#define MODE_CREATE (O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS) +#endif + +static int ParamFileOpen(const char* path, int oflag, int mode) +{ +#ifdef PARAM_SUPPORT_POSIX + return open(path, oflag, mode); +#else + return UtilsFileOpen(path, oflag, mode); +#endif +} + +static int ParamFileClose(int fd) +{ +#ifdef PARAM_SUPPORT_POSIX + return close(fd); +#else + return UtilsFileClose(fd); +#endif +} + +static int ParamFileRead(int fd, char* buf, unsigned int len) +{ +#ifdef PARAM_SUPPORT_POSIX + return read(fd, buf, len); +#else + return UtilsFileRead(fd, buf, len); +#endif +} + +static int ParamFileWrite(int fd, const char* buf, unsigned int len) +{ +#ifdef PARAM_SUPPORT_POSIX + return write(fd, buf, len); +#else + return UtilsFileWrite(fd, buf, len); +#endif +} + +static int ParamFileDelete(const char* path) +{ +#ifdef PARAM_SUPPORT_POSIX + return unlink(path); +#else + return UtilsFileDelete(path); +#endif +} + +static int ParamFileStat(const char* path, unsigned int* fileSize) +{ +#ifdef PARAM_SUPPORT_POSIX + int fd = open(path, O_RDONLY); + if (fd < 0) { + return -1; + } + *fileSize = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + close(fd); + return 0; +#else + return UtilsFileStat(path, fileSize); +#endif +} + +static void ParamFileSync(int ft) +{ +#ifdef PARAM_SUPPORT_POSIX + fsync(ft); +#else + (void)ft; +#endif +} + +static int LoadOnePersistParam_(const uint32_t *context, const char *name, const char *value) +{ + (void)context; + uint32_t dataIndex = 0; + int ret = WriteParam(name, value, &dataIndex, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to write param %d name:%s %s", ret, name, value); + return 0; +} + +static int LoadPersistParam(void) +{ + const char *path = PARAM_PERSIST_SAVE_TMP_PATH; + CheckAndCreateDir(path); + char *buffer = NULL; + int fd = -1; + uint32_t paramNum = 0; + do { + fd = ParamFileOpen(path, MODE_READ, 0); + if (fd < 0) { + path = PARAM_PERSIST_SAVE_PATH; + fd = ParamFileOpen(path, MODE_READ, 0); + PARAM_LOGI("LoadPersistParam open file %s", path); + } + PARAM_CHECK(fd >= 0, break, "No valid persist parameter file %s", path); + // read file + uint32_t fileSize = 0; + int ret = ParamFileStat(path, &fileSize); + PARAM_CHECK(ret == 0, break, "Failed to get file state %s", path); + buffer = calloc(fileSize, sizeof(char)); + PARAM_CHECK(buffer != NULL, break, "Failed to get file"); + ret = ParamFileRead(fd, buffer, fileSize); + PARAM_CHECK(ret >= 0, break, "Failed to read file %s", path); + + uint32_t currLen = 0; + char *tmp = buffer; + while (currLen < fileSize) { + if (buffer[currLen] == '\n') { // split line + buffer[currLen] = '\0'; + ret = SplitParamString(tmp, NULL, 0, LoadOnePersistParam_, NULL); + PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buffer); + paramNum++; + if (currLen + 1 >= fileSize) { + break; + } + tmp = buffer + currLen + 1; + } + currLen++; + } + } while (0); + if (fd > 0) { + ParamFileClose(fd); + } + if (buffer != NULL) { + free(buffer); + } + PARAM_LOGI("LoadPersistParam paramNum %d", paramNum); + return 0; +} + +static int PersistWrite(int fd, const char *name, const char *value) +{ + int ret = ParamFileWrite(fd, name, strlen(name)); + if (ret <= 0) { + PARAM_LOGE("Failed to save persist param %s", name); + } + ret = ParamFileWrite(fd, "=", strlen("=")); + if (ret <= 0) { + PARAM_LOGE("Failed to save persist param %s", name); + } + ret = ParamFileWrite(fd, value, strlen(value)); + if (ret <= 0) { + PARAM_LOGE("Failed to save persist param %s", name); + } + ret = ParamFileWrite(fd, "\n", strlen("\n")); + if (ret <= 0) { + PARAM_LOGE("Failed to save persist param %s", name); + } + return 0; +} + +static int SavePersistParam(const char *name, const char *value) +{ + ParamMutexPend(&g_saveMutex); + int ret = -1; + int fd = ParamFileOpen(PARAM_PERSIST_SAVE_PATH, MODE_APPEND, 0); + if (fd > 0) { + ret = PersistWrite(fd, name, value); + ParamFileSync(fd); + ParamFileClose(fd); + } + if (ret != 0) { + PARAM_LOGE("SavePersistParam %s errno %d", name, errno); + } + ParamMutexPost(&g_saveMutex); + return ret; +} + +static int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle) +{ + ParamMutexPend(&g_saveMutex); + int fd = ParamFileOpen(PARAM_PERSIST_SAVE_PATH, MODE_CREATE, 0); + if (fd < 0) { + ParamMutexPost(&g_saveMutex); + PARAM_LOGE("Open file %s fail error %d", PARAM_PERSIST_SAVE_PATH, errno); + return -1; + } + *handle = (PERSIST_SAVE_HANDLE)fd; + return 0; +} + +static int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle, const char *name, const char *value) +{ + int fd = (int)handle; + int ret = PersistWrite(fd, name, value); + PARAM_CHECK(ret == 0, return -1, "Failed to write param %s", name); + PARAM_LOGV("BatchSavePersistParam %s=%s", name, value); + return 0; +} + +static void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle) +{ + int ret; + int fd = (int)handle; + ParamFileSync(fd); + ret = ParamFileClose(fd); + ParamMutexPost(&g_saveMutex); + PARAM_CHECK(ret == 0, return, "BatchSavePersistParamEnd fail error %d", errno); +} + +int RegisterPersistParamOps(PersistParamOps *ops) +{ + ParamMutexCreate(&g_saveMutex); + PARAM_CHECK(ops != NULL, return -1, "Invalid ops"); + ops->save = SavePersistParam; + ops->load = LoadPersistParam; + ops->batchSaveBegin = BatchSavePersistParamBegin; + ops->batchSave = BatchSavePersistParam; + ops->batchSaveEnd = BatchSavePersistParamEnd; + return 0; +} diff --git a/services/param/liteos/param_litedac.c b/services/param/liteos/param_litedac.c new file mode 100644 index 0000000000000000000000000000000000000000..ef9de763fc00705d710d4451a4bbf53b6304d724 --- /dev/null +++ b/services/param/liteos/param_litedac.c @@ -0,0 +1,83 @@ +/* + * 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 "param_osadp.h" +#include "param_security.h" +#include "securec.h" + +static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit) +{ + UNUSED(isInit); + PARAM_CHECK(security != NULL, return -1, "Invalid security"); +#if defined __LITEOS_A__ + security->cred.pid = getpid(); + security->cred.uid = getuid(); + security->cred.gid = 0; +#else + security->cred.pid = 0; + security->cred.uid = 0; + security->cred.gid = 0; +#endif + security->flags[PARAM_SECURITY_DAC] |= LABEL_CHECK_IN_ALL_PROCESS; + return 0; +} + +static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel) +{ + (void)srcLabel; + return 0; +} + +static int DacGetParamSecurityLabel(const char *path) +{ + UNUSED(path); + return 0; +} + +static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags) +{ + UNUSED(flags); + PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param"); + return 0; +} + +static int LiteDacCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ + UNUSED(labelIndex); + UNUSED(srcLabel); + UNUSED(name); + UNUSED(mode); +#if defined(__LITEOS_A__) + uid_t uid = getuid(); + return uid <= SYS_UID_INDEX ? DAC_RESULT_PERMISSION : DAC_RESULT_FORBIDED; +#endif + return DAC_RESULT_PERMISSION; +} + +INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit) +{ + PARAM_CHECK(ops != NULL, return -1, "Invalid param"); + PARAM_LOGV("RegisterSecurityDacOps %d", isInit); + int ret = strcpy_s(ops->name, sizeof(ops->name), "dac"); + ops->securityGetLabel = NULL; + ops->securityInitLabel = InitLocalSecurityLabel; + ops->securityCheckFilePermission = CheckFilePermission; + ops->securityCheckParamPermission = LiteDacCheckParamPermission; + ops->securityFreeLabel = FreeLocalSecurityLabel; + if (isInit) { + ops->securityGetLabel = DacGetParamSecurityLabel; + } + return ret; +} diff --git a/services/param/liteos/param_osadp.c b/services/param/liteos/param_osadp.c new file mode 100644 index 0000000000000000000000000000000000000000..2c39ae4db5a49c9d73aec07d9d4f0592511494fa --- /dev/null +++ b/services/param/liteos/param_osadp.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2021-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 "param_osadp.h" + +#include +#include +#include +#include +#ifdef __LITEOS_A__ +#include +#include +#include +#else +#include "los_task.h" +#include "los_mux.h" +#endif +#include +#include +#include +#include +#include +#include + +#include "param_security.h" +#include "securec.h" + +#define NSEC_PER_MSEC 1000000LL +#define MSEC_PER_SEC 1000LL + +static void TimerHandle(union sigval v) +{ + ParamTimer *timer = (ParamTimer *)v.sival_ptr; + PARAM_CHECK(timer != NULL, return, "Invalid timer"); + if (timer->timeProcessor != NULL) { + timer->timeProcessor(timer, timer->context); + } +} + +static void SetTimeSpec(struct timespec *ts, int64_t msec) +{ + ts->tv_sec = msec / MSEC_PER_SEC; // 1000LL ms --> m + ts->tv_nsec = (msec - ts->tv_sec * MSEC_PER_SEC) * NSEC_PER_MSEC; +} + +static int StartTimer(const ParamTimer *paramTimer, int64_t whenMsec, int64_t repeat) +{ + UNUSED(repeat); + struct itimerspec ts; + SetTimeSpec(&ts.it_value, whenMsec); + SetTimeSpec(&ts.it_interval, whenMsec); + int32_t ret = timer_settime(paramTimer->timerId, 0, &ts, NULL); + if (ret < 0) { + PARAM_LOGE("Failed to start timer"); + return -1; + } + return 0; +} + +int ParamTimerCreate(ParamTaskPtr *timer, ProcessTimer process, void *context) +{ + PARAM_CHECK(timer != NULL && process != NULL, return -1, "Invalid timer"); + ParamTimer *paramTimer = malloc(sizeof(ParamTimer)); + PARAM_CHECK(paramTimer != NULL, return -1, "Failed to create timer"); + paramTimer->timeProcessor = process; + paramTimer->context = context; + + struct sigevent evp; + (void)memset_s(&evp, sizeof(evp), 0, sizeof(evp)); + evp.sigev_value.sival_ptr = paramTimer; + evp.sigev_notify = SIGEV_THREAD; + evp.sigev_notify_function = TimerHandle; + int32_t ret = timer_create(CLOCK_REALTIME, &evp, ¶mTimer->timerId); + if (ret < 0) { + PARAM_LOGE("Failed to create timer"); + free(paramTimer); + return -1; + } + *timer = paramTimer; + return 0; +} + +int ParamTimerStart(const ParamTaskPtr timer, uint64_t timeout, uint64_t repeat) +{ + PARAM_CHECK(timer != NULL, return -1, "Invalid timer"); + ParamTimer *paramTimer = (ParamTimer *)timer; + PARAM_LOGV("ParamTimerStart timeout %llu ", timeout); + int32_t ret = StartTimer(paramTimer, timeout, repeat); + PARAM_CHECK(ret >= 0, return -1, "Failed to start timer"); + return 0; +} + +void ParamTimerClose(ParamTaskPtr timer) +{ + PARAM_CHECK(timer != NULL, return, "Invalid timer"); + ParamTimer *paramTimer = (ParamTimer *)timer; + int32_t ret = timer_delete(paramTimer->timerId); + if (ret < 0) { + PARAM_LOGE("Failed to delete timer, errno:%d", errno); + } + free(paramTimer); +} + +#ifdef __LITEOS_A__ +INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly) +{ + PARAM_CHECK(fileName != NULL && handle != NULL, return NULL, "Invalid filename or handle"); + int mode = readOnly ? O_RDONLY : O_CREAT | O_RDWR; + void *areaAddr = NULL; + if (!readOnly) { + int fd = open(fileName, mode, S_IRWXU | S_IRWXG | S_IROTH); + PARAM_CHECK(fd >= 0, return NULL, "Open file %s mode %x fail error %d", fileName, mode, errno); + close(fd); + } + key_t key = ftok(fileName, 0x03); // 0x03 flags for shmget + PARAM_CHECK(key != -1, return NULL, "Invalid errno %d key for %s", errno, fileName); + handle->shmid = shmget(key, spaceSize, IPC_CREAT | IPC_EXCL | 0666); // 0666 + if (handle->shmid == -1) { + handle->shmid = shmget(key, spaceSize, 0); // 0666 + } + PARAM_CHECK(handle->shmid != -1, return NULL, "Invalid shmId errno %d for %s", errno, fileName); + areaAddr = (void *)shmat(handle->shmid, NULL, 0); + return areaAddr; +} + +INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize) +{ + PARAM_CHECK(mem != NULL && handle != NULL, return, "Invalid mem or handle"); + shmdt(mem); + shmctl(handle->shmid, IPC_RMID, NULL); +} + +INIT_LOCAL_API void paramMutexEnvInit(void) +{ + return; +} + +INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlockattr_t rwlockatt; + pthread_rwlockattr_init(&rwlockatt); + pthread_rwlockattr_setpshared(&rwlockatt, PTHREAD_PROCESS_SHARED); + pthread_rwlock_init(&lock->rwlock, &rwlockatt); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlock_wrlock(&lock->rwlock); + return 0; +} +INIT_LOCAL_API int ParamRWMutexRDLock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlock_rdlock(&lock->rwlock); + return 0; +} +INIT_LOCAL_API int ParamRWMutexUnlock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + pthread_rwlock_unlock(&lock->rwlock); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexDelete(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + uint32_t ret = pthread_rwlock_destroy(&lock->rwlock); + PARAM_CHECK(ret == 0, return -1, "Failed to mutex lock ret %d", ret); + return 0; +} + +INIT_LOCAL_API int ParamMutexCreate(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex"); + pthread_mutexattr_t mutexattr; + pthread_mutexattr_init(&mutexattr); + pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&mutex->mutex, &mutexattr); + return 0; +} +INIT_LOCAL_API int ParamMutexPend(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex"); + if (pthread_mutex_lock(&mutex->mutex) != 0) { + PARAM_LOGE("Failed to batch begin to save param errno %d", errno); + return errno; + } + return 0; +} +INIT_LOCAL_API int ParamMutexPost(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex"); + pthread_mutex_unlock(&mutex->mutex); + return 0; +} + +INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid lock"); + uint32_t ret = pthread_mutex_destroy(&mutex->mutex); + PARAM_CHECK(ret == 0, return -1, "Failed to mutex lock ret %d", ret); + return 0; +} +#endif + +#ifdef __LITEOS_M__ +__attribute__((weak)) void* GetSysParamMem(uint32_t spaceSize) +{ + return malloc(spaceSize); +} + +__attribute__((weak)) void FreeSysParamMem(void *mem) +{ + if (mem == NULL) { + return; + } + free(mem); +} + +INIT_LOCAL_API void *GetSharedMem(const char *fileName, MemHandle *handle, uint32_t spaceSize, int readOnly) +{ + PARAM_CHECK(spaceSize <= PARAM_WORKSPACE_MAX, return NULL, "Invalid spaceSize %u", spaceSize); + UNUSED(fileName); + UNUSED(handle); + UNUSED(readOnly); + return GetSysParamMem(spaceSize); +} + +INIT_LOCAL_API void FreeSharedMem(const MemHandle *handle, void *mem, uint32_t dataSize) +{ + PARAM_CHECK(mem != NULL && handle != NULL, return, "Invalid mem or handle"); + UNUSED(handle); + UNUSED(dataSize); + FreeSysParamMem(mem); +} + +INIT_LOCAL_API void paramMutexEnvInit(void) +{ + return; +} + +INIT_LOCAL_API int ParamRWMutexCreate(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxCreate(&lock->mutex); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to init mutex ret %d", ret); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexWRLock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxPend(lock->mutex, LOS_WAIT_FOREVER); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexRDLock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxPend(lock->mutex, LOS_WAIT_FOREVER); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexUnlock(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxPost(lock->mutex); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex); + return 0; +} + +INIT_LOCAL_API int ParamRWMutexDelete(ParamRWMutex *lock) +{ + PARAM_CHECK(lock != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxDelete(lock->mutex); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, lock->mutex); + return 0; +} + +INIT_LOCAL_API int ParamMutexCreate(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxCreate(&mutex->mutex); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to init mutex ret %d", ret); + return 0; +} + +INIT_LOCAL_API int ParamMutexPend(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxPend(mutex->mutex, LOS_WAIT_FOREVER); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, mutex->mutex); + return 0; +} + +INIT_LOCAL_API int ParamMutexPost(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid lock"); + uint32_t ret = LOS_MuxPost(mutex->mutex); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to mutex lock ret %d %d", ret, mutex->mutex); + return 0; +} + +INIT_LOCAL_API int ParamMutexDelete(ParamMutex *mutex) +{ + PARAM_CHECK(mutex != NULL, return -1, "Invalid mutex"); + uint32_t ret = LOS_MuxDelete(mutex->mutex); + PARAM_CHECK(ret == LOS_OK, return -1, "Failed to delete mutex lock ret %d %d", ret, mutex->mutex); + return 0; +} +#endif + diff --git a/services/param/liteos/param_persistadp.c b/services/param/liteos/param_persistadp.c new file mode 100644 index 0000000000000000000000000000000000000000..aa1897b5f6affeb4eaccb7375f769b44c8d5c30b --- /dev/null +++ b/services/param/liteos/param_persistadp.c @@ -0,0 +1,135 @@ +/* + * 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 +#include +#include + +#include "init_utils.h" +#include "param_manager.h" +#include "param_persist.h" +#include "param_utils.h" + +// for linux, no mutex +static ParamMutex g_saveMutex = {}; + +static int LoadOnePersistParam_(const uint32_t *context, const char *name, const char *value) +{ + UNUSED(context); + uint32_t dataIndex = 0; + return WriteParam(name, value, &dataIndex, 0); +} + +static void LoadPersistParam_(const char *fileName, char *buffer, uint32_t buffSize) +{ + FILE *fp = fopen(fileName, "r"); + PARAM_WARNING_CHECK(fp != NULL, return, "No valid persist parameter file %s", fileName); + + uint32_t paramNum = 0; + while (fgets(buffer, buffSize, fp) != NULL) { + buffer[buffSize - 1] = '\0'; + int ret = SplitParamString(buffer, NULL, 0, LoadOnePersistParam_, NULL); + PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buffer); + paramNum++; + } + (void)fclose(fp); + PARAM_LOGI("LoadPersistParam from file %s paramNum %d", fileName, paramNum); +} + +static int LoadPersistParam(void) +{ + CheckAndCreateDir(PARAM_PERSIST_SAVE_PATH); + const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 max len + char *buffer = malloc(buffSize); + PARAM_CHECK(buffer != NULL, return -1, "Failed to alloc"); + + int updaterMode = InUpdaterMode(); + char *tmpPath = (updaterMode == 0) ? PARAM_PERSIST_SAVE_PATH : "/param/persist_parameters"; + LoadPersistParam_(tmpPath, buffer, buffSize); + tmpPath = (updaterMode == 0) ? PARAM_PERSIST_SAVE_TMP_PATH : "/param/tmp_persist_parameters"; + LoadPersistParam_(tmpPath, buffer, buffSize); + free(buffer); + return 0; +} + +static int SavePersistParam(const char *name, const char *value) +{ + ParamMutexPend(&g_saveMutex); + char *path = (InUpdaterMode() == 0) ? PARAM_PERSIST_SAVE_PATH : "/param/persist_parameters"; + FILE *fp = fopen(path, "a+"); + int ret = -1; + if (fp != NULL) { + ret = fprintf(fp, "%s=%s\n", name, value); + (void)fclose(fp); + } + ParamMutexPost(&g_saveMutex); + if (ret <= 0) { + PARAM_LOGE("Failed to save persist param %s", name); + } + return ret; +} + +static int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle) +{ + ParamMutexPend(&g_saveMutex); + char *path = (InUpdaterMode() == 0) ? PARAM_PERSIST_SAVE_TMP_PATH : "/param/tmp_persist_parameters"; + unlink(path); + FILE *fp = fopen(path, "w"); + if (fp == NULL) { + ParamMutexPost(&g_saveMutex); + PARAM_LOGE("Open file %s fail error %d", path, errno); + return -1; + } + *handle = (PERSIST_SAVE_HANDLE)fp; + return 0; +} + +static int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle, const char *name, const char *value) +{ + FILE *fp = (FILE *)handle; + int ret = fprintf(fp, "%s=%s\n", name, value); + PARAM_LOGV("BatchSavePersistParam %s=%s", name, value); + return (ret > 0) ? 0 : -1; +} + +static void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle) +{ + int ret; + FILE *fp = (FILE *)handle; + (void)fflush(fp); + (void)fsync(fileno(fp)); + (void)fclose(fp); + if (InUpdaterMode() == 0) { + unlink(PARAM_PERSIST_SAVE_PATH); + ret = rename(PARAM_PERSIST_SAVE_TMP_PATH, PARAM_PERSIST_SAVE_PATH); + } else { + unlink("/param/persist_parameters"); + ret = rename("/param/tmp_persist_parameters", "/param/persist_parameters"); + } + ParamMutexPost(&g_saveMutex); + PARAM_CHECK(ret == 0, return, "BatchSavePersistParamEnd %s fail error %d", PARAM_PERSIST_SAVE_TMP_PATH, errno); +} + +int RegisterPersistParamOps(PersistParamOps *ops) +{ + ParamMutexCreate(&g_saveMutex); + PARAM_CHECK(ops != NULL, return -1, "Invalid ops"); + ops->save = SavePersistParam; + ops->load = LoadPersistParam; + ops->batchSaveBegin = BatchSavePersistParamBegin; + ops->batchSave = BatchSavePersistParam; + ops->batchSaveEnd = BatchSavePersistParamEnd; + return 0; +} \ No newline at end of file diff --git a/services/param/liteos/param_service.c b/services/param/liteos/param_service.c new file mode 100644 index 0000000000000000000000000000000000000000..cd7f5d9d3847c767b6d90ea803e14134d854e418 --- /dev/null +++ b/services/param/liteos/param_service.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021 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 "init_log.h" +#include "init_param.h" +#include "init_utils.h" +#include "param_manager.h" +#ifdef PARAM_LOAD_CFG_FROM_CODE +#include "param_cfg.h" +#endif +#ifdef __LITEOS_M__ +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "parameter.h" +#endif + +#ifdef PARAM_LOAD_CFG_FROM_CODE +static const char *StringTrim(char *buffer, int size, const char *name) +{ + char *tmp = (char *)name; + while (*tmp != '\0' && *tmp != '"') { + tmp++; + } + if (*tmp == '\0') { + return name; + } + // skip " + tmp++; + int i = 0; + while (*tmp != '\0' && i < size) { + buffer[i++] = *tmp; + tmp++; + } + if (i >= size) { + return name; + } + while (i > 0) { + if (buffer[i] == '"') { + buffer[i] = '\0'; + return buffer; + } + i--; + } + return name; +} +#endif + +int InitParamService(void) +{ + PARAM_LOGI("InitParamService %s", DATA_PATH); + CheckAndCreateDir(PARAM_STORAGE_PATH "/"); + CheckAndCreateDir(DATA_PATH); + // param space + int ret = InitParamWorkSpace(0, NULL); + PARAM_CHECK(ret == 0, return ret, "Init parameter workspace fail"); + ret = InitPersistParamWorkSpace(); + PARAM_CHECK(ret == 0, return ret, "Init persist parameter workspace fail"); + + // from build + LoadParamFromBuild(); +#ifdef PARAM_LOAD_CFG_FROM_CODE + char *buffer = calloc(1, PARAM_VALUE_LEN_MAX); + PARAM_CHECK(buffer != NULL, return ret, "Failed to malloc for buffer"); + for (size_t i = 0; i < ARRAY_LENGTH(g_paramDefCfgNodes); i++) { + PARAM_LOGV("InitParamService name %s = %s", g_paramDefCfgNodes[i].name, g_paramDefCfgNodes[i].value); + uint32_t dataIndex = 0; + ret = WriteParam(g_paramDefCfgNodes[i].name, + StringTrim(buffer, PARAM_VALUE_LEN_MAX, g_paramDefCfgNodes[i].value), &dataIndex, 0); + PARAM_CHECK(ret == 0, continue, "Failed to set param %d name %s %s", + ret, g_paramDefCfgNodes[i].name, g_paramDefCfgNodes[i].value); + } + free(buffer); +#endif + + return 0; +} + +int StartParamService(void) +{ + return 0; +} + +void StopParamService(void) +{ + PARAM_LOGI("StopParamService."); + ClosePersistParamWorkSpace(); + CloseParamWorkSpace(); +} + +int SystemWriteParam(const char *name, const char *value) +{ + int ctrlService = 0; + int ret = CheckParameterSet(name, value, GetParamSecurityLabel(), &ctrlService); + PARAM_CHECK(ret == 0, return ret, "Forbid to set parameter %s", name); + PARAM_LOGV("SystemWriteParam name %s value: %s ctrlService %d", name, value, ctrlService); + if ((ctrlService & PARAM_CTRL_SERVICE) != PARAM_CTRL_SERVICE) { // ctrl param + uint32_t dataIndex = 0; + ret = WriteParam(name, value, &dataIndex, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value); + ret = WritePersistParam(name, value); + PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name); + } else { + PARAM_LOGE("SystemWriteParam can not support service ctrl parameter name %s", name); + } + return ret; +} + +#ifdef __LITEOS_M__ +#define OS_DELAY 1000 // * 30 // 30s +#define STACK_SIZE 1024 + +static void ParamServiceTask(int *arg) +{ + (void)arg; + PARAM_LOGI("ParamServiceTask start"); + while (1) { + CheckAndSavePersistParam(); + osDelay(OS_DELAY); + } +} + +void LiteParamService(void) +{ + static int init = 0; + if (init) { + return; + } + init = 1; + EnableInitLog(INIT_INFO); + InitParamService(); + // get persist param + LoadPersistParams(); +} +CORE_INIT(LiteParamService); +#endif \ No newline at end of file diff --git a/services/param/manager/param_cache.c b/services/param/manager/param_cache.c deleted file mode 100644 index 690de37e869cb0a8777f1a275013d02da97d8aae..0000000000000000000000000000000000000000 --- a/services/param/manager/param_cache.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2020 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 "sys_param.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "param_manager.h" - -#define LABEL "Manager" -#define MAX_PROPERT_IN_WATCH 5 -#define NORMAL_MEMORY_FOR_PARAM_CACHE 4 * 1024 -static WorkSpace g_workSpace; -static pthread_mutex_t cacheLock = PTHREAD_MUTEX_INITIALIZER; - -static int InitNormalMemory(WorkSpace *workSpace, u_int32_t spaceSize) -{ - PARAM_CHECK(workSpace != NULL, return -1, "Invalid param"); - if (workSpace->area != NULL) { - return 0; - } - - void *areaAddr = (void *)mmap(NULL, spaceSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_POPULATE | MAP_ANON, -1, 0); - PARAM_CHECK(areaAddr != MAP_FAILED, return -1, "Failed to map memory error %s", strerror(errno)); - workSpace->area = (WorkArea*)areaAddr; - atomic_init(&workSpace->area->serial, 0); - workSpace->area->dataSize = spaceSize; - workSpace->area->currOffset = sizeof(WorkArea); - PARAM_LOGI("InitNormalMemory success, currOffset %u firstNode %u dataSize %u", - workSpace->area->currOffset, workSpace->area->firstNode, workSpace->area->dataSize); - return 0; -} - -static ParamCacheNode *AllocParamCacheNode(WorkSpace *workSpace, u_int32_t size) -{ - PARAM_CHECK(workSpace != NULL, return 0, "Invalid param"); - PARAM_CHECK((workSpace->area->currOffset + size) < workSpace->area->dataSize, return 0, - "Failed to allocate currOffset %d, dataSize %d", workSpace->area->currOffset, workSpace->area->dataSize); - ParamCacheNode *cache = (ParamCacheNode *)(workSpace->area->data + workSpace->area->currOffset); - workSpace->area->currOffset += size; - return cache; -} - -static int CreateParamCache(ParamCache *cache, ParamWorkSpace *workSpace, ParamEvaluatePtr evaluate) -{ - PARAM_CHECK(cache != NULL && evaluate != NULL, return -1, "Invalid param"); - if (cache->cacheNode != NULL) { - return 0; - } - int ret = InitNormalMemory(&g_workSpace, NORMAL_MEMORY_FOR_PARAM_CACHE); - PARAM_CHECK(ret == 0, return -1, "Failed to init normal memory"); - pthread_mutex_init(&cache->lock, NULL); - cache->serial = GetWorkSpaceSerial(&workSpace->paramSpace); - cache->cacheCount = 0; - cache->evaluate = evaluate; - cache->cacheNode = (ParamCacheNode *)AllocParamCacheNode(&g_workSpace, - sizeof(ParamCache) * MAX_PROPERT_IN_WATCH); - PARAM_CHECK(cache->cacheNode != NULL, return -1, "Failed to malloc memory"); - return 0; -} - -static int AddParamNode(ParamCache *cache, ParamWorkSpace *workSpace, const char *name, const char *defValue) -{ - PARAM_CHECK(cache != NULL && name != NULL, return -1, "Invalid param"); - PARAM_CHECK(cache->cacheCount < MAX_PROPERT_IN_WATCH, return -1, "Full param in cache"); - - ParamCacheNode *cacheNode = &cache->cacheNode[cache->cacheCount++]; - int ret = memcpy_s(cacheNode->value, sizeof(cacheNode->value), defValue, strlen(defValue)); - PARAM_CHECK(ret == 0, return -1, "Failed to copy default value"); - - ret = ReadParamWithCheck(workSpace, name, &cacheNode->handle); - PARAM_CHECK(ret == 0, return -1, "Failed to read param"); - cacheNode->serial = ReadParamSerial(workSpace, cacheNode->handle); - return ret; -} - -static int CheckCacheNode(ParamWorkSpace *workSpace, ParamCacheNode *cacheNode) -{ - return cacheNode && ReadParamSerial(workSpace, cacheNode->handle) != cacheNode->serial; -} - -static void RefreshCacheNode(ParamWorkSpace *workSpace, ParamCacheNode *cacheNode) -{ - cacheNode->serial = ReadParamSerial(workSpace, cacheNode->handle); - u_int32_t len = sizeof(cacheNode->value); - ReadParamValue(workSpace, cacheNode->handle, cacheNode->value, &len); -} - -static const char *TestParamCache(ParamCache *cache, ParamWorkSpace *workSpace) -{ - int changeDetected = 0; - if (pthread_mutex_trylock(&cache->lock)) { - return cache->evaluate(cache->cacheCount, cache->cacheNode); - } - if (GetWorkSpaceSerial(&workSpace->paramSpace) != cache->serial) { - changeDetected = 1; - } - for (u_int32_t i = 0; (i < cache->cacheCount) && changeDetected == 0; i++) { - changeDetected = CheckCacheNode(workSpace, &cache->cacheNode[i]); - } - if (changeDetected) { - for (u_int32_t i = 0; i < cache->cacheCount; i++) { - RefreshCacheNode(workSpace, &cache->cacheNode[i]); - } - cache->serial = GetWorkSpaceSerial(&workSpace->paramSpace); - } - pthread_mutex_unlock(&cache->lock); - - return cache->evaluate(cache->cacheCount, cache->cacheNode); -} - -const char *DetectParamChange(ParamWorkSpace *workSpace, ParamCache *cache, - ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2]) -{ - pthread_mutex_lock(&cacheLock); - while (cache->cacheCount == 0) { - int ret = CreateParamCache(cache, workSpace, evaluate); - PARAM_CHECK(ret == 0, break, "Failed to create cache"); - for (u_int32_t i = 0; i < count; i++) { - ret = AddParamNode(cache, workSpace, parameters[i][0], parameters[i][1]); - PARAM_CHECK(ret == 0, break, "Failed to add param cache"); - } - PARAM_CHECK(ret == 0, break, "Failed to add param cache"); - } - pthread_mutex_unlock(&cacheLock); - return TestParamCache(cache, workSpace); -} diff --git a/services/param/manager/param_manager.c b/services/param/manager/param_manager.c index d0a9b11bd10cbcdd3bfc3a48618b4c80610735f9..2af4302cfe5ff7c0e1fc01200038a96f40d182cc 100644 --- a/services/param/manager/param_manager.c +++ b/services/param/manager/param_manager.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Huawei Device Co., Ltd. + * 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 @@ -16,331 +16,635 @@ #include "param_manager.h" #include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include -#define LABEL "Manager" +#include "init_cmds.h" +#include "init_hook.h" +#include "param_base.h" +#include "param_trie.h" +#include "param_utils.h" +#include "securec.h" +static DUMP_PRINTF g_printf = printf; -#ifdef PARAM_SUPPORT_SELINUX -static int SelinuxAuditCallback(void *data, - __attribute__((unused))security_class_t class, char *msgBuf, size_t msgSize) +static int ReadParamName(ParamHandle handle, char *name, uint32_t length); + +ParamNode *SystemCheckMatchParamWait(const char *name, const char *value) { - ParamAuditData *auditData = (ParamAuditData*)(data); - PARAM_CHECK(auditData != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(auditData->name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(auditData->cr != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - if (snprintf_s(msgBuf, msgSize, msgSize - 1, "param=%s pid=%d uid=%d gid=%d", - auditData->name, auditData->cr->pid, auditData->cr->uid, auditData->cr->gid) == -1) { - return PARAM_CODE_INVALID_PARAM; + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space"); + + WorkSpace *workspace = GetWorkSpaceByName(name); + PARAM_CHECK(workspace != NULL, return NULL, "Failed to get workspace %s", name); + PARAM_LOGV("SystemCheckMatchParamWait name %s", name); + uint32_t nameLength = strlen(name); + ParamTrieNode *node = FindTrieNode(workspace, name, nameLength, NULL); + if (node == NULL || node->dataIndex == 0) { + return NULL; } - return 0; + ParamNode *param = (ParamNode *)GetTrieNode(workspace, node->dataIndex); + if (param == NULL) { + return NULL; + } + if ((param->keyLength != nameLength) || (strncmp(param->data, name, nameLength) != 0)) { // compare name + return NULL; + } + ATOMIC_SYNC_OR_AND_FETCH(¶m->commitId, PARAM_FLAGS_WAITED, MEMORY_ORDER_RELEASE); + if ((strncmp(value, "*", 1) == 0) || (strcmp(param->data + nameLength + 1, value) == 0)) { // compare value + return param; + } + char *tmp = strstr(value, "*"); + if (tmp != NULL && (strncmp(param->data + nameLength + 1, value, tmp - value) == 0)) { + return param; + } + return NULL; } -#endif -int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead, const char *context) +static int ProcessParamTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie) { - u_int32_t flags = atomic_load_explicit(&workSpace->flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) == WORKSPACE_FLAGS_INIT) { + ParamTraversalContext *context = (ParamTraversalContext *)cookie; + ParamTrieNode *current = (ParamTrieNode *)node; + if (current == NULL) { + return 0; + } + if (current->dataIndex == 0) { return 0; } + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex); + if (entry == NULL) { + return 0; + } + if ((strcmp("#", context->prefix) != 0) && (strncmp(entry->data, context->prefix, strlen(context->prefix)) != 0)) { + return 0; + } + uint32_t index = PARAM_HANDLE(workSpace, current->dataIndex); + context->traversalParamPtr(index, context->context); + return 0; +} -#ifdef PARAM_SUPPORT_SELINUX - union selinux_callback cb; - cb.func_audit = SelinuxAuditCallback; - selinux_set_callback(SELINUX_CB_AUDIT, cb); -#endif +int SystemTraversalParameter(const char *prefix, TraversalParamPtr traversalParameter, void *cookie) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); + PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null"); -#ifdef PARAM_SUPPORT_SELINUX - if (context && fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) { - PARAM_LOGI("fsetxattr context %s fail", context); +#ifdef PARAM_SUPPORT_SELINUX // load security label + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); + if (ops != NULL && ops->securityGetLabel != NULL) { + ops->securityGetLabel("open"); } #endif - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_NAME, "Invalid param"); - workSpace->paramSpace.compareTrieNode = CompareTrieDataNode; - workSpace->paramSpace.allocTrieNode = AllocateTrieDataNode; - int ret = InitWorkSpace(PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead); - PARAM_CHECK(ret == 0, return ret, "InitWorkSpace failed."); - - workSpace->paramLabelSpace.compareTrieNode = CompareTrieNode; // 必须先设置 - workSpace->paramLabelSpace.allocTrieNode = AllocateTrieNode; - ret = InitWorkSpace(PARAM_INFO_PATH, &workSpace->paramLabelSpace, onlyRead); - PARAM_CHECK(ret == 0, return ret, "InitWorkSpace failed."); - - atomic_store_explicit(&workSpace->flags, WORKSPACE_FLAGS_INIT, memory_order_release); - return ret; + ParamTraversalContext context = {traversalParameter, cookie, "#"}; + if (!(prefix == NULL || strlen(prefix) == 0)) { + int ret = CheckParamPermission(GetParamSecurityLabel(), prefix, DAC_READ); + PARAM_CHECK(ret == 0, return ret, "Forbid to traversal parameters %s", prefix); + context.prefix = (char *)prefix; + } + + WorkSpace *workSpace = GetNextWorkSpace(NULL); + if (workSpace != NULL && strcmp(workSpace->fileName, WORKSPACE_NAME_DAC) == 0) { + workSpace = GetNextWorkSpace(workSpace); + } + while (workSpace != NULL) { + WorkSpace *next = GetNextWorkSpace(workSpace); + ParamTrieNode *root = NULL; + if (prefix != NULL && strlen(prefix) != 0) { + root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL); + } + PARAMSPACE_AREA_RD_LOCK(workSpace); + TraversalTrieNode(workSpace, root, ProcessParamTraversal, (const void *)&context); + PARAMSPACE_AREA_RW_UNLOCK(workSpace); + workSpace = next; + } + return 0; +} + +static int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie) +{ + int verbose = *(int *)cookie; + ParamTrieNode *current = (ParamTrieNode *)node; + if (current == NULL) { + return 0; + } + if (verbose) { + PARAM_DUMP("\tTrie node info [%u,%u,%u] data: %u label: %u key length:%u \n\t key: %s \n", + current->left, current->right, current->child, + current->dataIndex, current->labelIndex, current->length, current->key); + } + if (current->dataIndex != 0) { + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex); + if (entry != NULL) { + PARAM_DUMP("\tparameter length info [%d] [%u, %u] \n\t param: %s \n", + entry->commitId, entry->keyLength, entry->valueLength, entry->data); + } + } + if (current->labelIndex == 0) { + return 0; + } + ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex); + if (label == NULL) { + return 0; + } + PARAM_DUMP("\tparameter label dac %u %u 0%o \n", label->uid, label->gid, label->mode); + PARAM_DUMP("\tparameter label dac member [%u] ", label->memberNum); + for (uint32_t i = 0; i < label->memberNum; i++) { + PARAM_DUMP(" %u", label->members[i]); + } + if (label->memberNum > 0) { + PARAM_DUMP("\n"); + } + return 0; } -void CloseParamWorkSpace(ParamWorkSpace *workSpace) +static void HashNodeTraverseForDump(WorkSpace *workSpace, int verbose) { - CloseWorkSpace(&workSpace->paramSpace); - CloseWorkSpace(&workSpace->paramLabelSpace); - atomic_store_explicit(&workSpace->flags, 0, memory_order_release); + PARAM_DUMP(" map file: %s \n", workSpace->fileName); + PARAM_DUMP(" space index : %d \n", workSpace->spaceIndex); + PARAM_DUMP(" space size : %d \n", workSpace->spaceSize); + if (workSpace->area != NULL) { + PARAM_DUMP(" total size: %u \n", workSpace->area->dataSize); + PARAM_DUMP(" first offset: %u \n", workSpace->area->firstNode); + PARAM_DUMP(" current offset: %u \n", workSpace->area->currOffset); + PARAM_DUMP(" total node: %u \n", workSpace->area->trieNodeCount); + PARAM_DUMP(" total param node: %u \n", workSpace->area->paramNodeCount); + PARAM_DUMP(" total security node: %u\n", workSpace->area->securityNodeCount); + if (verbose) { + PARAM_DUMP(" commitId : %" PRId64 "\n", workSpace->area->commitId); + PARAM_DUMP(" commitPersistId : %" PRId64 "\n", workSpace->area->commitPersistId); + } + } + PARAM_DUMP(" node info: \n"); + PARAMSPACE_AREA_RD_LOCK(workSpace); + TraversalTrieNode(workSpace, NULL, DumpTrieDataNodeTraversal, (const void *)&verbose); + PARAMSPACE_AREA_RW_UNLOCK(workSpace); } -int WriteParamInfo(ParamWorkSpace *workSpace, SubStringInfo *info, int subStrNumber) +void SystemDumpParameters(int verbose, int index, int (*dump)(const char *fmt, ...)) { - PARAM_CHECK(workSpace != NULL && info != NULL && subStrNumber > SUBSTR_INFO_NAME, - return PARAM_CODE_INVALID_PARAM, "Failed to check param"); - const char *name = info[SUBSTR_INFO_NAME].value; - char *label = NULL; - char *type = NULL; - if (subStrNumber >= SUBSTR_INFO_LABEL) { - label = info[SUBSTR_INFO_LABEL].value; + if (dump != NULL) { + g_printf = dump; } else { - label = "u:object_r:default_prop:s0"; + g_printf = printf; + } + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space"); + // check default dac + int ret = CheckParamPermission(GetParamSecurityLabel(), "#", DAC_READ); + PARAM_CHECK(ret == 0, return, "Forbid to dump parameters "); +#ifdef PARAM_SUPPORT_SELINUX // load security label + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); + if (ops != NULL && ops->securityGetLabel != NULL) { + ops->securityGetLabel("open"); } - if (subStrNumber >= SUBSTR_INFO_TYPE) { - type = info[SUBSTR_INFO_TYPE].value; - } else { - type = "string"; +#endif + PARAM_DUMP("Dump all parameters begin ...\n"); + if (verbose) { + PARAM_DUMP("Local security information\n"); + PARAM_DUMP("pid: %d uid: %u gid: %u \n", + paramSpace->securityLabel.cred.pid, + paramSpace->securityLabel.cred.uid, + paramSpace->securityLabel.cred.gid); + } + if (index > 0) { + WorkSpace *workSpace = GetWorkSpace(index); + if (workSpace != NULL) { + HashNodeTraverseForDump(workSpace, verbose); + } + return; + } + // show workspace size + WorkSpaceSize *spaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE)); + if (spaceSize != NULL) { + PARAM_DUMP("Max label index : %u\n", spaceSize->maxLabelIndex); + for (uint32_t i = 0; i < spaceSize->maxLabelIndex; i++) { + if (spaceSize->spaceSize[i] == PARAM_WORKSPACE_MIN) { + continue; + } + PARAM_DUMP("\t workspace %u size : %u\n", i, spaceSize->spaceSize[i]); + } } - int ret = CheckParamName(name, 1); - PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name); + WorkSpace *workSpace = GetNextWorkSpace(NULL); + while (workSpace != NULL) { + WorkSpace *next = GetNextWorkSpace(workSpace); + HashNodeTraverseForDump(workSpace, verbose); + workSpace = next; + } + PARAM_DUMP("Dump all parameters finish\n"); +} - // 先保存标签值 - TrieNode *node = AddTrieNode(&workSpace->paramLabelSpace, - workSpace->paramLabelSpace.rootNode, label, strlen(label)); - PARAM_CHECK(node != NULL, return PARAM_CODE_REACHED_MAX, "Failed to add label"); - u_int32_t offset = GetTrieNodeOffset(&workSpace->paramLabelSpace, node); +INIT_LOCAL_API int SysCheckParamExist(const char *name) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); + PARAM_CHECK(name != NULL, return -1, "The name or handle is null"); - TrieDataNode *dataNode = AddTrieDataNode(&workSpace->paramSpace, name, strlen(name)); - PARAM_CHECK(dataNode != NULL, return PARAM_CODE_REACHED_MAX, "Failed to add node %s", name); - TrieNode *entry = (TrieNode *)GetTrieNode(&workSpace->paramLabelSpace, &dataNode->labelIndex); - if (entry != 0) { // 已经存在label - PARAM_LOGE("Has been set label %s old label %s new label: %s", name, entry->key, label); +#ifdef PARAM_SUPPORT_SELINUX // load security label + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_SELINUX); + if (ops != NULL && ops->securityGetLabel != NULL) { + ops->securityGetLabel("open"); } - SaveIndex(&dataNode->labelIndex, offset); - return 0; +#endif + WorkSpace *workSpace = GetNextWorkSpace(NULL); + while (workSpace != NULL) { + PARAM_LOGV("SysCheckParamExist name %s in space %s", name, workSpace->fileName); + WorkSpace *next = GetNextWorkSpace(workSpace); + ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL); + if (node != NULL && node->dataIndex != 0) { + return 0; + } else if (node != NULL) { + return PARAM_CODE_NODE_EXIST; + } + workSpace = next; + } + return PARAM_CODE_NOT_FOUND; } -int AddParam(WorkSpace *workSpace, const char *name, const char *value) +INIT_INNER_API int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData) { - PARAM_CHECK(workSpace != NULL && name != NULL && value != NULL, - return PARAM_CODE_INVALID_PARAM, "Failed to check param"); - - TrieDataNode *node = AddTrieDataNode(workSpace, name, strlen(name)); - PARAM_CHECK(node != NULL, return PARAM_CODE_REACHED_MAX, "Failed to add node"); - DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, &node->dataIndex); - //PARAM_LOGI("AddParam entry %p", entry); - if (entry == NULL) { - u_int32_t offset = AddData(workSpace, name, strlen(name), value, strlen(value)); - PARAM_CHECK(offset > 0, return PARAM_CODE_REACHED_MAX, "Failed to allocate name %s", name); - SaveIndex(&node->dataIndex, offset); - //PARAM_LOGI("AddParam entry %p %u", entry, offset); + UNUSED(type); + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); + uint32_t labelIndex = 0; + // get from dac + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + PARAM_CHECK(space != NULL, return -1, "Invalid workSpace"); + FindTrieNode(space, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, labelIndex); + PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex); + + auditData->name = name; + auditData->dacData.uid = node->uid; + auditData->dacData.gid = node->gid; + auditData->dacData.mode = node->mode; +#ifdef PARAM_SUPPORT_SELINUX + const char *tmpName = (paramSpace->selinuxSpace.getParamLabel != NULL) ? + paramSpace->selinuxSpace.getParamLabel(name) : NULL; + if (tmpName != NULL) { + int ret = strcpy_s(auditData->label, sizeof(auditData->label), tmpName); + PARAM_CHECK(ret == 0, return 0, "Failed to copy label for %s", name); } - atomic_store_explicit(&workSpace->area->serial, - atomic_load_explicit(&workSpace->area->serial, memory_order_relaxed) + 1, memory_order_release); - futex_wake(&workSpace->area->serial, INT_MAX); +#endif return 0; } -int UpdateParam(WorkSpace *workSpace, u_int32_t *dataIndex, const char *name, const char *value) +static int CreateCtrlInfo(ServiceCtrlInfo **ctrlInfo, const char *cmd, uint32_t offset, + uint8_t ctrlParam, const char *format, ...) { - PARAM_CHECK(workSpace != NULL && name != NULL && value != NULL, - return PARAM_CODE_INVALID_PARAM, "Failed to check param"); - - DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, dataIndex); - PARAM_CHECK(entry != NULL, return PARAM_CODE_REACHED_MAX, - "Failed to update param value %s %u", name, *dataIndex); - u_int32_t keyLen = DATA_ENTRY_KEY_LEN(entry); - PARAM_CHECK(keyLen == strlen(name), return PARAM_CODE_INVALID_NAME, "Failed to check name len %s", name); - - u_int32_t serial = atomic_load_explicit(&entry->serial, memory_order_relaxed); - serial |= 1; - atomic_store_explicit(&entry->serial, serial | 1, memory_order_release); - atomic_thread_fence(memory_order_release); - int ret = UpdateDataValue(entry, value); - if (ret != 0) { - PARAM_LOGE("Failed to update param value %s %s", name, value); - } - //PARAM_LOGI("UpdateParam entry %p", entry); - atomic_store_explicit(&entry->serial, serial + 1, memory_order_release); - futex_wake(&entry->serial, INT_MAX); - atomic_store_explicit(&workSpace->area->serial, - atomic_load_explicit(&workSpace->area->serial, memory_order_relaxed) + 1, memory_order_release); - futex_wake(&workSpace->area->serial, INT_MAX); - return ret; + *ctrlInfo = calloc(1, sizeof(ServiceCtrlInfo)); + PARAM_CHECK(*ctrlInfo != NULL, return -1, "Failed to alloc memory %s", cmd); + va_list vargs; + va_start(vargs, format); + int len = vsnprintf_s((*ctrlInfo)->realKey, + sizeof((*ctrlInfo)->realKey), sizeof((*ctrlInfo)->realKey) - 1, format, vargs); + va_end(vargs); + int ret = strcpy_s((*ctrlInfo)->cmdName, sizeof((*ctrlInfo)->cmdName), cmd); + (*ctrlInfo)->valueOffset = offset; + if (ret != 0 || len <= 0) { + free(*ctrlInfo); + *ctrlInfo = NULL; + return -1; + } + (*ctrlInfo)->ctrlParam = ctrlParam; + return 0; } -DataEntry *FindParam(WorkSpace *workSpace, const char *name) +static int GetServiceCtrlInfoForPowerCtrl(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo) { - PARAM_CHECK(workSpace != NULL, return NULL, "Failed to check param"); - PARAM_CHECK(name != NULL, return NULL, "Invalid param size"); - - TrieDataNode *node = FindTrieDataNode(workSpace, name, strlen(name), 0); - if (node != NULL) { - return (DataEntry *)GetTrieNode(workSpace, &node->dataIndex); + size_t size = 0; + const ParamCmdInfo *powerCtrlArg = GetStartupPowerCtl(&size); + PARAM_CHECK(powerCtrlArg != NULL, return -1, "Invalid ctrlInfo for %s", name); + uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen("reboot") + 1; + if (strcmp(value, "reboot") == 0) { + return CreateCtrlInfo(ctrlInfo, "reboot", valueOffset, 1, + "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, "reboot", value); + } + for (size_t i = 0; i < size; i++) { + PARAM_LOGV("Get power ctrl %s name %s value %s", powerCtrlArg[i].name, name, value); + if (strncmp(value, powerCtrlArg[i].name, strlen(powerCtrlArg[i].name)) == 0) { + valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(powerCtrlArg[i].replace) + 1; + return CreateCtrlInfo(ctrlInfo, powerCtrlArg[i].cmd, valueOffset, 1, + "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, powerCtrlArg[i].replace, value); + } } - return NULL; + // not found reboot, so reboot by normal + valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen("reboot") + 1; + return CreateCtrlInfo(ctrlInfo, "reboot.other", valueOffset, 1, "%s%s.%s", + OHOS_SERVICE_CTRL_PREFIX, "reboot", value); } -int WriteParamWithCheck(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const char *name, const char *value) +INIT_LOCAL_API int GetServiceCtrlInfo(const char *name, const char *value, ServiceCtrlInfo **ctrlInfo) { - PARAM_CHECK(workSpace != NULL && srcLabel != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - u_int32_t flags = atomic_load_explicit(&workSpace->flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) { - return PARAM_CODE_NOT_INIT; + PARAM_CHECK(ctrlInfo != NULL, return -1, "Invalid ctrlInfo %s", name); + *ctrlInfo = NULL; + size_t size = 0; + if (strcmp("ohos.startup.powerctrl", name) == 0) { + return GetServiceCtrlInfoForPowerCtrl(name, value, ctrlInfo); + } + if (strncmp("ohos.ctl.", name, strlen("ohos.ctl.")) == 0) { + const ParamCmdInfo *ctrlParam = GetServiceStartCtrl(&size); + PARAM_CHECK(ctrlParam != NULL, return -1, "Invalid ctrlInfo for %s", name); + for (size_t i = 0; i < size; i++) { + if (strcmp(name, ctrlParam[i].name) == 0) { + uint32_t valueOffset = strlen(OHOS_SERVICE_CTRL_PREFIX) + strlen(ctrlParam[i].replace) + 1; + return CreateCtrlInfo(ctrlInfo, ctrlParam[i].cmd, valueOffset, 1, + "%s%s.%s", OHOS_SERVICE_CTRL_PREFIX, ctrlParam[i].replace, value); + } + } + } + if (strncmp("ohos.servicectrl.", name, strlen("ohos.servicectrl.")) == 0) { + const ParamCmdInfo *installParam = GetServiceCtl(&size); + PARAM_CHECK(installParam != NULL, return -1, "Invalid ctrlInfo for %s", name); + for (size_t i = 0; i < size; i++) { + if (strncmp(name, installParam[i].name, strlen(installParam[i].name)) == 0) { + return CreateCtrlInfo(ctrlInfo, installParam[i].cmd, strlen(name) + 1, 1, "%s.%s", name, value); + } + } + } + const ParamCmdInfo *other = GetOtherSpecial(&size); + for (size_t i = 0; i < size; i++) { + if (strncmp(name, other[i].name, strlen(other[i].name)) == 0) { + return CreateCtrlInfo(ctrlInfo, other[i].cmd, strlen(other[i].replace), 0, "%s.%s", name, value); + } } + return 0; +} +INIT_LOCAL_API int CheckParameterSet(const char *name, + const char *value, const ParamSecurityLabel *srcLabel, int *ctrlService) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return PARAM_WORKSPACE_NOT_INIT, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return PARAM_WORKSPACE_NOT_INIT, "Invalid space"); + PARAM_LOGV("CheckParameterSet name %s value: %s", name, value); + PARAM_CHECK(srcLabel != NULL && ctrlService != NULL, return -1, "Invalid param "); int ret = CheckParamName(name, 0); PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name); - TrieDataNode *info = FindTrieDataNode(&workSpace->paramSpace, name, strlen(name), 1); - ret = CanWriteParam(workSpace, srcLabel, info, name, value); - //PARAM_LOGI("WriteParamWithCheck info %p", info); - PARAM_CHECK(ret == 0, return ret, "Permission to write param %s", name); - return WriteParam(&workSpace->paramSpace, name, value); + ret = CheckParamValue(NULL, name, value, GetParamValueType(name)); + PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value); + *ctrlService = 0; + + ServiceCtrlInfo *serviceInfo = NULL; + GetServiceCtrlInfo(name, value, &serviceInfo); + ret = CheckParamPermission(srcLabel, (serviceInfo == NULL) ? name : serviceInfo->realKey, DAC_WRITE); + if (ret == 0) { + if (serviceInfo == NULL) { + return 0; + } + if (serviceInfo->ctrlParam != 0) { // ctrl param + *ctrlService |= PARAM_CTRL_SERVICE; + } +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + // do hook cmd + PARAM_LOGV("Check parameter settings realKey %s cmd: '%s' value: %s", + serviceInfo->realKey, serviceInfo->cmdName, (char *)serviceInfo->realKey + serviceInfo->valueOffset); + int cmdIndex = 0; + (void)GetMatchCmd(serviceInfo->cmdName, &cmdIndex); + DoCmdByIndex(cmdIndex, (char *)serviceInfo->realKey + serviceInfo->valueOffset, NULL); +#endif + } + if (serviceInfo != NULL) { + free(serviceInfo); + } + return ret; } -int WriteParam(WorkSpace *workSpace, const char *name, const char *value) +int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len) { - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); + PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null"); + return ReadParamName(handle, name, len); +} - TrieDataNode *node = FindTrieDataNode(workSpace, name, strlen(name), 0); - int ret = CheckParamValue(workSpace, node, name, value); - PARAM_CHECK(ret == 0, return ret, "Invalid value %s %s", name, value); - //PARAM_LOGI("WriteParamWithCheck node %p", node); - if (node != NULL && node->dataIndex != 0) { - return UpdateParam(workSpace, &node->dataIndex, name, value); +static int AddParam(WorkSpace *workSpace, ParamInfos paramInfos, uint32_t *dataIndex) +{ + ParamTrieNode *node = AddTrieNode(workSpace, paramInfos.name, strlen(paramInfos.name)); + PARAM_CHECK(node != NULL, return PARAM_CODE_REACHED_MAX, + "Failed to add node name %s space %s", paramInfos.name, workSpace->fileName); + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); + if (entry == NULL) { + uint32_t offset = AddParamNode(workSpace, paramInfos.type, paramInfos.name, + strlen(paramInfos.name), paramInfos.value, strlen(paramInfos.value), paramInfos.mode); + PARAM_CHECK(offset > 0, return PARAM_CODE_REACHED_MAX, + "Failed to allocate name %s space %s", paramInfos.name, workSpace->fileName); + SaveIndex(&node->dataIndex, offset); + ATOMIC_SYNC_ADD_AND_FETCH(&workSpace->area->commitId, 1, MEMORY_ORDER_RELEASE); +#ifdef PARAM_SUPPORT_SELINUX + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + if (space != NULL && space != workSpace) { // dac commit is global commit + ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitId, 1, MEMORY_ORDER_RELEASE); + } +#endif + } + if (dataIndex != NULL) { + *dataIndex = node->dataIndex; } - return AddParam(workSpace, name, value); + PARAM_LOGV("AddParam name %s value: %s", paramInfos.name, paramInfos.value); + return 0; } -int ReadParamWithCheck(ParamWorkSpace *workSpace, const char *name, ParamHandle *handle) +static int UpdateParam(const WorkSpace *workSpace, uint32_t *dataIndex, const char *name, const char *value, int mode) { - PARAM_CHECK(handle != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(workSpace != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - u_int32_t flags = atomic_load_explicit(&workSpace->flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) { - return PARAM_CODE_NOT_INIT; + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, *dataIndex); + PARAM_CHECK(entry != NULL, return PARAM_CODE_REACHED_MAX, "Failed to update param value %s %u", name, *dataIndex); + PARAM_CHECK(entry->keyLength == strlen(name), return PARAM_CODE_INVALID_NAME, "Failed to check name len %s", name); + + uint32_t valueLen = strlen(value); + uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_RELAXED); + ATOMIC_STORE_EXPLICIT(&entry->commitId, commitId | PARAM_FLAGS_MODIFY, MEMORY_ORDER_RELAXED); + if (entry->valueLength < PARAM_VALUE_LEN_MAX && valueLen < PARAM_VALUE_LEN_MAX) { + int ret = PARAM_MEMCPY(entry->data + entry->keyLength + 1, PARAM_VALUE_LEN_MAX, value, valueLen + 1); + PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_VALUE, "Failed to copy value"); + entry->valueLength = valueLen; + } + + uint32_t flags = commitId & ~PARAM_FLAGS_COMMITID; + uint32_t commitIdCount = (++commitId) & PARAM_FLAGS_COMMITID; + ATOMIC_STORE_EXPLICIT(&entry->commitId, flags | commitIdCount, MEMORY_ORDER_RELEASE); + ATOMIC_SYNC_ADD_AND_FETCH(&workSpace->area->commitId, 1, MEMORY_ORDER_RELEASE); +#ifdef PARAM_SUPPORT_SELINUX + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + if (space != NULL && space != workSpace) { // dac commit is global commit + ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitId, 1, MEMORY_ORDER_RELEASE); } +#endif + PARAM_LOGV("UpdateParam name %s value: %s", name, value); - *handle = 0; - // 取最长匹配 - TrieDataNode *paramInfo = FindTrieDataNode(&workSpace->paramSpace, name, strlen(name), 1); - int ret = CanReadParam(workSpace, paramInfo == NULL ? 0 : paramInfo->labelIndex, name); - PARAM_CHECK(ret == 0, return ret, "Permission to read param %s", name); + if (((unsigned int)mode & LOAD_PARAM_PERSIST) != 0) { + entry->commitId |= PARAM_FLAGS_PERSIST; + } + futex_wake(&entry->commitId, INT_MAX); + return 0; +} - // 查找结点 - TrieDataNode *node = FindTrieDataNode(&workSpace->paramSpace, name, strlen(name), 0); +INIT_LOCAL_API int WriteParam(const char *name, const char *value, uint32_t *dataIndex, int mode) +{ + int flag = 0; + PARAM_LOGV("WriteParam %s", name); + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return PARAM_WORKSPACE_NOT_INIT, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return PARAM_WORKSPACE_NOT_INIT, "Invalid space"); + PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid name or value"); + WorkSpace *workSpace = GetWorkSpaceByName(name); + PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace"); +#ifdef PARAM_SUPPORT_SELINUX + if (strcmp(workSpace->fileName, WORKSPACE_NAME_DEF_SELINUX) == 0) { + flag = 1; + } +#endif + ParamTrieNode *node = FindTrieNode(workSpace, name, strlen(name), NULL); + int ret = 0; if (node != NULL && node->dataIndex != 0) { - //PARAM_LOGI("ReadParamWithCheck trie %p dataIndex %u name %s", node, node->dataIndex, name); - *handle = node->dataIndex; - return 0; + if (dataIndex != NULL) { + *dataIndex = node->dataIndex; + } + if ((mode & LOAD_PARAM_ONLY_ADD) == LOAD_PARAM_ONLY_ADD) { + return PARAM_CODE_READ_ONLY; + } + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, node->dataIndex); + PARAM_CHECK(entry != NULL, return PARAM_CODE_REACHED_MAX, + "Failed to update param value %s %u", name, node->dataIndex); + // use save type to check value + ret = CheckParamValue(node, name, value, entry->type); + PARAM_CHECK(ret == 0, return ret, "Invalid param value param: %s=%s", name, value); + PARAMSPACE_AREA_RW_LOCK(workSpace); + ret = UpdateParam(workSpace, &node->dataIndex, name, value, mode); + PARAMSPACE_AREA_RW_UNLOCK(workSpace); + } else { + uint8_t type = GetParamValueType(name); + ret = CheckParamValue(node, name, value, type); + PARAM_CHECK(ret == 0, return ret, "Invalid param value param: %s=%s", name, value); + PARAMSPACE_AREA_RW_LOCK(workSpace); + ParamInfos paramInfos = {type, mode, name, value}; + ret = AddParam((WorkSpace *)workSpace, paramInfos, dataIndex); + PARAMSPACE_AREA_RW_UNLOCK(workSpace); + } + if ((ret == PARAM_CODE_REACHED_MAX) && (flag == 1)) { + PARAM_LOGE("Add node %s to space %s failed! memory is not enough, system reboot!", name, workSpace->fileName); + return PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH; } - return PARAM_CODE_NOT_FOUND_PROP; + return ret; } -int ReadParamValue(ParamWorkSpace *workSpace, ParamHandle handle, char *value, u_int32_t *len) +INIT_LOCAL_API WorkSpace *GetNextWorkSpace(WorkSpace *curr) { - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - u_int32_t flags = atomic_load_explicit(&workSpace->flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) { - return PARAM_CODE_NOT_INIT; - } - DataEntry *entry = (DataEntry *)GetTrieNode(&workSpace->paramSpace, &handle); - if (entry == NULL) { - return -1; + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); + uint32_t i = (curr == NULL) ? 0 : (curr->spaceIndex + 1); + WorkSpace *workSpace = NULL; + for (; i < paramSpace->maxLabelIndex; ++i) { + workSpace = GetWorkSpace(i); + if (workSpace != NULL) { + return workSpace; + } } + return NULL; +} - if (value == NULL) { - *len = DATA_ENTRY_DATA_LEN(entry) + 1; - return 0; +INIT_LOCAL_API uint8_t GetParamValueType(const char *name) +{ + uint32_t labelIndex = 0; + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + if (space == NULL) { + return PARAM_TYPE_STRING; } + (void)FindTrieNode(space, name, strlen(name), &labelIndex); + ParamSecurityNode *securityNode = (ParamSecurityNode *)GetTrieNode(space, labelIndex); + if (securityNode == NULL) { + return PARAM_TYPE_STRING; + } + return securityNode->type; +} - while (1) { - u_int32_t serial = GetDataSerial(entry); - int ret = GetDataValue(entry, value, *len); - PARAM_CHECK(ret == 0, return ret, "Failed to get value"); - atomic_thread_fence(memory_order_acquire); - if (serial == atomic_load_explicit(&(entry->serial), memory_order_relaxed)) { - return 0; +static int CheckParamValueType(const char *name, const char *value, uint8_t paramType) +{ + (void)name; + if (paramType == PARAM_TYPE_INT) { + long long int temp1 = 0; + if (strlen(value) > 1 && value[0] == '-' && StringToLL(value, &temp1) != 0) { + PARAM_LOGE("Illegal param value %s for int", value); + return PARAM_CODE_INVALID_VALUE; + } + unsigned long long int temp2 = 0; + if (StringToULL(value, &temp2) != 0) { + PARAM_LOGE("Illegal param value %s for int", value); + return PARAM_CODE_INVALID_VALUE; + } + } else if (paramType == PARAM_TYPE_BOOL) { + static const char *validValue[] = { + "1", "0", "true", "false", "y", "yes", "on", "off", "n", "no" + }; + size_t i = 0; + for (; i < ARRAY_LENGTH(validValue); i++) { + if (strcasecmp(validValue[i], value) == 0) { + break; + } + } + if (i >= ARRAY_LENGTH(validValue)) { + PARAM_LOGE("Illegal param value %s for bool", value); + return PARAM_CODE_INVALID_VALUE; } } return 0; } -int ReadParamName(ParamWorkSpace *workSpace, ParamHandle handle, char *name, u_int32_t len) +INIT_LOCAL_API int CheckParamValue(const ParamTrieNode *node, const char *name, const char *value, uint8_t paramType) { - PARAM_CHECK(workSpace != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - DataEntry *entry = (DataEntry *)GetTrieNode(&workSpace->paramSpace, &handle); - if (entry == NULL) { - return -1; + if (IS_READY_ONLY(name)) { + PARAM_CHECK(strlen(value) < PARAM_CONST_VALUE_LEN_MAX, + return PARAM_CODE_INVALID_VALUE, "Illegal param value %s", value); + if (node != NULL && node->dataIndex != 0) { + PARAM_LOGE("Read-only param was already set %s", name); + return PARAM_CODE_READ_ONLY; + } + } else { + PARAM_CHECK(strlen(value) < GetParamMaxLen(paramType), + return PARAM_CODE_INVALID_VALUE, "Illegal param value %s length", value); } - return GetDataName(entry, name, len); + PARAM_CHECK(strstr(value, "\n") == NULL, + return PARAM_CODE_INVALID_VALUE, "Illegal param value %s for \\n", value); + return CheckParamValueType(name, value, paramType); } -u_int32_t ReadParamSerial(ParamWorkSpace *workSpace, ParamHandle handle) +static int ReadParamName(ParamHandle handle, char *name, uint32_t length) { - PARAM_CHECK(workSpace != NULL, return 0, "Invalid param"); - DataEntry *entry = (DataEntry *)GetTrieNode(&workSpace->paramSpace, &handle); - if (entry == NULL) { - return 0; + PARAM_CHECK(name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Param workspace has not init."); + PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND); + uint32_t labelIndex = 0; + uint32_t index = 0; + PARAM_GET_HANDLE_INFO(handle, labelIndex, index); + WorkSpace *workSpace = GetWorkSpace(labelIndex); + PARAM_CHECK(workSpace != NULL, return PARAM_CODE_NOT_FOUND, "Invalid workSpace for handle %x", handle); + ParamNode *entry = NULL; + if (PARAM_IS_ALIGNED(index)) { + entry = (ParamNode *)GetTrieNode(workSpace, index); } - return GetDataSerial(entry); -} - -int CheckControlParamPerms(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const char *name, const char *value) -{ - PARAM_CHECK(srcLabel != NULL && name != NULL && value != NULL, - return PARAM_CODE_INVALID_PARAM, "Invalid param"); - - char * ctrlName[] = { - "ctl.start", "ctl.stop", "ctl.restart" - }; - size_t size1 = strlen("ctl.") + strlen(value); - size_t size2 = strlen(name) + strlen(value) + 1; - size_t size = ((size1 > size2) ? size1 : size2) + 1; - char *legacyName = (char*)malloc(size); - PARAM_CHECK(legacyName != NULL, return PARAM_CODE_INVALID_PARAM, "Failed to alloc memory"); - - // We check the legacy method first but these parameters are dontaudit, so we only log an audit - // if the newer method fails as well. We only do this with the legacy ctl. parameters. - for (size_t i = 0; i < sizeof(ctrlName) / sizeof(char*); i++) { - if (strcmp(name, ctrlName[i]) == 0) { - // The legacy permissions model is that ctl. parameters have their name ctl. and - // their value is the name of the service to apply that action to. Permissions for these - // actions are based on the service, so we must create a fake name of ctl. to - // check permissions. - int n = snprintf_s(legacyName, size, strlen("ctl.") + strlen(value) + 1, "ctl.%s", value); - PARAM_CHECK(n > 0, free(legacyName); return PARAM_CODE_INVALID_PARAM, "Failed to snprintf value"); - legacyName[n] = '\0'; - - TrieDataNode *node = FindTrieDataNode(&workSpace->paramSpace, legacyName, strlen(legacyName), 1); - int ret = CheckMacPerms(workSpace, srcLabel, legacyName, node == NULL ? 0 : node->labelIndex); - if (ret == 0) { - free(legacyName); - return 0; - } - break; - } + if (entry == NULL) { + return PARAM_CODE_NOT_FOUND; } - int n = snprintf_s(legacyName, size, size, "%s$%s", name, value); - PARAM_CHECK(n > 0, free(legacyName); return PARAM_CODE_INVALID_PARAM, "Failed to snprintf value"); - - TrieDataNode *node = FindTrieDataNode(&workSpace->paramSpace, name, strlen(name), 1); - int ret = CheckMacPerms(workSpace, srcLabel, name, node == NULL ? 0 : node->labelIndex); - free(legacyName); - return ret; + PARAM_CHECK(length > entry->keyLength, return -1, "Invalid param size %u %u", entry->keyLength, length); + int ret = PARAM_MEMCPY(name, length, entry->data, entry->keyLength); + PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_PARAM, "Failed to copy name"); + name[entry->keyLength] = '\0'; + return 0; } -int CheckParamName(const char *name, int info) +INIT_LOCAL_API int CheckParamName(const char *name, int info) { + PARAM_CHECK(name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); size_t nameLen = strlen(name); if (nameLen >= PARAM_NAME_LEN_MAX) { return PARAM_CODE_INVALID_NAME; } + if (strcmp(name, "#") == 0) { + return 0; + } if (nameLen < 1 || name[0] == '.' || (!info && name[nameLen - 1] == '.')) { PARAM_LOGE("CheckParamName %s %d", name, info); @@ -367,168 +671,158 @@ int CheckParamName(const char *name, int info) return 0; } -int CheckParamValue(WorkSpace *workSpace, const TrieDataNode *node, const char *name, const char *value) +static int CheckParamPermission_(WorkSpace **workspace, ParamTrieNode **node, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) { - if (IS_READY_ONLY(name)) { - if (node != NULL && node->dataIndex != 0) { - PARAM_LOGE("Read-only param was already set %s", name); - return PARAM_CODE_READ_ONLY_PROPERTY; - } - } else { - // 限制非read only的参数,防止参数值修改后,原空间不能保存 - PARAM_CHECK(strlen(value) < PARAM_VALUE_LEN_MAX, - return PARAM_CODE_INVALID_VALUE, "Illegal param value"); - } - return 0; + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(srcLabel != NULL, return DAC_RESULT_FORBIDED, "The srcLabel is null"); + WorkSpace *dacSpace = GetWorkSpace(WORKSPACE_INDEX_DAC); + PARAM_CHECK(paramSpace->checkParamPermission != NULL, return DAC_RESULT_FORBIDED, "Invalid check permission"); + ParamLabelIndex labelIndex = {0}; + // search node from dac space, and get selinux label index + *node = FindTrieNode(dacSpace, name, strlen(name), &labelIndex.dacLabelIndex); + labelIndex.workspace = GetWorkSpaceByName(name); + PARAM_CHECK(labelIndex.workspace != NULL, return DAC_RESULT_FORBIDED, "Invalid workSpace for %s", name); + labelIndex.selinuxLabelIndex = labelIndex.workspace->spaceIndex; + + int ret = paramSpace->checkParamPermission(&labelIndex, srcLabel, name, mode); + PARAM_CHECK(ret == 0, return ret, + "Forbid to access %s label %u %u", name, labelIndex.dacLabelIndex, labelIndex.selinuxLabelIndex); + *workspace = labelIndex.workspace; + return ret; } -int CheckMacPerms(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const char *name, u_int32_t labelIndex) +INIT_LOCAL_API int CheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) { -#ifdef PARAM_SUPPORT_SELINUX - ParamAuditData auditData; - auditData.name = name; - auditData.cr = &srcLabel->cred; - - int ret = 0; - TrieNode *node = (TrieNode *)GetTrieNode(&workSpace->paramLabelSpace, &labelIndex); - if (node != 0) { // 已经存在label - ret = selinux_check_access(srcLabel, node->key, "param_service", "set", &auditData); - } else { - ret = selinux_check_access(srcLabel, "u:object_r:default_prop:s0", "param_service", "set", &auditData); - } - return ret == 0 ? 0 : PARAM_CODE_PERMISSION_DENIED; -#else - return 0; -#endif + ParamTrieNode *entry = NULL; + WorkSpace *workspace = NULL; + return CheckParamPermission_(&workspace, &entry, srcLabel, name, mode); } -int CanWriteParam(ParamWorkSpace *workSpace, - const ParamSecurityLabel *srcLabel, const TrieDataNode *node, const char *name, const char *value) +STATIC_INLINE ParamTrieNode *GetTrieNodeByHandle(ParamHandle handle) { - PARAM_CHECK(workSpace != NULL && name != NULL && value != NULL && srcLabel != NULL, - return PARAM_CODE_INVALID_PARAM, "Invalid param"); - - if (strncmp(name, "ctl.", strlen("ctl.")) == 0) { // 处理ctrl TODO - return CheckControlParamPerms(workSpace, srcLabel, name, value); + PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return NULL); + uint32_t labelIndex = 0; + uint32_t index = 0; + PARAM_GET_HANDLE_INFO(handle, labelIndex, index); + WorkSpace *workSpace = GetWorkSpace(labelIndex); + PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace for handle %x", handle); + if (PARAM_IS_ALIGNED(index)) { + return (ParamTrieNode *)GetTrieNode(workSpace, index); } - - int ret = CheckMacPerms(workSpace, srcLabel, name, node == NULL ? 0 : node->labelIndex); - PARAM_CHECK(ret == 0, return ret, "SELinux permission check failed"); - return 0; + return NULL; } -int CanReadParam(ParamWorkSpace *workSpace, u_int32_t labelIndex, const char *name) +STATIC_INLINE int ReadParamValue(ParamNode *entry, char *value, uint32_t *length) { - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); -#ifdef PARAM_SUPPORT_SELINUX - ParamAuditData auditData; - auditData.name = name; - UserCred cr = {.pid = 0, .uid = 0, .gid = 0}; - auditData.cr = &cr; - - int ret = 0; - TrieNode *node = (TrieNode *)GetTrieNode(&workSpace->paramLabelSpace, &labelIndex); - if (node != 0) { // 已经存在label - ret = selinux_check_access(&workSpace->context, node->key, "param_service", "read", &auditData); - } else { - ret = selinux_check_access(&workSpace->context, "selinux_check_access", "file", "read", &auditData); + if (entry == NULL) { + return PARAM_CODE_NOT_FOUND; } - return ret == 0 ? 0 : PARAM_CODE_PERMISSION_DENIED; -#else - return 0; -#endif + if (value == NULL) { + *length = entry->valueLength + 1; + return 0; + } + PARAM_CHECK(*length > entry->valueLength, return PARAM_CODE_INVALID_VALUE, + "Invalid value len %u %u", *length, entry->valueLength); + uint32_t commitId = ReadCommitId(entry); + return ReadParamValue_(entry, &commitId, value, length); } -int GetSubStringInfo(const char *buff, u_int32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber) +int SystemReadParam(const char *name, char *value, uint32_t *len) { - size_t i = 0; - // 去掉开始的空格 - for (; i < strlen(buff); i++) { - if (!isspace(buff[i])) { - break; - } - } - // 过滤掉注释 - if (buff[i] == '#') { - return -1; + PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return PARAM_WORKSPACE_NOT_INIT, + "SystemReadParam failed! name is:%s, errNum is:%d!", name, PARAM_WORKSPACE_NOT_INIT); + PARAM_CHECK(name != NULL && len != NULL, return PARAM_CODE_ERROR, + "SystemReadParam failed! name is:%s, errNum is:%d!", name, PARAM_CODE_ERROR); + ParamTrieNode *node = NULL; + WorkSpace *workspace = NULL; + int ret = CheckParamPermission_(&workspace, &node, GetParamSecurityLabel(), name, DAC_READ); + if (ret != 0) { + PARAM_LOGE("SystemReadParam failed! name is:%s, errNum is:%d!", name, ret); + return ret; } - // 分割字符串 - int spaceIsValid = 0; - int curr = 0; - int valueCurr = 0; - for (; i < buffLen; i++) { - if (buff[i] == '\n' || buff[i] == '\r') { - break; - } - if (buff[i] == delimiter && valueCurr != 0) { - info[curr].value[valueCurr] = '\0'; - valueCurr = 0; - curr++; - spaceIsValid = 1; - } else { - if (!spaceIsValid && isspace(buff[i])) { - continue; - } - if ((valueCurr + 1) >= (int)sizeof(info[curr].value)) { - continue; - } - info[curr].value[valueCurr++] = buff[i]; - } - if (curr >= subStrNumber) { - break; - } +#ifdef PARAM_SUPPORT_SELINUX + // search from real workspace + node = FindTrieNode(workspace, name, strlen(name), NULL); +#endif + if (node == NULL) { + return PARAM_CODE_NOT_FOUND; } - if (valueCurr > 0) { - info[curr].value[valueCurr] = '\0'; - valueCurr = 0; - curr++; + ret = ReadParamValue((ParamNode *)GetTrieNode(workspace, node->dataIndex), value, len); + if (ret != 0) { + PARAM_LOGE("SystemReadParam failed! name is:%s, errNum is:%d!", name, ret); } - return curr; + return ret; } -int BuildParamContent(char *content, u_int32_t contentSize, const char *name, const char *value) +int SystemFindParameter(const char *name, ParamHandle *handle) { - PARAM_CHECK(name != NULL && value != NULL && content != NULL, return -1, "Invalid param"); - u_int32_t nameLen = (u_int32_t)strlen(name); - u_int32_t valueLen = (u_int32_t)strlen(value); - PARAM_CHECK(contentSize >= (nameLen + valueLen + 2), return -1, "Invalid content size %u", contentSize); - - int offset = 0; - int ret = memcpy_s(content + offset, contentSize - offset, name, nameLen); - PARAM_CHECK(ret == 0, return -1, "Failed to copy porperty"); - offset += nameLen; - ret = memcpy_s(content + offset, contentSize - offset, "=", 1); - PARAM_CHECK(ret == 0, return -1, "Failed to copy porperty"); - offset += 1; - ret = memcpy_s(content + offset, contentSize - offset, value, valueLen); - offset += valueLen; - content[offset] = '\0'; - PARAM_CHECK(ret == 0, return -1, "Failed to copy porperty"); - offset += 1; - return offset; + PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return PARAM_WORKSPACE_NOT_INIT, "Param workspace has not init."); + PARAM_CHECK(name != NULL && handle != NULL, return -1, "The name or handle is null"); + *handle = -1; + ParamTrieNode *entry = NULL; + WorkSpace *workspace = NULL; + int ret = CheckParamPermission_(&workspace, &entry, GetParamSecurityLabel(), name, DAC_READ); + PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name); +#ifdef PARAM_SUPPORT_SELINUX + // search from real workspace + entry = FindTrieNode(workspace, name, strlen(name), NULL); +#endif + if (entry != NULL && entry->dataIndex != 0) { + *handle = PARAM_HANDLE(workspace, entry->dataIndex); + return 0; + } else if (entry != NULL) { + return PARAM_CODE_NODE_EXIST; + } + return PARAM_CODE_NOT_FOUND; } -int ProcessParamTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie) +int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId) { - ParamTraversalContext *context = (ParamTraversalContext *)cookie; - TrieDataNode *current = (TrieDataNode *)node; - if (current == NULL) { - return 0; + PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init."); + PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND); + PARAM_CHECK(handle != 0 && commitId != NULL, return -1, "The handle is null"); + ParamNode *entry = (ParamNode *)GetTrieNodeByHandle(handle); + if (entry == NULL) { + return PARAM_CODE_NOT_FOUND; } - if (current->dataIndex == 0) { + *commitId = ReadCommitId(entry); + return 0; +} + +long long GetSystemCommitId(void) +{ + PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init."); + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + if (space == NULL || space->area == NULL) { return 0; } - context->traversalParamPtr(current->dataIndex, context->context); - return 0; + return ATOMIC_UINT64_LOAD_EXPLICIT(&space->area->commitId, MEMORY_ORDER_ACQUIRE); +} + +int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len) +{ + PARAM_WORKSPACE_CHECK(GetParamWorkSpace(), return -1, "Param workspace has not init."); + PARAM_ONLY_CHECK(handle != (ParamHandle)-1, return PARAM_CODE_NOT_FOUND); + PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null"); + return ReadParamValue((ParamNode *)GetTrieNodeByHandle(handle), value, len); } -int TraversalParam(ParamWorkSpace *workSpace, TraversalParamPtr walkFunc, void *cookie) +INIT_LOCAL_API int CheckIfUidInGroup(const gid_t groupId, const char *groupCheckName) { - ParamTraversalContext context = { - walkFunc, cookie - }; - return TraversalTrieDataNode(&workSpace->paramSpace, - (TrieDataNode *)workSpace->paramSpace.rootNode, ProcessParamTraversal, &context); -} \ No newline at end of file + PARAM_CHECK(groupCheckName != NULL, return -1, "Invalid groupCheckName"); + struct group *groupName = getgrnam(groupCheckName); + PARAM_CHECK(groupName != NULL, return -1, "Not find %s group", groupCheckName); + char **gr_mem = groupName->gr_mem; + PARAM_CHECK(gr_mem != NULL, return -1, "No member in %s", groupCheckName); + for (int i = 0; gr_mem[i] != NULL; ++i) { + struct group *userGroup = getgrnam(gr_mem[i]); + if (userGroup != NULL) { + if (groupId == userGroup->gr_gid) { + return 0; + } + } + } + PARAM_LOGE("Forbid to access, groupId %u not in %s", groupId, groupCheckName); + return PARAM_CODE_PERMISSION_DENIED; +} diff --git a/services/param/manager/param_persist.c b/services/param/manager/param_persist.c new file mode 100644 index 0000000000000000000000000000000000000000..3ee14da5de868e236e966cc4932b469b21ac38f1 --- /dev/null +++ b/services/param/manager/param_persist.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2021-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 "param_persist.h" + +#include + +#include "init_param.h" +#include "init_utils.h" +#include "param_manager.h" +#include "param_trie.h" +#include "param_osadp.h" +#include "securec.h" + +static ParamPersistWorkSpace g_persistWorkSpace = {0, 0, NULL, {0}, {0}}; +static int IsNeedToSave(const char *name) +{ +#if defined(__LITEOS_M__) || defined(__LITEOS_A__) + return IS_READY_ONLY(name) ? 0 : 1; +#else + return (strncmp(name, PARAM_PERSIST_PREFIX, strlen(PARAM_PERSIST_PREFIX)) == 0) ? 1 : 0; +#endif +} + +static long long GetPersistCommitId(void) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return 0, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return 0, "Invalid space"); + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + if (space == NULL) { + return 0; + } + PARAMSPACE_AREA_RD_LOCK(space); + long long globalCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&space->area->commitPersistId, MEMORY_ORDER_ACQUIRE); + PARAMSPACE_AREA_RW_UNLOCK(space); + return globalCommitId; +} + +static void UpdatePersistCommitId(void) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space"); + WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); + if (space == NULL) { + return; + } + PARAMSPACE_AREA_RW_LOCK(space); + ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitPersistId, 1, MEMORY_ORDER_RELEASE); + PARAMSPACE_AREA_RW_UNLOCK(space); +} + +static int SavePersistParam(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie) +{ + ParamTrieNode *current = (ParamTrieNode *)node; + if (current == NULL || current->dataIndex == 0) { + return 0; + } + ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex); + if (entry == NULL) { + return 0; + } + + if (!IsNeedToSave(entry->data)) { + return 0; + } + + if ((entry->commitId & PARAM_FLAGS_PERSIST) == 0) { + return 0; + } + static char name[PARAM_NAME_LEN_MAX] = {0}; + int ret = memcpy_s(name, PARAM_NAME_LEN_MAX - 1, entry->data, entry->keyLength); + PARAM_CHECK(ret == EOK, return -1, "Failed to read param name %s", entry->data); + name[entry->keyLength] = '\0'; + ret = g_persistWorkSpace.persistParamOps.batchSave( + (PERSIST_SAVE_HANDLE)cookie, name, entry->data + entry->keyLength + 1); + PARAM_CHECK(ret == 0, return -1, "Failed to write param %s", current->key); + return ret; +} + +static int BatchSavePersistParam(void) +{ + PARAM_LOGV("BatchSavePersistParam"); + if (g_persistWorkSpace.persistParamOps.batchSaveBegin == NULL || + g_persistWorkSpace.persistParamOps.batchSave == NULL || + g_persistWorkSpace.persistParamOps.batchSaveEnd == NULL) { + return 0; + } +#if defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__) + PERSIST_SAVE_HANDLE handle; + int ret = g_persistWorkSpace.persistParamOps.batchSaveBegin(&handle); +#if defined(__LITEOS_M__) || defined(__LITEOS_A__) + const char *prefix = ""; +#else + const char *prefix = PARAM_PERSIST_PREFIX; +#endif +#else + PERSIST_SAVE_HANDLE handle[PERSIST_HANDLE_MAX] = { NULL, NULL }; + int ret = g_persistWorkSpace.persistParamOps.batchSaveBegin(handle); + const char *prefix = PARAM_PERSIST_PREFIX; +#endif + PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to save persist"); + // walk and save persist param + WorkSpace *workSpace = GetNextWorkSpace(NULL); + while (workSpace != NULL) { + WorkSpace *next = GetNextWorkSpace(workSpace); + ParamTrieNode *root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL); + PARAMSPACE_AREA_RD_LOCK(workSpace); + TraversalTrieNode(workSpace, root, SavePersistParam, (void *)handle); + PARAMSPACE_AREA_RW_UNLOCK(workSpace); + workSpace = next; + } + g_persistWorkSpace.persistParamOps.batchSaveEnd(handle); + PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Save persist param fail"); + + PARAM_CLEAR_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE); + (void)clock_gettime(CLOCK_MONOTONIC, &g_persistWorkSpace.lastSaveTimer); + return ret; +} + +INIT_LOCAL_API int InitPersistParamWorkSpace(void) +{ + if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { + return 0; + } + (void)clock_gettime(CLOCK_MONOTONIC, &g_persistWorkSpace.lastSaveTimer); + RegisterPersistParamOps(&g_persistWorkSpace.persistParamOps); + PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT); + return 0; +} + +INIT_LOCAL_API void ClosePersistParamWorkSpace(void) +{ + if (g_persistWorkSpace.saveTimer != NULL) { + ParamTimerClose(g_persistWorkSpace.saveTimer); + } + g_persistWorkSpace.flags = 0; +} + +void CheckAndSavePersistParam(void) +{ + // check commit + long long commit = GetPersistCommitId(); + PARAM_LOGV("CheckAndSavePersistParam commit %lld %lld", commit, g_persistWorkSpace.commitId); + if (g_persistWorkSpace.commitId == commit) { + return; + } + g_persistWorkSpace.commitId = commit; + (void)BatchSavePersistParam(); +} + +PARAM_STATIC void TimerCallbackForSave(const ParamTaskPtr timer, void *context) +{ + UNUSED(context); + UNUSED(timer); + PARAM_LOGV("TimerCallbackForSave "); + // for liteos-a must cycle check +#if (!defined(PARAM_SUPPORT_CYCLE_CHECK) || defined(PARAM_SUPPORT_REAL_CHECK)) + ParamTimerClose(g_persistWorkSpace.saveTimer); + g_persistWorkSpace.saveTimer = NULL; + if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE)) { + return; + } +#endif + CheckAndSavePersistParam(); +} + +INIT_LOCAL_API int WritePersistParam(const char *name, const char *value) +{ + PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); + if (!IsNeedToSave(name)) { + return 0; + } + PARAM_LOGV("WritePersistParam name %s ", name); + if (g_persistWorkSpace.persistParamOps.save != NULL) { + g_persistWorkSpace.persistParamOps.save(name, value); + } + // update commit for check + UpdatePersistCommitId(); + // for liteos-m, start task to check and save parameter + // for linux, start timer after set persist parameter + // for liteos-a, start timer in init to check and save parameter +#ifdef PARAM_SUPPORT_REAL_CHECK + if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) { + PARAM_LOGE("Can not save persist param before load %s ", name); + return 0; + } + if (g_persistWorkSpace.persistParamOps.batchSave == NULL) { + return 0; + } + + // check timer for save all + struct timespec currTimer = {0}; + (void)clock_gettime(CLOCK_MONOTONIC, &currTimer); + uint32_t diff = IntervalTime(&g_persistWorkSpace.lastSaveTimer, &currTimer); + if (diff > PARAM_MUST_SAVE_PARAM_DIFF) { + if (g_persistWorkSpace.saveTimer != NULL) { + ParamTimerClose(g_persistWorkSpace.saveTimer); + g_persistWorkSpace.saveTimer = NULL; + } + return BatchSavePersistParam(); + } + + PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE); + if (g_persistWorkSpace.saveTimer == NULL) { + ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL); + ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT); + } +#endif + return 0; +} + +int LoadPersistParams(void) +{ + // get persist parameter + int ret = InitPersistParamWorkSpace(); + PARAM_CHECK(ret == 0, return ret, "Failed to init persist param"); +#ifndef STARTUP_INIT_TEST + if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) { + PARAM_LOGE("Persist param has been loaded"); + return 0; + } +#endif +#if defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__) + if (g_persistWorkSpace.persistParamOps.load != NULL) { + (void)g_persistWorkSpace.persistParamOps.load(); + PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED); + } + // save new persist param + ret = BatchSavePersistParam(); + PARAM_CHECK(ret == 0, return ret, "Failed to load persist param"); + // for liteos-a, start time to check in init +#ifdef PARAM_SUPPORT_CYCLE_CHECK + PARAM_LOGV("LoadPersistParams start check time "); + if (g_persistWorkSpace.saveTimer == NULL) { + ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL); + ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT); + } +#endif +#else + if (g_persistWorkSpace.persistParamOps.load != NULL) { + (void)g_persistWorkSpace.persistParamOps.load(PUBLIC_PERSIST_FILE); + } +#endif + return 0; +} + +int LoadPrivatePersistParams(void) +{ +#if !(defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__)) +#ifndef STARTUP_INIT_TEST + if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) { + PARAM_LOGE("Persist param has been loaded"); + return 0; + } +#endif + if (g_persistWorkSpace.persistParamOps.load != NULL) { + (void)g_persistWorkSpace.persistParamOps.load(PRIVATE_PERSIST_FILE); + PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED); + } + // save new persist param + int ret = BatchSavePersistParam(); + PARAM_CHECK(ret == 0, return ret, "Failed to load persist param"); + // for liteos-a, start time to check in init +#ifdef PARAM_SUPPORT_CYCLE_CHECK + PARAM_LOGV("LoadPersistParams start check time "); + if (g_persistWorkSpace.saveTimer == NULL) { + ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL); + ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT); + } +#endif +#endif + return 0; +} \ No newline at end of file diff --git a/services/param/manager/param_server.c b/services/param/manager/param_server.c new file mode 100755 index 0000000000000000000000000000000000000000..2ba552cf5b760f174d4ae6088ba7bf3807517a22 --- /dev/null +++ b/services/param/manager/param_server.c @@ -0,0 +1,520 @@ +/* + * 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 "param_manager.h" +#include "param_trie.h" +#ifdef SUPPORT_PARAM_LOAD_HOOK +#include "init_module_engine.h" +#endif +#include "securec.h" +#include "init_cmds.h" +#include "init_param.h" + +/** + * Loading system parameter from /proc/cmdline by the following rules: + * 1) reserved cmdline with or without ohos.boot. prefix listed in CmdlineIterator + will be processed by the specified processor + * 2) cmdline not listed in CmdlineIterator but prefixed with ohos.boot will be add by default + * + * Special cases for sn: + * a) if sn value in cmdline is started with "/", it means a file to be read as parameter value + * b) if sn or ohos.boot.sn are not specified, try to generate sn by GenerateSnByDefault + */ +#define OHOS_CMDLINE_PARA_PREFIX "ohos.boot." +#define OHOS_CMDLINE_CONST_PARA_PREFIX "const.product." +#define OHOS_CMDLINE_PARA_PREFIX_LEN 10 +#define IMPORT_PREFIX_LEN 7 + +typedef struct CmdLineInfo { + const char *name; + int (*processor)(const char *name, const char *value); +} CmdLineInfo; + +typedef struct CmdLineInfoContainer { + const CmdLineInfo *cmdLineInfo; + size_t cmdLineInfoSize; +} CmdLineInfoContainer; + +typedef struct CmdLineIteratorCtx { + char *cmdline; + bool gotSn; + bool *matches; +} CmdLineIteratorCtx; + +static int CommonDealFun(const char *name, const char *value) +{ + int ret = 0; + PARAM_LOGV("Add param from cmdline %s %s", name, value); + ret = CheckParamName(name, 0); + PARAM_CHECK(ret == 0, return ret, "Invalid param name %s", name); + PARAM_LOGV("Param name %s, value %s", name, value); + ret = WriteParam(name, value, NULL, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value); + return ret; +} + +static int ReadSnFromFile(const char *name, const char *file) +{ + char *data = ReadFileData(file); + PARAM_CHECK(data != NULL, return -1, "Read sn from %s file failed!", file); + + int index = 0; + for (size_t i = 0; i < strlen(data); i++) { + // cancel \r\n + if (*(data + i) == '\r' || *(data + i) == '\n') { + break; + } + if (*(data + i) != ':') { + *(data + index) = *(data + i); + index++; + } + } + data[index] = '\0'; + PARAM_LOGV("**** name %s, value %s", name, data); + int ret = WriteParam(name, data, NULL, 0); + free(data); + PARAM_CHECK(ret == 0, return ret, "Failed to write param %s", name); + return ret; +} + +#define OHOS_SN_PARAM_NAME OHOS_CMDLINE_PARA_PREFIX"sn" + +static int SnDealFun(const char *name, const char *value) +{ + int ret = CheckParamName(name, 0); + PARAM_CHECK(ret == 0, return ret, "Invalid name %s", name); + if (value != NULL && value[0] != '/') { + PARAM_LOGV("**** name %s, value %s", name, value); + ret = WriteParam(OHOS_SN_PARAM_NAME, value, NULL, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", name, value); + return ret; + } + if (value != NULL && value[0] == '/') { + ret = ReadSnFromFile(OHOS_SN_PARAM_NAME, value); + if (ret == 0) { + return ret; + } + } + return ret; +} + +static int Common2ConstDealFun(const char *name, const char *value) +{ + const char *tmpName; + tmpName = name; + if (strncmp(tmpName, OHOS_CMDLINE_PARA_PREFIX, OHOS_CMDLINE_PARA_PREFIX_LEN) == 0) { + tmpName = tmpName + OHOS_CMDLINE_PARA_PREFIX_LEN; + } + char fullName[PARAM_NAME_LEN_MAX]; + int ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1, + OHOS_CMDLINE_CONST_PARA_PREFIX"%s", tmpName); + PARAM_CHECK(ret > 0, return ret, "snprinf_s failed"); + ret = CheckParamName(fullName, 0); + PARAM_CHECK(ret == 0, return ret, "Invalid name %s", name); + PARAM_LOGV("Param name %s, value %s", fullName, value); + ret = WriteParam(fullName, value, NULL, 0); + PARAM_CHECK(ret == 0, return ret, "Failed to write param %s %s", fullName, value); + return ret; +} + +static int MatchReserverCmdline(const NAME_VALUE_PAIR* nv, CmdLineIteratorCtx *ctx, const char *name, + CmdLineInfoContainer *container) +{ + const char* tmpName = name; + char fullName[PARAM_NAME_LEN_MAX]; + int ret = 0; + const char* matched; + + // Matching reserved cmdlines + for (size_t i = 0; i < container->cmdLineInfoSize; i++) { + // Check exact match + if (strcmp(tmpName, (container->cmdLineInfo + i)->name) != 0) { + // Check if contains ".xxx" for compatibility + ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1, ".%s", + (container->cmdLineInfo + i)->name); + matched = strstr(tmpName, fullName); + if (matched == NULL) { + continue; + } + // Check if it is ended with pattern + if (matched[ret] != '\0') { + continue; + } + } + ret = snprintf_s(fullName, sizeof(fullName), sizeof(fullName) - 1, + OHOS_CMDLINE_PARA_PREFIX "%s", (container->cmdLineInfo + i)->name); + if (ret <= 0) { + continue; + } + if (ctx->matches[i]) { + return PARAM_CODE_SUCCESS; + } + bool isSnSet = ((container->cmdLineInfo + i)->processor == SnDealFun); + if (isSnSet && ctx->gotSn) { + return PARAM_CODE_SUCCESS; + } + PARAM_LOGV("proc cmdline %s matched.", fullName); + ret = (container->cmdLineInfo + i)->processor(fullName, nv->value); + if (ret == 0) { + ctx->matches[i] = true; + if (isSnSet) { + ctx->gotSn = true; + } + } + return PARAM_CODE_SUCCESS; + } + return PARAM_CODE_NOT_FOUND; +} + +static const CmdLineInfo CMDLINES[] = { + { "hardware", CommonDealFun }, + { "bootgroup", CommonDealFun }, + { "reboot_reason", CommonDealFun }, + { "bootslots", CommonDealFun }, + { "sn", SnDealFun }, + { "root_package", CommonDealFun }, + { "serialno", SnDealFun }, + { "udid", Common2ConstDealFun }, + { "productid", Common2ConstDealFun } +}; + +static void CmdlineIterator(const NAME_VALUE_PAIR *nv, void *context) +{ + CmdLineIteratorCtx *ctx = (CmdLineIteratorCtx *)context; + char *data = (char *)ctx->cmdline; + + data[nv->nameEnd - data] = '\0'; + data[nv->valueEnd - data] = '\0'; + PARAM_LOGV("proc cmdline: name [%s], value [%s]", nv->name, nv->value); + + // Get name without prefix + const char *name = nv->name; + if (strncmp(name, OHOS_CMDLINE_PARA_PREFIX, OHOS_CMDLINE_PARA_PREFIX_LEN) == 0) { + name = name + OHOS_CMDLINE_PARA_PREFIX_LEN; + } + + CmdLineInfoContainer container = { 0 }; + container.cmdLineInfo = CMDLINES; + container.cmdLineInfoSize = ARRAY_LENGTH(CMDLINES); + if (MatchReserverCmdline(nv, ctx, name, &container) == 0) { + PARAM_LOGV("match reserver cmd line success, name: %s, value: %s", nv->name, nv->value); + return; + } + if (name == nv->name) { + return; + } + + // cmdline with prefix but not matched, add to param by default + PARAM_LOGI("add proc cmdline param %s by default.", nv->name); + CommonDealFun(nv->name, nv->value); +} + +static void GenerateSnByDefault(void) +{ + const char *snFileList [] = { + "/sys/block/mmcblk0/device/cid", + "/proc/bootdevice/cid" + }; + + for (size_t i = 0; i < ARRAY_LENGTH(snFileList); i++) { + int ret = ReadSnFromFile(OHOS_CMDLINE_PARA_PREFIX "sn", snFileList[i]); + if (ret == 0) { + break; + } + } +} + +INIT_LOCAL_API int LoadParamFromCmdLine(void) +{ + CmdLineIteratorCtx ctx; + + ctx.gotSn = false; + ctx.cmdline = ReadFileData(BOOT_CMD_LINE); + PARAM_CHECK(ctx.cmdline != NULL, return -1, "Failed to read file %s", BOOT_CMD_LINE); + bool matches[ARRAY_LENGTH(CMDLINES)] = {false}; + ctx.matches = matches; + IterateNameValuePairs(ctx.cmdline, CmdlineIterator, (void *)(&ctx)); + + // sn is critical, it must be specified + if (!ctx.gotSn) { + PARAM_LOGE("Generate default sn now ..."); + GenerateSnByDefault(); + } + + free(ctx.cmdline); + return 0; +} + +/* + * Load parameters from files + */ + +static int LoadSecurityLabel(const char *fileName) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL, return -1, "Invalid paramSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return -1, "Invalid space"); + PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load"); +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + // load security label + ParamSecurityOps *ops = GetParamSecurityOps(PARAM_SECURITY_DAC); + if (ops != NULL && ops->securityGetLabel != NULL) { + if (ops->securityGetLabel(fileName) == PARAM_CODE_REACHED_MAX) { + PARAM_LOGE("[startup_failed]Load Security Lable failed! system reboot! %d", SYS_PARAM_INIT_FAILED); + ExecReboot("panic"); + }; + } +#endif + return 0; +} + +static int LoadOneParam_(const uint32_t *context, const char *name, const char *value) +{ + uint32_t mode = *(uint32_t *)context; + int ret = CheckParamName(name, 0); + if (ret != 0) { + return 0; + } + +#ifdef SUPPORT_PARAM_LOAD_HOOK + PARAM_LOAD_FILTER_CTX filter; + + // Filter by hook + filter.name = name; + filter.value = value; + filter.ignored = 0; + HookMgrExecute(GetBootStageHookMgr(), INIT_PARAM_LOAD_FILTER, (void *)&filter, NULL); + + if (filter.ignored) { + PARAM_LOGV("Default parameter [%s] [%s] ignored", name, value); + return 0; + } +#endif + + PARAM_LOGV("Add default parameter [%s] [%s]", name, value); + return WriteParam(name, value, NULL, mode & LOAD_PARAM_ONLY_ADD); +} + +static int LoadFileFromImport(char *target, uint32_t mode) +{ + if (strstr(target, ".para.dac")) { + LoadSecurityLabel(target); + } else { + LoadDefaultParams(target, mode); + } + return 0; +} + +// Content format of .import.para is "import /dir/param.para" +// Use ${} to pass parameter like "import /dir/${const.product.productid}.para" +static int LoadParamFromImport_(char *buffer, const int buffSize, uint32_t mode) +{ + int spaceCount = 0; + while (*(buffer + IMPORT_PREFIX_LEN + spaceCount) == ' ') { + spaceCount++; + } + char *target = calloc(PATH_MAX, 1); + PARAM_CHECK(target != NULL, return -1, "Failed to alloc memory"); + if (strncpy_s(target, PATH_MAX, buffer + IMPORT_PREFIX_LEN + spaceCount, buffSize) != 0) { + PARAM_LOGE("Failed to get value of import."); + free(target); + return -1; + } + char *tmp = NULL; + if ((tmp = strstr(target, "\n"))) { + *tmp = '\0'; + } + char *tmpParamValue = calloc(PARAM_VALUE_LEN_MAX + 1, sizeof(char)); + if (tmpParamValue == NULL) { + PARAM_LOGE("Failed to alloc memory"); + free(target); + return -1; + } + int ret = GetParamValue(target, strlen(target), tmpParamValue, PARAM_VALUE_LEN_MAX); + if (ret == 0) { + LoadFileFromImport(tmpParamValue, mode); + } + PARAM_LOGI("Load params from import %s return %d.", tmpParamValue, ret); + free(tmpParamValue); + free(target); + return ret; +} + +static int LoadParamFromImport(const char *fileName, void *context) +{ + char realPath[PATH_MAX] = ""; + realpath(fileName, realPath); + FILE *fp = fopen(realPath, "r"); + if (fp == NULL) { + PARAM_LOGE("Failed to open file '%s' error:%d ", fileName, errno); + return -1; + } + + const int buffSize = PATH_MAX; + char *buffer = calloc(buffSize, sizeof(char)); + PARAM_CHECK(buffer != NULL, (void)fclose(fp); + return -1, "Failed to alloc memory"); + + uint32_t mode = *(int *)context; + while (fgets(buffer, buffSize, fp) != NULL) { + buffer[buffSize - 1] = '\0'; + if (!strncmp(buffer, "import ", IMPORT_PREFIX_LEN)) { + (void)LoadParamFromImport_(buffer, buffSize, mode); + } + } + (void)fclose(fp); + free(buffer); + return 0; +} + +static int LoadDefaultParam_(const char *fileName, uint32_t mode, + const char *exclude[], uint32_t count, int (*loadOneParam)(const uint32_t *, const char *, const char *)) +{ + uint32_t paramNum = 0; + char realPath[PATH_MAX] = ""; + realpath(fileName, realPath); + FILE *fp = fopen(realPath, "r"); + if (fp == NULL) { + PARAM_LOGW("Failed to open file '%s' error:%d ", fileName, errno); + return -1; + } + + const int buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 max len + char *buffer = calloc(buffSize, sizeof(char)); + PARAM_CHECK(buffer != NULL, (void)fclose(fp); + return -1, "Failed to alloc memory"); + + while (fgets(buffer, buffSize, fp) != NULL) { + buffer[buffSize - 1] = '\0'; + int ret = SplitParamString(buffer, exclude, count, loadOneParam, &mode); + PARAM_ONLY_CHECK(ret != PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH, + (void)fclose(fp); free(buffer); return PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH); + if (mode == LOAD_PARAM_ONLY_ADD && ret == PARAM_CODE_READ_ONLY) { + PARAM_WARNING_CHECK(ret == 0, continue, "Set param '%s' error:%d with only add mode", buffer, ret); + } else { + PARAM_CHECK(ret == 0, continue, "Failed to set param '%s' error:%d ", buffer, ret); + } + paramNum++; + } + (void)fclose(fp); + free(buffer); + PARAM_LOGV("Load %u default parameters success from %s.", paramNum, fileName); + return 0; +} + +static int ProcessParamFile(const char *fileName, void *context) +{ + static const char *exclude[] = {"ctl.", "selinux.restorecon_recursive"}; + uint32_t mode = *(int *)context; + int ret = LoadDefaultParam_(fileName, mode, exclude, ARRAY_LENGTH(exclude), LoadOneParam_); + if (ret == PARAM_DEFAULT_PARAM_MEMORY_NOT_ENOUGH) { + PARAM_LOGE("[startup_failed]default_param memory is not enough, system reboot! %d", SYS_PARAM_INIT_FAILED); + ExecReboot("panic"); + } + return ret; +} + +int LoadParamsFile(const char *fileName, bool onlyAdd) +{ + return LoadDefaultParams(fileName, onlyAdd ? LOAD_PARAM_ONLY_ADD : LOAD_PARAM_NORMAL); +} + +int LoadDefaultParams(const char *fileName, uint32_t mode) +{ + PARAM_CHECK(fileName != NULL, return -1, "Invalid filename for load"); + PARAM_LOGI("Load default parameters from %s.", fileName); + struct stat st; + if ((stat(fileName, &st) == 0) && !S_ISDIR(st.st_mode)) { + if (strstr(fileName, ".para.dac")) { + return LoadSecurityLabel(fileName); + } else { + return ProcessParamFile(fileName, &mode); + } + } else { + (void)ReadFileInDir(fileName, ".para", ProcessParamFile, &mode); + (void)ReadFileInDir(fileName, ".para.import", LoadParamFromImport, &mode); + return LoadSecurityLabel(fileName); + } +} + +INIT_LOCAL_API void LoadParamFromBuild(void) +{ + PARAM_LOGI("load parameters from build "); +#ifdef INCREMENTAL_VERSION + if (strlen(INCREMENTAL_VERSION) > 0) { + WriteParam("const.product.incremental.version", INCREMENTAL_VERSION, NULL, LOAD_PARAM_NORMAL); + } +#endif +#ifdef BUILD_TYPE + if (strlen(BUILD_TYPE) > 0) { + WriteParam("const.product.build.type", BUILD_TYPE, NULL, LOAD_PARAM_NORMAL); + } +#endif +#ifdef BUILD_USER + if (strlen(BUILD_USER) > 0) { + WriteParam("const.product.build.user", BUILD_USER, NULL, LOAD_PARAM_NORMAL); + } +#endif +#ifdef BUILD_TIME + if (strlen(BUILD_TIME) > 0) { + WriteParam("const.product.build.date", BUILD_TIME, NULL, LOAD_PARAM_NORMAL); + } +#endif +#ifdef BUILD_HOST + if (strlen(BUILD_HOST) > 0) { + WriteParam("const.product.build.host", BUILD_HOST, NULL, LOAD_PARAM_NORMAL); + } +#endif +#ifdef BUILD_ROOTHASH + if (strlen(BUILD_ROOTHASH) > 0) { + WriteParam("const.ohos.buildroothash", BUILD_ROOTHASH, NULL, LOAD_PARAM_NORMAL); + } +#endif +} + +static int LoadOneParamAreaSize_(const uint32_t *context, const char *name, const char *value) +{ + uint32_t size = (uint32_t)strtoul(value, NULL, DECIMAL_BASE); + PARAM_LOGV("LoadOneParamAreaSize_ [%s] [%s]", name, value); + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != NULL && paramSpace->workSpace != NULL, + return -1, "Invalid workspace name %s", name); + WorkSpaceSize *spaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE)); + PARAM_CHECK(spaceSize != NULL, return PARAM_CODE_ERROR, "Failed to get workspace size"); + static char buffer[SELINUX_CONTENT_LEN] = {0}; + int ret = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "u:object_r:%s:s0", name); + PARAM_CHECK(ret > 0, return PARAM_CODE_ERROR, "Failed to snprintf workspace name"); + + for (uint32_t i = WORKSPACE_INDEX_BASE + 1; i < spaceSize->maxLabelIndex; i++) { + if (paramSpace->workSpace[i] == NULL) { + continue; + } + if (strcmp(paramSpace->workSpace[i]->fileName, buffer) == 0) { + spaceSize->spaceSize[i] = size; + paramSpace->workSpace[i]->spaceSize = size; + break; + } + } + return 0; +} + +INIT_LOCAL_API void LoadParamAreaSize(void) +{ + LoadDefaultParam_("/sys_prod/etc/param/ohos.para.size", 0, NULL, 0, LoadOneParamAreaSize_); + LoadDefaultParam_(PARAM_AREA_SIZE_CFG, 0, NULL, 0, LoadOneParamAreaSize_); +} diff --git a/services/param/manager/param_trie.c b/services/param/manager/param_trie.c deleted file mode 100644 index c380a87869dab5896f3020900a8c9321f3167cca..0000000000000000000000000000000000000000 --- a/services/param/manager/param_trie.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2020 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 "param_trie.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "init_utils.h" -#include "sys_param.h" -#include "param_manager.h" - -#define LABEL "Manager" - -int InitWorkSpace(const char *fileName, WorkSpace *workSpace, int onlyRead) -{ - PARAM_CHECK(fileName != NULL, return PARAM_CODE_INVALID_NAME, "Invalid param"); - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_NAME, "Invalid param"); - if (workSpace->area != NULL) { - return 0; - } - - int ret = memcpy_s(workSpace->fileName, FILENAME_LEN_MAX, fileName, strlen(fileName)); - PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Copy file %s fail ", fileName); - int openMode = 0; - int prot = PROT_READ; - if (onlyRead) { - openMode = O_RDONLY; - } else { - openMode = O_CREAT | O_RDWR | O_TRUNC; - prot = PROT_READ | PROT_WRITE; - } - ret = InitWorkSpace_(workSpace, openMode, prot, PARAM_WORKSPACE_MAX, onlyRead); - PARAM_CHECK(ret == 0, return ret, "Failed to init workspace %s", workSpace->fileName); - return ret; -} - -int InitPersistWorkSpace(const char *fileName, WorkSpace *workSpace) -{ - PARAM_CHECK(fileName != NULL, return PARAM_CODE_INVALID_NAME, "Invalid param"); - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_NAME, "Invalid param"); - if (workSpace->area != NULL) { - return 0; - } - - int ret = memcpy_s(workSpace->fileName, FILENAME_LEN_MAX, fileName, strlen(fileName)); - PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Copy file %s fail ", fileName); - - int flag = (access(fileName, F_OK) == 0) ? 1 : 0; - int openMode = (flag == 0) ? (O_CREAT | O_RDWR | O_TRUNC) : O_RDWR; - int prot = PROT_READ | PROT_WRITE; - ret = InitWorkSpace_(workSpace, openMode, prot, PARAM_WORKSPACE_MAX, flag); - PARAM_CHECK(ret == 0, return ret, "Failed to init workspace %s", workSpace->fileName); - return ret; -} - -int InitWorkSpace_(WorkSpace *workSpace, int mode, int prot, u_int32_t spaceSize, int readOnly) -{ - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid fileName"); - PARAM_CHECK(workSpace->allocTrieNode != NULL, - return PARAM_CODE_INVALID_PARAM, "Invalid param %s", workSpace->fileName); - PARAM_CHECK(workSpace->compareTrieNode != NULL, - return PARAM_CODE_INVALID_PARAM, "Invalid param %s", workSpace->fileName); - PARAM_LOGD("InitWorkSpace %s ", workSpace->fileName); - CheckAndCreateDir(workSpace->fileName); - - int fd = open(workSpace->fileName, mode, 00777); //0444); - PARAM_CHECK(fd >= 0, return PARAM_CODE_INVALID_NAME, - "Open file %s fail error %s", workSpace->fileName, strerror(errno)); - - if (!readOnly) { - lseek(fd, spaceSize - 1, SEEK_SET); - write(fd, "", 1); - } - void *areaAddr = (void *)mmap(NULL, spaceSize, prot, MAP_SHARED, fd, 0); - PARAM_CHECK(areaAddr != MAP_FAILED, close(fd); return PARAM_CODE_ERROR_MAP_FILE, - "Failed to map memory error %s", strerror(errno)); - close(fd); - - if (!readOnly) { - workSpace->area = (WorkArea*)areaAddr; - atomic_init(&workSpace->area->serial, 0); - workSpace->area->dataSize = spaceSize; - workSpace->area->currOffset = sizeof(WorkArea); - // 创建一个key为#的节点 - u_int32_t offset = workSpace->allocTrieNode(workSpace, "#", 1); - workSpace->area->firstNode = offset; - workSpace->rootNode = GetTrieNode(workSpace, &offset); - } else { - workSpace->area = (WorkArea*)areaAddr; - workSpace->rootNode = GetTrieNode(workSpace, &workSpace->area->firstNode); - } - PARAM_LOGD("InitWorkSpace success, readOnly %d currOffset %u firstNode %u dataSize %u", - readOnly, workSpace->area->currOffset, workSpace->area->firstNode, workSpace->area->dataSize); - return 0; -} - -void CloseWorkSpace(WorkSpace *workSpace) -{ - PARAM_CHECK(workSpace != NULL && workSpace->area != NULL, return, "The workspace is null"); - munmap((char *)workSpace->area, workSpace->area->dataSize); - workSpace->area = NULL; -} - -u_int32_t GetWorkSpaceSerial(WorkSpace *workSpace) -{ - PARAM_CHECK(workSpace != NULL && workSpace->area != NULL, return 0, "The workspace is null"); - return (u_int32_t)workSpace->area->serial; -} - -u_int32_t AllocateTrieNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen) -{ - u_int32_t len = keyLen + sizeof(TrieNode) + 1; - len = (len + 0x03) & (~0x03); - PARAM_CHECK((workSpace->area->currOffset + len) < workSpace->area->dataSize, return 0, - "Failed to allocate currOffset %d, dataSize %d", workSpace->area->currOffset, workSpace->area->dataSize); - TrieNode *node = (TrieNode*)(workSpace->area->data + workSpace->area->currOffset + len); - - atomic_init(&node->serial, ATOMIC_VAR_INIT(keyLen << TRIE_SERIAL_KEY_LEN_OFFSET)); - int ret = memcpy_s(node->key, keyLen, key, keyLen); - PARAM_CHECK(ret == 0, return 0, "Failed to copy key"); - node->key[keyLen] = '\0'; - node->left = 0; - node->right = 0; - u_int32_t offset = workSpace->area->currOffset; - workSpace->area->currOffset += len; - return offset; -} - -u_int32_t AllocateTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen) -{ - u_int32_t len = keyLen + sizeof(TrieDataNode) + 1; - len = (len + 0x03) & (~0x03); - PARAM_CHECK((workSpace->area->currOffset + len) < workSpace->area->dataSize, return 0, - "Failed to allocate currOffset %d, dataSize %d", workSpace->area->currOffset, workSpace->area->dataSize); - TrieDataNode *node = (TrieDataNode*)(workSpace->area->data + workSpace->area->currOffset); - - atomic_init(&node->serial, ATOMIC_VAR_INIT(keyLen << TRIE_SERIAL_KEY_LEN_OFFSET)); - int ret = memcpy_s(node->key, keyLen, key, keyLen); - PARAM_CHECK(ret == 0, return 0, "Failed to copy key"); - node->key[keyLen] = '\0'; - node->left = 0; - node->right = 0; - node->child = 0; - node->dataIndex = 0; - node->labelIndex = 0; - u_int32_t offset = workSpace->area->currOffset; - workSpace->area->currOffset += len; - return offset; -} - -TrieNode *GetTrieNode(WorkSpace *workSpace, NODE_INDEX *index) -{ - if (index == NULL) { - return NULL; - } - u_int32_t offset = *index; // atomic_load_explicit(¤t->children, memory_order_relaxed); - if (offset == 0 || offset > workSpace->area->dataSize) { - return NULL; - } - return (TrieNode*)(workSpace->area->data + offset); -} - -u_int32_t GetTrieKeyLen(TrieNode *current) -{ - return (current)->serial >> TRIE_SERIAL_KEY_LEN_OFFSET; -} - -u_int32_t GetTrieNodeOffset(WorkSpace *workSpace, const TrieNode *current) -{ - return (((char *)current) - workSpace->area->data); -} - -void SaveIndex(NODE_INDEX *index, u_int32_t offset) -{ - // atomic_store_explicit(¤t->children, new_offset, memory_order_release); - *index = offset; -} - -int CompareTrieDataNode(TrieNode *node, const char *key, u_int32_t keyLen) -{ - TrieDataNode *data = (TrieDataNode *)node; - u_int32_t len = GetTrieKeyLen((TrieNode *)data); - if (len > keyLen) { - return -1; - } else if (len < keyLen) { - return 1; - } - return strncmp(data->key, key, keyLen); -} - -int CompareTrieNode(TrieNode *node, const char *key, u_int32_t keyLen) -{ - u_int32_t len = GetTrieKeyLen(node); - if (len > keyLen) { - return -1; - } else if (len < keyLen) { - return 1; - } - return strncmp(node->key, key, keyLen); -} - -static void GetNextKey(const char **remainingKey, char **subKey, u_int32_t *subKeyLen) -{ - *subKey = strchr(*remainingKey, '.'); - if (*subKey != NULL) { - *subKeyLen = *subKey - *remainingKey; - } else { - *subKeyLen = strlen(*remainingKey); - } -} - -TrieDataNode *AddTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen) -{ - PARAM_CHECK(workSpace->allocTrieNode != NULL, return NULL, "Invalid param %s", key); - PARAM_CHECK(workSpace->compareTrieNode != NULL, return NULL, "Invalid param %s", key); - - const char *remainingKey = key; - TrieDataNode *current = (TrieDataNode *)workSpace->rootNode; - PARAM_CHECK(current != NULL, return NULL, "Invalid current param %s", key); - while (1) { - u_int32_t subKeyLen = 0; - char *subKey = NULL; - GetNextKey(&remainingKey, &subKey, &subKeyLen); - if (!subKeyLen) { - return NULL; - } - u_int32_t offset = subKey == NULL ? strlen(key) : subKey - key; - - if (current->child != 0) { // 如果child存在,则检查是否匹配 - TrieDataNode *next = (TrieDataNode*)GetTrieNode(workSpace, ¤t->child); - if (next != NULL && workSpace->compareTrieNode((TrieNode*)next, remainingKey, subKeyLen) == 0) { - current = next; - } else { // 不匹配,需要建立子树 - current = (TrieDataNode*)AddToSubTrie(workSpace, current, key, offset); - } - } else { - current = (TrieDataNode*)AddToSubTrie(workSpace, current, key, offset); - } - if (current == NULL) { - return NULL; - } - if (subKey == NULL || strcmp(subKey, ".") == 0) { - break; - } - remainingKey = subKey + 1; - } - return current; -} - -TrieDataNode *AddToSubTrie(WorkSpace *workSpace, TrieDataNode *dataNode, const char *key, u_int32_t keyLen) -{ - TrieDataNode *root = NULL; - int ret = workSpace->compareTrieNode((TrieNode *)dataNode, key, keyLen); - if (ret <= 0) { - root = (TrieDataNode *)GetTrieNode(workSpace, &dataNode->left); - if (root == NULL) { - u_int32_t offset = workSpace->allocTrieNode(workSpace, key, keyLen); - PARAM_CHECK(offset != 0, return NULL, "Failed to allocate key %s", key); - SaveIndex(&dataNode->left, offset); - return (TrieDataNode *)GetTrieNode(workSpace, &dataNode->left); - } - } else { - root = (TrieDataNode *)GetTrieNode(workSpace, &dataNode->right); - if (root == NULL) { - u_int32_t offset = workSpace->allocTrieNode(workSpace, key, keyLen); - PARAM_CHECK(offset != 0, return NULL, "Failed to allocate key %s", key); - SaveIndex(&dataNode->right, offset); - return (TrieDataNode *)GetTrieNode(workSpace, &dataNode->right); - } - } - return (TrieDataNode*)AddTrieNode(workSpace, (TrieNode*)root, key, keyLen); -} - -TrieNode *AddTrieNode(WorkSpace *workSpace, TrieNode *root, const char *key, u_int32_t keyLen) -{ - PARAM_CHECK(root != NULL, return NULL, "Invalid param %s", key); - TrieNode *current = root; - TrieNode *next = NULL; - while (1) { - if (current == NULL) { - return NULL; - } - int ret = workSpace->compareTrieNode(current, key, keyLen); - if (ret == 0) { - return current; - } - if (ret < 0) { - next = GetTrieNode(workSpace, ¤t->left); - if (next == NULL) { - u_int32_t offset = workSpace->allocTrieNode(workSpace, key, keyLen); - PARAM_CHECK(offset != 0, return NULL, "Failed to allocate key %s", key); - SaveIndex(¤t->left, offset); - return GetTrieNode(workSpace, ¤t->left); - } - } else { - next = GetTrieNode(workSpace, ¤t->right); - if (next == NULL) { - u_int32_t offset = workSpace->allocTrieNode(workSpace, key, keyLen); - PARAM_CHECK(offset != 0, return NULL, "Failed to allocate key %s", key); - SaveIndex(¤t->right, offset); - return GetTrieNode(workSpace, ¤t->right); - } - } - current = next; - } - return current; -} - -TrieDataNode *FindTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen, int matchPrefix) -{ - PARAM_CHECK(workSpace->allocTrieNode != NULL, return NULL, "Invalid param %s", key); - PARAM_CHECK(workSpace->compareTrieNode != NULL, return NULL, "Invalid param %s", key); - - const char *remainingKey = key; - TrieDataNode *matchNode = (TrieDataNode *)workSpace->rootNode; - TrieDataNode *current = (TrieDataNode *)workSpace->rootNode; - PARAM_CHECK(current != NULL, return NULL, "Invalid current param %s", key); - while (1) { - u_int32_t subKeyLen = 0; - char *subKey = NULL; - GetNextKey(&remainingKey, &subKey, &subKeyLen); - if (!subKeyLen) { - return matchPrefix ? matchNode : NULL; - } - u_int32_t offset = subKey == NULL ? strlen(key) : subKey - key; - - if (current->child != 0) { // 如果child存在,则检查是否匹配 - TrieDataNode *next = (TrieDataNode*)GetTrieNode(workSpace, ¤t->child); - if (next != NULL && workSpace->compareTrieNode((TrieNode*)next, remainingKey, subKeyLen) == 0) { - current = next; - } else { // 不匹配,搜索子树 - current = (TrieDataNode*)FindSubTrie(workSpace, current, key, offset); - } - } else { - current = (TrieDataNode*)FindSubTrie(workSpace, current, key, offset); - } - if (current == NULL) { - return matchPrefix ? matchNode : NULL; - } - matchNode = current; - if (subKey == NULL || strcmp(subKey, ".") == 0) { - break; - } - remainingKey = subKey + 1; - } - return matchPrefix ? matchNode : current; -} - -TrieDataNode *FindSubTrie(WorkSpace *workSpace, TrieDataNode *dataNode, const char *key, u_int32_t keyLen) -{ - TrieDataNode *root = NULL; - int ret = workSpace->compareTrieNode((TrieNode*)dataNode, key, keyLen); - if (ret <= 0) { - root = (TrieDataNode *)GetTrieNode(workSpace, &dataNode->left); - if (root == NULL) { - return NULL; - } - } else { - root = (TrieDataNode *)GetTrieNode(workSpace, &dataNode->right); - if (root == NULL) { - return NULL; - } - } - return (TrieDataNode*)FindTrieNode(workSpace, (TrieNode*)root, key, keyLen); -} - -TrieNode *FindTrieNode(WorkSpace *workSpace, TrieNode *root, const char *key, u_int32_t keyLen) -{ - PARAM_CHECK(root != NULL, return NULL, "Invalid param %s", key); - TrieNode *current = root; - TrieNode *next = NULL; - while (1) { - if (current == NULL) { - return NULL; - } - int ret = workSpace->compareTrieNode(current, key, keyLen); - if (ret == 0) { - return current; - } - if (ret < 0) { - next = GetTrieNode(workSpace, ¤t->left); - } else { - next = GetTrieNode(workSpace, ¤t->right); - } - if (next == NULL) { - return NULL; - } - current = next; - } - return current; -} - -int TraversalTrieDataNode(WorkSpace *workSpace, TrieDataNode *current, TraversalTrieNodePtr walkFunc, void* cookie) -{ - PARAM_CHECK(walkFunc != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - if (current == NULL) { - return 0; - } - - while (1) { - TrieDataNode *child = NULL; - // 显示子树 - TraversalTrieDataNode(workSpace, (TrieDataNode*)GetTrieNode(workSpace, ¤t->left), walkFunc, cookie); - TraversalTrieDataNode(workSpace, (TrieDataNode*)GetTrieNode(workSpace, ¤t->right), walkFunc, cookie); - walkFunc(workSpace, (TrieNode *)current, cookie); - - if (current->child != 0) { // 如果child存在,则检查是否匹配 - child = (TrieDataNode*)GetTrieNode(workSpace, ¤t->child); - } - if (child == NULL) { - return 0; - } - current = child; - } - return 0; -} - -int TraversalTrieNode(WorkSpace *workSpace, TrieNode *root, TraversalTrieNodePtr walkFunc, void* cookie) -{ - PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - PARAM_CHECK(walkFunc != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - if (root == NULL) { - return 0; - } - TraversalTrieNode(workSpace, GetTrieNode(workSpace, &root->left), walkFunc, cookie); - TraversalTrieNode(workSpace, GetTrieNode(workSpace, &root->right), walkFunc, cookie); - walkFunc(workSpace, (TrieNode *)root, cookie); - return 0; -} - -u_int32_t AddData(WorkSpace *workSpace, const char *key, u_int32_t keyLen, const char *value, u_int32_t valueLen) -{ - PARAM_CHECK(workSpace != NULL, return 0, "Invalid param"); - PARAM_CHECK(key != NULL && value != NULL, return 0, "Invalid param"); - u_int32_t realLen = sizeof(DataEntry) + 1 + 1; - if (valueLen > PARAM_VALUE_LEN_MAX) { - realLen += keyLen + valueLen; - } else { - realLen += keyLen + PARAM_VALUE_LEN_MAX; - } - realLen = (realLen + 0x03) & (~0x03); - //PARAM_LOGI("AddData realLen %u %u %u", realLen, keyLen, valueLen); - PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, return 0, - "Failed to allocate currOffset %d, dataSize %d", workSpace->area->currOffset, workSpace->area->dataSize); - - DataEntry *node = (DataEntry*)(workSpace->area->data + workSpace->area->currOffset); - u_int32_t dataLength = keyLen << TRIE_SERIAL_KEY_LEN_OFFSET | valueLen << TRIE_SERIAL_DATA_LEN_OFFSET; - atomic_init(&node->serial, ATOMIC_VAR_INIT(0)); - atomic_init(&node->dataLength, ATOMIC_VAR_INIT(dataLength)); - int ret = memcpy_s(node->data, keyLen, key, keyLen); - PARAM_CHECK(ret == 0, return 0, "Failed to copy key"); - ret = memcpy_s(node->data + keyLen + 1, valueLen, value, valueLen); - PARAM_CHECK(ret == 0, return 0, "Failed to copy key"); - node->data[keyLen] = '='; - node->data[keyLen + 1 + valueLen] = '\0'; - u_int32_t offset = workSpace->area->currOffset; - workSpace->area->currOffset += realLen; - //PARAM_LOGI("AddData node %p %u %d", node, offset, gettid()); - return offset; -} - -int UpdateDataValue(DataEntry *entry, const char *value) -{ - PARAM_CHECK(entry != NULL && value != NULL, return PARAM_CODE_INVALID_PARAM, "Failed to check param"); - int ret = PARAM_CODE_INVALID_VALUE; - u_int32_t keyLen = DATA_ENTRY_KEY_LEN(entry); - u_int32_t valueLen = strlen(value); - u_int32_t oldLen = DATA_ENTRY_DATA_LEN(entry); - if (oldLen < PARAM_VALUE_LEN_MAX && valueLen < PARAM_VALUE_LEN_MAX) { - PARAM_LOGD("Old value %s new value %s", entry->data + keyLen + 1, value); - ret = memcpy_s(entry->data + keyLen + 1, PARAM_VALUE_LEN_MAX, value, valueLen + 1); - PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_VALUE, "Failed to copy value"); - u_int32_t dataLength = keyLen << TRIE_SERIAL_KEY_LEN_OFFSET | valueLen << TRIE_SERIAL_DATA_LEN_OFFSET; - atomic_store_explicit(&entry->dataLength, dataLength, memory_order_release); - } - return ret; -} - -u_int32_t GetDataSerial(const DataEntry *entry) -{ - u_int32_t serial = atomic_load_explicit(&entry->serial, memory_order_acquire); - while (DATA_ENTRY_DIRTY(serial)) { - futex_wait(&entry->serial, serial, NULL); - serial = atomic_load_explicit(&entry->serial, memory_order_acquire); - } - return serial; -} - -int GetDataName(const DataEntry *entry, char *name, u_int32_t len) -{ - PARAM_CHECK(entry != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - u_int32_t keyLen = DATA_ENTRY_KEY_LEN(entry); - PARAM_CHECK(len > keyLen, return -1, "Invalid param size"); - int ret = memcpy_s(name, len, entry->data, keyLen); - PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_PARAM, "Failed to copy name"); - name[keyLen] = '\0'; - return ret; -} - -int GetDataValue(const DataEntry *entry, char *value, u_int32_t len) -{ - PARAM_CHECK(entry != NULL && value != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - u_int32_t keyLen = DATA_ENTRY_KEY_LEN(entry); - u_int32_t valueLen = DATA_ENTRY_DATA_LEN(entry); - PARAM_CHECK(len > valueLen, return PARAM_CODE_INVALID_PARAM, "Invalid value len %u %u", len, valueLen); - int ret = memcpy_s(value, len, entry->data + keyLen + 1, valueLen); - PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_PARAM, "Failed to copy value"); - value[valueLen] = '\0'; - return ret; -} diff --git a/services/param/service/param_persist.c b/services/param/service/param_persist.c deleted file mode 100644 index 7086357cb867e02c8d53a4c0bc132bb6f826aca9..0000000000000000000000000000000000000000 --- a/services/param/service/param_persist.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2020 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 "sys_param.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "param_manager.h" -#include "param_trie.h" - -#define LABEL "Manager" -#define MAX_BUFF 256 - -typedef struct { - WorkSpace *workSpace; - WorkSpace *persistWorkSpace; - char *buffer; -} PersistContext; - -static ParamPersistWorkSpace g_persistWorkSpace = {ATOMIC_VAR_INIT(0), }; - -static int ProcessParamTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie) -{ - PARAM_CHECK(workSpace != 0 && node != NULL && cookie != NULL, return -1, "Invalid param"); - TrieDataNode *current = (TrieDataNode *)node; - if (current == NULL || current->dataIndex == 0) { - return 0; - } - DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, ¤t->dataIndex); - if (entry == NULL) { - return -1; - } - PersistContext *persistContext = (PersistContext *)cookie; - int ret = GetDataName(entry, persistContext->buffer, MAX_BUFF); - PARAM_CHECK(ret == 0, return ret, "GetDataName failed"); - if (strncmp(persistContext->buffer, "persist.", strlen("persist.")) != 0) { - return 0; - } - ret = GetDataValue(entry, persistContext->buffer + MAX_BUFF, MAX_BUFF); - if (ret == 0) { // 只支持新建 - //PARAM_LOGI("Insert new persist param from normal param %s %s", - // persistContext->buffer, persistContext->buffer + MAX_BUFF); - ret = AddParam(persistContext->persistWorkSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF); - } - PARAM_CHECK(ret == 0, return ret, "Failed to add persist param"); - return ret; -} - -static int ProcessPersistPropertTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie) -{ - TrieDataNode *current = (TrieDataNode *)node; - if (current == NULL || current->dataIndex == 0) { - return 0; - } - DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, ¤t->dataIndex); - if (entry == NULL) { - return -1; - } - PersistContext *persistContext = (PersistContext *)cookie; - int ret = GetDataName(entry, persistContext->buffer, MAX_BUFF); - PARAM_CHECK(ret == 0, return ret, "GetDataName failed"); - ret = GetDataValue(entry, persistContext->buffer + MAX_BUFF, MAX_BUFF); - if (ret == 0) { - //PARAM_LOGI("update normal param %s %s from persist param %u", - // persistContext->buffer, persistContext->buffer + MAX_BUFF, current->dataIndex); - ret = WriteParam(persistContext->workSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF); - } - PARAM_CHECK(ret == 0, return ret, "Failed to add persist param"); - return ret; -} - -int InitPersistParamWorkSpace(const char *context) -{ - u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) == WORKSPACE_FLAGS_INIT) { - return 0; - } - g_persistWorkSpace.persistWorkSpace.compareTrieNode = CompareTrieDataNode; - g_persistWorkSpace.persistWorkSpace.allocTrieNode = AllocateTrieDataNode; - int ret = InitPersistWorkSpace(PARAM_PERSIST_PATH, &g_persistWorkSpace.persistWorkSpace); - PARAM_CHECK(ret == 0, return ret, "Failed to init persist param"); - atomic_store_explicit(&g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT, memory_order_release); - return ret; -} - -int RefreshPersistParams(ParamWorkSpace *workSpace, const char *context) -{ - int ret = InitPersistParamWorkSpace(context); - PARAM_CHECK(ret == 0, return ret, "Failed to init persist param"); - u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_LOADED) == WORKSPACE_FLAGS_LOADED) { - PARAM_LOGE("RefreshPersistParams has been loaded"); - return 0; - } - - // 申请临时的缓存,用于数据读取 - char *buffer = (char *)malloc(MAX_BUFF + MAX_BUFF); - PARAM_CHECK(buffer != NULL, return -1, "Failed to malloc memory for param"); - PersistContext persistContext = { - &workSpace->paramSpace, &g_persistWorkSpace.persistWorkSpace, buffer - }; - - // 遍历当前的参数,并把persist的写入 - ret = TraversalTrieDataNode(&workSpace->paramSpace, - (TrieDataNode *)workSpace->paramSpace.rootNode, ProcessParamTraversal, &persistContext); - - // 修改默认参数值 - ret = TraversalTrieDataNode(&g_persistWorkSpace.persistWorkSpace, - (TrieDataNode *)g_persistWorkSpace.persistWorkSpace.rootNode, ProcessPersistPropertTraversal, &persistContext); - - atomic_store_explicit(&g_persistWorkSpace.flags, flags | WORKSPACE_FLAGS_LOADED, memory_order_release); - free(buffer); - return ret; -} - -void ClosePersistParamWorkSpace() -{ - CloseWorkSpace(&g_persistWorkSpace.persistWorkSpace); - atomic_store_explicit(&g_persistWorkSpace.flags, 0, memory_order_release); -} - -int WritePersistParam(const char *name, const char *value) -{ - PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); - if (strncmp(name, "persist.", strlen("persist.")) != 0) { - return 0; - } - int ret = InitPersistParamWorkSpace(""); - PARAM_CHECK(ret == 0, return ret, "Failed to init persist param"); - u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_LOADED) != WORKSPACE_FLAGS_LOADED) { - return 0; - } - return WriteParam(&g_persistWorkSpace.persistWorkSpace, name, value); -} diff --git a/services/param/service/param_service.c b/services/param/service/param_service.c deleted file mode 100644 index 58d6c8c3ed04908d9e16af932b6595b00a720734..0000000000000000000000000000000000000000 --- a/services/param/service/param_service.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2020 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 "param_service.h" - -#include -#include -#include -#include - -#include "sys_param.h" -#include "param_manager.h" -#include "param_request.h" -#include "init_param.h" - -#include "uv.h" - -#define BUFFER_SIZE 256 -#define LABEL "Server" - -static char *g_initContext = ""; -static ParamWorkSpace g_paramWorkSpace = {ATOMIC_VAR_INIT(0), {}, {}, {}}; - -void InitParamService() -{ - int ret = InitParamWorkSpace(&g_paramWorkSpace, 0, g_initContext); - PARAM_CHECK(ret == 0, return, "Init parameter workspace fail"); -} - -int LoadDefaultParams(const char *fileName) -{ - u_int32_t flags = atomic_load_explicit(&g_paramWorkSpace.flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) { - return PARAM_CODE_NOT_INIT; - } - FILE *fp = fopen(fileName, "r"); - PARAM_CHECK(fp != NULL, return -1, "Open file %s fail", fileName); - char buff[BUFFER_SIZE]; - SubStringInfo *info = malloc(sizeof(SubStringInfo) * (SUBSTR_INFO_LABEL + 1)); - PARAM_CHECK(info != NULL, return -1, "malloc failed"); - - while(fgets(buff, BUFFER_SIZE, fp) != NULL) { - int subStrNumber = GetSubStringInfo(buff, strlen(buff), '=', info, SUBSTR_INFO_LABEL + 1); - if (subStrNumber <= SUBSTR_INFO_LABEL) { - continue; - } - - if (strncmp(info[0].value, "ctl.", strlen("ctl.")) == 0) { - PARAM_LOGE("Do not set ctl. parameters from init %s", info[0].value); - continue; - } - if (strcmp(info[0].value, "selinux.restorecon_recursive") == 0) { - PARAM_LOGE("Do not set selinux.restorecon_recursive from init %s", info[0].value); - continue; - } - int ret = CheckParamName(info[0].value, 0); - PARAM_CHECK(ret == 0, continue, "Illegal param name %s", info[0].value); - - ret = WriteParam(&g_paramWorkSpace.paramSpace, info[0].value, info[1].value); - PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buff); - } - fclose(fp); - free(info); - PARAM_LOGI("LoadDefaultParams proterty success %s", fileName); - return 0; -} - -int LoadParamInfos(const char *fileName) -{ - u_int32_t flags = atomic_load_explicit(&g_paramWorkSpace.flags, memory_order_relaxed); - if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) { - return PARAM_CODE_NOT_INIT; - } - FILE *fp = fopen(fileName, "r"); - PARAM_CHECK(fp != NULL, return -1, "Open file %s fail", fileName); - SubStringInfo *info = malloc(sizeof(SubStringInfo) * SUBSTR_INFO_MAX); - PARAM_CHECK(info != NULL, return -1, "Load parameter malloc failed."); - char buff[BUFFER_SIZE]; - int infoCount = 0; - while(fgets(buff, BUFFER_SIZE, fp) != NULL) { - int subStrNumber = GetSubStringInfo(buff, strlen(buff), ' ', info, SUBSTR_INFO_MAX); - if (subStrNumber <= 0) { - continue; - } - int ret = WriteParamInfo(&g_paramWorkSpace, info, subStrNumber); - PARAM_CHECK(ret == 0, continue, "Failed to write param info %d %s", ret, buff); - infoCount++; - } - fclose(fp); - free(info); - PARAM_LOGI("Load parameter info %d success %s", infoCount, fileName); - return 0; -} - -static int ProcessParamSet(RequestMsg *msg) -{ - PARAM_CHECK(msg != NULL, return PARAM_CODE_INVALID_PARAM, "Failed to check param"); - - SubStringInfo info[3]; - int ret = GetSubStringInfo(msg->content, msg->contentSize, '=', info, sizeof(info)/sizeof(info[0])); - PARAM_CHECK(ret >= 2, return ret, "Failed to get name from content %s", msg->content); - - PARAM_LOGD("ProcessParamSet name %s value: %s", info[0].value, info[1].value); - ret = WriteParamWithCheck(&g_paramWorkSpace, &msg->securitylabel, info[0].value, info[1].value); - PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, info[0].value, info[1].value); - ret = WritePersistParam(info[0].value, info[1].value); - PARAM_CHECK(ret == 0, return ret, "Failed to set param"); - // notify event to process trigger - PostTrigger(EVENT_PROPERTY, msg->content, msg->contentSize); - return 0; -} - -static void OnClose(uv_handle_t *handle) -{ - free(handle); -} - -static void OnReceiveAlloc(uv_handle_t *handle, size_t suggestedSize, uv_buf_t* buf) -{ - // 这里需要按实际消息的大小申请内存,取最大消息的长度 - buf->len = sizeof(RequestMsg) + BUFFER_SIZE * 2; - buf->base = (char *)malloc(buf->len); -} - -static void OnWriteResponse(uv_write_t *req, int status) -{ - // 发送成功,释放请求内存 - PARAM_LOGD("OnWriteResponse status %d", status); - ResponseNode *node = (ResponseNode*)req; - free(node); -} - -static void SendResponse(uv_stream_t *handle, RequestType type, int result, const void *content, int size) -{ - int ret = 0; - // 申请整块内存,用于回复数据和写请求 - ResponseNode *response = (ResponseNode *)malloc(sizeof(ResponseNode) + size); - PARAM_CHECK(response != NULL, return, "Failed to alloc memory for response"); - response->msg.type = type; - response->msg.contentSize = size; - response->msg.result = result; - if (content != NULL && size != 0) { - ret = memcpy_s(response->msg.content, size, content, size); - PARAM_CHECK(ret == 0, return, "Failed to copy content"); - } - uv_buf_t buf = uv_buf_init((char *)&response->msg, sizeof(response->msg) + size); - ret = uv_write2(&response->writer, handle, &buf, 1, handle, OnWriteResponse); - PARAM_CHECK(ret >= 0, return, "Failed to uv_write2 ret %s", uv_strerror(ret)); -} - -static void OnReceiveRequest(uv_stream_t *handle, ssize_t nread, uv_buf_t *buf) -{ - if (nread <= 0 || buf == NULL || buf->base == NULL) { - uv_close((uv_handle_t*)handle, OnClose); - if (buf != NULL && buf->base != NULL) { - free(buf->base); - } - return; - } - int freeHandle = 1; - RequestMsg *msg = (RequestMsg *)buf->base; - switch (msg->type) { - case SET_PARAM: { - freeHandle = 0; - int ret = ProcessParamSet(msg); - SendResponse(handle, SET_PARAM, ret, NULL, 0); - break; - } - default: - PARAM_LOGE("not supported the command: %d", msg->type); - break; - } - free(buf->base); - buf->base = NULL; - uv_close((uv_handle_t*)handle, OnClose); -} - -static void OnConnection(uv_stream_t *server, int status) -{ - PARAM_CHECK(status >= 0, return, "Error status %d", status); - PARAM_CHECK(server != NULL, return, "Error server"); - uv_pipe_t *stream = (uv_pipe_t*)malloc(sizeof(uv_pipe_t)); - PARAM_CHECK(stream != NULL, return, "Failed to alloc stream"); - - int ret = uv_pipe_init(uv_default_loop(), (uv_pipe_t*)stream, 1); - PARAM_CHECK(ret == 0, free(stream); return, "Failed to uv_pipe_init %d", ret); - - stream->data = server; - ret = uv_accept(server, (uv_stream_t *)stream); - PARAM_CHECK(ret == 0, uv_close((uv_handle_t*)stream, NULL); free(stream); - return, "Failed to uv_accept %d", ret); - - ret = uv_read_start((uv_stream_t *)stream, OnReceiveAlloc, OnReceiveRequest); - PARAM_CHECK(ret == 0, uv_close((uv_handle_t*)stream, NULL); free(stream); - return, "Failed to uv_read_start %d", ret); -} - -void StopParamService() -{ - uv_fs_t req; - uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL); - CloseParamWorkSpace(&g_paramWorkSpace); - ClosePersistParamWorkSpace(); - uv_stop(uv_default_loop()); - PARAM_LOGI("StopParamService."); -} - -int StartParamService() -{ - PARAM_LOGI("StartParamService."); - uv_fs_t req; - uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL); - - uv_pipe_t pipeServer; - int ret = uv_pipe_init(uv_default_loop(), &pipeServer, 0); - PARAM_CHECK(ret == 0, return ret, "Failed to uv_pipe_init %d", ret); - ret = uv_pipe_bind(&pipeServer, PIPE_NAME); - PARAM_CHECK(ret == 0, return ret, "Failed to uv_pipe_bind %d %s", ret, uv_err_name(ret)); - ret = chmod(PIPE_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - PARAM_CHECK(ret == 0, return ret, "Failed to chmod %s, err %d. ", PIPE_NAME, errno); - ret = uv_listen((uv_stream_t*)&pipeServer, SOMAXCONN, OnConnection); - PARAM_CHECK(ret == 0, return ret, "Failed to uv_listen %d %s", ret, uv_err_name(ret)); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - PARAM_LOGI("Start service exit."); - return 0; -} - -int SystemWriteParam(const char *name, const char *value) -{ - PARAM_CHECK(name != NULL && value != NULL, return -1, "The name is null"); - PARAM_LOGI("SystemWriteParam name %s value: %s", name, value); - int ret = WriteParamWithCheck(&g_paramWorkSpace, &g_paramWorkSpace.label, name, value); - PARAM_CHECK(ret == 0, return ret, "Failed to set param %s", name); - ret = WritePersistParam(name, value); - PARAM_CHECK(ret == 0, return ret, "Failed to set persist param %s", name); - - // notify event to process trigger - PostParamTrigger(name, value); - return ret; -} - -int SystemReadParam(const char *name, char *value, unsigned int *len) -{ - PARAM_CHECK(name != NULL && len != NULL, return -1, "The name is null"); - ParamHandle handle = 0; - int ret = ReadParamWithCheck(&g_paramWorkSpace, name, &handle); - if (ret == 0) { - ret = ReadParamValue(&g_paramWorkSpace, handle, value, len); - } - return ret; -} - -ParamWorkSpace *GetParamWorkSpace() -{ - return &g_paramWorkSpace; -} - -int LoadPersistParams() -{ - return RefreshPersistParams(&g_paramWorkSpace, g_initContext); -} - -int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie) -{ - PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null"); - return TraversalParam(&g_paramWorkSpace, traversalParameter, cookie); -} \ No newline at end of file diff --git a/services/param/trigger/trigger_checker.c b/services/param/trigger/trigger_checker.c index fff388e10254a5dcf1f0cd794c76c32d7ecf36f5..42e7c2d0bfe9b5fda2f4548347288c4ee65c5bec 100644 --- a/services/param/trigger/trigger_checker.c +++ b/services/param/trigger/trigger_checker.c @@ -14,20 +14,24 @@ */ #include "trigger_checker.h" + #include -#include "trigger_manager.h" #include "init_param.h" +#include "trigger_manager.h" +#include "securec.h" -#define LABEL "Trigger" +#define MAX_CALC_PARAM 100 // 申请整块能存作为计算的节点 int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition) { PARAM_CHECK(calculator != NULL, return -1, "Invalid param"); + PARAM_CHECK(dataUnit <= (int)sizeof(LogicData), return -1, "Invalid param"); + PARAM_CHECK(dataNumber <= MAX_CALC_PARAM, return -1, "Invalid param"); int dataSize = dataUnit * dataNumber; if (needCondition) { - dataSize += 5 * SUPPORT_DATA_BUFFER_MAX; + dataSize += MAX_DATA_BUFFER_MAX; } - calculator->data = (char *)malloc(dataSize); + calculator->data = (char *)calloc(1, dataSize); PARAM_CHECK(calculator->data != NULL, return -1, "Failed to malloc for calculator"); calculator->dataNumber = dataNumber; calculator->endIndex = 0; @@ -50,7 +54,9 @@ int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, in void CalculatorFree(LogicCalculator *calculator) { PARAM_CHECK(calculator != NULL, return, "Invalid param"); - free(calculator->data); + if (calculator->data != NULL) { + free(calculator->data); + } calculator->data = NULL; } @@ -84,9 +90,9 @@ static int CalculatorPush(LogicCalculator *calculator, const void *data) { PARAM_CHECK(calculator != NULL, return -1, "Invalid param"); PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support"); - char *tmpData = (calculator->data + calculator->dataUnit * calculator->endIndex); + char *tmpData = (char *)calculator->data + calculator->dataUnit * calculator->endIndex; int ret = memcpy_s(tmpData, calculator->dataUnit, data, calculator->dataUnit); - PARAM_CHECK(ret == 0, return -1, "Failed to copy logic data"); + PARAM_CHECK(ret == EOK, return -1, "Failed to copy logic data"); calculator->endIndex++; return 0; } @@ -98,9 +104,9 @@ static int CalculatorPop(LogicCalculator *calculator, void *data) if (calculator->endIndex == 0) { return -1; } - char *tmpData = calculator->data + calculator->dataUnit * (calculator->endIndex - 1); + char *tmpData = (char *)calculator->data + calculator->dataUnit * (calculator->endIndex - 1); int ret = memcpy_s(data, calculator->dataUnit, tmpData, calculator->dataUnit); - PARAM_CHECK(ret == 0, return -1, "Failed to copy logic data"); + PARAM_CHECK(ret == EOK, return -1, "Failed to copy logic data"); calculator->endIndex--; return 0; } @@ -111,9 +117,9 @@ static int CalculatorLength(const LogicCalculator *calculator) return calculator->endIndex; } -static int PrefixAdd(char *prefix, u_int32_t *prefixIndex, u_int32_t prefixLen, char op) +static int PrefixAdd(char *prefix, uint32_t *prefixIndex, uint32_t prefixLen, char op) { - if ((*prefixIndex + 3) >= prefixLen) { + if ((*prefixIndex + 1 + 1 + 1) >= prefixLen) { return -1; } prefix[(*prefixIndex)++] = ' '; @@ -122,12 +128,11 @@ static int PrefixAdd(char *prefix, u_int32_t *prefixIndex, u_int32_t prefixLen, return 0; } -static int HandleOperationOr(LogicCalculator *calculator, char *prefix, u_int32_t *prefixIndex, u_int32_t prefixLen) +static int HandleOperationOr(LogicCalculator *calculator, char *prefix, uint32_t *prefixIndex, uint32_t prefixLen) { - int ret = 0; - char e; + char e = 0; prefix[(*prefixIndex)++] = ' '; - if(CalculatorLength(calculator) == 0) { + if (CalculatorLength(calculator) == 0) { CalculatorPushChar(calculator, '|'); } else { do { @@ -135,7 +140,7 @@ static int HandleOperationOr(LogicCalculator *calculator, char *prefix, u_int32_ if (e == '(') { CalculatorPushChar(calculator, e); } else { - ret = PrefixAdd(prefix, prefixIndex, prefixLen, e); + int ret = PrefixAdd(prefix, prefixIndex, prefixLen, e); PARAM_CHECK(ret == 0, return -1, "Invalid prefix"); } } while (CalculatorLength(calculator) > 0 && e != '('); @@ -144,48 +149,59 @@ static int HandleOperationOr(LogicCalculator *calculator, char *prefix, u_int32_ return 0; } -static int ComputeSubCondition(LogicCalculator *calculator, LogicData *data, const char *condition) +static int CompareValue(const char *condition, const char *value) +{ + if (strcmp(condition, "*") == 0) { + return 1; + } + if (strcmp(condition, value) == 0) { + return 1; + } + char *tmp = strstr(condition, "*"); + if (tmp != NULL && (strncmp(value, condition, tmp - condition) == 0)) { + return 1; + } + return 0; +} + +static int ComputeSubCondition(const LogicCalculator *calculator, LogicData *data, const char *condition) { if (!LOGIC_DATA_TEST_FLAG(data, LOGIC_DATA_FLAGS_ORIGINAL)) { return LOGIC_DATA_TEST_FLAG(data, LOGIC_DATA_FLAGS_TRUE); } - // 解析条件 + uint32_t triggerContentSize = strlen(calculator->triggerContent); + // 解析条件, aaaa && bbb=1 && ccc=1的场景 char *subStr = strstr(condition + data->startIndex, "="); - if (subStr != NULL && ((u_int32_t)(subStr - condition) > data->endIndex)) { - if (strncmp(condition + data->startIndex, calculator->triggerContent, strlen(calculator->triggerContent)) == 0) { + if (subStr != NULL && ((uint32_t)(subStr - condition) > data->endIndex)) { + if (strncmp(condition + data->startIndex, calculator->triggerContent, triggerContentSize) == 0) { return 1; } - } else { - int ret = GetValueFromContent(condition + data->startIndex, - data->endIndex - data->startIndex, 0, calculator->conditionName, SUPPORT_DATA_BUFFER_MAX); - PARAM_CHECK(ret == 0, return -1, "Failed parse content name"); - ret = GetValueFromContent(condition + data->startIndex, data->endIndex - data->startIndex, - strlen(calculator->conditionName) + 1, calculator->conditionContent, SUPPORT_DATA_BUFFER_MAX); - PARAM_CHECK(ret == 0, return -1, "Failed parse content value"); - // check name - if (calculator->inputName && strcmp(calculator->conditionName, calculator->inputName) == 0) { - if (strcmp(calculator->conditionContent, "*") == 0) { - return 1; - } - if (strcmp(calculator->conditionContent, calculator->inputContent) == 0) { - return 1; - } - } else { - u_int32_t len = SUPPORT_DATA_BUFFER_MAX; - ret = SystemReadParam(calculator->conditionName, calculator->readContent, &len); - if (ret == 0 && (strcmp(calculator->conditionContent, "*") == 0 || - strcmp(calculator->conditionContent, calculator->readContent) == 0)) { - return 1; - } + return 0; + } + int ret = GetValueFromContent(condition + data->startIndex, + data->endIndex - data->startIndex, 0, calculator->conditionName, SUPPORT_DATA_BUFFER_MAX); + PARAM_CHECK(ret == 0, return -1, "Failed parse content name"); + ret = GetValueFromContent(condition + data->startIndex, data->endIndex - data->startIndex, + strlen(calculator->conditionName) + 1, calculator->conditionContent, SUPPORT_DATA_BUFFER_MAX); + PARAM_CHECK(ret == 0, return -1, "Failed parse content value"); + // check name + if ((calculator->inputName != NULL) && (strcmp(calculator->conditionName, calculator->inputName) == 0)) { + return CompareValue(calculator->conditionContent, calculator->inputContent); + } else if (strlen(calculator->conditionName) > 0) { + uint32_t len = SUPPORT_DATA_BUFFER_MAX; + ret = SystemReadParam(calculator->conditionName, calculator->readContent, &len); + if (ret != 0) { + return 0; } + return CompareValue(calculator->conditionContent, calculator->readContent); } return 0; } -int GetValueFromContent(const char *content, u_int32_t contentSize, u_int32_t start, char *value, u_int32_t valueSize) +int GetValueFromContent(const char *content, uint32_t contentSize, uint32_t start, char *value, uint32_t valueSize) { - u_int32_t contentIndex = start; - u_int32_t currIndex = 0; + uint32_t contentIndex = start; + uint32_t currIndex = 0; while (contentIndex < contentSize && currIndex < valueSize) { if (content[contentIndex] == '=') { value[currIndex++] = '\0'; @@ -202,13 +218,15 @@ int GetValueFromContent(const char *content, u_int32_t contentSize, u_int32_t st int ComputeCondition(LogicCalculator *calculator, const char *condition) { - u_int32_t currIndex = 0; - u_int32_t start = 0; + PARAM_CHECK(calculator != NULL && condition != NULL, return -1, "Invalid calculator"); + uint32_t currIndex = 0; + uint32_t start = 0; + size_t conditionLen = strlen(condition); int noneOper = 1; CalculatorClear(calculator); LogicData data1 = {}; LogicData data2 = {}; - while (currIndex < strlen(condition)) { + while (currIndex < conditionLen) { if (condition[currIndex] == '|' || condition[currIndex] == '&') { noneOper = 0; int ret = CalculatorPop(calculator, (void*)&data2); @@ -219,12 +237,11 @@ int ComputeCondition(LogicCalculator *calculator, const char *condition) data1.flags = 0; if (condition[currIndex] == '|' && ret == 1) { LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE); - } else if (condition[currIndex] == '|' || ret == 1) { - if (ComputeSubCondition(calculator, &data2, condition) == 1) { - LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE); - } + } else if ((condition[currIndex] == '|' || ret == 1) && + (ComputeSubCondition(calculator, &data2, condition) == 1)) { + LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE); } - ret = CalculatorPush(calculator, (void*)&data1); + ret = CalculatorPush(calculator, (void *)&data1); PARAM_CHECK(ret == 0, return -1, "Failed to push data"); start = currIndex + 1; // 跳过符号 } else if (isspace(condition[currIndex])) { @@ -235,7 +252,7 @@ int ComputeCondition(LogicCalculator *calculator, const char *condition) data1.flags = LOGIC_DATA_FLAGS_ORIGINAL; data1.startIndex = start; data1.endIndex = currIndex; - int ret = CalculatorPush(calculator, (void*)&data1); + int ret = CalculatorPush(calculator, (void *)&data1); PARAM_CHECK(ret == 0, return -1, "Failed to push data"); start = currIndex + 1; } @@ -252,31 +269,36 @@ int ComputeCondition(LogicCalculator *calculator, const char *condition) return ComputeSubCondition(calculator, &data1, condition); } -int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLen) +int ConvertInfixToPrefix(const char *condition, char *prefix, uint32_t prefixLen) { + PARAM_CHECK(condition != NULL && prefix != NULL, return -1, "Invalid condition"); char e = 0; - int ret = 0; - u_int32_t curr = 0; - u_int32_t prefixIndex = 0; + int ret; + uint32_t curr = 0; + uint32_t prefixIndex = 0; + size_t conditionLen = strlen(condition); LogicCalculator calculator; - CalculatorInit(&calculator, 100, 1, 0); + PARAM_CHECK(CalculatorInit(&calculator, MAX_CALC_PARAM, 1, 0) == 0, return -1, "Failed to init calculator"); - while (curr < strlen(condition)) { + while (curr < conditionLen) { if (condition[curr] == ')') { CalculatorPopChar(&calculator, &e); while (e != '(') { ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Invalid prefix"); - ret = CalculatorPopChar(&calculator, &e); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Invalid calculator"); + PARAM_CHECK(ret == 0, + CalculatorFree(&calculator); return -1, "Invalid prefix"); + CalculatorPopChar(&calculator, &e); } } else if (condition[curr] == '|') { - PARAM_CHECK(condition[curr + 1] == '|', CalculatorFree(&calculator); return -1, "Invalid condition"); + PARAM_CHECK(condition[curr + 1] == '|', + CalculatorFree(&calculator); return -1, "Invalid condition"); ret = HandleOperationOr(&calculator, prefix, &prefixIndex, prefixLen); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Invalid prefix"); + PARAM_CHECK(ret == 0, + CalculatorFree(&calculator); return -1, "Invalid prefix"); curr++; } else if (condition[curr] == '&') { - PARAM_CHECK(condition[curr + 1] == '&', CalculatorFree(&calculator); return -1, "Invalid condition"); + PARAM_CHECK(condition[curr + 1] == '&', + CalculatorFree(&calculator); return -1, "Invalid condition"); prefix[prefixIndex++] = ' '; CalculatorPushChar(&calculator, condition[curr]); curr++; @@ -286,13 +308,15 @@ int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLe prefix[prefixIndex++] = condition[curr]; } curr++; - PARAM_CHECK(prefixIndex < prefixLen, CalculatorFree(&calculator); return -1, "Invalid prefixIndex"); + PARAM_CHECK(prefixIndex < prefixLen, + CalculatorFree(&calculator); return -1, "Invalid prefixIndex"); } while (CalculatorLength(&calculator) > 0) { CalculatorPopChar(&calculator, &e); ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); + PARAM_CHECK(ret == 0, + CalculatorFree(&calculator); return -1, "Invalid prefix %u %u", prefixIndex, prefixLen); } prefix[prefixIndex] = '\0'; @@ -300,13 +324,25 @@ int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLe return 0; } -char *GetMatchedSubCondition(const char *condition, const char *input, int length) +int CheckMatchSubCondition(const char *condition, const char *input, int length) { - const char *p = condition; - for(;(p = strchr(p, *input)) != 0; p++) { - if(strncmp(p, input, length) == 0) { - return (char*)p; + PARAM_CHECK(condition != NULL, return 0, "Invalid condition"); + PARAM_CHECK(input != NULL, return 0, "Invalid input"); + const char *tmp = strstr(condition, input); + while (tmp != NULL) { + PARAM_LOGV("CheckMatchSubCondition Condition: '%s' content: '%s' length %d", condition, input, length); + if (((int)strlen(tmp) <= length) || (tmp[length] != '=')) { + return 0; + } + // for condition: parameter = 1 + if (tmp == condition) { + return 1; } + // for condition: parameter1 = 1 && parameter2 = 1 + if (*(tmp - 1) == ' ') { + return 1; + } + tmp = strstr(tmp + 1, input); } - return NULL; -} + return 0; +} \ No newline at end of file diff --git a/services/param/trigger/trigger_manager.c b/services/param/trigger/trigger_manager.c index 7d2d104baeb4c19b983cd5ccc26a6d394aa85686..0f51bcff3828fe07a3e3ccf599c4ad897b788ae4 100644 --- a/services/param/trigger/trigger_manager.c +++ b/services/param/trigger/trigger_manager.c @@ -15,407 +15,761 @@ #include "trigger_manager.h" -#include -#include -#include -#include #include -#include -#include -#include #include -#include #include "init_cmds.h" -#include "init_utils.h" +#include "param_manager.h" #include "trigger_checker.h" +#include "securec.h" -#define LABEL "Trigger" -#define TRIGGER_AREA_SPACE 1024*128 -#define TRIGGER_EXECUTE_QUEUE 64 -#define BUFFER_SIZE 256 -#define CHECK_INDEX_VALID(workSpace, index) \ - (u_int32_t)(index) < sizeof((workSpace)->header) / sizeof((workSpace)->header[0]) +static DUMP_PRINTF g_printf = printf; -#ifdef STARTUP_LOCAL -#define TRIGGER_PATH "/media/sf_ubuntu/test/__trigger__/trigger" -#else -#define TRIGGER_PATH "/dev/__trigger__/trigger" -#endif - -int InitTriggerWorkSpace(TriggerWorkSpace *workSpace) +int AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content, const ConfigContext *cfgContext) { - PARAM_CHECK(workSpace != NULL, return -1, "Invalid parm"); - if (workSpace->area != NULL) { - return 0; + PARAM_CHECK(trigger != NULL, return -1, "trigger is null"); + uint32_t size = sizeof(CommandNode); + size += (content == NULL) ? 1 : (strlen(content) + 1); + size = PARAM_ALIGN(size); + + CommandNode *node = (CommandNode *)calloc(1, size); + PARAM_CHECK(node != NULL, return -1, "Failed to alloc memory for command"); + node->cmdKeyIndex = cmdKeyIndex; + node->next = NULL; + node->content[0] = '\0'; + if (content != NULL && strlen(content) != 0) { + int ret = memcpy_s(node->content, size, content, strlen(content)); + node->content[strlen(content)] = '\0'; + PARAM_CHECK(ret == EOK, free(node); + return 0, "Failed to copy command"); } - CheckAndCreateDir(TRIGGER_PATH); - int fd = open(TRIGGER_PATH, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0444); - PARAM_CHECK(fd >= 0, return -1, "Open file fail error %s", strerror(errno)); - lseek(fd, TRIGGER_AREA_SPACE, SEEK_SET); - write(fd, "", 1); - - void *areaAddr = (void *)mmap(NULL, TRIGGER_AREA_SPACE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - PARAM_CHECK(areaAddr != MAP_FAILED, close(fd); return -1, - "Failed to map memory error %s", strerror(errno)); - close(fd); - - // 第一部分做执行队列 - workSpace->executeQueue.executeQueue = (u_int32_t *)areaAddr; - workSpace->executeQueue.queueCount = TRIGGER_EXECUTE_QUEUE; - workSpace->executeQueue.startIndex = 0; - workSpace->executeQueue.endIndex = 0; - pthread_mutex_init(&workSpace->executeQueue.mutex, NULL); - - // 动态数据保存 - workSpace->area = (TriggerArea *)(areaAddr + TRIGGER_EXECUTE_QUEUE * sizeof(u_int32_t)); - atomic_init(&workSpace->area->serial, ATOMIC_VAR_INIT(0)); - workSpace->area->dataSize = TRIGGER_AREA_SPACE - sizeof(TriggerArea) - TRIGGER_EXECUTE_QUEUE * sizeof(u_int32_t); - workSpace->area->currOffset = sizeof(TriggerArea) + TRIGGER_EXECUTE_QUEUE * sizeof(u_int32_t); - for (size_t i = 0; i < sizeof(workSpace->header) / sizeof(workSpace->header[0]); i++) { - atomic_init(&workSpace->header[i].firstTrigger, ATOMIC_VAR_INIT(0)); - atomic_init(&workSpace->header[i].lastTrigger, ATOMIC_VAR_INIT(0)); + node->cfgContext.type = INIT_CONTEXT_MAIN; + if (cfgContext != NULL) { + node->cfgContext.type = cfgContext->type; + } + if (trigger->firstCmd == NULL) { + trigger->firstCmd = node; + trigger->lastCmd = node; + } else { + PARAM_CHECK(trigger->lastCmd != NULL, free(node); + return 0, "Invalid last cmd"); + trigger->lastCmd->next = node; + trigger->lastCmd = node; } return 0; } -static CommandNode *GetCmdByIndex(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t index) +CommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr) { - if (index == 0 || index == (u_int32_t)-1) { - return NULL; + PARAM_CHECK(trigger != NULL, return NULL, "trigger is null"); + if (curr == NULL) { + return trigger->firstCmd; } - u_int32_t size = sizeof(CommandNode) + 2; - PARAM_CHECK((index + size) < workSpace->area->dataSize, - return NULL, "Invalid index for cmd %u", index); - return (CommandNode *)(workSpace->area->data + index); + return curr->next; } -u_int32_t AddCommand(TriggerWorkSpace *workSpace, TriggerNode *trigger, const char *cmdName, const char *content) +static int CopyCondition(TriggerNode *node, const char *condition) { - PARAM_CHECK(workSpace != NULL && trigger != NULL, return 0, "list is null"); - u_int32_t size = sizeof(CommandNode) + strlen(cmdName) + 1; - size += (content == NULL) ? 1 : strlen(content) + 1; - size = (size + 0x03) & (~0x03); - PARAM_CHECK((workSpace->area->currOffset + size) < workSpace->area->dataSize, - return 0, "Not enough memory for cmd %u %u", size, workSpace->area->currOffset); + if (condition == NULL || strlen(condition) == 0) { + return 0; + } + uint32_t buffSize = 0; + char *cond = GetTriggerCache(&buffSize); + int ret = ConvertInfixToPrefix(condition, cond, buffSize); + PARAM_CHECK(ret == 0, return -1, "Failed to convert condition for trigger"); + node->condition = strdup(cond); + PARAM_CHECK(node->condition != NULL, return -1, "Failed to dup conditition"); + return 0; +} - CommandNode *node = (CommandNode *)(workSpace->area->data + workSpace->area->currOffset); - PARAM_CHECK(node != NULL, return 0, "Failed to alloc memory for command"); +static TriggerNode *AddTriggerNode_(TriggerHeader *triggerHead, + uint32_t type, const char *condition, uint32_t dataSize) +{ + TriggerNode *node = (TriggerNode *)calloc(1, dataSize); + PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger"); + node->condition = NULL; + int ret = CopyCondition(node, condition); + PARAM_CHECK(ret == 0, free(node); + return NULL, "Failed to copy conditition"); + node->type = type; + node->flags = 0; + OH_ListInit(&node->node); + OH_ListAddTail(&triggerHead->triggerList, &node->node); + triggerHead->triggerCount++; + return node; +} - int ret = memcpy_s(node->name, sizeof(node->name) - 1, cmdName, strlen(cmdName)); - PARAM_CHECK(ret == 0, return 0, "Failed to copy command"); - node->name[strlen(cmdName)] = '\0'; - if (content != NULL) { - ret = memcpy_s(node->content, size, content, strlen(content)); - node->content[strlen(content)] = '\0'; - PARAM_CHECK(ret == 0, return 0, "Failed to copy command"); - } else { - node->content[0] = '\0'; +static int32_t AddJobNode_(TriggerNode *trigger, const TriggerExtInfo *extInfo) +{ + JobNode *node = (JobNode *)trigger; + int ret = strcpy_s(node->name, strlen(extInfo->info.name) + 1, extInfo->info.name); + PARAM_CHECK(ret == EOK, return -1, "Failed to copy name for trigger"); + node->firstCmd = NULL; + node->lastCmd = NULL; + ret = OH_HashMapAdd(GetTriggerWorkSpace()->hashMap, &node->hashNode); + PARAM_CHECK(ret == 0, return -1, "Failed to add hash node"); + return 0; +} + +static TriggerNode *AddJobTrigger_(const TriggerWorkSpace *workSpace, + const char *condition, const TriggerExtInfo *extInfo) +{ + PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null"); + PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null"); + PARAM_CHECK(extInfo->type <= TRIGGER_UNKNOW, return NULL, "Invalid type"); + TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type); + PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type); + uint32_t nameLen = strlen(extInfo->info.name); + uint32_t triggerNodeLen = PARAM_ALIGN(nameLen + 1) + sizeof(JobNode); + TriggerNode *node = (TriggerNode *)AddTriggerNode_(triggerHead, extInfo->type, condition, triggerNodeLen); + PARAM_CHECK(node != NULL, return NULL, "Failed to alloc jobnode"); + int ret = extInfo->addNode(node, extInfo); + PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node); + return NULL, "Failed to add hash node"); + if (extInfo->type == TRIGGER_BOOT) { + TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE); + if (strncmp("boot-service:", extInfo->info.name, strlen("boot-service:")) != 0) { + TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_SUBTRIGGER); + } } + return node; +} - u_int32_t offset = workSpace->area->currOffset; - atomic_init(&node->next, ATOMIC_VAR_INIT(0)); - // 插入队列 - if (trigger->firstCmd == 0) { - atomic_store_explicit(&trigger->firstCmd, offset, memory_order_release); - atomic_store_explicit(&trigger->lastCmd, offset, memory_order_release); - } else { - CommandNode *lastNode = GetCmdByIndex(workSpace, trigger, trigger->lastCmd); - if (lastNode != NULL) { - atomic_store_explicit(&lastNode->next, offset, memory_order_release); +static void DelJobTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger) +{ + PARAM_CHECK(workSpace != NULL, return, "Param is null"); + PARAM_CHECK(trigger != NULL, return, "Trigger is null"); + JobNode *jobNode = (JobNode *)trigger; + TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type); + PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type); + CommandNode *cmd = jobNode->firstCmd; + while (cmd != NULL) { + CommandNode *next = cmd->next; + free(cmd); + triggerHead->cmdNodeCount--; + cmd = next; + } + if (jobNode->condition != NULL) { + free(jobNode->condition); + jobNode->condition = NULL; + } + jobNode->lastCmd = NULL; + jobNode->firstCmd = NULL; + OH_ListRemove(&trigger->node); + triggerHead->triggerCount--; + OH_HashMapRemove(workSpace->hashMap, jobNode->name); + + if (!TRIGGER_IN_QUEUE(trigger)) { + free(jobNode); + return; + } + TriggerExecuteQueue *executeQueue = (TriggerExecuteQueue *)&workSpace->executeQueue; + for (uint32_t i = executeQueue->startIndex; i < executeQueue->endIndex; i++) { + if (executeQueue->executeQueue[i] == trigger) { + executeQueue->executeQueue[i] = NULL; + break; } - atomic_store_explicit(&trigger->lastCmd, offset, memory_order_release); } - workSpace->area->currOffset += size; - return offset; + free(jobNode); } -static TriggerNode *GetTriggerByIndex(TriggerWorkSpace *workSpace, u_int32_t index) +static TriggerNode *AddWatchTrigger_(const TriggerWorkSpace *workSpace, + const char *condition, const TriggerExtInfo *extInfo) { - if (index == 0 || index == (u_int32_t)-1) { + PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null"); + PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null"); + TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type); + PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type); + uint32_t size = 0; + if (extInfo->type == TRIGGER_PARAM_WATCH) { + size = sizeof(WatchNode); + } else if (extInfo->type == TRIGGER_PARAM_WAIT) { + size = sizeof(WaitNode); + } else { + PARAM_LOGE("Invalid trigger type %d", extInfo->type); return NULL; } - u_int32_t size = sizeof(TriggerNode) + 1; - PARAM_CHECK((index + size) < workSpace->area->dataSize, - return NULL, "Invalid index for trigger %u", index); - return (TriggerNode *)(workSpace->area->data + index); + TriggerNode *node = AddTriggerNode_(triggerHead, extInfo->type, condition, size); + PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger"); + int ret = extInfo->addNode(node, extInfo); + PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node); + return NULL, "Failed to add node"); + if (extInfo->type == TRIGGER_PARAM_WAIT) { + TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE); + } + return node; } -u_int32_t AddTrigger(TriggerWorkSpace *workSpace, int type, const char *name, const char *condition) +static void DelWatchTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger) { - PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "list is null"); - const char *tmpCond = condition; - if (type == TRIGGER_BOOT && condition == NULL) { - tmpCond = name; + PARAM_CHECK(workSpace != NULL && trigger != NULL, return, "Param is null"); + TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type); + PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type); + OH_ListRemove(&trigger->node); + if (trigger->type == TRIGGER_PARAM_WAIT) { + WaitNode *node = (WaitNode *)trigger; + OH_ListRemove(&node->item); + } else if (trigger->type == TRIGGER_PARAM_WATCH) { + WatchNode *node = (WatchNode *)trigger; + OH_ListRemove(&node->item); } - u_int32_t conditionSize = (tmpCond == NULL) ? 1 : strlen(tmpCond) + 1 + CONDITION_EXTEND_LEN; - conditionSize = (conditionSize + 0x03) & (~0x03); - PARAM_CHECK((workSpace->area->currOffset + sizeof(TriggerNode) + conditionSize) < workSpace->area->dataSize, - return -1, "Not enough memory for cmd"); - - TriggerNode *node = (TriggerNode *)(workSpace->area->data + workSpace->area->currOffset); - PARAM_CHECK(node != NULL, return 0, "Failed to alloc memory for trigger"); - node->type = type; - int ret = memcpy_s(node->name, sizeof(node->name) - 1, name, strlen(name)); - PARAM_CHECK(ret == 0, return 0, "Failed to memcpy_s for trigger"); - node->name[strlen(name)] = '\0'; - - if (tmpCond != NULL) { - ret = ConvertInfixToPrefix(tmpCond, node->condition, conditionSize); - PARAM_CHECK(ret == 0, return 0, "Failed to memcpy_s for trigger"); - } else { - node->condition[0] = '\0'; + PARAM_LOGV("DelWatchTrigger_ %s count %d", GetTriggerName(trigger), triggerHead->triggerCount); + triggerHead->triggerCount--; + if (trigger->condition != NULL) { + free(trigger->condition); + trigger->condition = NULL; } + free(trigger); +} - u_int32_t offset = workSpace->area->currOffset; - atomic_init(&node->serial, ATOMIC_VAR_INIT(0)); - atomic_init(&node->next, ATOMIC_VAR_INIT(0)); - atomic_init(&node->firstCmd, ATOMIC_VAR_INIT(0)); - atomic_init(&node->lastCmd, ATOMIC_VAR_INIT(0)); - - // 插入到trigger队列中 - if (workSpace->header[type].firstTrigger == 0) { - atomic_store_explicit(&workSpace->header[type].firstTrigger, offset, memory_order_release); - atomic_store_explicit(&workSpace->header[type].lastTrigger, offset, memory_order_release); +static TriggerNode *GetNextTrigger_(const TriggerHeader *triggerHead, const TriggerNode *curr) +{ + PARAM_CHECK(triggerHead != NULL, return NULL, "Invalid triggerHead"); + ListNode *node = NULL; + if (curr != NULL) { + node = curr->node.next; } else { - TriggerNode *lastNode = GetTriggerByIndex(workSpace, workSpace->header[type].lastTrigger); - if (lastNode != NULL) { - atomic_store_explicit(&lastNode->next, offset, memory_order_release); - } - atomic_store_explicit(&workSpace->header[type].lastTrigger, offset, memory_order_release); + node = triggerHead->triggerList.next; + } + if (node != &triggerHead->triggerList) { + return ListEntry(node, TriggerNode, node); } - workSpace->area->currOffset += conditionSize + sizeof(TriggerNode); - return offset; + return NULL; } -static int GetTriggerIndex(const char *type) +static const char *GetTriggerCondition_(const TriggerNode *trigger) { - if (strncmp("param:", type, strlen("param:")) == 0) { - return TRIGGER_PARAM; - } - static const char *triggerType[] = { - "pre-init", "boot", "early-init", "init", "late-init", "post-init", - "early-fs", "post-fs", "late-fs", "post-fs-data" - }; - for (size_t i = 0; i < sizeof(triggerType) / sizeof(char*); i++) { - if (strcmp(triggerType[i], type) == 0) { - return TRIGGER_BOOT; - } - } - return TRIGGER_UNKNOW; + return (trigger == NULL || trigger->condition == NULL) ? "" : trigger->condition; } -int ParseTrigger(TriggerWorkSpace *workSpace, cJSON *triggerItem) +static const char *GetBootCondition_(const TriggerNode *trigger) { - PARAM_CHECK(triggerItem != NULL, return -1, "Invalid file"); - PARAM_CHECK(workSpace != NULL, return -1, "Failed to create trigger list"); + PARAM_CHECK(trigger != NULL, return "", "Invalid trigger"); + PARAM_CHECK(trigger->type == TRIGGER_BOOT, return "", "Invalid type"); + const JobNode *node = (const JobNode *)trigger; + return node->name; +} - char *name = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "name")); - PARAM_CHECK(name != NULL, return -1, "Can not get name from cfg"); - char *condition = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "condition")); +static const char *GetJobName_(const TriggerNode *trigger) +{ + PARAM_CHECK(trigger != NULL, return "", "Invalid trigger"); + PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return "", "Invalid type"); + const JobNode *node = (const JobNode *)trigger; + return node->name; +} - int index = GetTriggerIndex(name); - PARAM_CHECK(CHECK_INDEX_VALID(workSpace, index), return -1, "Failed to get trigger index"); +static const char *GetWatchName_(const TriggerNode *trigger) +{ + PARAM_CHECK(trigger != NULL, return "", "Invalid trigger"); + PARAM_CHECK(trigger->type < TRIGGER_MAX && trigger->type > TRIGGER_UNKNOW, + return "", "Invalid type"); + return trigger->condition; +} - u_int32_t offset = 0; - TriggerNode *trigger = GetTriggerByName(workSpace, name, &offset); - if (trigger == NULL) { - offset = AddTrigger(workSpace, index, name, condition); - PARAM_CHECK(offset > 0, return -1, "Failed to create trigger %s", name); - trigger = GetTriggerByIndex(workSpace, offset); - } else { - if (condition != NULL) { - PARAM_LOGE("Warning parseTrigger %s %s", name, condition); - } +JobNode *UpdateJobTrigger(const TriggerWorkSpace *workSpace, + int type, const char *condition, const char *name) +{ + PARAM_CHECK(workSpace != NULL && name != NULL, return NULL, "name is null"); + PARAM_CHECK(type <= TRIGGER_UNKNOW, return NULL, "Invalid type"); + TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type); + PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", type); + JobNode *jobNode = GetTriggerByName(workSpace, name); + if (jobNode == NULL) { + TriggerExtInfo extInfo = {}; + extInfo.info.name = (char *)name; + extInfo.type = type; + extInfo.addNode = AddJobNode_; + return (JobNode *)triggerHead->addTrigger(workSpace, condition, &extInfo); + } else if (jobNode->condition == NULL && condition != NULL) { + int ret = CopyCondition((TriggerNode *)jobNode, condition); + PARAM_CHECK(ret == 0, FreeTrigger(workSpace, (TriggerNode*)jobNode); + return NULL, "Failed to copy conditition"); } - PARAM_LOGD("ParseTrigger %s %u", name, offset); - - // 添加命令行 - cJSON* cmdItems = cJSON_GetObjectItem(triggerItem, CMDS_ARR_NAME_IN_JSON); - PARAM_CHECK(cJSON_IsArray(cmdItems), return -1, "Command item must be array"); - int cmdLinesCnt = cJSON_GetArraySize(cmdItems); - PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name); + return jobNode; +} - for (int i = 0; i < cmdLinesCnt; ++i) { - char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i)); - PARAM_CHECK(cmdLineStr != NULL, continue, "Command is null"); +JobNode *GetTriggerByName(const TriggerWorkSpace *workSpace, const char *triggerName) +{ + PARAM_CHECK(workSpace != NULL && triggerName != NULL, return NULL, "Invalid param"); + HashNode *node = OH_HashMapGet(workSpace->hashMap, triggerName); + if (node == NULL) { + return NULL; + } + JobNode *trigger = HASHMAP_ENTRY(node, JobNode, hashNode); + return trigger; +} - size_t cmdLineLen = strlen(cmdLineStr); - const char *matchCmd = GetMatchCmd(cmdLineStr); - if (matchCmd == NULL && strncmp(cmdLineStr, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) { - matchCmd = TRIGGER_CMD; - } - PARAM_CHECK(matchCmd != NULL, continue, "Command not support %s", cmdLineStr); - size_t matchLen = strlen(matchCmd); - if (matchLen == cmdLineLen) { - offset = AddCommand(workSpace, trigger, matchCmd, NULL); - } else { - offset = AddCommand(workSpace, trigger, matchCmd, cmdLineStr + matchLen); - } - //PARAM_LOGE("AddCommand %u %s %u", offset, cmdLineStr, workSpace->area->currOffset); - PARAM_CHECK(offset > 0, continue, "Failed to add command %s", cmdLineStr); +void FreeTrigger(const TriggerWorkSpace *workSpace, TriggerNode *trigger) +{ + PARAM_CHECK(workSpace != NULL && trigger != NULL, return, "Invalid param"); + TriggerHeader *head = GetTriggerHeader(workSpace, trigger->type); + if (head != NULL) { + head->delTrigger(workSpace, trigger); } - return 0; } -int ExecuteTrigger(TriggerWorkSpace *workSpace, TriggerNode *trigger, CMD_EXECUTE cmdExecuter) +void ClearTrigger(const TriggerWorkSpace *workSpace, int8_t type) { - PARAM_CHECK(workSpace != NULL && trigger != NULL && cmdExecuter != NULL, return -1, "Invalid param"); - PARAM_LOGI("ExecuteTrigger trigger %s", trigger->name); - CommandNode *cmd = GetCmdByIndex(workSpace, trigger, trigger->firstCmd); - while (cmd != NULL) { - cmdExecuter(trigger, cmd->name, cmd->content); - cmd = GetCmdByIndex(workSpace, trigger, cmd->next); + PARAM_CHECK(workSpace != NULL, return, "head is null"); + TriggerHeader *head = GetTriggerHeader(workSpace, type); + PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); + TriggerNode *trigger = head->nextTrigger(head, NULL); + while (trigger != NULL) { + TriggerNode *next = head->nextTrigger(head, trigger); + FreeTrigger(workSpace, trigger); + trigger = next; } - return 0; + OH_ListInit(&head->triggerList); } -int ExecuteQueuePush(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t triggerIndex) +int ExecuteQueuePush(TriggerWorkSpace *workSpace, const TriggerNode *trigger) { - PARAM_CHECK(workSpace != NULL, return -1, "Invalid area"); - pthread_mutex_lock(&workSpace->executeQueue.mutex); - u_int32_t index = workSpace->executeQueue.endIndex++ % workSpace->executeQueue.queueCount; - workSpace->executeQueue.executeQueue[index] = triggerIndex; - pthread_mutex_unlock(&workSpace->executeQueue.mutex); + PARAM_CHECK(workSpace != NULL, return -1, "Invalid workSpace"); + uint32_t index = workSpace->executeQueue.endIndex++ % workSpace->executeQueue.queueCount; + workSpace->executeQueue.executeQueue[index] = (TriggerNode *)trigger; return 0; } TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace) { - if (workSpace->executeQueue.endIndex <= workSpace->executeQueue.startIndex) { - return NULL; - } - pthread_mutex_lock(&workSpace->executeQueue.mutex); - u_int32_t currIndex = workSpace->executeQueue.startIndex % workSpace->executeQueue.queueCount; - u_int32_t triggerIndex = workSpace->executeQueue.executeQueue[currIndex]; - workSpace->executeQueue.executeQueue[currIndex] = 0; - workSpace->executeQueue.startIndex++; - pthread_mutex_unlock(&workSpace->executeQueue.mutex); - return GetTriggerByIndex(workSpace, triggerIndex); + PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace"); + TriggerNode *trigger = NULL; + do { + if (workSpace->executeQueue.endIndex <= workSpace->executeQueue.startIndex) { + return NULL; + } + uint32_t currIndex = workSpace->executeQueue.startIndex % workSpace->executeQueue.queueCount; + trigger = workSpace->executeQueue.executeQueue[currIndex]; + workSpace->executeQueue.executeQueue[currIndex] = NULL; + workSpace->executeQueue.startIndex++; + } while (trigger == NULL); + return trigger; } -int ExecuteQueueSize(TriggerWorkSpace *workSpace) +static int CheckBootCondition_(LogicCalculator *calculator, + const char *condition, const char *content, uint32_t contentSize) { - PARAM_CHECK(workSpace != NULL, return 0, "Invalid param"); - return workSpace->executeQueue.endIndex - workSpace->executeQueue.startIndex; + UNUSED(calculator); + if (strncmp(condition, content, contentSize) == 0) { + return 1; + } + return 0; } -static int CheckBootTriggerMatch(LogicCalculator *calculator, - TriggerNode *trigger, const char *content, u_int32_t contentSize) +static int CheckWatchCondition_(LogicCalculator *calculator, + const char *condition, const char *content, uint32_t contentSize) { - if (strncmp(trigger->name, (char *)content, contentSize) == 0) { + UNUSED(calculator); + UNUSED(contentSize); + if (strncmp(condition, content, strlen(condition)) == 0) { return 1; } return 0; } -static int CheckParamTriggerMatch(LogicCalculator *calculator, - TriggerNode *trigger, const char *content, u_int32_t contentSize) +static int CheckParamCondition_(LogicCalculator *calculator, + const char *condition, const char *content, uint32_t contentSize) { - if (calculator->inputName != NULL) { // 存在input数据时,先过滤非input的 - if (GetMatchedSubCondition(trigger->condition, content, strlen(calculator->inputName) + 1) == NULL) { + UNUSED(content); + UNUSED(contentSize); + if (calculator->inputName != NULL) { + if (!CheckMatchSubCondition(condition, calculator->inputName, strlen(calculator->inputName))) { return 0; } } - return ComputeCondition(calculator, trigger->condition); + return ComputeCondition(calculator, condition); } -static int CheckOtherTriggerMatch(LogicCalculator *calculator, - TriggerNode *trigger, const char *content, u_int32_t contentSize) +static int CheckUnknowCondition_(LogicCalculator *calculator, + const char *condition, const char *content, uint32_t contentSize) { - return ComputeCondition(calculator, trigger->condition); + if (condition != NULL && content != NULL && strcmp(content, condition) == 0) { + return 1; + } + return ComputeCondition(calculator, condition); } -static int CheckTrigger_(TriggerWorkSpace *workSpace, - LogicCalculator *calculator, int type, const char *content, u_int32_t contentSize) +static int ExecTriggerMatch_(const TriggerWorkSpace *workSpace, + int type, LogicCalculator *calculator, const char *content, uint32_t contentSize) { - static TRIGGER_MATCH triggerCheckMatch[TRIGGER_MAX] = { - CheckBootTriggerMatch, CheckParamTriggerMatch, CheckOtherTriggerMatch - }; - PARAM_LOGD("CheckTrigger_ content %s ", content); - PARAM_CHECK(calculator != NULL, return -1, "Failed to check calculator"); - PARAM_CHECK(CHECK_INDEX_VALID(workSpace, type), return -1, "Invalid type %d", type); - PARAM_CHECK((u_int32_t)type < sizeof(triggerCheckMatch) / sizeof(triggerCheckMatch[0]), - return -1, "Failed to get check function"); - PARAM_CHECK(triggerCheckMatch[type] != NULL, return -1, "Failed to get check function"); - - u_int32_t index = workSpace->header[type].firstTrigger; - TriggerNode *trigger = GetTriggerByIndex(workSpace, workSpace->header[type].firstTrigger); + TriggerHeader *head = GetTriggerHeader(workSpace, type); + PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type); + TriggerNode *trigger = head->nextTrigger(head, NULL); while (trigger != NULL) { - if (triggerCheckMatch[type](calculator, trigger, content, contentSize) == 1) { // 等于1 则认为匹配 - calculator->triggerExecuter(trigger, index); + TriggerNode *next = head->nextTrigger(head, trigger); + const char *condition = head->getCondition(trigger); + if (head->checkCondition(calculator, condition, content, contentSize) == 1) { + calculator->triggerCheckDone(trigger, content, contentSize); } - index = trigger->next; - trigger = GetTriggerByIndex(workSpace, trigger->next); + trigger = next; } return 0; } -int CheckTrigger(const TriggerWorkSpace *workSpace, - int type, void *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter) +static int CheckBootMatch_(const TriggerWorkSpace *workSpace, + int type, LogicCalculator *calculator, const char *content, uint32_t contentSize) { - PARAM_CHECK(workSpace != NULL && content != NULL && triggerExecuter != NULL, - return -1, "Failed arg for trigger"); - - LogicCalculator calculator = {}; - calculator.triggerExecuter = triggerExecuter; - return CheckTrigger_(workSpace, &calculator, type, (char *)content, contentSize); + PARAM_CHECK(workSpace != NULL, return -1, "Invalid space"); + PARAM_CHECK((type == TRIGGER_BOOT) || (type == TRIGGER_PARAM_WATCH), return -1, "Invalid type"); + return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize); } -int CheckParamTrigger(TriggerWorkSpace *workSpace, - const char *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter) +static int CheckParamMatch_(const TriggerWorkSpace *workSpace, + int type, LogicCalculator *calculator, const char *content, uint32_t contentSize) { - PARAM_CHECK(workSpace != NULL && content != NULL && triggerExecuter != NULL, - return -1, "Failed arg for param trigger"); - LogicCalculator calculator = {}; - CalculatorInit(&calculator, 100, sizeof(LogicData), 1); + PARAM_CHECK(workSpace != NULL, return -1, "Invalid space"); + PARAM_CHECK((type == TRIGGER_PARAM) || (type == TRIGGER_PARAM_WAIT), return -1, "Invalid type"); - // 先解析content - int ret = GetValueFromContent(content, contentSize, 0, calculator.inputName, SUPPORT_DATA_BUFFER_MAX); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Failed parse content name"); + CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1); + int ret = GetValueFromContent(content, contentSize, 0, calculator->inputName, SUPPORT_DATA_BUFFER_MAX); + PARAM_CHECK(ret == 0, return -1, "Failed parse content name"); ret = GetValueFromContent(content, contentSize, - strlen(calculator.inputName) + 1, calculator.inputContent, SUPPORT_DATA_BUFFER_MAX); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Failed parse content value"); + strlen(calculator->inputName) + 1, calculator->inputContent, SUPPORT_DATA_BUFFER_MAX); + PARAM_CHECK(ret == 0, return -1, "Failed parse content value"); + return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize); +} + +static int CheckUnknowMatch_(const TriggerWorkSpace *workSpace, + int type, LogicCalculator *calculator, const char *content, uint32_t contentSize) +{ + PARAM_CHECK(workSpace != NULL && content != NULL, return -1, "Failed arg for trigger"); + PARAM_CHECK(type == TRIGGER_UNKNOW, return -1, "Invalid type"); + + CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1); + int ret = memcpy_s(calculator->triggerContent, sizeof(calculator->triggerContent), content, contentSize); + PARAM_CHECK(ret == EOK, return -1, "Failed to memcpy"); + calculator->inputName = NULL; + calculator->inputContent = NULL; + return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize); +} + +int32_t CheckAndMarkTrigger_(const TriggerWorkSpace *workSpace, int type, const char *name) +{ + PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "Failed arg for trigger"); + TriggerHeader *head = GetTriggerHeader(workSpace, type); + PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type); + int ret = 0; + TriggerNode *trigger = head->nextTrigger(head, NULL); + while (trigger != NULL) { + if (head->getCondition(trigger) == NULL) { + trigger = head->nextTrigger(head, trigger); + continue; + } + if (CheckMatchSubCondition(head->getCondition(trigger), name, strlen(name)) == 1) { + TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_RELATED); + ret = 1; + } + trigger = head->nextTrigger(head, trigger); + } + return ret; +} - calculator.triggerExecuter = triggerExecuter; - CheckTrigger_(workSpace, &calculator, TRIGGER_PARAM, content, contentSize); - CalculatorFree(&calculator); +int CheckTrigger(TriggerWorkSpace *workSpace, int type, + const char *content, uint32_t contentSize, PARAM_CHECK_DONE triggerCheckDone) +{ + PARAM_CHECK(workSpace != NULL && content != NULL && triggerCheckDone != NULL, + return -1, "Failed arg for trigger"); + PARAM_LOGV("CheckTrigger_ type: %d content: %s ", type, content); + TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type); + if (triggerHead != NULL) { + LogicCalculator calculator = {{0}}; + calculator.triggerCheckDone = triggerCheckDone; + int ret = triggerHead->checkTriggerMatch(workSpace, type, &calculator, content, contentSize); + CalculatorFree(&calculator); + return ret; + } return 0; } -int CheckAndExecuteTrigger(TriggerWorkSpace *workSpace, const char *content, PARAM_CHECK_DONE triggerExecuter) +static void DumpJobTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger) { - PARAM_CHECK(workSpace != NULL && content != NULL && triggerExecuter != NULL, - return -1, "Failed arg for param trigger"); - LogicCalculator calculator = {}; - CalculatorInit(&calculator, 100, sizeof(LogicData), 1); + const JobNode *node = (const JobNode *)trigger; + PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags); + PARAM_DUMP("trigger name: %s \n", node->name); + PARAM_DUMP("trigger condition: %s \n", node->condition); + const int maxCmd = 1024; + int count = 0; + CommandNode *cmd = GetNextCmdNode(node, NULL); + while (cmd != NULL && count < maxCmd) { + PARAM_DUMP(" command name: %s (%s) \n", GetCmdKey(cmd->cmdKeyIndex), + (cmd->cfgContext.type == INIT_CONTEXT_CHIPSET) ? "chipset" : "system"); + PARAM_DUMP(" command args : %s \n", cmd->content); + cmd = GetNextCmdNode(node, cmd); + count++; + } +} - int ret = memcpy_s(calculator.triggerContent, sizeof(calculator.triggerContent), content, strlen(content)); - PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Failed to memcpy"); +static void DumpWatchTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger) +{ + PARAM_CHECK(trigger != NULL, return, "Empty trigger"); + const WatchNode *node = (const WatchNode *)trigger; + PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags); + PARAM_DUMP("trigger condition: %s \n", trigger->condition); + PARAM_DUMP("trigger watchId: %d \n", node->watchId); +} - calculator.triggerExecuter = triggerExecuter; - calculator.inputName = NULL; - calculator.inputContent = NULL; - // 执行完成后,对第三类trigger检查,执行必须是在本阶段执行的trigger - CheckTrigger_(workSpace, &calculator, TRIGGER_UNKNOW, content, 0); - CalculatorFree(&calculator); - return 0; +static void DumpWaitTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger) +{ + PARAM_CHECK(trigger != NULL, return, "Empty trigger"); + const WaitNode *node = (const WaitNode *)trigger; + PARAM_DUMP("trigger flags: 0x%08x \n", trigger->flags); + PARAM_DUMP("trigger name: %s \n", GetTriggerName(trigger)); + PARAM_DUMP("trigger condition: %s \n", trigger->condition); + PARAM_DUMP("trigger waitId: %d \n", node->waitId); + PARAM_DUMP("trigger timeout: %d \n", node->timeout); } -TriggerNode *GetTriggerByName(TriggerWorkSpace *workSpace, const char *triggerName, u_int32_t *triggerIndex) +static void DumpTrigger_(const TriggerWorkSpace *workSpace, int type) { - PARAM_CHECK(workSpace != NULL && triggerName != NULL, return NULL, "Invalid param"); - for (size_t i = 0; i < sizeof(workSpace->header) / sizeof(workSpace->header[0]); i++) { - u_int32_t index = workSpace->header[i].firstTrigger; - TriggerNode *trigger = GetTriggerByIndex(workSpace, workSpace->header[i].firstTrigger); - while (trigger != NULL) { - if (strcmp(triggerName, trigger->name) == 0) { - *triggerIndex = index; - return trigger; - } - index = trigger->next; - trigger = GetTriggerByIndex(workSpace, trigger->next); + PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace "); + TriggerHeader *head = GetTriggerHeader(workSpace, type); + PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); + TriggerNode *trigger = head->nextTrigger(head, NULL); + while (trigger != NULL) { + head->dumpTrigger(workSpace, trigger); + trigger = head->nextTrigger(head, trigger); + } +} + +void SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...)) +{ + if (dump != NULL) { + g_printf = dump; + } else { + g_printf = printf; + } + TriggerWorkSpace *workSpace = GetTriggerWorkSpace(); + PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace "); + PARAM_DUMP("workspace queue BOOT info:\n"); + DumpTrigger_(workSpace, TRIGGER_BOOT); + PARAM_DUMP("workspace queue parameter info:\n"); + DumpTrigger_(workSpace, TRIGGER_PARAM); + PARAM_DUMP("workspace queue other info:\n"); + DumpTrigger_(workSpace, TRIGGER_UNKNOW); + PARAM_DUMP("workspace queue watch info:\n"); + DumpTrigger_(workSpace, TRIGGER_PARAM_WATCH); + PARAM_DUMP("workspace queue wait info:\n"); + DumpTrigger_(workSpace, TRIGGER_PARAM_WAIT); + + PARAM_DUMP("workspace queue execute info:\n"); + PARAM_DUMP("queue info count: %u start: %u end: %u\n", + workSpace->executeQueue.queueCount, workSpace->executeQueue.startIndex, workSpace->executeQueue.endIndex); + for (uint32_t index = workSpace->executeQueue.startIndex; index < workSpace->executeQueue.endIndex; index++) { + TriggerNode *trigger = workSpace->executeQueue.executeQueue[index % workSpace->executeQueue.queueCount]; + if (trigger != 0) { + PARAM_DUMP(" queue node trigger name: %s \n", GetTriggerName(trigger)); } } - return NULL; +} + +static int32_t CompareData_(const struct tagTriggerNode_ *trigger, const void *data) +{ + PARAM_CHECK(trigger != NULL && data != NULL, return -1, "Invalid trigger"); + if (trigger->type == TRIGGER_PARAM_WAIT) { + WaitNode *node = (WaitNode *)trigger; + return node->waitId - *(uint32_t *)data; + } else if (trigger->type == TRIGGER_PARAM_WATCH) { + WatchNode *node = (WatchNode *)trigger; + return node->watchId - *(uint32_t *)data; + } + return -1; +} + +static void TriggerHeadSetDefault(TriggerHeader *head) +{ + OH_ListInit(&head->triggerList); + head->triggerCount = 0; + head->cmdNodeCount = 0; + head->addTrigger = AddJobTrigger_; + head->nextTrigger = GetNextTrigger_; + head->delTrigger = DelJobTrigger_; + head->executeTrigger = NULL; + head->checkAndMarkTrigger = CheckAndMarkTrigger_; + head->checkTriggerMatch = CheckBootMatch_; + head->checkCondition = CheckBootCondition_; + head->getCondition = GetBootCondition_; + head->getTriggerName = GetJobName_; + head->dumpTrigger = DumpJobTrigger_; + head->compareData = CompareData_; +} + +static int JobNodeNodeCompare(const HashNode *node1, const HashNode *node2) +{ + JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode); + JobNode *jobNode2 = HASHMAP_ENTRY(node2, JobNode, hashNode); + return strcmp(jobNode1->name, jobNode2->name); +} + +static int JobNodeKeyCompare(const HashNode *node1, const void *key) +{ + JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode); + return strcmp(jobNode1->name, (char *)key); +} + +static int JobNodeGetNodeHasCode(const HashNode *node) +{ + JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode); + int code = 0; + size_t nameLen = strlen(jobNode->name); + for (size_t i = 0; i < nameLen; i++) { + code += jobNode->name[i] - 'A'; + } + return code; +} + +static int JobNodeGetKeyHasCode(const void *key) +{ + int code = 0; + const char *buff = (char *)key; + size_t buffLen = strlen(buff); + for (size_t i = 0; i < buffLen; i++) { + code += buff[i] - 'A'; + } + return code; +} + +static void JobNodeFree(const HashNode *node, void *context) +{ + JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode); + FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)jobNode); +} + +void InitTriggerHead(const TriggerWorkSpace *workSpace) +{ + HashInfo info = { + JobNodeNodeCompare, + JobNodeKeyCompare, + JobNodeGetNodeHasCode, + JobNodeGetKeyHasCode, + JobNodeFree, + 64 + }; + PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace"); + int ret = OH_HashMapCreate((HashMapHandle *)&workSpace->hashMap, &info); + PARAM_CHECK(ret == 0, return, "Failed to create hash map"); + + TriggerHeader *head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_BOOT]; + TriggerHeadSetDefault(head); + // param trigger + head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM]; + TriggerHeadSetDefault(head); + head->checkTriggerMatch = CheckParamMatch_; + head->checkCondition = CheckParamCondition_; + head->getCondition = GetTriggerCondition_; + // unknown trigger + head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_UNKNOW]; + TriggerHeadSetDefault(head); + head->checkTriggerMatch = CheckUnknowMatch_; + head->checkCondition = CheckUnknowCondition_; + head->getCondition = GetTriggerCondition_; + // wait trigger + head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WAIT]; + TriggerHeadSetDefault(head); + head->addTrigger = AddWatchTrigger_; + head->delTrigger = DelWatchTrigger_; + head->checkTriggerMatch = CheckParamMatch_; + head->checkCondition = CheckParamCondition_; + head->getCondition = GetTriggerCondition_; + head->dumpTrigger = DumpWaitTrigger_; + head->getTriggerName = GetWatchName_; + // watch trigger + head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WATCH]; + TriggerHeadSetDefault(head); + head->addTrigger = AddWatchTrigger_; + head->delTrigger = DelWatchTrigger_; + head->checkTriggerMatch = CheckBootMatch_; + head->checkCondition = CheckWatchCondition_; + head->getCondition = GetTriggerCondition_; + head->dumpTrigger = DumpWatchTrigger_; + head->getTriggerName = GetWatchName_; +} + +void DelWatchTrigger(int type, const void *data) +{ + PARAM_CHECK(data != NULL, return, "Invalid data"); + TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type); + PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); + PARAM_CHECK(head->compareData != NULL, return, "Invalid compareData"); + TriggerNode *trigger = head->nextTrigger(head, NULL); + while (trigger != NULL) { + if (head->compareData(trigger, data) == 0) { + head->delTrigger(GetTriggerWorkSpace(), trigger); + return; + } + trigger = head->nextTrigger(head, trigger); + } +} + +void ClearWatchTrigger(ParamWatcher *watcher, int type) +{ + PARAM_CHECK(watcher != NULL, return, "Invalid watcher"); + TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type); + PARAM_CHECK(head != NULL, return, "Failed to get header %d", type); + ListNode *node = watcher->triggerHead.next; + while (node != &watcher->triggerHead) { + TriggerNode *trigger = NULL; + if (type == TRIGGER_PARAM_WAIT) { + trigger = (TriggerNode *)ListEntry(node, WaitNode, item); + } else if (type == TRIGGER_PARAM_WATCH) { + trigger = (TriggerNode *)ListEntry(node, WatchNode, item); + } + if (trigger == NULL || type != trigger->type) { + PARAM_LOGE("ClearWatchTrigger %s error type %d", GetTriggerName(trigger), type); + return; + } + PARAM_LOGV("ClearWatchTrigger %s", GetTriggerName(trigger)); + ListNode *next = node->next; + FreeTrigger(GetTriggerWorkSpace(), trigger); + node = next; + } +} + +int CheckWatchTriggerTimeout(void) +{ + TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), TRIGGER_PARAM_WAIT); + PARAM_CHECK(head != NULL && head->nextTrigger != NULL, return 0, "Invalid header"); + int hasNode = 0; + WaitNode *node = (WaitNode *)head->nextTrigger(head, NULL); + while (node != NULL) { + WaitNode *next = (WaitNode *)head->nextTrigger(head, (TriggerNode *)node); + if (node->timeout > 0) { + node->timeout--; + } else { + head->executeTrigger((TriggerNode*)node, NULL, 0); + FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)node); + } + hasNode = 1; + node = next; + } + return hasNode; +} + +TriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type) +{ + if (workSpace == NULL || type >= TRIGGER_MAX) { + return NULL; + } + return (TriggerHeader *)&workSpace->triggerHead[type]; +} + +char *GetTriggerCache(uint32_t *size) +{ + TriggerWorkSpace *space = GetTriggerWorkSpace(); + if (space == NULL) { + return NULL; + } + if (size != NULL) { + *size = sizeof(space->cache) / sizeof(space->cache[0]); + } + return space->cache; +} + +const char *GetTriggerName(const TriggerNode *trigger) +{ + PARAM_CHECK(trigger != NULL, return "", "Invalid trigger"); + TriggerHeader *triggerHead = GetTriggerHeader(GetTriggerWorkSpace(), trigger->type); + if (triggerHead) { + return triggerHead->getTriggerName(trigger); + } + return ""; } diff --git a/services/param/trigger/trigger_processor.c b/services/param/trigger/trigger_processor.c index 96d67fc46b9864a43f1ff4983c5021cd4801bca0..172f774c7ed8a581915111ac0b92217484a991f9 100644 --- a/services/param/trigger/trigger_processor.c +++ b/services/param/trigger/trigger_processor.c @@ -12,204 +12,402 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include -#include "trigger_processor.h" -#include -#include - -#include "init_cmds.h" +#include "init_param.h" +#include "init_service_manager.h" +#include "init_utils.h" #include "param_manager.h" +#include "param_message.h" +#include "param_utils.h" #include "trigger_checker.h" -#include "uv.h" +#include "trigger_manager.h" +#include "securec.h" +#include "hookmgr.h" +#include "bootstage.h" -#define LABEL "Trigger" #define MAX_TRIGGER_COUNT_RUN_ONCE 20 -#define SYS_POWER_CTRL "sys.powerctrl=" -#define OHOS_CTL_START "ohos.ctl.start=" -#define OHOS_CTL_STOP "ohos.ctl.stop=" - +#define MAX_TRIGGER_NAME_LENGTH 256 static TriggerWorkSpace g_triggerWorkSpace = {}; -static int DoCmdExecute(TriggerNode *trigger, const char *cmdName, const char *command) +static int DoTriggerExecute_(const TriggerNode *trigger, const char *content, uint32_t size) { - PARAM_CHECK(trigger != NULL && cmdName != NULL && command != NULL, return -1, "Invalid param"); - PARAM_LOGD("DoCmdExecute trigger %s cmd %s %s", trigger->name, cmdName, command); - if (strncmp(cmdName, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) { - DoTriggerExec(command); - return 0; + PARAM_CHECK(trigger != NULL, return -1, "Invalid trigger"); + PARAM_LOGV("Do execute trigger %s type: %d", GetTriggerName(trigger), trigger->type); + PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return -1, "Invalid trigger type %d", trigger->type); + CommandNode *cmd = GetNextCmdNode((JobNode *)trigger, NULL); + while (cmd != NULL) { +#ifndef STARTUP_INIT_TEST + DoCmdByIndex(cmd->cmdKeyIndex, cmd->content, &cmd->cfgContext); +#endif + cmd = GetNextCmdNode((JobNode *)trigger, cmd); } - DoCmdByName(cmdName, command); return 0; } -static int DoTiggerCheckResult(TriggerNode *trigger, u_int32_t triggerIndex) +static int DoTriggerCheckResult(TriggerNode *trigger, const char *content, uint32_t size) { - // 已经在队列中了,则不执行 TODO - if (TRIGGER_NODE_IN_QUEUE(trigger)) { - PARAM_LOGI("DoTiggerExecute trigger %s has been waiting execute", trigger->name); + UNUSED(content); + UNUSED(size); + if (TRIGGER_IN_QUEUE(trigger)) { + PARAM_LOGI("DoTiggerExecute trigger %s has been waiting execute", GetTriggerName(trigger)); return 0; } - TRIGGER_NODE_SET_QUEUE_FLAG(trigger); - PARAM_LOGI("Waiting to exec trigger %s", trigger->name); - ExecuteQueuePush(&g_triggerWorkSpace, trigger, triggerIndex); + TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_QUEUE); + PARAM_LOGV("Add trigger %s to execute queue", GetTriggerName(trigger)); + ExecuteQueuePush(&g_triggerWorkSpace, trigger); return 0; } -static int ExecuteTiggerImmediately(TriggerNode *trigger, u_int32_t triggerIndex) +static int ExecuteTriggerImmediately(TriggerNode *trigger, const char *content, uint32_t size) { - return ExecuteTrigger(&g_triggerWorkSpace, trigger, DoCmdExecute); + PARAM_CHECK(trigger != NULL, return -1, "Invalid trigger"); + PARAM_LOGV("ExecuteTriggerImmediately trigger %s", GetTriggerName(trigger)); + TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, trigger->type); + if (triggerHead != NULL) { + triggerHead->executeTrigger(trigger, content, size); + TRIGGER_CLEAR_FLAG(trigger, TRIGGER_FLAGS_QUEUE); + + if (TRIGGER_TEST_FLAG(trigger, TRIGGER_FLAGS_ONCE)) { + FreeTrigger(&g_triggerWorkSpace, trigger); + } + } + return 0; } -void ExecuteQueueWork(u_int32_t maxCount) +static void StartTriggerExecute_(TriggerNode *trigger, const char *content, uint32_t size) { - u_int32_t executeCount = 0; + TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, trigger->type); + if (triggerHead != NULL) { + PARAM_LOGV("StartTriggerExecute_ trigger %s flags:0x%04x", + GetTriggerName(trigger), trigger->flags); + triggerHead->executeTrigger(trigger, content, size); + TRIGGER_CLEAR_FLAG(trigger, TRIGGER_FLAGS_QUEUE); + if (TRIGGER_TEST_FLAG(trigger, TRIGGER_FLAGS_SUBTRIGGER)) { // boot && xxx=xxx trigger + const char *condition = triggerHead->getCondition(trigger); + CheckTrigger(&g_triggerWorkSpace, TRIGGER_UNKNOW, condition, strlen(condition), ExecuteTriggerImmediately); + } + if (TRIGGER_TEST_FLAG(trigger, TRIGGER_FLAGS_ONCE)) { + FreeTrigger(&g_triggerWorkSpace, trigger); + } + } +} + +static void ExecuteQueueWork(uint32_t maxCount, void (*bootStateChange)(int start, const char *)) +{ + uint32_t executeCount = 0; TriggerNode *trigger = ExecuteQueuePop(&g_triggerWorkSpace); + char triggerName[MAX_TRIGGER_NAME_LENGTH] = {0}; while (trigger != NULL) { - ExecuteTrigger(&g_triggerWorkSpace, trigger, DoCmdExecute); - TRIGGER_NODE_CLEAR_QUEUE_FLAG(trigger); - CheckAndExecuteTrigger(&g_triggerWorkSpace, trigger->name, ExecuteTiggerImmediately); + int ret = strcpy_s(triggerName, sizeof(triggerName), GetTriggerName(trigger)); + PARAM_CHECK(ret == 0, return, "strcpy triggerName failed!"); + if (bootStateChange != NULL) { + bootStateChange(0, triggerName); + } + StartTriggerExecute_(trigger, NULL, 0); + if (bootStateChange != NULL) { + bootStateChange(1, triggerName); + } executeCount++; if (executeCount > maxCount) { break; } - PARAM_LOGI("ExecuteQueueWork %u", executeCount); trigger = ExecuteQueuePop(&g_triggerWorkSpace); } } -static void CheckTriggers(int type, void *content, u_int32_t contentLen) +PARAM_STATIC void ProcessBeforeEvent(const ParamTaskPtr stream, + uint64_t eventId, const uint8_t *content, uint32_t size) { - switch (type) { - case EVENT_PROPERTY: { - CheckParamTrigger(&g_triggerWorkSpace, content, contentLen, DoTiggerCheckResult); + PARAM_LOGV("ProcessBeforeEvent %s ", (char *)content); + switch (eventId) { + case EVENT_TRIGGER_PARAM: { + CheckTrigger(&g_triggerWorkSpace, TRIGGER_PARAM, + (const char *)content, size, DoTriggerCheckResult); + ExecuteQueueWork(MAX_TRIGGER_COUNT_RUN_ONCE, NULL); + break; + } + case EVENT_TRIGGER_BOOT: { + if (g_triggerWorkSpace.bootStateChange != NULL) { + g_triggerWorkSpace.bootStateChange(0, (const char *)content); + } + CheckTrigger(&g_triggerWorkSpace, TRIGGER_BOOT, + (const char *)content, size, DoTriggerCheckResult); + ExecuteQueueWork(1, NULL); + if (g_triggerWorkSpace.bootStateChange != NULL) { + g_triggerWorkSpace.bootStateChange(1, (const char *)content); + } + ExecuteQueueWork(MAX_TRIGGER_COUNT_RUN_ONCE, g_triggerWorkSpace.bootStateChange); + break; + } + case EVENT_TRIGGER_PARAM_WAIT: { + CheckTrigger(&g_triggerWorkSpace, TRIGGER_PARAM_WAIT, + (const char *)content, size, ExecuteTriggerImmediately); break; } - case EVENT_BOOT: { - CheckTrigger(&g_triggerWorkSpace, TRIGGER_BOOT, content, contentLen, DoTiggerCheckResult); + case EVENT_TRIGGER_PARAM_WATCH: { + CheckTrigger(&g_triggerWorkSpace, TRIGGER_PARAM_WATCH, + (const char *)content, size, ExecuteTriggerImmediately); break; } default: - PARAM_LOGI("CheckTriggers: %d", type); break; } } -static void ProcessAfterEvent(uv_work_t *req, int status) +static void SendTriggerEvent(int type, const char *content, uint32_t contentLen) { - free(req); - ExecuteQueueWork(MAX_TRIGGER_COUNT_RUN_ONCE); + PARAM_CHECK(content != NULL, return, "Invalid param"); + PARAM_LOGV("SendTriggerEvent type %d content %s", type, content); + ParamEventSend(g_triggerWorkSpace.eventHandle, (uint64_t)type, content, contentLen); } -static void ProcessEvent(uv_work_t *req) +void PostParamTrigger(int type, const char *name, const char *value) { - TriggerDataEvent *event = (TriggerDataEvent *)req; - CheckTriggers(event->type, event->content, event->contentSize); + PARAM_CHECK(name != NULL && value != NULL, return, "Invalid param"); + uint32_t bufferSize = strlen(name) + strlen(value) + 1 + 1 + 1; + PARAM_CHECK(bufferSize < (PARAM_CONST_VALUE_LEN_MAX + PARAM_NAME_LEN_MAX + 1 + 1 + 1), + return, "bufferSize is longest %d", bufferSize); + char *buffer = (char *)calloc(1, bufferSize); + PARAM_CHECK(buffer != NULL, return, "Failed to alloc memory for param %s", name); + int ret = sprintf_s(buffer, bufferSize - 1, "%s=%s", name, value); + PARAM_CHECK(ret > EOK, free(buffer); + return, "Failed to copy param"); + SendTriggerEvent(type, buffer, strlen(buffer)); + free(buffer); } -static const char *GetCmdInfo(const char *content, u_int32_t contentSize, char **cmdParam) +void PostTrigger(EventType type, const char *content, uint32_t contentLen) { - static const char *ctrlCmds[][2] = { - {"reboot", "reboot "} + PARAM_CHECK(content != NULL && contentLen > 0, return, "Invalid param"); + SendTriggerEvent(type, content, contentLen); +} + +static int GetTriggerType(const char *type) +{ + if (strncmp("param:", type, strlen("param:")) == 0) { + return TRIGGER_PARAM; + } + if (strncmp("boot-service:", type, strlen("boot-service:")) == 0) { + return TRIGGER_BOOT; + } + const char *triggerTypeStr[] = { + "pre-init", "boot", "early-init", "init", "late-init", "post-init", + "fs", "early-fs", "post-fs", "late-fs", "early-boot", "post-fs-data", "reboot", "suspend" }; - for (size_t i = 0; i < sizeof(ctrlCmds) / sizeof(ctrlCmds[0]); i++) { - if (strncmp(content, ctrlCmds[i][0], strlen(ctrlCmds[i][0])) == 0) { - *cmdParam = (char *)content; - return GetMatchCmd(ctrlCmds[i][1]); + for (size_t i = 0; i < ARRAY_LENGTH(triggerTypeStr); i++) { + if (strcmp(triggerTypeStr[i], type) == 0) { + return TRIGGER_BOOT; } } - return NULL; + return TRIGGER_UNKNOW; } -static void SendTriggerEvent(TriggerDataEvent *event) +static int GetCommandInfo(const char *cmdLine, int *cmdKeyIndex, char **content) { - if (event == NULL) { - return; + const char *matchCmd = GetMatchCmd(cmdLine, cmdKeyIndex); + PARAM_CHECK(matchCmd != NULL, return -1, "Command not support %s", cmdLine); + char *str = strstr(cmdLine, matchCmd); + if (str != NULL) { + str += strlen(matchCmd); } - int ctrlSize = strlen(SYS_POWER_CTRL); - if (strncmp(event->content, SYS_POWER_CTRL, ctrlSize) == 0) { - char *cmdParam = NULL; - const char *matchCmd = GetCmdInfo(event->content + ctrlSize, event->contentSize - ctrlSize, &cmdParam); - if (matchCmd != NULL) { - DoCmdByName(matchCmd, cmdParam); - } else { - PARAM_LOGE("SendTriggerEvent cmd %s not found", event->content); - } - } else if (strncmp(event->content, OHOS_CTL_START, strlen(OHOS_CTL_START)) == 0) { - DoCmdByName("start ", event->content + strlen(OHOS_CTL_START)); - } else if (strncmp(event->content, OHOS_CTL_STOP, strlen(OHOS_CTL_STOP)) == 0) { - DoCmdByName("stop ", event->content + strlen(OHOS_CTL_STOP)); - } else { - uv_queue_work(uv_default_loop(), &event->request, ProcessEvent, ProcessAfterEvent); - event = NULL; - } - if (event != NULL) { - free(event); + while (str != NULL && isspace(*str)) { + str++; } + *content = str; + return 0; } -void PostParamTrigger(const char *name, const char *value) +static void ParseJobHookExecute(const char *name, const cJSON *jobNode) { - PARAM_CHECK(name != NULL && value != NULL, return, "Invalid param"); - PARAM_LOGD("PostParamTrigger %s ", name); - int contentLen = strlen(name) + strlen(value) + 2; - TriggerDataEvent *event = (TriggerDataEvent *)malloc(sizeof(TriggerDataEvent) + contentLen); - PARAM_CHECK(event != NULL, return, "Failed to alloc memory"); - event->type = EVENT_PROPERTY; - event->request.data = (char*)event + sizeof(uv_work_t); - event->contentSize = BuildParamContent(event->content, contentLen, name, value); - PARAM_CHECK(event->contentSize > 0, return, "Failed to copy porperty"); - SendTriggerEvent(event); - PARAM_LOGI("PostParamTrigger %s success", name); + JOB_PARSE_CTX context; + + context.jobName = name; + context.jobNode = jobNode; + + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_JOB_PARSE, (void *)(&context), NULL); } -void PostTrigger(EventType type, const char *content, u_int32_t contentLen) +static int ParseTrigger_(const TriggerWorkSpace *workSpace, + const cJSON *triggerItem, int (*checkJobValid)(const char *jobName), const ConfigContext *cfgContext) { - PARAM_LOGD("PostTrigger %d %s", type, content); - PARAM_CHECK(content != NULL && contentLen > 0, return, "Invalid param"); - TriggerDataEvent *event = (TriggerDataEvent *)malloc(sizeof(TriggerDataEvent) + contentLen + 1); - PARAM_CHECK(event != NULL, return, "Failed to alloc memory"); - event->type = type; - event->request.data = (char*)event + sizeof(uv_work_t); - event->contentSize = contentLen; - PARAM_CHECK(memcpy_s(event->content, contentLen, content, contentLen) == 0, return, "Failed to copy content"); - event->content[contentLen] = '\0'; - SendTriggerEvent(event); - PARAM_LOGD("PostTrigger %d success", type); + PARAM_CHECK(triggerItem != NULL, return -1, "Invalid file"); + PARAM_CHECK(workSpace != NULL, return -1, "Failed to create trigger list"); + char *name = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "name")); + PARAM_CHECK(name != NULL, return -1, "Can not get name from cfg"); + char *condition = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "condition")); + int type = GetTriggerType(name); + PARAM_CHECK(type <= TRIGGER_UNKNOW, return -1, "Failed to get trigger index"); + if (type != TRIGGER_BOOT && checkJobValid != NULL && checkJobValid(name) != 0) { + PARAM_LOGI("Trigger %s not exist in group", name); + return 0; + } + + TriggerHeader *header = GetTriggerHeader(workSpace, type); + PARAM_CHECK(header != NULL, return -1, "Failed to get header %d", type); + JobNode *trigger = UpdateJobTrigger(workSpace, type, condition, name); + PARAM_CHECK(trigger != NULL, return -1, "Failed to create trigger %s", name); + PARAM_LOGV("ParseTrigger %s type %d count %d", name, type, header->triggerCount); + cJSON *cmdItems = cJSON_GetObjectItem(triggerItem, CMDS_ARR_NAME_IN_JSON); + if (cmdItems == NULL || !cJSON_IsArray(cmdItems)) { + return 0; + } + int cmdLinesCnt = cJSON_GetArraySize(cmdItems); + PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name); + + int ret; + int cmdKeyIndex = 0; + for (int i = 0; (i < cmdLinesCnt) && (i < TRIGGER_MAX_CMD); ++i) { + char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i)); + PARAM_CHECK(cmdLineStr != NULL, continue, "Command is null"); + + char *content = NULL; + ret = GetCommandInfo(cmdLineStr, &cmdKeyIndex, &content); + PARAM_CHECK(ret == 0, continue, "Command not support %s", cmdLineStr); + ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content, cfgContext); + PARAM_CHECK(ret == 0, continue, "Failed to add command %s", cmdLineStr); + header->cmdNodeCount++; + } + return 0; } -int ParseTriggerConfig(cJSON *fileRoot) +int ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName), void *context) { + PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Invalid trigger data"); PARAM_CHECK(fileRoot != NULL, return -1, "Invalid file"); - int ret = InitTriggerWorkSpace(&g_triggerWorkSpace); - PARAM_CHECK(ret == 0, return -1, "Failed to init trigger"); - + ConfigContext *cfgContext = (ConfigContext *)context; cJSON *triggers = cJSON_GetObjectItemCaseSensitive(fileRoot, TRIGGER_ARR_NAME_IN_JSON); - PARAM_CHECK(cJSON_IsArray(triggers), return -1, "Trigger item must array"); - + if (triggers == NULL || !cJSON_IsArray(triggers)) { + return 0; + } int size = cJSON_GetArraySize(triggers); PARAM_CHECK(size > 0, return -1, "Trigger array size must positive"); - for (int i = 0; i < size; ++i) { + for (int i = 0; i < size && i < TRIGGER_MAX_CMD; ++i) { cJSON *item = cJSON_GetArrayItem(triggers, i); - ParseTrigger(&g_triggerWorkSpace, item); + ParseTrigger_(&g_triggerWorkSpace, item, checkJobValid, cfgContext); + /* + * execute job parsing hooks + */ + ParseJobHookExecute(cJSON_GetStringValue(cJSON_GetObjectItem(item, "name")), item); } return 0; } -void DoTriggerExec(const char *content) +int CheckAndMarkTrigger(int type, const char *name) { - PARAM_CHECK(content != NULL, return, "Invalid trigger content"); - u_int32_t triggerIndex = 0; - TriggerNode *trigger = GetTriggerByName(&g_triggerWorkSpace, content, &triggerIndex); - if (trigger != NULL && !TRIGGER_NODE_IN_QUEUE(trigger)) { // 不在队列中 - PARAM_LOGI("DoTriggerExec trigger %s", trigger->name); - TRIGGER_NODE_SET_QUEUE_FLAG(trigger); - ExecuteQueuePush(&g_triggerWorkSpace, trigger, triggerIndex); + TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, type); + if (triggerHead) { + return triggerHead->checkAndMarkTrigger(&g_triggerWorkSpace, type, name); } + return 0; } -TriggerWorkSpace *GetTriggerWorkSpace() +int InitTriggerWorkSpace(void) +{ + if (g_triggerWorkSpace.eventHandle != NULL) { + return 0; + } + g_triggerWorkSpace.bootStateChange = NULL; + ParamEventTaskCreate(&g_triggerWorkSpace.eventHandle, ProcessBeforeEvent); + PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Failed to event handle"); + + // executeQueue + g_triggerWorkSpace.executeQueue.executeQueue = calloc(1, TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *)); + PARAM_CHECK(g_triggerWorkSpace.executeQueue.executeQueue != NULL, + return -1, "Failed to alloc memory for executeQueue"); + g_triggerWorkSpace.executeQueue.queueCount = TRIGGER_EXECUTE_QUEUE; + g_triggerWorkSpace.executeQueue.startIndex = 0; + g_triggerWorkSpace.executeQueue.endIndex = 0; + InitTriggerHead(&g_triggerWorkSpace); + RegisterTriggerExec(TRIGGER_BOOT, DoTriggerExecute_); + RegisterTriggerExec(TRIGGER_PARAM, DoTriggerExecute_); + RegisterTriggerExec(TRIGGER_UNKNOW, DoTriggerExecute_); + PARAM_LOGV("InitTriggerWorkSpace success"); + return 0; +} + +void CloseTriggerWorkSpace(void) +{ + for (size_t i = 0; i < sizeof(g_triggerWorkSpace.triggerHead) / sizeof(g_triggerWorkSpace.triggerHead[0]); i++) { + ClearTrigger(&g_triggerWorkSpace, i); + } + OH_HashMapDestory(g_triggerWorkSpace.hashMap, NULL); + g_triggerWorkSpace.hashMap = NULL; + free(g_triggerWorkSpace.executeQueue.executeQueue); + g_triggerWorkSpace.executeQueue.executeQueue = NULL; + ParamTaskClose(g_triggerWorkSpace.eventHandle); + g_triggerWorkSpace.eventHandle = NULL; +} + +TriggerWorkSpace *GetTriggerWorkSpace(void) { return &g_triggerWorkSpace; } + +void RegisterTriggerExec(int type, + int32_t (*executeTrigger)(const struct tagTriggerNode_ *, const char *, uint32_t)) +{ + TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, type); + if (triggerHead != NULL) { + triggerHead->executeTrigger = executeTrigger; + } +} + +void DoTriggerExec(const char *triggerName) +{ + PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return, "Invalid trigger data"); + PARAM_CHECK(triggerName != NULL, return, "Invalid param"); + JobNode *trigger = GetTriggerByName(&g_triggerWorkSpace, triggerName); + if (trigger != NULL && !TRIGGER_IN_QUEUE((TriggerNode *)trigger)) { + PARAM_LOGV("Trigger job %s", trigger->name); + TRIGGER_SET_FLAG((TriggerNode *)trigger, TRIGGER_FLAGS_QUEUE); + ExecuteQueuePush(&g_triggerWorkSpace, (TriggerNode *)trigger); + } else { + PARAM_LOGW("Can not find trigger %s", triggerName); + } +} + +void DoJobExecNow(const char *triggerName) +{ + PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return, "Invalid trigger data"); + PARAM_CHECK(triggerName != NULL, return, "Invalid param"); + JobNode *trigger = GetTriggerByName(&g_triggerWorkSpace, triggerName); + if (trigger != NULL) { + if (strncmp(triggerName, "reboot", strlen("reboot")) == 0) { + HookMgrExecute(GetBootStageHookMgr(), INIT_SHUT_DETECTOR, NULL, NULL); + } + StartTriggerExecute_((TriggerNode *)trigger, NULL, 0); + } +} + +int AddCompleteJob(const char *name, const char *condition, const char *cmdContent) +{ + PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Invalid trigger data"); + PARAM_CHECK(name != NULL, return -1, "Invalid name"); + PARAM_CHECK(cmdContent != NULL, return -1, "Invalid cmdContent"); + int type = GetTriggerType(name); + PARAM_CHECK(type <= TRIGGER_UNKNOW, return -1, "Failed to get trigger index"); + TriggerHeader *header = GetTriggerHeader(&g_triggerWorkSpace, type); + PARAM_CHECK(header != NULL, return -1, "Failed to get header %d", type); + + JobNode *trigger = UpdateJobTrigger(&g_triggerWorkSpace, type, condition, name); + PARAM_CHECK(trigger != NULL, return -1, "Failed to create trigger"); + char *content = NULL; + int cmdKeyIndex = 0; + int ret = GetCommandInfo(cmdContent, &cmdKeyIndex, &content); + PARAM_CHECK(ret == 0, return -1, "Command not support %s", cmdContent); + ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content, NULL); // use default context + PARAM_CHECK(ret == 0, return -1, "Failed to add command %s", cmdContent); + header->cmdNodeCount++; + PARAM_LOGV("AddCompleteJob %s type %d count %d", name, type, header->triggerCount); + return 0; +} + +void RegisterBootStateChange(void (*bootStateChange)(int, const char *)) +{ + if (bootStateChange != NULL) { + g_triggerWorkSpace.bootStateChange = bootStateChange; + } +} diff --git a/services/param/watcher/BUILD.gn b/services/param/watcher/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d21f29a24bdb513b04fb364d74036a28c712f972 --- /dev/null +++ b/services/param/watcher/BUILD.gn @@ -0,0 +1,71 @@ +# Copyright (c) 2021 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/begetd.gni") +import("//build/ohos.gni") + +ohos_prebuilt_etc("param_watcher.rc") { + source = "etc/param_watcher.cfg" + relative_install_dir = "init" + part_name = "init" + subsystem_name = "startup" +} + +ohos_shared_library("param_watcher") { + sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "proxy/watcher_manager.cpp", + "proxy/watcher_manager_stub.cpp", + "proxy/watcher_proxy.cpp", + ] + + include_dirs = [ + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/log", + "//base/startup/init/services/loopevent/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + ] + + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson", + "c_utils:utils", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (init_paramwatcher_hicollie_enable) { + external_deps += [ "hicollie:libhicollie" ] + defines = [ "HICOLLIE_ENABLE" ] + } + shlib_type = "sa" + install_images = [ "system" ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/services/param/watcher/agent/watcher.cpp b/services/param/watcher/agent/watcher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e289e1c14100d3575e78b0319a34e62dd1554c4 --- /dev/null +++ b/services/param/watcher/agent/watcher.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 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 "watcher.h" +#include "watcher_utils.h" + +namespace OHOS { +namespace init_param { +void Watcher::OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) +{ + UNUSED(name); + UNUSED(value); +} +} // namespace init_param +} // namespace OHOS diff --git a/services/param/watcher/agent/watcher.h b/services/param/watcher/agent/watcher.h new file mode 100644 index 0000000000000000000000000000000000000000..cf2541864904b24a4ac5215366ea8a2aaa284f55 --- /dev/null +++ b/services/param/watcher/agent/watcher.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 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 START_WATCHER_H +#define START_WATCHER_H + +#include +#include "watcher_stub.h" + +namespace OHOS { +namespace init_param { +class Watcher : public WatcherStub { +public: + Watcher() = default; + virtual ~Watcher() = default; + + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) override; +}; +} // namespace init_param +} // namespace OHOS +#endif // START_WATCHER_H \ No newline at end of file diff --git a/services/param/watcher/agent/watcher_manager_kits.cpp b/services/param/watcher/agent/watcher_manager_kits.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb48244bebe4f782cd01843c31ae6ca38c1c0fd6 --- /dev/null +++ b/services/param/watcher/agent/watcher_manager_kits.cpp @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2021 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 "watcher_manager_kits.h" + +#include "if_system_ability_manager.h" +#include "init_param.h" +#include "iservice_registry.h" +#include "iwatcher.h" +#include "iwatcher_manager.h" +#include "system_ability_definition.h" +#include "watcher_utils.h" +#include "parameter.h" + +namespace OHOS { +namespace init_param { +WatcherManagerKits &WatcherManagerKits::GetInstance(void) +{ + return DelayedRefSingleton::GetInstance(); +} + +WatcherManagerKits::WatcherManagerKits(void) {} + +WatcherManagerKits::~WatcherManagerKits(void) {} + +void WatcherManagerKits::ResetService(const wptr &remote) +{ + WATCHER_LOGI("Remote is dead, reset service instance"); + std::lock_guard lock(lock_); + if (watcherManager_ != nullptr) { + sptr object = watcherManager_->AsObject(); + if ((object != nullptr) && (remote == object)) { + object->RemoveDeathRecipient(deathRecipient_); + watcherManager_ = nullptr; + remoteWatcherId_ = 0; + remoteWatcher_ = nullptr; + if (threadForReWatch_ != nullptr) { + WATCHER_LOGI("Thead exist, delete thread"); + stop_ = true; + threadForReWatch_->join(); + delete threadForReWatch_; + } + stop_ = false; + threadForReWatch_ = new (std::nothrow)std::thread([this] {this->ReAddWatcher();}); + WATCHER_CHECK(threadForReWatch_ != nullptr, return, "Failed to create thread"); + } + } +} + +sptr WatcherManagerKits::GetService(void) +{ + std::lock_guard lock(lock_); + if (watcherManager_ != nullptr) { + return watcherManager_; + } + + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + WATCHER_CHECK(samgr != nullptr, return nullptr, "Get samgr failed"); + sptr object = samgr->GetSystemAbility(PARAM_WATCHER_DISTRIBUTED_SERVICE_ID); + WATCHER_CHECK(object != nullptr, return nullptr, "Get watcher manager object from samgr failed"); + if (deathRecipient_ == nullptr) { + deathRecipient_ = new DeathRecipient(); + } + + if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) { + WATCHER_LOGE("Failed to add death recipient"); + } + watcherManager_ = iface_cast(object); + return watcherManager_; +} + +void WatcherManagerKits::DeathRecipient::OnRemoteDied(const wptr &remote) +{ + DelayedRefSingleton::GetInstance().ResetService(remote); +} + +void WatcherManagerKits::ReAddWatcher(void) +{ + WATCHER_LOGV("ReAddWatcher"); + int count = 0; + const int maxRetryCount = 100; + const int sleepTime = 100; + auto watcherManager = GetService(); + while (watcherManager == nullptr && count < maxRetryCount) { + if (stop_) { + return; + } + watcherManager = GetService(); + usleep(sleepTime); + count++; + } + WATCHER_LOGV("ReAddWatcher count %d ", count); + WATCHER_CHECK(watcherManager != nullptr, return, "Failed to get watcher manager"); + // add or get remote agent + uint32_t remoteWatcherId = GetRemoteWatcher(); + WATCHER_CHECK(remoteWatcherId > 0, return, "Failed to get remote agent"); + std::lock_guard lock(mutex_); + for (auto iter = watchers_.begin(); iter != watchers_.end(); iter++) { + WATCHER_LOGI("Add old watcher keyPrefix %s ", iter->first.c_str()); + int ret = watcherManager->AddWatcher(iter->first, remoteWatcherId); + WATCHER_CHECK(ret == 0, continue, "Failed to add watcher for %s", iter->first.c_str()); + } +} + +WatcherManagerKits::ParamWatcher *WatcherManagerKits::GetParamWatcher(const std::string &keyPrefix) +{ + std::lock_guard lock(mutex_); + auto iter = watchers_.find(keyPrefix); + if (iter != watchers_.end()) { + return iter->second.get(); + } + return nullptr; +} + +uint32_t WatcherManagerKits::GetRemoteWatcher(void) +{ + std::lock_guard lock(mutex_); + if (remoteWatcher_ != nullptr) { + return remoteWatcherId_; + } + auto watcherManager = GetService(); + WATCHER_CHECK(watcherManager != nullptr, return 0, "Failed to get watcher manager"); + remoteWatcher_ = new RemoteWatcher(this); + WATCHER_CHECK(remoteWatcher_ != nullptr, return 0, "Failed to create watcher"); + remoteWatcherId_ = watcherManager->AddRemoteWatcher(getpid(), remoteWatcher_); + WATCHER_CHECK(remoteWatcherId_ != 0, return 0, "Failed to add watcher"); + return remoteWatcherId_; +} + +int32_t WatcherManagerKits::AddWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context) +{ + auto watcherManager = GetService(); + WATCHER_CHECK(watcherManager != nullptr, return PARAM_WATCHER_GET_SERVICE_FAILED, "Failed to get watcher manager"); + + // add or get remote agent + uint32_t remoteWatcherId = GetRemoteWatcher(); + WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent"); + ParamWatcherKitPtr watcher = nullptr; + { + std::lock_guard lock(mutex_); + // must check + WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent"); + if (watchers_.find(keyPrefix) == watchers_.end()) { + watcher = std::make_shared(keyPrefix); + WATCHER_CHECK(watcher != nullptr, return -1, "Failed to create watcher for %s", keyPrefix.c_str()); + int ret = watcher->AddParameterListener(callback, context); + WATCHER_CHECK(ret == 0, return ret, "Failed to add callback for %s ", keyPrefix.c_str()); + ret = watcherManager->AddWatcher(keyPrefix, remoteWatcherId); + WATCHER_CHECK(ret == 0, return -1, "Failed to add watcher for %s", keyPrefix.c_str()); + watchers_[keyPrefix] = watcher; + } else { + watcher = watchers_[keyPrefix]; + int ret = watcher->AddParameterListener(callback, context); + WATCHER_CHECK(ret == 0, return ret, "Failed to add callback for %s ", keyPrefix.c_str()); + ret = watcherManager->RefreshWatcher(keyPrefix, remoteWatcherId); + WATCHER_CHECK(ret == 0, return -1, + "Failed to refresh watcher for %s %d", keyPrefix.c_str(), remoteWatcherId); + } + } + WATCHER_LOGI("Add watcher keyPrefix %s remoteWatcherId %u success", keyPrefix.c_str(), remoteWatcherId); + return 0; +} + +int32_t WatcherManagerKits::DelWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context) +{ + auto watcherManager = GetService(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get watcher manager"); + + WatcherManagerKits::ParamWatcher *watcher = GetParamWatcher(keyPrefix); + WATCHER_CHECK(watcher != nullptr, return -1, "Failed to get watcher"); + + int count = watcher->DelParameterListener(callback, context); + WATCHER_LOGI("DelWatcher keyPrefix_ %s count %d", keyPrefix.c_str(), count); + if (count != 0) { + return 0; + } + // delete watcher + int ret = watcherManager->DelWatcher(keyPrefix, remoteWatcherId_); + WATCHER_CHECK(ret == 0, return -1, "Failed to delete watcher for %s", keyPrefix.c_str()); + { + std::lock_guard lock(mutex_); + auto it = watchers_.find(keyPrefix); // delete watcher + if (it != watchers_.end()) { + watchers_.erase(it); + } + if (watchers_.empty()) { // no watcher, so delete remote agent + watcherManager->DelRemoteWatcher(remoteWatcherId_); + remoteWatcherId_ = 0; + remoteWatcher_ = nullptr; + } + } + return 0; +} + +WatcherManagerKits::ParameterChangeListener *WatcherManagerKits::ParamWatcher::GetParameterListener(uint32_t *idx) +{ + uint32_t index = *idx; + if (parameterChangeListeners.empty()) { + return nullptr; + } + while (index < listenerId_) { + auto it = parameterChangeListeners.find(index); + if (it != parameterChangeListeners.end()) { + *idx = index; + return parameterChangeListeners[index].get(); + } + index++; + } + return nullptr; +} + +void WatcherManagerKits::ParamWatcher::RemoveParameterListener(uint32_t idx) +{ + auto it = parameterChangeListeners.find(idx); + if (it != parameterChangeListeners.end()) { + parameterChangeListeners.erase(it); + } +} + +int WatcherManagerKits::ParamWatcher::AddParameterListener(ParameterChangePtr callback, void *context) +{ + std::lock_guard lock(mutex_); + WATCHER_CHECK(callback != nullptr, return -1, "Invalid callback "); + WATCHER_LOGV("AddParameterListener %s listenerId_ %d", keyPrefix_.c_str(), listenerId_); + for (auto it = parameterChangeListeners.begin(); it != parameterChangeListeners.end(); it++) { + if (it->second == nullptr) { + continue; + } + if (it->second->IsEqual(callback, context)) { + return PARAM_WATCHER_CALLBACK_EXIST; + } + } + std::shared_ptr changeNode = + std::make_shared(callback, context); + WATCHER_CHECK(changeNode != nullptr, return -1, "Failed to create listener"); + parameterChangeListeners[listenerId_] = changeNode; + listenerId_++; + return 0; +} + +int WatcherManagerKits::ParamWatcher::DelParameterListener(ParameterChangePtr callback, void *context) +{ + std::lock_guard lock(mutex_); + if (callback == nullptr) { + parameterChangeListeners.clear(); + return 0; + } + uint32_t index = 0; + ParameterChangeListener *listener = GetParameterListener(&index); + while (listener != nullptr) { + if (listener->IsEqual(callback, context)) { + WATCHER_LOGV("DelParameterListener listenerId_ %d", index); + RemoveParameterListener(index); + break; + } + index++; + listener = GetParameterListener(&index); + } + return static_cast(parameterChangeListeners.size()); +} + +void WatcherManagerKits::RemoteWatcher::OnParameterChange( + const std::string &prefix, const std::string &name, const std::string &value) +{ + Watcher::OnParameterChange(prefix, name, value); + // get param watcher + WatcherManagerKits::ParamWatcher *watcher = watcherManager_->GetParamWatcher(prefix); + WATCHER_CHECK(watcher != nullptr, return, "Failed to get watcher '%s'", prefix.c_str()); + if (watcher != nullptr) { + watcher->OnParameterChange(name, value); + } +} + +void WatcherManagerKits::ParamWatcher::OnParameterChange(const std::string &name, const std::string &value) +{ + std::lock_guard lock(mutex_); + WATCHER_LOGV("OnParameterChange name %s value %s", name.c_str(), value.c_str()); + uint32_t index = 0; + ParameterChangeListener *listener = GetParameterListener(&index); + while (listener != nullptr) { + if (!listener->CheckValueChange(name, value)) { + listener->OnParameterChange(name, value); + } + index++; + listener = GetParameterListener(&index); + } +} + +void WatcherManagerKits::ParameterChangeListener::OnParameterChange(const std::string &name, const std::string &value) +{ + if (callback_ != nullptr) { + callback_(name.c_str(), value.c_str(), context_); + } +} +} // namespace init_param +} // namespace OHOS + +static int PreHandleWatchParam(std::string &prefix) +{ + // clear space in head or tail + prefix.erase(0, prefix.find_first_not_of(" ")); + prefix.erase(prefix.find_last_not_of(" ") + 1); + WATCHER_CHECK(!prefix.empty(), return PARAM_CODE_INVALID_PARAM, "Invalid prefix"); + int ret = 0; + if (prefix.rfind(".*") == prefix.length() - 2) { // 2 last index + ret = WatchParamCheck(prefix.substr(0, prefix.length() - 2).c_str()); // 2 last index + } else if (prefix.rfind("*") == prefix.length() - 1) { + ret = WatchParamCheck(prefix.substr(0, prefix.length() - 1).c_str()); + } else if (prefix.rfind(".") == prefix.length() - 1) { + ret = WatchParamCheck(prefix.substr(0, prefix.length() - 1).c_str()); + } else { + ret = WatchParamCheck(prefix.c_str()); + } + return ret; +} + +int SystemWatchParameter(const char *keyPrefix, ParameterChangePtr callback, void *context) +{ + WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix"); + std::string key(keyPrefix); + int ret = PreHandleWatchParam(key); + if (ret != 0) { + return ret; + } + OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); + if (callback != nullptr) { + ret = instance.AddWatcher(keyPrefix, callback, context); + } else { + ret = instance.DelWatcher(keyPrefix, nullptr, nullptr); + } + + if (ret != 0) { + WATCHER_LOGE("SystemWatchParameter is failed! keyPrefix is:%s, errNum is:%d", keyPrefix, ret); + } + return ret; +} + +int RemoveParameterWatcher(const char *keyPrefix, ParameterChgPtr callback, void *context) +{ + WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix"); + std::string key(keyPrefix); + int ret = PreHandleWatchParam(key); + if (ret != 0) { + return ret; + } + OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); + ret = instance.DelWatcher(keyPrefix, (ParameterChangePtr)callback, context); + if (ret != 0) { + WATCHER_LOGE("RemoveParameterWatcher is failed! keyPrefix is:%s, errNum is:%d", keyPrefix, ret); + } + return ret; +} \ No newline at end of file diff --git a/services/param/watcher/agent/watcher_manager_kits.h b/services/param/watcher/agent/watcher_manager_kits.h new file mode 100644 index 0000000000000000000000000000000000000000..5816a1487d45cd9573c66c26559e2c7788e11089 --- /dev/null +++ b/services/param/watcher/agent/watcher_manager_kits.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 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 WATCHER_MANAGER_KITS_H +#define WATCHER_MANAGER_KITS_H +#include +#include +#include +#include + +#include "iwatcher.h" +#include "iwatcher_manager.h" +#include "singleton.h" +#include "init_param.h" +#include "watcher.h" +#include "watcher_utils.h" +#include "beget_ext.h" + +namespace OHOS { +namespace init_param { +class INIT_LOCAL_API WatcherManagerKits final : public DelayedRefSingleton { + DECLARE_DELAYED_REF_SINGLETON(WatcherManagerKits); +public: + DISALLOW_COPY_AND_MOVE(WatcherManagerKits); + + static WatcherManagerKits &GetInstance(void); + int32_t AddWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context); + int32_t DelWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context); + void ReAddWatcher(void); +private: + class ParameterChangeListener { + public: + ParameterChangeListener(ParameterChangePtr callback, void *context) + : callback_(callback), context_(context) {} + ~ParameterChangeListener(void) = default; + + bool IsEqual(ParameterChangePtr callback, const void *context) const + { + return (callback == callback_ && context == context_); + } + void OnParameterChange(const std::string &name, const std::string &value); + bool CheckValueChange(const std::string &name, const std::string &value) + { + bool ret = (value_ == value && name_ == name); + value_ = value; + name_ = name; + return ret; + } + private: + std::string value_ {}; + std::string name_ {}; + ParameterChangePtr callback_ { nullptr }; + void *context_ { nullptr }; + }; + + class ParamWatcher { + public: + explicit ParamWatcher(const std::string &key) : keyPrefix_(key) {} + ~ParamWatcher(void) + { + parameterChangeListeners.clear(); + }; + void OnParameterChange(const std::string &name, const std::string &value); + int AddParameterListener(ParameterChangePtr callback, void *context); + int DelParameterListener(ParameterChangePtr callback, void *context); + private: + ParameterChangeListener *GetParameterListener(uint32_t *idx); + void RemoveParameterListener(uint32_t idx); + std::string keyPrefix_ {}; + std::mutex mutex_; + uint32_t listenerId_ { 0 }; + std::map> parameterChangeListeners; + }; + + class RemoteWatcher final : public Watcher { + public: + explicit RemoteWatcher(WatcherManagerKits *watcherManager) : watcherManager_(watcherManager) {} + ~RemoteWatcher(void) override {} + + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) final; + private: + WatcherManagerKits *watcherManager_ = { nullptr }; + }; + + using ParamWatcherKitPtr = std::shared_ptr; + // For death event procession + class DeathRecipient final : public IRemoteObject::DeathRecipient { + public: + DeathRecipient(void) = default; + ~DeathRecipient(void) final = default; + DISALLOW_COPY_AND_MOVE(DeathRecipient); + void OnRemoteDied(const wptr &remote) final; + }; + sptr GetDeathRecipient(void) + { + return deathRecipient_; + } + + uint32_t GetRemoteWatcher(void); + ParamWatcher *GetParamWatcher(const std::string &keyPrefix); + void ResetService(const wptr &remote); + sptr GetService(void); + std::mutex lock_; + sptr watcherManager_ {}; + sptr deathRecipient_ {}; + + std::mutex mutex_; + uint32_t remoteWatcherId_ = { 0 }; + sptr remoteWatcher_ = { nullptr }; + std::map watchers_; + std::atomic stop_ { false }; + std::thread *threadForReWatch_ { nullptr }; +}; +} // namespace init_param +} // namespace OHOS +#endif // WATCHER_MANAGER_KITS_H diff --git a/services/param/watcher/agent/watcher_manager_proxy.cpp b/services/param/watcher/agent/watcher_manager_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5931268fa97a0cf1e17b799c0089f6d2ccfa7ff5 --- /dev/null +++ b/services/param/watcher/agent/watcher_manager_proxy.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 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 "watcher_manager_proxy.h" +#include "watcher_utils.h" +#include "sysparam_errno.h" + +namespace OHOS { +namespace init_param { +uint32_t WatcherManagerProxy::AddRemoteWatcher(uint32_t id, const sptr &watcher) +{ + WATCHER_CHECK(watcher != nullptr, return ERR_INVALID_VALUE, "Invalid param"); + MessageParcel data; + data.WriteInterfaceToken(WatcherManagerProxy::GetDescriptor()); + bool ret = data.WriteRemoteObject(watcher->AsObject()); + WATCHER_CHECK(ret, return 0, "Can not get remote"); + data.WriteUint32(id); + + MessageParcel reply; + MessageOption option { MessageOption::TF_SYNC }; + int32_t res = SendWatcherMsg(static_cast(ParamWatcherInterfaceCode::ADD_REMOTE_AGENT), + data, reply, option); + WATCHER_CHECK(res == ERR_OK, return 0, "Transact error %d", res); + return reply.ReadUint32(); +} + +int32_t WatcherManagerProxy::DelRemoteWatcher(uint32_t remoteWatcherId) +{ + MessageParcel data; + data.WriteInterfaceToken(WatcherManagerProxy::GetDescriptor()); + data.WriteUint32(remoteWatcherId); + MessageParcel reply; + MessageOption option { MessageOption::TF_SYNC }; + int32_t res = SendWatcherMsg(static_cast(ParamWatcherInterfaceCode::DEL_REMOTE_AGENT), + data, reply, option); + WATCHER_CHECK(res == ERR_OK, return ERR_FLATTEN_OBJECT, "Transact error"); + return reply.ReadInt32(); +} + +int32_t WatcherManagerProxy::SendMsg(int op, const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + MessageParcel data; + data.WriteInterfaceToken(WatcherManagerProxy::GetDescriptor()); + data.WriteString(keyPrefix); + data.WriteUint32(remoteWatcherId); + MessageParcel reply; + MessageOption option { MessageOption::TF_SYNC }; + int32_t res = SendWatcherMsg(op, data, reply, option); + WATCHER_CHECK(res == ERR_OK, return 0, "Transact error"); + return reply.ReadInt32(); +} + +int32_t WatcherManagerProxy::AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + return SendMsg(static_cast(ParamWatcherInterfaceCode::ADD_WATCHER), keyPrefix, remoteWatcherId); +} + +int32_t WatcherManagerProxy::DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + return SendMsg(static_cast(ParamWatcherInterfaceCode::DEL_WATCHER), keyPrefix, remoteWatcherId); +} + +int32_t WatcherManagerProxy::RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + return SendMsg(static_cast(ParamWatcherInterfaceCode::REFRESH_WATCHER), keyPrefix, remoteWatcherId); +} + +int32_t WatcherManagerProxy::SendWatcherMsg(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + auto remote = Remote(); + if (remote != nullptr) { + return remote->SendRequest(code, data, reply, option); + } +#ifdef STARTUP_INIT_TEST + return 0; +#else + return SYSPARAM_SYSTEM_ERROR; +#endif +} +} +} // namespace OHOS diff --git a/services/param/watcher/agent/watcher_manager_proxy.h b/services/param/watcher/agent/watcher_manager_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..432a91ad72d83836ba5acf9108eaeb49f00e96dd --- /dev/null +++ b/services/param/watcher/agent/watcher_manager_proxy.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 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 STARTUP_WATCH_MANAGER_PROXY_H +#define STARTUP_WATCH_MANAGER_PROXY_H + +#include "iremote_proxy.h" +#include "iwatcher_manager.h" +#include "beget_ext.h" + +namespace OHOS { +namespace init_param { +class INIT_LOCAL_API WatcherManagerProxy : public IRemoteProxy { +public: + explicit WatcherManagerProxy(const sptr &impl) : IRemoteProxy(impl) {} + + uint32_t AddRemoteWatcher(uint32_t id, const sptr &watcher) override; + int32_t DelRemoteWatcher(uint32_t remoteWatcherId) override; + int32_t AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; +private: + int32_t SendMsg(int op, const std::string &keyPrefix, uint32_t remoteWatcherId); + int32_t SendWatcherMsg(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option); + static inline BrokerDelegator delegator_; +}; +} // namespace init_param +} // namespace OHOS +#endif // STARTUP_WATCH_MANAGER_PROXY_H \ No newline at end of file diff --git a/services/param/watcher/agent/watcher_stub.cpp b/services/param/watcher/agent/watcher_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74356f52e5e96f4bfae4c19c4117c3ffdfbebabc --- /dev/null +++ b/services/param/watcher/agent/watcher_stub.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 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 "watcher_stub.h" + +#include "securec.h" +#include "watcher_utils.h" + +namespace OHOS { +namespace init_param { +int32_t WatcherStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string myDescriptor = IWatcher::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + WATCHER_CHECK(myDescriptor == remoteDescriptor, return -1, "Invalid remoteDescriptor"); + + switch (code) { + case PARAM_CHANGE: { + std::string key(data.ReadString()); + std::string name(data.ReadString()); + std::string value(data.ReadString()); + OnParameterChange(key, name, value); + break; + } + default: { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } + return 0; +} +} // namespace init_param +} // namespace OHOS diff --git a/services/include/init_service_socket.h b/services/param/watcher/agent/watcher_stub.h similarity index 44% rename from services/include/init_service_socket.h rename to services/param/watcher/agent/watcher_stub.h index 32669508531a6ac7d837e7b7421c9d89e722e9c1..778cbce532f59fefd56814de283e695a4bb2906e 100644 --- a/services/include/init_service_socket.h +++ b/services/param/watcher/agent/watcher_stub.h @@ -1,51 +1,35 @@ -/* - * Copyright (c) 2021 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 INIT_SERVICE_SOCKET_ -#define INIT_SERVICE_SOCKET_ -#include -#include -#include -#include -#include - -#define MAX_SOCK_NAME_LEN 16 -#define SOCK_OPT_NUMS 6 -enum SockOptionTab -{ - SERVICE_SOCK_NAME = 0, - SERVICE_SOCK_TYPE, - SERVICE_SOCK_PERM, - SERVICE_SOCK_UID, - SERVICE_SOCK_GID, - SERVICE_SOCK_SETOPT -}; - -struct ServiceSocket; -struct ServiceSocket -{ - char *name; // service name - int type; // socket type - uid_t uid; // uid - gid_t gid; // gid - bool passcred; // setsocketopt - mode_t perm; // Setting permissions - int sockFd; - struct ServiceSocket *next; -}; - -int DoCreateSocket(struct ServiceSocket *sockopt); - -#endif +/* + * Copyright (c) 2021 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 STARTUP_WATCHER_STUB_H_ +#define STARTUP_WATCHER_STUB_H_ + +#include "iremote_stub.h" +#include "iwatcher.h" +#include "message_parcel.h" +#include "parcel.h" + +namespace OHOS { +namespace init_param { +class WatcherStub : public IRemoteStub { +public: + explicit WatcherStub(bool serialInvokeFlag = true) + : IRemoteStub(serialInvokeFlag), serialInvokeFlag_(serialInvokeFlag) {} + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + bool serialInvokeFlag_ = { true }; +}; +} // namespace init_param +} // namespace OHOS +#endif // !defined(STARTUP_WATCHER_STUB_H_) diff --git a/services/param/watcher/etc/param_watcher.cfg b/services/param/watcher/etc/param_watcher.cfg new file mode 100755 index 0000000000000000000000000000000000000000..4b6f610f3972bf7a9a97474a0c3c4b990098be6b --- /dev/null +++ b/services/param/watcher/etc/param_watcher.cfg @@ -0,0 +1,13 @@ +{ + "services" : [{ + "name" : "param_watcher", + "path" : ["/system/bin/sa_main", "/system/profile/param_watcher.json"], + "critical" : [1, 4, 240], + "uid" : "paramwatcher", + "start-mode" : "boot", + "gid" : ["paramwatcher", "shell"], + "secon" : "u:r:param_watcher:s0", + "bootevents" : "bootevent.param_watcher.started" + } + ] +} diff --git a/services/param/watcher/etc/param_watcher.rc b/services/param/watcher/etc/param_watcher.rc new file mode 100755 index 0000000000000000000000000000000000000000..cea668a296d339f425619e533e948c848ddf29ed --- /dev/null +++ b/services/param/watcher/etc/param_watcher.rc @@ -0,0 +1,21 @@ +# Copyright (c) 2021 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. +service param_watcher /system/bin/sa_main /system/profile/param_watcher.json +class z_core +user system +group system shell +seclabel u:r:param_watcher:s0 + +on boot + start param_watcher + diff --git a/services/param/watcher/include/iwatcher.h b/services/param/watcher/include/iwatcher.h new file mode 100644 index 0000000000000000000000000000000000000000..9c3226003b533fdf2a9cae64e9a07b3d3fa653da --- /dev/null +++ b/services/param/watcher/include/iwatcher.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 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 ISTARTUP_WATCHER_H +#define ISTARTUP_WATCHER_H + +#include +#include "iremote_broker.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace init_param { +class IWatcher : public OHOS::IRemoteBroker { +public: + virtual ~IWatcher() = default; + enum { + PARAM_CHANGE = 1, + }; + + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Startup.IWatcher"); +public: + virtual void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) = 0; +}; +} // namespace init_param +} // namespace OHOS +#endif // ISTARTUP_WATCHER_H diff --git a/services/param/watcher/include/iwatcher_manager.h b/services/param/watcher/include/iwatcher_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..47453671ace5650d424a378eeede00e0d1378c3a --- /dev/null +++ b/services/param/watcher/include/iwatcher_manager.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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 ISTARTUP_WATCHER_MANAGER_H +#define ISTARTUP_WATCHER_MANAGER_H + +#include +#include "iremote_broker.h" +#include "iremote_proxy.h" +#include "iwatcher.h" +#include "param_watcher_ipc_interface_code.h" + +namespace OHOS { +namespace init_param { +class IWatcherManager : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Startup.IWatcherManager"); +public: + virtual uint32_t AddRemoteWatcher(uint32_t id, const sptr &watcher) = 0; + virtual int32_t DelRemoteWatcher(uint32_t remoteWatcherId) = 0; + virtual int32_t AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) = 0; + virtual int32_t DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) = 0; + virtual int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) = 0; +}; +} // namespace update_engine +} // namespace OHOS +#endif // ISTARTUP_WATCHER_MANAGER_H diff --git a/services/param/watcher/include/param_watcher_ipc_interface_code.h b/services/param/watcher/include/param_watcher_ipc_interface_code.h new file mode 100644 index 0000000000000000000000000000000000000000..adb2fb189d1d462fa2d46cc137311fed2b97ef01 --- /dev/null +++ b/services/param/watcher/include/param_watcher_ipc_interface_code.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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 PARAM_WATCHER_IPC_INTERFACE_CODE_H +#define PARAM_WATCHER_IPC_INTERFACE_CODE_H + +/* SAID: 3901 */ +namespace OHOS { +namespace init_param { +enum class ParamWatcherInterfaceCode { + ADD_WATCHER = 0, + DEL_WATCHER, + ADD_REMOTE_AGENT, + DEL_REMOTE_AGENT, + REFRESH_WATCHER +}; +} // namespace init_param +} // namespace OHOS + +#endif // PARAM_WATCHER_IPC_INTERFACE_CODE_H diff --git a/services/param/watcher/include/watcher_utils.h b/services/param/watcher/include/watcher_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..901630809280e3e670ab2f51e4b268e6cd11d30c --- /dev/null +++ b/services/param/watcher/include/watcher_utils.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 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 STARTUP_WATCHER_UTILS_H +#define STARTUP_WATCHER_UTILS_H +#include + +#include "init_log.h" +#include "iremote_broker.h" +#include "iremote_proxy.h" + +#include "securec.h" + +namespace OHOS { +namespace init_param { +#define UNUSED(x) (void)(x) +#ifndef WATCHER_DOMAIN +#define WATCHER_DOMAIN (BASE_DOMAIN + 3) +#endif +#define WATCHER_LABEL "PARAM_WATCHER" +#define WATCHER_LOGI(fmt, ...) STARTUP_LOGI(WATCHER_DOMAIN, WATCHER_LABEL, fmt, ##__VA_ARGS__) +#define WATCHER_LOGE(fmt, ...) STARTUP_LOGE(WATCHER_DOMAIN, WATCHER_LABEL, fmt, ##__VA_ARGS__) +#define WATCHER_LOGV(fmt, ...) STARTUP_LOGV(WATCHER_DOMAIN, WATCHER_LABEL, fmt, ##__VA_ARGS__) + +#define WATCHER_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + WATCHER_LOGE(__VA_ARGS__); \ + exper; \ + } +} // namespace init_param +} // namespace OHOS +#endif // STARTUP_WATCHER_UTILS_H diff --git a/services/param/watcher/proxy/watcher_manager.cpp b/services/param/watcher/proxy/watcher_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..065e57c7aca0510b40a918dd93631c34ee0c23dd --- /dev/null +++ b/services/param/watcher/proxy/watcher_manager.cpp @@ -0,0 +1,844 @@ +/* + * Copyright (c) 2021 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 "watcher_manager.h" +#include +#include +#include +#include +#include +#include + +#include "init_param.h" +#include "param_init.h" +#include "parameter.h" +#include "system_ability_definition.h" +#include "string_ex.h" +#include "watcher_utils.h" + +namespace OHOS { +namespace init_param { +REGISTER_SYSTEM_ABILITY_BY_ID(WatcherManager, PARAM_WATCHER_DISTRIBUTED_SERVICE_ID, true) + +const static int32_t INVALID_SOCKET = -1; +const static int32_t PUBLIC_APP_BEGIN_UID = 10000; +WatcherManager::~WatcherManager() +{ + Clear(); +} + +uint32_t WatcherManager::AddRemoteWatcher(uint32_t id, const sptr &watcher) +{ +#ifndef STARTUP_INIT_TEST + if (id == static_cast(getpid())) { + WATCHER_LOGE("Failed to add remote watcher %u", id); + return 0; + } +#endif + WATCHER_CHECK(watcher != nullptr, return 0, "Invalid remote watcher"); + WATCHER_CHECK(deathRecipient_ != nullptr, return 0, "Invalid deathRecipient_"); + sptr object = watcher->AsObject(); + if ((object != nullptr) && (object->IsProxyObject())) { + WATCHER_CHECK(object->AddDeathRecipient(deathRecipient_), return 0, "Failed to add death recipient %u", id); + } + uint32_t remoteWatcherId = 0; + { + std::lock_guard lock(watcherMutex_); + // check watcher id + int ret = GetRemoteWatcherId(remoteWatcherId); + WATCHER_CHECK(ret == 0, return 0, "Failed to get watcher id for %u", id); + // create remote watcher + RemoteWatcher *remoteWatcher = new RemoteWatcher(remoteWatcherId, watcher); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Failed to create watcher for %u", id); + remoteWatcher->SetAgentId(GetCallingPid()); + AddRemoteWatcher(remoteWatcher); + } + WATCHER_LOGI("Add remote watcher remoteWatcherId %u %u success", remoteWatcherId, id); + return remoteWatcherId; +} + +int32_t WatcherManager::DelRemoteWatcher(uint32_t remoteWatcherId) +{ + sptr watcher = {0}; + { + std::lock_guard lock(watcherMutex_); + RemoteWatcher *remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Can not find watcher %u", remoteWatcherId); + WATCHER_CHECK(remoteWatcher->CheckAgent(GetCallingPid()), return 0, + "Can not find watcher %u calling %u", remoteWatcher->GetAgentId(), static_cast(GetCallingPid())); + WATCHER_LOGI("Del remote watcher remoteWatcherId %u", remoteWatcherId); + watcher = remoteWatcher->GetWatcher(); + DelRemoteWatcher(remoteWatcher); + } + sptr object = watcher->AsObject(); + if (object != nullptr) { + object->RemoveDeathRecipient(deathRecipient_); + } + return 0; +} + +int32_t WatcherManager::CheckAppWatchPermission(const std::string &keyPrefix) +{ + if (keyPrefix.find("*") != std::string::npos) { + WATCHER_LOGE("param key has *, not need deal"); + return false; + } + static const std::vector whitelist = { + "persist.ace.debug.statemgr.enabled", + "persist.ace.debug.boundary.enabled", + "persist.ace.trace.layout.enabled", + "persist.ace.trace.inputevent.enabled", + "persist.ace.performance.monitor.enabled", + "persist.sys.graphic.animationscale", + "persist.sys.arkui.animationscale", + "persist.hdc.jdwp", + "persist.location.switch_mode", + "persist.super_privacy.mode", + "persist.global.locale", + "const.security.developermode.state", + "debug.graphic.frame", + "debug.graphic.debug_layer", + "debug.graphic.overdraw", + "debug.graphic.colors_overdraw", + "accessibility.config.ready", + "sys.hiview.chr.fluchcache", + "web.render.dump", + "web.debug.trace" + }; + + if (std::find(whitelist.begin(), whitelist.end(), keyPrefix) != whitelist.end()) { + return true; + } + return false; +} + +int32_t WatcherManager::AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + std::lock_guard lock(watcherMutex_); + // get remote watcher and group + WATCHER_CHECK((keyPrefix != "*") && (keyPrefix.size() < PARAM_NAME_LEN_MAX), + return -1, "Failed to verify keyPrefix."); + + // check calling uid, app not have watch permission + int uid = GetCallingUid(); + if (uid >= PUBLIC_APP_BEGIN_UID && !CheckAppWatchPermission(keyPrefix)) { + WATCHER_LOGE("app not have permission watch param:%s uid:%d pid:%d", keyPrefix.c_str(), uid, GetCallingPid()); + return -1; + } + + auto remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return -1, "Can not find remote watcher %d", remoteWatcherId); + WATCHER_CHECK(remoteWatcher->CheckAgent(GetCallingPid()), return 0, + "Can not find watcher %u calling %u", remoteWatcher->GetAgentId(), static_cast(GetCallingPid())); + auto group = AddWatcherGroup(keyPrefix); + WATCHER_CHECK(group != nullptr, return -1, "Failed to create group for %s", keyPrefix.c_str()); + { + // add watcher to agent and group + bool newGroup = group->Empty(); + AddParamWatcher(group, remoteWatcher); + if (newGroup) { + StartLoop(); + SendMessage(group, MSG_ADD_WATCHER); + } + } + SendLocalChange(keyPrefix, remoteWatcherId); + WATCHER_LOGI("Add watcher %s remoteWatcherId: %u groupId %u success", + keyPrefix.c_str(), remoteWatcherId, group->GetGroupId()); + return 0; +} + +int32_t WatcherManager::DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + std::lock_guard lock(watcherMutex_); + WATCHER_CHECK(keyPrefix.size() < PARAM_NAME_LEN_MAX, return -1, "Failed to verify keyPrefix."); + auto group = GetWatcherGroup(keyPrefix); + WATCHER_CHECK(group != nullptr, return 0, "Can not find group %s", keyPrefix.c_str()); + auto remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Can not find watcher %s %d", keyPrefix.c_str(), remoteWatcherId); + WATCHER_CHECK(remoteWatcher->CheckAgent(GetCallingPid()), return -1, + "Can not find watcher %u calling %u", remoteWatcher->GetAgentId(), static_cast(GetCallingPid())); + WATCHER_LOGI("Delete watcher prefix %s remoteWatcherId %u", keyPrefix.c_str(), remoteWatcherId); + { + // remove watcher from agent and group + DelParamWatcher(group, remoteWatcher); + if (group->Empty()) { // no watcher, so delete it + SendMessage(group, MSG_DEL_WATCHER); + DelWatcherGroup(group); + } + } + return 0; +} + +int32_t WatcherManager::RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + std::lock_guard lock(watcherMutex_); + WATCHER_CHECK(keyPrefix.size() < PARAM_NAME_LEN_MAX, return -1, "Failed to verify keyPrefix."); + WATCHER_LOGV("Refresh watcher %s remoteWatcherId: %u", keyPrefix.c_str(), remoteWatcherId); + auto remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Can not find watcher %s %d", keyPrefix.c_str(), remoteWatcherId); + WATCHER_CHECK(remoteWatcher->CheckAgent(GetCallingPid()), return 0, + "Can not find watcher %u calling %d", remoteWatcher->GetAgentId(), static_cast(GetCallingPid())); + + auto group = GetWatcherGroup(keyPrefix); + WATCHER_CHECK(group != nullptr, return 0, "Can not find group %s", keyPrefix.c_str()); + SendLocalChange(keyPrefix, remoteWatcherId); + return 0; +} + +int WatcherManager::SendMessage(WatcherGroupPtr group, int type) +{ + ParamMessage *request = nullptr; + std::string key(group->GetKeyPrefix()); + if (key.rfind("*") == key.length() - 1) { + key = key.substr(0, key.length() - 1); + } + request = (ParamMessage *)CreateParamMessage(type, key.c_str(), sizeof(ParamMessage)); + WATCHER_CHECK(request != NULL, return PARAM_CODE_ERROR, "Failed to malloc for watch"); + request->id.watcherId = group->GetGroupId(); + request->msgSize = sizeof(ParamMessage); + int ret = PARAM_CODE_FAIL_CONNECT; + int fd = GetServerFd(false); + if (fd < 0) { + WATCHER_LOGE("ParamWatcher get server fd failed!"); + free(request); + return PARAM_CODE_FAIL_CONNECT; + } + + ssize_t sendLen = send(serverFd_, (char *)request, request->msgSize, 0); + ret = (sendLen > 0) ? 0 : PARAM_CODE_IPC_ERROR; + free(request); + WATCHER_CHECK(ret == 0, return ret, "SendMessage key: %s %d fail!", group->GetKeyPrefix().c_str(), type); + return 0; +} + +void WatcherGroup::ProcessParameterChange( + WatcherManager *manager, const std::string &name, const std::string &value) +{ + WATCHER_LOGV("ProcessParameterChange key '%s' '%s'", GetKeyPrefix().c_str(), name.c_str()); + // walk watcher + TraversalNode([this, manager, name, value](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + auto remoteWatcher = manager->GetRemoteWatcher(node->GetNodeId()); + if (remoteWatcher == nullptr) { + return; + } + WATCHER_LOGI("ProcessParameterChange key '%s' pid: %d", GetKeyPrefix().c_str(), remoteWatcher->GetAgentId()); + remoteWatcher->ProcessParameterChange(GetKeyPrefix(), name, value); + }); +} + +static int FilterParam(const char *name, const std::string &keyPrefix) +{ + if (keyPrefix.rfind("*") == keyPrefix.length() - 1) { + return strncmp(name, keyPrefix.c_str(), keyPrefix.length() - 1) == 0; + } + if (keyPrefix.rfind(".") == keyPrefix.length() - 1) { + return strncmp(name, keyPrefix.c_str(), keyPrefix.length() - 1) == 0; + } + return strcmp(name, keyPrefix.c_str()) == 0; +} + +void WatcherManager::ProcessWatcherMessage(const ParamMessage *msg) +{ + uint32_t offset = 0; + if (msg->type != MSG_NOTIFY_PARAM) { + return; + } + ParamMsgContent *valueContent = GetNextContent(msg, &offset); + WATCHER_CHECK(valueContent != NULL, return, "Invalid msg "); + WATCHER_LOGV("Process watcher message name '%s' group id %u ", msg->key, msg->id.watcherId); + { + std::lock_guard lock(watcherMutex_); + WatcherGroupPtr group = GetWatcherGroup(msg->id.watcherId); + WATCHER_CHECK(group != NULL, return, "Can not find group for %u %s", msg->id.watcherId, msg->key); + if (!FilterParam(msg->key, group->GetKeyPrefix())) { + WATCHER_LOGV("Invalid message name '%s' group '%s' ", msg->key, group->GetKeyPrefix().c_str()); + return; + } + group->ProcessParameterChange(this, msg->key, valueContent->content); + } +} + +void WatcherManager::SendLocalChange(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + struct Context { + char *buffer; + uint32_t remoteWatcherId; + std::string keyPrefix; + WatcherManager *watcherManagerPtr; + }; + WATCHER_LOGI("SendLocalChange start keyPrefix '%s' remoteWatcherId %d", keyPrefix.c_str(), remoteWatcherId); + std::vector buffer(PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX); + struct Context context = {buffer.data(), remoteWatcherId, keyPrefix, this}; + // walk watcher + SystemTraversalParameter("", [](ParamHandle handle, void *cookie) { + if (cookie == nullptr) { + return; + } + struct Context *context = (struct Context *)(cookie); + SystemGetParameterName(handle, context->buffer, PARAM_NAME_LEN_MAX); + if (!FilterParam(context->buffer, context->keyPrefix)) { + return; + } + WATCHER_LOGV("SendLocalChange name '%s' prefix '%s'", context->buffer, context->keyPrefix.c_str()); + uint32_t size = PARAM_CONST_VALUE_LEN_MAX; + SystemGetParameterValue(handle, context->buffer + PARAM_NAME_LEN_MAX, &size); + auto remoteWatcher = context->watcherManagerPtr->GetRemoteWatcher(context->remoteWatcherId); + if (remoteWatcher == nullptr) { + return; + } + remoteWatcher->ProcessParameterChange( + context->keyPrefix, context->buffer, context->buffer + PARAM_NAME_LEN_MAX); + }, reinterpret_cast(&context)); +} + +void WatcherManager::RunLoop() +{ + const int32_t RECV_BUFFER_MAX = 5 * 1024; + std::vector buffer(RECV_BUFFER_MAX, 0); + bool retry = false; + ssize_t recvLen = 0; + while (!stop_) { + int fd = GetServerFd(retry); + if (stop_) { + break; + } + if (fd >= 0) { + recvLen = recv(fd, buffer.data(), RECV_BUFFER_MAX, 0); + } + if (recvLen <= 0) { + if (errno == EAGAIN) { // timeout + continue; + } + PARAM_LOGE("Failed to recv msg from server errno %d", errno); + retry = true; // re connect + continue; + } + uint32_t curr = 0; + uint32_t dataLen = static_cast(recvLen); + while (curr < dataLen) { + if (sizeof(ParamMessage) >= dataLen - curr) { + break; + } + ParamMessage *msg = (ParamMessage *)(buffer.data() + curr); + if (msg->msgSize == 0 || (msg->msgSize > dataLen - curr)) { + break; + } + ProcessWatcherMessage(msg); + curr += msg->msgSize; + } + } + if (serverFd_ >= 0) { + close(serverFd_); + serverFd_ = INVALID_SOCKET; + } + WATCHER_LOGV("Exit runLoop serverFd %d", serverFd_); +} + +void WatcherManager::StartLoop() +{ + if (pRecvThread_ == nullptr) { + pRecvThread_ = new (std::nothrow)std::thread([this] {this->RunLoop();}); + WATCHER_CHECK(pRecvThread_ != nullptr, return, "Failed to create thread"); + } +} + +int WatcherManager::GetServerFd(bool retry) +{ + const int32_t sleepTime = 200; + const int32_t maxRetry = 10; + std::lock_guard lock(mutex_); + if (retry && serverFd_ != INVALID_SOCKET) { + close(serverFd_); + serverFd_ = INVALID_SOCKET; + } + if (serverFd_ != INVALID_SOCKET) { + return serverFd_; + } + int32_t retryCount = 0; + do { + serverFd_ = socket(PF_UNIX, SOCK_STREAM, 0); + int flags = fcntl(serverFd_, F_GETFL, 0); + (void)fcntl(serverFd_, F_SETFL, flags & ~O_NONBLOCK); + int ret = ConnectServer(serverFd_, CLIENT_PIPE_NAME); + if (ret == 0) { + break; + } + close(serverFd_); + serverFd_ = INVALID_SOCKET; + usleep(sleepTime); + retryCount++; + if (stop_) { + break; + } + } while (retryCount < maxRetry); + WATCHER_LOGV("GetServerFd serverFd_ %d retryCount %d ", serverFd_, retryCount); + return serverFd_; +} + +void WatcherManager::OnStart() +{ + int level = GetIntParameter(INIT_DEBUG_LEVEL, (int)INIT_ERROR); + SetInitLogLevel((InitLogLevel)level); + if (deathRecipient_ == nullptr) { + deathRecipient_ = new DeathRecipient(this); + } + WATCHER_LOGI("Watcher manager OnStart"); + bool res = Publish(this); + if (!res) { + WATCHER_LOGE("WatcherManager Publish failed"); + } + SystemSetParameter("bootevent.param_watcher.started", "true"); + return; +} + +void WatcherManager::StopLoop() +{ + WATCHER_LOGI("Watcher manager StopLoop serverFd_ %d", serverFd_); + stop_ = true; + if (serverFd_ >= 0) { + shutdown(serverFd_, SHUT_RDWR); + close(serverFd_); + serverFd_ = INVALID_SOCKET; + } + if (pRecvThread_ != nullptr) { + pRecvThread_->join(); + delete pRecvThread_; + pRecvThread_ = nullptr; + } +} + +void WatcherManager::OnStop() +{ + if (remoteWatchers_ != nullptr) { + std::lock_guard lock(watcherMutex_); + remoteWatchers_->TraversalNodeSafe([this](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + RemoteWatcherPtr remoteWatcher = ConvertTo(node); + OnRemoteDied(remoteWatcher); + }); + } + Clear(); + StopLoop(); +} + +void WatcherManager::OnRemoteDied(const wptr &remote) +{ + std::lock_guard lock(watcherMutex_); + WATCHER_CHECK(remote != nullptr, return, "Invalid remote obj"); + auto remoteWatcher = GetRemoteWatcher(remote); + WATCHER_CHECK(remoteWatcher != nullptr, return, "Failed to get remote watcher info "); + { + OnRemoteDied(remoteWatcher); + } +} + +void WatcherManager::OnRemoteDied(RemoteWatcherPtr remoteWatcher) +{ + WATCHER_CHECK(remoteWatcher != nullptr, return, "Invalid remote obj"); + WATCHER_LOGI("Agent died %u %u", remoteWatcher->GetRemoteWatcherId(), remoteWatcher->GetAgentId()); + remoteWatcher->TraversalNodeSafe( + [this, remoteWatcher](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + auto group = GetWatcherGroup(node->GetNodeId()); + if (group == nullptr) { + return; + } + // delete node from group and remote + DelParamWatcher(group, remoteWatcher); + if (group->Empty()) { // no watcher, so delete it + SendMessage(group, MSG_DEL_WATCHER); + DelWatcherGroup(group); + } + }); + DelRemoteWatcher(remoteWatcher); +} + +RemoteWatcherPtr WatcherManager::GetRemoteWatcher(const wptr &remote) +{ + WatcherNodePtr node = remoteWatchers_->GetNextNode(nullptr); + while (node != nullptr) { + RemoteWatcherPtr remoteWatcher = ConvertTo(node); + if (remoteWatcher == nullptr) { + continue; + } + if (remote == remoteWatcher->GetWatcher()->AsObject()) { + return remoteWatcher; + } + node = remoteWatchers_->GetNextNode(node); + } + return nullptr; +} + +int WatcherManager::GetRemoteWatcherId(uint32_t &remoteWatcherId) +{ + remoteWatcherId_++; + if (remoteWatcherId_ == 0) { + remoteWatcherId_++; + } + remoteWatcherId = remoteWatcherId_; + return 0; +} + +int WatcherManager::GetGroupId(uint32_t &groupId) +{ + groupId = groupId_; + do { + groupId_++; + if (watcherGroups_->GetNode(groupId_) == nullptr) { + break; + } + WATCHER_CHECK(groupId_ == groupId, return -1, "No enough groupId %u", groupId); + } while (1); + groupId = groupId_; + return 0; +} + +void WatcherManager::DumpAllGroup(int fd, ParamWatcherProcessor dumpHandle) +{ + // all output + uint32_t count = 0; + std::lock_guard lock(watcherMutex_); + for (auto it = groupMap_.begin(); it != groupMap_.end(); ++it) { + auto group = it->second; + dprintf(fd, "Watch prefix : %s \n", group->GetKeyPrefix().c_str()); + dprintf(fd, "Watch group id : %u \n", group->GetGroupId()); + dprintf(fd, "Watch count : %u \n", group->GetNodeCount()); + group->TraversalNode(dumpHandle); + count += group->GetNodeCount(); + dprintf(fd, "\n"); + } + + dprintf(fd, "Watch prefix count : %u [%zu %zu %zu]\n", watcherGroups_->GetNodeCount(), + sizeof(RemoteWatcher), sizeof(WatcherGroup), sizeof(WatcherNode)); + dprintf(fd, "Watch agent count : %u \n", remoteWatchers_->GetNodeCount()); + dprintf(fd, "Watch count : %u \n", count); +} + +int WatcherManager::Dump(int fd, const std::vector& args) +{ + WATCHER_CHECK(fd >= 0, return -1, "Invalid fd for dump %d", fd); + WATCHER_CHECK(remoteWatchers_ != 0, return -1, "Invalid remote watcher"); + WATCHER_CHECK(watcherGroups_ != 0, return -1, "Invalid watcher group"); + std::vector params; + for (auto& arg : args) { + params.emplace_back(Str16ToStr8(arg)); + } + if (params.size() >= 1 && params[0] == "-h") { + std::string dumpInfo = {}; + dumpInfo.append("Usage:\n") + .append(" -h ") + .append("|help text for the tool\n") + .append(" -k ") + .append("|dump watcher infomation for key prefix\n"); + dprintf(fd, "%s\n", dumpInfo.c_str()); + return 0; + } + auto dumpParamWatcher = [this, fd](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + auto remoteWatcher = GetRemoteWatcher(node->GetNodeId()); + if (remoteWatcher != nullptr) { + dprintf(fd, "%s%u(%u)", (index == 0) ? "Watch id list : " : ", ", + node->GetNodeId(), remoteWatcher->GetAgentId()); + } else { + dprintf(fd, "%s%u", (index == 0) ? "Watch id list : " : ", ", node->GetNodeId()); + } + }; + + if (params.size() > 1 && params[0] == "-k") { + std::lock_guard lock(watcherMutex_); + auto group = GetWatcherGroup(params[1]); + if (group == NULL) { + dprintf(fd, "Prefix %s not found in watcher list\n", params[1].c_str()); + return 0; + } + { + group->TraversalNode(dumpParamWatcher); + } + return 0; + } + DumpAllGroup(fd, dumpParamWatcher); + return 0; +} + +void WatcherManager::Clear(void) +{ + WATCHER_LOGV("Clear"); + std::lock_guard lock(watcherMutex_); + remoteWatchers_->TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + auto group = ConvertTo(node); + WATCHER_LOGV("Delete watcher group %u", group->GetGroupId()); + delete group; + }); + watcherGroups_->TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + auto remoteWatcher = ConvertTo(node); + WATCHER_LOGV("Delete remote watcher %u", remoteWatcher->GetRemoteWatcherId()); + delete remoteWatcher; + }); + delete remoteWatchers_; + remoteWatchers_ = nullptr; + delete watcherGroups_; + watcherGroups_ = nullptr; +} + +int WatcherManager::AddRemoteWatcher(RemoteWatcherPtr remoteWatcher) +{ + if (remoteWatchers_ == nullptr) { + remoteWatchers_ = new ParamWatcherList(); + WATCHER_CHECK(remoteWatchers_ != nullptr, return -1, "Failed to create watcher"); + } + return remoteWatchers_->AddNode(ConvertTo(remoteWatcher)); +} + +RemoteWatcherPtr WatcherManager::GetRemoteWatcher(uint32_t remoteWatcherId) +{ + WATCHER_CHECK(remoteWatchers_ != nullptr, return nullptr, "Invalid remote watcher"); + WatcherNodePtr node = remoteWatchers_->GetNode(remoteWatcherId); + if (node == nullptr) { + return nullptr; + } + return ConvertTo(node); +} + +void WatcherManager::DelRemoteWatcher(RemoteWatcherPtr remoteWatcher) +{ + WATCHER_CHECK(remoteWatchers_ != nullptr, return, "Invalid remote watcher"); + remoteWatchers_->RemoveNode(ConvertTo(remoteWatcher)); + delete remoteWatcher; +} + +int WatcherManager::AddParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher) +{ + WatcherNodePtr nodeGroup = new ParamWatcher(group->GetGroupId()); + WATCHER_CHECK(nodeGroup != nullptr, return -1, "Failed to create watcher node for group"); + WatcherNodePtr nodeRemote = new ParamWatcher(remoteWatcher->GetRemoteWatcherId()); + WATCHER_CHECK(nodeRemote != nullptr, delete nodeGroup; + return -1, "Failed to create watcher node for remote watcher"); + group->AddNode(nodeRemote); + remoteWatcher->AddNode(nodeGroup); + return 0; +} + +int WatcherManager::DelParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher) +{ + WATCHER_LOGI("Delete param watcher remoteWatcherId %u group %u", + remoteWatcher->GetRemoteWatcherId(), group->GetGroupId()); + WatcherNodePtr node = group->GetNode(remoteWatcher->GetRemoteWatcherId()); + if (node != nullptr) { + group->RemoveNode(node); + delete node; + } + node = remoteWatcher->GetNode(group->GetGroupId()); + if (node != nullptr) { + remoteWatcher->RemoveNode(node); + delete node; + } + return 0; +} + +WatcherGroupPtr WatcherManager::AddWatcherGroup(const std::string &keyPrefix) +{ + if (watcherGroups_ == nullptr) { + watcherGroups_ = new ParamWatcherList(); + WATCHER_CHECK(watcherGroups_ != nullptr, return nullptr, "Failed to create watcher"); + } + // get group + auto it = groupMap_.find(keyPrefix); + if (it != groupMap_.end()) { + return it->second; + } + // create group + uint32_t groupId = 0; + int ret = GetGroupId(groupId); + WATCHER_CHECK(ret == 0, return nullptr, "Failed to get group id for %s", keyPrefix.c_str()); + WatcherGroupPtr group = new WatcherGroup(groupId, keyPrefix); + WATCHER_CHECK(group != nullptr, return nullptr, "Failed to create group for %s", keyPrefix.c_str()); + watcherGroups_->AddNode(ConvertTo(group)); + groupMap_[keyPrefix] = group; + return group; +} + +WatcherGroupPtr WatcherManager::GetWatcherGroup(uint32_t groupId) +{ + WATCHER_CHECK(watcherGroups_ != nullptr, return nullptr, "Invalid watcher groups"); + WatcherNodePtr node = watcherGroups_->GetNode(groupId); + if (node == nullptr) { + return nullptr; + } + return ConvertTo(node); +} + +WatcherGroupPtr WatcherManager::GetWatcherGroup(const std::string &keyPrefix) +{ + // get group + auto it = groupMap_.find(keyPrefix); + if (it != groupMap_.end()) { + return it->second; + } + return nullptr; +} + +void WatcherManager::DelWatcherGroup(WatcherGroupPtr group) +{ + WATCHER_CHECK(watcherGroups_ != nullptr, return, "Invalid watcher groups"); + WATCHER_LOGI("Delete watcher group %s %u", group->GetKeyPrefix().c_str(), group->GetGroupId()); + watcherGroups_->RemoveNode(ConvertTo(group)); + auto it = groupMap_.find(group->GetKeyPrefix()); + if (it != groupMap_.end()) { + groupMap_.erase(it); + } + delete group; +} + +int ParamWatcherList::AddNode(WatcherNodePtr node) +{ + WATCHER_CHECK(node, return -1, "Invalid input node"); + node->AddToList(&nodeList_); + nodeCount_++; + return 0; +} + +int ParamWatcherList::RemoveNode(WatcherNodePtr node) +{ + WATCHER_CHECK(node, return -1, "Invalid input node"); + node->RemoveFromList(&nodeList_); + nodeCount_--; + return 0; +} + +WatcherNodePtr ParamWatcherList::GetNode(uint32_t nodeId) +{ + return WatcherNode::GetFromList(&nodeList_, nodeId); +} + +WatcherNodePtr ParamWatcherList::GetNextNodeSafe(WatcherNodePtr node) +{ + if (node == nullptr) { // get first + return WatcherNode::GetNextFromList(&nodeList_, 0); + } + return WatcherNode::GetNextFromList(&nodeList_, node->GetNodeId()); +} + +WatcherNodePtr ParamWatcherList::GetNextNode(WatcherNodePtr node) +{ + if (node == nullptr) { // get first + return WatcherNode::GetNextFromList(&nodeList_, 0); + } + return node->GetNext(&nodeList_); +} + +void ParamWatcherList::TraversalNode(ParamWatcherProcessor handle) +{ + uint32_t index = 0; + // get first + WatcherNodePtr node = WatcherNode::GetNextFromList(&nodeList_, 0); + while (node != nullptr) { + WatcherNodePtr next = node->GetNext(&nodeList_); + handle(this, node, index); + node = next; + index++; + } +} + +void ParamWatcherList::TraversalNodeSafe(ParamWatcherProcessor processor) +{ + uint32_t index = 0; + // get first + WatcherNodePtr node = WatcherNode::GetNextFromList(&nodeList_, 0); + while (node != nullptr) { + uint32_t nodeId = node->GetNodeId(); + // notify free, must be free + processor(this, node, index); + node = WatcherNode::GetNextFromList(&nodeList_, nodeId); + index++; + } +} + +void WatcherNode::AddToList(ListHead *list) +{ + OH_ListAddWithOrder(list, &node_, CompareNode); +} + +void WatcherNode::RemoveFromList(ListHead *list) +{ + OH_ListRemove(&node_); +} + +WatcherNodePtr WatcherNode::GetFromList(ListHead *list, uint32_t nodeId) +{ + ListNodePtr node = OH_ListFind(list, &nodeId, CompareData); + if (node == nullptr) { + return nullptr; + } + return WatcherNode::ConvertNodeToBase(node); +} + +WatcherNodePtr WatcherNode::GetNextFromList(ListHead *list, uint32_t nodeId) +{ + ListNodePtr node = OH_ListFind(list, &nodeId, Greater); + if (node == nullptr) { + return nullptr; + } + return WatcherNode::ConvertNodeToBase(node); +} + +WatcherNodePtr WatcherNode::GetNext(ListHead *list) +{ + if (node_.next == list) { + return nullptr; + } + return WatcherNode::ConvertNodeToBase(node_.next); +} + +int WatcherNode::CompareNode(ListNodePtr node, ListNodePtr newNode) +{ + WatcherNodePtr watcher = WatcherNode::ConvertNodeToBase(node); + WatcherNodePtr newWatcher = WatcherNode::ConvertNodeToBase(node); + return watcher->nodeId_ - newWatcher->nodeId_; +} + +int WatcherNode::CompareData(ListNodePtr node, void *data) +{ + WatcherNodePtr watcher = WatcherNode::ConvertNodeToBase(node); + uint32_t id = *(uint32_t *)data; + return watcher->nodeId_ - id; +} + +int WatcherNode::Greater(ListNodePtr node, void *data) +{ + WatcherNodePtr watcher = WatcherNode::ConvertNodeToBase(node); + uint32_t id = *(uint32_t *)data; + return (watcher->nodeId_ > id) ? 0 : 1; +} + +WatcherGroup::~WatcherGroup(void) +{ + TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + ParamWatcher *watcher = ConvertTo(node); + WATCHER_LOGV("delete watcher group %u", watcher->GetNodeId()); + delete watcher; + }); +} + +RemoteWatcher::~RemoteWatcher(void) +{ + watcher_ = nullptr; + TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + ParamWatcher *watcher = ConvertTo(node); + WATCHER_LOGV("delete remote watcher %u", watcher->GetNodeId()); + delete watcher; + }); +} +} // namespace init_param +} // namespace OHOS diff --git a/services/param/watcher/proxy/watcher_manager.h b/services/param/watcher/proxy/watcher_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..f7bd0a9614b9a478eb0c3651dc5daadf03ec8054 --- /dev/null +++ b/services/param/watcher/proxy/watcher_manager.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021 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 WATCHER_MANAGER_H_ +#define WATCHER_MANAGER_H_ +#include +#include +#include +#include +#include +#include + +#include "iremote_stub.h" +#include "iwatcher.h" +#include "list.h" +#include "message_parcel.h" +#include "param_utils.h" +#include "parcel.h" +#include "param_message.h" +#include "system_ability.h" +#include "watcher_manager_stub.h" + +namespace OHOS { +namespace init_param { +class WatcherNode; +class ParamWatcherList; +class WatcherGroup; +class RemoteWatcher; +using WatcherGroupPtr = WatcherGroup *; +using RemoteWatcherPtr = RemoteWatcher *; +using WatcherNodePtr = WatcherNode *; +using ListNodePtr = ListNode *; +using ListHeadPtr = ListHead *; +using ParamWatcherListPtr = ParamWatcherList *; +using ParamWatcherProcessor = std::function; + +class WatcherManager : public SystemAbility, public WatcherManagerStub { +public: + friend class WatcherGroup; + DECLARE_SYSTEM_ABILITY(WatcherManager); + DISALLOW_COPY_AND_MOVE(WatcherManager); + explicit WatcherManager(int32_t systemAbilityId, bool runOnCreate = true) + : SystemAbility(systemAbilityId, runOnCreate) + { + } + ~WatcherManager() override; + + // For death event procession + class DeathRecipient final : public IRemoteObject::DeathRecipient { + public: + explicit DeathRecipient(WatcherManager *manager) : manager_(manager) {} + ~DeathRecipient() final = default; + DISALLOW_COPY_AND_MOVE(DeathRecipient); + void OnRemoteDied(const wptr &remote) final + { + manager_->OnRemoteDied(remote); + } + private: + WatcherManager *manager_; + }; + sptr GetDeathRecipient(void) + { + return deathRecipient_; + } + uint32_t AddRemoteWatcher(uint32_t id, const sptr &watcher) override; + int32_t DelRemoteWatcher(uint32_t remoteWatcherId) override; + int32_t AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; +protected: + void OnStart() override; + void OnStop() override; + int Dump(int fd, const std::vector& args) override; +private: + void RunLoop(); + void StartLoop(); + void StopLoop(); + void SendLocalChange(const std::string &keyPrefix, uint32_t remoteWatcherId); + int SendMessage(WatcherGroupPtr group, int type); + int GetServerFd(bool retry); + int GetRemoteWatcherId(uint32_t &remoteWatcherId); + int GetGroupId(uint32_t &groupId); + // for remote watcher + int AddRemoteWatcher(RemoteWatcherPtr remoteWatcher); + RemoteWatcherPtr GetRemoteWatcher(uint32_t remoteWatcherId); + RemoteWatcherPtr GetRemoteWatcher(const wptr &remote); + void DelRemoteWatcher(RemoteWatcherPtr remoteWatcher); + // for group + WatcherGroupPtr AddWatcherGroup(const std::string &keyPrefix); + WatcherGroupPtr GetWatcherGroup(const std::string &keyPrefix); + WatcherGroupPtr GetWatcherGroup(uint32_t groupId); + void DelWatcherGroup(WatcherGroupPtr group); + // for param watcher + int AddParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher); + int DelParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher); + // for app param watcher permission + int32_t CheckAppWatchPermission(const std::string &keyPrefix); + // for process message form init + void ProcessWatcherMessage(const ParamMessage *msg); + // for client died + void OnRemoteDied(const wptr &remote); + void OnRemoteDied(RemoteWatcherPtr remoteWatcher); + // clear + void Clear(void); + // dump + void DumpAllGroup(int fd, ParamWatcherProcessor dumpHandle); +private: + std::atomic remoteWatcherId_ { 0 }; + std::atomic groupId_ { 0 }; + std::mutex mutex_; + std::mutex watcherMutex_; + int serverFd_ { -1 }; + std::thread *pRecvThread_ { nullptr }; + std::atomic stop_ { false }; + std::map groupMap_ {}; + sptr deathRecipient_ {}; + ParamWatcherListPtr watcherGroups_ {}; + ParamWatcherListPtr remoteWatchers_ {}; +}; + +class WatcherNode { +public: + explicit WatcherNode(uint32_t nodeId) : nodeId_(nodeId) + { + OH_ListInit(&node_); + } + virtual ~WatcherNode(void) = default; + uint32_t GetNodeId(void) const + { + return nodeId_; + } + + void AddToList(ListHeadPtr list); + void RemoveFromList(ListHeadPtr list); + WatcherNodePtr GetNext(ListHeadPtr list); + static WatcherNodePtr GetFromList(ListHeadPtr list, uint32_t nodeId); + static WatcherNodePtr GetNextFromList(ListHeadPtr list, uint32_t nodeId); + static WatcherNodePtr ConvertNodeToBase(ListNodePtr node) + { + return reinterpret_cast((char *)node - (char*)(&(((WatcherNodePtr)0)->node_))); + } + ListNodePtr GetListNode() + { + return &node_; + } +private: + static int CompareNode(ListNodePtr node, ListNodePtr newNode); + static int CompareData(ListNodePtr node, void *data); + static int Greater(ListNodePtr node, void *data); + ListNode node_; + uint32_t nodeId_; +}; + +template +inline T *ConvertTo(WatcherNodePtr node) +{ +#ifdef PARAM_WATCHER_RTTI_ENABLE + // when -frtti is enabled, we use dynamic cast directly + // to achieve the correct base class side-to-side conversion. + T *obj = dynamic_cast(node); +#else + // adjust pointer position when multiple inheritance. + void *tmp = reinterpret_cast(node); + // when -frtti is not enable, we use static cast. + // static cast is not safe enough, but we have checked before we get here. + T *obj = static_cast(tmp); +#endif + return obj; +} + +class ParamWatcher : public WatcherNode { +public: + explicit ParamWatcher(uint32_t watcherId) : WatcherNode(watcherId) {} + ~ParamWatcher(void) override {} +}; + +class ParamWatcherList { +public: + ParamWatcherList(void) + { + OH_ListInit(&nodeList_); + } + ~ParamWatcherList(void) = default; + + bool Empty(void) const + { + return nodeList_.next == &nodeList_; + } + uint32_t GetNodeCount(void) const + { + return nodeCount_; + } + int AddNode(WatcherNodePtr node); + int RemoveNode(WatcherNodePtr node); + WatcherNodePtr GetNode(uint32_t nodeId); + WatcherNodePtr GetNextNodeSafe(WatcherNodePtr node); + WatcherNodePtr GetNextNode(WatcherNodePtr node); + void TraversalNode(ParamWatcherProcessor handle); + void TraversalNodeSafe(ParamWatcherProcessor processor); +public: + ListHead nodeList_ {}; + uint32_t nodeCount_ = 0; +}; + +class RemoteWatcher : public WatcherNode, public ParamWatcherList { +public: + RemoteWatcher(uint32_t watcherId, const sptr &watcher) + : WatcherNode(watcherId), ParamWatcherList(), watcher_(watcher) {} + ~RemoteWatcher(void) override; + + uint32_t GetRemoteWatcherId(void) const + { + return GetNodeId(); + } + uint32_t GetAgentId(void) const + { + return id_; + } + bool CheckAgent(pid_t calling) const + { + return id_ == static_cast(calling); + } + void SetAgentId(uint32_t id) + { + id_ = id; + } + void ProcessParameterChange(const std::string &prefix, const std::string &name, const std::string &value) + { + watcher_->OnParameterChange(prefix, name, value); + } + sptr GetWatcher(void) + { + return watcher_; + } +private: + uint32_t id_ = { 0 }; + sptr watcher_ {}; +}; + +class WatcherGroup : public WatcherNode, public ParamWatcherList { +public: + WatcherGroup(uint32_t groupId, const std::string &key) + : WatcherNode(groupId), ParamWatcherList(), keyPrefix_(key) {} + ~WatcherGroup(void) override; + + void ProcessParameterChange(WatcherManager *manager, const std::string &name, const std::string &value); + const std::string GetKeyPrefix() const + { + return keyPrefix_; + } + uint32_t GetGroupId() const + { + return GetNodeId(); + } +private: + std::string keyPrefix_ { }; +}; +} // namespace init_param +} // namespace OHOS +#endif // WATCHER_MANAGER_H_ \ No newline at end of file diff --git a/services/param/watcher/proxy/watcher_manager_stub.cpp b/services/param/watcher/proxy/watcher_manager_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3af047fbe1e5e1121cc2f62b585455a512ab6f7 --- /dev/null +++ b/services/param/watcher/proxy/watcher_manager_stub.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 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 "watcher_manager_stub.h" +#include "watcher_proxy.h" +#include "watcher_utils.h" +#ifdef HICOLLIE_ENABLE +#include "xcollie/xcollie.h" +#include "xcollie/xcollie_define.h" +#endif + +namespace OHOS { +namespace init_param { +int32_t WatcherManagerStub::OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + std::u16string myDescriptor = IWatcherManager::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + WATCHER_CHECK(myDescriptor == remoteDescriptor, return -1, "Invalid remoteDescriptor %u", code); + + WATCHER_LOGV("OnRemoteRequest code %u", code); + switch (code) { + case static_cast(ParamWatcherInterfaceCode::ADD_WATCHER): { + std::string key = data.ReadString(); +#ifdef HICOLLIE_ENABLE + const int dfxDelayS = 10; + int id = HiviewDFX::XCollie::GetInstance().SetTimer("ParamWatcher_AddWatcher", + dfxDelayS, nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG); +#endif + int ret = AddWatcher(key, data.ReadUint32()); +#ifdef HICOLLIE_ENABLE + HiviewDFX::XCollie::GetInstance().CancelTimer(id); +#endif + reply.WriteInt32(ret); + break; + } + case static_cast(ParamWatcherInterfaceCode::DEL_WATCHER): { + std::string key = data.ReadString(); + int ret = DelWatcher(key, data.ReadUint32()); + reply.WriteInt32(ret); + break; + } + case static_cast(ParamWatcherInterfaceCode::ADD_REMOTE_AGENT): { + auto remote = data.ReadRemoteObject(); + sptr watcher = new WatcherProxy(remote); + uint32_t remoteWatcherId = AddRemoteWatcher(data.ReadUint32(), watcher); + reply.WriteUint32(remoteWatcherId); + break; + } + case static_cast(ParamWatcherInterfaceCode::DEL_REMOTE_AGENT): { + int ret = DelRemoteWatcher(data.ReadUint32()); + reply.WriteInt32(ret); + break; + } + case static_cast(ParamWatcherInterfaceCode::REFRESH_WATCHER): { + std::string key = data.ReadString(); + int ret = RefreshWatcher(key, data.ReadUint32()); + reply.WriteInt32(ret); + break; + } + default: { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + } + return 0; +} +} +} diff --git a/services/param/watcher/proxy/watcher_manager_stub.h b/services/param/watcher/proxy/watcher_manager_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..62fdb8bfb8e1fd815ac8a505fce65525e2aaee8a --- /dev/null +++ b/services/param/watcher/proxy/watcher_manager_stub.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 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 WATCHER_MANAGER_STUB_H_ +#define WATCHER_MANAGER_STUB_H_ + +#include "iremote_stub.h" +#include "iwatcher_manager.h" +#include "message_parcel.h" +#include "parcel.h" + +namespace OHOS { +namespace init_param { +class WatcherManagerStub : public IRemoteStub { +public: + explicit WatcherManagerStub(bool serialInvokeFlag = true) + : IRemoteStub(serialInvokeFlag), serialInvokeFlag_(serialInvokeFlag) {} + int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, + MessageOption &option) override; + bool serialInvokeFlag_ = { true }; +}; +} +} +#endif // WATCHER_MANAGER_STUB_H_ \ No newline at end of file diff --git a/services/param/watcher/proxy/watcher_proxy.cpp b/services/param/watcher/proxy/watcher_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10d02efbc3afdcbfcebf7846f9f6b269cb9ec174 --- /dev/null +++ b/services/param/watcher/proxy/watcher_proxy.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 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 "watcher_proxy.h" + +#include +#include "parcel.h" +#include "message_parcel.h" +#include "watcher_utils.h" +#include "securec.h" +#include "sysparam_errno.h" + +namespace OHOS { +namespace init_param { +void WatcherProxy::OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option { MessageOption::TF_ASYNC }; + + data.WriteInterfaceToken(WatcherProxy::GetDescriptor()); + data.WriteString(prefix); + data.WriteString(name); + data.WriteString(value); + auto remote = Remote(); +#ifdef STARTUP_INIT_TEST + int ret = 0; +#else + int ret = SYSPARAM_SYSTEM_ERROR; +#endif + if (remote != nullptr) { + ret = remote->SendRequest(PARAM_CHANGE, data, reply, option); + } + WATCHER_CHECK(ret == ERR_OK, return, "Can not SendRequest for name %s err:%d", name.c_str(), ret); + return; +} +} +} // namespace OHOS diff --git a/services/param/watcher/proxy/watcher_proxy.h b/services/param/watcher/proxy/watcher_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..6daf428ae5aa469f0acb6ae5ea09573ca1a56812 --- /dev/null +++ b/services/param/watcher/proxy/watcher_proxy.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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 STARTUP_WATCHER_PROXY_H +#define STARTUP_WATCHER_PROXY_H + +#include "iremote_proxy.h" +#include "iwatcher.h" + +namespace OHOS { +namespace init_param { +class WatcherProxy : public IRemoteProxy { +public: + explicit WatcherProxy(const sptr& impl) : IRemoteProxy(impl) {} + + virtual ~WatcherProxy() = default; + + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) override; + +private: + static inline BrokerDelegator delegator_; +}; +} +} // namespace OHOS +#endif // STARTUP_WATCHER_PROXY_H \ No newline at end of file diff --git a/services/etc/ohos.para b/services/param/watcher/sa_profile/BUILD.gn old mode 100755 new mode 100644 similarity index 50% rename from services/etc/ohos.para rename to services/param/watcher/sa_profile/BUILD.gn index f53e55ad3588c8a2cb9cd2054a60bae68ebb52b6..26d25968701e6bfa897be1ab7fe3ae138fd88378 --- a/services/etc/ohos.para +++ b/services/param/watcher/sa_profile/BUILD.gn @@ -11,29 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -build_version = 2.0 +import("//build/ohos/sa_profile/sa_profile.gni") -# whether ohos is enabled. -hw_sc.build.os.enable=true +ohos_sa_profile("param_watcher_profile") { + sources = [ "param_watcher.json" ] -# ohos API version number. -hw_sc.build.os.apiversion=6 - -# ohos system version. -hw_sc.build.os.version=2.2.0 - -# ohos device type please use hw_sc.build.os.devicetype - -# ohos release type -hw_sc.build.os.releasetype=Canary1 - -ro.actionable_compatible_property.enabled=false -ro.postinstall.fstab.prefix=/system -ro.secure=1 -security.perf_harden=1 -ro.allow.mock.location=0 -ro.debuggable=1 -ro.build.characteristics="default" -ro.product.model="ohos" -ro.product.name="OpenHarmony 2.0 Canary" -persist.sys.usb.config=hdc + part_name = "init" +} diff --git a/services/param/watcher/sa_profile/param_watcher.json b/services/param/watcher/sa_profile/param_watcher.json new file mode 100644 index 0000000000000000000000000000000000000000..f039824790e735e03bdd696c4a544105cc53635c --- /dev/null +++ b/services/param/watcher/sa_profile/param_watcher.json @@ -0,0 +1,12 @@ +{ + "process": "param_watcher", + "systemability": [ + { + "name": 3901, + "libpath": "libparam_watcher.z.so", + "run-on-create": true, + "distributed": false, + "dump_level": 1 + } + ] +} \ No newline at end of file diff --git a/services/sandbox/BUILD.gn b/services/sandbox/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..4d1aba7a22cc4a00c3fa2cde9e130308c149e1f7 --- /dev/null +++ b/services/sandbox/BUILD.gn @@ -0,0 +1,84 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ "./include" ] +} + +ohos_static_library("sandbox") { + sources = [ + "sandbox.c", + "sandbox_namespace.c", + ] + public_configs = [ ":exported_header_files" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include", + ] + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines = [ "SUPPORT_64BIT" ] + } + deps = [ + ":chipset-sandbox.json", + ":system-sandbox.json", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson", + "config_policy:configpolicy_util", + ] + part_name = "init" + subsystem_name = "startup" +} + +ohos_prebuilt_etc("system-sandbox.json") { + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + source = "system-sandbox64.json" + } else { + source = "system-sandbox.json" + } + output = "//base/startup/init/services/sandbox/system-sandbox.json" + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/sandbox" + install_enable = true + install_images = [ + "system", + "updater", + ] +} + +ohos_prebuilt_etc("chipset-sandbox.json") { + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + source = "chipset-sandbox64.json" + } else { + source = "chipset-sandbox.json" + } + output = "//base/startup/init/services/sandbox/chipset-sandbox.json" + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/sandbox" + install_enable = true + install_images = [ + "system", + "updater", + ] +} diff --git a/services/sandbox/chipset-sandbox.json b/services/sandbox/chipset-sandbox.json new file mode 100644 index 0000000000000000000000000000000000000000..6dac4b4931a980a478a6be818254e47769a658d1 --- /dev/null +++ b/services/sandbox/chipset-sandbox.json @@ -0,0 +1,106 @@ +{ + "sandbox-root" : "/mnt/sandbox/chipset", + "mount-bind-paths" : [{ + "src-path" : "/system/bin", + "sandbox-path" : "/system/bin", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/etc/selinux", + "sandbox-path" : "/system/etc/selinux", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/chipset-pub-sdk", + "sandbox-path" : "/system/lib/chipset-pub-sdk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/chipset-sdk", + "sandbox-path" : "/system/lib/chipset-sdk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/ndk", + "sandbox-path" : "/system/lib/ndk", + "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", "private" ] + }, { + "src-path" : "/storage", + "sandbox-path" : "/storage", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/chip_prod", + "sandbox-path" : "/chip_prod", + "sandbox-flags" : [ "bind", "rec", "private" ] + } + ], + "mount-bind-files" : [{ + "src-path" : "/data/service/el1/network/hosts_user/hosts", + "sandbox-path" : "/system/etc/hosts", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/etc/passwd", + "sandbox-path" : "/system/etc/passwd", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/etc/group", + "sandbox-path" : "/system/etc/group", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/etc/ld-musl-arm.path", + "sandbox-path" : "/system/etc/ld-musl-arm.path", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/etc/ld-musl-namespace-arm.ini", + "sandbox-path" : "/system/etc/ld-musl-namespace-arm.ini", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/ld-musl-arm.so.1", + "sandbox-path" : "/system/lib/ld-musl-arm.so.1", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/libc.so", + "sandbox-path" : "/system/lib/libc.so", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/system/lib/libc++.so", + "sandbox-path" : "/system/lib/libc++.so", + "sandbox-flags" : [ "bind", "rec", "private" ] + } + ], + "symbol-links" : [{ + "target-name" : "/system/lib", + "link-name" : "/lib" + }, { + "target-name" : "/system/bin", + "link-name" : "/bin" + }, { + "target-name" : "/system/etc", + "link-name" : "/etc" + } + ] +} diff --git a/services/sandbox/chipset-sandbox64.json b/services/sandbox/chipset-sandbox64.json new file mode 100644 index 0000000000000000000000000000000000000000..c6394c527774f09db1d355c79681a5a4704901cf --- /dev/null +++ b/services/sandbox/chipset-sandbox64.json @@ -0,0 +1,96 @@ +{ + "sandbox-root" : "/mnt/sandbox/chipset", + "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/lib64", + "sandbox-path" : "/system/lib64", + "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" ], + "ignore": 1 + }, { + "src-path" : "/system/fonts", + "sandbox-path" : "/system/fonts", + "sandbox-flags" : [ "bind", "rec", "private" ], + "ignore": 1 + }, { + "src-path" : "/system/usr", + "sandbox-path" : "/system/usr", + "sandbox-flags" : [ "bind", "rec", "private" ], + "ignore": 1 + }, { + "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", "private" ] + }, { + "src-path" : "/storage", + "sandbox-path" : "/storage", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/sys_prod", + "sandbox-path" : "/sys_prod", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/chip_prod", + "sandbox-path" : "/chip_prod", + "sandbox-flags" : [ "bind", "rec", "private" ] + } + ], + "mount-bind-files" : [{ + }], + "symbol-links" : [{ + "target-name" : "/system/lib64", + "link-name" : "/lib64" + }, { + "target-name" : "/system/lib", + "link-name" : "/lib" + }, { + "target-name" : "/system/bin", + "link-name" : "/bin" + }, { + "target-name" : "/system/etc", + "link-name" : "/etc" + } + ] +} diff --git a/services/sandbox/include/sandbox.h b/services/sandbox/include/sandbox.h new file mode 100644 index 0000000000000000000000000000000000000000..e7490ea1d84419913f8c8f551b5d3a1a2dbf47aa --- /dev/null +++ b/services/sandbox/include/sandbox.h @@ -0,0 +1,65 @@ +/* +* 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 + +#include +#include "init_utils.h" +#include "list.h" +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum SandboxTag { + SANDBOX_TAG_MOUNT_PATH = 0, + SANDBOX_TAG_MOUNT_FILE, + SANDBOX_TAG_SYMLINK +} SandboxTag; + +typedef struct MountList { + char *source; // source 目录,一般是全局的fs 目录 + char *target; // 沙盒化后的目录 + unsigned long flags; + bool ignoreErrors; + SandboxTag tag; + struct ListNode node; +} mountlist_t; + +typedef struct LinkList { + char *target; + char *linkName; + struct ListNode node; +} linklist_t; + +typedef struct { + ListNode pathMountsHead; + ListNode fileMountsHead; + ListNode linksHead; + 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); +void DumpSandboxByName(const char *name); +#ifdef __cplusplus +} +#endif +#endif diff --git a/services/sandbox/include/sandbox_namespace.h b/services/sandbox/include/sandbox_namespace.h new file mode 100644 index 0000000000000000000000000000000000000000..8137d73e691fe124434efca6f37e215050a356a3 --- /dev/null +++ b/services/sandbox/include/sandbox_namespace.h @@ -0,0 +1,37 @@ +/* +* 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 SetNamespace(int nsFd, int nsType); +void InitDefaultNamespace(void); +int EnterDefaultNamespace(void); +void CloseDefaultNamespace(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif + diff --git a/services/sandbox/sandbox.c b/services/sandbox/sandbox.c new file mode 100755 index 0000000000000000000000000000000000000000..e54fe994178a96e768780d274ef425654d9b81bb --- /dev/null +++ b/services/sandbox/sandbox.c @@ -0,0 +1,701 @@ +/* +* 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 +#include "beget_ext.h" +#include "config_policy_utils.h" +#include "init_utils.h" +#include "cJSON.h" +#include "list.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_IGNORE_ERRORS "ignore" +#define SANDBOX_SYMLINK_TAG "symbol-links" +#define SANDBOX_SYMLINK_TARGET "target-name" +#define SANDBOX_SYMLINK_NAME "link-name" + +#define SANDBOX_SYSTEM_CONFIG_FILE "etc/sandbox/system-sandbox.json" +#define SANDBOX_CHIPSET_CONFIG_FILE "etc/sandbox/chipset-sandbox.json" + +#ifdef STARTUP_INIT_TEST +#define SANDBOX_TEST_CONFIG_FILE "/data/init_ut/test-sandbox.json" +#endif + +#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; +}; + +static const struct SandboxMountFlags 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 = {}; +#ifdef STARTUP_INIT_TEST +static sandbox_t g_testSandbox = {}; +#endif + +struct SandboxMap { + const char *name; + sandbox_t *sandbox; + const char *configfile; +}; + +static const struct SandboxMap MAP[] = { + { + .name = "system", + .sandbox = &g_systemSandbox, + .configfile = SANDBOX_SYSTEM_CONFIG_FILE, + }, + { + .name = "chipset", + .sandbox = &g_chipsetSandbox, + .configfile = SANDBOX_CHIPSET_CONFIG_FILE, + }, +#ifdef STARTUP_INIT_TEST + { + .name = "test", + .sandbox = &g_testSandbox, + .configfile = SANDBOX_TEST_CONFIG_FILE, + } +#endif +}; + +static unsigned long GetSandboxMountFlags(cJSON *item) +{ + BEGET_ERROR_CHECK(item != NULL, return 0, "Invalid parameter."); + char *str = cJSON_GetStringValue(item); + BEGET_CHECK(str != NULL, return 0); + for (size_t i = 0; i < ARRAY_LENGTH(FLAGS); i++) { + if (strcmp(str, FLAGS[i].flag) == 0) { + return FLAGS[i].value; + } + } + return 0; +} + +static void FreeSandboxMountInfo(ListNode *list) +{ + if (list == NULL) { + return; + } + mountlist_t *info = ListEntry(list, mountlist_t, node); + if (info == NULL) { + return; + } + if (info->source != NULL) { + free(info->source); + info->source = NULL; + } + if (info->target != NULL) { + free(info->target); + info->target = NULL; + } + free(info); + info = NULL; + return; +} + +static void FreeSandboxLinkInfo(ListNode *list) +{ + if (list == NULL) { + return; + } + linklist_t *info = ListEntry(list, linklist_t, node); + if (info == NULL) { + return; + } + if (info->target != NULL) { + free(info->target); + info->target = NULL; + } + if (info->linkName != NULL) { + free(info->linkName); + info->linkName = NULL; + } + free(info); + info = NULL; + return; +} + +static int CompareSandboxListForMountTarget(ListNode *list, void *data) +{ + if ((list == NULL) || (data == NULL)) { + return -1; + } + mountlist_t *info = ListEntry(list, mountlist_t, node); + if (info == NULL) { + return -1; + } + const char *mountTarget = (const char *)data; + return strcmp(info->target, mountTarget); +} + +static void RemoveOldSandboxMountListNode(ListNode *head, const char *targetMount) +{ + if ((head == NULL) || (targetMount == NULL)) { + return; + } + ListNode *node = OH_ListFind(head, (void *)targetMount, CompareSandboxListForMountTarget); + if (node == NULL) { + return; + } + OH_ListRemove(node); + FreeSandboxMountInfo(node); +} + +static int CompareSandboxListForLinkName(ListNode *list, void *data) +{ + if ((list == NULL) || (data == NULL)) { + return -1; + } + linklist_t *info = ListEntry(list, linklist_t, node); + if (info == NULL) { + return -1; + } + const char *linkName = (const char *)data; + return strcmp(info->linkName, linkName); +} + +static void RemoveOldSandboxLinkListNode(ListNode *head, const char *linkName) +{ + if ((head == NULL) || (linkName == NULL)) { + return; + } + ListNode *node = OH_ListFind(head, (void *)linkName, CompareSandboxListForLinkName); + if (node == NULL) { + return; + } + OH_ListRemove(node); + FreeSandboxLinkInfo(node); +} + +typedef int (*AddInfoToSandboxCallback)(sandbox_t *sandbox, cJSON *item, const char *type); + +static int AddMountInfoToSandbox(sandbox_t *sandbox, cJSON *item, const char *type) +{ + BEGET_CHECK(sandbox != NULL && item != NULL && type != NULL, return -1); + char *srcPath = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SOURCE)); + BEGET_INFO_CHECK(srcPath != NULL, return 0, "Get src-path is null"); + char *dstPath = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_TARGET)); + BEGET_INFO_CHECK(dstPath != NULL, return 0, "Get sandbox-path is null"); + cJSON *obj = cJSON_GetObjectItem(item, SANDBOX_FLAGS); + BEGET_INFO_CHECK(obj != NULL, return 0, "Get sandbox-flags is null"); + int ret = cJSON_IsArray(obj); + BEGET_INFO_CHECK(ret, return 0, "Sandbox-flags is not array"); + int count = cJSON_GetArraySize(obj); + BEGET_INFO_CHECK(count > 0, return 0, "Get sandbox-flags array size is zero"); + mountlist_t *tmpMount = (mountlist_t *)calloc(1, sizeof(mountlist_t)); + BEGET_ERROR_CHECK(tmpMount != NULL, return -1, "Failed calloc err=%d", errno); + tmpMount->source = strdup(srcPath); + BEGET_ERROR_CHECK(tmpMount->source != NULL, free(tmpMount); return -1, "Failed to dup source"); + tmpMount->target = strdup(dstPath); + BEGET_ERROR_CHECK(tmpMount->target != NULL, free(tmpMount); return -1, "Failed to dup target"); + for (int i = 0; i < count; i++) { + cJSON *item = cJSON_GetArrayItem(obj, i); + tmpMount->flags |= GetSandboxMountFlags(item); + } + tmpMount->ignoreErrors = false; + obj = cJSON_GetObjectItem(item, SANDBOX_IGNORE_ERRORS); + if (obj != NULL) { + if (cJSON_GetNumberValue(obj) == 1) { + tmpMount->ignoreErrors = true; + } + } + OH_ListInit(&tmpMount->node); + if (strcmp(type, SANDBOX_MOUNT_PATH_TAG) == 0) { + tmpMount->tag = SANDBOX_TAG_MOUNT_PATH; + RemoveOldSandboxMountListNode(&sandbox->pathMountsHead, dstPath); + OH_ListAddTail(&sandbox->pathMountsHead, &tmpMount->node); + } else if (strcmp(type, SANDBOX_MOUNT_FILE_TAG) == 0) { + tmpMount->tag = SANDBOX_TAG_MOUNT_FILE; + RemoveOldSandboxMountListNode(&sandbox->fileMountsHead, dstPath); + OH_ListAddTail(&sandbox->fileMountsHead, &tmpMount->node); + } + return 0; +} + +static int AddSymbolLinksToSandbox(sandbox_t *sandbox, cJSON *item, const char *type) +{ + BEGET_CHECK(!(sandbox == NULL || item == NULL || type == NULL), return -1); + BEGET_ERROR_CHECK(strcmp(type, SANDBOX_SYMLINK_TAG) == 0, return -1, "Type is not sandbox symbolLink."); + char *target = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_TARGET)); + BEGET_ERROR_CHECK(target != NULL, return 0, "Get target-name is null"); + char *name = cJSON_GetStringValue(cJSON_GetObjectItem(item, SANDBOX_SYMLINK_NAME)); + BEGET_ERROR_CHECK(name != NULL, return 0, "Get link-name is null"); + linklist_t *tmpLink = (linklist_t *)calloc(1, sizeof(linklist_t)); + BEGET_ERROR_CHECK(tmpLink != NULL, return -1, "Failed calloc err=%d", errno); + tmpLink->target = strdup(target); + BEGET_ERROR_CHECK(tmpLink->target != NULL, free(tmpLink); return -1, "Failed to dup target"); + tmpLink->linkName = strdup(name); + BEGET_ERROR_CHECK(tmpLink->linkName != NULL, free(tmpLink); return -1, "Failed to dup linkName"); + OH_ListInit(&tmpLink->node); + RemoveOldSandboxLinkListNode(&sandbox->linksHead, tmpLink->linkName); + OH_ListAddTail(&sandbox->linksHead, &tmpLink->node); + return 0; +} + +static int GetSandboxInfo(sandbox_t *sandbox, cJSON *root, const char *itemName) +{ + BEGET_ERROR_CHECK(!(sandbox == NULL || root == NULL || itemName == NULL), return -1, + "Get sandbox mount info with invalid argument"); + cJSON *obj = cJSON_GetObjectItem(root, itemName); + BEGET_WARNING_CHECK(obj != NULL, return 0, "Cannot find item \' %s \' in sandbox config", itemName); + BEGET_WARNING_CHECK(cJSON_IsArray(obj), return 0, "ItemName %s with invalid type, should be array", itemName); + + int counts = cJSON_GetArraySize(obj); + BEGET_WARNING_CHECK(counts > 0, return 0, "Item %s array size is zero.", itemName); + AddInfoToSandboxCallback func = NULL; + if (strcmp(itemName, SANDBOX_MOUNT_PATH_TAG) == 0) { + func = AddMountInfoToSandbox; + } else if (strcmp(itemName, SANDBOX_MOUNT_FILE_TAG) == 0) { + func = AddMountInfoToSandbox; + } else if (strcmp(itemName, SANDBOX_SYMLINK_TAG) == 0) { + func = AddSymbolLinksToSandbox; + } else { + BEGET_LOGE("Item %s 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); + BEGET_ERROR_CHECK(func(sandbox, item, itemName) == 0, return -1, "Failed add info to sandbox."); + } + return 0; +} + +static int ParseSandboxConfig(cJSON *root, sandbox_t *sandbox) +{ + BEGET_ERROR_CHECK(!(root == NULL || sandbox == NULL), return -1, "Invalid parameter."); + // sandbox rootpath must initialize according to the system configuration, and it can only be initialized once. + if (sandbox->rootPath == NULL) { + cJSON *sandboxRoot = cJSON_GetObjectItem(root, SANDBOX_ROOT_TAG); + BEGET_ERROR_CHECK(sandboxRoot != NULL, return -1, + "Cannot find item \' %s \' in sandbox config", SANDBOX_ROOT_TAG); + + char *rootdir = cJSON_GetStringValue(sandboxRoot); + if (rootdir != NULL) { + sandbox->rootPath = strdup(rootdir); + BEGET_ERROR_CHECK(sandbox->rootPath != NULL, return -1, + "Get sandbox root path out of memory"); + } + } + BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_PATH_TAG) == 0, return -1, + "config info %s error", SANDBOX_MOUNT_PATH_TAG); + BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_MOUNT_FILE_TAG) == 0, return -1, + "config info %s error", SANDBOX_MOUNT_FILE_TAG); + BEGET_ERROR_CHECK(GetSandboxInfo(sandbox, root, SANDBOX_SYMLINK_TAG) == 0, return -1, + "config info %s error", SANDBOX_SYMLINK_TAG); + return 0; +} + +static const struct SandboxMap *GetSandboxMapByName(const char *name) +{ + BEGET_ERROR_CHECK(name != NULL, return NULL, "Sandbox map name is NULL."); + int len = ARRAY_LENGTH(MAP); + for (int i = 0; i < len; i++) { + if (strcmp(MAP[i].name, name) == 0) { + return &MAP[i]; + } + } + return NULL; +} + +static int ParseInitSandboxConfigFile(sandbox_t *sandbox, const char *sandboxConfigFile, const char *name) +{ + char *contents = ReadFileToBuf(sandboxConfigFile); + if (contents == NULL) { + return 0; + } + cJSON *root = cJSON_Parse(contents); + free(contents); + BEGET_ERROR_CHECK(root != NULL, return -1, "Parse sandbox config \' %s \' failed", sandboxConfigFile); + int ret = ParseSandboxConfig(root, sandbox); + cJSON_Delete(root); + if (ret < 0) { + DestroySandbox(name); + return -1; + } + return 0; +} + +static void ParseInitSandboxConfigPath(sandbox_t *sandbox, const char *sandboxConfig, const char *name) +{ + CfgFiles *files = GetCfgFiles(sandboxConfig); + for (int i = 0; files && i < MAX_CFG_POLICY_DIRS_CNT; i++) { + if (files->paths[i]) { + BEGET_LOGI("Parse sandbox cfg file is %s", files->paths[i]); + if (ParseInitSandboxConfigFile(sandbox, files->paths[i], name) < 0) { + break; + } + } + } + FreeCfgFiles(files); +} + +static void InitSandbox(sandbox_t *sandbox, const char *sandboxConfig, const char *name) +{ + BEGET_ERROR_CHECK(!(sandbox == NULL || sandboxConfig == NULL || name == NULL), return, + "Init sandbox with invalid arguments"); + if (sandbox->isCreated) { + BEGET_LOGE("Sandbox %s has created.", name); + return; + } + if (UnshareNamespace(CLONE_NEWNS) < 0) { + return; + } + sandbox->ns = GetNamespaceFd("/proc/self/ns/mnt"); + BEGET_ERROR_CHECK(!(sandbox->ns < 0), return, "Get sandbox namespace fd is failed"); + + BEGET_ERROR_CHECK(strcpy_s(sandbox->name, MAX_BUFFER_LEN - 1, name) == 0, return, "Failed to copy sandbox name"); + OH_ListInit(&sandbox->pathMountsHead); + OH_ListInit(&sandbox->fileMountsHead); + OH_ListInit(&sandbox->linksHead); + // parse json config +#ifdef STARTUP_INIT_TEST + (void)ParseInitSandboxConfigFile(sandbox, sandboxConfig, name); +#else + ParseInitSandboxConfigPath(sandbox, sandboxConfig, name); +#endif + return; +} + +static int CheckAndMakeDir(const char *dir, mode_t mode) +{ + struct stat sb; + + if ((stat(dir, &sb) == 0) && S_ISDIR(sb.st_mode)) { + BEGET_LOGI("Mount point \' %s \' already exist, no need to mkdir", dir); + return 0; + } else { + if (errno == ENOENT) { + BEGET_ERROR_CHECK(MakeDirRecursive(dir, mode) == 0, return -1, + "Failed MakeDirRecursive %s, err=%d", dir, errno); + } 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, SandboxTag tag) +{ + if (source == NULL || target == NULL) { + BEGET_LOGE("Mount with invalid arguments"); + errno = EINVAL; + return -1; + } + unsigned long tmpflags = flags; + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + if (tag == SANDBOX_TAG_MOUNT_PATH) { + BEGET_ERROR_CHECK(CheckAndMakeDir(target, mode) == 0, return -1, "Failed make %s dir.", target); + } else if (tag == SANDBOX_TAG_MOUNT_FILE) { + BEGET_ERROR_CHECK(CheckAndCreatFile(target, mode) == 0, return -1, "Failed make %s file.", target); + } else { + BEGET_LOGE("Tag is error."); + return -1; + } + + BEGET_WARNING_CHECK((tmpflags & MS_BIND) != 0, tmpflags |= MS_BIND, + "Not configure mount bind, must configure mount bind flag."); + + // do mount + if (mount(source, target, NULL, tmpflags, NULL) != 0) { + BEGET_LOGE("Failed to bind mount \' %s \' to \' %s \', err = %d", source, target, errno); + if (errno != ENOTDIR) { // mount errno is 'Not a directory' can ignore + return -1; + } + } + + return 0; +} + +static bool IsValidSandbox(sandbox_t *sandbox) +{ + BEGET_ERROR_CHECK(sandbox != NULL, return false, "preparing sandbox with invalid argument"); + + if (sandbox->rootPath == NULL) { + return false; + } + + return true; +} + +static int MountSandboxNode(ListNode *list, void *data) +{ + if ((list == NULL) || (data == NULL)) { + return 0; + } + const char *rootPath = (const char *)data; + mountlist_t *info = ListEntry(list, mountlist_t, node); + char target[PATH_MAX] = {}; + BEGET_ERROR_CHECK(snprintf_s(target, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->target) > 0, + return -1, "Failed snprintf_s err=%d", errno); + int rc = BindMount(info->source, target, info->flags, info->tag); + if (rc != 0) { + BEGET_LOGW("Failed bind mount %s to %s.", info->source, target); + if (info->ignoreErrors == false) { + return -1; + } + } + return 0; +} + +static int MountSandboxInfo(struct ListNode *head, const char *rootPath, SandboxTag tag) +{ + if ((head == NULL) || (rootPath == NULL)) { + return 0; + } + int ret = OH_ListTraversal(head, (void *)rootPath, MountSandboxNode, 1); + return ret; +} + +static int LinkSandboxNode(ListNode *list, void *data) +{ + if ((list == NULL) || (data == NULL)) { + return 0; + } + const char *rootPath = (const char *)data; + linklist_t *info = ListEntry(list, linklist_t, node); + char linkName[PATH_MAX] = {0}; + BEGET_ERROR_CHECK(!(snprintf_s(linkName, PATH_MAX, PATH_MAX - 1, "%s%s", rootPath, info->linkName) < 0), + return -1, "snprintf_s failed, err=%d", errno); + int rc = symlink(info->target, linkName); + if (rc != 0) { + if (errno == EEXIST) { + BEGET_LOGW("symbol link name \' %s \' already exist", linkName); + } else { + BEGET_LOGE("Failed to link \' %s \' to \' %s \', err = %d", info->target, linkName, errno); + return -1; + } + } + return 0; +} + +static int LinkSandboxInfo(struct ListNode *head, const char *rootPath) +{ + if ((head == NULL) || (rootPath == NULL)) { + return 0; + } + int ret = OH_ListTraversal(head, (void *)rootPath, LinkSandboxNode, 1); + return ret; +} + +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."); + const struct SandboxMap *map = GetSandboxMapByName(name); + BEGET_ERROR_CHECK(map != NULL, return -1, "Cannot 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, SANDBOX_TAG_MOUNT_PATH); + 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->pathMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_PATH); + BEGET_CHECK(rc == 0, return -1); + + rc = MountSandboxInfo(&sandbox->fileMountsHead, sandbox->rootPath, SANDBOX_TAG_MOUNT_FILE); + BEGET_CHECK(rc == 0, return -1); + + // 2) walk through all links and do symbol link + rc = LinkSandboxInfo(&sandbox->linksHead, sandbox->rootPath); + BEGET_CHECK(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; +} + +bool InitSandboxWithName(const char *name) +{ + bool isFound = false; + if (name == NULL) { + BEGET_LOGE("Init sandbox name is NULL."); + return isFound; + } + const 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; + } + const struct SandboxMap *map = GetSandboxMapByName(name); + if (map == NULL) { + BEGET_LOGE("Cannot get sandbox map by name %s.", name); + return; + } + sandbox_t *sandbox = map->sandbox; + + BEGET_CHECK(sandbox != NULL, return); + + if (sandbox->rootPath != NULL) { + free(sandbox->rootPath); + sandbox->rootPath = NULL; + } + OH_ListRemoveAll(&sandbox->linksHead, FreeSandboxLinkInfo); + OH_ListRemoveAll(&sandbox->fileMountsHead, FreeSandboxMountInfo); + OH_ListRemoveAll(&sandbox->pathMountsHead, FreeSandboxMountInfo); + + if (sandbox->ns > 0) { + (void)close(sandbox->ns); + } + sandbox->isCreated = false; + return; +} + +int EnterSandbox(const char *name) +{ + if (name == NULL) { + BEGET_LOGE("Sandbox name is NULL."); + return -1; + } + const struct SandboxMap *map = GetSandboxMapByName(name); + if (map == NULL) { + BEGET_LOGE("Cannot get sandbox map by name %s.", name); + return -1; + } + sandbox_t *sandbox = map->sandbox; + + BEGET_CHECK(sandbox != NULL, return -1); + if (sandbox->isCreated == false) { + BEGET_LOGE("Sandbox %s has not been created.", name); + return -1; + } + if (sandbox->ns > 0) { + BEGET_ERROR_CHECK(!(SetNamespace(sandbox->ns, CLONE_NEWNS) < 0), return -1, + "Cannot enter mount namespace for sandbox \' %s \', err=%d.", name, errno); + } else { + BEGET_LOGE("Sandbox \' %s \' namespace fd is invalid.", name); + return -1; + } + return 0; +} + +static int DumpSandboxMountInfo(ListNode *list, void *data) +{ + if (list == NULL) { + return -1; + } + mountlist_t *info = ListEntry(list, mountlist_t, node); + if (info != NULL) { + if (info->source != NULL) { + printf("Sandbox mounts list source: %s \n", info->source); + } + if (info->target != NULL) { + printf("Sandbox mounts list target: %s \n", info->target); + } + } + return 0; +} + +static int DumpSandboxLinkInfo(ListNode *list, void *data) +{ + if (list == NULL) { + return -1; + } + linklist_t *info = ListEntry(list, linklist_t, node); + if (info != NULL) { + if (info->linkName != NULL) { + printf("Sandbox link list name: %s \n", info->linkName); + } + if (info->target != NULL) { + printf("Sandbox link list target: %s \n", info->target); + } + } + return 0; +} + +void DumpSandboxByName(const char *name) +{ + if (name == NULL) { + BEGET_LOGE("Init sandbox name is NULL."); + return; + } + const struct SandboxMap *map = GetSandboxMapByName(name); + if (map == NULL) { + return; + } + printf("Sandbox Map name: %s \n", map->name); + printf("Sandbox Map config file: %s. \n", map->configfile); + printf("Sandbox name: %s. \n", map->sandbox->name); + printf("Sandbox root path is %s. \n", map->sandbox->rootPath); + printf("Sandbox mounts info: \n"); + OH_ListTraversal(&map->sandbox->pathMountsHead, NULL, DumpSandboxMountInfo, 0); + OH_ListTraversal(&map->sandbox->fileMountsHead, NULL, DumpSandboxMountInfo, 0); + printf("Sandbox links info: \n"); + OH_ListTraversal(&map->sandbox->linksHead, NULL, DumpSandboxLinkInfo, 0); + return; +} diff --git a/services/sandbox/sandbox_namespace.c b/services/sandbox/sandbox_namespace.c new file mode 100644 index 0000000000000000000000000000000000000000..380bc75f770c6e98fe4acea36c90bb2844b38c76 --- /dev/null +++ b/services/sandbox/sandbox_namespace.c @@ -0,0 +1,84 @@ +/* +* 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 "beget_ext.h" + +static int g_defaultNs; + +int GetNamespaceFd(const char *nsPath) +{ + BEGET_CHECK(nsPath != NULL, return -1); + int ns = open(nsPath, O_RDONLY | O_CLOEXEC); + if (ns < 0) { + BEGET_LOGE("Open default namespace failed, err=%d", errno); + return -1; + } + return ns; +} + +int UnshareNamespace(int nsType) +{ + if (nsType == CLONE_NEWNS) { + if (unshare(nsType) < 0) { + BEGET_LOGE("Unshare namespace failed, err=%d", errno); + return -1; + } else { + return 0; + } + } else { + BEGET_LOGE("Namespace type is not support"); + return -1; + } +} + +int SetNamespace(int nsFd, int nsType) +{ + if (nsFd < 0) { + BEGET_LOGE("Namespace fd is invalid"); + return -1; + } + if (nsType != CLONE_NEWNS) { + BEGET_LOGE("Namespace type is not support"); + return -1; + } + return setns(nsFd, nsType); +} + +void InitDefaultNamespace(void) +{ + BEGET_CHECK(!(g_defaultNs > 0), (void)close(g_defaultNs)); + g_defaultNs = GetNamespaceFd("/proc/self/ns/mnt"); + return; +} + +int EnterDefaultNamespace(void) +{ + BEGET_CHECK(!(g_defaultNs < 0), return -1); + return SetNamespace(g_defaultNs, CLONE_NEWNS); +} + +void CloseDefaultNamespace(void) +{ + if (g_defaultNs > 0) { + (void)close(g_defaultNs); + g_defaultNs = -1; + } + return; +} diff --git a/services/sandbox/system-sandbox.json b/services/sandbox/system-sandbox.json new file mode 100644 index 0000000000000000000000000000000000000000..5998732ddeded867a98923831a3db44529c3973b --- /dev/null +++ b/services/sandbox/system-sandbox.json @@ -0,0 +1,110 @@ +{ + "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" ], + "ignore": 1 + }, { + "src-path" : "/system/fonts", + "sandbox-path" : "/system/fonts", + "sandbox-flags" : [ "bind", "rec", "private" ], + "ignore": 1 + }, { + "src-path" : "/system/usr", + "sandbox-path" : "/system/usr", + "sandbox-flags" : [ "bind", "rec", "private" ], + "ignore": 1 + }, { + "src-path" : "/system/resource", + "sandbox-path" : "/system/resource", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/lib/chipsetsdk", + "sandbox-path" : "/vendor/lib/chipsetsdk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/lib/chipset-sdk", + "sandbox-path" : "/vendor/lib/chipset-sdk", + "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" : "/log", + "sandbox-path" : "/log", + "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" ], + "ignore": 1 + }, { + "src-path" : "/mnt", + "sandbox-path" : "/mnt", + "sandbox-flags" : [ "bind", "private" ] + }, { + "src-path" : "/sys_prod", + "sandbox-path" : "/sys_prod", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/etc", + "sandbox-path" : "/vendor/etc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/chipset/etc", + "sandbox-path" : "/chipset/etc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/chip_prod/etc", + "sandbox-path" : "/chip_prod/etc", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/module_update", + "sandbox-path" : "/module_update", + "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" + } + ] +} diff --git a/services/sandbox/system-sandbox64.json b/services/sandbox/system-sandbox64.json new file mode 100644 index 0000000000000000000000000000000000000000..6bb3bf2ed15980f8f669d59f1287ed4382a5617c --- /dev/null +++ b/services/sandbox/system-sandbox64.json @@ -0,0 +1,112 @@ +{ + "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/lib64", + "sandbox-path" : "/system/lib64", + "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" ], + "ignore": 1 + }, { + "src-path" : "/system/fonts", + "sandbox-path" : "/system/fonts", + "sandbox-flags" : [ "bind", "rec", "private" ], + "ignore": 1 + }, { + "src-path" : "/system/usr", + "sandbox-path" : "/system/usr", + "sandbox-flags" : [ "bind", "rec", "private" ], + "ignore": 1 + }, { + "src-path" : "/system/resource", + "sandbox-path" : "/system/resource", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/lib64/chipsetsdk", + "sandbox-path" : "/vendor/lib64/chipsetsdk", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor/firmware", + "sandbox-path" : "/vendor/firmware", + "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" : "/log", + "sandbox-path" : "/log", + "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", "private" ] + }, { + "src-path" : "/sys_prod", + "sandbox-path" : "/sys_prod", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/vendor", + "sandbox-path" : "/chipset", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/chip_prod", + "sandbox-path" : "/chip_prod", + "sandbox-flags" : [ "bind", "rec", "private" ] + }, { + "src-path" : "/module_update", + "sandbox-path" : "/module_update", + "sandbox-flags" : [ "bind", "rec", "private" ] + } + ], + "mount-bind-files" : [{ + }], + "symbol-links" : [{ + "target-name" : "/system/lib64", + "link-name" : "/lib64" + }, { + "target-name" : "/system/lib", + "link-name" : "/lib" + }, { + "target-name" : "/system/bin", + "link-name" : "/bin" + }, { + "target-name" : "/system/etc", + "link-name" : "/etc" + } + ] +} diff --git a/services/src/init_capability.c b/services/src/init_capability.c deleted file mode 100644 index 58884ef3116c95209184e003e0198586623cc155..0000000000000000000000000000000000000000 --- a/services/src/init_capability.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2020 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 "init_capability.h" - -#include -#include -#include -#include -#include -#if defined OHOS_LITE && !defined __LINUX__ -#include -#else -#include -#endif -#include -#include - -#include "init_log.h" -#include "init_perms.h" - -#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100 - -struct CapStrCapNum { - char *capStr; - int CapNum; -}; - -static const struct CapStrCapNum g_capStrCapNum[] = { - {"CHOWN", CAP_CHOWN}, - {"DAC_OVERRIDE", CAP_DAC_OVERRIDE}, - {"DAC_READ_SEARCH", CAP_DAC_READ_SEARCH}, - {"FOWNER", CAP_FOWNER}, - {"FSETID", CAP_FSETID}, - {"KILL", CAP_KILL}, - {"SETGID", CAP_SETGID}, - {"SETUID", CAP_SETUID}, - {"SETPCAP", CAP_SETPCAP}, - {"LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE}, - {"NET_BIND_SERVICE", CAP_NET_BIND_SERVICE}, - {"NET_BROADCAST", CAP_NET_BROADCAST}, - {"NET_ADMIN", CAP_NET_ADMIN}, - {"NET_RAW", CAP_NET_RAW}, - {"IPC_LOCK", CAP_IPC_LOCK}, - {"IPC_OWNER", CAP_IPC_OWNER}, - {"SYS_MODULE", CAP_SYS_MODULE}, - {"SYS_RAWIO", CAP_SYS_RAWIO}, - {"SYS_CHROOT", CAP_SYS_CHROOT}, - {"SYS_PTRACE", CAP_SYS_PTRACE}, - {"SYS_PACCT", CAP_SYS_PACCT}, - {"SYS_ADMIN", CAP_SYS_ADMIN}, - {"SYS_BOOT", CAP_SYS_BOOT}, - {"SYS_NICE", CAP_SYS_NICE}, - {"SYS_RESOURCE", CAP_SYS_RESOURCE}, - {"SYS_TIME", CAP_SYS_TIME}, - {"SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG}, - {"MKNOD", CAP_MKNOD}, - {"LEASE", CAP_LEASE}, - {"AUDIT_WRITE", CAP_AUDIT_WRITE}, - {"AUDIT_CONTROL", CAP_AUDIT_CONTROL}, - {"SETFCAP", CAP_SETFCAP}, - {"MAC_OVERRIDE", CAP_MAC_OVERRIDE}, - {"MAC_ADMIN", CAP_MAC_ADMIN}, - {"SYSLOG", CAP_SYSLOG}, - {"WAKE_ALARM", CAP_WAKE_ALARM}, - {"BLOCK_SUSPEND", CAP_BLOCK_SUSPEND}, - {"AUDIT_READ", CAP_AUDIT_READ}, -}; - -static int GetServiceStringCaps(const cJSON* filedJ, Service* curServ) // string form -{ - unsigned int i = 0; - for (; i < curServ->servPerm.capsCnt; ++i) { - if (cJSON_GetArrayItem(filedJ, i) == NULL || !cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i)) - || strlen(cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))) <= 0) { // check all errors - INIT_LOGE("service=%s, parse item[%d] as string, error.", curServ->name, i); - break; - } - char* fieldStr = cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i)); - if (fieldStr == NULL) { - INIT_LOGE("fieldStr is NULL"); - break; - } - int mapSize = sizeof(g_capStrCapNum) / sizeof(struct CapStrCapNum); // search - int j = 0; - for (; j < mapSize; j++) { - if (!strcmp(fieldStr, g_capStrCapNum[j].capStr)) { - break; - } - } - if (j < mapSize) { - curServ->servPerm.caps[i] = g_capStrCapNum[j].CapNum; - } else { - INIT_LOGE("service=%s, CapbilityName=%s, error.", curServ->name, fieldStr); - break; - } - if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("service=%s, cap = %d, error.", curServ->name, curServ->servPerm.caps[i]); - return SERVICE_FAILURE; - } - } - int ret = i == curServ->servPerm.capsCnt ? SERVICE_SUCCESS : SERVICE_FAILURE; - return ret; -} - -int GetServiceCaps(const cJSON* curArrItem, Service* curServ) -{ - if (curServ == NULL || curArrItem == NULL) { - INIT_LOGE("GetServiceCaps failed, curServ or curArrItem is NULL."); - return SERVICE_FAILURE; - } - curServ->servPerm.capsCnt = 0; - curServ->servPerm.caps = NULL; - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "caps"); - if (filedJ == NULL) { - return SERVICE_SUCCESS; - } - if (!cJSON_IsArray(filedJ)) { - INIT_LOGE("service=%s, caps is not a list, error.", curServ->name); - return SERVICE_FAILURE; - } - // caps array does not exist, means do not need any capability - int capsCnt = cJSON_GetArraySize(filedJ); - if (capsCnt <= 0) { - return SERVICE_SUCCESS; - } - if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) { - INIT_LOGE("service=%s, too many caps[cnt %d] for one service, max is %d.", - curServ->name, capsCnt, MAX_CAPS_CNT_FOR_ONE_SERVICE); - return SERVICE_FAILURE; - } - curServ->servPerm.caps = (unsigned int*)malloc(sizeof(unsigned int) * capsCnt); - if (curServ->servPerm.caps == NULL) { - INIT_LOGE("GetServiceCaps, service=%s, malloc error.", curServ->name); - return SERVICE_FAILURE; - } - curServ->servPerm.capsCnt = capsCnt; - int i = 0; - for (; i < capsCnt; ++i) { // number form - cJSON* capJ = cJSON_GetArrayItem(filedJ, i); - if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) { - // resources will be released by function: ReleaseServiceMem - break; - } - curServ->servPerm.caps[i] = (unsigned int)cJSON_GetNumberValue(capJ); - if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) { // CAP_LAST_CAP = 37 - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("service=%s, caps = %d, error.", curServ->name, curServ->servPerm.caps[i]); - return SERVICE_FAILURE; - } - } - if (i == capsCnt) { - return SERVICE_SUCCESS; - } - int ret = GetServiceStringCaps(filedJ, curServ); - return ret; -} - diff --git a/services/src/init_cmds.c b/services/src/init_cmds.c deleted file mode 100644 index d929e7976765fa8b75222158416957ae8b6a3eba..0000000000000000000000000000000000000000 --- a/services/src/init_cmds.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * Copyright (c) 2020-2021 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 "init_cmds.h" - -#include -#include -#include -#ifndef OHOS_LITE -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "init_jobs.h" -#include "init_log.h" -#ifndef OHOS_LITE -#include "init_param.h" -#endif -#include "init_reboot.h" -#include "init_service_manager.h" -#include "init_utils.h" -#include "securec.h" - -#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) // mkdir, default mode -#define SPACES_CNT_IN_CMD_MAX 10 // mount, max number of spaces in cmdline -#define SPACES_CNT_IN_CMD_MIN 2 // mount, min number of spaces in cmdline - -#define LOADCFG_BUF_SIZE 128 // loadcfg, max buffer for one cmdline -#define LOADCFG_MAX_FILE_LEN 51200 // loadcfg, max file size is 50K -#define LOADCFG_MAX_LOOP 20 // loadcfg, to prevent to be trapped in infite loop -#define OCTAL_TYPE 8 // 8 means octal to decimal -#define MAX_BUFFER 256UL -#define AUTHORITY_MAX_SIZE 128 -#define WAIT_MAX_COUNT 10 - -static const char *g_supportCfg[] = { - "/etc/patch.cfg", - "/patch/fstab.cfg", -}; - -#ifndef OHOS_LITE -int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen) -{ - if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) { - return -1; - } - char tmpName[MAX_PARAM_NAME_LEN] = {0}; - char tmpValue[MAX_PARAM_VALUE_LEN] = {0}; - unsigned int tmpLen = 0; - char *p = NULL; - char *tmpptr = NULL; - p = strchr(symValue, '$'); - if (p == NULL) { // not has '$' copy the original string - INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, paramLen - 1) == EOK, -1); - return 0; - } - tmpLen = p - symValue; - if (tmpLen > 0) { // copy '$' front string - INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, tmpLen) == EOK, -1); - } - p++; - if (*p == '{') { - p++; - char *right = strchr(p, '}'); - if (right == NULL) { - INIT_LOGE("Invalid cfg file name, miss '}'."); - return -1; - } - tmpLen = right - p; - if (tmpLen > MAX_PARAM_NAME_LEN) { - INIT_LOGE("Parameter name longer than %d", MAX_PARAM_NAME_LEN); - return -1; - } - INIT_CHECK_RETURN_VALUE(strncpy_s(tmpName, MAX_PARAM_NAME_LEN, p, tmpLen) == EOK, -1); - int ret = SystemReadParam(tmpName, tmpValue, &tmpLen); // get param - if (ret != 0) { - INIT_LOGE("Failed to read parameter \" %s \"", tmpName); - return -1; - } - // change param to new string - INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpValue, MAX_PARAM_VALUE_LEN) == EOK, -1); - tmpptr = right + 1; - tmpLen = paramLen - (tmpptr - symValue); - if (*tmpptr != '\0') { // copy last string - INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpptr, tmpLen) == EOK, -1); - } - INIT_LOGI("paramValue is %s ", paramValue); - return 0; - } else { - INIT_LOGE("Invalid cfg file name, miss '{'."); - return -1; - } -} -#else -// For ite ohos, do not support parameter operation. just do string copy -inline int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen) -{ - return (strncpy_s(paramValue, paramLen, symValue, strlen(symValue)) == EOK) ? 0 : -1; -} -#endif - -struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount) -{ - INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL); - struct CmdArgs *ctx = (struct CmdArgs *)malloc(sizeof(struct CmdArgs)); - INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL); - - if (argsCount > SPACES_CNT_IN_CMD_MAX) { - INIT_LOGW("Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX); - argsCount = SPACES_CNT_IN_CMD_MAX; - } - ctx->argv = (char**)malloc(sizeof(char*) * (size_t)argsCount + 1); - INIT_CHECK(ctx->argv != NULL, FreeCmd(&ctx); return NULL); - - char tmpCmd[MAX_BUFFER]; - size_t cmdLength = strlen(cmdContent); - if (cmdLength > MAX_BUFFER - 1) { - INIT_LOGE("command line is too larget, should not bigger than %d. ignore...\n", MAX_BUFFER); - FreeCmd(&ctx); - return NULL; - } - - INIT_CHECK(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK, - FreeCmd(&ctx); - return NULL); - tmpCmd[strlen(cmdContent)] = '\0'; - - char *p = tmpCmd; - char *token = NULL; - size_t allocSize = 0; - - // Skip lead whitespaces - while (isspace(*p)) { - p++; - } - ctx->argc = 0; - token = strstr(p, delim); - if (token == NULL) { // No whitespaces - // Make surce there is enough memory to store parameter value - allocSize = (size_t)(cmdLength + MAX_PARAM_VALUE_LEN + 1); - ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(&ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[ctx->argc], allocSize) == 0, - FreeCmd(&ctx); return NULL); - ctx->argc += 1; - ctx->argv[ctx->argc] = NULL; - return ctx; - } - - int index = ctx->argc; - while (token != NULL) { - // Too more arguments, treat rest of data as one argument - if (index == (argsCount - 1)) { - break; - } - *token = '\0'; // replace it with '\0'; - allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1); - ctx->argv[index] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0, - FreeCmd(&ctx); return NULL); - p = token + 1; // skip '\0' - // Skip lead whitespaces - while (isspace(*p)) { - p++; - } - index++; - token = strstr(p, delim); - } - - ctx->argc = index; - if (p < tmpCmd + cmdLength) { - // no more white space or encounter max argument count - size_t restSize = tmpCmd + cmdLength - p; - allocSize = restSize + MAX_PARAM_VALUE_LEN + 1; - ctx->argv[index] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(&ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0, - FreeCmd(&ctx); return NULL); - ctx->argc = index + 1; - } - - ctx->argv[ctx->argc] = NULL; - return ctx; -} - -void FreeCmd(struct CmdArgs **cmd) -{ - struct CmdArgs *tmpCmd = *cmd; - INIT_CHECK_ONLY_RETURN(tmpCmd != NULL); - for (int i = 0; i < tmpCmd->argc; ++i) { - INIT_CHECK(tmpCmd->argv[i] == NULL, free(tmpCmd->argv[i])); - } - INIT_CHECK(tmpCmd->argv == NULL, free(tmpCmd->argv)); - free(tmpCmd); - return; -} - -#define EXTRACT_ARGS(cmdname, cmdContent, args) \ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", args); \ - if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != args)) { \ - INIT_LOGE("Command \"%s\" with invalid arguments: %s", #cmdname, cmdContent); \ - goto out; \ - } \ - -static void DoSetDomainname(const char *cmdContent, int maxArg) -{ - EXTRACT_ARGS(domainname, cmdContent, maxArg) - int fd = open("/proc/sys/kernel/domainname", O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, - S_IRUSR | S_IWUSR); - if (fd < 0) { - INIT_LOGE("DoSetDomainame failed to open \"/proc/sys/kernel/domainname\". err = %d", errno); - goto out; - } - - size_t size = strlen(ctx->argv[0]); - ssize_t n = write(fd, ctx->argv[0], size); - if (n != (ssize_t)size) { - INIT_LOGE("DoSetHostname failed to write %s to \"/proc/sys/kernel/domainname\". err = %d", errno); - } - - close(fd); -out: - FreeCmd(&ctx); - fd = -1; - return; -} - -static void DoSetHostname(const char *cmdContent, int maxArg) -{ - EXTRACT_ARGS(hostname, cmdContent, maxArg) - int fd = open("/proc/sys/kernel/hostname", O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, - S_IRUSR | S_IWUSR); - if (fd < 0) { - INIT_LOGE("DoSetHostname failed to open \"/proc/sys/kernel/hostname\". err = %d", errno); - goto out; - } - - size_t size = strlen(ctx->argv[0]); - ssize_t n = write(fd, ctx->argv[0], size); - if (n != (ssize_t)size) { - INIT_LOGE("DoSetHostname failed to write %s to \"/proc/sys/kernel/hostname\". err = %d", errno); - } - - close(fd); -out: - FreeCmd(&ctx); - fd = -1; - return; -} - -#ifndef OHOS_LITE -static void DoIfup(const char *cmdContent, int maxArg) -{ - EXTRACT_ARGS(ifup, cmdContent, maxArg) - struct ifreq interface; - if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) { - INIT_LOGE("DoIfup failed to copy interface name"); - goto out; - } - - INIT_LOGD("interface name: %s", interface.ifr_name); - int fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - INIT_LOGE("DoIfup failed to create socket, err = %d", errno); - goto out; - } - - if (ioctl(fd, SIOCGIFFLAGS, &interface) < 0) { - INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCGIFFLAGS\", err = %d", errno); - close(fd); - fd = -1; - goto out; - } - interface.ifr_flags |= IFF_UP; - - if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) { - INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno); - } - - close(fd); -out: - FreeCmd(&ctx); - fd = -1; - return; -} -#endif - -static void DoSleep(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoSleep invalid arguments :%s", cmdContent); - goto out; - } - - errno = 0; - unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE); - if (errno != 0) { - INIT_LOGE("cannot covert sleep time in command \" sleep \""); - goto out; - } - - // Limit sleep time in 5 seconds - const unsigned long sleepTimeLimit = 5; - if (sleepTime > sleepTimeLimit) { - sleepTime = sleepTimeLimit; - } - INIT_LOGI("Sleeping %d second(s)", sleepTime); - sleep((unsigned int)sleepTime); -out: - FreeCmd(&ctx); - return; -} - -static void DoStart(const char* cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoStart invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoStart %s", cmdContent); - StartServiceByName(cmdContent); -out: - FreeCmd(&ctx); - return; -} - -static void DoStop(const char* cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoStop invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoStop %s", cmdContent); - StopServiceByName(cmdContent); -out: - FreeCmd(&ctx); - return; -} - -static void DoReset(const char* cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoReset invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoReset %s", cmdContent); - DoStop(cmdContent, maxArg); - DoStart(cmdContent, maxArg); -out: - FreeCmd(&ctx); - return; -} - -static void DoCopy(const char* cmdContent, int maxArg) -{ - int srcFd = -1; - int dstFd = -1; - int rdLen = 0; - int rtLen = 0; - char buf[MAX_COPY_BUF_SIZE] = {0}; - char *realPath1 = NULL; - char *realPath2 = NULL; - mode_t mode = 0; - struct stat fileStat = {0}; - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argv[1] == NULL || - ctx->argc != DEFAULT_COPY_ARGS_CNT) { - INIT_LOGE("DoCopy invalid arguments :%s", cmdContent); - goto out; - } - realPath1 = realpath(ctx->argv[0], NULL); - if (realPath1 == NULL) { - goto out; - } - realPath2 = realpath(ctx->argv[1], NULL); - if (realPath2 == NULL) { - goto out; - } - srcFd = open(realPath1, O_RDONLY); - INIT_ERROR_CHECK(srcFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[0], errno); - INIT_ERROR_CHECK(stat(ctx->argv[0], &fileStat) == 0, goto out, "stat fail "); - mode = fileStat.st_mode; - dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode); - INIT_ERROR_CHECK(dstFd >= 0, goto out, "copy open %s fail %d! ", ctx->argv[1], errno); - while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) { - rtLen = write(dstFd, buf, rdLen); - INIT_ERROR_CHECK(rtLen == rdLen, goto out, "write %s file fail %d! ", ctx->argv[1], errno); - } - fsync(dstFd); -out: - FreeCmd(&ctx); - ctx = NULL; - INIT_CHECK(srcFd < 0, close(srcFd); srcFd = -1); - INIT_CHECK(dstFd < 0, close(dstFd); dstFd = -1); - INIT_CHECK(realPath1 == NULL, free(realPath1); realPath1 = NULL); - INIT_CHECK(realPath2 == NULL, free(realPath2); realPath2 = NULL); - return; -} - -static void DoChown(const char* cmdContent, int maxArg) -{ - // format: chown owner group /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoChown invalid arguments :%s", cmdContent); - goto out; - } - - uid_t owner = DecodeUid(ctx->argv[0]); - INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoChown invalid uid :%s.", ctx->argv[0]); - - gid_t group = DecodeUid(ctx->argv[1]); - INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "DoChown invalid gid :%s.", ctx->argv[1]); - - int pathPos = 2; - if (chown(ctx->argv[pathPos], owner, group) != 0) { - INIT_LOGE("DoChown, failed for %s, err %d.", cmdContent, errno); - } -out: - FreeCmd(&ctx); - return; -} - -static void DoMkDir(const char* cmdContent, int maxArg) -{ - // mkdir support format: - // 1.mkdir path - // 2.mkdir path mode - // 3.mkdir path mode owner group - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc < 1) { - INIT_LOGE("DoMkDir invalid arguments :%s", cmdContent); - goto out; - } - - const int withModeArg = 2; - if (ctx->argc != 1 && ctx->argc != maxArg && ctx->argc != withModeArg) { - INIT_LOGE("DoMkDir invalid arguments: %s", cmdContent); - goto out; - } - - mode_t mode = DEFAULT_DIR_MODE; - if (mkdir(ctx->argv[0], mode) != 0 && errno != EEXIST) { - INIT_LOGE("DoMkDir, failed for %s, err %d.", cmdContent, errno); - goto out; - } - - if (ctx->argc > 1) { - mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE); - if (chmod(ctx->argv[0], mode) != 0) { - INIT_LOGE("DoMkDir failed for %s, err %d.", cmdContent, errno); - } - if (ctx->argc == withModeArg) { - goto out; - } - const int ownerPos = 2; - const int groupPos = 3; - - uid_t owner = DecodeUid(ctx->argv[ownerPos]); - INIT_ERROR_CHECK(owner != (uid_t)-1, goto out, "DoMkDir invalid uid :%s.", ctx->argv[ownerPos]); - - gid_t group = DecodeUid(ctx->argv[groupPos]); - INIT_ERROR_CHECK(group != (gid_t)-1, goto out, "DoMkDir invalid gid :%s.", ctx->argv[groupPos]); - - if (chown(ctx->argv[0], owner, group) != 0) { - INIT_LOGE("DoMkDir, chown failed for %s, err %d.", cmdContent, errno); - } - } -out: - FreeCmd(&ctx); - return; -} - -static void DoChmod(const char* cmdContent, int maxArg) -{ - // format: chmod xxxx /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoChmod invalid arguments :%s", cmdContent); - goto out; - } - - mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE); - if (mode == 0) { - INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno); - goto out; - } - - if (chmod(ctx->argv[1], mode) != 0) { - INIT_LOGE("DoChmod, failed for %s, err %d.", cmdContent, errno); - } -out: - FreeCmd(&ctx); - return; -} - -static char* CopySubStr(const char* srcStr, size_t startPos, size_t endPos) -{ - if (endPos <= startPos) { - INIT_LOGE("DoMount, invalid params<%zu, %zu> for %s.", endPos, startPos, srcStr); - return NULL; - } - - size_t mallocLen = endPos - startPos + 1; - char* retStr = (char*)malloc(mallocLen); - if (retStr == NULL) { - INIT_LOGE("DoMount, malloc failed! malloc size %zu, for %s.", mallocLen, srcStr); - return NULL; - } - - const char* copyStart = srcStr + startPos; - if (memcpy_s(retStr, mallocLen, copyStart, endPos - startPos) != EOK) { - INIT_LOGE("DoMount, memcpy_s failed for %s.", srcStr); - free(retStr); - return NULL; - } - retStr[mallocLen - 1] = '\0'; - - // for example, source may be none - if (strncmp(retStr, "none", strlen("none")) == 0) { - retStr[0] = '\0'; - } - return retStr; -} - -static int GetMountFlag(unsigned long* mountflags, const char* targetStr, const char *source) -{ - if (targetStr == NULL) { - return 0; - } - - if (strncmp(targetStr, "nodev", strlen("nodev")) == 0) { - (*mountflags) |= MS_NODEV; - } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) { - (*mountflags) |= MS_NOEXEC; - } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) { - (*mountflags) |= MS_NOSUID; - } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) { - (*mountflags) |= MS_RDONLY; - } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) { - (*mountflags) |= MS_NOATIME; - } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) { - WaitForFile(source, WAIT_MAX_COUNT); - } else { - return 0; - } - return 1; -} - -static int CountSpaces(const char* cmdContent, size_t* spaceCnt, size_t* spacePosArr, size_t spacePosArrLen) -{ - *spaceCnt = 0; - size_t strLen = strlen(cmdContent); - for (size_t i = 0; i < strLen; ++i) { - if (cmdContent[i] == ' ') { - ++(*spaceCnt); - if ((*spaceCnt) > spacePosArrLen) { - INIT_LOGE("DoMount, too many spaces, bad format for %s.", cmdContent); - return 0; - } - spacePosArr[(*spaceCnt) - 1] = i; - } - } - - if ((*spaceCnt) < SPACES_CNT_IN_CMD_MIN || // spaces count should not less than 2(at least 3 items) - spacePosArr[0] == 0 || // should not start with space - spacePosArr[(*spaceCnt) - 1] == strLen - 1) { // should not end with space - INIT_LOGE("DoMount, bad format for %s.", cmdContent); - return 0; - } - - // spaces should not be adjacent - for (size_t i = 1; i < (*spaceCnt); ++i) { - if (spacePosArr[i] == spacePosArr[i - 1] + 1) { - INIT_LOGE("DoMount, bad format for %s.", cmdContent); - return 0; - } - } - return 1; -} - -static void DoMount(const char* cmdContent, int maxArg) -{ - size_t spaceCnt = 0; - size_t spacePosArr[SPACES_CNT_IN_CMD_MAX] = {0}; - if (!CountSpaces(cmdContent, &spaceCnt, spacePosArr, SPACES_CNT_IN_CMD_MAX)) { - return; - } - - // format: fileSystemType source target mountFlag1 mountFlag2... data - unsigned long mountflags = 0; - size_t strLen = strlen(cmdContent); - size_t indexOffset = 0; - char* fileSysType = CopySubStr(cmdContent, 0, spacePosArr[indexOffset]); - if (fileSysType == NULL) { - return; - } - - char* source = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, spacePosArr[indexOffset + 1]); - if (source == NULL) { - free(fileSysType); - return; - } - ++indexOffset; - - // maybe only has "filesystype source target", 2 spaces - size_t targetEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1]; - char* target = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, targetEndPos); - if (target == NULL) { - free(fileSysType); - free(source); - return; - } - ++indexOffset; - - // get mountflags, if fail, the rest part of string will be data - while (indexOffset < spaceCnt) { - size_t tmpStrEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1]; - char* tmpStr = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, tmpStrEndPos); - int ret = GetMountFlag(&mountflags, tmpStr, source); - free(tmpStr); - tmpStr = NULL; - - // get flag failed, the rest part of string will be data - if (ret == 0) { - break; - } - ++indexOffset; - } - - int mountRet; - if (indexOffset >= spaceCnt) { // no data - mountRet = mount(source, target, fileSysType, mountflags, NULL); - } else { - const char* dataStr = cmdContent + spacePosArr[indexOffset] + 1; - mountRet = mount(source, target, fileSysType, mountflags, dataStr); - } - - if (mountRet != 0) { - INIT_LOGE("DoMount, failed for %s, err %d.", cmdContent, errno); - } - - free(fileSysType); - free(source); - free(target); -} - -#ifndef OHOS_LITE -#define OPTIONS_SIZE 128u -static void DoInsmodInternal(const char *fileName, char *secondPtr, char *restPtr, int flags) -{ - char options[OPTIONS_SIZE] = {0}; - if (flags == 0) { // '-f' option - if (restPtr != NULL && secondPtr != NULL) { // Reset arugments, combine then all. - if (snprintf_s(options, sizeof(options), OPTIONS_SIZE -1, "%s %s", secondPtr, restPtr) == -1) { - return; - } - } else if (secondPtr != NULL) { - if (strncpy_s(options, OPTIONS_SIZE - 1, secondPtr, strlen(secondPtr)) != 0) { - return; - } - } - } else { // Only restPtr is option - if (restPtr != NULL) { - if (strncpy_s(options, OPTIONS_SIZE - 1, restPtr, strlen(restPtr)) != 0) { - return; - } - } - } - if (fileName == NULL) { - return; - } - char *realPath = realpath(fileName, NULL); - if (realPath == NULL) { - return; - } - int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) { - INIT_LOGE("failed to open %s: %d", realPath, errno); - free(realPath); - realPath = NULL; - return; - } - int rc = syscall(__NR_finit_module, fd, options, flags); - if (rc == -1) { - INIT_LOGE("finit_module for %s failed: %d", realPath, errno); - } - if (fd >= 0) { - close(fd); - } - free(realPath); - realPath = NULL; - return; -} - -// format insmod [-f] [options] -static void DoInsmod(const char *cmdContent, int maxArg) -{ - char *p = NULL; - char *restPtr = NULL; - char *fileName = NULL; - char *line = NULL; - int flags = 0; - - size_t count = strlen(cmdContent); - if (count > OPTIONS_SIZE) { - INIT_LOGE("DoInsmod options too long, maybe lost some of options"); - } - line = (char *)malloc(count + 1); - if (line == NULL) { - INIT_LOGE("DoInsmod allocate memory failed."); - return; - } - - if (memcpy_s(line, count + 1, cmdContent, count) != EOK) { - INIT_LOGE("DoInsmod memcpy failed"); - free(line); - return; - } - line[count] = '\0'; - do { - if ((p = strtok_r(line, " ", &restPtr)) == NULL) { - INIT_LOGE("DoInsmod cannot get filename."); - free(line); - return; - } - fileName = p; - INIT_LOGI("DoInsmod fileName is [%s].", fileName); - if ((p = strtok_r(NULL, " ", &restPtr)) == NULL) { - break; - } - if (!strcmp(p, "-f")) { - flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS; - } - } while (0); - DoInsmodInternal(fileName, p, restPtr, flags); - if (line != NULL) { - free(line); - } - return; -} - -static void DoSetParam(const char* cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoSetParam invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGE("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]); - SystemWriteParam(ctx->argv[0], ctx->argv[1]); -out: - FreeCmd(&ctx); - return; -} - -#endif // OHOS_LITE - -static bool CheckValidCfg(const char *path) -{ - size_t cfgCnt = sizeof(g_supportCfg) / sizeof(g_supportCfg[0]); - struct stat fileStat = {0}; - - if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) { - return false; - } - - for (size_t i = 0; i < cfgCnt; ++i) { - if (strcmp(path, g_supportCfg[i]) == 0) { - return true; - } - } - return false; -} - -static void DoLoadCfg(const char *path, int maxArg) -{ - char buf[LOADCFG_BUF_SIZE] = {0}; - FILE *fp = NULL; - size_t maxLoop = 0; - CmdLine *cmdLine = NULL; - int len; - INIT_CHECK_ONLY_RETURN(path != NULL); - INIT_LOGI("DoLoadCfg cfg file %s", path); - if (!CheckValidCfg(path)) { - INIT_LOGE("CheckCfg file %s Failed", path); - return; - } - INIT_ERROR_CHECK(path != NULL, return, "CheckCfg path is NULL."); - char *realPath = realpath(path, NULL); - INIT_CHECK_ONLY_RETURN(realPath != NULL); - fp = fopen(realPath, "r"); - if (fp == NULL) { - INIT_LOGE("open cfg error = %d", errno); - free(realPath); - realPath = NULL; - return; - } - - cmdLine = (CmdLine *)malloc(sizeof(CmdLine)); - if (cmdLine == NULL) { - INIT_LOGE("malloc cmdline error"); - fclose(fp); - free(realPath); - realPath = NULL; - return; - } - - while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) { - maxLoop++; - len = strlen(buf); - if (len < 1) { - continue; - } - if (buf[len - 1] == '\n') { - buf[len - 1] = '\0'; // we replace '\n' with '\0' - } - (void)memset_s(cmdLine, sizeof(CmdLine), 0, sizeof(CmdLine)); - ParseCmdLine(buf, cmdLine); - DoCmd(cmdLine); - (void)memset_s(buf, sizeof(char) * LOADCFG_BUF_SIZE, 0, sizeof(char) * LOADCFG_BUF_SIZE); - } - free(realPath); - realPath = NULL; - free(cmdLine); - fclose(fp); -} - -static void DoWrite(const char *cmdContent, int maxArg) -{ - // format: write path content - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoWrite: invalid arguments :%s", cmdContent); - goto out; - } - char *realPath = realpath(ctx->argv[0], NULL); - if (realPath == NULL) { - goto out; - } - int fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); - if (fd == -1) { - INIT_LOGE("DoWrite: open %s failed: %d", ctx->argv[0], errno); - free(realPath); - realPath = NULL; - goto out; - } - - size_t ret = write(fd, ctx->argv[1], strlen(ctx->argv[1])); - if (ret < 0) { - INIT_LOGE("DoWrite: write to file %s failed: %d", ctx->argv[0], errno); - free(realPath); - realPath = NULL; - close(fd); - goto out; - } - free(realPath); - realPath = NULL; - close(fd); -out: - FreeCmd(&ctx); - return; -} - -static void DoRmdir(const char *cmdContent, int maxArg) -{ - // format: rmdir path - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoRmdir: invalid arguments :%s", cmdContent); - goto out; - } - - int ret = rmdir(ctx->argv[0]); - if (ret == -1) { - INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} - -static void DoRebootCmd(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoReboot invalid arguments :%s", cmdContent); - goto out; - } - DoReboot(cmdContent); -out: - FreeCmd(&ctx); - return; -} - -static void DoLoadPersistParams(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoLoadPersistParams invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("load persist params : %s", cmdContent); - LoadPersistParams(); -out: - FreeCmd(&ctx); - return; -} - -static void DoTriggerCmd(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoTrigger invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("DoTrigger :%s", cmdContent); - DoTriggerExec(cmdContent); -out: - FreeCmd(&ctx); - return; -} - -static void DoLoadDefaultParams(const char *cmdContent, int maxArg) -{ - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoLoadDefaultParams invalid arguments :%s", cmdContent); - goto out; - } - INIT_LOGD("load persist params : %s", cmdContent); - LoadDefaultParams(cmdContent); -out: - FreeCmd(&ctx); - return; -} - -static void DoSetrlimit(const char *cmdContent, int maxArg) -{ - char *resource[] = { - "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS", - "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING", - "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS" - }; - // format: setrlimit resource curValue maxValue - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - const int rlimMaxPos = 2; - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoSetrlimit: invalid arguments :%s", cmdContent); - goto out; - } - - struct rlimit limit; - limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]); - limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]); - int rcs = -1; - for (unsigned int i = 0 ; i < sizeof(resource) / sizeof(char*); ++i) { - if (strcmp(ctx->argv[0], resource[i]) == 0) { - rcs = (int)i; - } - } - if (rcs == -1) { - INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]); - goto out; - } - int ret = setrlimit(rcs, &limit); - if (ret) { - INIT_LOGE("DoSetrlimit failed : %d", errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} - -static void DoRm(const char *cmdContent, int maxArg) -{ - // format: rm /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoRm: invalid arguments :%s", cmdContent); - goto out; - } - int ret = unlink(ctx->argv[0]); - if (ret == -1) { - INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} - -static void DoExport(const char *cmdContent, int maxArg) -{ - // format: export xxx /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoExport: invalid arguments :%s", cmdContent); - goto out; - } - int ret = setenv(ctx->argv[0], ctx->argv[1], 1); - if (ret != 0) { - INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} - -static void DoExec(const char *cmdContent, int maxArg) -{ - // format: exec /xxx/xxx/xxx xxx - pid_t pid = fork(); - if (pid < 0) { - INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent); - return; - } - if (pid == 0) { - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL) { - INIT_LOGE("DoExec: invalid arguments :%s", cmdContent); - _exit(0x7f); - } -#ifdef OHOS_LITE - int ret = execve(ctx->argv[0], ctx->argv, NULL); -#else - int ret = execv(ctx->argv[0], ctx->argv); -#endif - if (ret == -1) { - INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno); - } - FreeCmd(&ctx); - _exit(0x7f); - } - return; -} - -#ifndef __LITEOS__ -static void DoSymlink(const char *cmdContent, int maxArg) -{ - // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoSymlink: invalid arguments :%s", cmdContent); - goto out; - } - - int ret = symlink(ctx->argv[0], ctx->argv[1]); - if (ret != 0) { - INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} - -static mode_t GetDeviceMode(const char *deviceStr) -{ - switch (*deviceStr) { - case 'b': - case 'B': - return S_IFBLK; - case 'c': - case 'C': - return S_IFCHR; - case 'f': - case 'F': - return S_IFIFO; - default: - return -1; - } -} - -static void DoMakeNode(const char *cmdContent, int maxArg) -{ - // format: mknod path b 0644 1 9 - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - const int deviceTypePos = 1; - const int authorityPos = 2; - const int majorDevicePos = 3; - const int minorDevicePos = 4; - const int decimal = 10; - const int octal = 8; - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoMakeNode: invalid arguments :%s", cmdContent); - goto out; - } - - if (!access(ctx->argv[1], F_OK)) { - INIT_LOGE("DoMakeNode failed, path has not sexisted"); - goto out; - } - mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]); - unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal); - unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal); - mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal); - - int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor)); - if (ret != 0) { - INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} - -static void DoMakeDevice(const char *cmdContent, int maxArg) -{ - // format: makedev major minor - struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg); - const int decimal = 10; - if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) { - INIT_LOGE("DoMakedevice: invalid arguments :%s", cmdContent); - goto out; - } - unsigned int major = strtoul(ctx->argv[0], NULL, decimal); - unsigned int minor = strtoul(ctx->argv[1], NULL, decimal); - dev_t deviceId = makedev(major, minor); - if (deviceId < 0) { - INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno); - goto out; - } -out: - FreeCmd(&ctx); - return; -} -#endif // __LITEOS__ - -void DoCmd(const CmdLine* curCmd) -{ - // null curCmd or empty command, just quit. - if (curCmd == NULL || curCmd->name[0] == '\0') { - return; - } - DoCmdByName(curCmd->name, curCmd->cmdContent); -} - -struct CmdTable { - char name[MAX_CMD_NAME_LEN]; - int maxArg; - void (*DoFuncion)(const char *cmdContent, int maxArg); -}; - -static const struct CmdTable CMD_TABLE[] = { - { "start ", 1, DoStart }, - { "mkdir ", 4, DoMkDir }, - { "chmod ", 2, DoChmod }, - { "chown ", 3, DoChown }, - { "mount ", 10, DoMount }, - { "export ", 2, DoExport }, - { "loadcfg ", 1, DoLoadCfg }, - { "rm ", 1, DoRm }, - { "rmdir ", 1, DoRmdir }, - { "write ", 2, DoWrite }, - { "exec ", 10, DoExec }, -#ifndef OHOS_LITE - { "mknode ", 5, DoMakeNode }, - { "makedev ", 2, DoMakeDevice }, - { "symlink ", 2, DoSymlink }, - { "trigger ", 1, DoTriggerCmd }, - { "insmod ", 10, DoInsmod }, - { "setparam ", 2, DoSetParam }, - { "load_persist_params ", 1, DoLoadPersistParams }, - { "load_param ", 1, DoLoadDefaultParams }, - { "ifup ", 1, DoIfup }, -#endif - { "stop ", 1, DoStop }, - { "reset ", 1, DoReset }, - { "copy ", 2, DoCopy }, - { "reboot ", 1, DoRebootCmd }, - { "setrlimit ", 3, DoSetrlimit }, - { "sleep ", 1, DoSleep }, - { "hostname ", 1, DoSetHostname }, - { "domainname ", 1, DoSetDomainname } -}; - -void DoCmdByName(const char *name, const char *cmdContent) -{ - if (name == NULL || cmdContent == NULL) { - return; - } - - size_t cmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]); - unsigned int i = 0; - for (; i < cmdCnt; ++i) { - if (strncmp(name, CMD_TABLE[i].name, strlen(CMD_TABLE[i].name)) == 0) { - CMD_TABLE[i].DoFuncion(cmdContent, CMD_TABLE[i].maxArg); - break; - } - } - if (i == cmdCnt) { - INIT_LOGE("DoCmd, unknown cmd name %s.", name); - } -} - -const char *GetMatchCmd(const char *cmdStr) -{ - if (cmdStr == NULL) { - return NULL; - } - size_t supportCmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]); - for (size_t i = 0; i < supportCmdCnt; ++i) { - size_t curCmdNameLen = strlen(CMD_TABLE[i].name); - if (strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) { - return CMD_TABLE[i].name; - } - } - return NULL; -} - -void ParseCmdLine(const char* cmdStr, CmdLine* resCmd) -{ - size_t cmdLineLen = 0; - if (cmdStr == NULL || resCmd == NULL || (cmdLineLen = strlen(cmdStr)) == 0) { - return; - } - - size_t supportCmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]); - int foundAndSucceed = 0; - for (size_t i = 0; i < supportCmdCnt; ++i) { - size_t curCmdNameLen = strlen(CMD_TABLE[i].name); - if (cmdLineLen > curCmdNameLen && cmdLineLen <= (curCmdNameLen + MAX_CMD_CONTENT_LEN) && - strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) { - if (memcpy_s(resCmd->name, MAX_CMD_NAME_LEN, cmdStr, curCmdNameLen) != EOK) { - break; - } - resCmd->name[curCmdNameLen] = '\0'; - - const char* cmdContent = cmdStr + curCmdNameLen; - size_t cmdContentLen = cmdLineLen - curCmdNameLen; - if (memcpy_s(resCmd->cmdContent, MAX_CMD_CONTENT_LEN, cmdContent, cmdContentLen) != EOK) { - break; - } - resCmd->cmdContent[cmdContentLen] = '\0'; - foundAndSucceed = 1; - break; - } - } - - if (!foundAndSucceed) { - INIT_LOGE("Cannot parse command: %s", cmdStr); - (void)memset_s(resCmd, sizeof(*resCmd), 0, sizeof(*resCmd)); - } -} - diff --git a/services/src/init_import.c b/services/src/init_import.c deleted file mode 100644 index 36d031fd4a2830afa9a7ce2676ccdfe62149d97e..0000000000000000000000000000000000000000 --- a/services/src/init_import.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2021 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 "init_import.h" -#include -#include -#include "cJSON.h" -#include "init_cmds.h" -#include "init_log.h" -#include "init_read_cfg.h" -#include "securec.h" - -#ifndef OHOS_LITE -static int ExtractCfgFile(char **cfgFile, const char *content) -{ - if ((!cfgFile) || (!content)) { - return -1; - } - size_t cfgFileLen = strlen(content) + MAX_PARAM_VALUE_LEN + 1; - if (cfgFileLen <= 0) { - return -1; - } - if ((*cfgFile = malloc(cfgFileLen)) == NULL) { - INIT_LOGW("Failed to allocate memory to import cfg file. err = %d", errno); - return -1; - } - return GetParamValue(content, *cfgFile, cfgFileLen); -} -#endif - -void ParseAllImports(cJSON *root) -{ - cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import"); - char *cfgFile = NULL; - if (!cJSON_IsArray(importAttr)) { - return; - } - int importAttrSize = cJSON_GetArraySize(importAttr); - - for (int i = 0; i < importAttrSize; i++) { - cJSON *importItem = cJSON_GetArrayItem(importAttr, i); - if (!cJSON_IsString(importItem)) { - INIT_LOGE("Invalid type of import item. should be string"); - return; - } - char *importContent = cJSON_GetStringValue(importItem); - if (importContent == NULL) { - INIT_LOGE("cannot get import config file"); - return; - } -// Only OHOS L2 support parameter. -#ifndef OHOS_LITE - if (ExtractCfgFile(&cfgFile, importContent) < 0) { - INIT_LOGW("Failed to import from %s", importContent); - if (cfgFile != NULL) { - free(cfgFile); - cfgFile = NULL; - } - continue; - } -#else - cfgFile = importContent; -#endif - INIT_LOGI("Import %s...", cfgFile); - ParseInitCfg(cfgFile); - // Do not forget to free memory. - free(cfgFile); - cfgFile = NULL; - } - INIT_LOGD("parse import file done"); - return; -} diff --git a/services/src/init_read_cfg.c b/services/src/init_read_cfg.c deleted file mode 100644 index 336820ea174bf62dffcde75d46823e773f75e675..0000000000000000000000000000000000000000 --- a/services/src/init_read_cfg.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2020 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 "init_read_cfg.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "init_import.h" -#include "init_jobs.h" -#include "init_log.h" -#include "init_perms.h" -#include "init_service_manager.h" -#include "init_utils.h" - -#ifndef OHOS_LITE -#include "init_param.h" -#endif -#include "securec.h" -#ifndef __LINUX__ -#ifdef OHOS_LITE -#include "init_stage.h" -#endif -#endif - -#define FILE_NAME_MAX_SIZE 100 -static void ParseInitCfgContents(cJSON *root) -{ - if (root == NULL) { - INIT_LOGE("ParseInitCfgContents root is NULL"); - return; - } - // parse services - ParseAllServices(root); -#ifdef OHOS_LITE - // parse jobs - ParseAllJobs(root); -#else - ParseTriggerConfig(root); -#endif - - // parse imports - ParseAllImports(root); -} - -void ParseInitCfg(const char *configFile) -{ - if (configFile == NULL || *configFile == '\0') { - INIT_LOGE("Invalid config file"); - return; - } - - char *fileBuf = ReadFileToBuf(configFile); - if (fileBuf == NULL) { - INIT_LOGE("Read %s failed", configFile); - return; - } - cJSON* fileRoot = cJSON_Parse(fileBuf); - free(fileBuf); - fileBuf = NULL; - - if (fileRoot == NULL) { - INIT_LOGE("InitReadCfg, parse failed! please check file %s format.", configFile); - return; - } - ParseInitCfgContents(fileRoot); - // Release JSON object - cJSON_Delete(fileRoot); - return; -} - -static void ReadCfgs(const char *dirPath) -{ - DIR *pDir = opendir(dirPath); - if (pDir == NULL) { - INIT_LOGE("ParseCfgs open cfg dir :%s failed.%d", dirPath, errno); - return; - } - struct dirent *dp; - while ((dp = readdir(pDir)) != NULL) { - char fileName[FILE_NAME_MAX_SIZE]; - if (snprintf_s(fileName, FILE_NAME_MAX_SIZE, FILE_NAME_MAX_SIZE - 1, "%s/%s", dirPath, dp->d_name) == -1) { - INIT_LOGE("ParseCfgs snprintf_s failed."); - closedir(pDir); - return; - } - struct stat st; - if (stat(fileName, &st) == 0) { - if (strstr(dp->d_name, ".cfg") == NULL) { - continue; - } - INIT_LOGI("ReadCfgs :%s from %s success.", fileName, dirPath); - ParseInitCfg(fileName); - } - } - closedir(pDir); - return; -} - -static void ParseOtherCfgs() -{ - ReadCfgs("/system/etc/init"); - return; -} - -void InitReadCfg() -{ -#ifndef OHOS_LITE - InitParamService(); - LoadDefaultParams("/system/etc/ohos.para"); -#endif - ParseInitCfg(INIT_CONFIGURATION_FILE); - ParseOtherCfgs(); - INIT_LOGI("Parse init config file done."); -#ifdef OHOS_SERVICE_DUMP - DumpAllServices(); -#endif - -#ifdef OHOS_LITE - // do jobs - DoJob("pre-init"); -#ifndef __LINUX__ - TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1); -#endif - - DoJob("init"); -#ifndef __LINUX__ - TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2); -#endif - - DoJob("post-init"); -#ifndef __LINUX__ - TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3); - - InitStageFinished(); -#endif - ReleaseAllJobs(); -#else - PostTrigger(EVENT_BOOT, "pre-init", strlen("pre-init")); - - PostTrigger(EVENT_BOOT, "init", strlen("init")); - - PostTrigger(EVENT_BOOT, "post-init", strlen("post-init")); -#endif -} - diff --git a/services/src/init_reboot.c b/services/src/init_reboot.c deleted file mode 100644 index e1b285c75754afa94029fb2db15dcb04bbc223b3..0000000000000000000000000000000000000000 --- a/services/src/init_reboot.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2020 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 "init_reboot.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include "securec.h" -#include "init_service.h" -#include "init_service_manager.h" -#include "init_log.h" - -#define MAX_VALUE_LENGTH 500 -#define MAX_COMMAND_SIZE 20 -#define MAX_UPDATE_SIZE 100 - -struct RBMiscUpdateMessage { - char command[MAX_COMMAND_SIZE]; - char update[MAX_UPDATE_SIZE]; -}; - -static bool RBMiscWriteUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot) -{ - if (path == NULL || boot == NULL) { - INIT_LOGE("path or boot is NULL."); - return false; - } - char *realPath = realpath(path, NULL); - if (realPath == NULL) { - return false; - } - FILE* fp = fopen(realPath, "rb+"); - if (fp == NULL) { - INIT_LOGE("open %s failed", path); - free(realPath); - realPath = NULL; - return false; - } - - size_t ret = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp); - if (ret < 0) { - INIT_LOGE("write to misc failed"); - free(realPath); - realPath = NULL; - fclose(fp); - return false; - } - free(realPath); - realPath = NULL; - fclose(fp); - return true; -} - -static bool RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot) -{ - if (path == NULL || boot == NULL) { - INIT_LOGE("path or boot is NULL."); - return false; - } - char *realPath = realpath(path, NULL); - if (realPath == NULL) { - return false; - } - FILE* fp = fopen(realPath, "rb"); - if (fp == NULL) { - INIT_LOGE("open %s failed", path); - free(realPath); - realPath = NULL; - return false; - } - - size_t ret = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp); - if (ret <= 0) { - INIT_LOGE("read to misc failed"); - free(realPath); - realPath = NULL; - fclose(fp); - return false; - } - free(realPath); - realPath = NULL; - fclose(fp); - return true; -} - -static int GetMountStatusForMountPoint(const char *mountPoint) -{ - const int bufferMaxSize = 512; - char buffer[bufferMaxSize]; - size_t n; - const char *mountFile = "/proc/mounts"; - FILE *fp = fopen(mountFile, "r"); - if (fp == NULL) { - INIT_LOGE("DoReboot %s can't open.", mountPoint); - return 1; - } - - while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) { - n = strlen(buffer); - if (buffer[n - 1] == '\n') { - buffer[n - 1] = '\0'; - } - if (strstr(buffer, mountPoint) != NULL) { - fclose(fp); - return 1; - } - } - - // Cannot find it from system. - fclose(fp); - return 0; -} - -static int UpdateUpdaterStatus(const char *valueData) -{ - const char *miscFile = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc"; - struct RBMiscUpdateMessage msg; - bool ret = RBMiscReadUpdaterMessage(miscFile, &msg); - if (!ret) { - INIT_LOGE("RBMiscReadUpdaterMessage error."); - return -1; - } - if (snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", "boot_updater") == -1) { - INIT_LOGE("RBMiscWriteUpdaterMessage error"); - return -1; - } - if (strlen(valueData) > strlen("updater:") && strncmp(valueData, "updater:", strlen("updater:")) == 0) { - if (snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", valueData + strlen("updater:")) == -1) { - INIT_LOGE("RBMiscWriteUpdaterMessage error"); - return -1; - } - ret = RBMiscWriteUpdaterMessage(miscFile, &msg); - if (ret != true) { - INIT_LOGE("RBMiscWriteUpdaterMessage error"); - return -1; - } - } else if (strlen(valueData) == strlen("updater") && strncmp(valueData, "updater", strlen("updater")) == 0) { - ret = RBMiscWriteUpdaterMessage(miscFile, &msg); - if (ret != true) { - INIT_LOGE("RBMiscWriteUpdaterMessage error"); - return -1; - } - } else { - return -1; - } - return 0; -} - -static int DoRebootCore(const char *valueData) -{ - if (valueData == NULL) { - reboot(RB_AUTOBOOT); - return 0; - } else if (strncmp(valueData, "shutdown", strlen("shutdown")) == 0) { - reboot(RB_POWER_OFF); - return 0; - } else if (strncmp(valueData, "updater", strlen("updater")) == 0) { - int ret = UpdateUpdaterStatus(valueData); - if (ret == 0) { - reboot(RB_AUTOBOOT); - return 0; - } - } else { - return -1; - } - return 0; -} - -void DoReboot(const char *value) -{ - if (value == NULL) { - INIT_LOGE("DoReboot value = NULL"); - return; - } - INIT_LOGI("DoReboot value = %s", value); - - if (strlen(value) > MAX_VALUE_LENGTH || strlen(value) < strlen("reboot") || strlen(value) == strlen("reboot,")) { - INIT_LOGE("DoReboot reboot value error, value = %s.", value); - return; - } - const char *valueData = NULL; - if (strncmp(value, "reboot,", strlen("reboot,")) == 0) { - valueData = value + strlen("reboot,"); - } else if (strlen(value) < strlen("reboot,") && strncmp(value, "reboot", strlen("reboot")) == 0) { - valueData = NULL; - } else { - INIT_LOGE("DoReboot reboot value = %s, must started with reboot ,error.", value); - return; - } - if (valueData != NULL && strncmp(valueData, "shutdown", strlen("shutdown")) != 0 && - strncmp(valueData, "updater:", strlen("updater:")) != 0 && - strncmp(valueData, "updater", strlen("updater")) != 0) { - INIT_LOGE("DoReboot value = %s, parameters error.", value); - return; - } - StopAllServicesBeforeReboot(); - if (GetMountStatusForMountPoint("/vendor") != 0) { - if (umount("/vendor") != 0) { - INIT_LOGE("DoReboot umount vendor failed! errno = %d.", errno); - } - } - if (GetMountStatusForMountPoint("/data") != 0) { - if (umount("/data") != 0) { - INIT_LOGE("DoReboot umount data failed! errno = %d.", errno); - } - } - int ret = DoRebootCore(valueData); - if (ret != 0) { - INIT_LOGE("DoReboot value = %s, error.", value); - } - return; - -} - diff --git a/services/src/init_service.c b/services/src/init_service.c deleted file mode 100644 index 248c1962d75f4ab7d9b6888592a36f895f3ee0d7..0000000000000000000000000000000000000000 --- a/services/src/init_service.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (c) 2020 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 "init_service.h" - -#include -#include -#include -#include -#include -#include -#include -#ifdef __MUSL__ -#include -#endif -#include -#ifndef OHOS_LITE -#include -#endif -#include -#include -#include - -#include "init_adapter.h" -#include "init_cmds.h" -#include "init_log.h" -#ifndef OHOS_LITE -#include "init_param.h" -#endif -#include "init_perms.h" -#include "init_service_socket.h" -#include "init_utils.h" -#include "securec.h" -#ifndef OHOS_LITE -#include "sys_param.h" -#endif - -#define CAP_NUM 2 -#define WAIT_MAX_COUNT 10 - -#ifndef TIOCSCTTY -#define TIOCSCTTY 0x540E -#endif -// 240 seconds, 4 minutes -static const int CRASH_TIME_LIMIT = 240; -// maximum number of crashes within time CRASH_TIME_LIMIT for one service -static const int CRASH_COUNT_LIMIT = 4; - -// 240 seconds, 4 minutes -static const int CRITICAL_CRASH_TIME_LIMIT = 240; -// maximum number of crashes within time CRITICAL_CRASH_TIME_LIMIT for one service -static const int CRITICAL_CRASH_COUNT_LIMIT = 4; -static const int MAX_PID_STRING_LENGTH = 50; - - -static int SetAllAmbientCapability() -{ - for (int i = 0; i <= CAP_LAST_CAP; ++i) { - if (SetAmbientCapability(i) != 0) { - return SERVICE_FAILURE; - } - } - return SERVICE_SUCCESS; -} - -static int SetPerms(const Service *service) -{ - INIT_CHECK_RETURN_VALUE(KeepCapability() == 0, SERVICE_FAILURE); - if (service->servPerm.gIDCnt > 0) { - INIT_ERROR_CHECK(setgid(service->servPerm.gIDArray[0]) == 0, return SERVICE_FAILURE, - "SetPerms, setgid for %s failed. %d", service->name, errno); - } - if (service->servPerm.gIDCnt > 1) { - INIT_ERROR_CHECK(setgroups(service->servPerm.gIDCnt - 1, &service->servPerm.gIDArray[1]) == 0, - return SERVICE_FAILURE, - "SetPerms, setgroups failed. errno = %d, gIDCnt=%d", errno, service->servPerm.gIDCnt); - } - if (service->servPerm.uID != 0) { - if (setuid(service->servPerm.uID) != 0) { - INIT_LOGE("setuid of service: %s failed, uid = %d", service->name, service->servPerm.uID); - return SERVICE_FAILURE; - } - } - - // umask call always succeeds and return the previous mask value which is not needed here - (void)umask(DEFAULT_UMASK_INIT); - - struct __user_cap_header_struct capHeader; - capHeader.version = _LINUX_CAPABILITY_VERSION_3; - capHeader.pid = 0; - - struct __user_cap_data_struct capData[CAP_NUM] = {}; - for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) { - if (service->servPerm.caps[i] == FULL_CAP) { - for (int i = 0; i < CAP_NUM; ++i) { - capData[i].effective = FULL_CAP; - capData[i].permitted = FULL_CAP; - capData[i].inheritable = FULL_CAP; - } - break; - } - capData[CAP_TO_INDEX(service->servPerm.caps[i])].effective |= CAP_TO_MASK(service->servPerm.caps[i]); - capData[CAP_TO_INDEX(service->servPerm.caps[i])].permitted |= CAP_TO_MASK(service->servPerm.caps[i]); - capData[CAP_TO_INDEX(service->servPerm.caps[i])].inheritable |= CAP_TO_MASK(service->servPerm.caps[i]); - } - - if (capset(&capHeader, capData) != 0) { - INIT_LOGE("capset faild for service: %s, error: %d", service->name, errno); - return SERVICE_FAILURE; - } - for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) { - if (service->servPerm.caps[i] == FULL_CAP) { - return SetAllAmbientCapability(); - } - if (SetAmbientCapability(service->servPerm.caps[i]) != 0) { - INIT_LOGE("SetAmbientCapability faild for service: %s", service->name); - return SERVICE_FAILURE; - } - } - return SERVICE_SUCCESS; -} - -static void OpenConsole() -{ - setsid(); - WaitForFile("/dev/console", WAIT_MAX_COUNT); - int fd = open("/dev/console", O_RDWR); - if (fd >= 0) { - ioctl(fd, TIOCSCTTY, 0); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - close(fd); - } else { - INIT_LOGE("Open /dev/console failed. err = %d", errno); - } - return; -} - -int ServiceStart(Service *service) -{ - if (service == NULL) { - INIT_LOGE("start service failed! null ptr."); - return SERVICE_FAILURE; - } - if (service->pid > 0) { - INIT_LOGI("service : %s had started already.", service->name); - return SERVICE_SUCCESS; - } - if (service->attribute & SERVICE_ATTR_INVALID) { - INIT_LOGE("start service %s invalid.", service->name); - return SERVICE_FAILURE; - } - if (service->pathArgs == NULL) { - INIT_LOGE("start service pathArgs is NULL."); - return SERVICE_FAILURE; - } - struct stat pathStat = {0}; - service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP)); - if (stat(service->pathArgs[0], &pathStat) != 0) { - service->attribute |= SERVICE_ATTR_INVALID; - INIT_LOGE("start service %s invalid, please check %s.",\ - service->name, service->pathArgs[0]); - return SERVICE_FAILURE; - } - int ret = 0; - int pid = fork(); - if (pid == 0) { - if (service->socketCfg != NULL) { // start socket service - INIT_LOGI("Create socket "); - ret = DoCreateSocket(service->socketCfg); - if (ret < 0) { - INIT_LOGE("DoCreateSocket failed. "); - _exit(0x7f); // 0x7f: user specified - } - } - if (service->attribute & SERVICE_ATTR_CONSOLE) { - OpenConsole(); - } - // permissions - if (SetPerms(service) != SERVICE_SUCCESS) { - INIT_LOGE("service %s exit! set perms failed! err %d.", service->name, errno); - _exit(0x7f); // 0x7f: user specified - } - char pidString[MAX_PID_STRING_LENGTH]; // writepid - pid_t childPid = getpid(); - if (snprintf_s(pidString, MAX_PID_STRING_LENGTH, MAX_PID_STRING_LENGTH - 1, "%d", childPid) < 0) { - INIT_LOGE("start service writepid sprintf failed."); - _exit(0x7f); // 0x7f: user specified - } - for (int i = 0; i < MAX_WRITEPID_FILES; i++) { - if (service->writepidFiles[i] == NULL) { - continue; - } - char *realPath = realpath(service->writepidFiles[i], NULL); - if (realPath == NULL) { - continue; - } - FILE *fd = fopen(realPath, "wb"); - if (fd == NULL) { - INIT_LOGE("start service writepidFiles %s invalid.", service->writepidFiles[i]); - free(realPath); - realPath = NULL; - continue; - } - if (fwrite(pidString, 1, strlen(pidString), fd) != strlen(pidString)) { - INIT_LOGE("start service writepid error.file:%s pid:%s", service->writepidFiles[i], pidString); - } - free(realPath); - realPath = NULL; - fclose(fd); - INIT_LOGE("ServiceStart writepid filename=%s, childPid=%s, ok", service->writepidFiles[i], - pidString); - } - - INIT_LOGI("service->name is %s ", service->name); -#ifndef OHOS_LITE - if (service->importance != 0) { - if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) { - INIT_LOGE("setpriority failed for %s, importance = %d", service->name, service->importance); - _exit(0x7f); // 0x7f: user specified - } - } - // L2 Can not be reset env - if (execv(service->pathArgs[0], service->pathArgs) != 0) { - INIT_LOGE("service %s execve failed! err %d.", service->name, errno); - } -#else - char* env[] = {"LD_LIBRARY_PATH=/storage/app/libs", NULL}; - if (execve(service->pathArgs[0], service->pathArgs, env) != 0) { - INIT_LOGE("service %s execve failed! err %d.", service->name, errno); - } -#endif - - _exit(0x7f); // 0x7f: user specified - } else if (pid < 0) { - INIT_LOGE("start service %s fork failed!", service->name); - return SERVICE_FAILURE; - } - - service->pid = pid; -#ifndef OHOS_LITE - char paramName[PARAM_NAME_LEN_MAX] = {0}; - if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) { - INIT_LOGE("snprintf_s paramName error %d ", errno); - } - SystemWriteParam(paramName, "running"); -#endif - return SERVICE_SUCCESS; -} - -int ServiceStop(Service *service) -{ - if (service == NULL) { - INIT_LOGE("stop service failed! null ptr."); - return SERVICE_FAILURE; - } - - service->attribute &= ~SERVICE_ATTR_NEED_RESTART; - service->attribute |= SERVICE_ATTR_NEED_STOP; - if (service->pid <= 0) { - return SERVICE_SUCCESS; - } - - if (kill(service->pid, SIGKILL) != 0) { - INIT_LOGE("stop service %s pid %d failed! err %d.", service->name, service->pid, errno); - return SERVICE_FAILURE; - } -#ifndef OHOS_LITE - char paramName[PARAM_NAME_LEN_MAX] = {0}; - if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) { - INIT_LOGE("snprintf_s paramName error %d ", errno); - } - SystemWriteParam(paramName, "stopping"); -#endif - INIT_LOGI("stop service %s, pid %d.", service->name, service->pid); - return SERVICE_SUCCESS; -} - -// the service need to be restarted, if it crashed more than 4 times in 4 minutes -void CheckCritical(Service *service) -{ - if (service == NULL) { - return; - } - if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical - // crash time and count check - time_t curTime = time(NULL); - if (service->criticalCrashCnt == 0) { - service->firstCriticalCrashTime = curTime; - ++service->criticalCrashCnt; - } else if (difftime(curTime, service->firstCriticalCrashTime) > CRITICAL_CRASH_TIME_LIMIT) { - service->firstCriticalCrashTime = curTime; - service->criticalCrashCnt = 1; - } else { - ++service->criticalCrashCnt; - if (service->criticalCrashCnt > CRITICAL_CRASH_COUNT_LIMIT) { - INIT_LOGE("reap critical service %s, crash too many times! Need reboot!", service->name); - RebootSystem(); - } - } - } -} - -static int ExecRestartCmd(const Service *service) -{ - INIT_LOGI("ExecRestartCmd "); - if ((service == NULL) || (service->onRestart == NULL) || (service->onRestart->cmdLine == NULL)) { - return SERVICE_FAILURE; - } - - for (int i = 0; i < service->onRestart->cmdNum; i++) { - INIT_LOGI("SetOnRestart cmdLine->name %s cmdLine->cmdContent %s ", service->onRestart->cmdLine[i].name, - service->onRestart->cmdLine[i].cmdContent); - DoCmd(&service->onRestart->cmdLine[i]); - } - free(service->onRestart->cmdLine); - service->onRestart->cmdLine = NULL; - free(service->onRestart); - return SERVICE_SUCCESS; -} - -void ServiceReap(Service *service) -{ - if (service == NULL) { - INIT_LOGE("reap service failed! null ptr."); - return; - } - - service->pid = -1; -#ifndef OHOS_LITE - char paramName[PARAM_NAME_LEN_MAX] = {0}; - if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) { - INIT_LOGE("snprintf_s paramName error %d ", errno); - } - SystemWriteParam(paramName, "stopped"); -#endif - if (service->attribute & SERVICE_ATTR_INVALID) { - INIT_LOGE("ServiceReap service %s invalid.", service->name); - return; - } - - // stopped by system-init itself, no need to restart even if it is not one-shot service - if (service->attribute & SERVICE_ATTR_NEED_STOP) { - service->attribute &= (~SERVICE_ATTR_NEED_STOP); - service->crashCnt = 0; - return; - } - - // for one-shot service - if (service->attribute & SERVICE_ATTR_ONCE) { - // no need to restart - if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { - service->attribute &= (~SERVICE_ATTR_NEED_STOP); - return; - } - // the service could be restart even if it is one-shot service - } - - // the service that does not need to be restarted restarts, indicating that it has crashed - if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { - // crash time and count check - time_t curTime = time(NULL); - if (service->crashCnt == 0) { - service->firstCrashTime = curTime; - ++service->crashCnt; - } else if (difftime(curTime, service->firstCrashTime) > CRASH_TIME_LIMIT) { - service->firstCrashTime = curTime; - service->crashCnt = 1; - } else { - ++service->crashCnt; - if (service->crashCnt > CRASH_COUNT_LIMIT) { - INIT_LOGE("reap service %s, crash too many times!", service->name); - return; - } - } - } - - CheckCritical(service); - int ret = 0; - if (service->onRestart != NULL) { - ret = ExecRestartCmd(service); - if (ret != SERVICE_SUCCESS) { - INIT_LOGE("SetOnRestart fail "); - } - } - ret = ServiceStart(service); - if (ret != SERVICE_SUCCESS) { - INIT_LOGE("reap service %s start failed!", service->name); - } - - service->attribute &= (~SERVICE_ATTR_NEED_RESTART); -} - diff --git a/services/src/init_service_manager.c b/services/src/init_service_manager.c deleted file mode 100644 index 8079fbe8cb7c529689003a245e9d2d720eba9e41..0000000000000000000000000000000000000000 --- a/services/src/init_service_manager.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright (c) 2020 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 "init_service_manager.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cJSON.h" -#include "init_adapter.h" -#include "init_jobs.h" -#include "init_log.h" -#include "init_perms.h" -#include "init_read_cfg.h" -#include "init_capability.h" -#include "init_service_socket.h" -#include "init_utils.h" -#include "securec.h" - -#define MIN_IMPORTANT_LEVEL (-20) -#define MAX_IMPORTANT_LEVEL 19 - -// All serivce processes that init will fork+exec. -static Service* g_services = NULL; -static int g_servicesCnt = 0; - -#ifdef OHOS_SERVICE_DUMP -void DumpAllServices() -{ - if (g_services == NULL) { - return; - } - INIT_LOGD("Ready to dump all services:"); - INIT_LOGD("total service number: %d", g_servicesCnt); - for (int i = 0; i < g_servicesCnt; i++) { - INIT_LOGD("\tservice name: [%s]", g_services[i].name); - INIT_LOGD("\tpath :"); - for (int j = 0; j < g_services[i].pathArgsCnt; j++) { - if (g_services[i].pathArgs[j] != NULL) { - INIT_LOGD(" %s", g_services[i].pathArgs[j]); - } - } - } - INIT_LOGD("Dump all services finished"); -} -#endif - -void RegisterServices(Service* services, int servicesCnt) -{ - if (services == NULL) { - return; - } - g_services = services; - g_servicesCnt += servicesCnt; -} - -static void ReleaseServiceMem(Service* curServ) -{ - if (curServ == NULL) { - return; - } - if (curServ->pathArgs != NULL) { - for (int i = 0; i < curServ->pathArgsCnt; ++i) { - if (curServ->pathArgs[i] != NULL) { - free(curServ->pathArgs[i]); - curServ->pathArgs[i] = NULL; - } - } - free(curServ->pathArgs); - curServ->pathArgs = NULL; - } - curServ->pathArgsCnt = 0; - - if (curServ->servPerm.caps != NULL) { - free(curServ->servPerm.caps); - curServ->servPerm.caps = NULL; - } - curServ->servPerm.capsCnt = 0; - for (int i = 0; i < MAX_WRITEPID_FILES; i++) { - if (curServ->writepidFiles[i] != NULL) { - free(curServ->writepidFiles[i]); - curServ->writepidFiles[i] = NULL; - } - } - - if (curServ->servPerm.gIDArray != NULL) { - free(curServ->servPerm.gIDArray); - curServ->servPerm.gIDArray = NULL; - } - curServ->servPerm.gIDCnt = 0; -} - -static int GetServiceName(const cJSON* curArrItem, Service* curServ) -{ - char* fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(curArrItem, "name")); - if (fieldStr == NULL) { - INIT_LOGE("GetServiceName cJSON_GetStringValue error"); - return SERVICE_FAILURE; - } - - size_t strLen = strlen(fieldStr); - if (strLen == 0 || strLen > MAX_SERVICE_NAME) { - INIT_LOGE("GetServiceName strLen = %d, error", strLen); - return SERVICE_FAILURE; - } - - if (memcpy_s(curServ->name, MAX_SERVICE_NAME, fieldStr, strLen) != EOK) { - INIT_LOGE("GetServiceName memcpy_s error"); - return SERVICE_FAILURE; - } - curServ->name[strLen] = '\0'; - return SERVICE_SUCCESS; -} - -#ifdef OHOS_LITE -static int IsForbidden(const char* fieldStr) -{ - size_t fieldLen = strlen(fieldStr); - size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED); - if (fieldLen == forbidStrLen) { - if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) { - return 1; - } - return 0; - } else if (fieldLen > forbidStrLen) { - // "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid - if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) { - if (fieldStr[forbidStrLen] == ' ') { - return 1; - } - } - return 0; - } else { - return 0; - } -} -#else -static int IsForbidden(const char* fieldStr) -{ - return 0; -} -#endif - -// TODO: move this function to common files -static cJSON* GetArrItem(const cJSON* fileRoot, int* arrSize, const char* arrName) -{ - cJSON* arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName); - if (!cJSON_IsArray(arrItem)) { - return NULL; - } - - *arrSize = cJSON_GetArraySize(arrItem); - if (*arrSize <= 0) { - return NULL; - } - return arrItem; -} - -static int GetWritepidStrings(const cJSON *curArrItem, Service *curServ) // writepid -{ - int writepidCnt = 0; - cJSON *filedJ = GetArrItem(curArrItem, &writepidCnt, "writepid"); - if ((writepidCnt <= 0) || (filedJ == NULL)) { // not item is ok. - return SERVICE_SUCCESS; - } - - if (writepidCnt > MAX_WRITEPID_FILES) { - INIT_LOGE("GetWritepidStrings, too many writepid[cnt %d] for one service, should not exceed %d.", - writepidCnt, MAX_WRITEPID_FILES); - return SERVICE_FAILURE; - } - - for (int i = 0; i < writepidCnt; ++i) { - cJSON *item = cJSON_GetArrayItem(filedJ, i); - if (item == NULL) { - return SERVICE_FAILURE; - } - char *fieldStr = cJSON_GetStringValue(item); - if ((fieldStr == NULL) || (fieldStr[0] == '\0')) { - return SERVICE_FAILURE; - } - size_t strLen = strlen(fieldStr); - curServ->writepidFiles[i] = (char *)malloc(sizeof(char) * strLen + 1); - if (curServ->writepidFiles[i] == NULL) { - INIT_LOGE("GetWritepidStrings, malloc item[%d] error.", i); - return SERVICE_FAILURE; - } - if (memcpy_s(curServ->writepidFiles[i], strLen + 1, fieldStr, strLen) != EOK) { - INIT_LOGE("GetWritepidStrings, memcpy_s error."); - return SERVICE_FAILURE; - } - curServ->writepidFiles[i][strLen] = '\0'; - } - - return SERVICE_SUCCESS; -} - -static int GetGidOneItem(const cJSON *curArrItem, Service *curServ) // gid one item -{ - cJSON *filedJ = cJSON_GetObjectItem(curArrItem, GID_STR_IN_CFG); - if (filedJ == NULL) { - return SERVICE_SUCCESS; // not found - } - curServ->servPerm.gIDCnt = 1; - curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t)); - if (curServ->servPerm.gIDArray == NULL) { - INIT_LOGE("GetGidOneItem, can't malloc, error."); - return SERVICE_FAILURE; - } - - if (cJSON_IsString(filedJ)) { - char *fieldStr = cJSON_GetStringValue(filedJ); - if (fieldStr == NULL) { - return SERVICE_FAILURE; - } - gid_t gID = DecodeUid(fieldStr); - if (gID == (gid_t)(-1)) { - INIT_LOGE("GetGidOneItem, DecodeUid %s error.", fieldStr); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray[0] = gID; - return SERVICE_SUCCESS; - } - - if (cJSON_IsNumber(filedJ)) { - gid_t gID = (int)cJSON_GetNumberValue(filedJ); - if (gID < 0) { - INIT_LOGE("GetGidOneItem, gID = %d error.", gID); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray[0] = gID; - return SERVICE_SUCCESS; - } - - INIT_LOGE("GetGidOneItem, this gid is neither a string nor a number, error."); - return SERVICE_FAILURE; -} - -static int GetGidArray(const cJSON *curArrItem, Service *curServ) // gid array -{ - int gIDCnt = 0; - cJSON *filedJ = GetArrItem(curArrItem, &gIDCnt, GID_STR_IN_CFG); // "gid" must have 1 item. - if ((gIDCnt <= 0) || (filedJ == NULL)) { // not a array, but maybe a item? - return GetGidOneItem(curArrItem, curServ); - } - - if (gIDCnt > NGROUPS_MAX + 1) { - INIT_LOGE("GetGidArray, too many gids[cnt %d] for one service, should not exceed %d.", - gIDCnt, NGROUPS_MAX + 1); - return SERVICE_FAILURE; - } - - curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gIDCnt); - if (curServ->servPerm.gIDArray == NULL) { - INIT_LOGE("GetGidArray malloc error"); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDCnt = gIDCnt; - int i = 0; - for (; i < gIDCnt; ++i) { - cJSON *item = cJSON_GetArrayItem(filedJ, i); - if (item == NULL) { - break; - } - char *fieldStr = cJSON_GetStringValue(item); - if ((fieldStr == NULL) || (fieldStr[0] == '\0')) { - break; - } - gid_t gID = DecodeUid(fieldStr); - if ((gID) == (gid_t)(-1)) { - INIT_LOGE("GetGidArray, DecodeUid item[%d] error.", i); - return SERVICE_FAILURE; - } - curServ->servPerm.gIDArray[i] = gID; - } - if (i == gIDCnt) { - return SERVICE_SUCCESS; - } - for (i = 0; i < gIDCnt; ++i) { - cJSON *item = cJSON_GetArrayItem(filedJ, i); - if (item == NULL) { - break; - } - if (!cJSON_IsNumber(item)) { - break; - } - gid_t gID = (int)cJSON_GetNumberValue(item); - if (gID < 0) { - INIT_LOGE("GetGidArray gID = %d, error", gID); - break; - } - curServ->servPerm.gIDArray[i] = gID; - } - int ret = i == gIDCnt ? SERVICE_SUCCESS : SERVICE_FAILURE; - return ret; -} - -static int GetServicePathAndArgs(const cJSON* curArrItem, Service* curServ) -{ - cJSON* pathItem = cJSON_GetObjectItem(curArrItem, "path"); - if (!cJSON_IsArray(pathItem)) { - INIT_LOGE("GetServicePathAndArgs path item not found or not a array"); - return SERVICE_FAILURE; - } - - int arrSize = cJSON_GetArraySize(pathItem); - if (arrSize <= 0 || arrSize > MAX_PATH_ARGS_CNT) { // array size invalid - INIT_LOGE("GetServicePathAndArgs arrSize = %d, error", arrSize); - return SERVICE_FAILURE; - } - - curServ->pathArgs = (char**)malloc((arrSize + 1) * sizeof(char*)); - if (curServ->pathArgs == NULL) { - INIT_LOGE("GetServicePathAndArgs malloc 1 error"); - return SERVICE_FAILURE; - } - for (int i = 0; i < arrSize + 1; ++i) { - curServ->pathArgs[i] = NULL; - } - curServ->pathArgsCnt = arrSize + 1; - - for (int i = 0; i < arrSize; ++i) { - char* curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathItem, i)); - if (curParam == NULL || strlen(curParam) > MAX_ONE_ARG_LEN) { - // resources will be released by function: ReleaseServiceMem - if (curParam == NULL) { - INIT_LOGE("GetServicePathAndArgs curParam == NULL, error"); - } else { - INIT_LOGE("GetServicePathAndArgs strlen = %d, error", strlen(curParam)); - } - return SERVICE_FAILURE; - } - - if (i == 0 && IsForbidden(curParam)) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("GetServicePathAndArgs i == 0 && IsForbidden, error"); - return SERVICE_FAILURE; - } - - size_t paramLen = strlen(curParam); - curServ->pathArgs[i] = (char*)malloc(paramLen + 1); - if (curServ->pathArgs[i] == NULL) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("GetServicePathAndArgs i == 0 && IsForbidden, error"); - return SERVICE_FAILURE; - } - - if (memcpy_s(curServ->pathArgs[i], paramLen + 1, curParam, paramLen) != EOK) { - // resources will be released by function: ReleaseServiceMem - INIT_LOGE("GetServicePathAndArgs malloc 2 error."); - return SERVICE_FAILURE; - } - curServ->pathArgs[i][paramLen] = '\0'; - } - return SERVICE_SUCCESS; -} - -static int GetImportantValue(int value, Service *curServ) -{ -#ifdef OHOS_LITE - if (value != 0) { - curServ->attribute |= SERVICE_ATTR_IMPORTANT; - } -#else - if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19 - curServ->importance = value; - } else { - INIT_LOGE("importance level = %d, is not between -20 and 19, error", value); - return SERVICE_FAILURE; - } -#endif - return SERVICE_SUCCESS; -} - -static int GetServiceNumber(const cJSON* curArrItem, Service* curServ, const char* targetField) -{ - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, targetField); - if (filedJ == NULL && (strncmp(targetField, CRITICAL_STR_IN_CFG, strlen(CRITICAL_STR_IN_CFG)) == 0 - || strncmp(targetField, DISABLED_STR_IN_CFG, strlen(DISABLED_STR_IN_CFG)) == 0 - || strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0 - || strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0 - || strncmp(targetField, CONSOLE_STR_IN_CFG, strlen(CONSOLE_STR_IN_CFG)) == 0)) { - return SERVICE_SUCCESS; // not found "critical","disabled","once","importance","console" item is ok - } - - if (!cJSON_IsNumber(filedJ)) { - INIT_LOGE("%s is null or is not a number, error.service name is %s", targetField, curServ->name); - return SERVICE_FAILURE; - } - - int value = (int)cJSON_GetNumberValue(filedJ); - // importance value allow < 0 - if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) != 0) { - if (value < 0) { - INIT_LOGE("value = %d, error.service name is %s", value, curServ->name); - return SERVICE_FAILURE; - } - } - - if (strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0) { - if (value != 0) { - curServ->attribute |= SERVICE_ATTR_ONCE; - } - } else if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0) { - INIT_CHECK_RETURN_VALUE(GetImportantValue(value, curServ) == SERVICE_SUCCESS, SERVICE_FAILURE); - } else if (strncmp(targetField, CRITICAL_STR_IN_CFG, strlen(CRITICAL_STR_IN_CFG)) == 0) { // set critical - curServ->attribute &= ~SERVICE_ATTR_CRITICAL; - if (value == 1) { - curServ->attribute |= SERVICE_ATTR_CRITICAL; - } - } else if (strncmp(targetField, DISABLED_STR_IN_CFG, strlen(DISABLED_STR_IN_CFG)) == 0) { // set disabled - curServ->attribute &= ~SERVICE_ATTR_DISABLED; - if (value == 1) { - curServ->attribute |= SERVICE_ATTR_DISABLED; - } - } else if (strncmp(targetField, CONSOLE_STR_IN_CFG, strlen(CONSOLE_STR_IN_CFG)) == 0) { // set console - curServ->attribute &= ~SERVICE_ATTR_CONSOLE; - if (value == 1) { - curServ->attribute |= SERVICE_ATTR_CONSOLE; - } - } else { - INIT_LOGE("item = %s, not expected, error.service name is %s", targetField, curServ->name); - return SERVICE_FAILURE; - } - return SERVICE_SUCCESS; -} - -static int GetUidStringNumber(const cJSON *curArrItem, Service *curServ) -{ - cJSON *filedJ = cJSON_GetObjectItem(curArrItem, UID_STR_IN_CFG); - if (filedJ == NULL) { - return SERVICE_SUCCESS; // uID not found, but ok. - } - - if (cJSON_IsString(filedJ)) { - char *fieldStr = cJSON_GetStringValue(filedJ); - if (fieldStr == NULL) { - return SERVICE_FAILURE; - } - int uID = DecodeUid(fieldStr); - if (uID < 0) { - INIT_LOGE("GetUidStringNumber, DecodeUid %s error.", fieldStr); - return SERVICE_FAILURE; - } - curServ->servPerm.uID = uID; - return SERVICE_SUCCESS; - } - - if (cJSON_IsNumber(filedJ)) { - int uID = (int)cJSON_GetNumberValue(filedJ); - if (uID < 0) { - INIT_LOGE("GetUidStringNumber, uID = %d error.", uID); - return SERVICE_FAILURE; - } - curServ->servPerm.uID = uID; - return SERVICE_SUCCESS; - } - - INIT_LOGE("GetUidStringNumber, this uid is neither a string nor a number, error."); - return SERVICE_FAILURE; -} - -static int ParseServiceSocket(char **opt, const int optNum, struct ServiceSocket *sockopt) -{ - if (optNum != SOCK_OPT_NUMS) { - return -1; - } - if (opt[SERVICE_SOCK_TYPE] == NULL) { - return -1; - } - sockopt->type = - strncmp(opt[SERVICE_SOCK_TYPE], "stream", strlen(opt[SERVICE_SOCK_TYPE])) == 0 ? SOCK_STREAM : - (strncmp(opt[SERVICE_SOCK_TYPE], "dgram", strlen(opt[SERVICE_SOCK_TYPE])) == 0 ? SOCK_DGRAM : SOCK_SEQPACKET); - - if (opt[SERVICE_SOCK_PERM] == NULL) { - return -1; - } - sockopt->perm = strtoul(opt[SERVICE_SOCK_PERM], 0, OCTAL_BASE); - if (opt[SERVICE_SOCK_UID] == NULL) { - return -1; - } - int uuid = DecodeUid(opt[SERVICE_SOCK_UID]); - if (uuid < 0) { - return -1; - } - sockopt->uid = uuid; - if (opt[SERVICE_SOCK_GID] == NULL) { - return -1; - } - int ggid = DecodeUid(opt[SERVICE_SOCK_GID]); - if (ggid < 0) { - return -1; - } - sockopt->gid = ggid; - if (opt[SERVICE_SOCK_SETOPT] == NULL) { - return -1; - } - sockopt->passcred = strncmp(opt[SERVICE_SOCK_SETOPT], "passcred", strlen(opt[SERVICE_SOCK_SETOPT])) == 0 ? true : false; - if (opt[SERVICE_SOCK_NAME] == NULL) { - return -1; - } - sockopt->name = (char *)calloc(MAX_SOCK_NAME_LEN, sizeof(char)); - if (sockopt->name == NULL) { - return -1; - } - int ret = memcpy_s(sockopt->name, MAX_SOCK_NAME_LEN, opt[SERVICE_SOCK_NAME], MAX_SOCK_NAME_LEN - 1); - if (ret != 0) { - free(sockopt->name); - sockopt->name = NULL; - return -1; - } - sockopt->next = NULL; - sockopt->sockFd = -1; - return 0; -} - -static void FreeServiceSocket(struct ServiceSocket *sockopt) -{ - if (!sockopt) { - return; - } - struct ServiceSocket *tmpSock = NULL; - while (sockopt) { - tmpSock = sockopt; - if (sockopt->name != NULL) { - free(sockopt->name); - sockopt->name = NULL; - } - sockopt = tmpSock->next; - free(tmpSock); - } - return; -} -static int GetServiceSocket(const cJSON* curArrItem, Service* curServ) -{ - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "socket"); - if (!cJSON_IsArray(filedJ)) { - return SERVICE_FAILURE; - } - - int sockCnt = cJSON_GetArraySize(filedJ); - if (sockCnt <= 0) { - return SERVICE_FAILURE; - } - curServ->socketCfg = NULL; - for (int i = 0; i < sockCnt; ++i) { - cJSON *sockJ = cJSON_GetArrayItem(filedJ, i); - if (!cJSON_IsString(sockJ) || !cJSON_GetStringValue(sockJ)) { - return SERVICE_FAILURE; - } - char *sockStr = cJSON_GetStringValue(sockJ); - char *tmpStr[SOCK_OPT_NUMS] = {NULL,}; - int num = SplitString(sockStr, tmpStr, SOCK_OPT_NUMS); - if (num != SOCK_OPT_NUMS) { - return SERVICE_FAILURE; - } - struct ServiceSocket *socktmp = (struct ServiceSocket *)calloc(1, sizeof(struct ServiceSocket)); - if (!socktmp) { - return SERVICE_FAILURE; - } - int ret = ParseServiceSocket(tmpStr, SOCK_OPT_NUMS, socktmp); - if (ret < 0) { - free(socktmp); - socktmp = NULL; - return SERVICE_FAILURE; - } - if (curServ->socketCfg == NULL) { - curServ->socketCfg = socktmp; - } else { - socktmp->next = curServ->socketCfg->next; - curServ->socketCfg->next = socktmp; - } - } - return SERVICE_SUCCESS; -} - -static int GetServiceOnRestart(const cJSON* curArrItem, Service* curServ) -{ - cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "onrestart"); - if (filedJ == NULL) { - return SERVICE_SUCCESS; // onrestart not found, but ok. - } - if (!cJSON_IsArray(filedJ)) { - return SERVICE_FAILURE; - } - int cmdCnt = cJSON_GetArraySize(filedJ); - if (cmdCnt <= 0) { - return SERVICE_FAILURE; - } - curServ->onRestart = (struct OnRestartCmd *)calloc(1, sizeof(struct OnRestartCmd)); - if (curServ->onRestart == NULL) { - return SERVICE_FAILURE; - } - curServ->onRestart->cmdLine = (CmdLine *)calloc(cmdCnt, sizeof(CmdLine)); - if (curServ->onRestart->cmdLine == NULL) { - free(curServ->onRestart); - curServ->onRestart = NULL; - return SERVICE_FAILURE; - } - curServ->onRestart->cmdNum = cmdCnt; - for (int i = 0; i < cmdCnt; ++i) { - cJSON* cmdJ = cJSON_GetArrayItem(filedJ, i); - if (!cJSON_IsString(cmdJ) || !cJSON_GetStringValue(cmdJ)) { - free(curServ->onRestart->cmdLine); - curServ->onRestart->cmdLine = NULL; - free(curServ->onRestart); - curServ->onRestart = NULL; - return SERVICE_FAILURE; - } - char *cmdStr = cJSON_GetStringValue(cmdJ); - ParseCmdLine(cmdStr, &curServ->onRestart->cmdLine[i]); - } - return SERVICE_SUCCESS; -} - -static int CheckServiceKeyName(const cJSON* curService) -{ - char *cfgServiceKeyList[] = {"name", "path", "uid", "gid", "once", - "importance", "caps", "disabled", "writepid", "critical", "socket", "console" - }; - if (curService == NULL) { - return SERVICE_FAILURE; - } - cJSON *child = curService->child; - if (child == NULL) { - return SERVICE_FAILURE; - } - while (child) { - int i = 0; - int keyListSize = sizeof(cfgServiceKeyList) / sizeof(char *); - for (; i < keyListSize; i++) { - if (!strcmp(child->string, cfgServiceKeyList[i])) { - break; - } - } - if(i < keyListSize) { - child = child->next; - } else { - INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string); - return SERVICE_FAILURE; - } - } - return SERVICE_SUCCESS; -} - -void ParseAllServices(const cJSON* fileRoot) -{ - int servArrSize = 0; - cJSON* serviceArr = GetArrItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON); - if (serviceArr == NULL) { - INIT_LOGI("ParseAllServices, this config does not contain service array."); - return; - } - - if (servArrSize > MAX_SERVICES_CNT_IN_FILE) { - INIT_LOGE("ParseAllServices, too many services[cnt %d] detected, should not exceed %d.", - servArrSize, MAX_SERVICES_CNT_IN_FILE); - return; - } - if ((g_servicesCnt + servArrSize) <= 0) { - return; - } - Service* retServices = (Service*)realloc(g_services, sizeof(Service) * (g_servicesCnt + servArrSize)); - if (retServices == NULL) { - INIT_LOGE("ParseAllServices, realloc for %s arr failed! %d.", SERVICES_ARR_NAME_IN_JSON, servArrSize); - return; - } - // Skip already saved services, - Service* tmp = retServices + g_servicesCnt; - if (memset_s(tmp, sizeof(Service) * servArrSize, 0, sizeof(Service) * servArrSize) != EOK) { - free(retServices); - retServices = NULL; - return; - } - - for (int i = 0; i < servArrSize; ++i) { - cJSON* curItem = cJSON_GetArrayItem(serviceArr, i); - if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { - ReleaseServiceMem(&tmp[i]); - tmp[i].attribute |= SERVICE_ATTR_INVALID; - continue; - } - int ret1 = GetServiceName(curItem, &tmp[i]); - int ret2 = GetServicePathAndArgs(curItem, &tmp[i]); - int ret3 = GetUidStringNumber(curItem, &tmp[i]); // uid in string or number form - int ret4 = GetGidArray(curItem, &tmp[i]); // gid array - int ret5 = GetServiceNumber(curItem, &tmp[i], ONCE_STR_IN_CFG); - int ret6 = GetServiceNumber(curItem, &tmp[i], IMPORTANT_STR_IN_CFG); - int ret7 = GetServiceNumber(curItem, &tmp[i], CRITICAL_STR_IN_CFG); // critical - int ret8 = GetServiceNumber(curItem, &tmp[i], DISABLED_STR_IN_CFG); // disabled - int ret9 = GetServiceNumber(curItem, &tmp[i], CONSOLE_STR_IN_CFG); // console - int reta = GetWritepidStrings(curItem, &tmp[i]); // writepid - int retb = GetServiceCaps(curItem, &tmp[i]); - int retAll = ret1 | ret2 | ret3 | ret4 | ret5 | ret6 | ret7 | ret8 | ret9 | reta | retb; - if (retAll != SERVICE_SUCCESS) { - // release resources if it fails - ReleaseServiceMem(&tmp[i]); - tmp[i].attribute |= SERVICE_ATTR_INVALID; - INIT_LOGE("ParseAllServices, parse information for service %s failed. ", tmp[i].name); - continue; - } else { - INIT_LOGD("ParseAllServices ParseAllServices Service[%d] name=%s, uid=%d, critical=%d, disabled=%d", - i, tmp[i].name, tmp[i].servPerm.uID, tmp[i].attribute & SERVICE_ATTR_CRITICAL ? 1 : 0, - tmp[i].attribute & SERVICE_ATTR_DISABLED ? 1 : 0); - } - if (GetServiceSocket(curItem, &tmp[i]) != SERVICE_SUCCESS) { - if (tmp[i].socketCfg != NULL) { - FreeServiceSocket(tmp[i].socketCfg); - tmp[i].socketCfg = NULL; - } - } - (void)GetServiceOnRestart(curItem, &tmp[i]); - } - // Increase service counter. - RegisterServices(retServices, servArrSize); -} - -static int FindServiceByName(const char* servName) -{ - if ((servName == NULL) || (g_services == NULL)) { - return -1; - } - - for (int i = 0; i < g_servicesCnt; ++i) { - if (strlen(g_services[i].name) == strlen(servName) && - strncmp(g_services[i].name, servName, strlen(g_services[i].name)) == 0) { - return i; - } - } - return -1; -} - -void StartServiceByName(const char* servName) -{ - // find service by name - int servIdx = FindServiceByName(servName); - if (servIdx < 0) { - INIT_LOGE("StartServiceByName, cannot find service %s.", servName); - return; - } - - if (ServiceStart(&g_services[servIdx]) != SERVICE_SUCCESS) { - INIT_LOGE("StartServiceByName, service %s start failed!", g_services[servIdx].name); - } - - return; -} - -void StopServiceByName(const char* servName) -{ - // find service by name - int servIdx = FindServiceByName(servName); - if (servIdx < 0) { - INIT_LOGE("StopServiceByName, cannot find service %s.", servName); - return; - } - - if (ServiceStop(&g_services[servIdx]) != SERVICE_SUCCESS) { - INIT_LOGE("StopServiceByName, service %s start failed!", g_services[servIdx].name); - } - - return; -} - -void StopAllServices() -{ - if (g_services == NULL) { - return; - } - - for (int i = 0; i < g_servicesCnt; i++) { - if (ServiceStop(&g_services[i]) != SERVICE_SUCCESS) { - INIT_LOGE("StopAllServices, service %s stop failed!", g_services[i].name); - } - } -} - -void StopAllServicesBeforeReboot() -{ - if (g_services == NULL) { - return; - } - - for (int i = 0; i < g_servicesCnt; i++) { - g_services[i].attribute |= SERVICE_ATTR_INVALID; - if (ServiceStop(&g_services[i]) != SERVICE_SUCCESS) { - INIT_LOGE("StopAllServicesBeforeReboot, service %s stop failed!", g_services[i].name); - } - } -} - -void ReapServiceByPID(int pid) -{ - if (g_services == NULL) { - return; - } - - for (int i = 0; i < g_servicesCnt; i++) { - if (g_services[i].pid == pid) { -#ifdef OHOS_LITE - if (g_services[i].attribute & SERVICE_ATTR_IMPORTANT) { - // important process exit, need to reboot system - g_services[i].pid = -1; - StopAllServices(); - RebootSystem(); - } -#endif - ServiceReap(&g_services[i]); - break; - } - } -} - - diff --git a/services/src/init_service_socket.c b/services/src/init_service_socket.c deleted file mode 100644 index f6d9720c249c1014c62f53b8d06f5384c091b9e1..0000000000000000000000000000000000000000 --- a/services/src/init_service_socket.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2021 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 "init_service_socket.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "init_log.h" -#include "securec.h" - -#define HOS_SOCKET_DIR "/dev/unix/socket" -#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_" -#define MAX_SOCKET_ENV_PREFIX_LEN 64 -#define MAX_SOCKET_FD_LEN 16 - -static int CreateSocket(struct ServiceSocket *sockopt) -{ - if (!sockopt || !sockopt->name) { - return -1; - } - if (sockopt->sockFd >= 0) { - close(sockopt->sockFd); - sockopt->sockFd = -1; - } - sockopt->sockFd = socket(PF_UNIX, sockopt->type, 0); - if (sockopt->sockFd < 0) { - INIT_LOGE("socket fail %d ", errno); - return -1; - } - - struct sockaddr_un addr; - bzero(&addr,sizeof(addr)); - addr.sun_family = AF_UNIX; - if (snprintf_s(addr.sun_path, sizeof(addr.sun_path), sizeof(addr.sun_path) - 1, HOS_SOCKET_DIR"/%s", - sockopt->name) < 0) { - return -1; - } - if (access(addr.sun_path, F_OK)) { - INIT_LOGE("%s already exist, remove it", addr.sun_path); - if (unlink(addr.sun_path) != 0) { - INIT_LOGE("ulink fail err %d ", errno); - } - } - if (sockopt->passcred) { - int on = 1; - if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) { - unlink(addr.sun_path); - close(sockopt->sockFd); - return -1; - } - } - - if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) { - INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno); - unlink(addr.sun_path); - close(sockopt->sockFd); - return -1; - } - - if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) { - unlink(addr.sun_path); - close(sockopt->sockFd); - INIT_LOGE("lchown fail %d ", errno); - return -1; - } - - if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) { - unlink(addr.sun_path); - close(sockopt->sockFd); - INIT_LOGE("fchmodat fail %d ", errno); - return -1; - } - INIT_LOGI("CreateSocket success "); - return sockopt->sockFd; -} - -static int SetSocketEnv(int fd, const char *name) -{ - if (name == NULL) { - return -1; - } - char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = {0}; - char val[MAX_SOCKET_FD_LEN] = {0}; - if (snprintf_s(pubName, MAX_SOCKET_ENV_PREFIX_LEN, MAX_SOCKET_ENV_PREFIX_LEN - 1, - HOS_SOCKET_ENV_PREFIX"%s", name) < 0) { - return -1; - } - if (snprintf_s(val, MAX_SOCKET_FD_LEN, MAX_SOCKET_FD_LEN - 1, "%d", fd) < 0) { - return -1; - } - int ret = setenv(pubName, val, 1); - if (ret < 0) { - INIT_LOGE("setenv fail %d ", errno); - return -1; - } - fcntl(fd, F_SETFD, 0); - return 0; -} - -int DoCreateSocket(struct ServiceSocket *sockopt) -{ - if (!sockopt) { - return -1; - } - struct ServiceSocket *tmpSock = sockopt; - while (tmpSock) { - int fd = CreateSocket(tmpSock); - if (fd < 0) { - return -1; - } - if (tmpSock->name == NULL) { - return -1; - } - int ret = SetSocketEnv(fd, tmpSock->name); - if (ret < 0) { - return -1; - } - tmpSock = tmpSock->next; - } - return 0; -} - diff --git a/services/src/init_utils.c b/services/src/init_utils.c deleted file mode 100644 index f1dba38a040d2f80527d30f0effbfea289cacff6..0000000000000000000000000000000000000000 --- a/services/src/init_utils.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2021 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 "init_utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "init_log.h" -#include "init_utils.h" -#include "securec.h" - -#define WAIT_MAX_COUNT 10 -#define MAX_BUF_SIZE 1024 -#ifdef STARTUP_UT -#define LOG_FILE_NAME "/media/sf_ubuntu/test/log.txt" -#else -#define LOG_FILE_NAME "/data/startup_log.txt" -#endif - -#define MAX_JSON_FILE_LEN 102400 // max init.cfg size 100KB -#define CONVERT_MICROSEC_TO_SEC(x) ((x) / 1000 / 1000.0) - -int DecodeUid(const char *name) -{ - if (name == NULL) { - return -1; - } - bool digitFlag = true; - for (unsigned int i = 0; i < strlen(name); ++i) { - if (isalpha(name[i])) { - digitFlag = false; - break; - } - } - if (digitFlag) { - errno = 0; - uid_t result = strtoul(name, 0, 10); - if (errno != 0) { - return -1; - } - return result; - } else { - struct passwd *userInf = getpwnam(name); - if (userInf == NULL) { - return -1; - } - return userInf->pw_uid; - } -} - -void CheckAndCreateDir(const char *fileName) -{ - if (fileName == NULL || *fileName == '\0') { - return; - } - char *path = strndup(fileName, strrchr(fileName, '/') - fileName); - if (path != NULL && access(path, F_OK) != 0) { - mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - } - free(path); -} - -char* ReadFileToBuf(const char *configFile) -{ - char* buffer = NULL; - FILE* fd = NULL; - struct stat fileStat = {0}; - if (configFile == NULL || *configFile == '\0') { - return NULL; - } - - do { - if (stat(configFile, &fileStat) != 0 || - fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) { - INIT_LOGE("Unexpected config file \" %s \", check if it exist. if exist, check file size", configFile); - break; - } - fd = fopen(configFile, "r"); - if (fd == NULL) { - INIT_LOGE("Open %s failed. err = %d", configFile, errno); - break; - } - buffer = (char*)malloc((size_t)(fileStat.st_size + 1)); - if (buffer == NULL) { - INIT_LOGE("Failed to allocate memory for config file, err = %d", errno); - break; - } - - if (fread(buffer, fileStat.st_size, 1, fd) != 1) { - free(buffer); - buffer = NULL; - break; - } - buffer[fileStat.st_size] = '\0'; - } while (0); - - if (fd != NULL) { - fclose(fd); - fd = NULL; - } - return buffer; -} - -int SplitString(char *srcPtr, char **dstPtr, int maxNum) -{ - if ((!srcPtr) || (!dstPtr)){ - return -1; - } - char *buf = NULL; - dstPtr[0] = strtok_r(srcPtr, " ", &buf); - int counter = 0; - while (dstPtr[counter] != NULL && (counter < maxNum)) { - counter++; - dstPtr[counter] = strtok_r(NULL, " ", &buf); - } - dstPtr[counter] = NULL; - return counter; -} - -void WaitForFile(const char *source, unsigned int maxCount) -{ - if (maxCount > WAIT_MAX_COUNT) { - INIT_LOGE("WaitForFile max time is 5s"); - maxCount = WAIT_MAX_COUNT; - } - struct stat sourceInfo; - const unsigned int waitTime = 500000; - unsigned int count = 0; - do { - usleep(waitTime); - count++; - } while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < maxCount)); - if (count == maxCount) { - INIT_LOGE("wait for file:%s failed after %f.", source, maxCount * CONVERT_MICROSEC_TO_SEC(waitTime)); - } - return; -} - diff --git a/services/src/main.c b/services/src/main.c deleted file mode 100644 index 8c027bcd21ab8b261475685dadd9f2774bc81d82..0000000000000000000000000000000000000000 --- a/services/src/main.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2020 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 - -#ifdef OHOS_DEBUG -#include -#endif // OHOS_DEBUG - -#include - -#include "init_adapter.h" -#include "init_log.h" -#include "init_read_cfg.h" -#include "init_signal_handler.h" -#ifdef OHOS_LITE -#include "parameter.h" -#endif - -#ifndef OHOS_LITE -#include "device.h" -#include "init_param.h" -#endif - -static const pid_t INIT_PROCESS_PID = 1; - -static void PrintSysInfo() -{ -#ifdef OHOS_LITE - const char* sysInfo = GetVersionId(); - if (sysInfo != NULL) { - INIT_LOGE("%s", sysInfo); - return; - } - INIT_LOGE("main, GetVersionId failed!"); -#endif -} - -#ifdef OHOS_DEBUG -static long TimeDiffMs(const struct timespec* tmBefore, const struct timespec* tmAfter) -{ - if (tmBefore != NULL && tmAfter != NULL) { - long timeUsed = (tmAfter->tv_sec - tmBefore->tv_sec) * 1000 + // 1 s = 1000 ms - (tmAfter->tv_nsec - tmBefore->tv_nsec) / 1000000L; // 1 ms = 1000000 ns - return timeUsed; - } - return -1; -} -#endif // OHOS_DEBUG - -int main(int argc, char **argv) -{ -#ifndef OHOS_LITE - if(setenv("UV_THREADPOOL_SIZE", "1", 1) != 0) { - INIT_LOGE("set UV_THREADPOOL_SIZE error : %d.", errno); - } - - CloseStdio(); - OpenLogDevice(); - -#endif -#ifdef OHOS_DEBUG - struct timespec tmEnter; - if (clock_gettime(CLOCK_REALTIME, &tmEnter) != 0) { - INIT_LOGE("main, enter, get time failed! err %d.\n", errno); - } -#endif // OHOS_DEBUG - - if (getpid() != INIT_PROCESS_PID) { - INIT_LOGE("main, current process id is %d not %d, failed!", getpid(), INIT_PROCESS_PID); - return 0; - } - - // 1. print system info - PrintSysInfo(); - -#ifndef OHOS_LITE - // 2. Mount basic filesystem and create common device node. - MountBasicFs(); - CreateDeviceNode(); - EnableDevKmsg(); - MakeSocketDir("/dev/unix/socket/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); -#endif - - // 3. signal register - SignalInitModule(); - -#ifdef OHOS_DEBUG - struct timespec tmSysInfo; - if (clock_gettime(CLOCK_REALTIME, &tmSysInfo) != 0) { - INIT_LOGE("main, after sysinfo, get time failed! err %d.", errno); - } -#endif // OHOS_DEBUG - - // 4. execute rcs - ExecuteRcs(); - -#ifdef OHOS_DEBUG - struct timespec tmRcs; - if (clock_gettime(CLOCK_REALTIME, &tmRcs) != 0) { - INIT_LOGE("main, after rcs, get time failed! err %d.", errno); - } -#endif // OHOS_DEBUG - // 5. read configuration file and do jobs - InitReadCfg(); -#ifdef OHOS_DEBUG - struct timespec tmCfg; - if (clock_gettime(CLOCK_REALTIME, &tmCfg) != 0) { - INIT_LOGE("main, get time failed! err %d.", errno); - } -#endif // OHOS_DEBUG - - // 6. keep process alive -#ifdef OHOS_DEBUG - INIT_LOGI("main, time used: sigInfo %ld ms, rcs %ld ms, cfg %ld ms.", \ - TimeDiffMs(&tmEnter, &tmSysInfo), TimeDiffMs(&tmSysInfo, &tmRcs), TimeDiffMs(&tmRcs, &tmCfg)); -#endif - - INIT_LOGI("main, entering wait."); -#ifndef OHOS_LITE - StartParamService(); -#endif - while (1) { - // pause only returns when a signal was caught and the signal-catching function returned. - // pause only returns -1, no need to process the return value. - (void)pause(); - } - return 0; -} diff --git a/services/test/unittest/common/BUILD.gn b/services/test/unittest/common/BUILD.gn deleted file mode 100644 index 066f0dd531f0346a7c1caba5103a161b897194f5..0000000000000000000000000000000000000000 --- a/services/test/unittest/common/BUILD.gn +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (c) 2020 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. -if (defined(ohos_lite)) { - import("//build/lite/config/component/lite_component.gni") - import("//build/lite/config/test.gni") - - unittest("init_test") { - output_extension = "bin" - output_dir = "$root_out_dir/test/unittest/startup" - ldflags = [ - "-lstdc++", - "-lpthread", - "-lm", - ] - defines = [ "OHOS_LITE" ] - if (storage_type == "emmc") { - defines += [ "USE_EMMC_STORAGE" ] - } - - include_dirs = [ - "//base/startup/init_lite/services/include", - "//base/startup/init_lite/services/param/include", - "//base/startup/init_lite/services/log", - "//third_party/cJSON", - "//third_party/bounds_checking_function/include", - "//base/startup/syspara_lite/interfaces/kits", - "//base/hiviewdfx/hilog_lite/interfaces/native/kits", - ] - - sources = [ - "//base/startup/init_lite/services/log/init_log.c", - "//base/startup/init_lite/services/src/init_adapter.c", - "//base/startup/init_lite/services/src/init_capability.c", - "//base/startup/init_lite/services/src/init_cmds.c", - "//base/startup/init_lite/services/src/init_import.c", - "//base/startup/init_lite/services/src/init_jobs.c", - "//base/startup/init_lite/services/src/init_read_cfg.c", - "//base/startup/init_lite/services/src/init_reboot.c", - "//base/startup/init_lite/services/src/init_service.c", - "//base/startup/init_lite/services/src/init_service_manager.c", - "//base/startup/init_lite/services/src/init_service_socket.c", - "//base/startup/init_lite/services/src/init_signal_handler.c", - "//base/startup/init_lite/services/src/init_utils.c", - "cmd_func_test.cpp", - ] - - deps = [ - "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", - "//base/startup/init_lite/initsync:initsync", - "//base/startup/syspara_lite/frameworks/parameter:parameter", - "//build/lite/config/component/cJSON:cjson_shared", - "//third_party/bounds_checking_function:libsec_shared", - ] - if (ohos_kernel_type == "liteos_a") { - include_dirs += [ - "//kernel/liteos_a/syscall", - "//base/startup/init_lite/interfaces/kits", - "//base/startup/init_lite/initsync/include", - ] - } - } - - group("unittest") { - deps = [ ":init_test" ] - } -} else { - import("//build/ohos.gni") - sources = [] - group("unittest") { - deps = [] - } -} diff --git a/services/utils/BUILD.gn b/services/utils/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..00fddb9b4e1b664ef3def55dd81bbe079fd85cb4 --- /dev/null +++ b/services/utils/BUILD.gn @@ -0,0 +1,50 @@ +# Copyright (c) 2021-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/begetd.gni") +config("exported_header_files") { + visibility = [ ":*" ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/log", + ] +} + +if (defined(ohos_lite)) { + static_library("libinit_utils") { + sources = [ "init_utils.c" ] + public_configs = [ ":exported_header_files" ] + include_dirs = [ + "//base/hiviewdfx/hilog_lite/interfaces/native/kits", + "//base/startup/init/interfaces/innerkits/include", + ] + defines = [ + "_GNU_SOURCE", + "OHOS_LITE", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + if (init_lite_no_log) { + defines += [ "INIT_NO_LOG" ] + } + } +} else { + import("//build/ohos.gni") + ohos_static_library("libinit_utils") { + sources = [ "init_utils.c" ] + public_configs = [ ":exported_header_files" ] + include_dirs = [ "//base/startup/init/interfaces/innerkits/include" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + defines = [ "_GNU_SOURCE" ] + part_name = "init" + subsystem_name = "startup" + } +} diff --git a/services/utils/init_hashmap.c b/services/utils/init_hashmap.c new file mode 100644 index 0000000000000000000000000000000000000000..2e744e593ae02597c6e4c908ab07f50f1f329487 --- /dev/null +++ b/services/utils/init_hashmap.c @@ -0,0 +1,197 @@ +/* + * 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 "init_hashmap.h" +#include "init_log.h" + +typedef struct { + HashNodeCompare nodeCompare; + HashKeyCompare keyCompare; + HashNodeFunction nodeHash; + HashKeyFunction keyHash; + HashNodeOnFree nodeFree; + int maxBucket; + uint32_t tableId; + HashNode *buckets[0]; +} HashTab; + +static uint32_t g_tableId = 0; +int32_t OH_HashMapCreate(HashMapHandle *handle, const HashInfo *info) +{ + INIT_ERROR_CHECK(handle != NULL, return -1, "Invalid hash handle"); + INIT_ERROR_CHECK(info != NULL && info->maxBucket > 0, return -1, "Invalid hash info"); + INIT_ERROR_CHECK(info->keyHash != NULL && info->nodeHash != NULL, return -1, "Invalid hash key"); + INIT_ERROR_CHECK(info->nodeCompare != NULL && info->keyCompare != NULL, return -1, "Invalid hash compare"); + HashTab *tab = (HashTab *)calloc(1, sizeof(HashTab) + sizeof(HashNode*) * info->maxBucket); + INIT_ERROR_CHECK(tab != NULL, return -1, "Failed to create hash tab"); + tab->maxBucket = info->maxBucket; + tab->keyHash = info->keyHash; + tab->nodeCompare = info->nodeCompare; + tab->keyCompare = info->keyCompare; + tab->nodeHash = info->nodeHash; + tab->nodeFree = info->nodeFree; + tab->tableId = g_tableId++; + *handle = (HashMapHandle)tab; + return 0; +} + +static HashNode *GetHashNodeByNode(const HashTab *tab, const HashNode *root, const HashNode *new) +{ + HashNode *node = (HashNode *)root; + while (node != NULL) { + int ret = tab->nodeCompare(node, new); + if (ret == 0) { + return node; + } + node = node->next; + } + return NULL; +} + +static HashNode *GetHashNodeByKey(const HashTab *tab, const HashNode *root, const void *key, HashKeyCompare keyCompare) +{ + (void)tab; + HashNode *node = (HashNode *)root; + while (node != NULL) { + int ret = keyCompare(node, key); + if (ret == 0) { + return node; + } + node = node->next; + } + return NULL; +} + +int32_t OH_HashMapAdd(HashMapHandle handle, HashNode *node) +{ + INIT_ERROR_CHECK(handle != NULL, return -1, "Invalid hash handle"); + INIT_ERROR_CHECK(node != NULL && node->next == NULL, return -1, "Invalid param"); + HashTab *tab = (HashTab *)handle; + int hashCode = tab->nodeHash(node); + hashCode = (hashCode < 0) ? -hashCode : hashCode; + hashCode = hashCode % tab->maxBucket; + INIT_ERROR_CHECK(hashCode < tab->maxBucket, return -1, "Invalid hashcode %d %d", tab->maxBucket, hashCode); + + // check key exist + HashNode *tmp = GetHashNodeByNode(tab, tab->buckets[hashCode], node); + if (tmp != NULL) { + INIT_LOGE("node hash been exist"); + return -1; + } + node->next = tab->buckets[hashCode]; + tab->buckets[hashCode] = node; + return 0; +} + +void OH_HashMapRemove(HashMapHandle handle, const void *key) +{ + INIT_ERROR_CHECK(handle != NULL && key != NULL, return, "Invalid hash handle key:%s", key); + HashTab *tab = (HashTab *)handle; + int hashCode = tab->keyHash(key); + hashCode = (hashCode < 0) ? -hashCode : hashCode; + hashCode = hashCode % tab->maxBucket; + INIT_ERROR_CHECK(hashCode < tab->maxBucket, return, "Invalid hashcode %d %d", tab->maxBucket, hashCode); + + HashNode *node = tab->buckets[hashCode]; + HashNode *preNode = node; + while (node != NULL) { + int ret = tab->keyCompare(node, key); + if (ret == 0) { + if (node == tab->buckets[hashCode]) { + tab->buckets[hashCode] = node->next; + } else { + preNode->next = node->next; + } + return; + } + preNode = node; + node = node->next; + } +} + +HashNode *OH_HashMapGet(HashMapHandle handle, const void *key) +{ + INIT_ERROR_CHECK(handle != NULL && key != NULL, return NULL, "Invalid hash handle key:%s", key); + HashTab *tab = (HashTab *)handle; + int hashCode = tab->keyHash(key); + hashCode = (hashCode < 0) ? -hashCode : hashCode; + hashCode = hashCode % tab->maxBucket; + INIT_ERROR_CHECK(hashCode < tab->maxBucket, return NULL, + "Invalid hashcode %d %d", tab->maxBucket, hashCode); + return GetHashNodeByKey(tab, tab->buckets[hashCode], key, tab->keyCompare); +} + +static void HashListFree(HashTab *tab, HashNode *root, void *context) +{ + if (root == NULL) { + return; + } + HashNode *node = root; + while (node != NULL) { + HashNode *next = node->next; + if (tab->nodeFree != NULL) { + tab->nodeFree(node, context); + } + node = next; + } +} + +void OH_HashMapDestory(HashMapHandle handle, void *context) +{ + INIT_ERROR_CHECK(handle != NULL, return, "Invalid hash handle"); + HashTab *tab = (HashTab *)handle; + for (int i = 0; i < tab->maxBucket; i++) { + HashListFree(tab, tab->buckets[i], context); + } + free(tab); +} + +HashNode *OH_HashMapFind(HashMapHandle handle, + int hashCode, const void *key, HashKeyCompare keyCompare) +{ + INIT_ERROR_CHECK(handle != NULL, return NULL, "Invalid hash handle"); + INIT_ERROR_CHECK(key != NULL && keyCompare != NULL, return NULL, "Invalid hash key"); + HashTab *tab = (HashTab *)handle; + INIT_ERROR_CHECK((hashCode < tab->maxBucket) && (hashCode >= 0), return NULL, + "Invalid hash code %d %d", tab->maxBucket, hashCode); + return GetHashNodeByKey(tab, tab->buckets[hashCode], key, keyCompare); +} + +void OH_HashMapTraverse(HashMapHandle handle, void (*hashNodeTraverse)(const HashNode *node, const void *context), + const void *context) +{ + INIT_ERROR_CHECK(handle != NULL && hashNodeTraverse != NULL, return, "Invalid hash handle"); + HashTab *tab = (HashTab *)handle; + for (int i = 0; i < tab->maxBucket; i++) { + HashNode *node = tab->buckets[i]; + while (node != NULL) { + HashNode *next = node->next; + hashNodeTraverse(node, context); + node = next; + } + } +} + +int OH_HashMapIsEmpty(HashMapHandle handle) +{ + INIT_ERROR_CHECK(handle != NULL, return 1, "Invalid hash handle"); + HashTab *tab = (HashTab *)handle; + for (int i = 0; i < tab->maxBucket; i++) { + HashNode *node = tab->buckets[i]; + if (node != NULL) { + return 0; + } + } + return 1; +} diff --git a/services/utils/init_utils.c b/services/utils/init_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..3305074b4bfd193727d8724415d2c582b91c7bdb --- /dev/null +++ b/services/utils/init_utils.c @@ -0,0 +1,987 @@ +/* + * Copyright (c) 2021 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 "init_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "init_log.h" +#include "securec.h" +#include "service_control.h" + +#define MAX_BUF_SIZE 1024 +#define MAX_SMALL_BUFFER 4096 + +#define MAX_JSON_FILE_LEN 102400 // max init.cfg size 100KB +#define CONVERT_MICROSEC_TO_SEC(x) ((x) / 1000 / 1000.0) +#ifndef DT_DIR +#define DT_DIR 4 +#endif + +#define THOUSAND_UNIT_FLOAT 1000.0 + +float ConvertMicrosecondToSecond(int x) +{ + return ((x / THOUSAND_UNIT_FLOAT) / THOUSAND_UNIT_FLOAT); +} + +#ifndef __LITEOS_M__ +static bool CheckDigit(const char *name) +{ + size_t nameLen = strlen(name); + for (size_t i = 0; i < nameLen; ++i) { + if (!isdigit(name[i])) { + return false; + } + } + return true; +} +#endif + +int StringToUint(const char *name, unsigned int *value) +{ + errno = 0; + *value = (unsigned int)strtoul(name, 0, DECIMAL_BASE); + INIT_CHECK_RETURN_VALUE(errno == 0, -1); + return 0; +} + +uid_t DecodeUid(const char *name) +{ +#ifndef __LITEOS_M__ + INIT_CHECK_RETURN_VALUE(name != NULL, -1); + uid_t uid = -1; + if (CheckDigit(name)) { + if (!StringToUint(name, &uid)) { + return uid; + } else { + return -1; + } + } + struct passwd *p = getpwnam(name); + if (p == NULL) { + return -1; + } + return p->pw_uid; +#else + (void)name; + return -1; +#endif +} + +gid_t DecodeGid(const char *name) +{ +#ifndef __LITEOS_M__ + INIT_CHECK_RETURN_VALUE(name != NULL, -1); + gid_t gid = -1; + if (CheckDigit(name)) { + if (!StringToUint(name, &gid)) { + return gid; + } else { + return -1; + } + } + struct group *data = getgrnam(name); + if (data != NULL) { + return data->gr_gid; + } + while ((data = getgrent()) != NULL) { + if ((data->gr_name != NULL) && (strcmp(data->gr_name, name) == 0)) { + gid = data->gr_gid; + break; + } + } + endgrent(); + return gid; +#else + (void)name; + return -1; +#endif +} + +char *ReadFileToBuf(const char *configFile) +{ + char *buffer = NULL; + FILE *fd = NULL; + struct stat fileStat = {0}; + INIT_CHECK_RETURN_VALUE(configFile != NULL && *configFile != '\0', NULL); + do { + if (stat(configFile, &fileStat) != 0 || + fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) { + break; + } + fd = fopen(configFile, "r"); + if (fd == NULL) { + INIT_LOGE("Open %s failed. err = %d", configFile, errno); + break; + } + buffer = (char*)calloc((size_t)(fileStat.st_size + 1), sizeof(char)); + if (buffer == NULL) { + INIT_LOGE("Failed to allocate memory for config file, err = %d", errno); + break; + } + + if (fread(buffer, fileStat.st_size, 1, fd) != 1) { + free(buffer); + buffer = NULL; + break; + } + buffer[fileStat.st_size] = '\0'; + } while (0); + + if (fd != NULL) { + (void)fclose(fd); + fd = NULL; + } + return buffer; +} + +void CloseStdio(void) +{ +#ifndef STARTUP_INIT_TEST +#ifndef __LITEOS_M__ + int fd = open("/dev/null", O_RDWR); + if (fd < 0) { + return; + } + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, STDERR_HANDLE); + if (fd > STDERR_HANDLE) { + close(fd); + } +#endif +#endif +} + +char *ReadFileData(const char *fileName) +{ + if (fileName == NULL) { + return NULL; + } + char *buffer = NULL; + int fd = -1; + fd = open(fileName, O_RDONLY); + INIT_ERROR_CHECK(fd >= 0, return NULL, "Failed to read file %s errno:%d", fileName, errno); + buffer = (char *)calloc(1, MAX_SMALL_BUFFER); // fsmanager not create, can not get fileStat st_size + INIT_ERROR_CHECK(buffer != NULL, close(fd); + return NULL, "Failed to allocate memory for %s", fileName); + ssize_t readLen = read(fd, buffer, MAX_SMALL_BUFFER - 1); + INIT_ERROR_CHECK((readLen > 0) && (readLen <= (MAX_SMALL_BUFFER - 1)), close(fd); + free(buffer); + return NULL, "Failed to read data for %s", fileName); + buffer[readLen] = '\0'; + if (fd != -1) { + close(fd); + } + return buffer; +} + +int IterateNameValuePairs(const char *src, void (*iterator)(const NAME_VALUE_PAIR *nv, void *context), void *context) +{ + int cnt = 0; + const char *seperator; + const char *tmp = src; + NAME_VALUE_PAIR nv; + if ((src == NULL) || (iterator == NULL)) { + return -1; + } + + do { + // Find space seperator + nv.name = tmp; + seperator = strchr(tmp, ' '); + if (seperator == NULL) { + // Last nv + nv.valueEnd = tmp + strlen(tmp); + tmp = NULL; + } else { + nv.valueEnd = seperator; + tmp = seperator + 1; + } + + // Find equal seperator + seperator = strchr(nv.name, '='); + if (seperator == NULL) { + // Invalid name value pair + continue; + } + if (seperator > nv.valueEnd) { + // name without value, just ignore + continue; + } + nv.nameEnd = seperator; + nv.value = seperator + 1; + + iterator(&nv, context); + cnt += 1; + } while (tmp != NULL); + + return cnt; +} + +int GetProcCmdlineValue(const char *name, const char *buffer, char *value, int length) +{ + INIT_ERROR_CHECK(name != NULL && buffer != NULL && value != NULL, return -1, "Failed get parameters"); + char *endData = (char *)buffer + strlen(buffer); + char *tmp = strstr(buffer, name); + do { + if (tmp == NULL) { + return -1; + } + tmp = tmp + strlen(name); + while (tmp < endData && *tmp == ' ') { + tmp++; + } + if (tmp >= endData) { + return -1; + } + if (*tmp == '=') { + break; + } + tmp = strstr(tmp + 1, name); + } while (tmp < endData); + tmp++; + size_t i = 0; + size_t endIndex = 0; + while (tmp < endData && *tmp == ' ') { + tmp++; + } + for (; i < (size_t)length; tmp++) { + if (tmp >= endData || *tmp == ' ' || *tmp == '\n' || *tmp == '\r' || *tmp == '\t') { + endIndex = i; + break; + } + if (*tmp == '=') { + if (endIndex != 0) { // for root=uuid=xxxx + break; + } + i = 0; + endIndex = 0; + continue; + } + value[i++] = *tmp; + } + if (i >= (size_t)length) { + return -1; + } + value[endIndex] = '\0'; + return 0; +} + +int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum) +{ + INIT_CHECK_RETURN_VALUE(srcPtr != NULL && dstPtr != NULL && del != NULL, -1); + char *buf = NULL; + dstPtr[0] = strtok_r(srcPtr, del, &buf); + int counter = 0; + while ((counter < maxNum) && (dstPtr[counter] != NULL)) { + counter++; + if (counter >= maxNum) { + break; + } + dstPtr[counter] = strtok_r(NULL, del, &buf); + } + return counter; +} + +void FreeStringVector(char **vector, int count) +{ + if (vector != NULL) { + for (int i = 0; i < count; i++) { + if (vector[i] != NULL) { + free(vector[i]); + } + } + free(vector); + } +} + +char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount) +{ + INIT_CHECK_RETURN_VALUE((maxItemCount >= 0) && (buffer != NULL) && (del != NULL) && (returnCount != NULL), NULL); + // Why is this number? + // Now we use this function to split a string with a given delimiter + // We do not know how many sub-strings out there after splitting. + // 50 is just a guess value. + const int defaultItemCounts = 50; + int itemCounts = maxItemCount; + + if (maxItemCount > defaultItemCounts) { + itemCounts = defaultItemCounts; + } + char **items = (char **)malloc(sizeof(char*) * itemCounts); + INIT_ERROR_CHECK(items != NULL, return NULL, "No enough memory to store items"); + char *rest = NULL; + char *p = strtok_r(buffer, del, &rest); + int count = 0; + while (p != NULL) { + if (count > itemCounts - 1) { + itemCounts += (itemCounts / 2) + 1; // 2 Request to increase the original memory by half. + INIT_LOGV("Too many items,expand size"); + char **expand = (char **)(realloc(items, sizeof(char *) * itemCounts)); + INIT_ERROR_CHECK(expand != NULL, FreeStringVector(items, count); + return NULL, "Failed to expand memory"); + items = expand; + } + size_t len = strlen(p); + items[count] = (char *)calloc(len + 1, sizeof(char)); + INIT_CHECK(items[count] != NULL, FreeStringVector(items, count); + return NULL); + if (strncpy_s(items[count], len + 1, p, len) != EOK) { + INIT_LOGE("Copy string failed"); + FreeStringVector(items, count); + return NULL; + } + count++; + p = strtok_r(NULL, del, &rest); + } + *returnCount = count; + return items; +} + +long long InitDiffTime(INIT_TIMING_STAT *stat) +{ + long long diff = (long long)(stat->endTime.tv_sec - stat->startTime.tv_sec) * 1000000; // 1000000 1000ms + if (stat->endTime.tv_nsec > stat->startTime.tv_nsec) { + diff += (stat->endTime.tv_nsec - stat->startTime.tv_nsec) / BASE_MS_UNIT; + } else { + diff -= (stat->startTime.tv_nsec - stat->endTime.tv_nsec) / BASE_MS_UNIT; + } + return diff; +} + +void WaitForFile(const char *source, unsigned int maxSecond) +{ + INIT_ERROR_CHECK(maxSecond <= WAIT_MAX_SECOND, maxSecond = WAIT_MAX_SECOND, + "WaitForFile max time is %us", WAIT_MAX_SECOND); + struct stat sourceInfo = {0}; + unsigned int waitTime = 10 * BASE_MS_UNIT; // 10ms + long long maxDuration = maxSecond * BASE_MS_UNIT * BASE_MS_UNIT; // 5s +#ifdef STARTUP_INIT_TEST + maxDuration = 0; +#endif + long long duration = 0; + INIT_TIMING_STAT cmdTimer; + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.startTime); + while (1) { + if (stat(source, &sourceInfo) >= 0) { + break; + } + if (errno != ENOENT) { + INIT_LOGE("stat file err: %d", errno); + break; + } + + usleep(waitTime); + (void)clock_gettime(CLOCK_MONOTONIC, &cmdTimer.endTime); + duration = InitDiffTime(&cmdTimer); + + if (duration >= maxDuration) { + INIT_LOGE("wait for file:%s failed after %d second.", source, maxSecond); + break; + } + } +} + +size_t WriteAll(int fd, const char *buffer, size_t size) +{ + INIT_CHECK_RETURN_VALUE(buffer != NULL && fd >= 0 && *buffer != '\0', 0); + const char *p = buffer; + size_t left = size; + ssize_t written; + while (left > 0) { + do { + written = write(fd, p, left); + } while (written < 0 && errno == EINTR); + if (written < 0) { + INIT_LOGE("Failed to write %lu bytes, err = %d", left, errno); + break; + } + p += written; + left -= written; + } + return size - left; +} + +char *GetRealPath(const char *source) +{ + INIT_CHECK_RETURN_VALUE(source != NULL, NULL); + char *path = realpath(source, NULL); + if (path == NULL) { + INIT_ERROR_CHECK(errno == ENOENT, return NULL, "Failed to resolve %s real path err=%d", source, errno); + } + return path; +} + +int MakeDir(const char *dir, mode_t mode) +{ + int rc = -1; + if (dir == NULL || *dir == '\0') { + errno = EINVAL; + return rc; + } + rc = mkdir(dir, mode); + INIT_ERROR_CHECK(!(rc < 0 && errno != EEXIST), return rc, + "Create directory \" %s \" failed, err = %d", dir, errno); + // create dir success or it already exist. + return 0; +} + +int MakeDirRecursive(const char *dir, mode_t mode) +{ + int rc = -1; + char buffer[PATH_MAX] = {0}; + const char *p = NULL; + if (dir == NULL || *dir == '\0') { + errno = EINVAL; + return rc; + } + p = dir; + char *slash = strchr(dir, '/'); + while (slash != NULL) { + int gap = slash - p; + p = slash + 1; + if (gap == 0) { + slash = strchr(p, '/'); + continue; + } + if (gap < 0) { // end with '/' + break; + } + INIT_CHECK_RETURN_VALUE(memcpy_s(buffer, PATH_MAX, dir, p - dir - 1) == 0, -1); + rc = MakeDir(buffer, mode); + INIT_CHECK_RETURN_VALUE(rc >= 0, rc); + slash = strchr(p, '/'); + } + return MakeDir(dir, mode); +} + +void CheckAndCreateDir(const char *fileName) +{ +#ifndef __LITEOS_M__ + if (fileName == NULL || *fileName == '\0') { + return; + } + char *path = strndup(fileName, strrchr(fileName, '/') - fileName); + if (path == NULL) { + return; + } + if (access(path, F_OK) == 0) { + free(path); + return; + } + MakeDirRecursive(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + free(path); +#else + (void)fileName; +#endif +} + +int CheckAndCreatFile(const char *file, mode_t mode) +{ + if (access(file, F_OK) == 0) { + BEGET_LOGW("File \' %s \' already exist", file); + return 0; + } else { + if (errno == ENOENT) { + CheckAndCreateDir(file); + int fd = open(file, O_CREAT, mode); + if (fd < 0) { + BEGET_LOGE("Failed create %s, err=%d", file, errno); + return -1; + } else { + close(fd); + } + } else { + BEGET_LOGW("Failed to access \' %s \', err = %d", file, errno); + return -1; + } + } + return 0; +} + +int StringToInt(const char *str, int defaultValue) +{ + if (str == NULL || *str == '\0') { + return defaultValue; + } + errno = 0; + int value = (int)strtoul(str, NULL, DECIMAL_BASE); + return (errno != 0) ? defaultValue : value; +} + +int ReadFileInDir(const char *dirPath, const char *includeExt, + int (*processFile)(const char *fileName, void *context), void *context) +{ + INIT_CHECK_RETURN_VALUE(dirPath != NULL && processFile != NULL, -1); + DIR *pDir = opendir(dirPath); + INIT_ERROR_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno); + char *fileName = calloc(1, MAX_BUF_SIZE); + INIT_ERROR_CHECK(fileName != NULL, closedir(pDir); + return -1, "Failed to malloc for %s", dirPath); + + struct dirent *dp; + uint32_t count = 0; + while ((dp = readdir(pDir)) != NULL) { + if (dp->d_type == DT_DIR) { + continue; + } + if (includeExt != NULL) { + char *tmp = strstr(dp->d_name, includeExt); + if (tmp == NULL) { + continue; + } + if (strcmp(tmp, includeExt) != 0) { + continue; + } + } + int ret = snprintf_s(fileName, MAX_BUF_SIZE, MAX_BUF_SIZE - 1, "%s/%s", dirPath, dp->d_name); + if (ret <= 0) { + INIT_LOGE("Failed to get file name for %s", dp->d_name); + continue; + } + struct stat st; + if (stat(fileName, &st) == 0) { + count++; + processFile(fileName, context); + } + } + INIT_LOGV("ReadFileInDir dirPath %s %d", dirPath, count); + free(fileName); + closedir(pDir); + return 0; +} + +// Check if in updater mode. +int InUpdaterMode(void) +{ +#ifdef OHOS_LITE + return 0; +#else + const char * const updaterExecutableFile = "/bin/updater"; + if (access(updaterExecutableFile, X_OK) == 0) { + return 1; + } else { + return 0; + } +#endif +} + +// Check if in rescue mode. +int InRescueMode(void) +{ +#ifdef OHOS_LITE + return 1; +#else + char value[MAX_BUFFER_LEN] = {0}; + int ret = GetParameterFromCmdLine("rescue_mode", value, MAX_BUFFER_LEN); + if (ret == 0 && strcmp(value, "true") == 0) { + return 0; + } + return 1; +#endif +} + +int StringReplaceChr(char *strl, char oldChr, char newChr) +{ + INIT_ERROR_CHECK(strl != NULL, return -1, "Invalid parament"); + char *p = strl; + while (*p != '\0') { + if (*p == oldChr) { + *p = newChr; + } + p++; + } + INIT_LOGV("strl is %s", strl); + return 0; +} + +#ifndef __LITEOS_M__ +static void RedirectStdio(int fd) +{ + const int stdError = 2; + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, stdError); // Redirect fd to 0, 1, 2 +} +#endif + +#ifndef __LITEOS_M__ +static int OpenStdioDevice(const char *dev, int flag) +{ + setsid(); + WaitForFile(dev, WAIT_MAX_SECOND); + int fd = open(dev, O_RDWR); + if (fd >= 0) { + ioctl(fd, TIOCSCTTY, flag); + RedirectStdio(fd); + if (fd > 2) { + close(fd); + } + } else { + return errno; + } + return 0; +} +#endif + +int OpenConsole(void) +{ +#ifndef __LITEOS_M__ + return OpenStdioDevice("/dev/console", 1); +#else + return 0; +#endif +} + +int OpenKmsg(void) +{ +#ifndef __LITEOS_M__ + return OpenStdioDevice("/dev/kmsg", 0); +#else + return 0; +#endif +} + +INIT_LOCAL_API int StringToLL(const char *str, long long int *out) +{ + INIT_ERROR_CHECK(str != NULL && out != NULL, return -1, "Invalid parament"); + const char *s = str; + while (isspace(*s)) { + s++; + } + + size_t len = strlen(s); + int positiveHex = (len > 1 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')); + int negativeHex = (len > 2 && s[0] == '-' && s[1] == '0' && (s[2] == 'x' || s[2] == 'X')); // 2: shorttest + int base = (positiveHex || negativeHex) ? HEX_BASE : DECIMAL_BASE; + char *end = NULL; + errno = 0; + *out = strtoll(s, &end, base); + if (errno != 0) { + INIT_LOGE("StringToLL %s err = %d", str, errno); + return -1; + } + BEGET_CHECK(!(s == end || *end != '\0'), return -1); + return 0; +} + +INIT_LOCAL_API int StringToULL(const char *str, unsigned long long int *out) +{ + INIT_ERROR_CHECK(str != NULL && out != NULL, return -1, "Invalid parament"); + const char *s = str; + while (isspace(*s)) { + s++; + } + BEGET_CHECK(s[0] != '-', return -1); + int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? HEX_BASE : DECIMAL_BASE; + char *end = NULL; + errno = 0; + *out = strtoull(s, &end, base); + if (errno != 0) { + INIT_LOGE("StringToULL %s err = %d", str, errno); + return -1; + } + BEGET_CHECK(end != s, return -1); + BEGET_CHECK(*end == '\0', return -1); + return 0; +} + +void TrimTail(char *str, char c) +{ + char *end = str + strlen(str) - 1; + while (end >= str && *end == c) { + *end = '\0'; + end--; + } +} + +char *TrimHead(char *str, char c) +{ + char *head = str; + const char *end = str + strlen(str); + while (head < end && *head == c) { + *head = '\0'; + head++; + } + return head; +} + +static const char *GetCmdlineValueByName(const char *name, const char *buffer, const char *endData) +{ + const char *tmp = buffer; + do { + tmp = strstr(tmp, name); + if (tmp == NULL) { + return NULL; + } + if (tmp > buffer && *(tmp - 1) != ' ') { + tmp++; + continue; + } + tmp = tmp + strlen(name); + if (tmp >= endData) { + return NULL; + } + if (*tmp == '=') { + tmp++; + return tmp; + } + } while (tmp < endData); + return NULL; +} + +static int GetValuePriority(const char *str, const char *value) +{ + if (str == NULL || value == NULL || *value == '\0') { + return -1; + } + const char *endData = str + strlen(str); + const char *start = str; + const char *tmp = str; + int len = strlen(value); + while (tmp < endData) { + tmp = strstr(start, "<"); + if (tmp == NULL) { + tmp = endData; + } + if (tmp - start == len && strncmp(start, value, len) == 0) { + return tmp - str; + } + start = tmp + 1; + } + return -1; +} + +static int CopyCmdlineValue(const char *tmp, const char *endData, char *value, int length, int defaultValue) +{ + int i = 0; + while (i < length && tmp < endData && *tmp != ' ') { + value[i++] = *tmp; + tmp++; + } + + if (i >= length) { + BEGET_LOGE("value is too long"); + for (int j = 0; j < length; ++j) { + value[j] = '\0'; + } + return defaultValue ? defaultValue : -1; + } + value[i] = '\0'; + return defaultValue; +} + +static int DealConflictPriority(const char *name, const char *tmp, char *value, int length, const char *str) +{ + if (length <= 0 || length > CMDLINE_VALUE_LEN_MAX) { + BEGET_LOGE("length is invalid"); + return 1; + } + const char *endData = tmp + strlen(tmp); + char *valueTmp = (char *)calloc(length, sizeof(char)); + INIT_ERROR_CHECK(valueTmp != NULL, return 1, "Failed to calloc valueTmp"); + while (CopyCmdlineValue(tmp, endData, valueTmp, length, 0) == 0) { + if (GetValuePriority(str, valueTmp) <= GetValuePriority(str, value)) { + tmp = GetCmdlineValueByName(name, tmp, endData); + if (tmp == NULL) { + free(valueTmp); + return 1; + } + continue; + } + int i = 0; + while (*(valueTmp + i) != '\0') { + value[i] = *(valueTmp + i); + i++; + } + for (int j = i; j < length; ++j) { + value[j] = '\0'; + } + tmp = GetCmdlineValueByName(name, tmp, endData); + if (tmp == NULL) { + free(valueTmp); + return 1; + } + } + free(valueTmp); + return 1; +} + +static int GetExactProcCmdlineValue(const char *name, const char *buffer, char *value, int length, const char *strategy) +{ + INIT_ERROR_CHECK(name != NULL && buffer != NULL && value != NULL, return -1, "Failed get parameters"); + const char *endData = buffer + strlen(buffer); + const char *tmp = GetCmdlineValueByName(name, buffer, endData); + if (tmp == NULL) { + return -1; + } + + const char *temp = GetCmdlineValueByName(name, tmp, endData); + if (temp == NULL) { // 无冲突 + return CopyCmdlineValue(tmp, endData, value, length, 0); + } else if (strcmp(strategy, FIRST_VALUE) == 0) { // 取第一个值 + return CopyCmdlineValue(tmp, endData, value, length, 1); + } else if (strcmp(strategy, LAST_VALUE) == 0) { // 取最后一个值 + do { + tmp = temp; + temp = GetCmdlineValueByName(name, tmp, endData); + } while (temp != NULL); + return CopyCmdlineValue(tmp, endData, value, length, 1); + } else if (strcmp(strategy, EMPTY_VALUE) == 0) { // 不取任何一个值 + return 1; + } else { // 处理自定义优先级 + return DealConflictPriority(name, tmp, value, length, strategy); + } + return 0; +} + +int GetExactParameterFromCmdLine(const char *paramName, char *value, size_t valueLen, const char *conflictStrategy) +{ + char *buffer = ReadFileData(BOOT_CMD_LINE); + BEGET_ERROR_CHECK(buffer != NULL, return -1, "Failed to read /proc/cmdline"); + int ret = GetExactProcCmdlineValue(paramName, buffer, value, valueLen, conflictStrategy); + free(buffer); + return ret; +} + +int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen) +{ + char *buffer = ReadFileData(BOOT_CMD_LINE); + BEGET_ERROR_CHECK(buffer != NULL, return -1, "Failed to read /proc/cmdline"); + int ret = GetProcCmdlineValue(paramName, buffer, value, valueLen); + free(buffer); + return ret; +} + +uint32_t IntervalTime(struct timespec *startTime, struct timespec *endTime) +{ + uint32_t diff = 0; + if (endTime->tv_sec > startTime->tv_sec) { + diff = (uint32_t)(endTime->tv_sec - startTime->tv_sec); + } else { + diff = (uint32_t)(startTime->tv_sec - endTime->tv_sec); + } + return diff; +} + +typedef int (*str_compare)(const char *s1, const char *s2); +int OH_ExtendableStrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase, const char *extend[]) +{ + int i; + int idx; + str_compare cmp = strcmp; + + if ((strArray == NULL) || (target == NULL) || (target[0] == '\0')) { + return -1; + } + + if (ignoreCase) { + cmp = strcasecmp; + } + + for (i = 0; strArray[i] != NULL; i++) { + if (cmp(strArray[i], target) == 0) { + return i; + } + } + if (extend == NULL) { + return -1; + } + idx = 0; + while (extend[idx] != NULL) { + if (cmp(extend[idx], target) == 0) { + return i + idx; + } + idx++; + } + return -1; +} + +int OH_StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase) +{ + return OH_ExtendableStrArrayGetIndex(strArray, target, ignoreCase, NULL); +} + +void *OH_ExtendableStrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase, void **extendStrDict) +{ + int i; + const char *pos; + str_compare cmp = strcmp; + + if ((strDict == NULL) || dictSize < 0 || ((size_t)dictSize < sizeof(const char *)) || + (target == NULL) || (target[0] == '\0')) { + return NULL; + } + + if (ignoreCase) { + cmp = strcasecmp; + } + + i = 0; + pos = (const char *)strDict; + while (*(const char **)pos != NULL) { + if (cmp(*(const char **)pos, target) == 0) { + return (void *)pos; + } + i++; + pos = pos + dictSize; + } + if (extendStrDict == NULL) { + return NULL; + } + pos = (const char *)extendStrDict; + while (*(const char **)pos != NULL) { + if (cmp(*(const char **)pos, target) == 0) { + return (void *)pos; + } + i++; + pos = pos + dictSize; + } + return NULL; +} + +void *OH_StrDictGet(void **strDict, int dictSize, const char *target, int ignoreCase) +{ + return OH_ExtendableStrDictGet(strDict, dictSize, target, ignoreCase, NULL); +} + +long long GetUptimeInMicroSeconds(const struct timespec *uptime) +{ + struct timespec now; + + if (uptime == NULL) { + clock_gettime(CLOCK_MONOTONIC, &now); + uptime = &now; + } + + #define SECOND_TO_MICRO_SECOND (1000000) + #define MICRO_SECOND_TO_NANOSECOND (1000) + + return ((long long)uptime->tv_sec * SECOND_TO_MICRO_SECOND) + + (uptime->tv_nsec / MICRO_SECOND_TO_NANOSECOND); +} diff --git a/services/utils/list.c b/services/utils/list.c new file mode 100644 index 0000000000000000000000000000000000000000..1214eb267557804392d1a850225d63a403035477 --- /dev/null +++ b/services/utils/list.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2021 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 "list.h" + +#include +#include + +/** + * @brief Initialize a double-linked list head + * + * All other list API should be initialized by this function.\n + * + * @param head list head, make sure head is valid pointer + * @return None + */ +void OH_ListInit(struct ListNode *node) +{ + if (node == NULL) { + return; + } + node->next = node; + node->prev = node; +} + +/** + * @brief Add a node to the end of the list + * + * @param head list head, make sure head is valid pointer + * @param item new node to be added + * @return None + */ +void OH_ListAddTail(struct ListNode *head, struct ListNode *item) +{ + if (head == NULL || item == NULL) { + return; + } + item->next = head; + item->prev = head->prev; + head->prev->next = item; + head->prev = item; +} + +/** + * @brief Remove a node from the list + * + * @param item the node to be removed from the list. + * This function does not free any memory within item. + * @return None + */ +void OH_ListRemove(struct ListNode *item) +{ + if (item == NULL) { + return; + } + item->next->prev = item->prev; + item->prev->next = item->next; +} + +/** + * @brief Add a node to the list with order + * + * @param head list head, make sure head is valid pointer + * @param item new node to be added + * @param compareProc comparison function for adding node + * if it is ascending order, this function should return an integer less than, + * equal to, or greater than zero if the first argument is considered to be + * respectively less than, equal to, or greater than the second. + * @return None + */ +void OH_ListAddWithOrder(struct ListNode *head, struct ListNode *item, ListCompareProc compareProc) +{ + ListNode *match; + + if (head == NULL || item == NULL || compareProc == NULL) { + return; + } + + match = head->next; + while ((match != NULL) && (match != head)) { + if (compareProc(match, item) > 0) { + break; + } + match = match->next; + } + if (match == NULL) { + return; + } + + // Insert + item->next = match; + item->prev = match->prev; + match->prev->next = item; + match->prev = item; +} + +/** + * @brief Find a node by traversing the list + * + * @param head list head, make sure head is valid pointer. + * @param data comparing data. + * @param compareProc comparing function, return 0 if matched. + * @return the found node; return NULL if none is found. + */ +ListNode *OH_ListFind(const ListNode *head, void *data, ListTraversalProc compareProc) +{ + ListNode *match; + if ((head == NULL) || (compareProc == NULL)) { + return NULL; + } + + match = head->next; + while ((match != NULL) && (match != head)) { + if (compareProc(match, data) == 0) { + return match; + } + match = match->next; + } + + return NULL; +} + +#define IS_REVERSE_ORDER(flags) (((flags) & TRAVERSE_REVERSE_ORDER) != 0) +#define IS_STOP_WHEN_ERROR(flags) (((flags) & TRAVERSE_STOP_WHEN_ERROR) != 0) + +/** + * @brief Traversal the list with specified function + * + * @param head list head, make sure head is valid pointer. + * @param cookie optional traversing data. + * @param traversalProc comparing function, return 0 if matched. + * @param flags optional traversing flags: + * TRAVERSE_REVERSE_ORDER: traversing from last node to first node; + * default behaviour is from first node to last node + * TRAVERSE_STOP_WHEN_ERROR: stop traversing if traversalProc return non-zero + * default behaviour will ignore traversalProc return values + * @return return -1 for invalid input arguments. + * when TRAVERSE_STOP_WHEN_ERROR is specified, it will return errors from traversalProc + */ +int OH_ListTraversal(ListNode *head, void *data, ListTraversalProc traversalProc, unsigned int flags) +{ + ListNode *match; + ListNode *next; + + if ((head == NULL) || (traversalProc == NULL)) { + return -1; + } + + if (IS_REVERSE_ORDER(flags)) { + match = head->prev; + } else { + match = head->next; + } + while ((match != NULL) && (match != head)) { + if (IS_REVERSE_ORDER(flags)) { + next = match->prev; + } else { + next = match->next; + } + int ret = traversalProc(match, data); + if ((ret != 0) && IS_STOP_WHEN_ERROR(flags)) { + return ret; + } + match = next; + } + + return 0; +} + +static int listDestroyTraversal(ListNode *node, void *data) +{ + ListDestroyProc destroyProc = (ListDestroyProc)data; + + if (destroyProc == NULL) { + free((void *)node); + } else { + destroyProc(node); + } + + return 0; +} + +/** + * @brief Find a node by traversing the list + * + * @param head list head, make sure head is valid pointer. + * @param destroyProc destroy function; if NULL, it will free each node by default. + * @return None + */ +void OH_ListRemoveAll(ListNode *head, ListDestroyProc destroyProc) +{ + if (head == NULL) { + return; + } + + OH_ListTraversal(head, (void *)destroyProc, listDestroyTraversal, 0); + OH_ListInit(head); +} + +/** + * @brief Get list count + * + * @param head list head, make sure head is valid pointer. + * @return the count of nodes in the list; return 0 if error + */ +int OH_ListGetCnt(const ListNode *head) +{ + int cnt; + ListNode *node; + + if (head == NULL) { + return 0; + } + + cnt = 0; + ForEachListEntry(head, node) { + cnt++; + } + return cnt; +} diff --git a/simulator/BUILD.gn b/simulator/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..b26301eeb9287e773dd47285fbb8bbd275469953 --- /dev/null +++ b/simulator/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (c) 2020 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("//build/ohos.gni") + +config("sysparam_simulator_public_config") { + include_dirs = [ + "../interfaces/innerkits/include/syspara", + "../interfaces/hals", + ] +} + +config("sysparam_simulator_config") { + if (product_name != "ohos-sdk") { + if (board_toolchain_type != "iccarm") { + cflags = [ + "-Wno-error", + "-D_INC_STDIO_S", + "-D_INC_STDLIB_S", + "-D_INC_MEMORY_S", + "-D_INC_STRING_S", + "-D_INC_WCHAR_S", + "-D_SECTMP=//", + "-D_STDIO_S_DEFINED", + ] + } + } else { + cflags = [ + "-Wno-error", + "-D_INC_STDIO_S", + "-D_INC_STDLIB_S", + "-D_INC_MEMORY_S", + "-D_INC_STRING_S", + "-D_INC_WCHAR_S", + "-D_SECTMP=//", + "-D_STDIO_S_DEFINED", + ] + } + include_dirs = [ + "../../../../commonlibrary/utils_lite/include", + "./parameter/src", + "../interfaces/innerkits/include/syspara", + ] +} + +ohos_static_library("sysparam_simulator") { + public_configs = [ ":sysparam_simulator_public_config" ] + configs = [ ":sysparam_simulator_config" ] + sources = [ + "./parameter/src/param_impl_posix/param_impl_posix.c", + "./parameter/src/parameter_common.c", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + defines = [ + "INCREMENTAL_VERSION=\"\"", + "BUILD_TYPE=\"\"", + "BUILD_USER=\"\"", + "BUILD_TIME=\"\"", + "BUILD_HOST=\"\"", + "BUILD_ROOTHASH=\"\"", + ] + part_name = "init" + subsystem_name = "startup" +} diff --git a/simulator/parameter/src/param_adaptor.h b/simulator/parameter/src/param_adaptor.h new file mode 100755 index 0000000000000000000000000000000000000000..433b0bc7bc0025039f529551dd30b019c8b7f365 --- /dev/null +++ b/simulator/parameter/src/param_adaptor.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 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 IOT_SYSPARA_API_H +#define IOT_SYSPARA_API_H + +#include "ohos_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define MAX_GET_VALUE_LEN 0x7FFFFFFF +#define MAX_KEY_LEN 32 +#define MAX_VALUE_LEN 128 + +int GetSysParam(const char* key, char* value, unsigned int len); +int SetSysParam(const char* key, const char* value); +boolean CheckPermission(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif // IOT_SYSPARA_API_H diff --git a/simulator/parameter/src/param_impl_posix/param_impl_posix.c b/simulator/parameter/src/param_impl_posix/param_impl_posix.c new file mode 100755 index 0000000000000000000000000000000000000000..26c6cdb8711e57adac3b4ed33b76c349b31b43e6 --- /dev/null +++ b/simulator/parameter/src/param_impl_posix/param_impl_posix.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2020 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 "ohos_errno.h" +#include "param_adaptor.h" + +#ifndef __LITEOS_M__ +#define DATA_PATH "/storage/data/system/param/" +#define SYS_UID_INDEX 1000 +#else +#ifndef DATA_PATH +#define DATA_PATH "" +#endif +#endif + +#define MAX_KEY_PATH 128 + +static boolean IsValidChar(const char ch) +{ + if (islower(ch) || isdigit(ch) || (ch == '_') || (ch == '.')) { + return TRUE; + } + return FALSE; +} + +static boolean IsValidValue(const char* value, unsigned int len) +{ + if ((value == NULL) || !strlen(value) || (strlen(value) >= len)) { + return FALSE; + } + return TRUE; +} + +static boolean IsValidKey(const char* key) +{ + if (!IsValidValue(key, MAX_KEY_LEN)) { + return FALSE; + } + int keyLen = strlen(key); + for (int i = 0; i < keyLen; i++) { + if (!IsValidChar(key[i])) { + return FALSE; + } + } + return TRUE; +} + +int GetSysParam(const char* key, char* value, unsigned int len) +{ + if (!IsValidKey(key) || (value == NULL) || (len > MAX_GET_VALUE_LEN)) { + return EC_INVALID; + } + char* keyPath = (char *)calloc(1, MAX_KEY_PATH + 1); + if (keyPath == NULL) { + return EC_FAILURE; + } + if (sprintf_s(keyPath, MAX_KEY_PATH + 1, "%s%s", DATA_PATH, key) < 0) { + free(keyPath); + return EC_FAILURE; + } + struct stat info = {0}; + if (stat(keyPath, &info) != F_OK) { + free(keyPath); + return EC_FAILURE; + } + if (info.st_size >= len) { + free(keyPath); + return EC_INVALID; + } + int fd = open(keyPath, O_RDONLY, S_IRUSR); + free(keyPath); + keyPath = NULL; + if (fd < 0) { + return EC_FAILURE; + } + + int ret = read(fd, value, (size_t)info.st_size); + close(fd); + fd = -1; + if (ret < 0) { + return EC_FAILURE; + } + value[info.st_size] = '\0'; + return info.st_size; +} + +int SetSysParam(const char* key, const char* value) +{ + if (!IsValidKey(key) || !IsValidValue(value, MAX_VALUE_LEN)) { + return EC_INVALID; + } + char* keyPath = (char *)calloc(1, MAX_KEY_PATH + 1); + if (keyPath == NULL) { + return EC_FAILURE; + } + if (sprintf_s(keyPath, MAX_KEY_PATH + 1, "%s%s", DATA_PATH, key) < 0) { + free(keyPath); + return EC_FAILURE; + } + int fd = open(keyPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + free(keyPath); + keyPath = NULL; + if (fd < 0) { + return EC_FAILURE; + } + + int ret = write(fd, value, strlen(value)); + close(fd); + fd = -1; + return (ret < 0) ? EC_FAILURE : EC_SUCCESS; +} + +boolean CheckPermission(void) +{ +#if (!defined(_WIN32) && !defined(_WIN64) && !defined(__LITEOS_M__)) + uid_t uid = getuid(); + if (uid <= SYS_UID_INDEX) { + return TRUE; + } +#endif +#if defined(__LITEOS_M__) + return TRUE; +#else + return FALSE; +#endif +} diff --git a/simulator/parameter/src/parameter_common.c b/simulator/parameter/src/parameter_common.c new file mode 100755 index 0000000000000000000000000000000000000000..af83f82351dda74c3171a9a4a2d9ff44ee106de4 --- /dev/null +++ b/simulator/parameter/src/parameter_common.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2020 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 "hal_sys_param.h" +#ifdef USE_MBEDTLS +#include "mbedtls/sha256.h" +#endif +#include "ohos_errno.h" +#include "param_adaptor.h" +#include "parameter.h" + +#define FILE_RO "ro." +#define OS_FULL_NAME_LEN 128 +#define VERSION_ID_LEN 256 +#define HASH_LENGTH 32 +#define DEV_BUF_LENGTH 3 +#define DEV_BUF_MAX_LENGTH 1024 +#define DEV_UUID_LENGTH 65 +#define OHOS_DISPLAY_VERSION_LEN 128 +#define OHOS_PATCH_VERSION_LEN 64 +#define OHOS_PATCH_VERSION_FILE "/patch/pversion" + +static const char OHOS_OS_NAME[] = { "OpenHarmony" }; +static const int OHOS_SDK_API_VERSION = 6; +static const char OHOS_SECURITY_PATCH_TAG[] = {"2021-09-01"}; +static const char OHOS_RELEASE_TYPE[] = { "Beta" }; +static const char OHOS_DEFAULT_VALUE[] = { "Default" }; + +static const int MAJOR_VERSION = 1; +static const int SENIOR_VERSION = 0; +static const int FEATURE_VERSION = 1; +static const int BUILD_VERSION = 0; + +static boolean IsValidValue(const char *value, unsigned int len) +{ + if ((value == NULL) || !strlen(value) || (strlen(value) + 1 > len)) { + return FALSE; + } + return TRUE; +} + +int GetParameter(const char *key, const char *def, char *value, unsigned int len) +{ + if ((key == NULL) || (value == NULL)) { + return EC_INVALID; + } + if (!CheckPermission()) { + return EC_FAILURE; + } + int ret = GetSysParam(key, value, len); + if (ret == EC_INVALID) { + return EC_INVALID; + } + if ((ret < 0) && IsValidValue(def, len)) { + if (strncpy_s(value, len, def, len - 1) != 0) { + return EC_FAILURE; + } + ret = (int)strlen(def); + } + return ret; +} + +int SetParameter(const char *key, const char *value) +{ + if ((key == NULL) || (value == NULL)) { + return EC_INVALID; + } + if (!CheckPermission()) { + return EC_FAILURE; + } + if (strncmp(key, FILE_RO, strlen(FILE_RO)) == 0) { + return EC_INVALID; + } + + return SetSysParam(key, value); +} + +const char *GetDeviceType(void) +{ + return HalGetDeviceType(); +} + +const char *GetManufacture(void) +{ + return HalGetManufacture(); +} + +const char *GetBrand(void) +{ + return HalGetBrand(); +} + +const char *GetMarketName(void) +{ + return HalGetMarketName(); +} + +const char *GetProductSeries(void) +{ + return HalGetProductSeries(); +} + +const char *GetProductModel(void) +{ + return HalGetProductModel(); +} + +const char *GetSoftwareModel(void) +{ + return HalGetSoftwareModel(); +} + +const char *GetHardwareModel(void) +{ + return HalGetHardwareModel(); +} + +const char *GetHardwareProfile(void) +{ + return HalGetHardwareProfile(); +} + +const char *GetSerial(void) +{ + return HalGetSerial(); +} + +const char *GetBootloaderVersion(void) +{ + return HalGetBootloaderVersion(); +} + +const char *GetSecurityPatchTag(void) +{ + return OHOS_SECURITY_PATCH_TAG; +} + +const char *GetAbiList(void) +{ + return HalGetAbiList(); +} + +static const char *BuildOSFullName(void) +{ + const char release[] = "Release"; + char value[OS_FULL_NAME_LEN]; + const char *releaseType = GetOsReleaseType(); + int length; + if (strncmp(releaseType, release, sizeof(release) - 1) == 0) { + length = sprintf_s(value, OS_FULL_NAME_LEN, "%s-%d.%d.%d.%d", + OHOS_OS_NAME, MAJOR_VERSION, SENIOR_VERSION, FEATURE_VERSION, BUILD_VERSION); + } else { + length = sprintf_s(value, OS_FULL_NAME_LEN, "%s-%d.%d.%d.%d(%s)", + OHOS_OS_NAME, MAJOR_VERSION, SENIOR_VERSION, FEATURE_VERSION, BUILD_VERSION, releaseType); + } + if (length < 0) { + return EMPTY_STR; + } + const char *osFullName = strdup(value); + return osFullName; +} + +const char *GetOSFullName(void) +{ + static const char *osFullName = NULL; + if (osFullName != NULL) { + return osFullName; + } + osFullName = BuildOSFullName(); + if (osFullName == NULL) { + return EMPTY_STR; + } + return osFullName; +} + +static const char *BuildDisplayVersion(void) +{ + ssize_t len; + char patchValue[OHOS_PATCH_VERSION_LEN] = {0}; + char displayValue[OHOS_DISPLAY_VERSION_LEN] = {0}; + int fd = open(OHOS_PATCH_VERSION_FILE, O_RDONLY); + if (fd < 0) { + return NULL; + } + len = read(fd, patchValue, OHOS_PATCH_VERSION_LEN); + if (len < (ssize_t)strlen("version=")) { + close(fd); + return NULL; + } + close(fd); + if (patchValue[len - 1] == '\n') { + patchValue[len - 1] = '\0'; + } + const char *versionValue = HalGetDisplayVersion(); + const int versionLen = strlen(versionValue); + if (versionLen > 0) { + if (versionValue[versionLen - 1] != ')') { + len = sprintf_s(displayValue, OHOS_DISPLAY_VERSION_LEN, "%s(%s)", versionValue, + patchValue + strlen("version=")); + } else { + char tempValue[versionLen]; + (void)memset_s(tempValue, versionLen, 0, versionLen); + if (strncpy_s(tempValue, versionLen, versionValue, versionLen - 1) != 0) { + return NULL; + } + tempValue[versionLen - 1] = '\0'; + len = sprintf_s(displayValue, OHOS_DISPLAY_VERSION_LEN, "%s%s)", tempValue, + patchValue + strlen("version=")); + } + } + if (len < 0) { + return NULL; + } + return strdup(displayValue); +} + +const char *GetDisplayVersion(void) +{ + static const char *displayVersion = NULL; + if (displayVersion != NULL) { + return displayVersion; + } + displayVersion = BuildDisplayVersion(); + if (displayVersion == NULL) { + return HalGetDisplayVersion(); + } + return displayVersion; +} + +int GetSdkApiVersion(void) +{ + return OHOS_SDK_API_VERSION; +} + +int GetFirstApiVersion(void) +{ + return HalGetFirstApiVersion(); +} + +const char *GetIncrementalVersion(void) +{ + return HalGetIncrementalVersion(); +} + +static const char *BuildVersionId(void) +{ + char value[VERSION_ID_LEN]; + int len = sprintf_s(value, VERSION_ID_LEN, "%s/%s/%s/%s/%s/%s/%s/%d/%s/%s", + GetDeviceType(), GetManufacture(), GetBrand(), GetProductSeries(), + GetOSFullName(), GetProductModel(), GetSoftwareModel(), + OHOS_SDK_API_VERSION, GetIncrementalVersion(), GetBuildType()); + if (len < 0) { + return EMPTY_STR; + } + const char *versionId = strdup(value); + return versionId; +} + +const char *GetVersionId(void) +{ + static const char *versionId = NULL; + if (versionId != NULL) { + return versionId; + } + versionId = BuildVersionId(); + if (versionId == NULL) { + return EMPTY_STR; + } + return versionId; +} + +const char *GetBuildType(void) +{ + return HalGetBuildType(); +} + +const char *GetBuildUser(void) +{ + return HalGetBuildUser(); +} + +const char *GetBuildHost(void) +{ + return HalGetBuildHost(); +} + +const char *GetBuildTime(void) +{ + return HalGetBuildTime(); +} + +const char *GetBuildRootHash(void) +{ + return BUILD_ROOTHASH; +} + +const char *GetOsReleaseType(void) +{ + return OHOS_RELEASE_TYPE; +} + +int GetMajorVersion(void) +{ + return 0; +} + +int GetSeniorVersion(void) +{ + return 0; +} + +int GetFeatureVersion(void) +{ + return 0; +} + +int GetBuildVersion(void) +{ + return 0; +} + +const char *GetDistributionOSName(void) +{ + return OHOS_DEFAULT_VALUE; +} + +const char *GetDistributionOSVersion(void) +{ + return OHOS_DEFAULT_VALUE; +} + +int GetDistributionOSApiVersion(void) +{ + return 0; +} + +const char *GetDistributionOSReleaseType(void) +{ + return OHOS_DEFAULT_VALUE; +} + +int GetDevUdid(char *udid, int size) +{ + if (udid == NULL || size < 0) { + return -1; + } + return 0; +} \ No newline at end of file diff --git a/test/BUILD.gn b/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ac4e67b96a8dd06f6077e7eeecbdcf75c6d402fb --- /dev/null +++ b/test/BUILD.gn @@ -0,0 +1,32 @@ +# 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/begetd.gni") + +group("testgroup") { + testonly = true + if (!defined(ohos_lite)) { + deps = [ + "exec_test:exectest", + "fuzztest:fuzztest", + "moduletest:moduletest", + "moduletest:paramtestmodule", + "unittest:init_dmverify_unittest", + "unittest:init_fshvb_unittest", + "unittest:init_unittest", + ] + } else { + if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") { + deps = [ "unittest/lite:init_test" ] + } + } +} diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0100.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..fed60c0246778853a8323b77973d07883d0f9934 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0100.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..ac83ff7103fa4b2075d1a3ba72c9cd50b5e084fc --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0100.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- + +# +# 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. +# + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + + +class SunStartupInitBase0100(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + + def process(self): + bundle_name = "com.generic.hmos.notepad" + for i in range(5): + self.driver.System.reboot() + self.driver.System.wait_for_boot_complete() + + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + self.driver.AppManager.start_app(bundle_name) + pid = self.driver.System.get_pid(bundle_name) + self.driver.Assert.equal(type(pid), int) + self.driver.AppManager.stop_app(bundle_name) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0200.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0200.json new file mode 100644 index 0000000000000000000000000000000000000000..511a6941e5aef8e9a8188efda97777a248538e68 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0200.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_0200.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0200.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0200.py new file mode 100644 index 0000000000000000000000000000000000000000..c109770d45de03943492a94c5e7307cdb598223d --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0200.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +# +# 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. +# + +import os +import time +import gzip +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + + +class SunStartupInitBase0200(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + + def process(self): + Step("清理/data/log/hilog目录") + self.driver.shell("rm -rf /data/log/hilog") + + Step("重启设备") + self.driver.System.reboot() + self.driver.System.wait_for_boot_complete() + + Step("解锁设备") + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + Step("拉取日志匹配关键字") + result = self.driver.shell('ls /data/log/hilog').split() + count = 0 + path = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) + target_path = os.path.join(path, "testFile", "SUB_STARTUP_INIT_BASE") + self.driver.Assert.equal(count, 0) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0300.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0300.json new file mode 100644 index 0000000000000000000000000000000000000000..45767bdd10e30b40eacc8f79b7a0e4fc1320e1f8 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0300.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_0300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0300.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0300.py new file mode 100644 index 0000000000000000000000000000000000000000..c664aa0c429c453888fbba5a4e24fd1935b7fd63 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0300.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# +# 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. +# + +import os +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + + +class SunStartupInitBase0300(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + + Step("解锁设备") + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.shell("power-shell timeout -o 86400000") + + def process(self): + result1 = self.driver.shell("param get ohos.boot.time.init") + self.driver.Assert.equal(result1.split()[0].isdigit(), True) + + result2 = self.driver.shell("param set persist.init.debug.loglevel 0") + self.driver.Assert.contains(result2, "Set parameter persist.init.debug.loglevel 0 success") + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0400.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0400.json new file mode 100644 index 0000000000000000000000000000000000000000..e95c51d7ddf83595731fd922e3eeb029cd3cebc1 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0400.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_0400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0400.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0400.py new file mode 100644 index 0000000000000000000000000000000000000000..96085f63682e23334615cb18e6a10a6c50be9049 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0400.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# +# 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. +# + +import os +import sys +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from aw import Common + + +class SunStartupInitBase0400(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + + def process(self): + result = self.driver.hdc("target mount") + self.driver.Assert.contains(result, "Mount finish") + + txt_path = Common.sourcepath('test.txt', "SUB_STARTUP_INIT_BASE") + self.driver.push_file(txt_path, "/system") + + has_file = self.driver.Storage.has_file("/system/test.txt") + self.driver.Assert.equal(has_file, True) + self.driver.shell("echo '123456' > /system/test.txt") + + self.driver.System.reboot() + self.driver.System.wait_for_boot_complete() + + content = self.driver.shell("cat /system/test.txt") + self.driver.Assert.contains(content, "123456") + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0500.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0500.json new file mode 100644 index 0000000000000000000000000000000000000000..bc3bd819e2767e127ae6cef1d9048ddb4c5990e9 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0500.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_0500.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0500.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0500.py new file mode 100644 index 0000000000000000000000000000000000000000..cf8405f5006ec6e6231a5c6fece025c2d33c430f --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_0500.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +# +# 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. +# + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + + +class SunStartupInitBase0500(TestCase): + def __init__(self, controllers): + self.tag = self.__class__.__name__ + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + + def process(self): + bundle_name = "com.generic.hmos.notepad" + self.driver.shell("write_updater user_factory_reset") + self.driver.shell("reboot updater") + self.driver.System.wait_for_boot_complete() + self.driver.AppManager.disable_startup_guide() + + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + self.driver.AppManager.start_app(bundle_name) + pid = self.driver.System.get_pid(bundle_name) + self.driver.Assert.equal(type(pid), int) + self.driver.AppManager.stop_app(bundle_name) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1600.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1600.json new file mode 100644 index 0000000000000000000000000000000000000000..7ec4b0328739624a3a1373a407bec26335651165 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1600.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_1600.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1600.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1600.py new file mode 100644 index 0000000000000000000000000000000000000000..e7538f40686ec7cc6d470275a0292210d91fd211 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1600.py @@ -0,0 +1,86 @@ +# +# 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. +# + +import os +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBase1600(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件param_watcher.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /etc/init/param_watcher.cfg /etc/init/param_watcher.cfg_bak") + Step("把系统文件param_watcher.cfg拉到本地..........................") + devpath = "/etc/init/param_watcher.cfg" + self.driver.pull_file(devpath, "testFile/SUB_STARTUP_INIT_BASE/param_watcher.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile/SUB_STARTUP_INIT_BASE") + localpath = os.path.join(path2, "param_watcher.cfg") + with open(localpath, "r") as y: + for line in y: + lines1.append(line) + y.close() + Step(lines1) + line = lines1.index(' "services" : [{\n') + 1 + d_caps_entry = '\t\t\t"importance" : -20,\n' + lines1.insert(line, d_caps_entry) + s = ''.join(lines1) + Step(s) + with open(localpath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localpath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行启动服务命令begetctl start_service param_watcher..........................") + self.driver.shell('begetctl start_service param_watcher') + Step("查看服务状态ps -Al | grep param_watcher..........................") + result = self.driver.shell('ps -Al | grep param_watcher') + Step(result) + self.driver.Assert.contains(result, '-20') + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件useriam.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /etc/init/param_watcher.cfg") + self.driver.shell( + "mv /etc/init/param_watcher.cfg_bak /etc/init/param_watcher.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1700.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1700.json new file mode 100644 index 0000000000000000000000000000000000000000..936c9dd0d0719406c130798aa43eca090bc56225 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1700.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_1700.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1700.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1700.py new file mode 100644 index 0000000000000000000000000000000000000000..9a58476528dae704e22147c68ce7ad4f19018db5 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1700.py @@ -0,0 +1,87 @@ + +# +# 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. +# + +import os +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBase1700(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件param_watcher.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /etc/init/param_watcher.cfg /etc/init/param_watcher.cfg_bak") + Step("把系统文件param_watcher.cfg拉到本地..........................") + devpath = "/etc/init/param_watcher.cfg" + self.driver.pull_file(devpath, "testFile/SUB_STARTUP_INIT_BASE/param_watcher.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile/SUB_STARTUP_INIT_BASE") + localpath = os.path.join(path2, "param_watcher.cfg") + with open(localpath, "r") as y: + for line in y: + lines1.append(line) + y.close() + Step(lines1) + line = lines1.index(' "services" : [{\n') + 1 + d_caps_entry = '\t\t\t"d-caps" : ["OHOS_DMS"],\n\t\t\t"apl" : "normal",\n' + lines1.insert(line, d_caps_entry) + s = ''.join(lines1) + Step(s) + with open(localpath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localpath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行启动服务命令begetctl start_service param_watcher..........................") + self.driver.shell('begetctl start_service param_watcher') + Step("查看nativetoken.json..........................") + result = self.driver.shell('cat data/service/el0/access_token/nativetoken.json') + Step(result) + self.driver.Assert.contains(result, '"processName":"param_watcher","APL":1') + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件useriam.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /etc/init/param_watcher.cfg") + self.driver.shell( + "mv /etc/init/param_watcher.cfg_bak /etc/init/param_watcher.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1800.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1800.json new file mode 100644 index 0000000000000000000000000000000000000000..7c41754f4fd4e2c88cc65f33ed316bb92d94a188 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1800.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_1800.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1800.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1800.py new file mode 100644 index 0000000000000000000000000000000000000000..063389dd8988ccd8d4ebb7f0af604b0a98877fcb --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1800.py @@ -0,0 +1,88 @@ +# +# 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. +# + +import os +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBase1800(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件param_watcher.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /etc/init/param_watcher.cfg /etc/init/param_watcher.cfg_bak") + Step("把系统文件param_watcher.cfg拉到本地..........................") + devpath = "/etc/init/param_watcher.cfg" + self.driver.pull_file(devpath, "testFile/SUB_STARTUP_INIT_BASE/param_watcher.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile/SUB_STARTUP_INIT_BASE") + localpath = os.path.join(path2, "param_watcher.cfg") + with open(localpath, "r") as y: + for line in y: + lines1.append(line) + y.close() + Step(lines1) + line = lines1.index(' "services" : [{\n') + 1 + d_caps_entry = '\t\t\t"cpucore" : [0, 1],\n' + lines1.insert(line, d_caps_entry) + s = ''.join(lines1) + Step(s) + with open(localpath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localpath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行启动服务命令begetctl start_service param_watcher..........................") + self.driver.shell('begetctl start_service param_watcher') + Step("查看param_watcher服务pid..........................") + pid = self.driver.System.get_pid('param_watcher') + Step("查看param_watcher服务的亲和力掩码..........................") + result = self.driver.shell('taskset -p ' + str(pid)) + Step(result) + self.driver.Assert.contains(result, 'current affinity mask: 3') + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件useriam.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /etc/init/param_watcher.cfg") + self.driver.shell( + "mv /etc/init/param_watcher.cfg_bak /etc/init/param_watcher.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1900.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1900.json new file mode 100644 index 0000000000000000000000000000000000000000..505fdab2b55fcf8f0345cf532d7082541cec10fc --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1900.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_1900.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1900.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1900.py new file mode 100644 index 0000000000000000000000000000000000000000..85a6e5e87834b973eaa38aa3a4304504d8aa133d --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_1900.py @@ -0,0 +1,88 @@ +# +# 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. +# + +import os +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBase1900(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件param_watcher.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /etc/init/param_watcher.cfg /etc/init/param_watcher.cfg_bak") + Step("把系统文件param_watcher.cfg拉到本地..........................") + devpath = "/etc/init/param_watcher.cfg" + self.driver.pull_file(devpath, "testFile/SUB_STARTUP_INIT_BASE/param_watcher.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile/SUB_STARTUP_INIT_BASE") + localpath = os.path.join(path2, "param_watcher.cfg") + with open(localpath, "r") as y: + for line in y: + lines1.append(line) + y.close() + Step(lines1) + line = lines1.index(' "services" : [{\n') + 1 + d_caps_entry = '\t\t\t"cpucore" : [20],\n' + lines1.insert(line, d_caps_entry) + s = ''.join(lines1) + Step(s) + with open(localpath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localpath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行启动服务命令begetctl start_service param_watcher..........................") + self.driver.shell('begetctl start_service param_watcher') + Step("查看param_watcher服务pid..........................") + pid = self.driver.System.get_pid('param_watcher') + Step("查看param_watcher服务的亲和力掩码..........................") + result = self.driver.shell('taskset -p ' + str(pid)) + Step(result) + self.driver.Assert.contains(result, 'current affinity mask: ff') + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件useriam.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /etc/init/param_watcher.cfg") + self.driver.shell( + "mv /etc/init/param_watcher.cfg_bak /etc/init/param_watcher.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_2700.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_2700.json new file mode 100644 index 0000000000000000000000000000000000000000..54ea375581a7db32f69393960c0236f82c414403 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_2700.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_2700.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_2700.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_2700.py new file mode 100644 index 0000000000000000000000000000000000000000..fe92304d6b1cb0cb2d135e6f6e8da5362e1340fb --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_2700.py @@ -0,0 +1,44 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBase2700(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("执行启动服务命令begetctl start_service param_watcher..........................") + self.driver.shell('begetctl start_service param_watcher') + Step("查看param_watcher服务..........................") + result = self.driver.shell(' ps -AZ | grep param_watcher') + Step(result) + self.driver.Assert.contains(result, 'u:r:param_watcher:s0') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_3600.json b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_3600.json new file mode 100644 index 0000000000000000000000000000000000000000..910048bd6507b7b1f986a77fe09d02ec8e462a86 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_3600.json @@ -0,0 +1,15 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BASE/Sub_Starup_Init_Base_3600.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_3600.py b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_3600.py new file mode 100644 index 0000000000000000000000000000000000000000..527ffb1dccc102e7613c5bb0188e160614fe00b9 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BASE/sub_starup_init_base_3600.py @@ -0,0 +1,51 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBase3600(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("执行命令begetctl..........................") + result_beg = self.driver.shell('begetctl') + Step(result_beg) + self.driver.Assert.contains(result_beg, 'dump_service loop') + Step("执行命令begetctl dump_service..........................") + result_beg_dump_ser = self.driver.shell('begetctl dump_service') + Step(result_beg_dump_ser) + self.driver.Assert.contains(result_beg_dump_ser, 'dump_service loop') + Step("执行命令begetctl dump_service loop..........................") + result_beg_dump_ser_loop = self.driver.shell('begetctl dump_service loop') + Step(result_beg_dump_ser_loop) + self.driver.Assert.contains(result_beg_dump_ser_loop, 'dump service info') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0100.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..0b9d5c8d875ab6b24dfaa421067c59ec1c9fb5af --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0100.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..8002cc82fb09628139a9327c7d0a9f6daf853ab3 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0100.py @@ -0,0 +1,47 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0100(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取appspawn的pid.................") + pid = self.driver.System.get_pid("appspawn") + Step(pid) + sleep(1) + Step("查看appspawn的memory.................") + result = self.driver.shell('begetctl display memory ' + str(pid)) + Step("检查结果.................") + self.driver.Assert.contains(result, 'Total mem') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0200.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0200.json new file mode 100644 index 0000000000000000000000000000000000000000..88415c076cc3eece5dd371a45cc07278eb2b9729 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0200.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0200.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0200.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0200.py new file mode 100644 index 0000000000000000000000000000000000000000..ad812b017e7c0cde2e216b764d77ae8a7853d701 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0200.py @@ -0,0 +1,74 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0200(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取param ls结果.................") + result_param_ls = self.driver.shell('begetctl param ls') + Step(result_param_ls) + Step("检查param ls结果.................") + self.driver.Assert.contains(result_param_ls, 'Parameter information:') + self.driver.Assert.contains(result_param_ls, 'selinux :') + self.driver.Assert.contains(result_param_ls, 'dac :') + sleep(1) + Step("获取param ls -r结果.................") + result_param_ls_r = self.driver.shell('begetctl param ls -r') + Step(result_param_ls_r) + Step("检查param ls -r结果.................") + self.driver.Assert.contains(result_param_ls_r, 'Parameter information:') + self.driver.Assert.contains(result_param_ls_r, 'selinux :') + self.driver.Assert.contains(result_param_ls_r, 'dac :') + self.driver.Assert.contains(result_param_ls_r, 'name :') + self.driver.Assert.contains(result_param_ls_r, 'value:') + sleep(1) + Step("获取param ls name结果.................") + result_param_ls_name = self.driver.shell('begetctl param ls const.cust.vendor') + Step(result_param_ls_name) + Step("检查param ls name结果.................") + self.driver.Assert.contains(result_param_ls_name, 'Parameter information:') + self.driver.Assert.contains(result_param_ls_name, 'selinux : u:object_r:default_param:s0') + self.driver.Assert.contains(result_param_ls_name, 'dac : root(rww) root(rww) (r--)') + self.driver.Assert.contains(result_param_ls_name, 'name : const.cust.vendor') + sleep(1) + Step("获取param ls -r name结果.................") + result_param_ls_r_name = self.driver.shell('begetctl param ls -r const.cust.vendor') + Step(result_param_ls_r_name) + Step("检查param ls -r name结果.................") + self.driver.Assert.contains(result_param_ls_r_name, 'Parameter information:') + self.driver.Assert.contains(result_param_ls_r_name, 'selinux : u:object_r:default_param:s0') + self.driver.Assert.contains(result_param_ls_r_name, 'dac : root(rww) root(rww) (r--)') + self.driver.Assert.contains(result_param_ls_r_name, 'name : const.cust.vendor') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0300.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0300.json new file mode 100644 index 0000000000000000000000000000000000000000..814214a08c87d5e1731b647cabff09e6918dc95b --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0300.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0300.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0300.py new file mode 100644 index 0000000000000000000000000000000000000000..f206c9a4745209c78c9f346b6309390e598eb88e --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0300.py @@ -0,0 +1,50 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0300(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("设置参数.................") + result_set = self.driver.shell('begetctl param set test test.value') + Step(result_set) + Step("检查设置参数.................") + self.driver.Assert.contains(result_set, 'Set parameter test test.value success') + sleep(1) + Step("获取参数.................") + result_get = self.driver.shell('begetctl param get test') + Step(result_get) + Step("检查获取参数.................") + self.driver.Assert.contains(result_get, 'test.value') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0400.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0400.json new file mode 100644 index 0000000000000000000000000000000000000000..9840a18016f040e282ba40ee3b9093c42a821e7a --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0400.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0400.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0400.py new file mode 100644 index 0000000000000000000000000000000000000000..a4337dd2cd62800aa1b505e6b57a281c06846c75 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0400.py @@ -0,0 +1,60 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0400(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取param wait name结果.................") + result_wait_name = self.driver.shell('begetctl param wait const.cust.vendor') + Step(result_wait_name) + Step("检查param wait name结果.................") + self.driver.Assert.contains(result_wait_name, 'Wait parameter const.cust.vendor success') + sleep(1) + Step("获取param wait name value结果.................") + result = self.driver.shell("begetctl param ls -r const.cust.vendor | grep value") + result = result.strip() + value = result.split("value:")[1] + result_wait_name_value = self.driver.shell('begetctl param wait const.cust.vendor %s' % value) + Step(result_wait_name_value) + Step("检查param wait name value结果.................") + self.driver.Assert.contains(result_wait_name_value, 'Wait parameter const.cust.vendor success') + sleep(1) + Step("获取param wait name value timeout结果.................") + result_wait_name_value_timeout = self.driver.shell('begetctl param wait const.cust.vendor %s 10' % value) + Step(result_wait_name_value_timeout) + Step("检查param wait name value timeout结果.................") + self.driver.Assert.contains(result_wait_name_value_timeout, 'Wait parameter const.cust.vendor success') + sleep(1) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0500.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0500.json new file mode 100644 index 0000000000000000000000000000000000000000..fe015c38707e555065ee1714a7a71892de644540 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0500.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0500.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0500.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0500.py new file mode 100644 index 0000000000000000000000000000000000000000..8e02fb6a8de18e0fcb7865d2337d2ae86b83d6a2 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0500.py @@ -0,0 +1,43 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0500(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取param dump结果.................") + result = self.driver.shell('begetctl param dump') + Step(result) + Step("检查param dump结果.................") + self.driver.Assert.contains(result, 'Dump all parameters finish') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0600.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0600.json new file mode 100644 index 0000000000000000000000000000000000000000..2a2afa4d35ccd3fb3dcb16a14d93e7eaaea0830e --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0600.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0600.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0600.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0600.py new file mode 100644 index 0000000000000000000000000000000000000000..08e684079a7c47cfe48831f93f40d4a58df9bec6 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0600.py @@ -0,0 +1,43 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0600(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取param save结果.................") + result = self.driver.shell('begetctl param save') + Step(result) + Step("检查param dump结果.................") + self.driver.Assert.contains(result, 'Save persist parameters success') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0700.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0700.json new file mode 100644 index 0000000000000000000000000000000000000000..bd5aa4361abc725190eb308b8f1cb838a8d60d78 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0700.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0700.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0700.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0700.py new file mode 100644 index 0000000000000000000000000000000000000000..ac981ca8bd42f41df3665e81a1855195e8fdd84f --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0700.py @@ -0,0 +1,47 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0700(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取dump api结果.................") + result = self.driver.shell('begetctl dump api') + Step(result) + Step("检查dump api结果.................") + self.driver.Assert.contains(result, 'DeviceType') + self.driver.Assert.contains(result, 'Manufacture') + self.driver.Assert.contains(result, 'Brand') + self.driver.Assert.contains(result, 'MarketName') + self.driver.Assert.contains(result, 'ProductSeries') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0800.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0800.json new file mode 100644 index 0000000000000000000000000000000000000000..a601a5dc6e8ef8188dfc494312ea1ba30218bdb7 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0800.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0800.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0800.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0800.py new file mode 100644 index 0000000000000000000000000000000000000000..b53655616e2edfce747983e09ed0717a5658b38a --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0800.py @@ -0,0 +1,50 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0800(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("设置日志级别.................") + result_set = self.driver.shell('begetctl setloglevel 1') + Step(result_set) + Step("检查设置日志级别.................") + self.driver.Assert.contains(result_set, 'Success to set log level by param "persist.init.debug.loglevel" 1') + sleep(1) + Step("获取日志级别.................") + result_get = self.driver.shell('begetctl getloglevel') + Step(result_get) + Step("检查获取日志级别.................") + self.driver.Assert.contains(result_get, 'Success to get init log level: 1 from param "persist.init.debug.loglevel"') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0900.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0900.json new file mode 100644 index 0000000000000000000000000000000000000000..9f1b68a2d5f510d8cec8f7bae1c9139926e87d71 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0900.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_0900.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0900.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0900.py new file mode 100644 index 0000000000000000000000000000000000000000..268008414a1944d2cdf845d8eef9ed9c4e43717b --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_0900.py @@ -0,0 +1,53 @@ +# +# 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. +# + +import gzip +import os +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl0900(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("执行begetctl命令") + service_list = ["begetctl timer_start media_service 10000", "begetctl stop_service media_service", "dmesg|grep media_service"] + for i in service_list: + self.driver.shell(i) + sleep(3) + + Step("日志匹配") + result = self.driver.shell('ls /data/log/hilog').split() + count = 0 + path = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) + log = os.path.join(path, "testFile", "Log") + self.driver.Assert.greater(count, 0) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1000.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1000.json new file mode 100644 index 0000000000000000000000000000000000000000..ad974d5f516a38f98c6a1853ec4c69fcf19c3937 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1000.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_1000.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1000.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1000.py new file mode 100644 index 0000000000000000000000000000000000000000..2a525f05a7415183e67e4d860bfe0b94e32b08ed --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1000.py @@ -0,0 +1,56 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl1000(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取hiview的pid.................") + pid = self.driver.System.get_pid("hiview") + Step(pid) + sleep(1) + Step("停止hiview服务.................") + self.driver.shell('begetctl stop_service hiview') + Step("获取hiview的pid.................") + pid1 = self.driver.System.get_pid("hiview") + Step(pid1) + sleep(1) + Step("启动hiview服务.................") + self.driver.shell('begetctl start_service hiview') + Step("获取hiview的pid.................") + pid2 = self.driver.System.get_pid("hiview") + Step(pid2) + if (!pid2) + + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1100.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1100.json new file mode 100644 index 0000000000000000000000000000000000000000..f300f969a07b0d298d7c1444c4e8127b06a7a295 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_1100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1100.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1100.py new file mode 100644 index 0000000000000000000000000000000000000000..6b6790beda1efcf7ed7cd90f606d7ef424ecc3e6 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1100.py @@ -0,0 +1,54 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl1100(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("获取hiview的pid.................") + pid = self.driver.System.get_pid("hiview") + Step(pid) + sleep(1) + Step("停止hiview服务.................") + self.driver.shell('begetctl service_control stop hiview') + Step("获取hiview的pid.................") + pid1 = self.driver.System.get_pid("hiview") + Step(pid1) + sleep(1) + Step("启动hiview服务.................") + self.driver.shell('begetctl service_control start hiview') + Step("获取hiview的pid.................") + pid2 = self.driver.System.get_pid("hiview") + Step(pid2) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1200.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1200.json new file mode 100644 index 0000000000000000000000000000000000000000..6924c6fe2ee3d2ff64759163b452e2dd3aebd5c1 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1200.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_1200.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1200.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1200.py new file mode 100644 index 0000000000000000000000000000000000000000..db35debee7d04c4a84cd8b52c267be8f544e9b63 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1200.py @@ -0,0 +1,50 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl1200(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("设置bootevent enable.................") + result_enable = self.driver.shell('begetctl bootevent enable') + Step(result_enable) + Step("检查bootevent enable结果.................") + self.driver.Assert.contains(result_enable, 'bootevent enabled') + sleep(1) + Step("设置bootevent disable.................") + result_disable = self.driver.shell('begetctl bootevent disable') + Step(result_disable) + Step("检查bootevent disable结果.................") + self.driver.Assert.contains(result_disable, 'bootevent disabled') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1300.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1300.json new file mode 100644 index 0000000000000000000000000000000000000000..615b69c3eba92726dd1976762be6a7c2520152cb --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1300.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_1300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1300.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1300.py new file mode 100644 index 0000000000000000000000000000000000000000..bc72d9c777b3a757ac696e9be9960285d87155de --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1300.py @@ -0,0 +1,44 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl1300(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("查看system的uid.................") + result = self.driver.shell('begetctl dac uid system') + Step(result) + Step("检查system的uid结果.................") + self.driver.Assert.contains(result, 'getpwnam uid system : 1000') + self.driver.Assert.contains(result, 'getpwent uid system : 1000') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1400.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1400.json new file mode 100644 index 0000000000000000000000000000000000000000..0e943ab0befd71de76b7509c09ec124d27e8104a --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1400.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl_1400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1400.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1400.py new file mode 100644 index 0000000000000000000000000000000000000000..841632e800d44774e9ecce5f7199a6fafcfac079 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1400.py @@ -0,0 +1,44 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl1400(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("查看system的gid.................") + result = self.driver.shell('begetctl dac gid system') + Step(result) + Step("检查system的gid结果.................") + self.driver.Assert.contains(result, 'getgrnam gid system : 1000') + self.driver.Assert.contains(result, 'getgrent gid system : 1000') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1500.json b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1500.json new file mode 100644 index 0000000000000000000000000000000000000000..91e0b45c7fd16783cfea785e7d0d23ff877c9aca --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1500.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BEGETCTL/Sub_Startup_Init_Begetctl1500.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1500.py b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1500.py new file mode 100644 index 0000000000000000000000000000000000000000..db5b6229ee55a82fad82d182cbeec44a12b484e8 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BEGETCTL/sub_startup_init_begetctl_1500.py @@ -0,0 +1,50 @@ +# +# 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. +# + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SunStartupInitBegetctl1500(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("设置日志级别.................") + result_set = self.driver.shell('begetctl set log level 1') + Step(result_set) + Step("检查设置日志级别.................") + self.driver.Assert.contains(result_set, 'Success to set log level INFO') + sleep(1) + Step("获取日志级别.................") + result_get = self.driver.shell('begetctl get log level') + Step(result_get) + Step("检查获取日志级别.................") + self.driver.Assert.contains(result_get, 'Init log level:') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BOOT/sub_startup_init_boot_0100.json b/test/autotest/testcases/SUB_STARTUP_INIT_BOOT/sub_startup_init_boot_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..2c287920a7640e166d2138aec90d40d03013086e --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BOOT/sub_startup_init_boot_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_BOOT/Sub_Startup_Init_Boot_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_BOOT/sub_startup_init_boot_0100.py b/test/autotest/testcases/SUB_STARTUP_INIT_BOOT/sub_startup_init_boot_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..1abe895572776deadad7f4ea3694c140fca9ab3e --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_BOOT/sub_startup_init_boot_0100.py @@ -0,0 +1,96 @@ +# +# 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. +# + +import os +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiDriver + + +class SubStartupInitBoot0100(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件useriam.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /etc/init/useriam.cfg /etc/init/useriam.cfg_bak") + Step("把系统文件useriam.cfg拉到本地..........................") + devpath = "/etc/init/useriam.cfg" + self.driver.pull_file(devpath, "testFile/SUB_STARTUP_INIT_BOOT/useriam.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile/SUB_STARTUP_INIT_BOOT") + localpath = os.path.join(path2, "useriam.cfg") + with open(localpath, "r") as y: + for line in y: + lines1.append(line) + y.close() + Step(lines1) + line = lines1.index(' "services" : [{\n') + 1 + d_caps_entry = '\t\t\t"bootevents" : ["bootevent.useriam.fwkready"],\n' + lines1.insert(line, d_caps_entry) + s = ''.join(lines1) + Step(s) + line = lines1.index('{\n') + 1 + d_caps_entry = [ + '\t],\n', + '\t\t}\n', + '\t\t\t"cmds" : ["mkdir /data/service/el1/public/userauth/ 0700 useriam useriam"]\n', + '\t\t\t"name" : "service:useriam",\n', + '\t"jobs" : [{\n' + ] + for i in d_caps_entry: + lines1.insert(line, i) + s = ''.join(lines1) + Step(s) + with open(localpath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localpath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行命令param get bootevent.boot.completed..........................") + result = self.driver.shell('param get bootevent.boot.completed') + Step(result) + self.driver.Assert.contains(result, 'true') + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件useriam.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /etc/init/useriam.cfg") + self.driver.shell( + "mv /etc/init/useriam.cfg_bak /etc/init/useriam.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.json b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..5c31b6c86139811c1837190c797524a1f95ad5ea --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.py b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..43c9a472674489aa54a30ca3dcb107524f00aeb5 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0100.py @@ -0,0 +1,62 @@ +# 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. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + +class SUB_STARTUP_INIT_PARAMPERSIST_0100(TestCase): + + def __init__(self, controllers): + self.Tag = self.__class__.__name__ + TestCase.__init__(self, self.Tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + self.driver.hdc("target mount") + Step("hilog.para文件中添加persist.test1=true") + self.driver.shell("sed -i '14a\persist.test1=true' /system/etc/param/hilog.para") + + Step("重启设备") + self.driver.System.reboot() + self.driver.System.wait_for_boot_complete() + + Step("查询hilog.para文件中有persist.test1=true") + param1 = self.driver.shell("cat /system/etc/param/hilog.para").split("\n") + self.driver.Assert.contains(param1, 'persist.test1=true') + + Step("确认持久化参数文件中无persist.test1=true") + has_file = self.driver.Storage.has_file("/data/service/el1/startup/parameters/public_persist_parameters") + self.driver.Assert.equal(has_file, True) + param2 = self.driver.shell("cat /data/service/el1/startup/parameters/public_persist_parameters").split("\n") + self.driver.Assert.equal(param2.count('persist.test1=true'), 0) + + def teardown(self): + Step("收尾工作.................") + diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.json b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.json new file mode 100644 index 0000000000000000000000000000000000000000..e6fced72fa6567f82ae50f212c6458c931e404ba --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.py b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.py new file mode 100644 index 0000000000000000000000000000000000000000..a9a00ad868c362981bef61ba37afe8c4f05f8b86 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0200.py @@ -0,0 +1,57 @@ +# 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. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + +class SUB_STARTUP_INIT_PARAMPERSIST_0200(TestCase): + + def __init__(self, controllers): + self.Tag = self.__class__.__name__ + TestCase.__init__(self, self.Tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + self.driver.hdc("target mount") + Step("param set设置persist.***参数") + self.driver.shell("param set persist.test2 false") + + Step("param get获取persist.***参数为false") + param1 = self.driver.shell("param get persist.test2") + self.driver.Assert.contains(param1, 'false') + + Step("查询持久化参数文件中有persist.test2=false") + has_file = self.driver.Storage.has_file("/data/service/el1/startup/parameters/public_persist_parameters") + self.driver.Assert.equal(has_file, True) + param2 = self.driver.shell("cat /data/service/el1/startup/parameters/public_persist_parameters").split("\n") + self.driver.Assert.equal(param2.count("persist.test2=false"), 1) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.json b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.json new file mode 100644 index 0000000000000000000000000000000000000000..aad1961794415a1a8d56b04990573092ac5b66e4 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.py b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.py new file mode 100644 index 0000000000000000000000000000000000000000..8e71ff7dc9a235c07ef4e98d763a2c852fb8ab0d --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0300.py @@ -0,0 +1,63 @@ +# 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. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + +class SUB_STARTUP_INIT_PARAMPERSIST_0300(TestCase): + + def __init__(self, controllers): + self.Tag = self.__class__.__name__ + TestCase.__init__(self, self.Tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + self.driver.hdc("target mount") + Step("hilog.para文件中添加persist.***") + self.driver.shell("sed -e '16a\persist.test3=true' system/etc/param/hilog.para") + + Step("重启设备") + self.driver.System.reboot() + self.driver.System.wait_for_boot_complete() + + Step("确认持久化参数文件中无persist.***") + param1 = self.driver.shell("cat /data/service/el1/startup/parameters/persist_parameters").split("\n") + self.driver.Assert.equal(param1.count("persist.test3=false"), 0) + + time.sleep(3) + Step("param set设置persist.***参数后查询") + self.driver.shell("param set persist.test3 false") + has_file = self.driver.Storage.has_file("/data/service/el1/startup/parameters/public_persist_parameters") + self.driver.Assert.equal(has_file, True) + param2 = self.driver.shell("cat /data/service/el1/startup/parameters/public_persist_parameters").split("\n") + self.driver.Assert.equal(param2.count("persist.test3=false"), 1) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.json b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.json new file mode 100644 index 0000000000000000000000000000000000000000..d5c9b58ec845a8426278253c8d4f32d372162184 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.py b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.py new file mode 100644 index 0000000000000000000000000000000000000000..1c4306abbbd3d29c44f2aef2e3eef26d3264a7e0 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMPERSIST/SUB_STARTUP_INIT_PARAMPERSIST_0400.py @@ -0,0 +1,53 @@ +# 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. + +import time +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver + +class SUB_STARTUP_INIT_PARAMPERSIST_0400(TestCase): + + def __init__(self, controllers): + self.Tag = self.__class__.__name__ + TestCase.__init__(self, self.Tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step(self.devices[0].device_id) + device = self.driver.shell("param get const.product.model") + device = device.replace("\n", "").replace(" ", "") + device = str(device) + Step(device) + # 解锁屏幕 + wake = self.driver.Screen.is_on() + time.sleep(0.5) + if wake: + self.driver.ScreenLock.unlock() + else: + self.driver.Screen.wake_up() + self.driver.ScreenLock.unlock() + self.driver.Screen.enable_stay_awake() + + def process(self): + self.driver.hdc("target mount") + Step("param set设置persist.***参数后重启查询") + self.driver.shell("param set persist.test4 false") + self.driver.System.reboot() + self.driver.System.wait_for_boot_complete() + has_file = self.driver.Storage.has_file("/data/service/el1/startup/parameters/public_persist_parameters") + self.driver.Assert.equal(has_file, True) + param = self.driver.shell("cat /data/service/el1/startup/parameters/public_persist_parameters").split("\n") + self.driver.Assert.equal(param.count('persist.test4=false'), 1) + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.json b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..c1216c448af0d185d3b0f97aa9b419b0eee3a693 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.py b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..9a555abba6ee235a8bf12a2cdd8e5059647f5d21 --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAMSAVE/SUB_STARTUP_INIT_PARAMSAVE_0100.py @@ -0,0 +1,62 @@ +# 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. + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import * + + +class SUB_STARTUP_INIT_PARAMSAVE_0100(TestCase): + + def __init__(self, controllers): + self.Tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.Tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("第一次设置参数persist.test................") + persist_test_1 = self.driver.shell("param set persist.test 123") + Step(persist_test_1) + self.driver.Assert.contains(persist_test_1,'Set parameter persist.test 123 success', '参数设置失败') + sleep(1) + Step("检查设置结果................") + persist_test_result_1 = self.driver.shell( + "cat /data/service/el1/startup/parameters/public_persist_parameters | grep persist.test") + self.driver.Assert.contains(persist_test_result_1, "persist.test=123", '持久化参数设置失败') + Step("第二次设置参数persist.test................") + persist_test_2 = self.driver.shell("param set persist.test 123456") + Step(persist_test_2) + self.driver.Assert.contains(persist_test_2, 'Set parameter persist.test 123456 success', '参数设置失败') + Step("第三次设置参数persist.test................") + persist_test_3 = self.driver.shell("param set persist.test abc123") + Step(persist_test_3) + self.driver.Assert.contains(persist_test_3, 'Set parameter persist.test abc123 success', '参数设置失败') + Step('保存参数设置') + persist_test_save= self.driver.shell("param save") + Step(persist_test_save) + self.driver.Assert.contains(persist_test_save, 'Save persist parameters success', '参数保存失败') + Step("检查保存结果................") + persist_test_result = self.driver.shell( + "cat /data/service/el1/startup/parameters/public_persist_parameters| grep persist.test") + self.driver.Assert.contains(persist_test_result, "persist.test=abc123", '持久化参数保存失败') + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.json b/test/autotest/testcases/SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.json new file mode 100644 index 0000000000000000000000000000000000000000..e112726f94d2f487e8b395484fa0b58c3898f21e --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.py b/test/autotest/testcases/SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.py new file mode 100644 index 0000000000000000000000000000000000000000..a584d318fbcd0e0db6da9d020b8cba57d4feb47a --- /dev/null +++ b/test/autotest/testcases/SUB_STARTUP_INIT_PARAM_RIGHT/SUB_STARTUP_INIT_PARAM_RIGHT_0100.py @@ -0,0 +1,41 @@ +# 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. + +# -*- coding: utf-8 -*- +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import * + + +class SUB_STARTUP_INIT_PARAM_RIGHT_0100(TestCase): + + def __init__(self, controllers): + self.TAG = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.TAG, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("查看系统参数标签.................") + result = self.driver.shell("ls dev/__parameters__/") + Step(result) + self.driver.Assert.contains(result, "u:object_r:accessibility_param:s0", "系统标签不存在") + + def teardown(self): + Step("收尾工作.................") diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.json b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.json new file mode 100644 index 0000000000000000000000000000000000000000..816598f8b3f67b3489b96f48f5f91128cee714b4 --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.py b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.py new file mode 100644 index 0000000000000000000000000000000000000000..91409a10d23c6d4417adb5ffe837c9913637b46b --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0500.py @@ -0,0 +1,81 @@ +# 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. + +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiParam +import os + + +class SubStartupInitAbilityUp0500(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机/pc开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件param_watcher.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /system/etc/init/param_watcher.cfg /system/etc/init/param_watcher.cfg_bak") + Step("把系统文件param_watcher.cfg拉到本地..........................") + devpath = "/system/etc/init/param_watcher.cfg" + self.driver.pull_file(devpath, "testFile/SubStartupInitAbilityUp/param_watcher.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile\SubStartupInitAbilityUp") + localpath = os.path.join(path2, "param_watcher.cfg") + with open(localPath, "r") as y: + for line in y: + lines1.append(line) + y.close() + Step(lines1) + line = lines1.index(' "services" : [{\n') + 1 + list_item = '\t\t\t"importance" : 100,\n' + lines1.insert(line, list_item) + s = ''.join(lines1) + Step(s) + with open(localPath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localPath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + Step("执行命令begetctl dump_service..........................") + result = self.driver.shell('begetctl dump_service param_watcher') + Step(result) + pid = self.driver.System.get_pid('param_watcher') + Step(pid) + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件param_watcher.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /system/etc/init/param_watcher.cfg") + self.driver.shell( + "mv /system/etc/init/param_watcher.cfg_bak /system/etc/init/param_watcher.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.json b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.json new file mode 100644 index 0000000000000000000000000000000000000000..5d6231d146c756d2de4689ae6bd88b3b2a70d25b --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.py b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.py new file mode 100644 index 0000000000000000000000000000000000000000..7c6356c77d046992ebd487d4b2e23cec25d1ef71 --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0600.py @@ -0,0 +1,86 @@ +# 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. + +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiParam +import os + + +class SubStartupInitAbilityUp0600(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件wifi_standard.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /system/etc/init/wifi_standard.cfg /system/etc/init/wifi_standard.cfg_bak") + Step("把系统文件wifi_standard.cfg拉到本地..........................") + devpath = "/system/etc/init/wifi_standard.cfg" + self.driver.pull_file(devpath, "testFile/SubStartupInitAbilityUp/wifi_standard.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile\SubStartupInitAbilityUp") + localpath = os.path.join(path2, "wifi_standard.cfg") + with open(localPath, "r") as y: + for line in y: + lines1.append(line) + y.close() + line = lines1.index(' "name" : "wifi_manager_service",\n') + 1 + res1 = line + Step(f"目标索引:{res1}") + index_str1 = lines1[res1] + Step(f"需要修改的目标:{index_str1}") + lines1.remove(index_str1) + Step(f"移除目标之后:{lines1}") + list_item = ' "path" : ["/system/xxxx/bin/sa_main"],\n' + lines1.insert(line, list_item) + s = ''.join(lines1) + Step(f"添加修改之后的文件内容:{s}") + with open(localPath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localPath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + Step("执行命令begetctl dump_service..........................") + result = self.driver.shell('begetctl dump_service wifi_manager_service') + Step(result) + pid = self.driver.System.get_pid('wifi_manager_service') + Step(pid) + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件wifi_standard.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /system/etc/init/wifi_standard.cfg") + self.driver.shell( + "mv /system/etc/init/wifi_standard.cfg_bak /system/etc/init/wifi_standard.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.json b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.json new file mode 100644 index 0000000000000000000000000000000000000000..9122f5bfaba0bb8cb26b65179e012878f69b0e00 --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.py b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.py new file mode 100644 index 0000000000000000000000000000000000000000..b67d3c841dfe3468d45eb12e12dacc90e7d3c388 --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0700.py @@ -0,0 +1,86 @@ +# 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. + +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiParam +import os + + +class SubStartupInitAbilityUp0700(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件hilogd.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /system/etc/init/hilogd.cfg /system/etc/init/hilogd.cfg_bak") + Step("把系统文件hilogd.cfg拉到本地..........................") + devpath = "/system/etc/init/hilogd.cfg" + self.driver.pull_file(devpath, "testFile/SubStartupInitAbilityUp/hilogd.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile\SubStartupInitAbilityUp") + localpath = os.path.join(path2, "hilogd.cfg") + with open(localPath, "r") as y: + for line in y: + lines1.append(line) + y.close() + line = lines1.index(' "socket" : [{\n') - 1 + res1 = line + Step(f"目标索引:{res1}") + index_str1 = lines1[res1] + Step(f"需要修改的目标:{index_str1}") + lines1.remove(index_str1) + Step(f"移除目标之后:{lines1}") + list_item = ' "file" : ["/dev/test/kmsg rd 0640 root root"],\n' + lines1.insert(line, list_item) + s = ''.join(lines1) + Step(f"添加修改之后的文件内容:{s}") + with open(localPath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localPath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行命令begetctl dump_service..........................") + result = self.driver.shell('begetctl dump_service hilogd') + Step(result) + self.driver.Assert.contains(result, "HiLogAdapter_init: Can't connect to server. Errno: 2") + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件hilogd.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /system/etc/init/hilogd.cfg") + self.driver.shell( + "mv /system/etc/init/hilogd.cfg_bak /system/etc/init/hilogd.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0800.json b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0800.json new file mode 100644 index 0000000000000000000000000000000000000000..ddfd475eea3d9d7c62f20cdf81a312abb6798d3b --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0800.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SubStartupInitAbilityUp/SUB_STARTUP_INIT_ABILITY_UP_0800.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0800.py b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0800.py new file mode 100644 index 0000000000000000000000000000000000000000..40f99f19c3bb7bae85ce7983516ce0138e36a15c --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0800.py @@ -0,0 +1,86 @@ +# 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. + +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiParam +import os + + +class SubStartupInitAbilityUp0800(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件wifi_standard.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /system/etc/init/wifi_standard.cfg /system/etc/init/wifi_standard.cfg_bak") + Step("把系统文件wifi_standard.cfg拉到本地..........................") + devpath = "/system/etc/init/wifi_standard.cfg" + self.driver.pull_file(devpath, "testFile/SubStartupInitAbilityUp/wifi_standard.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile\SubStartupInitAbilityUp") + localpath = os.path.join(path2, "wifi_standard.cfg") + with open(localPath, "r") as y: + for line in y: + lines1.append(line) + y.close() + line = lines1.index(' "uid" : "wifi",\n') + res1 = line + Step(f"目标索引:{res1}") + index_str1 = lines1[res1] + Step(f"需要修改的目标:{index_str1}") + lines1.remove(index_str1) + Step(f"移除目标之后:{lines1}") + list_item = ' "uid" : "-1",\n' + lines1.insert(line, list_item) + s = ''.join(lines1) + Step(f"添加修改之后的文件内容:{s}") + with open(localPath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localPath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + Step("执行命令begetctl dump_service..........................") + result = self.driver.shell('begetctl dump_service wifi_manager_service') + Step(result) + pid = self.driver.System.get_pid('wifi_manager_service') + Step(pid) + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件wifi_standard.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /system/etc/init/wifi_standard.cfg") + self.driver.shell( + "mv /system/etc/init/wifi_standard.cfg_bak /system/etc/init/wifi_standard.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.json b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.json new file mode 100644 index 0000000000000000000000000000000000000000..f00cfc07b822dd8785a1d44a094b4b1caf3f8494 --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.py b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.py new file mode 100644 index 0000000000000000000000000000000000000000..66e4f07903bad04a2ac26a8e8fa6e34355cd18a5 --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_0900.py @@ -0,0 +1,87 @@ +# 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. + +import os +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiParam + + +class SubStartupInitAbilityUp0900(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始.................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件 ability.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /system/etc/init/ability.cfg /system/etc/init/ability.cfg_bak") + Step("把系统文件 ability.cfg 拉到本地..........................") + devpath = "/system/etc/init/ability_ability.cfg" + self.driver.pull_file(devpath, "testFile/SubStartupInitAbilityUp/ability_ability.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile\SubStartupInitAbilityUp") + localpath = os.path.join(path2, "ability_ability.cfg") + with open(localPath, "r") as y: + for line in y: + lines1.append(line) + y.close() + line = lines1.index(' "secon" : "u:r:ability:s0",\n') + res1 = line + Step(f"目标索引:{res1}") + index_str1 = lines1[res1] + Step(f"需要修改的目标:{index_str1}") + lines1.remove(index_str1) + Step(f"移除目标之后:{lines1}") + list_item = ' "secon" : "u:r:abilityly:s0",\n' + lines1.insert(line, list_item) + s = ''.join(lines1) + Step(f"添加修改之后的文件内容:{s}") + with open(localPath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localPath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行命令begetctl dump_service..........................") + result = self.driver.shell('begetctl dump_service ability') + Step(result) + pid = self.driver.System.get_pid('ability') + Step(pid) + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件ability.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /system/etc/init/ability.cfg") + self.driver.shell( + "mv /system/etc/init/ability.cfg_bak /system/etc/init/ability.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.json b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.json new file mode 100644 index 0000000000000000000000000000000000000000..1c9c71bd0151108dde0580aeebab15e585fa5b5f --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.json @@ -0,0 +1,14 @@ +{ + "description": "Config for OpenHarmony devicetest test cases", + "environment": [ + { + "type": "device" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.py b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.py new file mode 100644 index 0000000000000000000000000000000000000000..87053d15038e1e230a0dea918a0899d477627efd --- /dev/null +++ b/test/autotest/testcases/SubStartupInitAbilityUp/sub_startup_init_ability_up_1000.py @@ -0,0 +1,96 @@ +# 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. + +import os +from time import sleep +from devicetest.core.test_case import Step, TestCase +from hypium import UiParam + + +class SubStartupInitAbilityUp1000(TestCase): + + def __init__(self, controllers): + self.tag = self.__class__.__name__ + self.tests = [ + "test_step1" + ] + TestCase.__init__(self, self.tag, controllers) + self.driver = UiDriver(self.device1) + + def setup(self): + Step("预置工作:初始化手机开始..................") + Step(self.devices[0].device_id) + + def test_step1(self): + Step("重命名系统文件hilogd.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell( + "cp /system/etc/init/hilogd.cfg /system/etc/init/hilogd.cfg_bak") + Step("把系统文件hilogd.cfg拉到本地..........................") + devpath = "/system/etc/init/hilogd.cfg" + self.driver.pull_file(devpath, "testFile/SubStartupInitAbilityUp/hilogd.cfg") + Step("修改本地系统文件..........................") + lines1 = [] + path2 = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + "testFile\SubStartupInitAbilityUp") + localpath = os.path.join(path2, "hilogd.cfg") + with open(localPath, "r") as y: + for line in y: + lines1.append(line) + y.close() + line = lines1.index(' "secon" : "u:r:hilogd:s0"\n') + res1 = line + Step(f"目标索引:{res1}") + index_str1 = lines1[res1] + Step(f"需要删除目标:{index_str1}") + lines1.remove(index_str1) + line2 = line - 1 + index_str2 = lines1[line2] + lines2 = list(index_str2) + Step(f"需要修改,:{lines2}") + if ',' in lines2: + lines2.remove(',') + s2 = ''.join(lines2) + Step(f"修改,之后:{s2}") + else: + pass + lines1.remove(index_str2) + lines1.insert(line2, s2) + Step(f"全部修改:{lines1}") + s = ''.join(lines1) + Step(f"修改之后的文件内容:{s}") + with open(localPath, "w") as z: + z.write(s) + z.close() + Step("上传修改后的本地系统文件..........................") + self.driver.push_file(localPath, devpath) + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() + Step("执行命令begetctl dump_service..........................") + result = self.driver.shell('begetctl dump_service hilogd') + Step(result) + self.driver.Assert.contains(result, "HiLogAdapter_init: Can't connect to server.") + + def teardown(self): + Step("收尾工作.................") + Step("恢复系统文件hilogd.cfg..........................") + self.driver.hdc("target mount") + self.driver.shell("rm -rf /system/etc/init/hilogd.cfg") + self.driver.shell( + "mv /system/etc/init/hilogd.cfg_bak /system/etc/init/hilogd.cfg") + Step("执行重启..........................") + self.driver.System.reboot() + sleep(3) + self.driver.System.wait_for_boot_complete() diff --git a/test/benchmark/BUILD.gn b/test/benchmark/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ad435bfe46b90f4107a107d39f86e0252be4307d --- /dev/null +++ b/test/benchmark/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2023 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("//build/ohos.gni") + +common_include_dirs = [ "." ] + +ohos_executable("BMStartupTest") { + sources = [ + "benchmark_fwk.cpp", + "parameter_benchmark.cpp", + ] + + defines = [ "_GNU_SOURCE" ] + include_dirs = common_include_dirs + deps = [ "../../interfaces/innerkits:libbegetutil" ] + external_deps = [ + "benchmark:benchmark", + "bounds_checking_function:libsec_static", + ] + install_images = [ "system" ] + install_enable = true + + part_name = "init" + subsystem_name = "startup" +} diff --git a/test/benchmark/benchmark_fwk.cpp b/test/benchmark/benchmark_fwk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9f1c7b79484b2d3c50c289ea51a748b28afa4e8 --- /dev/null +++ b/test/benchmark/benchmark_fwk.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2023 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 "benchmark_fwk.h" +using namespace std; +using namespace init_benchmark_test; + +namespace { +constexpr auto K = 1024; +using args_vector = std::vector>; + +static const std::vector commonArgs { + 8, + 16, + 32, + 64, + 512, + 1 * K, + 8 * K, + 16 * K, + 32 * K, + 64 * K, + 128 * K, +}; + +static const std::vector limitSizes { + 1, + 2, + 3, + 4, + 5, + 6, + 7, +}; +} + +namespace init_benchmark_test { +std::map> g_allBenchmarks; +std::mutex g_benchmarkLock; +static struct option g_benchmarkLongOptions[] = { + {"init_cpu", required_argument, nullptr, 'c'}, + {"init_iterations", required_argument, nullptr, 'i'}, + {"help", no_argument, nullptr, 'h'}, + {nullptr, 0, nullptr, 0}, + }; +} + +static void PrintUsageAndExit() +{ + printf("Usage:\n"); + printf("init_benchmarks [--init_cpu=]\n"); + printf(" [--init_iterations=]\n"); + printf(" []\n"); + printf("benchmark flags:\n"); + + int argc = 2; + char argv0[] = "init_benchmark"; + char argv1[] = "--help"; + char *argv[3] = { argv0, argv1, nullptr }; + benchmark::Initialize(&argc, argv); + exit(1); +} + +static void ShiftOptions(int argc, char **argv, std::vector *argvAfterShift) +{ + (*argvAfterShift)[0] = argv[0]; + for (int i = 1; i < argc; ++i) { + char *optarg = argv[i]; + size_t index = 0; + // Find if musl defined this arg. + while (g_benchmarkLongOptions[index].name && strncmp(g_benchmarkLongOptions[index].name, optarg + 2, // 2 arg + strlen(g_benchmarkLongOptions[index].name))) { + ++index; + } + // Not defined. + if (!g_benchmarkLongOptions[index].name) { + argvAfterShift->push_back(optarg); + } else if ((g_benchmarkLongOptions[index].has_arg == required_argument) && !strchr(optarg, '=')) { + i++; + } + } + argvAfterShift->push_back(nullptr); +} + +static bench_opts_t ParseOptions(int argc, char **argv) +{ + bench_opts_t opts; + int opt; + char *errorCheck = nullptr; + opterr = 0; // Don't show unrecognized option error. + + while ((opt = getopt_long(argc, argv, "c:i:a:h", g_benchmarkLongOptions, nullptr)) != -1) { + switch (opt) { + case 'c': + if (!(*optarg)) { + printf("ERROR: no argument specified for init_cpu.\n"); + PrintUsageAndExit(); + break; + } + opts.cpuNum = strtol(optarg, &errorCheck, 10); // 10 base + if (*errorCheck) { + errx(1, "ERROR: Args %s is not a valid integer.", optarg); + } + break; + case 'i': + if (!(*optarg)) { + printf("ERROR: no argument specified for init_iterations.\n"); + PrintUsageAndExit(); + break; + } + opts.iterNum = strtol(optarg, &errorCheck, 10); // 10 base + if (*errorCheck != '\0' || opts.iterNum < 0) { + errx(1, "ERROR: Args %s is not a valid number of iterations.", optarg); + } + break; + case 'h': + PrintUsageAndExit(); + break; + case '?': + break; + default: + exit(1); + } + } + return opts; +} + +static void LockAndRun(benchmark::State &state, benchmark_func func, int cpuNum) +{ + if (cpuNum >= 0) { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(cpuNum, &cpuset); + + if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) { + printf("lock CPU failed, ERROR:%s\n", strerror(errno)); + } + } + + reinterpret_cast(func)(state); +} + +static args_vector *ResolveArgs(args_vector *argsVector, std::string args, + std::map &presetArgs) +{ + // Get it from preset args. + if (presetArgs.count(args)) { + return &presetArgs[args]; + } + + // Convert string to int. + argsVector->push_back(std::vector()); + std::stringstream sstream(args); + std::string arg; + while (sstream >> arg) { + char *errorCheck; + int converted = static_cast(strtol(arg.c_str(), &errorCheck, 10)); // 10 base + if (*errorCheck) { + errx(1, "ERROR: Args str %s contains an invalid macro or int.", args.c_str()); + } + (*argsVector)[0].push_back(converted); + } + return argsVector; +} + +static args_vector GetArgs(const std::vector &sizes) +{ + args_vector args; + for (int size : sizes) { + args.push_back({size}); + } + return args; +} + +static args_vector GetArgs(const std::vector &sizes, int value) +{ + args_vector args; + for (int size : sizes) { + args.push_back({size, value}); + } + return args; +} + +static args_vector GetArgs(const std::vector &sizes, int value1, int value2) +{ + args_vector args; + for (int size : sizes) { + args.push_back({size, value1, value2}); + } + return args; +} + +static args_vector GetArgs(const std::vector &sizes, const std::vector &limits, int value) +{ + args_vector args; + for (int size : sizes) { + for (int limit : limits) { + args.push_back({size, limit, value}); + } + } + return args; +} + +static std::map GetPresetArgs() +{ + std::map presetArgs { + {"COMMON_ARGS", GetArgs(commonArgs)}, + {"ALIGNED_ONEBUF", GetArgs(commonArgs, 0)}, + {"ALIGNED_TWOBUF", GetArgs(commonArgs, 0, 0)}, + {"STRING_LIMIT", GetArgs(commonArgs, limitSizes, 0)}, + {"MATH_COMMON", args_vector{{0}, {1}, {2}, {3}, {4}, {5}}}, + {"BENCHMARK_VARIABLE", args_vector{{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}}, + {"REALPATH_VARIABLE", args_vector{{0}, {1}, {2}, {3}, {4}}}, + {"MMAP_SIZE", args_vector{{8}, {16}, {32}, {64}, {128}, {512}}}, + }; + + return presetArgs; +} + +static void RegisterSingleBenchmark(bench_opts_t opts, const std::string &funcName, args_vector *runArgs) +{ + if (g_allBenchmarks.find(funcName) == g_allBenchmarks.end()) { + errx(1, "ERROR: No benchmark for function %s", funcName.c_str()); + } + + benchmark_func func = g_allBenchmarks.at(funcName).first; + for (const std::vector &args : (*runArgs)) { + // It will call LockAndRun(func, opts.cpuNum). + auto registration = benchmark::RegisterBenchmark(funcName.c_str(), LockAndRun, func, opts.cpuNum)->Args(args); + printf("opts.iterNum %ld \n", opts.iterNum); + if (opts.iterNum > 0) { + registration->Iterations(opts.iterNum); + } + } +} + +static void RegisterAllBenchmarks(const bench_opts_t &opts, std::map &presetArgs) +{ + for (auto &entry : g_allBenchmarks) { + auto &funcInfo = entry.second; + args_vector arg_vector; + args_vector *runArgs = ResolveArgs(&arg_vector, funcInfo.second, presetArgs); + RegisterSingleBenchmark(opts, entry.first, runArgs); + } +} + +int main(int argc, char **argv) +{ + std::map presetArgs = GetPresetArgs(); + bench_opts_t opts = ParseOptions(argc, argv); + std::vector argvAfterShift(argc); + ShiftOptions(argc, argv, &argvAfterShift); + RegisterAllBenchmarks(opts, presetArgs); + if (setpriority(PRIO_PROCESS, 0, -20)) { // 20 max + perror("Set priority of process failed.\n"); + } + CreateLocalParameterTest(512); // test max 512 + int argcAfterShift = argvAfterShift.size(); + benchmark::Initialize(&argcAfterShift, argvAfterShift.data()); + benchmark::RunSpecifiedBenchmarks(); +} diff --git a/test/benchmark/benchmark_fwk.h b/test/benchmark/benchmark_fwk.h new file mode 100644 index 0000000000000000000000000000000000000000..909ed81a0ce02b1495fd5ee36039cfc5f7463d03 --- /dev/null +++ b/test/benchmark/benchmark_fwk.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 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 STARTUP_INIT_BENCHMARK_FWK_H +#define STARTUP_INIT_BENCHMARK_FWK_H +#include +#include +#include +#include +#include + +namespace init_benchmark_test { +using benchmark_func = void (*) (void); +extern std::mutex g_benchmarkLock; +extern std::map> g_allBenchmarks; + +static int __attribute__((unused)) AddBenchmark(const std::string &funcName, + benchmark_func funcPtr, const std::string &arg = "") +{ + g_benchmarkLock.lock(); + g_allBenchmarks.emplace(std::string(funcName), std::make_pair(funcPtr, arg)); + g_benchmarkLock.unlock(); + return 0; +} + +#define INIT_BENCHMARK(n) \ + int _init_benchmark_##n __attribute__((unused)) = AddBenchmark(std::string(#n), \ + reinterpret_cast(n)) + +#define INIT_BENCHMARK_WITH_ARG(n, arg) \ + int _init_benchmark_##n __attribute__((unused)) = AddBenchmark(std::string(#n), \ + reinterpret_cast(n), arg) +} + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +typedef struct bench_opts_t { + int cpuNum = -1; + long iterNum = 0; +} BENCH_OPTS_T; + +void CreateLocalParameterTest(int max); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // STARTUP_INIT_BENCHMARK_FWK_H \ No newline at end of file diff --git a/test/benchmark/parameter_benchmark.cpp b/test/benchmark/parameter_benchmark.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42887491192e0d6c61e85390289ee81dc6cadf4c --- /dev/null +++ b/test/benchmark/parameter_benchmark.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2023 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 "benchmark_fwk.h" +#include "init_param.h" +#include "param_init.h" +#include "parameter.h" +#include "sys_param.h" + +using namespace std; +using namespace init_benchmark_test; +namespace { +static int g_maxCount = 512; +} + +static inline int TestRandom(void) +{ + return random(); +} + +namespace init_benchmark_param { +struct LocalParameterTestState { + explicit LocalParameterTestState(int nprops) noexcept : nprops(nprops), valid(false) + { + static const char paramNameChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_."; + if (g_maxCount < nprops) { + fprintf(stderr, "Invalid nprops %d\n", nprops); + return; + } + names = new char *[nprops]; + nameLens = new int[nprops]; + values = new char *[nprops]; + valueLens = new int[nprops]; + + srandom(nprops); + int count = 0; + for (int i = 0; i < nprops; i++) { + // Make sure the name has at least 10 characters to make + // it very unlikely to generate the same TestRandom name. + nameLens[i] = (TestRandom() % (PARAM_NAME_LEN_MAX - 10)) + 10; // 10 name len + names[i] = new char[PARAM_NAME_LEN_MAX + 1]; + size_t paramNameLen = sizeof(paramNameChars) - 1; + for (int j = 0; j < nameLens[i]; j++) { + if (j == 0 || names[i][j - 1] == '.' || j == nameLens[i] - 1) { + // Certain values are not allowed: + // - Don't start name with '.' + // - Don't allow '.' to appear twice in a row + // - Don't allow the name to end with '.' + // This assumes that '.' is the last character in the + // array so that decrementing the length by one removes + // the value from the possible values. + paramNameLen--; + } + names[i][j] = paramNameChars[TestRandom() % paramNameLen]; + } + names[i][nameLens[i]] = 0; + + // Make sure the value contains at least 1 character. + valueLens[i] = (TestRandom() % (PARAM_VALUE_LEN_MAX - 1)) + 1; + values[i] = new char[PARAM_VALUE_LEN_MAX]; + for (int j = 0; j < valueLens[i]; j++) { + values[i][j] = paramNameChars[TestRandom() % (sizeof(paramNameChars) - 1)]; + } + + if (SystemSetParameter(names[i], values[i]) != 0) { + count++; + } + } + if (count > 0) { + fprintf(stderr, "Failed to add a property, count %d\n", count); + } + valid = true; + } + + LocalParameterTestState(const LocalParameterTestState&) = delete; + LocalParameterTestState & operator=(const LocalParameterTestState&) = delete; + + ~LocalParameterTestState() noexcept + { + for (int i = 0; i < nprops; i++) { + delete names[i]; + delete values[i]; + } + delete[] names; + delete[] nameLens; + delete[] values; + delete[] valueLens; + } + +public: + const int nprops; + char **names; + int *nameLens; + char **values; + int *valueLens; + bool valid; +}; +} + +static init_benchmark_param::LocalParameterTestState *g_localParamTester = nullptr; + +void CreateLocalParameterTest(int max) +{ + g_maxCount = max > 0 ? max : g_maxCount; + g_localParamTester = new init_benchmark_param::LocalParameterTestState(g_maxCount); + if (g_localParamTester == nullptr) { + exit(0); + } +} + +/** + * @brief for parameter get + * + * @param state + */ +static void BMCachedParameterGet(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + CachedHandle handle = CachedParameterCreate(g_localParamTester->names[TestRandom() % g_maxCount], "4444444"); + for (auto _ : state) { + benchmark::DoNotOptimize(CachedParameterGet(handle)); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for parameter get, static handle + * + * @param state + */ +static void BMCachedParameterGetChangedStatic(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + for (auto _ : state) { + static CachedHandle handle = CachedParameterCreate( + g_localParamTester->names[TestRandom() % g_maxCount], "xxxxxx"); + int changed = 0; + benchmark::DoNotOptimize(CachedParameterGetChanged(handle, &changed)); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for parameter get, global handle + * + * @param state + */ +static void BMCachedParameterGetChangedGlobal(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + CachedHandle handle = CachedParameterCreate(g_localParamTester->names[TestRandom() % g_maxCount], "xxxxxxxxx"); + for (auto _ : state) { + int changed = 0; + benchmark::DoNotOptimize(CachedParameterGetChanged(handle, &changed)); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for parameter get, global handle + * + * @param state + */ +static void BMCachedParameterGetChangedGlobal2(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + CachedHandle handle = nullptr; + for (auto _ : state) { + if (handle == nullptr) { + handle = CachedParameterCreate(g_localParamTester->names[TestRandom() % g_maxCount], "xxxxxxxxx"); + } + int changed = 0; + benchmark::DoNotOptimize(CachedParameterGetChanged(handle, &changed)); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for get + * data exist + * + * @param state + */ +static void BMSystemReadParam(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + { + char value[PARAM_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_VALUE_LEN_MAX; + SystemReadParam(g_localParamTester->names[TestRandom() % g_maxCount], value, &len); + } + for (auto _ : state) { + char value[PARAM_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_VALUE_LEN_MAX; + SystemReadParam(g_localParamTester->names[TestRandom() % g_maxCount], value, &len); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for get + * data not exist + * + * @param state + */ +static void BMSystemReadParam_none(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + { + char value[PARAM_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_VALUE_LEN_MAX; + SystemReadParam("test.aaa.aaa.aaa", value, &len); + } + for (auto _ : state) { + char value[PARAM_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_VALUE_LEN_MAX; + SystemReadParam("test.aaa.aaa.aaa", value, &len); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for find + * + * @param state + */ +static void BMSystemFindParameter(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + for (auto _ : state) { + ParamHandle handle = 0; + SystemFindParameter(g_localParamTester->names[TestRandom() % g_maxCount], &handle); + } + state.SetItemsProcessed(state.iterations()); +} + +/** + * @brief for find, and read value + * + * @param state + */ +static void BMSystemGetParameterValue(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + ParamHandle *handle = new ParamHandle[g_maxCount]; + for (int i = 0; i < g_maxCount; ++i) { + SystemFindParameter(g_localParamTester->names[TestRandom() % g_maxCount], &handle[i]); + } + + int i = 0; + char value[PARAM_VALUE_LEN_MAX]; + for (auto _ : state) { + uint32_t len = PARAM_VALUE_LEN_MAX; + SystemGetParameterValue(handle[i], value, &len); + i = (i + 1) % g_maxCount; + } + state.SetItemsProcessed(state.iterations()); + delete[] handle; +} + +/** + * @brief for find, and read commit id + * + * @param state + */ +static void BMSystemGetParameterCommitId(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + ParamHandle *handle = new ParamHandle[g_maxCount]; + for (int i = 0; i < g_maxCount; ++i) { + SystemFindParameter(g_localParamTester->names[TestRandom() % g_maxCount], &handle[i]); + } + + int i = 0; + for (auto _ : state) { + uint32_t commitId = 0; + SystemGetParameterCommitId(handle[i], &commitId); + i = (i + 1) % g_maxCount; + } + state.SetItemsProcessed(state.iterations()); + delete[] handle; +} + +static void BMTestRandom(benchmark::State &state) +{ + if (g_localParamTester == nullptr || !g_localParamTester->valid) { + fprintf(stderr, "Invalid nprops %d \n", g_maxCount); + return; + } + + for (auto _ : state) { + benchmark::DoNotOptimize(TestRandom()); + } + state.SetItemsProcessed(state.iterations()); +} + +INIT_BENCHMARK(BMCachedParameterGet); +INIT_BENCHMARK(BMCachedParameterGetChangedStatic); +INIT_BENCHMARK(BMCachedParameterGetChangedGlobal); +INIT_BENCHMARK(BMCachedParameterGetChangedGlobal2); + +INIT_BENCHMARK(BMSystemReadParam); +INIT_BENCHMARK(BMSystemReadParam_none); +INIT_BENCHMARK(BMSystemFindParameter); +INIT_BENCHMARK(BMSystemGetParameterValue); +INIT_BENCHMARK(BMSystemGetParameterCommitId); +INIT_BENCHMARK(BMTestRandom); diff --git a/test/exec_test/BUILD.gn b/test/exec_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..60f6f9821723d401328b26bf00848f80877ea75a --- /dev/null +++ b/test/exec_test/BUILD.gn @@ -0,0 +1,92 @@ +# 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/begetd.gni") +import("//build/ohos.gni") + +ohos_executable("client") { + sources = [ "client.c" ] + include_dirs = [ + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + ] + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + install_images = [ "system" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" +} + +ohos_executable("fd_holder_test") { + sources = [ "fd_holder_test.c" ] + + defines = [ "INIT_AGENT" ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + + include_dirs = [ "//base/startup/init/interfaces/innerkits/include" ] + + install_images = [ "system" ] + install_enable = true + + part_name = "init" + subsystem_name = "startup" +} + +ohos_prebuilt_etc("fd_holder_test.cfg") { + source = "//base/startup/init/test/exec_test/fd_holder_test.cfg" + part_name = "init" + subsystem_name = "startup" + module_install_dir = "etc/init" +} + +ohos_executable("server") { + sources = [ "server.c" ] + include_dirs = [ + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + ] + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + install_images = [ "system" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" +} + +ohos_executable("ondemandTest") { + sources = [ "sa_service_ondemand_test.cpp" ] + + external_deps = [ + "c_utils:utils", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + install_images = [ "system" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" +} + +group("exectest") { + deps = [ + ":client", + ":fd_holder_test", + ":fd_holder_test.cfg", + ":ondemandTest", + ":server", + ] +} diff --git a/interfaces/innerkits/reboot/init_reboot.c b/test/exec_test/client.c similarity index 34% rename from interfaces/innerkits/reboot/init_reboot.c rename to test/exec_test/client.c index 51ac77497edcfaacd60075eb40437a9722f99453..333e532cc2a8ffa320b8f2fafce999c0e1e048e3 100644 --- a/interfaces/innerkits/reboot/init_reboot.c +++ b/test/exec_test/client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -12,53 +12,51 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "init_reboot.h" - -#include +#include #include -#include +#include +#include #include #include "init_log.h" +#include "init_socket.h" #include "securec.h" -#include "sys_param.h" -#define SYS_POWER_CTRL "sys.powerctrl=" -#define MAX_REBOOT_NAME_SIZE 100 -#define MAX_REBOOT_VAUE_SIZE 500 +#define BUFFER_LENGTH 15 +#define ARG_COUNT 2 -int DoReboot(const char *cmdContent) +int main(int argc, char* argv[]) { - uid_t uid1 = getuid(); - uid_t uid2 = geteuid(); - if (uid1 != 0 || uid2 != 0) { - INIT_LOGE("uid1=%d, uid2=%d, user MUST be root, error!", uid1, uid2); - return -1; - } - char value[MAX_REBOOT_VAUE_SIZE]; - if (cmdContent == NULL || strlen(cmdContent) == 0) { - if (snprintf_s(value, MAX_REBOOT_NAME_SIZE, strlen("reboot") + 1, "%s", "reboot") < 0) { - INIT_LOGE("DoReboot api error, MAX_REBOOT_NAME_SIZE is not enough"); - return -1; - } - if (SystemSetParameter("sys.powerctrl", value) != 0) { - INIT_LOGE("DoReboot Api SystemSetParameter error"); - return -1; - } + if (argc < ARG_COUNT) { + INIT_LOGE("Client need an argument"); return 0; } - int length = strlen(cmdContent); - if (length > MAX_REBOOT_VAUE_SIZE) { - INIT_LOGE("DoReboot api error, cmdContent = %s, length = %d.", cmdContent, length); + int sockFd = socket(PF_UNIX, SOCK_DGRAM, 0); + if (sockFd < 0) { + INIT_LOGE("Failed to create client socket"); return -1; } - if (snprintf_s(value, MAX_REBOOT_NAME_SIZE, MAX_REBOOT_NAME_SIZE - 1, "%s%s", "reboot,", cmdContent) < 0) { - INIT_LOGE("DoReboot api error, MAX_REBOOT_NAME_SIZE is not enough"); + struct sockaddr_un addr; + bzero(&addr, sizeof(struct sockaddr_un)); + addr.sun_family = PF_UNIX; + size_t addrLen = sizeof(addr.sun_path); + int ret = 0; + if (strcmp(argv[1], "server") == 0) { + ret = snprintf_s(addr.sun_path, addrLen, addrLen - 1, "/dev/unix/socket/serversock"); + INIT_ERROR_CHECK(ret >= 0, return -1, "Failed to format addr"); + if (connect(sockFd, (struct sockaddr *)&addr, sizeof(addr))) { + INIT_LOGE("Failed to connect socket: %d", errno); + close(sockFd); + return -1; + } + } else { + INIT_LOGE("input error, invalid server name"); + close(sockFd); return -1; } - if (SystemSetParameter("sys.powerctrl", value) != 0) { - INIT_LOGE("DoReboot Api SystemSetParameter error"); - return -1; + ret = write(sockFd, argv[ARG_COUNT], strlen(argv[ARG_COUNT])); + if (ret < 0) { + INIT_LOGE("Failed to write, errno = %d", errno); } + close(sockFd); return 0; -} - +} \ No newline at end of file diff --git a/test/exec_test/fd_holder_test.c b/test/exec_test/fd_holder_test.c new file mode 100644 index 0000000000000000000000000000000000000000..6ab7b302773704643bd8931be1b6a5e968857311 --- /dev/null +++ b/test/exec_test/fd_holder_test.c @@ -0,0 +1,83 @@ +/* + * 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" +#include "fd_holder.h" + +#define BUFFER_LENGTH 5 +#define FD_COUNT 2 +#define SLEEP_TIME 3 +#define ENV_FD_HOLD_PREFIX "OHOS_FD_HOLD_" + +static void SaveFds(const char *serviceName, int argc, char **argv) +{ + int fds[10]; + int i; + for (i = 0; i < argc; i++) { + BEGET_LOGI("Opening %s \n", argv[i]); + fds[i] = open(argv[i], O_APPEND | O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fds[i] < 0) { + BEGET_LOGI("Failed to open file %s\n", argv[i]); + break; + } + (void)write(fds[i], "hello", BUFFER_LENGTH); + } + int fdCount = i; + BEGET_LOGI("fdCount = %d\n", fdCount); + if (fdCount <= 0) { + BEGET_LOGE("Invalid fds for hold, abort\n"); + return; + } + int ret = ServiceSaveFd(serviceName, fds, (size_t)fdCount); + if (ret < 0) { + BEGET_LOGE("Request init save fds failed\n"); + } else { + BEGET_LOGI("Request init save fds done\n"); + } +} + + +int main(int argc, char **argv) +{ + size_t outfdCount = 0; + int *fds = ServiceGetFd("fd_holder_test", &outfdCount); + if (fds == NULL) { + BEGET_LOGE("Cannot get fds, maybe first time\n"); + } else { + for (size_t i = 0; i < outfdCount; i++) { + int fd = fds[i]; + if (write(fd, "world", BUFFER_LENGTH) < 0) { + BEGET_LOGE("Failed to write content to fd: %d, err = %d", fd, errno); + } + close(fd); + } + free(fds); + outfdCount = 0; + while (1) { + sleep(SLEEP_TIME); + } + } + char *files[] = {"/data/test/1", "/data/test/2"}; + SaveFds("fd_holder_test", FD_COUNT, (char **)files); + while (1) { + sleep(SLEEP_TIME); + } + return 0; +} diff --git a/test/exec_test/fd_holder_test.cfg b/test/exec_test/fd_holder_test.cfg new file mode 100644 index 0000000000000000000000000000000000000000..e7eaffc40de282658d43a03fd2e1da997eccc138 --- /dev/null +++ b/test/exec_test/fd_holder_test.cfg @@ -0,0 +1,17 @@ +{ + "jobs" : [{ + "name" : "post-fs-data", + "cmds" : [ + "mkdir /data/test", + "start fd_holder_test" + ] + } + ], + "services" : [{ + "name" : "fd_holder_test", + "path" : ["/system/bin/fd_holder_test", "save", "fd_holder_test", "/data/test/1", "/data/test/2"], + "uid" : "root", + "gid" : "system" + } + ] +} \ No newline at end of file diff --git a/test/exec_test/sa_service_ondemand_test.cpp b/test/exec_test/sa_service_ondemand_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a56ef651b2077a6edb1a9556d9bae18f4e4e744b --- /dev/null +++ b/test/exec_test/sa_service_ondemand_test.cpp @@ -0,0 +1,80 @@ +/* + * 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 "iservice_registry.h" +#include "system_ability_definition.h" +#include "system_ability_load_callback_stub.h" + +using namespace OHOS; +using namespace std; + +class OnDemandLoadCallback : public SystemAbilityLoadCallbackStub { +public: + void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr& remoteObject) override; + void OnLoadSystemAbilityFail(int32_t systemAbilityId) override; +}; + +void OnDemandLoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId, + const sptr& remoteObject) +{ + cout << "OnLoadSystemAbilitySuccess systemAbilityId:" << systemAbilityId << " IRemoteObject result:" << + ((remoteObject != nullptr) ? "succeed" : "failed") << endl; +} + +void OnDemandLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId) +{ + cout << "OnLoadSystemAbilityFail systemAbilityId:" << systemAbilityId << endl; +} + +int main(int argc, char * const argv[]) +{ + std::map saService = { + {"updater_sa", UPDATE_DISTRIBUTED_SERVICE_ID}, + {"softbus_server", SOFTBUS_SERVER_SA_ID}, + }; + int parameterNum = 2; + if ((argc != parameterNum) || (argv[1] == nullptr)) { + cout << "Invalid parameter" << endl; + return 0; + } + const string name = argv[1]; + int abilityId = 0; + std::map::iterator item = saService.find(name); + if (item != saService.end()) { + cout << "sa service name " << item->first << "ability id " << item->second << endl; + abilityId = item->second; + } else { + cout << "Invalid sa service name" << endl; + return 0; + } + + sptr loadCallback_ = new OnDemandLoadCallback(); + sptr sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (sm == nullptr) { + cout << "GetSystemAbilityManager samgr object null!" << endl; + return 0; + } + int32_t result = sm->LoadSystemAbility(abilityId, loadCallback_); + if (result != ERR_OK) { + cout << "systemAbilityId:" << abilityId << " load failed, result code:" << result << endl; + return 0; + } + return 0; +} + diff --git a/test/exec_test/server.c b/test/exec_test/server.c new file mode 100644 index 0000000000000000000000000000000000000000..aa7d09c6b61e068bbcc1cd3260745758e14ab381 --- /dev/null +++ b/test/exec_test/server.c @@ -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. + */ +#include +#include "init_log.h" +#include "init_socket.h" +#include "securec.h" +#define MAX_BUFFER_SIZE 1024 + +int main(int argc, char* argv[]) +{ + int sockFd = GetControlSocket("serversock"); + if (sockFd < 0) { + INIT_LOGE("Failed to get server socket"); + return -1; + } + char buffer[MAX_BUFFER_SIZE] = { 0 }; + while (1) { + if (read(sockFd, buffer, sizeof(buffer) - 1) > 0) { + INIT_LOGI("Read message: %s", buffer); + (void)memset_s(buffer, MAX_BUFFER_SIZE, 0, MAX_BUFFER_SIZE); + } + } + return 0; +} diff --git a/test/fuzztest/BUILD.gn b/test/fuzztest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..07c8f0df3b1faaef89439d5c2eb1b37c44c73c3e --- /dev/null +++ b/test/fuzztest/BUILD.gn @@ -0,0 +1,3711 @@ +# 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. + +module_output_path = "init/init" + +#####################hydra-fuzz################### +import("//base/startup/init/begetd.gni") +import("//build/config/features.gni") +import("//build/ohos.gni") +import("//build/test.gni") +ohos_static_library("libfuzz_utils") { + sources = [ "utils/fuzz_utils.cpp" ] + + include_dirs = [ "//base/startup/init/test/fuzztest/utils/include" ] + + deps = [] + part_name = "init" + subsystem_name = "startup" +} + +##############################fuzztest########################################## +ohos_fuzztest("DoRebootFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/doreboot_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "doreboot_fuzzer/doreboot_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("DoRebootExtFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/dorebootext_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "dorebootext_fuzzer/dorebootext_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetControlFileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getcontrolfile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getcontrolfile_fuzzer/getcontrolfile_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetControlSocketFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getcontrolsocket_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:init_log", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("MountAllWithFstabFileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/mountallwithfstabfile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + deps += [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ReadFileInDirFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/readfileindir_fuzzer" + + include_dirs = [ + "//base/startup/init/services/init/include", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "readfileindir_fuzzer/readfileindir_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceControlStartFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/servicecontrolstart_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceControlStopFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/servicecontrolstop_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SystemDumpParametersFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/systemdumpparameters_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param/linux:param_init", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "hilog:libhilog" ] + external_deps += [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("FindParameterFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/findparameter_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "findparameter_fuzzer/findparameter_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetParameterCFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getparameterc_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getparameterc_fuzzer/getparameterc_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetParameterCommitIdFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getparametercommitid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getparametercommitid_fuzzer/getparametercommitid_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetParameterNameFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getparametername_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getparametername_fuzzer/getparametername_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetParameterValueFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getparametervalue_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getparametervalue_fuzzer/getparametervalue_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SetParameterCFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/setparameterc_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "setparameterc_fuzzer/setparameterc_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SystemTraversalParameterFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/systemtraversalparameter_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/init/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("WaitParameterFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/waitparameter_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "waitparameter_fuzzer/waitparameter_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("WatchParameterFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/watchparameter_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/init/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "watchparameter_fuzzer/watchparameter_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("UmountAllWithFstabFileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/umountallwithfstabfile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("CmdServiceProcessDelClientFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/cmdserviceprocessdelclient_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/control_fd", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/loopevent/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd", + ] + + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("CmdClientInitFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/cmdclientinit_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/control_fd", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/loopevent/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/control_fd:libcontrolfd", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "cmdclientinit_fuzzer/cmdclientinit_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("CmdServiceInitFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/cmdserviceinit_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/control_fd", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/loopevent/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetIntParameterCFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getintparameterc_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/interfaces/innerkits/include/param", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getintparameterc_fuzzer/getintparameterc_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetUintParameterCFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getuintparameterc_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getuintparameterc_fuzzer/getuintparameterc_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("RemoveParameterWatcherFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/removeparameterwatcher_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SetParameterCppFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/setparametercpp_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "setparametercpp_fuzzer/setparametercpp_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBoolParameterCppFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getboolparametercpp_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetParameterCppFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getparametercpp_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getparametercpp_fuzzer/getparametercpp_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBlockDeviceByNameFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getblockdevicebyname_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBlockDeviceByMountPointFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getblockdevicebymountpoint_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("MountOneItemFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/mountoneitem_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "mountoneitem_fuzzer/mountoneitem_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetMountStatusForMountPointFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getmountstatusformountpoint_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("MountAllWithFstabFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/mountallwithfstab_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("DoFormatFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/doformat_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "doformat_fuzzer/doformat_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("IsSupportedFilesystemFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/issupportedfilesystem_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ParseFstabPerLineFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/parsefstabperline_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "parsefstabperline_fuzzer/parsefstabperline_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ParseUeventConfigFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/parseueventconfig_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "parseueventconfig_fuzzer/parseueventconfig_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ParseUeventdConfigFileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/parseueventdconfigfile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("FindFstabItemForMountPointFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/findfstabitemformountpoint_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("FindFstabItemForPathFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/findfstabitemforpath_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBlockDevicePathFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getblockdevicepath_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("LoadFscryptPolicyFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/loadfscryptpolicy_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ReleaseFstabFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/releasefstab_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "releasefstab_fuzzer/releasefstab_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ReadFstabFromFileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/readfstabfromfile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetIntParameterCppFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getintparametercpp_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getintparametercpp_fuzzer/getintparametercpp_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetStringParameterFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getstringparameter_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getstringparameter_fuzzer/getstringparameter_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrDelFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/hookmgrdel_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrdel_fuzzer/hookmgrdel_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrAddFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/hookmgradd_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgradd_fuzzer/hookmgradd_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrExecuteFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/hookmgrexecute_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrTraversalFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/hookmgrtraversal_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrGetHooksCntFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/hookmgrgethookscnt_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrGetStagesCntFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/hookmgrgetstagescnt_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrDestroyFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/hookmgrdestroy_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HookMgrCreateFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/hookmgrcreate_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrTraversalFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/modulemgrtraversal_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrGetCntFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/modulemgrgetcnt_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrUninstallFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/modulemgruninstall_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrScanFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/modulemgrscan_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgrscan_fuzzer/modulemgrscan_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrInstallFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/modulemgrinstall_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrDestroyFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/modulemgrdestroy_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ModuleMgrCreateFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/modulemgrcreate_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceSaveFdFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/servicesavefd_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicesavefd_fuzzer/servicesavefd_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceSaveFdWithPollFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/servicesavefdwithpoll_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fd_holder:fdholder", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "//base/startup/init/interfaces/innerkits/fd_holder/fd_holder.c", + "servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceGetFdFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/servicegetfd_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicegetfd_fuzzer/servicegetfd_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceControlWithExtraFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/servicecontrolwithextra_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceControlFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/servicecontrol_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicecontrol_fuzzer/servicecontrol_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceWaitForStatusFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/servicewaitforstatus_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceSetReadyFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/servicesetready_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicesetready_fuzzer/servicesetready_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("StartServiceByTimerFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/startservicebytimer_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "startservicebytimer_fuzzer/startservicebytimer_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("StopServiceTimerFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/stopservicetimer_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "stopservicetimer_fuzzer/stopservicetimer_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ServiceWatchForStatusFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/servicewatchforstatus_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/interfaces/innerkits/include/param", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HandleOtherDeviceEventFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/handleotherdeviceevent_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} +ohos_fuzztest("HandleBlockDeviceEventFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/handleblockdeviceevent_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("HasSystemCapabilityFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/hassystemcapability_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "hassystemcapability_fuzzer/hassystemcapability_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("BuildControlMessageFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/buildcontrolmessage_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fd_holder:fdholder", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ChangeSysAttributePermissionsFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/changesysattributepermissions_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ReceiveFdsFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/receivefds_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fd_holder:fdholder", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "receivefds_fuzzer/receivefds_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("LoadFstabFromCommandLineFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/loadfstabfromcommandline_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBootSlotsFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbootslots_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbootslots_fuzzer/getbootslots_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetCurrentSlotFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getcurrentslot_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getcurrentslot_fuzzer/getcurrentslot_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetSecurityPatchTagFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getsecuritypatchtag_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/fs_manager:libfsmanager_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetOSFullNameFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getosfullname_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getosfullname_fuzzer/getosfullname_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetVersionIdFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getversionid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getversionid_fuzzer/getversionid_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBuildRootHashFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbuildroothash_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbuildroothash_fuzzer/getbuildroothash_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetOsReleaseTypeFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getosreleasetype_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getosreleasetype_fuzzer/getosreleasetype_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetSdkApiVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getsdkapiversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetDeviceTypeCFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getdevicetypec_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getdevicetypec_fuzzer/getdevicetypec_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetDeviceNodePermissionsFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getdevicenodepermissions_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = + [ "getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetDeviceUdevConfByDevNodeFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getdeviceudevconfbydevnode_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/test/fuzztest:libfuzz_utils", + "//base/startup/init/ueventd:libueventd_ramdisk_static", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetProductModelFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getproductmodel_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getproductmodel_fuzzer/getproductmodel_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetManufactureFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getmanufacture_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getmanufacture_fuzzer/getmanufacture_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBrandFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbrand_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbrand_fuzzer/getbrand_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetMarketNameFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getmarketname_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getmarketname_fuzzer/getmarketname_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetProductSeriesFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getproductseries_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getproductseries_fuzzer/getproductseries_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetSoftwareModelFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getsoftwaremodel_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetHardwareModelFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/gethardwaremodel_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetHardwareProfileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/gethardwareprofile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetSerialFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getserial_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getserial_fuzzer/getserial_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetAbiListFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getabilist_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getabilist_fuzzer/getabilist_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetDisplayVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getdisplayversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getdisplayversion_fuzzer/getdisplayversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetIncrementalVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getincrementalversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getincrementalversion_fuzzer/getincrementalversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBootloaderVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getbootloaderversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBuildTypeFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbuildtype_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbuildtype_fuzzer/getbuildtype_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBuildUserFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbuilduser_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbuilduser_fuzzer/getbuilduser_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBuildHostFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbuildhost_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbuildhost_fuzzer/getbuildhost_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBuildTimeFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbuildtime_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbuildtime_fuzzer/getbuildtime_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetFirstApiVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getfirstapiversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("AclGetSerialFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/aclgetserial_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "aclgetserial_fuzzer/aclgetserial_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetSystemCommitIdFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getsystemcommitid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetDeviceTypeCppFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getdevicetypecpp_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetMajorVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getmajorversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getmajorversion_fuzzer/getmajorversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetSeniorVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getseniorversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getseniorversion_fuzzer/getseniorversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetFeatureVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getfeatureversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getfeatureversion_fuzzer/getfeatureversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetBuildVersionFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getbuildversion_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getbuildversion_fuzzer/getbuildversion_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("AclGetDevUdidFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/aclgetdevudid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbeget_proxy" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetDevUdidFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/getdevudid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "getdevudid_fuzzer/getdevudid_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("AddRemoteWatcherFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/addremotewatcher_fuzzer" + + sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/watcher/proxy/watcher_manager.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_proxy.cpp", + ] + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/param/watcher/agent", + "//base/startup/init/services/log", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (init_paramwatcher_hicollie_enable) { + external_deps += [ "hicollie:libhicollie" ] + } + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources += [ "addremotewatcher_fuzzer/addremotewatcher_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] + if (init_paramwatcher_hicollie_enable) { + defines += [ "HICOLLIE_ENABLE" ] + } +} + +ohos_fuzztest("DelRemoteWatcherFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/delremotewatcher_fuzzer" + sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/watcher/proxy/watcher_manager.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_proxy.cpp", + ] + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/param/watcher/agent", + "//base/startup/init/services/log", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + if (init_paramwatcher_hicollie_enable) { + external_deps += [ "hicollie:libhicollie" ] + } + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources += [ "delremotewatcher_fuzzer/delremotewatcher_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] + if (init_paramwatcher_hicollie_enable) { + defines += [ "HICOLLIE_ENABLE" ] + } +} + +ohos_fuzztest("AddWatcherFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/addwatcher_fuzzer" + + sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/watcher/proxy/watcher_manager.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_proxy.cpp", + ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/param/watcher/agent", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + if (init_paramwatcher_hicollie_enable) { + external_deps += [ "hicollie:libhicollie" ] + } + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources += [ "addwatcher_fuzzer/addwatcher_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] + if (init_paramwatcher_hicollie_enable) { + defines += [ "HICOLLIE_ENABLE" ] + } +} + +ohos_fuzztest("DelWatcherFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/delwatcher_fuzzer" + sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/watcher/proxy/watcher_manager.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_proxy.cpp", + ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/param/watcher/agent", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + if (init_paramwatcher_hicollie_enable) { + external_deps += [ "hicollie:libhicollie" ] + } + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources += [ "delwatcher_fuzzer/delwatcher_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] + if (init_paramwatcher_hicollie_enable) { + defines += [ "HICOLLIE_ENABLE" ] + } +} + +ohos_fuzztest("RefreshWatcherFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/refreshwatcher_fuzzer" + sources = [ + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/watcher/proxy/watcher_manager.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_proxy.cpp", + ] + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/param/watcher/agent", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/log:agent_log", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + if (init_paramwatcher_hicollie_enable) { + external_deps += [ "hicollie:libhicollie" ] + } + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources += [ "refreshwatcher_fuzzer/refreshwatcher_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] + if (init_paramwatcher_hicollie_enable) { + defines += [ "HICOLLIE_ENABLE" ] + } +} + +ohos_fuzztest("SaveParametersFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/saveparameters_fuzzer" + + include_dirs = [ + "//base/startup/init/services/include/param", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps += [ "hilog:libhilog" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "saveparameters_fuzzer/saveparameters_fuzzer.cpp" ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SystemWaitParameterFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/systemwaitparameter_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param:parameter", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SysCheckParamExistFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/syscheckparamexist_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/test/fuzztest/utils/include", + "//base/startup/init/services/param/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param:parameter", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetServiceCtrlInfoFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getservicectrlinfo_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/modules", + "//base/startup/init/services/param/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param/linux:param_init", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "//base/startup/init/services/init/standard/bootstagehooker.c", + "//base/startup/init/services/modules/init_hook/param_hook.c", + "//base/startup/init/services/modules/reboot/reboot_static.c", + "getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.cpp", + ] + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("GetParamSecurityAuditDataFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/getparamsecurityauditdata_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param:parameter", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "//base/startup/init/services/param/base/param_comm.c", + "getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.cpp", + ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("DecodeGidFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/decodegid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param:parameter", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "decodegid_fuzzer/decodegid_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("DecodeUidFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/decodeuid_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/services/param:parameter", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "decodeuid_fuzzer/decodeuid_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("ReadFileToBufFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/readfiletobuf_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/services/param:parameter", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "//base/startup/init/services/log/init_commlog.c", + "readfiletobuf_fuzzer/readfiletobuf_fuzzer.cpp", + ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("LoadParamFromCmdLineFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/loadparamfromcmdline_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/init/include", + "//base/startup/init/services/param/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/services/param:parameter", + "//base/startup/init/services/utils:libinit_utils", + "//base/startup/init/test/fuzztest:libfuzz_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ + "//base/startup/init/services/log/init_commlog.c", + "loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.cpp", + ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("CheckAndCreatFileFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = + "//base/startup/init/test/fuzztest/checkandcreatfile_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/services/param:parameter", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("WriteAllFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/writeall_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/services/param:parameter", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "writeall_fuzzer/writeall_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +ohos_fuzztest("SplitStringFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "//base/startup/init/test/fuzztest/splitstring_fuzzer" + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/test/fuzztest/utils/include", + ] + + deps = [ + "//base/startup/init/services/param:parameter", + "//base/startup/init/services/utils:libinit_utils", + ] + external_deps = [ + "bounds_checking_function:libsec_static", + "hilog:libhilog", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "splitstring_fuzzer/splitstring_fuzzer.cpp" ] + + defines = [ "STARTUP_INIT_TEST" ] +} + +############################################################################################## +group("fuzztest") { + testonly = true + deps = [] + deps += [ + ":AclGetDevUdidFuzzTest", + ":AclGetSerialFuzzTest", + ":AddRemoteWatcherFuzzTest", + ":AddWatcherFuzzTest", + ":BuildControlMessageFuzzTest", + ":ChangeSysAttributePermissionsFuzzTest", + ":CheckAndCreatFileFuzzTest", + ":CmdClientInitFuzzTest", + ":CmdServiceProcessDelClientFuzzTest", + ":DecodeGidFuzzTest", + ":DecodeUidFuzzTest", + ":DelRemoteWatcherFuzzTest", + ":DelWatcherFuzzTest", + ":DoFormatFuzzTest", + ":FindFstabItemForMountPointFuzzTest", + ":FindFstabItemForPathFuzzTest", + ":FindParameterFuzzTest", + ":GetAbiListFuzzTest", + ":GetBlockDeviceByMountPointFuzzTest", + ":GetBlockDeviceByNameFuzzTest", + ":GetBlockDevicePathFuzzTest", + ":GetBoolParameterCppFuzzTest", + ":GetBootSlotsFuzzTest", + ":GetBootloaderVersionFuzzTest", + ":GetBrandFuzzTest", + ":GetBuildHostFuzzTest", + ":GetBuildRootHashFuzzTest", + ":GetBuildTimeFuzzTest", + ":GetBuildTypeFuzzTest", + ":GetBuildUserFuzzTest", + ":GetBuildVersionFuzzTest", + ":GetControlFileFuzzTest", + ":GetControlSocketFuzzTest", + ":GetCurrentSlotFuzzTest", + ":GetDevUdidFuzzTest", + ":GetDeviceNodePermissionsFuzzTest", + ":GetDeviceTypeCFuzzTest", + ":GetDeviceTypeCppFuzzTest", + ":GetDeviceUdevConfByDevNodeFuzzTest", + ":GetDisplayVersionFuzzTest", + ":GetFeatureVersionFuzzTest", + ":GetFirstApiVersionFuzzTest", + ":GetHardwareModelFuzzTest", + ":GetHardwareProfileFuzzTest", + ":GetIncrementalVersionFuzzTest", + ":GetIntParameterCFuzzTest", + ":GetIntParameterCppFuzzTest", + ":GetMajorVersionFuzzTest", + ":GetManufactureFuzzTest", + ":GetMarketNameFuzzTest", + ":GetMountStatusForMountPointFuzzTest", + ":GetOSFullNameFuzzTest", + ":GetOsReleaseTypeFuzzTest", + ":GetParamSecurityAuditDataFuzzTest", + ":GetParameterCFuzzTest", + ":GetParameterCommitIdFuzzTest", + ":GetParameterCppFuzzTest", + ":GetParameterNameFuzzTest", + ":GetParameterValueFuzzTest", + ":GetProductModelFuzzTest", + ":GetProductSeriesFuzzTest", + ":GetSdkApiVersionFuzzTest", + ":GetSecurityPatchTagFuzzTest", + ":GetSeniorVersionFuzzTest", + ":GetSerialFuzzTest", + ":GetServiceCtrlInfoFuzzTest", + ":GetSoftwareModelFuzzTest", + ":GetStringParameterFuzzTest", + ":GetSystemCommitIdFuzzTest", + ":GetUintParameterCFuzzTest", + ":GetVersionIdFuzzTest", + ":HandleBlockDeviceEventFuzzTest", + ":HandleOtherDeviceEventFuzzTest", + ":HasSystemCapabilityFuzzTest", + ":HookMgrAddFuzzTest", + ":HookMgrCreateFuzzTest", + ":HookMgrDelFuzzTest", + ":HookMgrDestroyFuzzTest", + ":HookMgrExecuteFuzzTest", + ":HookMgrGetHooksCntFuzzTest", + ":HookMgrGetStagesCntFuzzTest", + ":HookMgrTraversalFuzzTest", + ":IsSupportedFilesystemFuzzTest", + ":LoadFscryptPolicyFuzzTest", + ":LoadFstabFromCommandLineFuzzTest", + ":LoadParamFromCmdLineFuzzTest", + ":ModuleMgrCreateFuzzTest", + ":ModuleMgrDestroyFuzzTest", + ":ModuleMgrGetCntFuzzTest", + ":ModuleMgrInstallFuzzTest", + ":ModuleMgrScanFuzzTest", + ":ModuleMgrTraversalFuzzTest", + ":ModuleMgrUninstallFuzzTest", + ":MountAllWithFstabFileFuzzTest", + ":MountAllWithFstabFuzzTest", + ":MountOneItemFuzzTest", + ":ParseFstabPerLineFuzzTest", + ":ParseUeventConfigFuzzTest", + ":ParseUeventdConfigFileFuzzTest", + ":ReadFileInDirFuzzTest", + ":ReadFileToBufFuzzTest", + ":ReadFstabFromFileFuzzTest", + ":ReceiveFdsFuzzTest", + ":RefreshWatcherFuzzTest", + ":ReleaseFstabFuzzTest", + ":RemoveParameterWatcherFuzzTest", + ":ServiceControlFuzzTest", + ":ServiceControlStartFuzzTest", + ":ServiceControlStopFuzzTest", + ":ServiceControlWithExtraFuzzTest", + ":ServiceGetFdFuzzTest", + ":ServiceSaveFdFuzzTest", + ":ServiceSaveFdWithPollFuzzTest", + ":ServiceSetReadyFuzzTest", + ":ServiceWaitForStatusFuzzTest", + ":ServiceWatchForStatusFuzzTest", + ":SetParameterCFuzzTest", + ":SetParameterCppFuzzTest", + ":SplitStringFuzzTest", + ":StartServiceByTimerFuzzTest", + ":StopServiceTimerFuzzTest", + ":SysCheckParamExistFuzzTest", + ":SystemDumpParametersFuzzTest", + ":SystemTraversalParameterFuzzTest", + ":SystemWaitParameterFuzzTest", + ":UmountAllWithFstabFileFuzzTest", + ":WaitParameterFuzzTest", + ":WatchParameterFuzzTest", + ":WriteAllFuzzTest", + ] +} +############################################################################### diff --git a/test/fuzztest/aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.cpp b/test/fuzztest/aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe5694ed9e4c0a4b85c2673b74653292f37e470a --- /dev/null +++ b/test/fuzztest/aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "aclgetdevudid_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzAclGetDevUdid(const uint8_t* data, size_t size) + { + bool result = false; + char udid[65] = {0}; + int len = sizeof(udid); + if (!AclGetDevUdid(udid, len)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzAclGetDevUdid(data, size); + return 0; +} diff --git a/test/fuzztest/aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.h b/test/fuzztest/aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a5eb1c461b7f2c367156501472b80eaa9f95937a --- /dev/null +++ b/test/fuzztest/aclgetdevudid_fuzzer/aclgetdevudid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_ACL_GET_DEV_UDID_FUZZER_H +#define TEST_FUZZTEST_ACL_GET_DEV_UDID_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "aclgetdevudid_fuzzer" +#endif diff --git a/test/fuzztest/aclgetdevudid_fuzzer/corpus/init b/test/fuzztest/aclgetdevudid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/aclgetdevudid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/aclgetdevudid_fuzzer/project.xml b/test/fuzztest/aclgetdevudid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/aclgetdevudid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/aclgetserial_fuzzer/aclgetserial_fuzzer.cpp b/test/fuzztest/aclgetserial_fuzzer/aclgetserial_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4acb20ef94ae31370b8fe7b6a6e8a98a62e18790 --- /dev/null +++ b/test/fuzztest/aclgetserial_fuzzer/aclgetserial_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "aclgetserial_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzAclGetSerial(const uint8_t* data, size_t size) + { + bool result = false; + if (AclGetSerial() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzAclGetSerial(data, size); + return 0; +} diff --git a/test/fuzztest/aclgetserial_fuzzer/aclgetserial_fuzzer.h b/test/fuzztest/aclgetserial_fuzzer/aclgetserial_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c27d534fd2f71c4a1bcc527cc08ba9bc1583a0b7 --- /dev/null +++ b/test/fuzztest/aclgetserial_fuzzer/aclgetserial_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_ACL_GET_SERIAL_H +#define TEST_FUZZTEST_ACL_GET_SERIAL_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "aclgetserial_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/aclgetserial_fuzzer/corpus/init b/test/fuzztest/aclgetserial_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/aclgetserial_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/aclgetserial_fuzzer/project.xml b/test/fuzztest/aclgetserial_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/aclgetserial_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/addremotewatcher_fuzzer/addremotewatcher_fuzzer.cpp b/test/fuzztest/addremotewatcher_fuzzer/addremotewatcher_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15414dbdf28e011941d6946b187cb5490a123ead --- /dev/null +++ b/test/fuzztest/addremotewatcher_fuzzer/addremotewatcher_fuzzer.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 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 "addremotewatcher_fuzzer.h" +#include +#include +#include "watcher_manager.h" + +using namespace OHOS::init_param; +namespace OHOS { + bool FuzzAddRemoteWatcher(const uint8_t* data, size_t size) + { + bool result = false; + std::unique_ptr watcherManager = std::make_unique(0, true); + uint32_t id = static_cast(*data); + if (!watcherManager->AddRemoteWatcher(id, nullptr)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzAddRemoteWatcher(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/addremotewatcher_fuzzer/addremotewatcher_fuzzer.h b/test/fuzztest/addremotewatcher_fuzzer/addremotewatcher_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..bbe3552d27e4e9f186993992ee9bd4980ab5a119 --- /dev/null +++ b/test/fuzztest/addremotewatcher_fuzzer/addremotewatcher_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_ADD_REMOTE_WATCHER_FUZZER_H +#define TEST_FUZZTEST_ADD_REMOTE_WATCHER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "addremotewatcher_fuzzer" +#endif diff --git a/test/fuzztest/addremotewatcher_fuzzer/corpus/init b/test/fuzztest/addremotewatcher_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/addremotewatcher_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/addremotewatcher_fuzzer/project.xml b/test/fuzztest/addremotewatcher_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/addremotewatcher_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/addwatcher_fuzzer/addwatcher_fuzzer.cpp b/test/fuzztest/addwatcher_fuzzer/addwatcher_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63651405bba3b8a86b766952971574b8fadeac12 --- /dev/null +++ b/test/fuzztest/addwatcher_fuzzer/addwatcher_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 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 "addwatcher_fuzzer.h" +#include +#include +#include "watcher_manager.h" + +using namespace OHOS::init_param; +namespace OHOS { + bool FuzzAddWatcher(const uint8_t* data, size_t size) + { + bool result = false; + std::unique_ptr watcherManager = std::make_unique(0, true); + std::string str(reinterpret_cast(data), size); + + if (!watcherManager->AddWatcher(str, 0)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzAddWatcher(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/addwatcher_fuzzer/addwatcher_fuzzer.h b/test/fuzztest/addwatcher_fuzzer/addwatcher_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1dc78b6bf0945e723db66831a129ab75ccc78ebb --- /dev/null +++ b/test/fuzztest/addwatcher_fuzzer/addwatcher_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_ADD_WATCHER_FUZZER_H +#define TEST_FUZZTEST_ADD_WATCHER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "addwatcher_fuzzer" +#endif diff --git a/test/fuzztest/addwatcher_fuzzer/corpus/init b/test/fuzztest/addwatcher_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/addwatcher_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/addwatcher_fuzzer/project.xml b/test/fuzztest/addwatcher_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/addwatcher_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.cpp b/test/fuzztest/buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c69c02eb176407b0d036aea2ca164b917bbe9c12 --- /dev/null +++ b/test/fuzztest/buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022-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 "buildcontrolmessage_fuzzer.h" +#include +#include "securec.h" +#include "fd_holder_internal.h" + + +namespace OHOS { + const uint8_t* BASE_DATA = nullptr; + size_t g_baseSize = 0; + size_t g_basePos = 0; + + template T GetData() + { + T object{}; + size_t objectSize = sizeof(object); + if ((BASE_DATA == nullptr) || (objectSize > g_baseSize - g_basePos)) { + return object; + } + errno_t ret = memcpy_s(&object, objectSize, BASE_DATA + g_basePos, objectSize); + if (ret != EOK) { + return {}; + } + g_basePos += objectSize; + return object; + } + + bool FuzzBuildControlMessage(const uint8_t* data, size_t size) + { + bool result = false; + BASE_DATA = data; + g_baseSize = size; + g_basePos = 0; + if (size > sizeof(struct msghdr) + sizeof(int)) { + struct msghdr msghdr = GetData(); + int fd = GetData(); + if (!BuildControlMessage(&msghdr, &fd, 1, false)) { + result = true; + } + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzBuildControlMessage(data, size); + return 0; +} diff --git a/test/fuzztest/buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.h b/test/fuzztest/buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3c7fbe130de66a78589da1a987078286c972e183 --- /dev/null +++ b/test/fuzztest/buildcontrolmessage_fuzzer/buildcontrolmessage_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_BUILD_CONTROL_MESSAGE_H +#define TEST_FUZZTEST_BUILD_CONTROL_MESSAGE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "buildcontrolmessage_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/buildcontrolmessage_fuzzer/corpus/init b/test/fuzztest/buildcontrolmessage_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/buildcontrolmessage_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/buildcontrolmessage_fuzzer/project.xml b/test/fuzztest/buildcontrolmessage_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/buildcontrolmessage_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.cpp b/test/fuzztest/changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a144b68c615e7af2633c8414083f8c407ecf8769 --- /dev/null +++ b/test/fuzztest/changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.cpp @@ -0,0 +1,35 @@ +/* + * 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 "changesysattributepermissions_fuzzer.h" +#include +#include "ueventd_read_cfg.h" + +namespace OHOS { + bool FuzzChangeSysAttributePermissions(const uint8_t* data, size_t size) + { + const char *sysPath = reinterpret_cast(data); + ChangeSysAttributePermissions(sysPath); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzChangeSysAttributePermissions(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.h b/test/fuzztest/changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..96d21d8652b8bbc6e65fb2d2e16462b63bd081c8 --- /dev/null +++ b/test/fuzztest/changesysattributepermissions_fuzzer/changesysattributepermissions_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_CHANGE_SYS_ATTRIBUTE_PERMISSIONS_FUZZER_H +#define TEST_FUZZTEST_CHANGE_SYS_ATTRIBUTE_PERMISSIONS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "changesysattributepermissions_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/changesysattributepermissions_fuzzer/corpus/init b/test/fuzztest/changesysattributepermissions_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/changesysattributepermissions_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/changesysattributepermissions_fuzzer/project.xml b/test/fuzztest/changesysattributepermissions_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/changesysattributepermissions_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.cpp b/test/fuzztest/checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19a12b37900240a3c29dbb1a8e6125b680474e28 --- /dev/null +++ b/test/fuzztest/checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 +#include "init_utils.h" +#include "checkandcreatfile_fuzzer.h" + +namespace OHOS { + bool FuzzCheckAndCreatFile(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + int ret = CheckAndCreatFile(str.c_str(), 0777); + if (ret != 0) { + return false; + }; + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzCheckAndCreatFile(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.h b/test/fuzztest/checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..ca421302f8b497c48d2c6799ccadb7c0cfaa415d --- /dev/null +++ b/test/fuzztest/checkandcreatfile_fuzzer/checkandcreatfile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_CHECK_AND_CREAT_FILE_FUZZER_H +#define TEST_FUZZTEST_CHECK_AND_CREAT_FILE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "checkandcreatfile_fuzzer" +#endif diff --git a/test/fuzztest/checkandcreatfile_fuzzer/corpus/init b/test/fuzztest/checkandcreatfile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/checkandcreatfile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/checkandcreatfile_fuzzer/project.xml b/test/fuzztest/checkandcreatfile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/checkandcreatfile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/cmdclientinit_fuzzer/cmdclientinit_fuzzer.cpp b/test/fuzztest/cmdclientinit_fuzzer/cmdclientinit_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb1d41052c8c1f91ed0fbe92e66aa297decf2956 --- /dev/null +++ b/test/fuzztest/cmdclientinit_fuzzer/cmdclientinit_fuzzer.cpp @@ -0,0 +1,35 @@ +/* + * 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 "cmdclientinit_fuzzer.h" +#include +#include "control_fd.h" + +namespace OHOS { + bool FuzzCmdClientInit(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + CmdClientInit(str.c_str(), 1, str.c_str(), nullptr); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzCmdClientInit(data, size); + return 0; +} diff --git a/test/fuzztest/cmdclientinit_fuzzer/cmdclientinit_fuzzer.h b/test/fuzztest/cmdclientinit_fuzzer/cmdclientinit_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d432169daabf86af98bdc8c2185e807daea057c5 --- /dev/null +++ b/test/fuzztest/cmdclientinit_fuzzer/cmdclientinit_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_CMD_CLIENT_INIT_FUZZER_H +#define TEST_FUZZTEST_CMD_CLIENT_INIT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "cmdclientinit_fuzzer" +#endif diff --git a/test/fuzztest/cmdclientinit_fuzzer/corpus/init b/test/fuzztest/cmdclientinit_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/cmdclientinit_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/cmdclientinit_fuzzer/project.xml b/test/fuzztest/cmdclientinit_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/cmdclientinit_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.cpp b/test/fuzztest/cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f3447af3392e4a2b9f6327886319215301dc525 --- /dev/null +++ b/test/fuzztest/cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * 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 "cmdserviceinit_fuzzer.h" +#include +#include "fuzz_utils.h" +#include "control_fd.h" + +static void Func(uint16_t type, const char *serviceCmd, const void *context) +{ + printf("type is:%d, serviceCmd is:%s\n", type, serviceCmd); +} + +namespace OHOS { + bool FuzzCmdServiceInit(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + CloseStdout(); + CmdServiceInit(str.c_str(), Func, LE_GetDefaultLoop()); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzCmdServiceInit(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.h b/test/fuzztest/cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..2aaadd26302baf41571e01388a13c9fda9e92b95 --- /dev/null +++ b/test/fuzztest/cmdserviceinit_fuzzer/cmdserviceinit_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_CMD_SERVICE_INIT_FUZZER_H +#define TEST_FUZZTEST_CMD_SERVICE_INIT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "cmdserviceinit_fuzzer" +#endif diff --git a/test/fuzztest/cmdserviceinit_fuzzer/corpus/init b/test/fuzztest/cmdserviceinit_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/cmdserviceinit_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/cmdserviceinit_fuzzer/project.xml b/test/fuzztest/cmdserviceinit_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/cmdserviceinit_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.cpp b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ceefb7704f7405e169ca05772613ac3633543d8b --- /dev/null +++ b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022-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 "cmdserviceprocessdelclient_fuzzer.h" +#include +#include "securec.h" +#include "control_fd.h" + +namespace OHOS { + const uint8_t *BASE_DATA = nullptr; + size_t g_baseSize = 0; + size_t g_basePos = 0; + + template T GetData() + { + T object{}; + size_t objectSize = sizeof(object); + if ((BASE_DATA == nullptr) || (objectSize > g_baseSize - g_basePos)) { + return object; + } + errno_t ret = memcpy_s(&object, objectSize, BASE_DATA + g_basePos, objectSize); + if (ret != EOK) { + return {}; + } + g_basePos += objectSize; + return object; + } + + bool FuzzCmdServiceProcessDelClient(const uint8_t* data, size_t size) + { + BASE_DATA = data; + g_baseSize = size; + g_basePos = 0; + if (size > sizeof(pid_t)) { + pid_t pid = GetData(); + CmdServiceProcessDelClient(pid); + } + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzCmdServiceProcessDelClient(data, size); + return 0; +} diff --git a/test/fuzztest/cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.h b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..707d2182c472f45212d810f8bbe63cedebd99ea8 --- /dev/null +++ b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/cmdserviceprocessdelclient_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_CMD_SERVICE_PROCESS_DEL_CLIENT_FUZZER_H +#define TEST_FUZZTEST_CMD_SERVICE_PROCESS_DEL_CLIENT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "cmdserviceprocessdelclient_fuzzer" +#endif diff --git a/test/fuzztest/cmdserviceprocessdelclient_fuzzer/corpus/init b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/cmdserviceprocessdelclient_fuzzer/project.xml b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/cmdserviceprocessdelclient_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/corpus b/test/fuzztest/corpus new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/corpus @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/decodegid_fuzzer/corpus/init b/test/fuzztest/decodegid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/decodegid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/decodegid_fuzzer/decodegid_fuzzer.cpp b/test/fuzztest/decodegid_fuzzer/decodegid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3246349f0cfaad321f35db749f21404a6d3202ee --- /dev/null +++ b/test/fuzztest/decodegid_fuzzer/decodegid_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "init_utils.h" +#include +#include "decodegid_fuzzer.h" + +namespace OHOS { + bool FuzzDecodeGid(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + + int ret = DecodeGid(str.c_str()); + if (ret == -1) { + return false; + }; + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDecodeGid(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/decodegid_fuzzer/decodegid_fuzzer.h b/test/fuzztest/decodegid_fuzzer/decodegid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..9d05d8a8002872608af276bc1355dd5edd98af13 --- /dev/null +++ b/test/fuzztest/decodegid_fuzzer/decodegid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_DECODE_GID_FUZZER_H +#define TEST_FUZZTEST_DECODE_GID_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "decodegid_fuzzer" +#endif diff --git a/test/fuzztest/decodegid_fuzzer/project.xml b/test/fuzztest/decodegid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/decodegid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/decodeuid_fuzzer/corpus/init b/test/fuzztest/decodeuid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/decodeuid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/decodeuid_fuzzer/decodeuid_fuzzer.cpp b/test/fuzztest/decodeuid_fuzzer/decodeuid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86135540aba5f80d7ac564ea67705b450760a14c --- /dev/null +++ b/test/fuzztest/decodeuid_fuzzer/decodeuid_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "init_utils.h" +#include +#include "decodeuid_fuzzer.h" + +namespace OHOS { + bool FuzzDecodeUid(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + + int ret = DecodeUid(str.c_str()); + if (ret == -1) { + return false; + }; + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDecodeUid(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/decodeuid_fuzzer/decodeuid_fuzzer.h b/test/fuzztest/decodeuid_fuzzer/decodeuid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..712efe40ca032a1e6ff87f3303cbc4a5a39fb45f --- /dev/null +++ b/test/fuzztest/decodeuid_fuzzer/decodeuid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_DECODE_UID_FUZZER_H +#define TEST_FUZZTEST_DECODE_UID_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "decodeuid_fuzzer" +#endif diff --git a/test/fuzztest/decodeuid_fuzzer/project.xml b/test/fuzztest/decodeuid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/decodeuid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/delremotewatcher_fuzzer/corpus/init b/test/fuzztest/delremotewatcher_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/delremotewatcher_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/delremotewatcher_fuzzer/delremotewatcher_fuzzer.cpp b/test/fuzztest/delremotewatcher_fuzzer/delremotewatcher_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c663eb718bf43aaae0d99747b0fd375ce2858fb --- /dev/null +++ b/test/fuzztest/delremotewatcher_fuzzer/delremotewatcher_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 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 "delremotewatcher_fuzzer.h" +#include +#include +#include "watcher_manager.h" + +using namespace OHOS::init_param; +namespace OHOS { + bool FuzzDelRemoteWatcher(const uint8_t* data, size_t size) + { + bool result = false; + std::unique_ptr watcherManager = std::make_unique(0, true); + + uint32_t id = static_cast(*data); + if (!watcherManager->DelRemoteWatcher(id)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDelRemoteWatcher(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/delremotewatcher_fuzzer/delremotewatcher_fuzzer.h b/test/fuzztest/delremotewatcher_fuzzer/delremotewatcher_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..8e3918262517cc0cfdf2f4716a90ac40445196eb --- /dev/null +++ b/test/fuzztest/delremotewatcher_fuzzer/delremotewatcher_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_DEL_REMOTE_WATCHER_FUZZER_H +#define TEST_FUZZTEST_DEL_REMOTE_WATCHER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "delremotewatcher_fuzzer" +#endif diff --git a/test/fuzztest/delremotewatcher_fuzzer/project.xml b/test/fuzztest/delremotewatcher_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/delremotewatcher_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/delwatcher_fuzzer/corpus/init b/test/fuzztest/delwatcher_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/delwatcher_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/delwatcher_fuzzer/delwatcher_fuzzer.cpp b/test/fuzztest/delwatcher_fuzzer/delwatcher_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..064dd748b4ac917be8190c3ee59d2be10951a57e --- /dev/null +++ b/test/fuzztest/delwatcher_fuzzer/delwatcher_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 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 "delwatcher_fuzzer.h" +#include +#include +#include "watcher_manager.h" + +using namespace OHOS::init_param; +namespace OHOS { + bool FuzzDelWatcher(const uint8_t* data, size_t size) + { + bool result = false; + std::unique_ptr watcherManager = std::make_unique(0, true); + std::string str(reinterpret_cast(data), size); + + if (!watcherManager->DelWatcher(str, 0)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDelWatcher(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/delwatcher_fuzzer/delwatcher_fuzzer.h b/test/fuzztest/delwatcher_fuzzer/delwatcher_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..e0c6adf59e64bee86c1a959d6a4566ba9c5c2915 --- /dev/null +++ b/test/fuzztest/delwatcher_fuzzer/delwatcher_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_DEL_WATCHER_FUZZER_H +#define TEST_FUZZTEST_DEL_WATCHER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "delwatcher_fuzzer" +#endif diff --git a/test/fuzztest/delwatcher_fuzzer/project.xml b/test/fuzztest/delwatcher_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/delwatcher_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/doformat_fuzzer/corpus/init b/test/fuzztest/doformat_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/doformat_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/doformat_fuzzer/doformat_fuzzer.cpp b/test/fuzztest/doformat_fuzzer/doformat_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be0ac2fb2eb4e28fa706bce65428bb1af207a08f --- /dev/null +++ b/test/fuzztest/doformat_fuzzer/doformat_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "doformat_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzDoFormat(const uint8_t* data, size_t size) + { + bool resule = false; + std::string str(reinterpret_cast(data), size); + if (!DoFormat(str.c_str(), str.c_str())) { + resule = true; + }; + return resule; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDoFormat(data, size); + return 0; +} diff --git a/test/fuzztest/doformat_fuzzer/doformat_fuzzer.h b/test/fuzztest/doformat_fuzzer/doformat_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..dd600a4b023afcdc8dc6b4efed1d9f816d7a393a --- /dev/null +++ b/test/fuzztest/doformat_fuzzer/doformat_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_DO_FORMAT_FUZZER_H +#define TEST_FUZZTEST_DO_FORMAT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "doformat_fuzzer" +#endif diff --git a/test/fuzztest/doformat_fuzzer/project.xml b/test/fuzztest/doformat_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/doformat_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/doreboot_fuzzer/corpus/init b/test/fuzztest/doreboot_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/doreboot_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/doreboot_fuzzer/doreboot_fuzzer.cpp b/test/fuzztest/doreboot_fuzzer/doreboot_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64e6754778185affe87f9f1b8cf269578831978f --- /dev/null +++ b/test/fuzztest/doreboot_fuzzer/doreboot_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "doreboot_fuzzer.h" +#include +#include "init_reboot.h" + +namespace OHOS { + bool FuzzDoReboot(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!DoReboot(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDoReboot(data, size); + return 0; +} diff --git a/test/fuzztest/doreboot_fuzzer/doreboot_fuzzer.h b/test/fuzztest/doreboot_fuzzer/doreboot_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..579524b65cdf9effbd3254dc163c31d5bc15aaad --- /dev/null +++ b/test/fuzztest/doreboot_fuzzer/doreboot_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_DOREBOOT_FUZZER_H +#define TEST_FUZZTEST_DOREBOOT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "doreboot_fuzzer" +#endif diff --git a/test/fuzztest/doreboot_fuzzer/project.xml b/test/fuzztest/doreboot_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/doreboot_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/dorebootext_fuzzer/corpus/init b/test/fuzztest/dorebootext_fuzzer/corpus/init new file mode 100755 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/test/fuzztest/dorebootext_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/dorebootext_fuzzer/dorebootext_fuzzer.cpp b/test/fuzztest/dorebootext_fuzzer/dorebootext_fuzzer.cpp new file mode 100755 index 0000000000000000000000000000000000000000..bedf63e4de1029bbe20f5f6f58e424a1b5f53333 --- /dev/null +++ b/test/fuzztest/dorebootext_fuzzer/dorebootext_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 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 "dorebootext_fuzzer.h" +#include +#include "init_reboot.h" + +namespace OHOS { + bool FuzzDoRebootExt(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!DoRebootExt(str.c_str(), str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzDoRebootExt(data, size); + return 0; +} diff --git a/test/fuzztest/dorebootext_fuzzer/dorebootext_fuzzer.h b/test/fuzztest/dorebootext_fuzzer/dorebootext_fuzzer.h new file mode 100755 index 0000000000000000000000000000000000000000..9f102b18473b1779c085ab9d8e6b0f1b529b864b --- /dev/null +++ b/test/fuzztest/dorebootext_fuzzer/dorebootext_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_DOREBOOTEXT_FUZZER_H +#define TEST_FUZZTEST_DOREBOOTEXT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "dorebootext_fuzzer" +#endif diff --git a/test/fuzztest/dorebootext_fuzzer/project.xml b/test/fuzztest/dorebootext_fuzzer/project.xml new file mode 100755 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/dorebootext_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/findfstabitemformountpoint_fuzzer/corpus/init b/test/fuzztest/findfstabitemformountpoint_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/findfstabitemformountpoint_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.cpp b/test/fuzztest/findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea1b58bda27dd08d78f168380ecded51d3231665 --- /dev/null +++ b/test/fuzztest/findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.cpp @@ -0,0 +1,55 @@ +/* + * 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 "findfstabitemformountpoint_fuzzer.h" +#include +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzFindFstabItemForMountPoint(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + Fstab *fstab = ReadFstabFromFile("fstab.test", false); + + std::string str(reinterpret_cast(data), size); + if (FindFstabItemForMountPoint(*fstab, str.c_str()) != nullptr) { + result = true; + }; + + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzFindFstabItemForMountPoint(data, size); + return 0; +} diff --git a/test/fuzztest/findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.h b/test/fuzztest/findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3ec09fae22f85e1996b2ea5527940ee05c054c36 --- /dev/null +++ b/test/fuzztest/findfstabitemformountpoint_fuzzer/findfstabitemformountpoint_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_FIND_FSTAB_ITEM_FOR_MOUNT_POINT_FUZZER_H +#define TEST_FUZZTEST_FIND_FSTAB_ITEM_FOR_MOUNT_POINT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "findfstabitemformountpoint_fuzzer" +#endif diff --git a/test/fuzztest/findfstabitemformountpoint_fuzzer/project.xml b/test/fuzztest/findfstabitemformountpoint_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/findfstabitemformountpoint_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/findfstabitemforpath_fuzzer/corpus/init b/test/fuzztest/findfstabitemforpath_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/findfstabitemforpath_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.cpp b/test/fuzztest/findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1db6f628ca4ae780ca14867d9e3fb5b61f8e659c --- /dev/null +++ b/test/fuzztest/findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.cpp @@ -0,0 +1,55 @@ +/* + * 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 "findfstabitemforpath_fuzzer.h" +#include +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzFindFstabItemForPath(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + Fstab *fstab = ReadFstabFromFile("fstab.test", false); + + std::string str(reinterpret_cast(data), size); + if (FindFstabItemForPath(*fstab, str.c_str()) != nullptr) { + result = true; + }; + + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzFindFstabItemForPath(data, size); + return 0; +} diff --git a/test/fuzztest/findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.h b/test/fuzztest/findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..89df068f118e6e77f9cc0d47074d3b310e43bc6f --- /dev/null +++ b/test/fuzztest/findfstabitemforpath_fuzzer/findfstabitemforpath_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_FIND_FSTAB_ITEM_FOR_PATH_FUZZER_H +#define TEST_FUZZTEST_FIND_FSTAB_ITEM_FOR_PATH_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "findfstabitemforpath_fuzzer" +#endif diff --git a/test/fuzztest/findfstabitemforpath_fuzzer/project.xml b/test/fuzztest/findfstabitemforpath_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/findfstabitemforpath_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/findparameter_fuzzer/corpus/init b/test/fuzztest/findparameter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/findparameter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/findparameter_fuzzer/findparameter_fuzzer.cpp b/test/fuzztest/findparameter_fuzzer/findparameter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3b6a93c8629021d1c485f9c4bc9f253e6d79214 --- /dev/null +++ b/test/fuzztest/findparameter_fuzzer/findparameter_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "findparameter_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzFindParameter(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!FindParameter(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzFindParameter(data, size); + return 0; +} diff --git a/test/fuzztest/findparameter_fuzzer/findparameter_fuzzer.h b/test/fuzztest/findparameter_fuzzer/findparameter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..fbdb4937d002444e02bc2c835be5bbea2feff720 --- /dev/null +++ b/test/fuzztest/findparameter_fuzzer/findparameter_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_FINDPARAMETER_FUZZER_H +#define TEST_FUZZTEST_FINDPARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "findparameter_fuzzer" +#endif diff --git a/test/fuzztest/findparameter_fuzzer/project.xml b/test/fuzztest/findparameter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/findparameter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getabilist_fuzzer/corpus/init b/test/fuzztest/getabilist_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getabilist_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getabilist_fuzzer/getabilist_fuzzer.cpp b/test/fuzztest/getabilist_fuzzer/getabilist_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08b36008dc230de8e5a258d788a0eb9825dbd6cd --- /dev/null +++ b/test/fuzztest/getabilist_fuzzer/getabilist_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getabilist_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetAbiList(const uint8_t* data, size_t size) + { + bool result = false; + if (GetAbiList() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetAbiList(data, size); + return 0; +} diff --git a/test/fuzztest/getabilist_fuzzer/getabilist_fuzzer.h b/test/fuzztest/getabilist_fuzzer/getabilist_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..84963988f1e79db1c4ff2d918ca909258aab2bc2 --- /dev/null +++ b/test/fuzztest/getabilist_fuzzer/getabilist_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_ABILIST_H +#define TEST_FUZZTEST_GET_ABILIST_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getabilist_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getabilist_fuzzer/project.xml b/test/fuzztest/getabilist_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getabilist_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getblockdevicebymountpoint_fuzzer/corpus/init b/test/fuzztest/getblockdevicebymountpoint_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getblockdevicebymountpoint_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.cpp b/test/fuzztest/getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d21cb915be9d31d600377901e0c7be5d61afed7c --- /dev/null +++ b/test/fuzztest/getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.cpp @@ -0,0 +1,54 @@ +/* + * 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 "getblockdevicebymountpoint_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzGetBlockDeviceByMountPoint(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + const Fstab *fstab = ReadFstabFromFile("fstab.test", false); + std::string str(reinterpret_cast(data), size); + char deviceName[100] = {0}; + int length = sizeof(deviceName); + if (!GetBlockDeviceByMountPoint(str.c_str(), fstab, deviceName, length)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBlockDeviceByMountPoint(data, size); + return 0; +} diff --git a/test/fuzztest/getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.h b/test/fuzztest/getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..e167a17cc6463dbacb9e52e90f599fabecc84cc9 --- /dev/null +++ b/test/fuzztest/getblockdevicebymountpoint_fuzzer/getblockdevicebymountpoint_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BLOCK_DEVICE_BY_MOUNT_POINT_FUZZER_H +#define TEST_FUZZTEST_GET_BLOCK_DEVICE_BY_MOUNT_POINT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getblockdevicebymountpoint_fuzzer" +#endif diff --git a/test/fuzztest/getblockdevicebymountpoint_fuzzer/project.xml b/test/fuzztest/getblockdevicebymountpoint_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getblockdevicebymountpoint_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getblockdevicebyname_fuzzer/corpus/init b/test/fuzztest/getblockdevicebyname_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getblockdevicebyname_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.cpp b/test/fuzztest/getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4ff51dbaa2860e41889d61c51cdd9d9d0c93588 --- /dev/null +++ b/test/fuzztest/getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.cpp @@ -0,0 +1,57 @@ +/* + * 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 "getblockdevicebyname_fuzzer.h" +#include +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzGetBlockDeviceByName(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + const Fstab *fstab = ReadFstabFromFile("fstab.test", false); + + std::string str(reinterpret_cast(data), size); + char miscDev[1024] = {0}; + size_t len = sizeof(miscDev); + + if (GetBlockDeviceByName(str.c_str(), fstab, miscDev, len)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBlockDeviceByName(data, size); + return 0; +} diff --git a/test/fuzztest/getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.h b/test/fuzztest/getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6fe36e6532b60b7205bcf423a1c7abcc441a1fb3 --- /dev/null +++ b/test/fuzztest/getblockdevicebyname_fuzzer/getblockdevicebyname_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BLOCK_DEVICE_NAME_FUZZER_H +#define TEST_FUZZTEST_GET_BLOCK_DEVICE_NAME_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getblockdevicebyname_fuzzer" +#endif diff --git a/test/fuzztest/getblockdevicebyname_fuzzer/project.xml b/test/fuzztest/getblockdevicebyname_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getblockdevicebyname_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getblockdevicepath_fuzzer/corpus/init b/test/fuzztest/getblockdevicepath_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getblockdevicepath_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.cpp b/test/fuzztest/getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43e915812777ac39adb2e1b45559237d2997b6a0 --- /dev/null +++ b/test/fuzztest/getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "getblockdevicepath_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzGetBlockDevicePath(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + + if (!GetBlockDevicePath(str.c_str(), nullptr, size)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBlockDevicePath(data, size); + return 0; +} diff --git a/test/fuzztest/getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.h b/test/fuzztest/getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a457d52c27ebf86812019b0b8bf8fff326ad72b5 --- /dev/null +++ b/test/fuzztest/getblockdevicepath_fuzzer/getblockdevicepath_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BLOCK_DEVICE_PATH_FUZZER_H +#define TEST_FUZZTEST_GET_BLOCK_DEVICE_PATH_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getblockdevicepath_fuzzer" +#endif diff --git a/test/fuzztest/getblockdevicepath_fuzzer/project.xml b/test/fuzztest/getblockdevicepath_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getblockdevicepath_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getboolparametercpp_fuzzer/corpus/init b/test/fuzztest/getboolparametercpp_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getboolparametercpp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.cpp b/test/fuzztest/getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87fbf09e27e4d14d6c8262bafb5d3b06ee38a9b4 --- /dev/null +++ b/test/fuzztest/getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "getboolparametercpp_fuzzer.h" +#include +#include "parameters.h" + +namespace OHOS { + bool FuzzGetBoolParameter(const uint8_t* data, size_t size) + { + bool result = false; + std::string key(reinterpret_cast(data), size); + if (system::GetBoolParameter(key, false)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBoolParameter(data, size); + return 0; +} diff --git a/test/fuzztest/getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.h b/test/fuzztest/getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..23f15962e8c38c935836edacdad24442e2aac923 --- /dev/null +++ b/test/fuzztest/getboolparametercpp_fuzzer/getboolparametercpp_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BOOL_PARAMETER_CPP_FUZZER_H +#define TEST_FUZZTEST_GET_BOOL_PARAMETER_CPP_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getboolparametercpp_fuzzer" +#endif diff --git a/test/fuzztest/getboolparametercpp_fuzzer/project.xml b/test/fuzztest/getboolparametercpp_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getboolparametercpp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbootloaderversion_fuzzer/corpus/init b/test/fuzztest/getbootloaderversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbootloaderversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.cpp b/test/fuzztest/getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..308ffb4bd35726971daaca1bb3303ce9a3398909 --- /dev/null +++ b/test/fuzztest/getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbootloaderversion_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBootloaderVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBootloaderVersion() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBootloaderVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.h b/test/fuzztest/getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a16df16f04e02a1191dcb6953a891312a12474d4 --- /dev/null +++ b/test/fuzztest/getbootloaderversion_fuzzer/getbootloaderversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BOOTLOADER_VERSION_H +#define TEST_FUZZTEST_GET_BOOTLOADER_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbootloaderversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbootloaderversion_fuzzer/project.xml b/test/fuzztest/getbootloaderversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbootloaderversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbootslots_fuzzer/corpus/init b/test/fuzztest/getbootslots_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbootslots_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbootslots_fuzzer/getbootslots_fuzzer.cpp b/test/fuzztest/getbootslots_fuzzer/getbootslots_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee1deee0fc0ad5d16447939de30d8e19c075320f --- /dev/null +++ b/test/fuzztest/getbootslots_fuzzer/getbootslots_fuzzer.cpp @@ -0,0 +1,34 @@ +/* + * 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 "getbootslots_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzGetBootSlots(const uint8_t* data, size_t size) + { + GetBootSlots(); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBootSlots(data, size); + return 0; +} diff --git a/test/fuzztest/getbootslots_fuzzer/getbootslots_fuzzer.h b/test/fuzztest/getbootslots_fuzzer/getbootslots_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..249839e967987a78ffc1f7d505e6fd026489c441 --- /dev/null +++ b/test/fuzztest/getbootslots_fuzzer/getbootslots_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BOOT_SLOTS_H +#define TEST_FUZZTEST_GET_BOOT_SLOTS_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbootslots_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbootslots_fuzzer/project.xml b/test/fuzztest/getbootslots_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbootslots_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbrand_fuzzer/corpus/init b/test/fuzztest/getbrand_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbrand_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbrand_fuzzer/getbrand_fuzzer.cpp b/test/fuzztest/getbrand_fuzzer/getbrand_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd98b230dd43a76ff88b7214ada33aaa7a2b3eaa --- /dev/null +++ b/test/fuzztest/getbrand_fuzzer/getbrand_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbrand_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBrand(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBrand() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBrand(data, size); + return 0; +} diff --git a/test/fuzztest/getbrand_fuzzer/getbrand_fuzzer.h b/test/fuzztest/getbrand_fuzzer/getbrand_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..bba400d52c8b306adfbfd08532d5e3b46d79fb5b --- /dev/null +++ b/test/fuzztest/getbrand_fuzzer/getbrand_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BRAND_H +#define TEST_FUZZTEST_GET_BRAND_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbrand_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbrand_fuzzer/project.xml b/test/fuzztest/getbrand_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbrand_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbuildhost_fuzzer/corpus/init b/test/fuzztest/getbuildhost_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbuildhost_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbuildhost_fuzzer/getbuildhost_fuzzer.cpp b/test/fuzztest/getbuildhost_fuzzer/getbuildhost_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8c8d04fd6a8f2b993678c10ccfa0ffd0f1f1d17 --- /dev/null +++ b/test/fuzztest/getbuildhost_fuzzer/getbuildhost_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbuildhost_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBuildHost(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBuildHost() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBuildHost(data, size); + return 0; +} diff --git a/test/fuzztest/getbuildhost_fuzzer/getbuildhost_fuzzer.h b/test/fuzztest/getbuildhost_fuzzer/getbuildhost_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a33e412365939b4e6b3772e17bce18f6988da720 --- /dev/null +++ b/test/fuzztest/getbuildhost_fuzzer/getbuildhost_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BUILD_HOST_H +#define TEST_FUZZTEST_GET_BUILD_HOST_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbuildhost_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbuildhost_fuzzer/project.xml b/test/fuzztest/getbuildhost_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbuildhost_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbuildroothash_fuzzer/corpus/init b/test/fuzztest/getbuildroothash_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbuildroothash_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbuildroothash_fuzzer/getbuildroothash_fuzzer.cpp b/test/fuzztest/getbuildroothash_fuzzer/getbuildroothash_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65f0ce3df8bc58820d76868fef8c66527c8c33f2 --- /dev/null +++ b/test/fuzztest/getbuildroothash_fuzzer/getbuildroothash_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbuildroothash_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBuildRootHash(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBuildRootHash() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBuildRootHash(data, size); + return 0; +} diff --git a/test/fuzztest/getbuildroothash_fuzzer/getbuildroothash_fuzzer.h b/test/fuzztest/getbuildroothash_fuzzer/getbuildroothash_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a4c85dc8b6c86101b90b0d3de71e6780fc0ce8a1 --- /dev/null +++ b/test/fuzztest/getbuildroothash_fuzzer/getbuildroothash_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BUILD_ROOT_HASH_H +#define TEST_FUZZTEST_GET_BUILD_ROOT_HASH_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbuildroothash_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbuildroothash_fuzzer/project.xml b/test/fuzztest/getbuildroothash_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbuildroothash_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbuildtime_fuzzer/corpus/init b/test/fuzztest/getbuildtime_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbuildtime_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbuildtime_fuzzer/getbuildtime_fuzzer.cpp b/test/fuzztest/getbuildtime_fuzzer/getbuildtime_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80f0eb59c2a95847b7877b78d7de033638c6fa2b --- /dev/null +++ b/test/fuzztest/getbuildtime_fuzzer/getbuildtime_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbuildtime_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBuildTime(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBuildTime() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBuildTime(data, size); + return 0; +} diff --git a/test/fuzztest/getbuildtime_fuzzer/getbuildtime_fuzzer.h b/test/fuzztest/getbuildtime_fuzzer/getbuildtime_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7d4413d9c485ed5c319c443818ab1d13110a6412 --- /dev/null +++ b/test/fuzztest/getbuildtime_fuzzer/getbuildtime_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BUILD_TIME_H +#define TEST_FUZZTEST_GET_BUILD_TIME_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbuildtime_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbuildtime_fuzzer/project.xml b/test/fuzztest/getbuildtime_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbuildtime_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbuildtype_fuzzer/corpus/init b/test/fuzztest/getbuildtype_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbuildtype_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbuildtype_fuzzer/getbuildtype_fuzzer.cpp b/test/fuzztest/getbuildtype_fuzzer/getbuildtype_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d37e0028bb40ab61350d808268462905fba51b6 --- /dev/null +++ b/test/fuzztest/getbuildtype_fuzzer/getbuildtype_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbuildtype_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBuildType(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBuildType() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBuildType(data, size); + return 0; +} diff --git a/test/fuzztest/getbuildtype_fuzzer/getbuildtype_fuzzer.h b/test/fuzztest/getbuildtype_fuzzer/getbuildtype_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..e1ddf9f49cb1616e90aa02714f76fcae2be7212d --- /dev/null +++ b/test/fuzztest/getbuildtype_fuzzer/getbuildtype_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BUILD_TYPE_H +#define TEST_FUZZTEST_GET_BUILD_TYPE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbuildtype_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbuildtype_fuzzer/project.xml b/test/fuzztest/getbuildtype_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbuildtype_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbuilduser_fuzzer/corpus/init b/test/fuzztest/getbuilduser_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbuilduser_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbuilduser_fuzzer/getbuilduser_fuzzer.cpp b/test/fuzztest/getbuilduser_fuzzer/getbuilduser_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94d74dc10d660cc30f3dbccd7142b97a6083ce47 --- /dev/null +++ b/test/fuzztest/getbuilduser_fuzzer/getbuilduser_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbuilduser_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetBuildUser(const uint8_t* data, size_t size) + { + bool result = false; + if (GetBuildUser() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBuildUser(data, size); + return 0; +} diff --git a/test/fuzztest/getbuilduser_fuzzer/getbuilduser_fuzzer.h b/test/fuzztest/getbuilduser_fuzzer/getbuilduser_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..40f54b8c31e5c8c6990d8af70a62130b263b82e4 --- /dev/null +++ b/test/fuzztest/getbuilduser_fuzzer/getbuilduser_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BUILD_USER_H +#define TEST_FUZZTEST_GET_BUILD_USER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbuilduser_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbuilduser_fuzzer/project.xml b/test/fuzztest/getbuilduser_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbuilduser_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getbuildversion_fuzzer/corpus/init b/test/fuzztest/getbuildversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getbuildversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getbuildversion_fuzzer/getbuildversion_fuzzer.cpp b/test/fuzztest/getbuildversion_fuzzer/getbuildversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75c72bf3f818f0c2f006b3bfa13456f8962e3e09 --- /dev/null +++ b/test/fuzztest/getbuildversion_fuzzer/getbuildversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getbuildversion_fuzzer.h" +#include +#include "sysversion.h" + +namespace OHOS { + bool FuzzGetBuildVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetBuildVersion()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetBuildVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getbuildversion_fuzzer/getbuildversion_fuzzer.h b/test/fuzztest/getbuildversion_fuzzer/getbuildversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..03e6ca8e678d6639ef55ffeedf18d3bd84866976 --- /dev/null +++ b/test/fuzztest/getbuildversion_fuzzer/getbuildversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_BUILD_VERSION_H +#define TEST_FUZZTEST_GET_BUILD_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getbuildversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getbuildversion_fuzzer/project.xml b/test/fuzztest/getbuildversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getbuildversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getcontrolfile_fuzzer/corpus/init b/test/fuzztest/getcontrolfile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getcontrolfile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getcontrolfile_fuzzer/getcontrolfile_fuzzer.cpp b/test/fuzztest/getcontrolfile_fuzzer/getcontrolfile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c236e2f6715049782c4a1aab1d9eef2881fd4d0d --- /dev/null +++ b/test/fuzztest/getcontrolfile_fuzzer/getcontrolfile_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * 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 "getcontrolfile_fuzzer.h" +#include +#include +#include "init_file.h" + +namespace OHOS { + bool FuzzGetControlFile(const uint8_t* data, size_t size) + { + bool result = false; + if (size > PATH_MAX) { + return true; + } + std::string str(reinterpret_cast(data), size); + if (!GetControlFile(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetControlFile(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/getcontrolfile_fuzzer/getcontrolfile_fuzzer.h b/test/fuzztest/getcontrolfile_fuzzer/getcontrolfile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..ba834febe0ea32eb9e7f3aa4b5756682ace839af --- /dev/null +++ b/test/fuzztest/getcontrolfile_fuzzer/getcontrolfile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GETCONTROLFILE_FUZZER_H +#define TEST_FUZZTEST_GETCONTROLFILE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getcontrolfile_fuzzer" +#endif diff --git a/test/fuzztest/getcontrolfile_fuzzer/project.xml b/test/fuzztest/getcontrolfile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getcontrolfile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getcontrolsocket_fuzzer/corpus/init b/test/fuzztest/getcontrolsocket_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getcontrolsocket_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.cpp b/test/fuzztest/getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fc40ad7d0a0334ec18fc5a35f52ca28a0b11a39 --- /dev/null +++ b/test/fuzztest/getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "getcontrolsocket_fuzzer.h" +#include +#include "init_socket.h" + +namespace OHOS { + bool FuzzGetControlSocket(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!GetControlSocket(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetControlSocket(data, size); + return 0; +} diff --git a/test/fuzztest/getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.h b/test/fuzztest/getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f1e17f1280a87c218065fc9d88da329599e75e5c --- /dev/null +++ b/test/fuzztest/getcontrolsocket_fuzzer/getcontrolsocket_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GETCONTROLSOCKET_FUZZER_H +#define TEST_FUZZTEST_GETCONTROLSOCKET_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getcontrolsocket_fuzzer" +#endif diff --git a/test/fuzztest/getcontrolsocket_fuzzer/project.xml b/test/fuzztest/getcontrolsocket_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getcontrolsocket_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getcurrentslot_fuzzer/corpus/init b/test/fuzztest/getcurrentslot_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getcurrentslot_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getcurrentslot_fuzzer/getcurrentslot_fuzzer.cpp b/test/fuzztest/getcurrentslot_fuzzer/getcurrentslot_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..737463822978a3b5211b117e063c9bc3874a3f82 --- /dev/null +++ b/test/fuzztest/getcurrentslot_fuzzer/getcurrentslot_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getcurrentslot_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzGetCurrentSlot(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetCurrentSlot()) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetCurrentSlot(data, size); + return 0; +} diff --git a/test/fuzztest/getcurrentslot_fuzzer/getcurrentslot_fuzzer.h b/test/fuzztest/getcurrentslot_fuzzer/getcurrentslot_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..79aa4d10fa7c3e76566286283381bc0794de8411 --- /dev/null +++ b/test/fuzztest/getcurrentslot_fuzzer/getcurrentslot_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_CURRENT_SLOTS_H +#define TEST_FUZZTEST_GET_CURRENT_SLOTS_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getcurrentslot_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getcurrentslot_fuzzer/project.xml b/test/fuzztest/getcurrentslot_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getcurrentslot_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getdevicenodepermissions_fuzzer/corpus/init b/test/fuzztest/getdevicenodepermissions_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/getdevicenodepermissions_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.cpp b/test/fuzztest/getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d85fd9f17e3011a4e8f51380d253748e95c58f72 --- /dev/null +++ b/test/fuzztest/getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.cpp @@ -0,0 +1,48 @@ +/* + * 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 "getdevicenodepermissions_fuzzer.h" +#include +#include "ueventd_read_cfg.h" + +namespace OHOS { + bool FuzzGetDeviceNodePermissions(const uint8_t* data, size_t size) + { + if ((data == nullptr) || (size < sizeof(char) + sizeof(uid_t) + sizeof(gid_t) + sizeof(mode_t))) { + return false; + } + bool result = false; + unsigned int offset = 0; + const char *devNode = reinterpret_cast(data + offset); + offset += sizeof(char); + uid_t *uid = reinterpret_cast(const_cast(data + offset)); + offset += sizeof(uid_t); + gid_t *gid = reinterpret_cast(const_cast(data + offset)); + offset += sizeof(gid_t); + mode_t *mode = reinterpret_cast(const_cast(data + offset)); + if (GetDeviceNodePermissions(devNode, uid, gid, mode) != 0) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetDeviceNodePermissions(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.h b/test/fuzztest/getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6fbf167f6dc15ca8ee074de87e19ad65c8de3691 --- /dev/null +++ b/test/fuzztest/getdevicenodepermissions_fuzzer/getdevicenodepermissions_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_DEVICE_NODE_PERMISSIONS_FUZZER_H +#define TEST_FUZZTEST_GET_DEVICE_NODE_PERMISSIONS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getdevicenodepermissions_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getdevicenodepermissions_fuzzer/project.xml b/test/fuzztest/getdevicenodepermissions_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/getdevicenodepermissions_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getdevicetypec_fuzzer/corpus/init b/test/fuzztest/getdevicetypec_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getdevicetypec_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getdevicetypec_fuzzer/getdevicetypec_fuzzer.cpp b/test/fuzztest/getdevicetypec_fuzzer/getdevicetypec_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0383126de471d1abc9b5f5870c8812b74c9b0c7 --- /dev/null +++ b/test/fuzztest/getdevicetypec_fuzzer/getdevicetypec_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getdevicetypec_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetDeviceCType(const uint8_t* data, size_t size) + { + bool result = false; + if (GetDeviceType() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetDeviceCType(data, size); + return 0; +} diff --git a/test/fuzztest/getdevicetypec_fuzzer/getdevicetypec_fuzzer.h b/test/fuzztest/getdevicetypec_fuzzer/getdevicetypec_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7038e88be13178b6cfbb65a652fedebd6789bcd9 --- /dev/null +++ b/test/fuzztest/getdevicetypec_fuzzer/getdevicetypec_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_DEVICE_TYPE_C_H +#define TEST_FUZZTEST_GET_DEVICE_TYPE_C_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getdevicetypec_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getdevicetypec_fuzzer/project.xml b/test/fuzztest/getdevicetypec_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getdevicetypec_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getdevicetypecpp_fuzzer/corpus/init b/test/fuzztest/getdevicetypecpp_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getdevicetypecpp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.cpp b/test/fuzztest/getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..611a870e9b53e04a7408f11a09bda6097db67355 --- /dev/null +++ b/test/fuzztest/getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.cpp @@ -0,0 +1,34 @@ +/* + * 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 "getdevicetypecpp_fuzzer.h" +#include +#include "parameters.h" + +namespace OHOS { + bool FuzzGetDeviceTypeCpp(const uint8_t* data, size_t size) + { + system::GetDeviceType(); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetDeviceTypeCpp(data, size); + return 0; +} diff --git a/test/fuzztest/getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.h b/test/fuzztest/getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..84500605cb5a60e1e3693717c04ea45d14bf577a --- /dev/null +++ b/test/fuzztest/getdevicetypecpp_fuzzer/getdevicetypecpp_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_DEVICE_TYPE_CPP_H +#define TEST_FUZZTEST_GET_DEVICE_TYPE_CPP_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getdevicetypecpp_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getdevicetypecpp_fuzzer/project.xml b/test/fuzztest/getdevicetypecpp_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getdevicetypecpp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/corpus/init b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.cpp b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b444a8ea8a9a8a44c5a793f73b9a07fe1876584 --- /dev/null +++ b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "getdeviceudevconfbydevnode_fuzzer.h" +#include +#include "ueventd_read_cfg.h" + +namespace OHOS { + bool FuzzGetDeviceUdevConfByDevNode(const uint8_t* data, size_t size) + { + bool result = false; + const char *devNode = reinterpret_cast(data); + if (GetDeviceUdevConfByDevNode(devNode) == NULL) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetDeviceUdevConfByDevNode(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.h b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6bdb47854dcdf2d494a9f884f6f8e4ee9decf804 --- /dev/null +++ b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/getdeviceudevconfbydevnode_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_DEVICE_UDEV_CINF_BY_DEV_NODE_FUZZER_H +#define TEST_FUZZTEST_GET_DEVICE_UDEV_CINF_BY_DEV_NODE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getdeviceudevconfbydevnode_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/project.xml b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/getdeviceudevconfbydevnode_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getdevudid_fuzzer/corpus/init b/test/fuzztest/getdevudid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getdevudid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getdevudid_fuzzer/getdevudid_fuzzer.cpp b/test/fuzztest/getdevudid_fuzzer/getdevudid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecfd3995b641c31bc790c7efab1a766951038f01 --- /dev/null +++ b/test/fuzztest/getdevudid_fuzzer/getdevudid_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "getdevudid_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetDevUdid(const uint8_t* data, size_t size) + { + bool result = false; + char udid[65] = {0}; + int len = sizeof(udid); + if (!GetDevUdid(udid, len)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetDevUdid(data, size); + return 0; +} diff --git a/test/fuzztest/getdevudid_fuzzer/getdevudid_fuzzer.h b/test/fuzztest/getdevudid_fuzzer/getdevudid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6589343eba78ad393ef881fa1d16366cc7140936 --- /dev/null +++ b/test/fuzztest/getdevudid_fuzzer/getdevudid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_DEV_UDID_FUZZER_H +#define TEST_FUZZTEST_GET_DEV_UDID_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getdevudid_fuzzer" +#endif diff --git a/test/fuzztest/getdevudid_fuzzer/project.xml b/test/fuzztest/getdevudid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getdevudid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getdisplayversion_fuzzer/corpus/init b/test/fuzztest/getdisplayversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getdisplayversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getdisplayversion_fuzzer/getdisplayversion_fuzzer.cpp b/test/fuzztest/getdisplayversion_fuzzer/getdisplayversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d76ea2df436b2d5018b3065f20836aa8a7a08bb1 --- /dev/null +++ b/test/fuzztest/getdisplayversion_fuzzer/getdisplayversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getdisplayversion_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetDisplayVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (GetDisplayVersion() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetDisplayVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getdisplayversion_fuzzer/getdisplayversion_fuzzer.h b/test/fuzztest/getdisplayversion_fuzzer/getdisplayversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..0fb9fac217839098e9b3df7d592c4616b6e684e8 --- /dev/null +++ b/test/fuzztest/getdisplayversion_fuzzer/getdisplayversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_DISPLAY_VERSION_H +#define TEST_FUZZTEST_GET_DISPLAY_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getdisplayversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getdisplayversion_fuzzer/project.xml b/test/fuzztest/getdisplayversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getdisplayversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getfeatureversion_fuzzer/corpus/init b/test/fuzztest/getfeatureversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getfeatureversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getfeatureversion_fuzzer/getfeatureversion_fuzzer.cpp b/test/fuzztest/getfeatureversion_fuzzer/getfeatureversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f8775b3f5cb36e91603a9f99757df1895c1dbab --- /dev/null +++ b/test/fuzztest/getfeatureversion_fuzzer/getfeatureversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getfeatureversion_fuzzer.h" +#include +#include "sysversion.h" + +namespace OHOS { + bool FuzzGetFeatureVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetFeatureVersion()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetFeatureVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getfeatureversion_fuzzer/getfeatureversion_fuzzer.h b/test/fuzztest/getfeatureversion_fuzzer/getfeatureversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..56d0c08354860a901135974da5dbbd84c11d0ee9 --- /dev/null +++ b/test/fuzztest/getfeatureversion_fuzzer/getfeatureversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_FEATURE_VERSION_H +#define TEST_FUZZTEST_GET_FEATURE_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getfeatureversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getfeatureversion_fuzzer/project.xml b/test/fuzztest/getfeatureversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getfeatureversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getfirstapiversion_fuzzer/corpus/init b/test/fuzztest/getfirstapiversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getfirstapiversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.cpp b/test/fuzztest/getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f022c2aab1614fd6658dce63b3a11bdc61208e9f --- /dev/null +++ b/test/fuzztest/getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getfirstapiversion_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetFirstApiVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetFirstApiVersion()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetFirstApiVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.h b/test/fuzztest/getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..271ac6a7f83ca2ffb7335ad9c6b5752a4f3aab2b --- /dev/null +++ b/test/fuzztest/getfirstapiversion_fuzzer/getfirstapiversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_FIRST_API_VERSION_H +#define TEST_FUZZTEST_GET_FIRST_API_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getfirstapiversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getfirstapiversion_fuzzer/project.xml b/test/fuzztest/getfirstapiversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getfirstapiversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/gethardwaremodel_fuzzer/corpus/init b/test/fuzztest/gethardwaremodel_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/gethardwaremodel_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.cpp b/test/fuzztest/gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7851fc8ad949cfc8a2ed130c9de610edc5661b1 --- /dev/null +++ b/test/fuzztest/gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "gethardwaremodel_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetHardwareModel(const uint8_t* data, size_t size) + { + bool result = false; + if (GetHardwareModel() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetHardwareModel(data, size); + return 0; +} diff --git a/test/fuzztest/gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.h b/test/fuzztest/gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..81bd3e675555f2914c0d9040e9954f81f6ceff33 --- /dev/null +++ b/test/fuzztest/gethardwaremodel_fuzzer/gethardwaremodel_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_HARDWARE_MODEL_H +#define TEST_FUZZTEST_GET_HARDWARE_MODEL_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "gethardwaremodel_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/gethardwaremodel_fuzzer/project.xml b/test/fuzztest/gethardwaremodel_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/gethardwaremodel_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/gethardwareprofile_fuzzer/corpus/init b/test/fuzztest/gethardwareprofile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/gethardwareprofile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.cpp b/test/fuzztest/gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a299cde89e4601bfd305c82f51d2d3ad28e70bd6 --- /dev/null +++ b/test/fuzztest/gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "gethardwareprofile_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetHardwareProfile(const uint8_t* data, size_t size) + { + bool result = false; + if (GetHardwareProfile() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetHardwareProfile(data, size); + return 0; +} diff --git a/test/fuzztest/gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.h b/test/fuzztest/gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..33f18b91faace3bebfdd1f1447dbc58e525640a7 --- /dev/null +++ b/test/fuzztest/gethardwareprofile_fuzzer/gethardwareprofile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_HARDWARE_PROFILE_H +#define TEST_FUZZTEST_GET_HARDWARE_PROFILE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "gethardwareprofile_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/gethardwareprofile_fuzzer/project.xml b/test/fuzztest/gethardwareprofile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/gethardwareprofile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getincrementalversion_fuzzer/corpus/init b/test/fuzztest/getincrementalversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getincrementalversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getincrementalversion_fuzzer/getincrementalversion_fuzzer.cpp b/test/fuzztest/getincrementalversion_fuzzer/getincrementalversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2469c53959a10c5d381b85017e6bc5c7ec9a41c3 --- /dev/null +++ b/test/fuzztest/getincrementalversion_fuzzer/getincrementalversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getincrementalversion_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetIncrementalVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (GetIncrementalVersion() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetIncrementalVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getincrementalversion_fuzzer/getincrementalversion_fuzzer.h b/test/fuzztest/getincrementalversion_fuzzer/getincrementalversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..40fb3fdd330f6a5d8c877095758fea888641e9ef --- /dev/null +++ b/test/fuzztest/getincrementalversion_fuzzer/getincrementalversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_INCREMENTAL_VERSION_H +#define TEST_FUZZTEST_GET_INCREMENTAL_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getincrementalversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getincrementalversion_fuzzer/project.xml b/test/fuzztest/getincrementalversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getincrementalversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getintparameterc_fuzzer/corpus/init b/test/fuzztest/getintparameterc_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getintparameterc_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getintparameterc_fuzzer/getintparameterc_fuzzer.cpp b/test/fuzztest/getintparameterc_fuzzer/getintparameterc_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea21fce7ccc8878f0af92284d2b9ea5b78e9f1cc --- /dev/null +++ b/test/fuzztest/getintparameterc_fuzzer/getintparameterc_fuzzer.cpp @@ -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. + */ + +#include "getintparameterc_fuzzer.h" +#include +#include "parameter.h" +#include "init_param.h" + +namespace OHOS { + bool FuzzGetIntParameterC(const uint8_t* data, size_t size) + { + std::string key(reinterpret_cast(data), size); + GetIntParameter(key.c_str(), 1); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetIntParameterC(data, size); + return 0; +} diff --git a/test/fuzztest/getintparameterc_fuzzer/getintparameterc_fuzzer.h b/test/fuzztest/getintparameterc_fuzzer/getintparameterc_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c344291b5539f9a27e0c14b02fc9e12a51aa1c60 --- /dev/null +++ b/test/fuzztest/getintparameterc_fuzzer/getintparameterc_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_INT_PARAMETER_C_FUZZER_H +#define TEST_FUZZTEST_GET_INT_PARAMETER_C_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getintparameterc_fuzzer" +#endif diff --git a/test/fuzztest/getintparameterc_fuzzer/project.xml b/test/fuzztest/getintparameterc_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getintparameterc_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getintparametercpp_fuzzer/corpus/init b/test/fuzztest/getintparametercpp_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getintparametercpp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getintparametercpp_fuzzer/getintparametercpp_fuzzer.cpp b/test/fuzztest/getintparametercpp_fuzzer/getintparametercpp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7970d06c06ec5fe2d502850e876349f66d49780 --- /dev/null +++ b/test/fuzztest/getintparametercpp_fuzzer/getintparametercpp_fuzzer.cpp @@ -0,0 +1,35 @@ +/* + * 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 "getintparametercpp_fuzzer.h" +#include +#include "param_wrapper.h" + +namespace OHOS { + bool FuzzGetIntParameterCpp(const uint8_t* data, size_t size) + { + std::string key(reinterpret_cast(data), size); + system::GetIntParameter(key, 1); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetIntParameterCpp(data, size); + return 0; +} diff --git a/test/fuzztest/getintparametercpp_fuzzer/getintparametercpp_fuzzer.h b/test/fuzztest/getintparametercpp_fuzzer/getintparametercpp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f09f0fca5a93b6922659b77072505009b9e2d2d7 --- /dev/null +++ b/test/fuzztest/getintparametercpp_fuzzer/getintparametercpp_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_INT_PARAMETER_CPP_FUZZER_H +#define TEST_FUZZTEST_GET_INT_PARAMETER_CPP_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getintparametercpp_fuzzer" +#endif diff --git a/test/fuzztest/getintparametercpp_fuzzer/project.xml b/test/fuzztest/getintparametercpp_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getintparametercpp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getmajorversion_fuzzer/corpus/init b/test/fuzztest/getmajorversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getmajorversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getmajorversion_fuzzer/getmajorversion_fuzzer.cpp b/test/fuzztest/getmajorversion_fuzzer/getmajorversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e696641e3aff81b0c80a1552d407824dc39ed59 --- /dev/null +++ b/test/fuzztest/getmajorversion_fuzzer/getmajorversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getmajorversion_fuzzer.h" +#include +#include "sysversion.h" + +namespace OHOS { + bool FuzzGetMajorVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetMajorVersion()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetMajorVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getmajorversion_fuzzer/getmajorversion_fuzzer.h b/test/fuzztest/getmajorversion_fuzzer/getmajorversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1f4cc870affc04dd6468bc2c971746194e9d82c0 --- /dev/null +++ b/test/fuzztest/getmajorversion_fuzzer/getmajorversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_MAJOR_VERSION_H +#define TEST_FUZZTEST_GET_MAJOR_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getmajorversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getmajorversion_fuzzer/project.xml b/test/fuzztest/getmajorversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getmajorversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getmanufacture_fuzzer/corpus/init b/test/fuzztest/getmanufacture_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getmanufacture_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getmanufacture_fuzzer/getmanufacture_fuzzer.cpp b/test/fuzztest/getmanufacture_fuzzer/getmanufacture_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb3968e1c9f66138ee9be99efea35b08fd9b2b31 --- /dev/null +++ b/test/fuzztest/getmanufacture_fuzzer/getmanufacture_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getmanufacture_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetManufacture(const uint8_t* data, size_t size) + { + bool result = false; + if (GetManufacture() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetManufacture(data, size); + return 0; +} diff --git a/test/fuzztest/getmanufacture_fuzzer/getmanufacture_fuzzer.h b/test/fuzztest/getmanufacture_fuzzer/getmanufacture_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d50f0daaff8ea23656b099ebd609490a7fdc6387 --- /dev/null +++ b/test/fuzztest/getmanufacture_fuzzer/getmanufacture_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_MANUFACTURE_H +#define TEST_FUZZTEST_GET_MANUFACTURE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getmanufacture_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getmanufacture_fuzzer/project.xml b/test/fuzztest/getmanufacture_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getmanufacture_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getmarketname_fuzzer/corpus/init b/test/fuzztest/getmarketname_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getmarketname_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getmarketname_fuzzer/getmarketname_fuzzer.cpp b/test/fuzztest/getmarketname_fuzzer/getmarketname_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87552415116d3fe77a564f547f229c49eb9ae51b --- /dev/null +++ b/test/fuzztest/getmarketname_fuzzer/getmarketname_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getmarketname_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetMarketName(const uint8_t* data, size_t size) + { + bool result = false; + if (GetMarketName() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetMarketName(data, size); + return 0; +} diff --git a/test/fuzztest/getmarketname_fuzzer/getmarketname_fuzzer.h b/test/fuzztest/getmarketname_fuzzer/getmarketname_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4dbdd632ae6bd93d49b1d3e184e05a40019b84de --- /dev/null +++ b/test/fuzztest/getmarketname_fuzzer/getmarketname_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_MARKET_NAME_H +#define TEST_FUZZTEST_GET_MARKET_NAME_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getmarketname_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getmarketname_fuzzer/project.xml b/test/fuzztest/getmarketname_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getmarketname_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getmountstatusformountpoint_fuzzer/corpus/init b/test/fuzztest/getmountstatusformountpoint_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getmountstatusformountpoint_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.cpp b/test/fuzztest/getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d995ed4e5500fc841e9abbef3057f5ab447391c --- /dev/null +++ b/test/fuzztest/getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "getmountstatusformountpoint_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzIsSupportedFilesystem(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (GetMountStatusForMountPoint(str.c_str()) != -1) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzIsSupportedFilesystem(data, size); + return 0; +} diff --git a/test/fuzztest/getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.h b/test/fuzztest/getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c3ee017437dc82de7d8b34a1498fe6f7abe20315 --- /dev/null +++ b/test/fuzztest/getmountstatusformountpoint_fuzzer/getmountstatusformountpoint_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_MOUNT_STATUS_FOR_MOUNT_POINT_FUZZER_H +#define TEST_FUZZTEST_GET_MOUNT_STATUS_FOR_MOUNT_POINT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getmountstatusformountpoint_fuzzer" +#endif diff --git a/test/fuzztest/getmountstatusformountpoint_fuzzer/project.xml b/test/fuzztest/getmountstatusformountpoint_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getmountstatusformountpoint_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getosfullname_fuzzer/corpus/init b/test/fuzztest/getosfullname_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getosfullname_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getosfullname_fuzzer/getosfullname_fuzzer.cpp b/test/fuzztest/getosfullname_fuzzer/getosfullname_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e019a438c01697854a40f54ac6a813a287bf547 --- /dev/null +++ b/test/fuzztest/getosfullname_fuzzer/getosfullname_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getosfullname_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetOSFullName(const uint8_t* data, size_t size) + { + bool result = false; + if (GetOSFullName() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetOSFullName(data, size); + return 0; +} diff --git a/test/fuzztest/getosfullname_fuzzer/getosfullname_fuzzer.h b/test/fuzztest/getosfullname_fuzzer/getosfullname_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..61f249ba32747c5942c10f0129e31bf3603bbe64 --- /dev/null +++ b/test/fuzztest/getosfullname_fuzzer/getosfullname_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_OS_FULL_NAME_H +#define TEST_FUZZTEST_GET_OS_FULL_NAME_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getosfullname_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getosfullname_fuzzer/project.xml b/test/fuzztest/getosfullname_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getosfullname_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getosreleasetype_fuzzer/corpus/init b/test/fuzztest/getosreleasetype_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getosreleasetype_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getosreleasetype_fuzzer/getosreleasetype_fuzzer.cpp b/test/fuzztest/getosreleasetype_fuzzer/getosreleasetype_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d74b05ceb418a456622fe7bf12735933eea15428 --- /dev/null +++ b/test/fuzztest/getosreleasetype_fuzzer/getosreleasetype_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getosreleasetype_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetOsReleaseType(const uint8_t* data, size_t size) + { + bool result = false; + if (GetOsReleaseType() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetOsReleaseType(data, size); + return 0; +} diff --git a/test/fuzztest/getosreleasetype_fuzzer/getosreleasetype_fuzzer.h b/test/fuzztest/getosreleasetype_fuzzer/getosreleasetype_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..cd881ccae9a9e1a4f1ec4928d5ca6c6835d5fc57 --- /dev/null +++ b/test/fuzztest/getosreleasetype_fuzzer/getosreleasetype_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_OS_RELEASE_TYPE_H +#define TEST_FUZZTEST_GET_OS_RELEASE_TYPE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getosreleasetype_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getosreleasetype_fuzzer/project.xml b/test/fuzztest/getosreleasetype_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getosreleasetype_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getparameterc_fuzzer/corpus/init b/test/fuzztest/getparameterc_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getparameterc_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getparameterc_fuzzer/getparameterc_fuzzer.cpp b/test/fuzztest/getparameterc_fuzzer/getparameterc_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68decc1cc65d1597b113c2893a1d96cfb92f86cc --- /dev/null +++ b/test/fuzztest/getparameterc_fuzzer/getparameterc_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "getparameterc_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetParameterC(const uint8_t* data, size_t size) + { + bool result = false; + char value[PARAM_CONST_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_CONST_VALUE_LEN_MAX; + std::string str(reinterpret_cast(data), size); + if (!GetParameter(str.c_str(), nullptr, value, len)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParameterC(data, size); + return 0; +} diff --git a/test/fuzztest/getparameterc_fuzzer/getparameterc_fuzzer.h b/test/fuzztest/getparameterc_fuzzer/getparameterc_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..8f56065e49fcc7593ad53ba2e01a5a45f9f73924 --- /dev/null +++ b/test/fuzztest/getparameterc_fuzzer/getparameterc_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_PARAMETER_C_FUZZER_H +#define TEST_FUZZTEST_GET_PARAMETER_C_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getparameterc_fuzzer" +#endif diff --git a/test/fuzztest/getparameterc_fuzzer/project.xml b/test/fuzztest/getparameterc_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getparameterc_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getparametercommitid_fuzzer/corpus/init b/test/fuzztest/getparametercommitid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getparametercommitid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getparametercommitid_fuzzer/getparametercommitid_fuzzer.cpp b/test/fuzztest/getparametercommitid_fuzzer/getparametercommitid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad60beaeea6b32f0fdb8a98cf12bf11a094e8698 --- /dev/null +++ b/test/fuzztest/getparametercommitid_fuzzer/getparametercommitid_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * 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 "getparametercommitid_fuzzer.h" +#include +#include "parameter.h" +#include "init_param.h" +#include "fuzz_utils.h" + +namespace OHOS { + bool FuzzGetParameterCommitId(const uint8_t* data, size_t size) + { + bool result = false; + char *rest = nullptr; + std::string str(reinterpret_cast(data), size); + ParamHandle handle = (ParamHandle)strtoul(str.c_str(), &rest, BASE); + if ((handle < BASE) && (!GetParameterCommitId(handle))) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParameterCommitId(data, size); + return 0; +} diff --git a/test/fuzztest/getparametercommitid_fuzzer/getparametercommitid_fuzzer.h b/test/fuzztest/getparametercommitid_fuzzer/getparametercommitid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..0a8af4d6b43a9de6168d4c15dc0ffcbb1177e06e --- /dev/null +++ b/test/fuzztest/getparametercommitid_fuzzer/getparametercommitid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GETPARAMETERCOMMITID_FUZZER_H +#define TEST_FUZZTEST_GETPARAMETERCOMMITID_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getparametercommitid_fuzzer" +#endif diff --git a/test/fuzztest/getparametercommitid_fuzzer/project.xml b/test/fuzztest/getparametercommitid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getparametercommitid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getparametercpp_fuzzer/corpus/init b/test/fuzztest/getparametercpp_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getparametercpp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getparametercpp_fuzzer/getparametercpp_fuzzer.cpp b/test/fuzztest/getparametercpp_fuzzer/getparametercpp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..967fe8b6511b96077ab590e05202fd0aba64534e --- /dev/null +++ b/test/fuzztest/getparametercpp_fuzzer/getparametercpp_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "getparametercpp_fuzzer.h" +#include +#include "parameters.h" + +namespace OHOS { + bool FuzzGetParameter(const uint8_t* data, size_t size) + { + bool result = false; + const std::string def = ""; + std::string key(reinterpret_cast(data), size); + if (system::GetParameter(key, def) != def) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParameter(data, size); + return 0; +} diff --git a/test/fuzztest/getparametercpp_fuzzer/getparametercpp_fuzzer.h b/test/fuzztest/getparametercpp_fuzzer/getparametercpp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b60e47619b0eb47e51cbb6ddba5494f13b41b396 --- /dev/null +++ b/test/fuzztest/getparametercpp_fuzzer/getparametercpp_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_PARAMETER_CPP_FUZZER_H +#define TEST_FUZZTEST_GET_PARAMETER_CPP_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getparametercpp_fuzzer" +#endif diff --git a/test/fuzztest/getparametercpp_fuzzer/project.xml b/test/fuzztest/getparametercpp_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getparametercpp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getparametername_fuzzer/corpus/init b/test/fuzztest/getparametername_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getparametername_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getparametername_fuzzer/getparametername_fuzzer.cpp b/test/fuzztest/getparametername_fuzzer/getparametername_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ef08425a2dd1a7117c689f689d2225163a2e999 --- /dev/null +++ b/test/fuzztest/getparametername_fuzzer/getparametername_fuzzer.cpp @@ -0,0 +1,43 @@ +/* + * 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 "getparametername_fuzzer.h" +#include +#include "parameter.h" +#include "init_param.h" +#include "fuzz_utils.h" + +namespace OHOS { + bool FuzzGetParameterName(const uint8_t* data, size_t size) + { + bool result = false; + char buffer[PARAM_NAME_LEN_MAX] = {0}; + char *rest = nullptr; + std::string str(reinterpret_cast(data), size); + ParamHandle handle = (ParamHandle)strtoul(str.c_str(), &rest, BASE); + if (!GetParameterName(handle, buffer, PARAM_NAME_LEN_MAX)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParameterName(data, size); + return 0; +} diff --git a/test/fuzztest/getparametername_fuzzer/getparametername_fuzzer.h b/test/fuzztest/getparametername_fuzzer/getparametername_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1af173f0bd7e63ad7922f18ea97bf557476c2328 --- /dev/null +++ b/test/fuzztest/getparametername_fuzzer/getparametername_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GETPARAMETERNAME_FUZZER_H +#define TEST_FUZZTEST_GETPARAMETERNAME_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getparametername_fuzzer" +#endif diff --git a/test/fuzztest/getparametername_fuzzer/project.xml b/test/fuzztest/getparametername_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getparametername_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getparametervalue_fuzzer/corpus/init b/test/fuzztest/getparametervalue_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getparametervalue_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getparametervalue_fuzzer/getparametervalue_fuzzer.cpp b/test/fuzztest/getparametervalue_fuzzer/getparametervalue_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20fcdf0859a6bc356602c93758a7e03247969d6a --- /dev/null +++ b/test/fuzztest/getparametervalue_fuzzer/getparametervalue_fuzzer.cpp @@ -0,0 +1,44 @@ +/* + * 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 "getparametervalue_fuzzer.h" +#include +#include "parameter.h" +#include "init_param.h" +#include "fuzz_utils.h" + +namespace OHOS { + bool FuzzGetParameterValue(const uint8_t* data, size_t size) + { + bool result = false; + char buffer[PARAM_CONST_VALUE_LEN_MAX] = {0}; + uint32_t len = PARAM_CONST_VALUE_LEN_MAX; + char *rest = nullptr; + std::string str(reinterpret_cast(data), size); + ParamHandle handle = (ParamHandle)strtoul(str.c_str(), &rest, BASE); + if ((handle < BASE) && (!GetParameterValue(handle, buffer, len))) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParameterValue(data, size); + return 0; +} diff --git a/test/fuzztest/getparametervalue_fuzzer/getparametervalue_fuzzer.h b/test/fuzztest/getparametervalue_fuzzer/getparametervalue_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..40a9f684ea0298e82653a9b9e52372ae72ddab7c --- /dev/null +++ b/test/fuzztest/getparametervalue_fuzzer/getparametervalue_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GETPARAMETERVALUE_FUZZER_H +#define TEST_FUZZTEST_GETPARAMETERVALUE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getparametervalue_fuzzer" +#endif diff --git a/test/fuzztest/getparametervalue_fuzzer/project.xml b/test/fuzztest/getparametervalue_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getparametervalue_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getparamsecurityauditdata_fuzzer/corpus/init b/test/fuzztest/getparamsecurityauditdata_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getparamsecurityauditdata_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.cpp b/test/fuzztest/getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1590f4e3944f5cc647af34e492d811755ec899a --- /dev/null +++ b/test/fuzztest/getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 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 "getparamsecurityauditdata_fuzzer.h" +#include +#include "param_manager.h" + +#define NAME_LEN_MAX 96 + +namespace OHOS { + bool FuzzGetParamSecurityAuditData(const uint8_t* data, size_t size) + { + if (size >= NAME_LEN_MAX) { + return false; + } + bool result = false; + + std::string str(reinterpret_cast(data), size); + int type = 0; + ParamAuditData auditData = {}; + + int ret = GetParamSecurityAuditData(str.c_str(), type, &auditData); + if (ret == 0) { + result = true; + } + + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParamSecurityAuditData(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.h b/test/fuzztest/getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4319d6073781f7f5f44b37d630dcbccb60c12dbf --- /dev/null +++ b/test/fuzztest/getparamsecurityauditdata_fuzzer/getparamsecurityauditdata_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_GET_PARAM_SECURITY_AUDIT_DATA_FUZZER_H +#define TEST_FUZZTEST_GET_PARAM_SECURITY_AUDIT_DATA_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getparamsecurityauditdata_fuzzer" +#endif diff --git a/test/fuzztest/getparamsecurityauditdata_fuzzer/project.xml b/test/fuzztest/getparamsecurityauditdata_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/getparamsecurityauditdata_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getproductmodel_fuzzer/corpus/init b/test/fuzztest/getproductmodel_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getproductmodel_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getproductmodel_fuzzer/getproductmodel_fuzzer.cpp b/test/fuzztest/getproductmodel_fuzzer/getproductmodel_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef72f4b90180300d0e66effafe58a52fe6609177 --- /dev/null +++ b/test/fuzztest/getproductmodel_fuzzer/getproductmodel_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getproductmodel_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetProductModel(const uint8_t* data, size_t size) + { + bool result = false; + if (GetProductModel() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetProductModel(data, size); + return 0; +} diff --git a/test/fuzztest/getproductmodel_fuzzer/getproductmodel_fuzzer.h b/test/fuzztest/getproductmodel_fuzzer/getproductmodel_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7d5d3a2f20cfa6fe74a63b109359a6cb531fdc56 --- /dev/null +++ b/test/fuzztest/getproductmodel_fuzzer/getproductmodel_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_PRODUCT_MODULE_H +#define TEST_FUZZTEST_GET_PRODUCT_MODULE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getproductmodel_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getproductmodel_fuzzer/project.xml b/test/fuzztest/getproductmodel_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getproductmodel_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getproductseries_fuzzer/corpus/init b/test/fuzztest/getproductseries_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getproductseries_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getproductseries_fuzzer/getproductseries_fuzzer.cpp b/test/fuzztest/getproductseries_fuzzer/getproductseries_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9eb9d5cbabc19f2cddbbda325362d5e8decf3f40 --- /dev/null +++ b/test/fuzztest/getproductseries_fuzzer/getproductseries_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getproductseries_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetProductSeries(const uint8_t* data, size_t size) + { + bool result = false; + if (GetProductSeries() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetProductSeries(data, size); + return 0; +} diff --git a/test/fuzztest/getproductseries_fuzzer/getproductseries_fuzzer.h b/test/fuzztest/getproductseries_fuzzer/getproductseries_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3e2740b3319f6f2973351574693d636ba2549b39 --- /dev/null +++ b/test/fuzztest/getproductseries_fuzzer/getproductseries_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_PRODUCT_SERIES_H +#define TEST_FUZZTEST_GET_PRODUCT_SERIES_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getproductseries_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getproductseries_fuzzer/project.xml b/test/fuzztest/getproductseries_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getproductseries_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getsdkapiversion_fuzzer/corpus/init b/test/fuzztest/getsdkapiversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getsdkapiversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.cpp b/test/fuzztest/getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa8f80c0b85eda2c5c0fe7b3ce2b00dee0c0ceb4 --- /dev/null +++ b/test/fuzztest/getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getsdkapiversion_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetSdkApiVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetSdkApiVersion()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetSdkApiVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.h b/test/fuzztest/getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6fac19997e84fb36d213fef17e16e769a16e431a --- /dev/null +++ b/test/fuzztest/getsdkapiversion_fuzzer/getsdkapiversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_SDK_API_VERSION_H +#define TEST_FUZZTEST_GET_SDK_API_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getsdkapiversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getsdkapiversion_fuzzer/project.xml b/test/fuzztest/getsdkapiversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getsdkapiversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getsecuritypatchtag_fuzzer/corpus/init b/test/fuzztest/getsecuritypatchtag_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getsecuritypatchtag_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.cpp b/test/fuzztest/getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98eef6f3b04327db25a91005ed6f62431a24ac29 --- /dev/null +++ b/test/fuzztest/getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getsecuritypatchtag_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetSecurityPatchTag(const uint8_t* data, size_t size) + { + bool result = false; + if (GetSecurityPatchTag() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetSecurityPatchTag(data, size); + return 0; +} diff --git a/test/fuzztest/getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.h b/test/fuzztest/getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c886d53c61bff386997dfb34efb3ad71693a52aa --- /dev/null +++ b/test/fuzztest/getsecuritypatchtag_fuzzer/getsecuritypatchtag_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_SECURITY_PATCH_TAG_H +#define TEST_FUZZTEST_GET_SECURITY_PATCH_TAG_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getsecuritypatchtag_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getsecuritypatchtag_fuzzer/project.xml b/test/fuzztest/getsecuritypatchtag_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getsecuritypatchtag_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getseniorversion_fuzzer/corpus/init b/test/fuzztest/getseniorversion_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getseniorversion_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getseniorversion_fuzzer/getseniorversion_fuzzer.cpp b/test/fuzztest/getseniorversion_fuzzer/getseniorversion_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5007c27a633e361acb7c4cc40ff7f765d2d3fb73 --- /dev/null +++ b/test/fuzztest/getseniorversion_fuzzer/getseniorversion_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getseniorversion_fuzzer.h" +#include +#include "sysversion.h" + +namespace OHOS { + bool FuzzGetSeniorVersion(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetSeniorVersion()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetSeniorVersion(data, size); + return 0; +} diff --git a/test/fuzztest/getseniorversion_fuzzer/getseniorversion_fuzzer.h b/test/fuzztest/getseniorversion_fuzzer/getseniorversion_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..2e19e6df4e2f5bc514cb5949ac8a2312f90e533f --- /dev/null +++ b/test/fuzztest/getseniorversion_fuzzer/getseniorversion_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_SENIOR_VERSION_H +#define TEST_FUZZTEST_GET_SENIOR_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getseniorversion_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getseniorversion_fuzzer/project.xml b/test/fuzztest/getseniorversion_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getseniorversion_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getserial_fuzzer/corpus/init b/test/fuzztest/getserial_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getserial_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getserial_fuzzer/getserial_fuzzer.cpp b/test/fuzztest/getserial_fuzzer/getserial_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0a7b2cf9eb949878adab77585b4b6bdbfa24240 --- /dev/null +++ b/test/fuzztest/getserial_fuzzer/getserial_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getserial_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetSerial(const uint8_t* data, size_t size) + { + bool result = false; + if (GetSerial() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetSerial(data, size); + return 0; +} diff --git a/test/fuzztest/getserial_fuzzer/getserial_fuzzer.h b/test/fuzztest/getserial_fuzzer/getserial_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..5742d64bd2a7f8051e647579e657ca8a70db5dd7 --- /dev/null +++ b/test/fuzztest/getserial_fuzzer/getserial_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_SERIAL_H +#define TEST_FUZZTEST_GET_SERIAL_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getserial_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getserial_fuzzer/project.xml b/test/fuzztest/getserial_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getserial_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getservicectrlinfo_fuzzer/corpus/init b/test/fuzztest/getservicectrlinfo_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getservicectrlinfo_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.cpp b/test/fuzztest/getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..531b7c2550b2c2904168bea2d42d390ce9f06c84 --- /dev/null +++ b/test/fuzztest/getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 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 "getservicectrlinfo_fuzzer.h" +#include +#include "init_hook.h" +#include "param_manager.h" + +#define NAME_LEN_MAX 96 + +namespace OHOS { + bool FuzzGetServiceCtrlInfo(const uint8_t* data, size_t size) + { + if (size + sizeof("test") >= NAME_LEN_MAX) { + return false; + } + + bool result = false; + ServiceCtrlInfo *serviceInfo = nullptr; + GetServiceCtrlInfo("ohos.ctl.stop", "test", &serviceInfo); + if (serviceInfo != nullptr) { + free(serviceInfo); + result = true; + }; + + ServiceCtrlInfo *powerctrl = nullptr; + GetServiceCtrlInfo("ohos.startup.powerctrl", "reboot,updater", &powerctrl); + if (powerctrl != nullptr) { + free(powerctrl); + result = true; + }; + + ServiceCtrlInfo *ctrlInfo = nullptr; + std::string str(reinterpret_cast(data), size); + GetServiceCtrlInfo(str.c_str(), "test", &ctrlInfo); + if (ctrlInfo != nullptr) { + free(ctrlInfo); + result = true; + }; + + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetServiceCtrlInfo(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.h b/test/fuzztest/getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..9ca58ee7f171d3d13986c49a83d1266dee6a3d13 --- /dev/null +++ b/test/fuzztest/getservicectrlinfo_fuzzer/getservicectrlinfo_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_GET_SEVICE_CTRL_INFO_FUZZER_H +#define TEST_FUZZTEST_GET_SEVICE_CTRL_INFO_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getservicectrlinfo_fuzzer" +#endif diff --git a/test/fuzztest/getservicectrlinfo_fuzzer/project.xml b/test/fuzztest/getservicectrlinfo_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/getservicectrlinfo_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getsoftwaremodel_fuzzer/corpus/init b/test/fuzztest/getsoftwaremodel_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getsoftwaremodel_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.cpp b/test/fuzztest/getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e747e054f0ecdbf4b6926f8eb77b78a739d488a9 --- /dev/null +++ b/test/fuzztest/getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getsoftwaremodel_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetSoftwareModel(const uint8_t* data, size_t size) + { + bool result = false; + if (GetSoftwareModel() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetSoftwareModel(data, size); + return 0; +} diff --git a/test/fuzztest/getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.h b/test/fuzztest/getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..bdf2dcd5656e75ee78338637a68f78817d8336a0 --- /dev/null +++ b/test/fuzztest/getsoftwaremodel_fuzzer/getsoftwaremodel_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_SOFTWARE_MODULE_H +#define TEST_FUZZTEST_GET_SOFTWARE_MODULE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getsoftwaremodel_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getsoftwaremodel_fuzzer/project.xml b/test/fuzztest/getsoftwaremodel_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getsoftwaremodel_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getstringparameter_fuzzer/corpus/init b/test/fuzztest/getstringparameter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getstringparameter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getstringparameter_fuzzer/getstringparameter_fuzzer.cpp b/test/fuzztest/getstringparameter_fuzzer/getstringparameter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d885ac8c34672f3c3d3355085b5964011ce5406 --- /dev/null +++ b/test/fuzztest/getstringparameter_fuzzer/getstringparameter_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "getstringparameter_fuzzer.h" +#include +#include "param_wrapper.h" + +namespace OHOS { + bool FuzzGetStringParameter(const uint8_t* data, size_t size) + { + bool result = false; + std::string value = ""; + std::string key(reinterpret_cast(data), size); + if (!system::GetStringParameter(key, value, "")) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetStringParameter(data, size); + return 0; +} diff --git a/test/fuzztest/getstringparameter_fuzzer/getstringparameter_fuzzer.h b/test/fuzztest/getstringparameter_fuzzer/getstringparameter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..9fb7579488a1160adea97a11fb20f1a17135aed7 --- /dev/null +++ b/test/fuzztest/getstringparameter_fuzzer/getstringparameter_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SYSTEMGETPARAMETER_FUZZER_H +#define TEST_FUZZTEST_SYSTEMGETPARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getstringparameter_fuzzer" +#endif diff --git a/test/fuzztest/getstringparameter_fuzzer/project.xml b/test/fuzztest/getstringparameter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getstringparameter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getsystemcommitid_fuzzer/corpus/init b/test/fuzztest/getsystemcommitid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getsystemcommitid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.cpp b/test/fuzztest/getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..704ec840c1b22e98a40a37a2d16a9a589ab07f3b --- /dev/null +++ b/test/fuzztest/getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getsystemcommitid_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetSystemCommitId(const uint8_t* data, size_t size) + { + bool result = false; + if (!GetSystemCommitId()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetSystemCommitId(data, size); + return 0; +} diff --git a/test/fuzztest/getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.h b/test/fuzztest/getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..221d4a0903b6e9f45605d87466efe5380ba77760 --- /dev/null +++ b/test/fuzztest/getsystemcommitid_fuzzer/getsystemcommitid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_SYSTEM_COMMITID_H +#define TEST_FUZZTEST_GET_SYSTEM_COMMITID_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getsystemcommitid_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getsystemcommitid_fuzzer/project.xml b/test/fuzztest/getsystemcommitid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getsystemcommitid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getuintparameterc_fuzzer/corpus/init b/test/fuzztest/getuintparameterc_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getuintparameterc_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getuintparameterc_fuzzer/getuintparameterc_fuzzer.cpp b/test/fuzztest/getuintparameterc_fuzzer/getuintparameterc_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abfb9b0788dcae340bb926556da8483a4fa3a872 --- /dev/null +++ b/test/fuzztest/getuintparameterc_fuzzer/getuintparameterc_fuzzer.cpp @@ -0,0 +1,35 @@ +/* + * 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 "getuintparameterc_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetUintParameterC(const uint8_t* data, size_t size) + { + std::string key(reinterpret_cast(data), size); + GetUintParameter(key.c_str(), 1); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetUintParameterC(data, size); + return 0; +} diff --git a/test/fuzztest/getuintparameterc_fuzzer/getuintparameterc_fuzzer.h b/test/fuzztest/getuintparameterc_fuzzer/getuintparameterc_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..fca50e0f965ff4477a9b866839a3a5a4abcde305 --- /dev/null +++ b/test/fuzztest/getuintparameterc_fuzzer/getuintparameterc_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_UINT_PARAMETER_C_FUZZER_H +#define TEST_FUZZTEST_GET_UINT_PARAMETER_C_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getuintparameterc_fuzzer" +#endif diff --git a/test/fuzztest/getuintparameterc_fuzzer/project.xml b/test/fuzztest/getuintparameterc_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getuintparameterc_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/getversionid_fuzzer/corpus/init b/test/fuzztest/getversionid_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/getversionid_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/getversionid_fuzzer/getversionid_fuzzer.cpp b/test/fuzztest/getversionid_fuzzer/getversionid_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52eff04e1de054f06df0c41bb8d83313d20118dd --- /dev/null +++ b/test/fuzztest/getversionid_fuzzer/getversionid_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "getversionid_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzGetVersionId(const uint8_t* data, size_t size) + { + bool result = false; + if (GetVersionId() != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetVersionId(data, size); + return 0; +} diff --git a/test/fuzztest/getversionid_fuzzer/getversionid_fuzzer.h b/test/fuzztest/getversionid_fuzzer/getversionid_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..ae0af1322a0ac2f4e8c76b4d8699ef95f489afa4 --- /dev/null +++ b/test/fuzztest/getversionid_fuzzer/getversionid_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_VERSION_ID_H +#define TEST_FUZZTEST_GET_VERSION_ID_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "getversionid_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/getversionid_fuzzer/project.xml b/test/fuzztest/getversionid_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/getversionid_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/handleblockdeviceevent_fuzzer/corpus/init b/test/fuzztest/handleblockdeviceevent_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/handleblockdeviceevent_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.cpp b/test/fuzztest/handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65b1c0cfbc4ed204c4f68656037f6a8fd2dd29d4 --- /dev/null +++ b/test/fuzztest/handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "handleblockdeviceevent_fuzzer.h" +#include +#include "ueventd_device_handler.h" + +namespace OHOS { + bool FuzzHandleBlockDeviceEvent(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + struct Uevent uevent = { + .subsystem = str.c_str(), + }; + HandleBlockDeviceEvent(&uevent); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHandleBlockDeviceEvent(data, size); + return 0; +} diff --git a/test/fuzztest/handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.h b/test/fuzztest/handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f10724a4ebeccdc91f1f1662e35c143416715db1 --- /dev/null +++ b/test/fuzztest/handleblockdeviceevent_fuzzer/handleblockdeviceevent_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HANDLE_BLOCK_DEVICE_EVENT_FUZZER_H +#define TEST_FUZZTEST_HANDLE_BLOCK_DEVICE_EVENT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "handleblockdeviceevent_fuzzer" +#endif diff --git a/test/fuzztest/handleblockdeviceevent_fuzzer/project.xml b/test/fuzztest/handleblockdeviceevent_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/handleblockdeviceevent_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/handleotherdeviceevent_fuzzer/corpus/init b/test/fuzztest/handleotherdeviceevent_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/handleotherdeviceevent_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.cpp b/test/fuzztest/handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..311e197d24d3de378533b0d388cf1fa0575cc4c7 --- /dev/null +++ b/test/fuzztest/handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "handleotherdeviceevent_fuzzer.h" +#include +#include "ueventd_device_handler.h" + +namespace OHOS { + bool FuzzHandleOtherDeviceEvent(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + struct Uevent uevent = { + .subsystem = str.c_str(), + }; + HandleOtherDeviceEvent(&uevent); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHandleOtherDeviceEvent(data, size); + return 0; +} diff --git a/test/fuzztest/handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.h b/test/fuzztest/handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..06c3a6db40de8f4df0e8d61217d9d5cc3f05f527 --- /dev/null +++ b/test/fuzztest/handleotherdeviceevent_fuzzer/handleotherdeviceevent_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HANDLE_OTHER_DEVICE_EVENT_FUZZER_H +#define TEST_FUZZTEST_HANDLE_OTHER_DEVICE_EVENT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "handleotherdeviceevent_fuzzer" +#endif diff --git a/test/fuzztest/handleotherdeviceevent_fuzzer/project.xml b/test/fuzztest/handleotherdeviceevent_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/handleotherdeviceevent_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hassystemcapability_fuzzer/corpus/init b/test/fuzztest/hassystemcapability_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hassystemcapability_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hassystemcapability_fuzzer/hassystemcapability_fuzzer.cpp b/test/fuzztest/hassystemcapability_fuzzer/hassystemcapability_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c3392800fb405dfb481ed5db5ac93078ae99385 --- /dev/null +++ b/test/fuzztest/hassystemcapability_fuzzer/hassystemcapability_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "hassystemcapability_fuzzer.h" +#include +#include "systemcapability.h" + +namespace OHOS { + bool FuzzHasSystemCapability(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!HasSystemCapability(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHasSystemCapability(data, size); + return 0; +} diff --git a/test/fuzztest/hassystemcapability_fuzzer/hassystemcapability_fuzzer.h b/test/fuzztest/hassystemcapability_fuzzer/hassystemcapability_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f181099508eb045c905fc59df4c72058c88f015e --- /dev/null +++ b/test/fuzztest/hassystemcapability_fuzzer/hassystemcapability_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HAS_SYSTEM_CAPABILITY_FUZZER_H +#define TEST_FUZZTEST_HAS_SYSTEM_CAPABILITY_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hassystemcapability_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hassystemcapability_fuzzer/project.xml b/test/fuzztest/hassystemcapability_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hassystemcapability_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgradd_fuzzer/corpus/init b/test/fuzztest/hookmgradd_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgradd_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgradd_fuzzer/hookmgradd_fuzzer.cpp b/test/fuzztest/hookmgradd_fuzzer/hookmgradd_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f5a5fb9becb8328ea07e85caa8417261b05f310 --- /dev/null +++ b/test/fuzztest/hookmgradd_fuzzer/hookmgradd_fuzzer.cpp @@ -0,0 +1,51 @@ +/* + * 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 "hookmgradd_fuzzer.h" +#include +#include "hookmgr.h" + +static int TestHook(const HOOK_INFO *hookInfo, void *executionContext) +{ + printf("Test HookMgrAdd\n"); + return 0; +} + +namespace OHOS { + bool FuzzHookMgrAdd(const uint8_t* data, size_t size) + { + if ((data == nullptr) || (size <= sizeof(int))) { + return false; + } + bool result = false; + int offset = 0; + int stage = *data; + offset += sizeof(int); + int prio = *(data + offset); + + if (!HookMgrAdd(NULL, stage, prio, TestHook)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrAdd(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hookmgradd_fuzzer/hookmgradd_fuzzer.h b/test/fuzztest/hookmgradd_fuzzer/hookmgradd_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..83d7afe9b5431a8825cf2b844059fff8e4e1cf06 --- /dev/null +++ b/test/fuzztest/hookmgradd_fuzzer/hookmgradd_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_ADD_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_ADD_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgradd_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgradd_fuzzer/project.xml b/test/fuzztest/hookmgradd_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgradd_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgraddex_fuzzer/corpus/init b/test/fuzztest/hookmgraddex_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgraddex_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgraddex_fuzzer/hookmgraddex_fuzzer.cpp b/test/fuzztest/hookmgraddex_fuzzer/hookmgraddex_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ec3e0ef8d4d7f457737b511bec2f0a9c0165da2 --- /dev/null +++ b/test/fuzztest/hookmgraddex_fuzzer/hookmgraddex_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "hookmgraddex_fuzzer.h" +#include +#include "hookmgr.h" + +namespace OHOS { + bool FuzzHookMgrAddEx(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + + if (!HookMgrAddEx(hookMgr, nullptr)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrAddEx(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hookmgraddex_fuzzer/hookmgraddex_fuzzer.h b/test/fuzztest/hookmgraddex_fuzzer/hookmgraddex_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..49f0f773199b9d87db7f741fe3d0c5527f93e9aa --- /dev/null +++ b/test/fuzztest/hookmgraddex_fuzzer/hookmgraddex_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_ADD_EX_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_ADD_EX_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgraddex_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgraddex_fuzzer/project.xml b/test/fuzztest/hookmgraddex_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgraddex_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrcreate_fuzzer/corpus/init b/test/fuzztest/hookmgrcreate_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrcreate_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.cpp b/test/fuzztest/hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7358b77802b3fbcbcf879daf1366982f9d9dcfb4 --- /dev/null +++ b/test/fuzztest/hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "hookmgrcreate_fuzzer.h" +#include +#include "hookmgr.h" + +namespace OHOS { + bool FuzzHookMgrCreate(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (HookMgrCreate(str.c_str()) != nullptr) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrCreate(data, size); + return 0; +} diff --git a/test/fuzztest/hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.h b/test/fuzztest/hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..bb154180910c81fd86ceb827a44cd5f6aeeab199 --- /dev/null +++ b/test/fuzztest/hookmgrcreate_fuzzer/hookmgrcreate_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_CREATE_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_CREATE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrcreate_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrcreate_fuzzer/project.xml b/test/fuzztest/hookmgrcreate_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrcreate_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrdel_fuzzer/corpus/init b/test/fuzztest/hookmgrdel_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrdel_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrdel_fuzzer/hookmgrdel_fuzzer.cpp b/test/fuzztest/hookmgrdel_fuzzer/hookmgrdel_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5228f25075af46f1ae589a8d421227aacf200ad2 --- /dev/null +++ b/test/fuzztest/hookmgrdel_fuzzer/hookmgrdel_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * 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 "hookmgrdel_fuzzer.h" +#include +#include "hookmgr.h" + +static int TestHook(const HOOK_INFO *hookInfo, void *executionContext) +{ + printf("Test HookMgrAdd\n"); + return 0; +} + +namespace OHOS { + bool FuzzHookMgrDel(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + HookMgrDel(hookMgr, 0, TestHook); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrDel(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hookmgrdel_fuzzer/hookmgrdel_fuzzer.h b/test/fuzztest/hookmgrdel_fuzzer/hookmgrdel_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d2776f42f56b6957b91716a7f437b958d2d65f83 --- /dev/null +++ b/test/fuzztest/hookmgrdel_fuzzer/hookmgrdel_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_DEL_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_DEL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrdel_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrdel_fuzzer/project.xml b/test/fuzztest/hookmgrdel_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrdel_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrdestroy_fuzzer/corpus/init b/test/fuzztest/hookmgrdestroy_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrdestroy_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.cpp b/test/fuzztest/hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffbbf101066344fb63b4e7524e17739458a203d5 --- /dev/null +++ b/test/fuzztest/hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.cpp @@ -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. + */ + +#include "hookmgrdestroy_fuzzer.h" +#include +#include "hookmgr.h" + +namespace OHOS { + bool FuzzHookMgrDestroy(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + HookMgrDestroy(hookMgr); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrDestroy(data, size); + return 0; +} diff --git a/test/fuzztest/hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.h b/test/fuzztest/hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..2643a1d5a6224712c666a977784fdd70a8462389 --- /dev/null +++ b/test/fuzztest/hookmgrdestroy_fuzzer/hookmgrdestroy_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_DESTROY_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_DESTROY_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrdestroy_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrdestroy_fuzzer/project.xml b/test/fuzztest/hookmgrdestroy_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrdestroy_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrexecute_fuzzer/corpus/init b/test/fuzztest/hookmgrexecute_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrexecute_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.cpp b/test/fuzztest/hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..acc061ccef1f618eb29e090c891a28b00edbf767 --- /dev/null +++ b/test/fuzztest/hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "hookmgrexecute_fuzzer.h" +#include +#include "hookmgr.h" + +namespace OHOS { + bool FuzzHookMgrExecute(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + if (HookMgrExecute(hookMgr, 0, nullptr, nullptr)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrExecute(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.h b/test/fuzztest/hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d3f1d44474326c6395e3d9976f1190f91ab14a13 --- /dev/null +++ b/test/fuzztest/hookmgrexecute_fuzzer/hookmgrexecute_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_EXECUTE_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_EXECUTE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrexecute_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrexecute_fuzzer/project.xml b/test/fuzztest/hookmgrexecute_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrexecute_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrgethookscnt_fuzzer/corpus/init b/test/fuzztest/hookmgrgethookscnt_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrgethookscnt_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.cpp b/test/fuzztest/hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b55bc25b93014e946b8e440608fc7ac4f7eb12f6 --- /dev/null +++ b/test/fuzztest/hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "hookmgrgethookscnt_fuzzer.h" +#include +#include "hookmgr.h" + +namespace OHOS { + bool FuzzHookMgrGetHooksCnt(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + if (HookMgrGetHooksCnt(hookMgr, 0)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrGetHooksCnt(data, size); + return 0; +} diff --git a/test/fuzztest/hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.h b/test/fuzztest/hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..40502e2b87ba9658c1d3be71161d015d776f220e --- /dev/null +++ b/test/fuzztest/hookmgrgethookscnt_fuzzer/hookmgrgethookscnt_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_GET_HOOKS_CNT_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_GET_HOOKS_CNT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrgethookscnt_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrgethookscnt_fuzzer/project.xml b/test/fuzztest/hookmgrgethookscnt_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrgethookscnt_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrgetstagescnt_fuzzer/corpus/init b/test/fuzztest/hookmgrgetstagescnt_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrgetstagescnt_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.cpp b/test/fuzztest/hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..880518a0784f5b407823b529639efb5d0e49aaf0 --- /dev/null +++ b/test/fuzztest/hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "hookmgrgetstagescnt_fuzzer.h" +#include +#include "hookmgr.h" + +namespace OHOS { + bool FuzzHookMgrGetStagesCnt(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + if (HookMgrGetStagesCnt(hookMgr)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrGetStagesCnt(data, size); + return 0; +} diff --git a/test/fuzztest/hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.h b/test/fuzztest/hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4d703ef790101203c565577017ed09914d0739aa --- /dev/null +++ b/test/fuzztest/hookmgrgetstagescnt_fuzzer/hookmgrgetstagescnt_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_GET_STAGES_CNT_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_GET_STAGES_CNT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrgetstagescnt_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrgetstagescnt_fuzzer/project.xml b/test/fuzztest/hookmgrgetstagescnt_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrgetstagescnt_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/hookmgrtraversal_fuzzer/corpus/init b/test/fuzztest/hookmgrtraversal_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/hookmgrtraversal_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.cpp b/test/fuzztest/hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a000a2aae3f98e23e6520e8967ffa50e420bb7f1 --- /dev/null +++ b/test/fuzztest/hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.cpp @@ -0,0 +1,41 @@ +/* + * 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 "hookmgrtraversal_fuzzer.h" +#include +#include "hookmgr.h" + +static void HookTraversal(const HOOK_INFO *hookInfo, void *traversalCookie) +{ + printf("hook traversal test!\n"); +} + +namespace OHOS { + bool FuzzHookMgrTraversal(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + HOOK_MGR *hookMgr = HookMgrCreate(str.c_str()); + HookMgrTraversal(hookMgr, nullptr, HookTraversal); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzHookMgrTraversal(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.h b/test/fuzztest/hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..bc852fa52d4940b4e0e7a7b491191817f4efc07c --- /dev/null +++ b/test/fuzztest/hookmgrtraversal_fuzzer/hookmgrtraversal_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_HOOK_MGR_TRAVERSAL_FUZZER_H +#define TEST_FUZZTEST_HOOK_MGR_TRAVERSAL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "hookmgrtraversal_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/hookmgrtraversal_fuzzer/project.xml b/test/fuzztest/hookmgrtraversal_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/hookmgrtraversal_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/issupportedfilesystem_fuzzer/corpus/init b/test/fuzztest/issupportedfilesystem_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/issupportedfilesystem_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.cpp b/test/fuzztest/issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5fb779b83725cd1ee9348413df3d0398d3d1db1 --- /dev/null +++ b/test/fuzztest/issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.cpp @@ -0,0 +1,34 @@ +/* + * 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 "issupportedfilesystem_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzIsSupportedFilesystem(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + return IsSupportedFilesystem(str.c_str()); + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzIsSupportedFilesystem(data, size); + return 0; +} diff --git a/test/fuzztest/issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.h b/test/fuzztest/issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..af91297707fe351f1a6f0148ee611af184fe5a2b --- /dev/null +++ b/test/fuzztest/issupportedfilesystem_fuzzer/issupportedfilesystem_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_IS_SUPPORTED_FILESYSTEM_FUZZER_H +#define TEST_FUZZTEST_IS_SUPPORTED_FILESYSTEM_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "issupportedfilesystem_fuzzer" +#endif diff --git a/test/fuzztest/issupportedfilesystem_fuzzer/project.xml b/test/fuzztest/issupportedfilesystem_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/issupportedfilesystem_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/loadfscryptpolicy_fuzzer/corpus/init b/test/fuzztest/loadfscryptpolicy_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/loadfscryptpolicy_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.cpp b/test/fuzztest/loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..791f2a1081cbf2147ac40074af96eb439db5cfdb --- /dev/null +++ b/test/fuzztest/loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "loadfscryptpolicy_fuzzer.h" +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzLoadFscryptPolicy(const uint8_t* data, size_t size) + { + bool result = false; + char buff[1024] = {0}; + size_t len = sizeof(buff); + if (!LoadFscryptPolicy(buff, len)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzLoadFscryptPolicy(data, size); + return 0; +} diff --git a/test/fuzztest/loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.h b/test/fuzztest/loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4e2f81a269a65501d7a0bd87bc461a78f2acf664 --- /dev/null +++ b/test/fuzztest/loadfscryptpolicy_fuzzer/loadfscryptpolicy_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_LOAD_FSCRYPT_POLICY_FUZZER_H +#define TEST_FUZZTEST_LOAD_FSCRYPT_POLICY_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "loadfscryptpolicy_fuzzer" +#endif diff --git a/test/fuzztest/loadfscryptpolicy_fuzzer/project.xml b/test/fuzztest/loadfscryptpolicy_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/loadfscryptpolicy_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/loadfstabfromcommandline_fuzzer/corpus/init b/test/fuzztest/loadfstabfromcommandline_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/loadfstabfromcommandline_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.cpp b/test/fuzztest/loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2d069d3dc4fb4e968b70a8831b1ec9876f0eaf2 --- /dev/null +++ b/test/fuzztest/loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * 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 "loadfstabfromcommandline_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzLoadFstabFromCommandLine(const uint8_t* data, size_t size) + { + bool result = false; + if (LoadFstabFromCommandLine() != nullptr) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzLoadFstabFromCommandLine(data, size); + return 0; +} diff --git a/test/fuzztest/loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.h b/test/fuzztest/loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..aa52134da3a1363ea5326eee33b811cd82ff0fd2 --- /dev/null +++ b/test/fuzztest/loadfstabfromcommandline_fuzzer/loadfstabfromcommandline_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_LOAD_FSTAB_FROM_COMMANDLINE_H +#define TEST_FUZZTEST_LOAD_FSTAB_FROM_COMMANDLINE_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "loadfstabfromcommandline_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/loadfstabfromcommandline_fuzzer/project.xml b/test/fuzztest/loadfstabfromcommandline_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/loadfstabfromcommandline_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/loadparamfromcmdline_fuzzer/corpus/init b/test/fuzztest/loadparamfromcmdline_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/loadparamfromcmdline_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.cpp b/test/fuzztest/loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b5768728ecb8109f8b1d247f1a439f58acb6ba9 --- /dev/null +++ b/test/fuzztest/loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.cpp @@ -0,0 +1,48 @@ +/* + * 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 "init_utils.h" +#include "param_manager.h" +#include +#include "loadparamfromcmdline_fuzzer.h" + +namespace OHOS { + void CreateFuzzTestFile(const char *fileName, const char *data) + { + CheckAndCreateDir(fileName); + FILE *tmpFile = fopen(fileName, "wr"); + if (tmpFile != nullptr) { + fprintf(tmpFile, "%s", data); + (void)fflush(tmpFile); + fclose(tmpFile); + } + } + + bool FuzzLoadParamFromCmdLine(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + CreateFuzzTestFile(BOOT_CMD_LINE, str.c_str()); + LoadParamFromCmdLine(); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzLoadParamFromCmdLine(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.h b/test/fuzztest/loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..fe73ad2fff594e9366f97f28d9b31419bca219e4 --- /dev/null +++ b/test/fuzztest/loadparamfromcmdline_fuzzer/loadparamfromcmdline_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_LOAD_PARAM_FROM_CMD_LINE_FUZZER_H +#define TEST_FUZZTEST_LOAD_PARAM_FROM_CMD_LINE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "loadparamfromcmdline_fuzzer" +#endif diff --git a/test/fuzztest/loadparamfromcmdline_fuzzer/project.xml b/test/fuzztest/loadparamfromcmdline_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/loadparamfromcmdline_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgrcreate_fuzzer/corpus/init b/test/fuzztest/modulemgrcreate_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgrcreate_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.cpp b/test/fuzztest/modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5139cd41626122a59754a9553f4654240b8ffed8 --- /dev/null +++ b/test/fuzztest/modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "modulemgrcreate_fuzzer.h" +#include +#include "modulemgr.h" + +namespace OHOS { + bool FuzzModuleMgrCreate(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (ModuleMgrCreate(str.c_str()) != nullptr) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrCreate(data, size); + return 0; +} diff --git a/test/fuzztest/modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.h b/test/fuzztest/modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..2ec9a9631a5665935764f05146eca87f75dafeb6 --- /dev/null +++ b/test/fuzztest/modulemgrcreate_fuzzer/modulemgrcreate_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_CONTROL_FUZZER_H +#define TEST_FUZZTEST_SERVICE_CONTROL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgrcreate_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgrcreate_fuzzer/project.xml b/test/fuzztest/modulemgrcreate_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgrcreate_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgrdestroy_fuzzer/corpus/init b/test/fuzztest/modulemgrdestroy_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgrdestroy_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.cpp b/test/fuzztest/modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2fd78b715902fed441ce46e1a6d9c8f7fb19aa7 --- /dev/null +++ b/test/fuzztest/modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-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 "modulemgrdestroy_fuzzer.h" +#include +#include "modulemgr.h" + +namespace OHOS { + bool FuzzModuleMgrDestroy(const uint8_t* data, size_t size) + { + std::string name(reinterpret_cast(data), size); + MODULE_MGR *moduleMgr = ModuleMgrCreate(name.c_str()); + ModuleMgrDestroy(moduleMgr); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrDestroy(data, size); + return 0; +} diff --git a/test/fuzztest/modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.h b/test/fuzztest/modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..dde71d1c2939d8bf9cdc056961f2e285534f208d --- /dev/null +++ b/test/fuzztest/modulemgrdestroy_fuzzer/modulemgrdestroy_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MODULE_MGR_DESTROY_FUZZER_H +#define TEST_FUZZTEST_MODULE_MGR_DESTROY_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgrdestroy_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgrdestroy_fuzzer/project.xml b/test/fuzztest/modulemgrdestroy_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgrdestroy_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgrgetcnt_fuzzer/corpus/init b/test/fuzztest/modulemgrgetcnt_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgrgetcnt_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.cpp b/test/fuzztest/modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4e47cdb359c981c0b68288c6907046fb1843c51 --- /dev/null +++ b/test/fuzztest/modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "modulemgrgetcnt_fuzzer.h" +#include +#include "modulemgr.h" + +namespace OHOS { + bool FuzzModuleMgrGetCnt(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + MODULE_MGR *moduleMgr = ModuleMgrCreate(str.c_str()); + + if (ModuleMgrGetCnt(moduleMgr)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrGetCnt(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.h b/test/fuzztest/modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6be57dae3db35caf844bbc0f33b4f8e0c05847bc --- /dev/null +++ b/test/fuzztest/modulemgrgetcnt_fuzzer/modulemgrgetcnt_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MODULE_MGR_GET_CNT_FUZZER_H +#define TEST_FUZZTEST_MODULE_MGR_GET_CNT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgrgetcnt_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgrgetcnt_fuzzer/project.xml b/test/fuzztest/modulemgrgetcnt_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgrgetcnt_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgrinstall_fuzzer/corpus/init b/test/fuzztest/modulemgrinstall_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgrinstall_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.cpp b/test/fuzztest/modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40e649609bdee197959aad29738af7d9ed7a60c9 --- /dev/null +++ b/test/fuzztest/modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "modulemgrinstall_fuzzer.h" +#include +#include "modulemgr.h" + +namespace OHOS { + bool FuzzModuleMgrInstall(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + MODULE_MGR *moduleMgr = ModuleMgrCreate(str.c_str()); + if (!ModuleMgrInstall(moduleMgr, str.c_str(), 0, nullptr)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrInstall(data, size); + return 0; +} diff --git a/test/fuzztest/modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.h b/test/fuzztest/modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6ba9198002d558c9515bc62d449be3e5414c5d17 --- /dev/null +++ b/test/fuzztest/modulemgrinstall_fuzzer/modulemgrinstall_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MODULE_MGR_INSTALL_FUZZER_H +#define TEST_FUZZTEST_MODULE_MGR_INSTALL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgrinstall_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgrinstall_fuzzer/project.xml b/test/fuzztest/modulemgrinstall_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgrinstall_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgrscan_fuzzer/corpus/init b/test/fuzztest/modulemgrscan_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgrscan_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgrscan_fuzzer/modulemgrscan_fuzzer.cpp b/test/fuzztest/modulemgrscan_fuzzer/modulemgrscan_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac341c01c74062046bb3d31a06e3285e6a597992 --- /dev/null +++ b/test/fuzztest/modulemgrscan_fuzzer/modulemgrscan_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "modulemgrscan_fuzzer.h" +#include +#include "modulemgr.h" + +namespace OHOS { + bool FuzzModuleMgrScan(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + std::string basePath("/lib/init/autorun"); + basePath += str; + if (ModuleMgrScan(basePath.c_str()) != nullptr) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrScan(data, size); + return 0; +} diff --git a/test/fuzztest/modulemgrscan_fuzzer/modulemgrscan_fuzzer.h b/test/fuzztest/modulemgrscan_fuzzer/modulemgrscan_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..bdd6c821c5a96e788a4cb03ececa8d51245eb78e --- /dev/null +++ b/test/fuzztest/modulemgrscan_fuzzer/modulemgrscan_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MODULE_MGR_SCAN_FUZZER_H +#define TEST_FUZZTEST_MODULE_MGR_SCAN_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgrscan_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgrscan_fuzzer/project.xml b/test/fuzztest/modulemgrscan_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgrscan_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgrtraversal_fuzzer/corpus/init b/test/fuzztest/modulemgrtraversal_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgrtraversal_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.cpp b/test/fuzztest/modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a678040a6ad6cde02621dd8c45ec2aaf463c73ee --- /dev/null +++ b/test/fuzztest/modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.cpp @@ -0,0 +1,41 @@ +/* + * 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 "modulemgrtraversal_fuzzer.h" +#include +#include "modulemgr.h" + +static void ModuleTraversal(const MODULE_INFO *moduleInfo) +{ + printf("module name is: %s\n", moduleInfo->name); +} + +namespace OHOS { + bool FuzzModuleMgrTraversal(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + MODULE_MGR *moduleMgr = ModuleMgrCreate(str.c_str()); + ModuleMgrTraversal(moduleMgr, nullptr, ModuleTraversal); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrTraversal(data, size); + return 0; +} diff --git a/test/fuzztest/modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.h b/test/fuzztest/modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c314887f428d6fe933c0c0c4a705eb1250789c19 --- /dev/null +++ b/test/fuzztest/modulemgrtraversal_fuzzer/modulemgrtraversal_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MODULE_MGR_TRAVERSAL_FUZZER_H +#define TEST_FUZZTEST_MODULE_MGR_TRAVERSAL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgrtraversal_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgrtraversal_fuzzer/project.xml b/test/fuzztest/modulemgrtraversal_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgrtraversal_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/modulemgruninstall_fuzzer/corpus/init b/test/fuzztest/modulemgruninstall_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/modulemgruninstall_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.cpp b/test/fuzztest/modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1cd1d0ae67b0a3a1376808bf44f7cfdc3381479b --- /dev/null +++ b/test/fuzztest/modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.cpp @@ -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. + */ + +#include "modulemgruninstall_fuzzer.h" +#include +#include "modulemgr.h" + +namespace OHOS { + bool FuzzModuleMgrUninstall(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + MODULE_MGR *moduleMgr = ModuleMgrCreate(str.c_str()); + ModuleMgrUninstall(moduleMgr, str.c_str()); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzModuleMgrUninstall(data, size); + return 0; +} diff --git a/test/fuzztest/modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.h b/test/fuzztest/modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..fc3ae5c471e940e1bb26668ec6404012be47d850 --- /dev/null +++ b/test/fuzztest/modulemgruninstall_fuzzer/modulemgruninstall_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MODULE_MGR_UNINSTALL_FUZZER_H +#define TEST_FUZZTEST_MODULE_MGR_UNINSTALL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "modulemgruninstall_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/modulemgruninstall_fuzzer/project.xml b/test/fuzztest/modulemgruninstall_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/modulemgruninstall_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/mountallwithfstab_fuzzer/corpus/init b/test/fuzztest/mountallwithfstab_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/mountallwithfstab_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.cpp b/test/fuzztest/mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec3191e242c0aa79a005efbd8ce0b07c1fcfc54a --- /dev/null +++ b/test/fuzztest/mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.cpp @@ -0,0 +1,50 @@ +/* + * 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 "mountallwithfstab_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzMountAllWithFstab(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + Fstab *fstab = ReadFstabFromFile("fstab.test", false); + if (!MountAllWithFstab(fstab, false)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzMountAllWithFstab(data, size); + return 0; +} diff --git a/test/fuzztest/mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.h b/test/fuzztest/mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..798fd4d461efa99ee300c6544fc6400564037227 --- /dev/null +++ b/test/fuzztest/mountallwithfstab_fuzzer/mountallwithfstab_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MOUNT_ALL_WITH_FSTAB_FUZZER_H +#define TEST_FUZZTEST_MOUNT_ALL_WITH_FSTAB_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "mountallwithfstab_fuzzer" +#endif diff --git a/test/fuzztest/mountallwithfstab_fuzzer/project.xml b/test/fuzztest/mountallwithfstab_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/mountallwithfstab_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/mountallwithfstabfile_fuzzer/corpus/init b/test/fuzztest/mountallwithfstabfile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/mountallwithfstabfile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.cpp b/test/fuzztest/mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6e85626c67c83f4165520de46a32b6351eefaa0 --- /dev/null +++ b/test/fuzztest/mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.cpp @@ -0,0 +1,50 @@ +/* + * 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 "mountallwithfstabfile_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzMountAllWithFstabFile(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + if (!MountAllWithFstabFile("fstab.test", false)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzMountAllWithFstabFile(data, size); + return 0; +} diff --git a/test/fuzztest/mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.h b/test/fuzztest/mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c66f722a80ce71e4db543404d168bb6551fa2567 --- /dev/null +++ b/test/fuzztest/mountallwithfstabfile_fuzzer/mountallwithfstabfile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_MOUNTALLFSTAB_FUZZER_H +#define TEST_FUZZTEST_MOUNTALLFSTAB_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "mountallwithfstabfile_fuzzer" +#endif diff --git a/test/fuzztest/mountallwithfstabfile_fuzzer/project.xml b/test/fuzztest/mountallwithfstabfile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/mountallwithfstabfile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/mountoneitem_fuzzer/corpus/init b/test/fuzztest/mountoneitem_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/mountoneitem_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/mountoneitem_fuzzer/mountoneitem_fuzzer.cpp b/test/fuzztest/mountoneitem_fuzzer/mountoneitem_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3cb60da85d6dcacdcbc754e4c41c94670645c000 --- /dev/null +++ b/test/fuzztest/mountoneitem_fuzzer/mountoneitem_fuzzer.cpp @@ -0,0 +1,55 @@ +/* + * 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 "mountoneitem_fuzzer.h" +#include +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzMountOneItem(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + Fstab *fstab = ReadFstabFromFile("fstab.test", false); + + std::string str(reinterpret_cast(data), size); + FstabItem *item = FindFstabItemForPath(*fstab, str.c_str()); + if (!MountOneItem(item)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzMountOneItem(data, size); + return 0; +} diff --git a/test/fuzztest/mountoneitem_fuzzer/mountoneitem_fuzzer.h b/test/fuzztest/mountoneitem_fuzzer/mountoneitem_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..fb933cff1e41f6cee013482756c0f78f325e64b9 --- /dev/null +++ b/test/fuzztest/mountoneitem_fuzzer/mountoneitem_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_DO_FORMAT_FUZZER_H +#define TEST_FUZZTEST_DO_FORMAT_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "mountoneitem_fuzzer" +#endif diff --git a/test/fuzztest/mountoneitem_fuzzer/project.xml b/test/fuzztest/mountoneitem_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/mountoneitem_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/parsefstabperline_fuzzer/corpus/init b/test/fuzztest/parsefstabperline_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/parsefstabperline_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/parsefstabperline_fuzzer/parsefstabperline_fuzzer.cpp b/test/fuzztest/parsefstabperline_fuzzer/parsefstabperline_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e1d835a7b98ce7be80ed8d0279387762356a3a3 --- /dev/null +++ b/test/fuzztest/parsefstabperline_fuzzer/parsefstabperline_fuzzer.cpp @@ -0,0 +1,55 @@ +/* + * 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 "parsefstabperline_fuzzer.h" +#include +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzParseFstabPerLine(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + Fstab *fstab = ReadFstabFromFile("fstab.test", false); + + std::string str(reinterpret_cast(data), size); + if (ParseFstabPerLine(nullptr, fstab, false, str.c_str())) { + result = true; + }; + + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzParseFstabPerLine(data, size); + return 0; +} diff --git a/test/fuzztest/parsefstabperline_fuzzer/parsefstabperline_fuzzer.h b/test/fuzztest/parsefstabperline_fuzzer/parsefstabperline_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..460202376406cd9b404abed30edaa67bf28fe727 --- /dev/null +++ b/test/fuzztest/parsefstabperline_fuzzer/parsefstabperline_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_PARSE_FSTAB_PERLINE_FUZZER_H +#define TEST_FUZZTEST_PARSE_FSTAB_PERLINE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "parsefstabperline_fuzzer" +#endif diff --git a/test/fuzztest/parsefstabperline_fuzzer/project.xml b/test/fuzztest/parsefstabperline_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/parsefstabperline_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/parseueventconfig_fuzzer/corpus/init b/test/fuzztest/parseueventconfig_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/parseueventconfig_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/parseueventconfig_fuzzer/parseueventconfig_fuzzer.cpp b/test/fuzztest/parseueventconfig_fuzzer/parseueventconfig_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..456b645bd4d8223f88ea6ccb1cd2f6a060747a73 --- /dev/null +++ b/test/fuzztest/parseueventconfig_fuzzer/parseueventconfig_fuzzer.cpp @@ -0,0 +1,49 @@ +/* + * 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 "parseueventconfig_fuzzer.h" +#include +#include "ueventd_read_cfg.h" +#include "securec.h" +#define MAX_ALLOW_SIZE 100 +namespace OHOS { + bool FuzzParseUeventConfig(const uint8_t* data, size_t size) + { + bool result = false; + if (size == 0 || size > MAX_ALLOW_SIZE) { + return false; + } + std::string str(reinterpret_cast(data), size); + char *buffer = new char[size + 1]; + int ret = strcpy_s(buffer, size + 1, str.c_str()); + if (ret != 0) { + delete[] buffer; + return false; + } + if (ParseUeventConfig(buffer) != 0) { + result = true; + } + delete[] buffer; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzParseUeventConfig(data, size); + return 0; +} diff --git a/test/fuzztest/parseueventconfig_fuzzer/parseueventconfig_fuzzer.h b/test/fuzztest/parseueventconfig_fuzzer/parseueventconfig_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3afda182301d05d917e423394efbc26a8d12d283 --- /dev/null +++ b/test/fuzztest/parseueventconfig_fuzzer/parseueventconfig_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_PARSE_FSTAB_PERLINE_FUZZER_H +#define TEST_FUZZTEST_PARSE_FSTAB_PERLINE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "parseueventconfig_fuzzer" +#endif diff --git a/test/fuzztest/parseueventconfig_fuzzer/project.xml b/test/fuzztest/parseueventconfig_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/parseueventconfig_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/parseueventdconfigfile_fuzzer/corpus/init b/test/fuzztest/parseueventdconfigfile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/parseueventdconfigfile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.cpp b/test/fuzztest/parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1eebf092f5804f446c43d26a8f27e6d2e68b8e3 --- /dev/null +++ b/test/fuzztest/parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.cpp @@ -0,0 +1,35 @@ +/* + * 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 "parseueventdconfigfile_fuzzer.h" +#include +#include "ueventd_read_cfg.h" + +namespace OHOS { + bool FuzzParseUeventdConfigFile(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + ParseUeventdConfigFile(str.c_str()); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzParseUeventdConfigFile(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.h b/test/fuzztest/parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..2e53e0c28dbaf0dd096081950d12cc4b1cfc7a9d --- /dev/null +++ b/test/fuzztest/parseueventdconfigfile_fuzzer/parseueventdconfigfile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_PARSE_UEVENTD_CONFIG_FILE_FUZZER_H +#define TEST_FUZZTEST_PARSE_UEVENTD_CONFIG_FILE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "parseueventdconfigfile_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/parseueventdconfigfile_fuzzer/project.xml b/test/fuzztest/parseueventdconfigfile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/parseueventdconfigfile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/project.xml b/test/fuzztest/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/readfileindir_fuzzer/corpus/init b/test/fuzztest/readfileindir_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/readfileindir_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/readfileindir_fuzzer/project.xml b/test/fuzztest/readfileindir_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/readfileindir_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/readfileindir_fuzzer/readfileindir_fuzzer.cpp b/test/fuzztest/readfileindir_fuzzer/readfileindir_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b694ecf487bf86bfa52fe0009da0f02092ec28bd --- /dev/null +++ b/test/fuzztest/readfileindir_fuzzer/readfileindir_fuzzer.cpp @@ -0,0 +1,69 @@ +/* + * 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 "readfileindir_fuzzer.h" + +#include +#include +#include +#include +#include "init.h" +#include "init_utils.h" + +static int FakeParser(const char *testFile, void *context) +{ + UNUSED(context); + std::ifstream fileStream; + fileStream.open(testFile); + std::vector fileText; + std::string textLine; + while (getline(fileStream, textLine)) { + fileText.push_back(textLine); + } + fileStream.close(); + std::vector().swap(fileText); + return 0; +} + +namespace OHOS { + bool FuzzReadFileInDir(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("ReadFileInDir.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file ReadFileInDir.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to ReadFileInDir.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + if (!ReadFileInDir("/data", ".test", FakeParser, NULL)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzReadFileInDir(data, size); + return 0; +} diff --git a/test/fuzztest/readfileindir_fuzzer/readfileindir_fuzzer.h b/test/fuzztest/readfileindir_fuzzer/readfileindir_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3012abd73d673465a2d9c107564abfda68f9f93c --- /dev/null +++ b/test/fuzztest/readfileindir_fuzzer/readfileindir_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_READFILEINDIR_FUZZER_H +#define TEST_FUZZTEST_READFILEINDIR_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "readfileindir_fuzzer" +#endif diff --git a/test/fuzztest/readfiletobuf_fuzzer/corpus/init b/test/fuzztest/readfiletobuf_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/readfiletobuf_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/readfiletobuf_fuzzer/project.xml b/test/fuzztest/readfiletobuf_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/readfiletobuf_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/readfiletobuf_fuzzer/readfiletobuf_fuzzer.cpp b/test/fuzztest/readfiletobuf_fuzzer/readfiletobuf_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b05adc7cf3b68868c2f86c7b61c0e89d92d3cdf4 --- /dev/null +++ b/test/fuzztest/readfiletobuf_fuzzer/readfiletobuf_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "init_utils.h" +#include +#include "readfiletobuf_fuzzer.h" + +namespace OHOS { + bool FuzzReadFileToBuf(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + char *fileBuf = ReadFileToBuf(str.c_str()); + if (fileBuf == nullptr) { + return false; + }; + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzReadFileToBuf(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/readfiletobuf_fuzzer/readfiletobuf_fuzzer.h b/test/fuzztest/readfiletobuf_fuzzer/readfiletobuf_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3cd9fb78b6e3e140fe9ad2fe9d6b72e3cad83b43 --- /dev/null +++ b/test/fuzztest/readfiletobuf_fuzzer/readfiletobuf_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_READ_FILE_TO_BUF_FUZZER_H +#define TEST_FUZZTEST_READ_FILE_TO_BUF_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "readfiletobuf_fuzzer" +#endif diff --git a/test/fuzztest/readfstabfromfile_fuzzer/corpus/init b/test/fuzztest/readfstabfromfile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/readfstabfromfile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/readfstabfromfile_fuzzer/project.xml b/test/fuzztest/readfstabfromfile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/readfstabfromfile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.cpp b/test/fuzztest/readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42a2a90c4e971b4f171200e2dc6a151bce84b428 --- /dev/null +++ b/test/fuzztest/readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.cpp @@ -0,0 +1,50 @@ +/* + * 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 "readfstabfromfile_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzReadFstabFromFile(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + if (ReadFstabFromFile("fstab.test", false) != nullptr) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzReadFstabFromFile(data, size); + return 0; +} diff --git a/test/fuzztest/readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.h b/test/fuzztest/readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..e48e6ae65832ef52b199017a4d625622aa7d91e4 --- /dev/null +++ b/test/fuzztest/readfstabfromfile_fuzzer/readfstabfromfile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_READ_FSTAB_FROM_FILE_FUZZER_H +#define TEST_FUZZTEST_READ_FSTAB_FROM_FILE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "readfstabfromfile_fuzzer" +#endif diff --git a/test/fuzztest/receivefds_fuzzer/corpus/init b/test/fuzztest/receivefds_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/receivefds_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/receivefds_fuzzer/project.xml b/test/fuzztest/receivefds_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/receivefds_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/receivefds_fuzzer/receivefds_fuzzer.cpp b/test/fuzztest/receivefds_fuzzer/receivefds_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ca6e22e8dd2169e299a9e6636589bc5e8b0466f --- /dev/null +++ b/test/fuzztest/receivefds_fuzzer/receivefds_fuzzer.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022-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 "receivefds_fuzzer.h" +#include +#include "securec.h" +#include "fd_holder_internal.h" + +namespace OHOS { + const uint8_t* BASE_DATA = nullptr; + size_t g_baseSize = 0; + size_t g_basePos = 0; + + template T GetData() + { + T object{}; + size_t objectSize = sizeof(object); + if ((BASE_DATA == nullptr) || (objectSize > g_baseSize - g_basePos)) { + return object; + } + errno_t ret = memcpy_s(&object, objectSize, BASE_DATA + g_basePos, objectSize); + if (ret != EOK) { + return {}; + } + g_basePos += objectSize; + return object; + } + + bool FuzzReceiveFds(const uint8_t* data, size_t size) + { + bool result = false; + BASE_DATA = data; + g_baseSize = size; + g_basePos = 0; + if (size > sizeof(struct iovec)) { + struct iovec iovec = GetData(); + if (!ReceiveFds(1, iovec, nullptr, false, nullptr)) { + result = true; + } + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzReceiveFds(data, size); + return 0; +} diff --git a/test/fuzztest/receivefds_fuzzer/receivefds_fuzzer.h b/test/fuzztest/receivefds_fuzzer/receivefds_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..7ce465b917be458182d857aabc548bac8e124a99 --- /dev/null +++ b/test/fuzztest/receivefds_fuzzer/receivefds_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_RECEIVE_FDS_H +#define TEST_FUZZTEST_RECEIVE_FDS_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "receivefds_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/refreshwatcher_fuzzer/corpus/init b/test/fuzztest/refreshwatcher_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/refreshwatcher_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/refreshwatcher_fuzzer/project.xml b/test/fuzztest/refreshwatcher_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/refreshwatcher_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/refreshwatcher_fuzzer/refreshwatcher_fuzzer.cpp b/test/fuzztest/refreshwatcher_fuzzer/refreshwatcher_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..803aab85efa7030388c4432faa6e7ef678471c2e --- /dev/null +++ b/test/fuzztest/refreshwatcher_fuzzer/refreshwatcher_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 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 "refreshwatcher_fuzzer.h" +#include +#include +#include "watcher_manager.h" + +using namespace OHOS::init_param; +namespace OHOS { + bool FuzzRefreshWatcher(const uint8_t* data, size_t size) + { + bool result = false; + std::unique_ptr watcherManager = std::make_unique(0, true); + std::string str(reinterpret_cast(data), size); + + if (!watcherManager->RefreshWatcher(str, *data)) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzRefreshWatcher(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/refreshwatcher_fuzzer/refreshwatcher_fuzzer.h b/test/fuzztest/refreshwatcher_fuzzer/refreshwatcher_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4bc69afdcca3469eeab21355ebe4d9903bf01b0e --- /dev/null +++ b/test/fuzztest/refreshwatcher_fuzzer/refreshwatcher_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_REFRESH_WATCHER_FUZZER_H +#define TEST_FUZZTEST_REFRESH_WATCHER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "refreshwatcher_fuzzer" +#endif diff --git a/test/fuzztest/releasefstab_fuzzer/corpus/init b/test/fuzztest/releasefstab_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/releasefstab_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/releasefstab_fuzzer/project.xml b/test/fuzztest/releasefstab_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/releasefstab_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/releasefstab_fuzzer/releasefstab_fuzzer.cpp b/test/fuzztest/releasefstab_fuzzer/releasefstab_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2d03395481ec8175adac4d842cec9a010624ffd --- /dev/null +++ b/test/fuzztest/releasefstab_fuzzer/releasefstab_fuzzer.cpp @@ -0,0 +1,48 @@ +/* + * 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 "releasefstab_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzReleaseFstab(const uint8_t* data, size_t size) + { + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + Fstab *fstab = ReadFstabFromFile("fstab.test", false); + ReleaseFstab(fstab); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzReleaseFstab(data, size); + return 0; +} diff --git a/test/fuzztest/releasefstab_fuzzer/releasefstab_fuzzer.h b/test/fuzztest/releasefstab_fuzzer/releasefstab_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1c90dc4849f8ac8a67ff13116abaff8e5f0b6ba3 --- /dev/null +++ b/test/fuzztest/releasefstab_fuzzer/releasefstab_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_RELEASE_FSTAB_FUZZER_H +#define TEST_FUZZTEST_RELEASE_FSTAB_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "releasefstab_fuzzer" +#endif diff --git a/test/fuzztest/removeparameterwatcher_fuzzer/corpus/init b/test/fuzztest/removeparameterwatcher_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/removeparameterwatcher_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/removeparameterwatcher_fuzzer/project.xml b/test/fuzztest/removeparameterwatcher_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/removeparameterwatcher_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.cpp b/test/fuzztest/removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6385710898321c1bc93ce0e3d23f47f81f193b3a --- /dev/null +++ b/test/fuzztest/removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.cpp @@ -0,0 +1,48 @@ +/* + * 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 "removeparameterwatcher_fuzzer.h" +#include +#include "parameter.h" +#include "fuzz_utils.h" + +static void HandleParamChange(const char *key, const char *value, void *context) +{ + if (key == nullptr || value == nullptr) { + return; + } + printf("Receive parameter change %s %s \n", key, value); +} + +namespace OHOS { + bool FuzzRemoveParameterWatcher(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + CloseStdout(); + if (!RemoveParameterWatcher(str.c_str(), HandleParamChange, NULL)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzRemoveParameterWatcher(data, size); + return 0; +} diff --git a/test/fuzztest/removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.h b/test/fuzztest/removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..e0984a51e932badc058948912a9b2ade3508f520 --- /dev/null +++ b/test/fuzztest/removeparameterwatcher_fuzzer/removeparameterwatcher_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_REMOVEWATCHPARAMETER_FUZZER_H +#define TEST_FUZZTEST_REMOVEWATCHPARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "removeparameterwatcher_fuzzer" +#endif diff --git a/test/fuzztest/saveparameters_fuzzer/corpus/init b/test/fuzztest/saveparameters_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..2b595da0c26af63ffb2d5f4132c086b2e5986fce --- /dev/null +++ b/test/fuzztest/saveparameters_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/saveparameters_fuzzer/project.xml b/test/fuzztest/saveparameters_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/saveparameters_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/saveparameters_fuzzer/saveparameters_fuzzer.cpp b/test/fuzztest/saveparameters_fuzzer/saveparameters_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7149b4cfd23ecb2414bfb0b2c15b3c3c19b35dd5 --- /dev/null +++ b/test/fuzztest/saveparameters_fuzzer/saveparameters_fuzzer.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 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 "saveparameters_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzSaveParameters(const uint8_t* data, size_t size) + { + bool result = false; + if (SaveParameters()) { + result = true; + }; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSaveParameters(data, size); + return 0; +} diff --git a/test/fuzztest/saveparameters_fuzzer/saveparameters_fuzzer.h b/test/fuzztest/saveparameters_fuzzer/saveparameters_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4dd2d25d22837f371feb035cccd21b5084713d6d --- /dev/null +++ b/test/fuzztest/saveparameters_fuzzer/saveparameters_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_GET_FIRST_API_VERSION_H +#define TEST_FUZZTEST_GET_FIRST_API_VERSION_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "saveparameters_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicecontrol_fuzzer/corpus/init b/test/fuzztest/servicecontrol_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicecontrol_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicecontrol_fuzzer/project.xml b/test/fuzztest/servicecontrol_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicecontrol_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicecontrol_fuzzer/servicecontrol_fuzzer.cpp b/test/fuzztest/servicecontrol_fuzzer/servicecontrol_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d6ddf231de6abd7e555e154854a94571fbb185d --- /dev/null +++ b/test/fuzztest/servicecontrol_fuzzer/servicecontrol_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "servicecontrol_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzServiceControl(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!ServiceControl(str.c_str(), START)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceControl(data, size); + return 0; +} diff --git a/test/fuzztest/servicecontrol_fuzzer/servicecontrol_fuzzer.h b/test/fuzztest/servicecontrol_fuzzer/servicecontrol_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f6267030f55557fad0c4cb7a1b2f58145af949bf --- /dev/null +++ b/test/fuzztest/servicecontrol_fuzzer/servicecontrol_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_CONTROL_FUZZER_H +#define TEST_FUZZTEST_SERVICE_CONTROL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicecontrol_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicecontrolstart_fuzzer/corpus/init b/test/fuzztest/servicecontrolstart_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicecontrolstart_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicecontrolstart_fuzzer/project.xml b/test/fuzztest/servicecontrolstart_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicecontrolstart_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.cpp b/test/fuzztest/servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..161633e00b20f248c2a98e5489a2b5ef840b9cd2 --- /dev/null +++ b/test/fuzztest/servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "servicecontrolstart_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzServiceControlStart(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!ServiceControl(str.c_str(), START)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceControlStart(data, size); + return 0; +} diff --git a/test/fuzztest/servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.h b/test/fuzztest/servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..b9ea415935ac8a467c08ade04037efbedeb4eb59 --- /dev/null +++ b/test/fuzztest/servicecontrolstart_fuzzer/servicecontrolstart_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_STARTONDEMANDPROCESS_FUZZER_H +#define TEST_FUZZTEST_STARTONDEMANDPROCESS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicecontrolstart_fuzzer" +#endif diff --git a/test/fuzztest/servicecontrolstop_fuzzer/corpus/init b/test/fuzztest/servicecontrolstop_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicecontrolstop_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicecontrolstop_fuzzer/project.xml b/test/fuzztest/servicecontrolstop_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicecontrolstop_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.cpp b/test/fuzztest/servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ccc9ff4526a644855bffe02eb351f57ef59ab87 --- /dev/null +++ b/test/fuzztest/servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "servicecontrolstop_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzServiceControlStop(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!ServiceControl(str.c_str(), STOP)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceControlStop(data, size); + return 0; +} diff --git a/test/fuzztest/servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.h b/test/fuzztest/servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..65d4892294b2368f63bfb888f5410b09ccd8f181 --- /dev/null +++ b/test/fuzztest/servicecontrolstop_fuzzer/servicecontrolstop_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_STOPONDEMANDPROCESS_FUZZER_H +#define TEST_FUZZTEST_STOPONDEMANDPROCESS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicecontrolstop_fuzzer" +#endif diff --git a/test/fuzztest/servicecontrolwithextra_fuzzer/corpus/init b/test/fuzztest/servicecontrolwithextra_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicecontrolwithextra_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicecontrolwithextra_fuzzer/project.xml b/test/fuzztest/servicecontrolwithextra_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicecontrolwithextra_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.cpp b/test/fuzztest/servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a0d8105bd96cecd83ecccf981383f87f935055c3 --- /dev/null +++ b/test/fuzztest/servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "servicecontrolwithextra_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzServiceControlWithExtra(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!ServiceControlWithExtra(str.c_str(), START, nullptr, 1)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceControlWithExtra(data, size); + return 0; +} diff --git a/test/fuzztest/servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.h b/test/fuzztest/servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..6170595ea7eac18072cbea72f9b24c5707d0a9e9 --- /dev/null +++ b/test/fuzztest/servicecontrolwithextra_fuzzer/servicecontrolwithextra_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_CONTROL_WITH_EXTRA_FUZZER_H +#define TEST_FUZZTEST_SERVICE_CONTROL_WITH_EXTRA_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicecontrolwithextra_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicegetfd_fuzzer/corpus/init b/test/fuzztest/servicegetfd_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicegetfd_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicegetfd_fuzzer/project.xml b/test/fuzztest/servicegetfd_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicegetfd_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicegetfd_fuzzer/servicegetfd_fuzzer.cpp b/test/fuzztest/servicegetfd_fuzzer/servicegetfd_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..250aef9e69bc9fc9b583792c3606c95e58036052 --- /dev/null +++ b/test/fuzztest/servicegetfd_fuzzer/servicegetfd_fuzzer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "servicegetfd_fuzzer.h" +#include +#include "fd_holder.h" + +namespace OHOS { + bool FuzzServiceGetFd(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + size_t fdCount[1] = {0}; + if (!ServiceGetFd(str.c_str(), fdCount)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceGetFd(data, size); + return 0; +} diff --git a/test/fuzztest/servicegetfd_fuzzer/servicegetfd_fuzzer.h b/test/fuzztest/servicegetfd_fuzzer/servicegetfd_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..41c51ae21aca0e21eb8b31e419a7362f17048773 --- /dev/null +++ b/test/fuzztest/servicegetfd_fuzzer/servicegetfd_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_GET_FD_FUZZER_H +#define TEST_FUZZTEST_SERVICE_GET_FD_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicegetfd_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicesavefd_fuzzer/corpus/init b/test/fuzztest/servicesavefd_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicesavefd_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicesavefd_fuzzer/project.xml b/test/fuzztest/servicesavefd_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicesavefd_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicesavefd_fuzzer/servicesavefd_fuzzer.cpp b/test/fuzztest/servicesavefd_fuzzer/servicesavefd_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..006f06e48758b18935fb39577bb8c3c240ec11f7 --- /dev/null +++ b/test/fuzztest/servicesavefd_fuzzer/servicesavefd_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "servicesavefd_fuzzer.h" +#include +#include "fd_holder.h" + +namespace OHOS { + bool FuzzServiceSaveFd(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + int fd[64] = {0}; + int count = 10; + if (!ServiceSaveFd(str.c_str(), fd, count)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceSaveFd(data, size); + return 0; +} diff --git a/test/fuzztest/servicesavefd_fuzzer/servicesavefd_fuzzer.h b/test/fuzztest/servicesavefd_fuzzer/servicesavefd_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..4403c26f4f87e7f4069ec773ab8f86f17adf1bcd --- /dev/null +++ b/test/fuzztest/servicesavefd_fuzzer/servicesavefd_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_SAVE_FD_FUZZER_H +#define TEST_FUZZTEST_SERVICE_SAVE_FD_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicesavefd_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicesavefdwithpoll_fuzzer/corpus/init b/test/fuzztest/servicesavefdwithpoll_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicesavefdwithpoll_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicesavefdwithpoll_fuzzer/project.xml b/test/fuzztest/servicesavefdwithpoll_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicesavefdwithpoll_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.cpp b/test/fuzztest/servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e73f16f1099b8f689fbc6c895b3efb8a15a95786 --- /dev/null +++ b/test/fuzztest/servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.cpp @@ -0,0 +1,40 @@ +/* + * 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 "servicesavefdwithpoll_fuzzer.h" +#include +#include "fd_holder.h" + +namespace OHOS { + bool FuzzServiceSaveFdWithPoll(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + int fds[64] = {0}; + int fdCount = 10; // fd count + if (!ServiceSaveFdWithPoll(str.c_str(), fds, fdCount)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceSaveFdWithPoll(data, size); + return 0; +} diff --git a/test/fuzztest/servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.h b/test/fuzztest/servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..194ec40855a8d7a29e21f89cc3811f93c53d9b60 --- /dev/null +++ b/test/fuzztest/servicesavefdwithpoll_fuzzer/servicesavefdwithpoll_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_SAVE_FD_WITH_POLL_FUZZER_H +#define TEST_FUZZTEST_SERVICE_SAVE_FD_WITH_POLL_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicesavefdwithpoll_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicesetready_fuzzer/corpus/init b/test/fuzztest/servicesetready_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicesetready_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicesetready_fuzzer/project.xml b/test/fuzztest/servicesetready_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicesetready_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicesetready_fuzzer/servicesetready_fuzzer.cpp b/test/fuzztest/servicesetready_fuzzer/servicesetready_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e1a59311251f7ca89ae7ab76ab2a0e3201e8118 --- /dev/null +++ b/test/fuzztest/servicesetready_fuzzer/servicesetready_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "servicesetready_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzServiceSetReady(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!ServiceSetReady(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceSetReady(data, size); + return 0; +} diff --git a/test/fuzztest/servicesetready_fuzzer/servicesetready_fuzzer.h b/test/fuzztest/servicesetready_fuzzer/servicesetready_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..e9032edf4d16265df83fd5c19c7b76805f503567 --- /dev/null +++ b/test/fuzztest/servicesetready_fuzzer/servicesetready_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_SET_READY_FUZZER_H +#define TEST_FUZZTEST_SERVICE_SET_READY_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicesetready_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicewaitforstatus_fuzzer/corpus/init b/test/fuzztest/servicewaitforstatus_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicewaitforstatus_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicewaitforstatus_fuzzer/project.xml b/test/fuzztest/servicewaitforstatus_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicewaitforstatus_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.cpp b/test/fuzztest/servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed60aa494011edb5506795379a6374aea514b421 --- /dev/null +++ b/test/fuzztest/servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "servicewaitforstatus_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzServiceWaitForStatus(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!ServiceWaitForStatus(str.c_str(), SERVICE_STARTED, 1)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceWaitForStatus(data, size); + return 0; +} diff --git a/test/fuzztest/servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.h b/test/fuzztest/servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..c190eccef55ba8fe65d592d09962f9fd1902df09 --- /dev/null +++ b/test/fuzztest/servicewaitforstatus_fuzzer/servicewaitforstatus_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_WAIT_FOR_STATUS_FUZZER_H +#define TEST_FUZZTEST_SERVICE_WAIT_FOR_STATUS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicewaitforstatus_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/servicewatchforstatus_fuzzer/corpus/init b/test/fuzztest/servicewatchforstatus_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/servicewatchforstatus_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/servicewatchforstatus_fuzzer/project.xml b/test/fuzztest/servicewatchforstatus_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/servicewatchforstatus_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.cpp b/test/fuzztest/servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40a16fbf2a19494698261b2fedba0c6485688047 --- /dev/null +++ b/test/fuzztest/servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.cpp @@ -0,0 +1,45 @@ +/* + * 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 "servicewatchforstatus_fuzzer.h" +#include +#include "service_watcher.h" +#include "fuzz_utils.h" + +static void callback(const char *key, const ServiceInfo *status) +{ + printf("key is: %s, ServiceStatus is: %d\n", key, status->status); +} + +namespace OHOS { + bool FuzzServiceWatchForStatus(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + CloseStdout(); + if (!ServiceWatchForStatus(str.c_str(), callback)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzServiceWatchForStatus(data, size); + return 0; +} diff --git a/test/fuzztest/servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.h b/test/fuzztest/servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..3df855757d1d5ad2c3d8c542e4fe31be2bfb2a79 --- /dev/null +++ b/test/fuzztest/servicewatchforstatus_fuzzer/servicewatchforstatus_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SERVICE_WATCH_FOR_STATUS_FUZZER_H +#define TEST_FUZZTEST_SERVICE_WATCH_FOR_STATUS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "servicewatchforstatus_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/setparameterc_fuzzer/corpus/init b/test/fuzztest/setparameterc_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/setparameterc_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/setparameterc_fuzzer/project.xml b/test/fuzztest/setparameterc_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/setparameterc_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/setparameterc_fuzzer/setparameterc_fuzzer.cpp b/test/fuzztest/setparameterc_fuzzer/setparameterc_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bc450be9364795f9a8170eac5e1f6a99ed5f346 --- /dev/null +++ b/test/fuzztest/setparameterc_fuzzer/setparameterc_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "setparameterc_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzSetParameterC(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!SetParameter(str.c_str(), str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSetParameterC(data, size); + return 0; +} diff --git a/test/fuzztest/setparameterc_fuzzer/setparameterc_fuzzer.h b/test/fuzztest/setparameterc_fuzzer/setparameterc_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..d233f1050dcd26af7d2f146551374ce5b46c9b69 --- /dev/null +++ b/test/fuzztest/setparameterc_fuzzer/setparameterc_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SETPARAMETER_C_FUZZER_H +#define TEST_FUZZTEST_SETPARAMETER_C_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "setparameterc_fuzzer" +#endif diff --git a/test/fuzztest/setparametercpp_fuzzer/corpus/init b/test/fuzztest/setparametercpp_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/setparametercpp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/setparametercpp_fuzzer/project.xml b/test/fuzztest/setparametercpp_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/setparametercpp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/setparametercpp_fuzzer/setparametercpp_fuzzer.cpp b/test/fuzztest/setparametercpp_fuzzer/setparametercpp_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9472aadeceb68ddbc7678ca728334e984eca008f --- /dev/null +++ b/test/fuzztest/setparametercpp_fuzzer/setparametercpp_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "setparametercpp_fuzzer.h" +#include +#include "parameters.h" + +namespace OHOS { + bool FuzzSetParameter(const uint8_t* data, size_t size) + { + bool result = false; + std::string key(reinterpret_cast(data), size); + if (system::SetParameter(key, key)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSetParameter(data, size); + return 0; +} diff --git a/test/fuzztest/setparametercpp_fuzzer/setparametercpp_fuzzer.h b/test/fuzztest/setparametercpp_fuzzer/setparametercpp_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a775aad6e14212a5cb788375d5d8c76d1754d371 --- /dev/null +++ b/test/fuzztest/setparametercpp_fuzzer/setparametercpp_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SET_PARAMETER_CPP_FUZZER_H +#define TEST_FUZZTEST_SET_PARAMETER_CPP_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "setparametercpp_fuzzer" +#endif diff --git a/test/fuzztest/splitstring_fuzzer/corpus/init b/test/fuzztest/splitstring_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/splitstring_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/splitstring_fuzzer/project.xml b/test/fuzztest/splitstring_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/splitstring_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/splitstring_fuzzer/splitstring_fuzzer.cpp b/test/fuzztest/splitstring_fuzzer/splitstring_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..918d5d506e3d2525d38023f3aed6d0b458b5e9d8 --- /dev/null +++ b/test/fuzztest/splitstring_fuzzer/splitstring_fuzzer.cpp @@ -0,0 +1,42 @@ +/* + * 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 +#include "init_utils.h" +#include "splitstring_fuzzer.h" + +namespace OHOS { + bool FuzzSplitString(const uint8_t* data, size_t size) + { + std::string str(reinterpret_cast(data), size); + char *opt[20] = {nullptr}; + char *srcPtr = strdup(str.c_str()); + int ret = SplitString(srcPtr, " ", opt, 20); + if (ret != 0) { + free(srcPtr); + return false; + }; + free(srcPtr); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSplitString(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/splitstring_fuzzer/splitstring_fuzzer.h b/test/fuzztest/splitstring_fuzzer/splitstring_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..85b9b3f88daa02e2807f9e1ba1dce3cc3debf230 --- /dev/null +++ b/test/fuzztest/splitstring_fuzzer/splitstring_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_CHECK_AND_CREAT_FILE_FUZZER_H +#define TEST_FUZZTEST_CHECK_AND_CREAT_FILE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "splitstring_fuzzer" +#endif diff --git a/test/fuzztest/startservicebytimer_fuzzer/corpus/init b/test/fuzztest/startservicebytimer_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/startservicebytimer_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/startservicebytimer_fuzzer/project.xml b/test/fuzztest/startservicebytimer_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/startservicebytimer_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/startservicebytimer_fuzzer/startservicebytimer_fuzzer.cpp b/test/fuzztest/startservicebytimer_fuzzer/startservicebytimer_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..601654e8201bb03b94b81f3b8d6b9f2bbcc78dae --- /dev/null +++ b/test/fuzztest/startservicebytimer_fuzzer/startservicebytimer_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "startservicebytimer_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzStartServiceByTimer(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!StartServiceByTimer(str.c_str(), 1)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzStartServiceByTimer(data, size); + return 0; +} diff --git a/test/fuzztest/startservicebytimer_fuzzer/startservicebytimer_fuzzer.h b/test/fuzztest/startservicebytimer_fuzzer/startservicebytimer_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..97baee60892e76a2fa8842776bf755396426a673 --- /dev/null +++ b/test/fuzztest/startservicebytimer_fuzzer/startservicebytimer_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_START_SERVICE_BY_TIMER_FUZZER_H +#define TEST_FUZZTEST_START_SERVICE_BY_TIMER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "startservicebytimer_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/stopservicetimer_fuzzer/corpus/init b/test/fuzztest/stopservicetimer_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/stopservicetimer_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/stopservicetimer_fuzzer/project.xml b/test/fuzztest/stopservicetimer_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/stopservicetimer_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/stopservicetimer_fuzzer/stopservicetimer_fuzzer.cpp b/test/fuzztest/stopservicetimer_fuzzer/stopservicetimer_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b3c44e91aae828a5f80c0c349cf7f10234d5c1f --- /dev/null +++ b/test/fuzztest/stopservicetimer_fuzzer/stopservicetimer_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "stopservicetimer_fuzzer.h" +#include +#include "service_control.h" + +namespace OHOS { + bool FuzzStopServiceTimer(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!StopServiceTimer(str.c_str())) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzStopServiceTimer(data, size); + return 0; +} diff --git a/test/fuzztest/stopservicetimer_fuzzer/stopservicetimer_fuzzer.h b/test/fuzztest/stopservicetimer_fuzzer/stopservicetimer_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..76bf187a363188d86c76c76c692c355e9aa5a6aa --- /dev/null +++ b/test/fuzztest/stopservicetimer_fuzzer/stopservicetimer_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_STOP_SERVICE_TIMER_FUZZER_H +#define TEST_FUZZTEST_STOP_SERVICE_TIMER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "stopservicetimer_fuzzer" +#endif \ No newline at end of file diff --git a/test/fuzztest/syscheckparamexist_fuzzer/corpus/init b/test/fuzztest/syscheckparamexist_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/syscheckparamexist_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/syscheckparamexist_fuzzer/project.xml b/test/fuzztest/syscheckparamexist_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/syscheckparamexist_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.cpp b/test/fuzztest/syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51f63a3ff775e026da3f6ad045580996698cb3be --- /dev/null +++ b/test/fuzztest/syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 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 "syscheckparamexist_fuzzer.h" +#include +#include "param_manager.h" + +#define NAME_LEN_MAX 96 + +namespace OHOS { + bool FuzzSysCheckParamExist(const uint8_t* data, size_t size) + { + if (size >= NAME_LEN_MAX) { + return false; + } + + std::string name(reinterpret_cast(data), size); + int ret = SysCheckParamExist(name.c_str()); + if (ret == 0) { + return false; + }; + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSysCheckParamExist(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.h b/test/fuzztest/syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..f0faa4c9c8cd99c95c687b0846dc4dcc9d57492a --- /dev/null +++ b/test/fuzztest/syscheckparamexist_fuzzer/syscheckparamexist_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_SYS_CHECK_PARAM_EXIST_FUZZER_H +#define TEST_FUZZTEST_SYS_CHECK_PARAM_EXIST_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "syscheckparamexist_fuzzer" +#endif diff --git a/test/fuzztest/systemdumpparameters_fuzzer/corpus/init b/test/fuzztest/systemdumpparameters_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/systemdumpparameters_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/systemdumpparameters_fuzzer/project.xml b/test/fuzztest/systemdumpparameters_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/systemdumpparameters_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.cpp b/test/fuzztest/systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a74e1a6818e3ae5c177a11ef2a19aba1da73de0 --- /dev/null +++ b/test/fuzztest/systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "systemdumpparameters_fuzzer.h" +#include +#include "init_param.h" +#include "fuzz_utils.h" + +namespace OHOS { + bool FuzzSystemDumpParameters(const uint8_t* data, size_t size) + { + CloseStdout(); + std::string str(reinterpret_cast(data), size); + int verbose = atoi(str.c_str()); + SystemDumpParameters(verbose, -1, nullptr); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSystemDumpParameters(data, size); + return 0; +} diff --git a/test/fuzztest/systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.h b/test/fuzztest/systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..a0c5f39cedf5c35e71bd67217a0724eb314afe24 --- /dev/null +++ b/test/fuzztest/systemdumpparameters_fuzzer/systemdumpparameters_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_SYSTEMDUMPPARAMETERS_FUZZER_H +#define TEST_FUZZTEST_SYSTEMDUMPPARAMETERS_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "systemdumpparameters_fuzzer" +#endif diff --git a/test/fuzztest/systemtraversalparameter_fuzzer/corpus/init b/test/fuzztest/systemtraversalparameter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/systemtraversalparameter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/systemtraversalparameter_fuzzer/project.xml b/test/fuzztest/systemtraversalparameter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/systemtraversalparameter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.cpp b/test/fuzztest/systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a11006ede2fb9ffc107e27340e9f8467afb1e266 --- /dev/null +++ b/test/fuzztest/systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.cpp @@ -0,0 +1,76 @@ +/* + * 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 "systemtraversalparameter_fuzzer.h" + +#include +#include "fuzz_utils.h" +#include "init.h" +#include "securec.h" +#include "init_param.h" +#include "param_init.h" + +static void FakeShowParam(ParamHandle handle, void *cookie) +{ + Cookie *nameAndValue = reinterpret_cast(cookie); + char *name = nameAndValue->data; + unsigned int nameLen = nameAndValue->size; + char value[PARAM_CONST_VALUE_LEN_MAX] = {0}; + SystemGetParameterName(handle, name, nameLen); + uint32_t size = PARAM_CONST_VALUE_LEN_MAX; + SystemGetParameterValue(handle, value, &size); + printf("\t%s = %s \n", name, value); +} + +namespace OHOS { + bool FuzzSystemTraversalParameter(const uint8_t* data, size_t size) + { + bool result = false; + CloseStdout(); + Cookie instance = {0, nullptr}; + Cookie *cookie = &instance; + if (size == 0) { + return false; + } + if (size > PARAM_CONST_VALUE_LEN_MAX + PARAM_NAME_LEN_MAX) { + return true; + } + cookie->data = static_cast(calloc(1, size)); + if (cookie->data == nullptr) { + return true; + } + cookie->size = size; + std::string str(reinterpret_cast(data), size - 1); + int ret = memcpy_s(cookie->data, size, str.c_str(), size); + if (ret != EOK) { + return false; + } + if (!SystemTraversalParameter(nullptr, FakeShowParam, reinterpret_cast(cookie))) { + result = true; + } + free(cookie->data); + cookie->data = nullptr; + cookie->size = 0; + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSystemTraversalParameter(data, size); + return 0; +} diff --git a/test/fuzztest/systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.h b/test/fuzztest/systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..324de343d87495cc449dcef3a3e66023296a37c5 --- /dev/null +++ b/test/fuzztest/systemtraversalparameter_fuzzer/systemtraversalparameter_fuzzer.h @@ -0,0 +1,26 @@ +/* + * 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 TEST_FUZZTEST_SYSTEMTRAVERSALPARAMETER_FUZZER_H +#define TEST_FUZZTEST_SYSTEMTRAVERSALPARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "systemtraversalparameter_fuzzer" + +typedef struct { + size_t size; + char *data; +} Cookie; + +#endif diff --git a/test/fuzztest/systemwaitparameter_fuzzer/corpus/init b/test/fuzztest/systemwaitparameter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/systemwaitparameter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/systemwaitparameter_fuzzer/project.xml b/test/fuzztest/systemwaitparameter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..a03232f21591eac33f2e0b55e2902ee4ecf49296 --- /dev/null +++ b/test/fuzztest/systemwaitparameter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.cpp b/test/fuzztest/systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bac6a7fab99314e2e120bc4ece8e2fa3d9bc727e --- /dev/null +++ b/test/fuzztest/systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 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 "systemwaitparameter_fuzzer.h" +#include +#include "init_param.h" + +#define NAME_LEN_MAX 96 + +namespace OHOS { + bool FuzzSystemWaitParameter(const uint8_t* data, size_t size) + { + if (size >= NAME_LEN_MAX) { + return false; + } + + std::string name(reinterpret_cast(data), size); + int ret = SystemWaitParameter(name.c_str(), "test", 1); + if (!ret) { + return true; + }; + return false; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzSystemWaitParameter(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.h b/test/fuzztest/systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1e5e653269baf4d9d55df20aa3249ab9150b8604 --- /dev/null +++ b/test/fuzztest/systemwaitparameter_fuzzer/systemwaitparameter_fuzzer.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 TEST_FUZZTEST_SYSTEM_WAIT_PARAMETER_FUZZER_H +#define TEST_FUZZTEST_SYSTEM_WAIT_PARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "systemwaitparameter_fuzzer" +#endif diff --git a/test/fuzztest/umountallwithfstabfile_fuzzer/corpus/init b/test/fuzztest/umountallwithfstabfile_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/umountallwithfstabfile_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/umountallwithfstabfile_fuzzer/project.xml b/test/fuzztest/umountallwithfstabfile_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/umountallwithfstabfile_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.cpp b/test/fuzztest/umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6742672619b5c0e375617f09950ea7064eb2859d --- /dev/null +++ b/test/fuzztest/umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.cpp @@ -0,0 +1,51 @@ +/* + * 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 "umountallwithfstabfile_fuzzer.h" +#include +#include "fs_manager/fs_manager.h" + +namespace OHOS { + bool FuzzUmountAllWithFstabFile(const uint8_t* data, size_t size) + { + bool result = false; + FILE *pFile = nullptr; + pFile = fopen("fstab.test", "w+"); + if (pFile == nullptr) { + std::cout << "[fuzz] open file fstab.test failed"; + return false; + } + if (fwrite(data, 1, size, pFile) != size) { + std::cout << "[fuzz] write data to fstab.test failed"; + (void)fclose(pFile); + return false; + } + (void)fclose(pFile); + CloseStdout(); + if (!UmountAllWithFstabFile("fstab.test")) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzUmountAllWithFstabFile(data, size); + return 0; +} + diff --git a/test/fuzztest/umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.h b/test/fuzztest/umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..44aa59d0cccb9b87bc6dab47ee5ebf31bd8154f8 --- /dev/null +++ b/test/fuzztest/umountallwithfstabfile_fuzzer/umountallwithfstabfile_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_UMOUNTALLFSTAB_FUZZER_H +#define TEST_FUZZTEST_UMOUNTALLFSTAB_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "umountallwithfstabfile_fuzzer" +#endif diff --git a/test/fuzztest/utils/fuzz_utils.cpp b/test/fuzztest/utils/fuzz_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5881b69240a77e4aba420949e6d507a2cd7055a4 --- /dev/null +++ b/test/fuzztest/utils/fuzz_utils.cpp @@ -0,0 +1,28 @@ +/* + * 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 "fuzz_utils.h" + +void CloseStdout(void) +{ + int fd = open("/dev/null", O_RDWR | O_CLOEXEC); + if (fd < 0) { + return; + } + dup2(fd, 1); + close(fd); +} \ No newline at end of file diff --git a/test/fuzztest/utils/include/fuzz_utils.h b/test/fuzztest/utils/include/fuzz_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1de03bebe5d3d301576b4ad51b64c60b5fc63bf7 --- /dev/null +++ b/test/fuzztest/utils/include/fuzz_utils.h @@ -0,0 +1,23 @@ +/* + * 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 FUZZ_UTILS_H +#define FUZZ_UTILS_H +#include +#include + +#define BASE 10 +void CloseStdout(void); +#endif diff --git a/test/fuzztest/waitparameter_fuzzer/corpus/init b/test/fuzztest/waitparameter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/waitparameter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/waitparameter_fuzzer/project.xml b/test/fuzztest/waitparameter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/waitparameter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/waitparameter_fuzzer/waitparameter_fuzzer.cpp b/test/fuzztest/waitparameter_fuzzer/waitparameter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c2f729bb3cc5bedfe7728dabc27ec9ef70597ab --- /dev/null +++ b/test/fuzztest/waitparameter_fuzzer/waitparameter_fuzzer.cpp @@ -0,0 +1,38 @@ +/* + * 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 "waitparameter_fuzzer.h" +#include +#include "parameter.h" + +namespace OHOS { + bool FuzzWaitParameter(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + if (!WaitParameter(str.c_str(), str.c_str(), 1)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzWaitParameter(data, size); + return 0; +} diff --git a/test/fuzztest/waitparameter_fuzzer/waitparameter_fuzzer.h b/test/fuzztest/waitparameter_fuzzer/waitparameter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..840d1caa0d7219d91042084e111a0bec02a793c2 --- /dev/null +++ b/test/fuzztest/waitparameter_fuzzer/waitparameter_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_WAITPARAMETER_FUZZER_H +#define TEST_FUZZTEST_WAITPARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "waitparameter_fuzzer" +#endif diff --git a/test/fuzztest/watchparameter_fuzzer/corpus/init b/test/fuzztest/watchparameter_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5 --- /dev/null +++ b/test/fuzztest/watchparameter_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/watchparameter_fuzzer/project.xml b/test/fuzztest/watchparameter_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..949d03efd7477905377ac79f3b0bb374c8ac2e9a --- /dev/null +++ b/test/fuzztest/watchparameter_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/watchparameter_fuzzer/watchparameter_fuzzer.cpp b/test/fuzztest/watchparameter_fuzzer/watchparameter_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8889249d3e3c23f12a487235c357a1fd0aa2eb39 --- /dev/null +++ b/test/fuzztest/watchparameter_fuzzer/watchparameter_fuzzer.cpp @@ -0,0 +1,48 @@ +/* + * 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 "watchparameter_fuzzer.h" +#include +#include "parameter.h" +#include "fuzz_utils.h" + +static void HandleParamChange(const char *key, const char *value, void *context) +{ + if (key == nullptr || value == nullptr) { + return; + } + printf("Receive parameter change %s %s \n", key, value); +} + +namespace OHOS { + bool FuzzWatchParameter(const uint8_t* data, size_t size) + { + bool result = false; + std::string str(reinterpret_cast(data), size); + CloseStdout(); + if (!WatchParameter(str.c_str(), HandleParamChange, NULL)) { + result = true; + } + return result; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzWatchParameter(data, size); + return 0; +} diff --git a/test/fuzztest/watchparameter_fuzzer/watchparameter_fuzzer.h b/test/fuzztest/watchparameter_fuzzer/watchparameter_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..01becc8588ff9e17d32321afccf7f8e642bde8c4 --- /dev/null +++ b/test/fuzztest/watchparameter_fuzzer/watchparameter_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_WATCHPARAMETER_FUZZER_H +#define TEST_FUZZTEST_WATCHPARAMETER_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "watchparameter_fuzzer" +#endif diff --git a/test/fuzztest/writeall_fuzzer/corpus/init b/test/fuzztest/writeall_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..6198079a28e860189d4294f6598f8ac6804c0dff --- /dev/null +++ b/test/fuzztest/writeall_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/test/fuzztest/writeall_fuzzer/project.xml b/test/fuzztest/writeall_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e35ed57fbc05fcaac3016839def9debdf5b9d74 --- /dev/null +++ b/test/fuzztest/writeall_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 100 + + 30 + + 2048 + + diff --git a/test/fuzztest/writeall_fuzzer/writeall_fuzzer.cpp b/test/fuzztest/writeall_fuzzer/writeall_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..682fc4a1efb8a7bb3c8f0475e59278cc752bf564 --- /dev/null +++ b/test/fuzztest/writeall_fuzzer/writeall_fuzzer.cpp @@ -0,0 +1,45 @@ +/* + * 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 +#include "init_utils.h" +#include "writeall_fuzzer.h" + +namespace OHOS { + bool FuzzGetParameterFromCmdLine(const uint8_t* data, size_t size) + { + CheckAndCreateDir("/data/init_fuzztest/FuzzTestData"); + int fd = open("/data/init_fuzztest/FuzzTestData", O_CREAT | O_RDWR, 0777); + if (fd < 0) { + return false; + } + std::string str(reinterpret_cast(data), size); + size_t ret = WriteAll(fd, str.c_str(), size); + if (ret == 0) { + close(fd); + return false; + }; + close(fd); + return true; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::FuzzGetParameterFromCmdLine(data, size); + return 0; +} \ No newline at end of file diff --git a/test/fuzztest/writeall_fuzzer/writeall_fuzzer.h b/test/fuzztest/writeall_fuzzer/writeall_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..99e441dbfb30742e8978112faa411762a40ad454 --- /dev/null +++ b/test/fuzztest/writeall_fuzzer/writeall_fuzzer.h @@ -0,0 +1,20 @@ +/* + * 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 TEST_FUZZTEST_GET_PARAMETER_FROM_CMD_LINE_FUZZER_H +#define TEST_FUZZTEST_GET_PARAMETER_FROM_CMD_LINE_FUZZER_H +#include "fuzz_utils.h" +#define FUZZ_PROJECT_NAME "writeall_fuzzer" +#endif diff --git a/test/mock/hvb/libhvb/auth/hvb.c b/test/mock/hvb/libhvb/auth/hvb.c new file mode 100644 index 0000000000000000000000000000000000000000..4cb62d3ca58aab40bddb35f408d7199374295a5b --- /dev/null +++ b/test/mock/hvb/libhvb/auth/hvb.c @@ -0,0 +1,64 @@ +/* + * 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 +#include +#include +#include "hvb.h" + +static struct hvb_cert_data g_testCert[1] = { + { + .partition_name = "boot", + .data = { + .addr = NULL, + .size = 0, + }, + .verify_result = HVB_OK, + }, +}; + +static struct hvb_verified_data g_testVd = { + .num_loaded_certs = 1, + .certs = &g_testCert[0], +}; + +enum hvb_errno hvb_chain_verify(struct hvb_ops *ops, const char *rvt_ptn, const char *const *hash_ptn_list, + struct hvb_verified_data **out_vd) +{ + char *verifyValue = getenv("VERIFY_VALUE"); + + printf("[Replace]:hvb_chain_verify in\n"); + + if ((verifyValue == NULL) || (strcmp(verifyValue, "Fail") == 0)) { + *out_vd = NULL; + return HVB_ERROR_INVALID_ARGUMENT; + } + if (strcmp(verifyValue, "PartFail") == 0) { + *out_vd = &g_testVd; + return HVB_ERROR_UNSUPPORTED_VERSION; + } + if (strcmp(verifyValue, "Succeed") == 0) { + *out_vd = &g_testVd; + return HVB_OK; + } + + return HVB_OK; +} + +void hvb_chain_verify_data_free(struct hvb_verified_data *vd) +{ + vd = NULL; + return; +} diff --git a/test/mock/hvb/libhvb/cert/hvb_cert.c b/test/mock/hvb/libhvb/cert/hvb_cert.c new file mode 100644 index 0000000000000000000000000000000000000000..3b6b7a1dc5649b4e8a3913971dd316eb863f7b98 --- /dev/null +++ b/test/mock/hvb/libhvb/cert/hvb_cert.c @@ -0,0 +1,33 @@ +/* + * 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 "hvb_cert.h" + +#define BLOCK_SIZE 4096 + +enum hvb_errno hvb_cert_parser(struct hvb_cert *cert, struct hvb_buf *cert_buf) +{ + cert->version_major = 0; + cert->version_minor = 0; + cert->image_original_len = BLOCK_SIZE; + cert->image_len = BLOCK_SIZE; + cert->rollback_location = 1; + cert->rollback_index = 0; + cert->verity_type = HVB_IMAGE_TYPE_HASHTREE; + cert->hash_algo = 0; + cert->data_block_size = BLOCK_SIZE; + cert->hash_block_size = BLOCK_SIZE; + return 0; +} \ No newline at end of file diff --git a/test/mock/hvb/libhvb/crypto/hvb_hash_sha256.c b/test/mock/hvb/libhvb/crypto/hvb_hash_sha256.c new file mode 100644 index 0000000000000000000000000000000000000000..c30cbbe077c698132cb06826b4ef248ffa782a19 --- /dev/null +++ b/test/mock/hvb/libhvb/crypto/hvb_hash_sha256.c @@ -0,0 +1,59 @@ +/* + * 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 +#include +#include +#include "hvb_crypto.h" + +int hash_ctx_init(struct hash_ctx_t *hash_ctx, enum hash_alg_type alg_type) +{ + char *hashValue = getenv("HASH_VALUE"); + + printf("[Replace]:hash_ctx_init in\n"); + + if ((hashValue == NULL) || (strcmp(hashValue, "InitFail") == 0)) { + return -1; + } + + return 0; +} + +int hash_calc_update(struct hash_ctx_t *hash_ctx, const void *msg, uint32_t msg_len) +{ + char *hashValue = getenv("HASH_VALUE"); + + printf("[Replace]:hash_calc_update in\n"); + + if ((hashValue == NULL) || (strcmp(hashValue, "UpdateFail") == 0)) { + return -1; + } + + return 0; +} + +int hash_calc_do_final(struct hash_ctx_t *hash_ctx, const void *msg, uint32_t msg_len, uint8_t *out, uint32_t out_len) +{ + char *hashValue = getenv("HASH_VALUE"); + + printf("[Replace]:hash_calc_do_final in\n"); + + if ((hashValue == NULL) || (strcmp(hashValue, "FinalFail") == 0)) { + return -1; + } + + out[0] = 1; + return 0; +} diff --git a/test/mock/hvb/libhvb/crypto/hvb_sm3.c b/test/mock/hvb/libhvb/crypto/hvb_sm3.c new file mode 100644 index 0000000000000000000000000000000000000000..c96979ec614efb3be6d7d6fc7da19bf0ed2abfdc --- /dev/null +++ b/test/mock/hvb/libhvb/crypto/hvb_sm3.c @@ -0,0 +1,64 @@ +/* + * 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 __HVB_SM3_H__ +#define __HVB_SM3_H__ + +#include +#include +#include +#include "hvb_sm3.h" + +int hvb_sm3_init(struct sm3_ctx_t *hash_ctx) +{ + char *hashValue = getenv("HASH_VALUE"); + + printf("[Replace]:hvb_sm3_init in\n"); + + if ((hashValue == NULL) || (strcmp(hashValue, "InitFail") == 0)) { + return -1; + } + + return SM3_OK; +} + +int hvb_sm3_update(struct sm3_ctx_t *hash_ctx, const void *msg, uint32_t msg_len) +{ + char *hashValue = getenv("HASH_VALUE"); + + printf("[Replace]:hvb_sm3_update in\n"); + + if ((hashValue == NULL) || (strcmp(hashValue, "UpdateFail") == 0)) { + return -1; + } + + return SM3_OK; +} + +int hvb_sm3_final(struct sm3_ctx_t *hash_ctx, uint8_t *out, uint32_t *out_len) +{ + char *hashValue = getenv("HASH_VALUE"); + + printf("[Replace]:hvb_sm3_final in\n"); + + if ((hashValue == NULL) || (strcmp(hashValue, "FinalFail") == 0)) { + return -1; + } + + out[0] = 1; + return SM3_OK; +} + +#endif diff --git a/test/mock/init/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c b/test/mock/init/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c new file mode 100644 index 0000000000000000000000000000000000000000..fa99ba2029cc162de921673590589a4e698ccce0 --- /dev/null +++ b/test/mock/init/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c @@ -0,0 +1,55 @@ +/* + * 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 +#include +#include +#include "fs_dm.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int FsDmInitDmDev(char *devPath, bool useSocket) +{ + char *initValue = getenv("FSDM_VALUE"); + printf("[Replace]:FsDmInitDmDev in\n"); + + if ((initValue == NULL) || (strcmp(initValue, "InitFail") == 0)) { + return -1; + } + + return 0; +} + +int FsDmCreateDevice(char **dmDevPath, const char *devName, DmVerityTarget *target) +{ + char *createValue = getenv("FSDM_VALUE"); + + printf("[Replace]:FsDmCreateDevice in\n"); + + if ((createValue == NULL) || (strcmp(createValue, "CreateFail") == 0)) { + return -1; + } + + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/mock/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c b/test/mock/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c new file mode 100644 index 0000000000000000000000000000000000000000..dc963795acd5f2ba1df58eb8a244addeb7f71080 --- /dev/null +++ b/test/mock/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c @@ -0,0 +1,98 @@ +/* + * 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 "fs_hvb.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int FsHvbGetValueFromCmdLine(char *val, size_t size, const char *key) +{ + char *swtypeValue = getenv("SWTYPE_VALUE"); + char *enableValue = getenv("ENABLE_VALUE"); + errno_t err; + + printf("[Replace]:FsHvbGetValueFromCmdLine in\n"); + + if (strcmp(key, "ohos.boot.hvb.oem_swtype") == 0) { + if (swtypeValue == NULL) { + return -1; + } + + err = memcpy_s(val, size, swtypeValue, strlen(swtypeValue)); + if (err != EOK) { + return -1; + } + return 0; + } + + if (strcmp(key, "ohos.boot.hvb.enable") == 0) { + if (enableValue == NULL) { + return -1; + } + + err = memcpy_s(val, size, enableValue, strlen(enableValue)); + if (err != EOK) { + return -1; + } + return 0; + } + + return 0; +} + +int FsHvbInit(InitHvbType hvbType) +{ + char *initValue = getenv("INIT_VALUE"); + printf("[Replace]:FsHvbInit in\n"); + + if (!initValue) { + return -1; + } + + return 0; +} + +int FsHvbFinal(InitHvbType hvbType) +{ + char *finalValue = getenv("FINAL_VALUE"); + printf("[Replace]:FsHvbFinal in\n"); + + if (!finalValue) { + return -1; + } + + return 0; +} + +int FsHvbSetupHashtree(FstabItem *fsItem) +{ + char *hashValue = getenv("HASH_VALUE"); + printf("[Replace]:FsHvbSetupHashtree in\n"); + + if (!hashValue) { + return -1; + } + + return 0; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/mock/init/ueventd/ueventd.c b/test/mock/init/ueventd/ueventd.c new file mode 100644 index 0000000000000000000000000000000000000000..2ce07268290f76444e474d6ce29dbe689e007e60 --- /dev/null +++ b/test/mock/init/ueventd/ueventd.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 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. + */ + +void RetriggerUeventByPath(int sockFd, char *path) +{ + return; +} \ No newline at end of file diff --git a/test/mock/init/ueventd/ueventd_socket.c b/test/mock/init/ueventd/ueventd_socket.c new file mode 100644 index 0000000000000000000000000000000000000000..9e4c7ceb28f9b20ad92de3e8400915e4c0f484af --- /dev/null +++ b/test/mock/init/ueventd/ueventd_socket.c @@ -0,0 +1,19 @@ +/* + * 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. + */ + +int UeventdSocketInit(void) +{ + return 0; +} diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..23f9c3c6824ebac12958d2b4a4ecf6394b73f001 --- /dev/null +++ b/test/moduletest/BUILD.gn @@ -0,0 +1,97 @@ +# Copyright (c) 2020-2021 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/begetd.gni") +import("//build/ohos.gni") +import("//build/test.gni") + +ohos_shared_library("libparamtestmodule") { + sources = [ "param_test_module.c" ] + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/param/include", + "//base/startup/init/ueventd/include", + "//base/startup/init/device_info", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbegetutil", + "//base/startup/init/interfaces/innerkits/init_module_engine:libinit_module_engine", + "//base/startup/init/services/log:agent_log", + ] + external_deps = [ + "bounds_checking_function:libsec_shared", + "cJSON:cjson", + ] + + part_name = "init" + subsystem_name = "startup" + module_install_dir = "lib/init" +} + +ohos_moduletest("InitModuleTest") { + module_out_path = "init/init" + + sources = [ + "hookmgr_moduletest.cpp", + "modulemgr_moduletest.cpp", + "service_control_test.cpp", + "service_watcher_moduleTest.cpp", + "syspara_moduleTest.cpp", + "test_utils.cpp", + ] + + if (enable_ohos_startup_init_feature_deviceinfo) { + sources += [ "deviceinfo_moduleTest.cpp" ] + } + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/syspara", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/param/include", + "//base/startup/init/device_info", + ".", + ] + + deps = [ + "//base/startup/init/interfaces/innerkits:libbeget_proxy", + "//base/startup/init/interfaces/innerkits:libbegetutil", + ] + + external_deps = [ + "bounds_checking_function:libsec_shared", + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog_base", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] +} + +group("moduletest") { + testonly = true + deps = [ ":InitModuleTest" ] +} + +group("paramtestmodule") { + if (param_test) { + deps = [ ":libparamtestmodule" ] + } +} diff --git a/test/moduletest/chipset.init.test.cfg b/test/moduletest/chipset.init.test.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0e8c5b8cbf4bedfb6bcafecbc452d5ddc8fbb843 --- /dev/null +++ b/test/moduletest/chipset.init.test.cfg @@ -0,0 +1,48 @@ +{ + "jobs" : [{ + "name" : "param:test.randrom.read.start=1", + "condition" : "test.randrom.read.start=1", + "cmds" : [ + "param_randrom_write test.randrom.read 100", + "mkdir /data/test_verdor_init 0711 root root", + "write /data/test_verdor_init/test.txt 1", + "ifup lo", + "hostname localhost", + "domainname localdomain", + "symlink /data/test_verdor_init/test.txt /data/test_verdor_init/test_link.txt", + "chmod 0666 /data/test_verdor_init/test.txt", + "chown shell shell /data/test_verdor_init/test.txt", + "symlink /data/test_verdor_init/test.txt /data/test_verdor_init/test_link2.txt", + "copy /data/test_verdor_init/test.txt /data/test_verdor_init/test2.txt", + "wait /data/test_verdor_init/test.txt3 1", + "start group-test-stage1" + ] + }, + { + "name" : "param:test.randrom.read.start=rm", + "condition" : "test.randrom.read.start=rm", + "cmds" : [ + "rm /data/test_verdor_init/test.txt ", + "rm /data/test_verdor_init/test2.txt", + "rmdir /data/test_verdor_init 0711 root root" + ] + }, + { + "name" : "test_verdor_init_job", + "cmds" : [ + "param_randrom_write test.randrom.read 200", + "mkdir /data/test_verdor_init_2 0711 root root" + ] + } + ], + "services" : [{ + "name" : "group-test-stage1", + "start-mode" : "normal", + "path" : ["/system/bin/begetctl", "init", "group", "test", "group-test-stage1"], + "once" : 1, + "jobs" : { + "on-start" : "test_verdor_init_job" + } + } + ] +} diff --git a/test/moduletest/deviceinfo_moduleTest.cpp b/test/moduletest/deviceinfo_moduleTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5346820e68f24e092411337b940c6a9012ad73c --- /dev/null +++ b/test/moduletest/deviceinfo_moduleTest.cpp @@ -0,0 +1,90 @@ +/* + * 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 "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "idevice_info.h" +#include "parameter.h" +#include "system_ability_definition.h" +#include "sysparam_errno.h" + +using namespace std; +using namespace testing::ext; +using namespace OHOS; + +namespace initModuleTest { +class DeviceInfoModuleTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(DeviceInfoModuleTest, DeviceInfoGetUdid_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "DeviceInfoGetUdid_001 start"; + char udid[65] = {}; // 65 udid len + int ret = AclGetDevUdid(udid, sizeof(udid)); + EXPECT_EQ(ret, SYSPARAM_PERMISSION_DENIED); + + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + BEGET_ERROR_CHECK(samgr != nullptr, return, "Get samgr failed"); + sptr object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + BEGET_ERROR_CHECK(object != nullptr, return, "Get deviceinfo manager object from samgr failed"); + + std::this_thread::sleep_for(std::chrono::seconds(20)); // wait sa died 20s + + object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + BEGET_ERROR_CHECK(object == nullptr, return, "Get deviceinfo manager object from samgr failed"); + + ret = AclGetDevUdid(udid, sizeof(udid)); + EXPECT_EQ(ret, SYSPARAM_PERMISSION_DENIED); + + object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + BEGET_ERROR_CHECK(object != nullptr, return, "Get deviceinfo manager object from samgr failed"); + + GTEST_LOG_(INFO) << "DeviceInfoGetUdid_001 end"; +} + +HWTEST_F(DeviceInfoModuleTest, DeviceInfoGetSerial_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "DeviceInfoGetSerial_001 start"; + const char *serial = AclGetSerial(); + EXPECT_EQ(serial != nullptr, 1); + + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + BEGET_ERROR_CHECK(samgr != nullptr, return, "Get samgr failed"); + sptr object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + BEGET_ERROR_CHECK(object != nullptr, return, "Get deviceinfo manager object from samgr failed"); + + std::this_thread::sleep_for(std::chrono::seconds(20)); // wait sa died 20s + + object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + BEGET_ERROR_CHECK(object == nullptr, return, "Get deviceinfo manager object from samgr failed"); + + serial = AclGetSerial(); + EXPECT_EQ(serial != nullptr, 1); + + object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + BEGET_ERROR_CHECK(object != nullptr, return, "Get deviceinfo manager object from samgr failed"); + + GTEST_LOG_(INFO) << "DeviceInfoGetSerial_001 end"; +} +} \ No newline at end of file diff --git a/test/moduletest/hookmgr_moduletest.cpp b/test/moduletest/hookmgr_moduletest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a72ac02c419edca04a9eca16d6e1930038be8d9f --- /dev/null +++ b/test/moduletest/hookmgr_moduletest.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 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 "hookmgr.h" +using namespace testing::ext; +using namespace std; + +namespace initModuleTest { +#define STAGE_TEST_ONE 0 +int g_publicData = 0; +mutex g_mutex; +HOOK_MGR *g_hookMgr = nullptr; +class HookMgrModuleTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +struct HookExecCtx { + int result; + int retErr; +}; + +void HookExecFunc(int n) +{ + for (int i = 0; i < n; ++i) { + HookMgrExecute(g_hookMgr, STAGE_TEST_ONE, nullptr, nullptr); + } +} + +static int OhosTestHookMultiThread(const HOOK_INFO *hookInfo, void *executionContext) +{ + lock_guard lg(g_mutex); + g_publicData++; + return 0; +} + +static int OhosTestHookMultiThreadAnother(const HOOK_INFO *hookInfo, void *executionContext) +{ + lock_guard lg(g_mutex); + g_publicData++; + return -1; +} + +static void OhosHookPrint(const HOOK_INFO *hookInfo, void *traversalCookie) +{ + printf("\tstage[%02d] prio[%02d].\n", hookInfo->stage, hookInfo->prio); +} + +static void DumpAllHooks(HOOK_MGR *hookMgr) +{ + printf("----------All Hooks---------------\n"); + HookMgrTraversal(hookMgr, NULL, OhosHookPrint); + printf("----------------------------------\n\n"); +} + +HWTEST_F(HookMgrModuleTest, HookMgrModuleTest, TestSize.Level1) +{ + int ret; + int cnt; + g_hookMgr = HookMgrCreate("moduleTestHook"); + ASSERT_NE(g_hookMgr, nullptr); + + ret = HookMgrAdd(g_hookMgr, STAGE_TEST_ONE, 0, OhosTestHookMultiThread); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + + HOOK_INFO info; + info.stage = STAGE_TEST_ONE; + info.prio = 1; + info.hook = OhosTestHookMultiThreadAnother; + info.hookCookie = nullptr; + HookMgrAddEx(g_hookMgr, &info); + cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 2); + cnt = HookMgrGetStagesCnt(g_hookMgr); + EXPECT_EQ(cnt, 1); + DumpAllHooks(g_hookMgr); + + // test multiThread HookMgrExecute + std::vector threads; + for (int i = 1; i <= 10; ++i) { + threads.push_back(std::thread(HookExecFunc, 10)); + } + for (auto & th : threads) { + th.join(); + } + EXPECT_EQ(g_publicData, 200); + + HookMgrAdd(g_hookMgr, STAGE_TEST_ONE, 1, OhosTestHookMultiThreadAnother); + cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 2); + + HookMgrDel(g_hookMgr, STAGE_TEST_ONE, OhosTestHookMultiThreadAnother); + cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + HookMgrDestroy(g_hookMgr); +} + +} // namespace init_ut diff --git a/test/moduletest/init_test.cfg b/test/moduletest/init_test.cfg new file mode 100755 index 0000000000000000000000000000000000000000..1ec228f617567645b7258b109bbf1d871f76b763 --- /dev/null +++ b/test/moduletest/init_test.cfg @@ -0,0 +1,49 @@ +{ + "jobs" : [{ + "name" : "param:test.randrom.read.start=1", + "condition" : "test.randrom.read.start=1", + "cmds" : [ + "param_randrom_write test.randrom.read 100" + ] + }, + { + "name" : "param:startup.service.ctl.group-test-stage1=2", + "condition" : "startup.service.ctl.group-test-stage1=2", + "cmds" : [ + "start group-test-stage2" + ] + }, + { + "name" : "param:startup.service.ctl.group-test-stage2=2", + "condition" : "startup.service.ctl.group-test-stage2=2", + "cmds" : [ + "start group-test-stage3" + ] + } + ], + "services" : [{ + "name" : "group-test-stage1", + "start-mode" : "normal", + "path" : ["/system/bin/begetctl", "init", "group", "test", "group-test-stage1"], + "once" : 1 + }, + { + "name" : "group-test-stage2", + "start-mode" : "condition", + "path" : ["/system/bin/begetctl", "init", "group", "test", "group-test-stage2"], + "once" : 1 + }, + { + "name" : "group-test-stage3", + "start-mode" : "condition", + "path" : ["/system/bin/begetctl", "init", "group", "test", "wait", "group-test-stage4"], + "once" : 1 + }, + { + "name" : "group-test-stage4", + "start-mode" : "condition", + "path" : ["/system/bin/begetctl", "init", "group", "test", "group-test-stage4"], + "once" : 1 + } + ] +} diff --git a/test/moduletest/modulemgr_moduletest.cpp b/test/moduletest/modulemgr_moduletest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7aad7855dce01612dc2f15adb50e543b3dd48b2 --- /dev/null +++ b/test/moduletest/modulemgr_moduletest.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 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 "modulemgr.h" + +using namespace testing::ext; +using namespace std; + +namespace initModuleTest { +class ModuleMgrModuleTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +static void TestModuleDump(const MODULE_INFO *moduleInfo) +{ + printf("%s\n", moduleInfo->name); +} + +HWTEST_F(ModuleMgrModuleTest, ModuleMrgTest, TestSize.Level1) +{ + int cnt; + MODULE_MGR *moduleMgr = nullptr; + moduleMgr = ModuleMgrCreate("init"); + + // Install one module + ModuleMgrInstall(moduleMgr, "bootchart", 0, NULL); + ModuleMgrDestroy(moduleMgr); + + // Scan all modules + moduleMgr = ModuleMgrScan("init"); + ASSERT_NE(moduleMgr, nullptr); + + ModuleMgrTraversal(moduleMgr, NULL, TestModuleDump); + + ModuleMgrUninstall(moduleMgr, NULL); + cnt = ModuleMgrGetCnt(moduleMgr); + EXPECT_EQ(cnt, 0); + ModuleMgrGetArgs(); + ModuleMgrDestroy(moduleMgr); +} +} // namespace init_ut diff --git a/test/moduletest/param_test_cmds.c b/test/moduletest/param_test_cmds.c new file mode 100644 index 0000000000000000000000000000000000000000..447c55660b2a397c2ad0fbcd83d5ab15d9de33e4 --- /dev/null +++ b/test/moduletest/param_test_cmds.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2021 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 "begetctl.h" +#include "init_param.h" +#include "param_init.h" +#include "init_utils.h" +#include "loop_event.h" +#include "parameter.h" +#include "plugin_test.h" +#include "service_watcher.h" +#include "parameter.h" +#include "param_base.h" + +#define MAX_THREAD_NUMBER 100 +#define MAX_NUMBER 10 +#define READ_DURATION 100000 +#define CMD_INDEX 2 + +static char *GetLocalBuffer(uint32_t *buffSize) +{ + static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0}; + if (buffSize != NULL) { + *buffSize = sizeof(buffer); + } + return buffer; +} + +int g_stop = 0; +static void *CmdReader(void *args) +{ + (void)srand((unsigned)time(NULL)); + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + while (g_stop == 0) { + int wait = READ_DURATION + READ_DURATION; // 100ms rand + uint32_t size = buffSize; + int ret = SystemGetParameter("test.randrom.read", buffer, &size); + if (ret == 0) { + printf("SystemGetParameter value %s %d \n", buffer, wait); + } else { + printf("SystemGetParameter fail %d \n", wait); + } + usleep(wait); + } + return NULL; +} + +static int32_t BShellParamCmdRead(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); + static pthread_t thread = 0; + PLUGIN_LOGV("BShellParamCmdWatch %s, threadId %d", argv[1], thread); + if (strcmp(argv[1], "start") == 0) { + if (thread != 0) { + return 0; + } + SystemSetParameter("test.randrom.read.start", "1"); + pthread_create(&thread, NULL, CmdReader, argv[1]); + } else if (strcmp(argv[1], "stop") == 0) { + if (thread == 0) { + return 0; + } + SystemSetParameter("test.randrom.read.start", "0"); + g_stop = 1; + pthread_join(thread, NULL); + thread = 0; + } + return 0; +} + +typedef struct { + char name[PARAM_NAME_LEN_MAX]; + pthread_t thread; +} TestWatchContext; + +static void HandleParamChange2(const char *key, const char *value, void *context) +{ + PLUGIN_CHECK(key != NULL && value != NULL, return, "Invalid parameter"); + long long commit = GetSystemCommitId(); + size_t index = (size_t)context; + printf("[%zu] Receive parameter commit %lld change %s %s \n", index, commit, key, value); + static int addWatcher = 0; + int ret = 0; + if ((index == 4) && !addWatcher) { // 4 when context == 4 add + index = 5; // 5 add context + ret = SystemWatchParameter(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Add watcher %s fail %zu \n", key, index); + } + addWatcher = 1; + return; + } + if (index == 2) { // 2 when context == 2 delete 3 + index = 3; // 3 delete context + RemoveParameterWatcher(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Remove watcher fail %zu \n", index); + } + return; + } + if (index == 1) { // 1 when context == 1 delete 1 + RemoveParameterWatcher(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Remove watcher fail %zu \n", index); + } + return; + } + if ((index == 5) && (addWatcher == 1)) { // 5 when context == 5 delete 5 + RemoveParameterWatcher(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Remove watcher fail %zu \n", index); + } + addWatcher = 0; + } +} + +static void HandleParamChange1(const char *key, const char *value, void *context) +{ + PLUGIN_CHECK(key != NULL && value != NULL, return, "Invalid parameter"); + long long commit = GetSystemCommitId(); + size_t index = (size_t)context; + printf("[%zu] Receive parameter commit %lld change %s %s \n", index, commit, key, value); +} + +static void *CmdThreadWatcher(void *args) +{ + TestWatchContext *context = (TestWatchContext *)args; + for (size_t i = 1; i <= MAX_NUMBER; i++) { + int ret = SystemWatchParameter(context->name, HandleParamChange2, (void *)i); + if (ret != 0) { + printf("Add watcher %s fail %zu \n", context->name, i); + } + ret = SetParameter(context->name, context->name); + if (ret != 0) { + printf("Set parameter %s fail %zu \n", context->name, i); + } + } + sleep(1); + for (size_t i = 1; i <= MAX_NUMBER; i++) { + int ret = RemoveParameterWatcher(context->name, HandleParamChange2, (void *)i); + if (ret != 0) { + printf("Remove watcher %s fail %zu \n", context->name, i); + } + } + free(context); + return NULL; +} + +static void StartWatcherInThread(const char *prefix) +{ + TestWatchContext *context[MAX_THREAD_NUMBER] = { NULL }; + for (size_t i = 0; i < MAX_THREAD_NUMBER; i++) { + context[i] = calloc(1, sizeof(TestWatchContext)); + PLUGIN_CHECK(context[i] != NULL, return, "Failed to alloc context"); + int len = sprintf_s(context[i]->name, sizeof(context[i]->name), "%s.%zu", prefix, i); + if (len > 0) { + printf("Add watcher %s \n", context[i]->name); + pthread_create(&context[i]->thread, NULL, CmdThreadWatcher, context[i]); + } + } +} + +static void StartWatcher(const char *prefix) +{ + static size_t index = 0; + int ret = SystemWatchParameter(prefix, HandleParamChange1, (void *)index); + if (ret != 0) { + printf("Add watcher %s fail \n", prefix); + return; + } + index++; +} + +static int32_t BShellParamCmdWatch(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGV("BShellParamCmdWatch %s", argv[1]); + StartWatcher(argv[1]); + + if (argc <= CMD_INDEX) { + return 0; + } + if (strcmp(argv[CMD_INDEX], "thread") == 0) { // 2 cmd index + StartWatcherInThread(argv[1]); + return 0; + } + + int maxCount = StringToInt(argv[CMD_INDEX], -1); // 2 cmd index + if (maxCount <= 0 || maxCount > 65535) { // 65535 max count + PLUGIN_LOGE("Invalid input %s", argv[CMD_INDEX]); + return 0; + } + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + size_t count = 0; + while (count < (size_t)maxCount) { // 100 max count + int len = sprintf_s(buffer, buffSize, "%s.%zu", argv[1], count); + PLUGIN_CHECK(len > 0, return -1, "Invalid buffer"); + buffer[len] = '\0'; + StartWatcher(buffer); + count++; + } + return 0; +} + +static int32_t BShellParamCmdInstall(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGV("BShellParamCmdInstall %s %s", argv[0], argv[1]); + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + int ret = sprintf_s(buffer, buffSize, "ohos.servicectrl.%s", argv[0]); + PLUGIN_CHECK(ret > 0, return -1, "Invalid buffer"); + buffer[ret] = '\0'; + SystemSetParameter(buffer, argv[1]); + return 0; +} + +static int32_t BShellParamCmdDisplay(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGV("BShellParamCmdDisplay %s %s", argv[0], argv[1]); + SystemSetParameter("ohos.servicectrl.display", argv[1]); + return 0; +} + +void ServiceStatusChangeTest(const char *key, const ServiceInfo *status) +{ + PLUGIN_LOGI("group-test-stage3: wait service %s status: %d", key, status->status); + if (status->status == SERVICE_READY || status->status == SERVICE_STARTED) { + PLUGIN_LOGI("Service %s start work", key); + } +} + +static int32_t BShellParamCmdGroupTest(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGI("BShellParamCmdGroupTest %s stage: %s", argv[0], argv[1]); + if (argc > 2 && strcmp(argv[1], "wait") == 0) { // 2 service name index + PLUGIN_LOGI("group-test-stage3: wait service %s", argv[2]); // 2 service name index + ServiceWatchForStatus(argv[2], ServiceStatusChangeTest); // 2 service name index + LE_RunLoop(LE_GetDefaultLoop()); + LE_CloseLoop(LE_GetDefaultLoop()); + } + return 0; +} + +static int32_t BShellParamCmdUdidGet(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); + PLUGIN_LOGI("BShellParamCmdUdidGet "); + char localDeviceId[65] = {0}; // 65 udid len + AclGetDevUdid(localDeviceId, 65); // 65 udid len + BShellEnvOutput(shell, " udid: %s\r\n", localDeviceId); + return 0; +} + +static int CalcValue(const char *value) +{ + char *begin = (char *)value; + while (*begin != '\0') { + if (*begin == ' ') { + begin++; + } else { + break; + } + } + char *end = begin + strlen(begin); + while (end > begin) { + if (*end > '9' || *end < '0') { + *end = '\0'; + } + end--; + } + return StringToInt(begin, -1); +} + +static int32_t BShellParamCmdMemGet(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); + uint32_t buffSize = 0; // 1024 max buffer for decode + char *buff = GetLocalBuffer(&buffSize); + PLUGIN_CHECK(buff != NULL, return -1, "Failed to get local buffer"); + int ret = sprintf_s(buff, buffSize - 1, "/proc/%s/smaps", argv[1]); + PLUGIN_CHECK(ret > 0, return -1, "Failed to format path %s", argv[1]); + buff[ret] = '\0'; + char *realPath = GetRealPath(buff); + PLUGIN_CHECK(realPath != NULL, return -1, "Failed to get real path"); + int all = 0; + if (argc > 2 && strcmp(argv[2], "all") == 0) { // 2 2 max arg + all = 1; + } + FILE *fp = fopen(realPath, "r"); + free(realPath); + int value = 0; + while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { + buff[buffSize - 1] = '\0'; + if (strncmp(buff, "Pss:", strlen("Pss:")) == 0) { + int v = CalcValue(buff + strlen("Pss:")); + if (all) { + printf("Pss: %d kb\n", v); + } + value += v; + } else if (strncmp(buff, "SwapPss:", strlen("SwapPss:")) == 0) { + int v = CalcValue(buff + strlen("SwapPss:")); + if (all) { + printf("SwapPss: %d kb\n", v); + } + value += v; + } + } + if (fp != NULL) { + fclose(fp); + printf("Total mem %d kb\n", value); + } else { + printf("Failed to get memory for %s %s \n", argv[1], buff); + } + return 0; +} + +void CmdServiceStatusChange(const char *key, const ServiceInfo *status) +{ + static const char *serviceStatusMap[] = { + "idle", + "starting", + "running", + "ready", + "stopping", + "stopped", + "error", + "suspended", + "freezed", + "disabled", + "critical", + }; + PLUGIN_CHECK(key != NULL && status != NULL, return, "Invalid parameter"); + if (status->status == SERVICE_STARTED || status->status == SERVICE_READY) { + printf("Service %s status: %s pid %d \n", key, + ((status->status < ARRAY_LENGTH(serviceStatusMap)) ? serviceStatusMap[status->status] : "unknown"), + status->pid); + } else { + printf("Service %s status: %s \n", key, + (status->status < ARRAY_LENGTH(serviceStatusMap)) ? serviceStatusMap[status->status] : "unknown"); + } +} + +static int32_t BShellParamCmdWatchService(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); + return ServiceWatchForStatus(argv[1], CmdServiceStatusChange); +} + +int32_t BShellCmdRegister(BShellHandle shell, int execMode) +{ + if (execMode == 0) { + const CmdInfo infos[] = { + {"init", BShellParamCmdGroupTest, "init group test", "init group test [stage]", "init group test"}, + {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(shell, &infos[i]); + } + } else { + const CmdInfo infos[] = { + {"display", BShellParamCmdDisplay, "display system service", "display service", "display service"}, + {"read", BShellParamCmdRead, "read system parameter", "read [start | stop]", ""}, + {"watcher", BShellParamCmdWatch, + "watcher system parameter", "watcher parameter [name]", "watcher parameter"}, + {"install", BShellParamCmdInstall, "install plugin", "install [name]", ""}, + {"uninstall", BShellParamCmdInstall, "uninstall plugin", "uninstall [name]", ""}, + {"group", BShellParamCmdGroupTest, "group test", "group test [stage]", "group test"}, + {"display", BShellParamCmdUdidGet, "display udid", "display udid", "display udid"}, + {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, + {"watcher", BShellParamCmdWatchService, + "watcher service status", "watcher service [name]", "watcher service"}, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } + } + return 0; +} diff --git a/test/moduletest/param_test_module.c b/test/moduletest/param_test_module.c new file mode 100644 index 0000000000000000000000000000000000000000..f25c2d972760111909ad820b66937b9d3b8d7ae5 --- /dev/null +++ b/test/moduletest/param_test_module.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 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 "init_param.h" +#include "modulemgr.h" +#include "init_module_engine.h" +#include "init_cmds.h" +#include "securec.h" + +#define MAX_COUNT 1 +#define TEST_CMD_NAME "param_randrom_write" + +#define READ_DURATION 100000 + +static int g_testCmdIndex = 0; +static int PluginParamCmdWriteParam(int id, const char *name, int argc, const char **argv) +{ + if ((argv == NULL) || (argc < 1)) { + return -1; + } + int maxCount = MAX_COUNT; + if (argc > 1) { + maxCount = atoi(argv[1]); + } + (void)srand((unsigned)time(NULL)); + char buffer[32] = { 0 }; // 32 buffer size + int count = 0; + while (count < maxCount) { + const int wait = READ_DURATION + READ_DURATION; // 100ms + int ret = sprintf_s(buffer, sizeof(buffer), "%d", count); + if (ret > 0) { + SystemWriteParam(argv[0], buffer); + usleep(wait); + } + count++; + } + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + g_testCmdIndex = AddCareContextCmdExecutor(TEST_CMD_NAME, PluginParamCmdWriteParam); +} + +MODULE_DESTRUCTOR(void) +{ + RemoveCmdExecutor(TEST_CMD_NAME, g_testCmdIndex); +} diff --git a/test/moduletest/plugin_param_test.cfg b/test/moduletest/plugin_param_test.cfg new file mode 100755 index 0000000000000000000000000000000000000000..2623a9d36ae4b0878a38f982cf7160e1979cbf78 --- /dev/null +++ b/test/moduletest/plugin_param_test.cfg @@ -0,0 +1,9 @@ +{ + "jobs" : [{ + "name" : "param:test.randrom.read.start=1", + "condition" : "test.randrom.read.start=1", + "cmds" : [ + "param_randrom_write test.randrom.read 100" + ] + }] +} diff --git a/test/moduletest/plugin_test.h b/test/moduletest/plugin_test.h new file mode 100644 index 0000000000000000000000000000000000000000..5b8b852c790d3130161d467eefd4505bc4b5490a --- /dev/null +++ b/test/moduletest/plugin_test.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 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 PLUGIN_TEST_ +#define PLUGIN_TEST_ +#include +#include +#include + +#include "init_log.h" +#include "securec.h" + +#ifndef PLUGIN_DOMAIN +#define PLUGIN_DOMAIN (BASE_DOMAIN + 7) +#endif +#define READ_DURATION 100000 +#define PLUGIN_LABEL "PLUGIN" +#define PLUGIN_LOGI(fmt, ...) STARTUP_LOGI(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) +#define PLUGIN_LOGE(fmt, ...) STARTUP_LOGE(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) +#define PLUGIN_LOGV(fmt, ...) STARTUP_LOGV(PLUGIN_DOMAIN, PLUGIN_LABEL, fmt, ##__VA_ARGS__) + +#define PLUGIN_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + PLUGIN_LOGE(__VA_ARGS__); \ + exper; \ + } +#define PLUGIN_ONLY_CHECK(ret, exper, ...) \ + if (!(ret)) { \ + exper; \ + } +#endif diff --git a/test/moduletest/service_control_test.cpp b/test/moduletest/service_control_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c978529f083db8e8beec6d0f02d1bdd75f079ce --- /dev/null +++ b/test/moduletest/service_control_test.cpp @@ -0,0 +1,270 @@ +/* + * 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 "service_control.h" +#include "beget_ext.h" +#include "test_utils.h" + +using namespace testing::ext; +namespace initModuleTest { +namespace { +// Default wait for service status change time is 10 seconds +constexpr int WAIT_SERVICE_STATUS_TIMEOUT = 10; +} + +class ServiceControlTest : public testing::Test { +public: + static void SetUpTestCase() {}; + static void TearDownTestCase() {}; + void SetUp() {}; + void TearDown() {}; +}; + +// Test service start +HWTEST_F(ServiceControlTest, ServiceStartTest, TestSize.Level1) +{ + // Pick an unusual service for testing + // Try to start media_service. + + // 1) Check if media_service exist + std::string serviceName = "media_service"; + auto status = GetServiceStatus(serviceName); + if (status == "running") { + int ret = ServiceControl(serviceName.c_str(), STOP); + ASSERT_EQ(ret, 0); + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STOPPED, WAIT_SERVICE_STATUS_TIMEOUT); + ASSERT_EQ(ret, 0); + } else if (status != "created" && status != "stopped") { + std::cout << serviceName << " in invalid status " << status << std::endl; + std::cout << "Debug " << serviceName << " in unexpected status " << status << std::endl; + ASSERT_TRUE(0); + } + + // 2) Now try to start service + int ret = ServiceControl(serviceName.c_str(), START); + EXPECT_EQ(ret, 0); + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STARTED, WAIT_SERVICE_STATUS_TIMEOUT); + EXPECT_EQ(ret, 0); + status = GetServiceStatus(serviceName); + std::cout << "Debug " << serviceName << " in status " << status << std::endl; + EXPECT_TRUE(status == "running"); +} + +HWTEST_F(ServiceControlTest, NonExistServiceStartTest, TestSize.Level1) +{ + std::string serviceName = "non_exist_service"; + int ret = ServiceControl(serviceName.c_str(), START); + EXPECT_EQ(ret, 0); // No matter if service exist or not, ServiceControl always success. + + auto status = GetServiceStatus(serviceName); + EXPECT_TRUE(status == "idle"); +} + +HWTEST_F(ServiceControlTest, ServiceStopTest, TestSize.Level1) +{ + std::string serviceName = "media_service"; + auto status = GetServiceStatus(serviceName); + if (status == "stopped" || status == "created") { + int ret = ServiceControl(serviceName.c_str(), START); + ASSERT_EQ(ret, 0); // start must be success + + } else if (status != "running") { + std::cout << serviceName << " in invalid status " << status << std::endl; + ASSERT_TRUE(0); + } + + int ret = ServiceControl(serviceName.c_str(), STOP); + EXPECT_EQ(ret, 0); + // Sleep for a while, let init handle service starting. + const int64_t ms = 500; + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + status = GetServiceStatus(serviceName); + bool isStopped = status == "stopped"; + EXPECT_TRUE(isStopped); +} + +HWTEST_F(ServiceControlTest, NonExistServiceStopTest, TestSize.Level1) +{ + std::string serviceName = "non_exist_service"; + int ret = ServiceControl(serviceName.c_str(), STOP); + EXPECT_EQ(ret, 0); // No matter if service exist or not, ServiceControl always success. + + auto status = GetServiceStatus(serviceName); + EXPECT_TRUE(status == "idle"); +} + +HWTEST_F(ServiceControlTest, ServiceTimerStartTest, TestSize.Level1) +{ + uint64_t timeout = 1000; // Start service in 1 second + std::string serviceName = "media_service"; + // stop this service first + int ret = ServiceControl(serviceName.c_str(), STOP); + auto oldStatus = GetServiceStatus(serviceName); + bool isRunning = oldStatus == "running"; + EXPECT_FALSE(isRunning); + + ret = StartServiceByTimer(serviceName.c_str(), timeout); + EXPECT_EQ(ret, 0); + + // Service will be started in @timeout seconds + // Now we try to sleep about @timeout / 2 seconds, then check service status. + int64_t ms = 600; + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + // Get service status. + auto newStatus = GetServiceStatus(serviceName); + bool notChange = oldStatus == newStatus; + EXPECT_TRUE(notChange); + + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + newStatus = GetServiceStatus(serviceName); + + isRunning = newStatus == "running"; + EXPECT_TRUE(isRunning); +} + +HWTEST_F(ServiceControlTest, ServiceTimerStartContinuouslyTest, TestSize.Level1) +{ + uint64_t oldTimeout = 500; + uint64_t newTimeout = 1000; + std::string serviceName = "media_service"; + int ret = ServiceControl(serviceName.c_str(), STOP); + EXPECT_EQ(ret, 0); + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STOPPED, WAIT_SERVICE_STATUS_TIMEOUT); + EXPECT_EQ(ret, 0); + auto oldStatus = GetServiceStatus(serviceName); + bool isRunning = oldStatus == "running"; + EXPECT_FALSE(isRunning); + + ret = StartServiceByTimer(serviceName.c_str(), oldTimeout); // Set timer as 500 ms + EXPECT_EQ(ret, 0); + ret = StartServiceByTimer(serviceName.c_str(), newTimeout); // Set timer as 1 second + EXPECT_EQ(ret, 0); + + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(oldTimeout))); + auto newStatus = GetServiceStatus(serviceName); + bool notChange = oldStatus == newStatus; + EXPECT_TRUE(notChange); + uint64_t margin = 20; // 20 ms margin in case of timer not that precisely + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(oldTimeout + margin))); + newStatus = GetServiceStatus(serviceName); + isRunning = newStatus == "running"; + EXPECT_TRUE(isRunning); +} + +HWTEST_F(ServiceControlTest, ServiceTimerStopTest, TestSize.Level1) +{ + uint64_t timeout = 1000; // set timer as 1 second + std::string serviceName = "media_service"; + int ret = ServiceControl(serviceName.c_str(), STOP); + EXPECT_EQ(ret, 0); + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STOPPED, WAIT_SERVICE_STATUS_TIMEOUT); + EXPECT_EQ(ret, 0); + auto oldStatus = GetServiceStatus(serviceName); + bool isRunning = oldStatus == "running"; + EXPECT_FALSE(isRunning); + + ret = StartServiceByTimer(serviceName.c_str(), timeout); + EXPECT_EQ(ret, 0); + + // Now sleep for a while + int64_t ms = 300; + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + auto newStatus = GetServiceStatus(serviceName); + + bool notChange = oldStatus == newStatus; + EXPECT_TRUE(notChange); + + ret = StopServiceTimer(serviceName.c_str()); + EXPECT_EQ(ret, 0); + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + + newStatus = GetServiceStatus(serviceName); + notChange = oldStatus == newStatus; + EXPECT_TRUE(notChange); +} + +HWTEST_F(ServiceControlTest, ServiceTimerStopLateTest, TestSize.Level1) +{ + uint64_t timeout = 500; // set timer as 5 micro seconds + std::string serviceName = "media_service"; + int ret = ServiceControl(serviceName.c_str(), STOP); + auto oldStatus = GetServiceStatus(serviceName); + bool isRunning = oldStatus == "running"; + EXPECT_FALSE(isRunning); + + ret = StartServiceByTimer(serviceName.c_str(), timeout); + EXPECT_EQ(ret, 0); + + int64_t ms = 550; + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + ret = StopServiceTimer(serviceName.c_str()); + EXPECT_EQ(ret, 0); + + auto newStatus = GetServiceStatus(serviceName); + isRunning = newStatus == "running"; + EXPECT_TRUE(isRunning); +} + +HWTEST_F(ServiceControlTest, RestartServiceTest, TestSize.Level1) +{ + std::string serviceName = "media_service"; + auto status = GetServiceStatus(serviceName); + EXPECT_FALSE(status.empty()); + + int ret = ServiceControl(serviceName.c_str(), RESTART); + EXPECT_EQ(ret, 0); + + ret = ServiceControl(serviceName.c_str(), STOP); + EXPECT_EQ(ret, 0); + + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STOPPED, WAIT_SERVICE_STATUS_TIMEOUT); + EXPECT_EQ(ret, 0); + + ret = ServiceControl(serviceName.c_str(), RESTART); + EXPECT_EQ(ret, 0); + + status = GetServiceStatus(serviceName); + + bool isRunning = status == "running"; + EXPECT_TRUE(isRunning); +} + +HWTEST_F(ServiceControlTest, WaitForServiceStatusTest, TestSize.Level1) +{ + std::string serviceName = "media_service"; + int ret = ServiceControl(serviceName.c_str(), STOP); + EXPECT_EQ(ret, 0); + + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STOPPED, WAIT_SERVICE_STATUS_TIMEOUT); + EXPECT_EQ(ret, 0); + + auto status = GetServiceStatus(serviceName); + bool isStopped = status == "stopped"; + EXPECT_TRUE(isStopped); + + // service is stopped now. try to wait a status which will not be set + std::cout << "Wait for service " << serviceName << " status change to start\n"; + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STARTED, WAIT_SERVICE_STATUS_TIMEOUT); + BEGET_ERROR_CHECK(ret == -1, return, "Get media_service status failed."); + + serviceName = "non-exist-service"; + std::cout << "Wait for service " << serviceName << " status change to stop\n"; + ret = ServiceWaitForStatus(serviceName.c_str(), SERVICE_STOPPED, WAIT_SERVICE_STATUS_TIMEOUT); + EXPECT_EQ(ret, -1); +} +} // initModuleTest diff --git a/test/moduletest/service_watcher_moduleTest.cpp b/test/moduletest/service_watcher_moduleTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1997ab615331692a3bfe93182ff0ffa85499c6de --- /dev/null +++ b/test/moduletest/service_watcher_moduleTest.cpp @@ -0,0 +1,89 @@ +/* + * 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 "parameter.h" +#include "service_control.h" +#include "service_watcher.h" +#include "test_utils.h" + +using namespace testing::ext; + +namespace initModuleTest { +class ServiceWatcherModuleTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +static void ServiceStatusChange(const char *key, const ServiceInfo *status) +{ + std::cout <<"service Name is: " << key; + std::cout <<", ServiceStatus is: "<< status->status; + std::cout <<", pid is: "<< status->pid << std::endl; +} + +HWTEST_F(ServiceWatcherModuleTest, serviceWatcher_test_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "serviceWatcher_test_001 start"; + string serviceName = "test.Service"; + int ret = ServiceWatchForStatus(serviceName.c_str(), ServiceStatusChange); + EXPECT_EQ(ret, 0); // No matter if service exist or not, ServiceWatchForStatus always success. + auto status = GetServiceStatus(serviceName); + EXPECT_TRUE(status == "idle"); + GTEST_LOG_(INFO) << "serviceWatcher_test_001 end"; +} + +HWTEST_F(ServiceWatcherModuleTest, serviceWatcher_test_002, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "serviceWatcher_test_002 start"; + string serviceName = "media_service"; + auto status = GetServiceStatus(serviceName); + if (status == "running") { + int ret = ServiceControl(serviceName.c_str(), STOP); + ASSERT_EQ(ret, 0); + } else if (status != "created" && status != "stopped") { + std::cout << serviceName << " in invalid status " << status << std::endl; + ASSERT_TRUE(0); + } + int ret = ServiceWatchForStatus(serviceName.c_str(), ServiceStatusChange); + EXPECT_EQ(ret, 0); + status = GetServiceStatus(serviceName); + EXPECT_TRUE(status == "stopped"); + GTEST_LOG_(INFO) << "serviceWatcher_test_002 end"; +} + +HWTEST_F(ServiceWatcherModuleTest, serviceWatcher_test_003, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "serviceWatcher_test_003 start"; + const std::string serviceName = "deviceinfoservice"; + // watcher service status + int ret = ServiceWatchForStatus(serviceName.c_str(), ServiceStatusChange); + EXPECT_EQ(ret, 0); // No matter if service exist or not, ServiceWatchForStatus always success. + // start service + char udid[65] = {}; // 65 udid len + ret = AclGetDevUdid(udid, sizeof(udid)); + EXPECT_NE(ret, 0); + auto status1 = GetServiceStatus(serviceName); + EXPECT_TRUE(status1 == "running"); + + GTEST_LOG_(INFO) << "serviceWatcher_test_003 end"; +} +} diff --git a/test/moduletest/syspara.cpp b/test/moduletest/syspara.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdae25c6ae0482216fd0d6378d4cf8298fcc9974 --- /dev/null +++ b/test/moduletest/syspara.cpp @@ -0,0 +1,102 @@ +/* + * 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 "begetctl.h" +#include "shell.h" +#include "shell_utils.h" +#include "parameter.h" +#include "parameters.h" +#include "sysversion.h" + +using SysParaInfoItem = struct { + char *infoName; + const char *(*getInfoValue)(void); +}; + +static const SysParaInfoItem SYSPARA_LIST[] = { + {(char *)"DeviceType", GetDeviceType}, + {(char *)"Manufacture", GetManufacture}, + {(char *)"Brand", GetBrand}, + {(char *)"MarketName", GetMarketName}, + {(char *)"ProductSeries", GetProductSeries}, + {(char *)"ProductModel", GetProductModel}, + {(char *)"ProductModelAlias", GetProductModel}, + {(char *)"SoftwareModel", GetSoftwareModel}, + {(char *)"HardwareModel", GetHardwareModel}, + {(char *)"Serial", GetSerial}, + {(char *)"OSFullName", GetOSFullName}, + {(char *)"DisplayVersion", GetDisplayVersion}, + {(char *)"BootloaderVersion", GetBootloaderVersion}, + {(char *)"GetSecurityPatchTag", GetSecurityPatchTag}, + {(char *)"AbiList", GetAbiList}, + {(char *)"IncrementalVersion", GetIncrementalVersion}, + {(char *)"VersionId", GetVersionId}, + {(char *)"BuildType", GetBuildType}, + {(char *)"BuildUser", GetBuildUser}, + {(char *)"BuildHost", GetBuildHost}, + {(char *)"BuildTime", GetBuildTime}, + {(char *)"BuildRootHash", GetBuildRootHash}, + {(char *)"GetOsReleaseType", GetOsReleaseType}, + {(char *)"GetHardwareProfile", GetHardwareProfile}, +}; + +static int32_t SysParaApiDumpCmd(BShellHandle shell, int32_t argc, char *argv[]) +{ + int index = 0; + int dumpInfoItemNum = (sizeof(SYSPARA_LIST) / sizeof(SYSPARA_LIST[0])); + const char *temp = nullptr; + BShellEnvOutput(shell, const_cast("Begin dump syspara\r\n")); + BShellEnvOutput(shell, const_cast("=======================\r\n")); + while (index < dumpInfoItemNum) { + temp = SYSPARA_LIST[index].getInfoValue(); + BShellEnvOutput(shell, const_cast("%s:%s\r\n"), SYSPARA_LIST[index].infoName, temp); + index++; + } + BShellEnvOutput(shell, const_cast("FirstApiVersion:%d\r\n"), GetFirstApiVersion()); + BShellEnvOutput(shell, const_cast("GetSerial:%s\r\n"), GetSerial()); +#ifndef OHOS_LITE + BShellEnvOutput(shell, const_cast("acl serial:%s\r\n"), AclGetSerial()); +#endif + char udid[65] = {0}; + GetDevUdid(udid, sizeof(udid)); + BShellEnvOutput(shell, const_cast("GetDevUdid:%s\r\n"), udid); +#ifndef OHOS_LITE + AclGetDevUdid(udid, sizeof(udid)); + BShellEnvOutput(shell, const_cast("Acl devUdid:%s\r\n"), udid); +#endif + BShellEnvOutput(shell, const_cast("Version:%d.%d.%d.%d\r\n"), + GetMajorVersion(), GetSeniorVersion(), GetFeatureVersion(), GetBuildVersion()); + BShellEnvOutput(shell, const_cast("GetSdkApiVersion:%d\r\n"), GetSdkApiVersion()); + BShellEnvOutput(shell, const_cast("GetSystemCommitId:%lld\r\n"), GetSystemCommitId()); + BShellEnvOutput(shell, const_cast("=======================\r\n")); + BShellEnvOutput(shell, const_cast("End dump syspara\r\n")); + return 0; +} + +MODULE_CONSTRUCTOR(void) +{ + const CmdInfo infos[] = { + { + const_cast("dump"), SysParaApiDumpCmd, const_cast("dump api"), + const_cast("dump api"), const_cast("dump api") + }, + }; + for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { + BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); + } +} diff --git a/test/moduletest/syspara_moduleTest.cpp b/test/moduletest/syspara_moduleTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10970bfdf91987ad4cd0354d6639b07ddfe11b15 --- /dev/null +++ b/test/moduletest/syspara_moduleTest.cpp @@ -0,0 +1,464 @@ +/* + * 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 "param_wrapper.h" +#include "parameter.h" +#include "parameters.h" +#include "sysversion.h" +#include "param_comm.h" +#include "init_param.h" +#include "sysparam_errno.h" +#include "sys_param.h" + +using namespace std; +using namespace testing::ext; +using namespace OHOS; + +const int THREAD_NUM = 5; + +namespace initModuleTest { +static void GetAllParameterTestFunc(void) +{ + EXPECT_STRNE(GetSecurityPatchTag(), nullptr); + EXPECT_STRNE(GetOSFullName(), nullptr); + EXPECT_STRNE(GetVersionId(), nullptr); + EXPECT_STRNE(GetBuildRootHash(), nullptr); + EXPECT_STRNE(GetOsReleaseType(), nullptr); + GetSdkApiVersion(); + EXPECT_STRNE(GetDeviceType(), nullptr); + EXPECT_STRNE(GetProductModel(), nullptr); + EXPECT_STRNE(GetProductModelAlias(), nullptr); + EXPECT_STRNE(GetManufacture(), nullptr); + EXPECT_STRNE(GetBrand(), nullptr); + EXPECT_STRNE(GetMarketName(), nullptr); + EXPECT_STRNE(GetProductSeries(), nullptr); + EXPECT_STRNE(GetSoftwareModel(), nullptr); + EXPECT_STRNE(GetHardwareModel(), nullptr); + EXPECT_STRNE(GetHardwareProfile(), nullptr); + EXPECT_STRNE(GetSerial(), nullptr); + EXPECT_STRNE(GetAbiList(), nullptr); + EXPECT_STRNE(GetDisplayVersion(), nullptr); + EXPECT_STRNE(GetIncrementalVersion(), nullptr); + EXPECT_STRNE(GetBootloaderVersion(), nullptr); + EXPECT_STRNE(GetBuildType(), nullptr); + EXPECT_STRNE(GetBuildUser(), nullptr); + EXPECT_STRNE(GetBuildHost(), nullptr); + EXPECT_STRNE(GetBuildTime(), nullptr); + GetFirstApiVersion(); + EXPECT_STRNE(system::GetDeviceType().c_str(), nullptr); +} + +static void GetUdidTestFunc(char* udid, int size) +{ + int ret = GetDevUdid(udid, size); + EXPECT_EQ(ret, 0); + EXPECT_STRNE(udid, nullptr); +} + +static void SetParameterTestFunc(const char *key, const char *value) +{ + EXPECT_EQ(SetParameter(key, value), 0); + uint32_t handle = FindParameter(key); + EXPECT_NE(handle, static_cast(-1)); + uint32_t result = GetParameterCommitId(handle); + EXPECT_NE(result, static_cast(-1)); + char nameGet[PARAM_NAME_LEN_MAX] = {0}; + int ret = GetParameterName(handle, nameGet, PARAM_NAME_LEN_MAX); + EXPECT_EQ(ret, strlen(nameGet)); + EXPECT_STREQ(key, nameGet); + char valueGet[PARAM_VALUE_LEN_MAX] = {0}; + ret = GetParameterValue(handle, valueGet, PARAM_VALUE_LEN_MAX); + EXPECT_EQ(ret, strlen(valueGet)); + EXPECT_STREQ(value, valueGet); + EXPECT_NE(GetSystemCommitId(), 0); +} + +static void GetParameterTestReInt(const char *key, const char *def, char *value, uint32_t len) +{ + int ret = GetParameter(key, def, value, len); + EXPECT_EQ(ret, strlen(value)); + EXPECT_STREQ(value, "v10.1.1"); +} + +static void GetParameterTestFuncReStr(string key, string def) +{ + string ret = system::GetParameter(key, def); + EXPECT_STREQ(ret.c_str(), "v10.1.1"); +} + +static void ParamSetFun(string key, string value) +{ + bool ret = system::SetParameter(key, value); + EXPECT_TRUE(ret); + string testValue = system::GetParameter(key, ""); + EXPECT_STREQ(testValue.c_str(), value.c_str()); +} + +static void TestParameterChange(const char *key, const char *value, void *context) +{ + std::cout<<"TestParameterChange key: "<(index)); + EXPECT_EQ(ret, 0); + ret = RemoveParameterWatcher("test.param.watcher.test1", TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); +} + +class SysparaModuleTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(SysparaModuleTest, Syspara_SysVersion_test_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_SysVersion_test_001 start"; + GetMajorVersion(); + GetSeniorVersion(); + GetFeatureVersion(); + GetBuildVersion(); + GTEST_LOG_(INFO) << "Syspara_SysVersion_test_001 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_GetParam_test_002, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_GetParam_test_002 start"; + for (int i = 0; i < THREAD_NUM; ++i) { + std::thread(GetAllParameterTestFunc).join(); + } + GTEST_LOG_(INFO) << "Syspara_GetParam_test_002 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_GetUdid_test_003, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_GetUdid_test_003 start"; + for (int i = 0; i < THREAD_NUM; ++i) { + char udid[UDID_LEN] = {0}; + std::thread(GetUdidTestFunc, udid, UDID_LEN).join(); + } + GTEST_LOG_(INFO) << "Syspara_GetUdid_test_003 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_SetParameter_test_004, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_SetParameter_test_004 start"; + char key1[] = "test1.param.version"; + char value1[] = "v10.1.1"; + char key2[] = "test2.param.version"; + char value2[] = "v10.2.2"; + char key3[] = "test3.param.version"; + char value3[] = "v10.3.3"; + std::thread(SetParameterTestFunc, key1, value1).join(); + std::thread(SetParameterTestFunc, key2, value2).join(); + std::thread(SetParameterTestFunc, key3, value3).join(); + GTEST_LOG_(INFO) << "Syspara_SetParameter_test_004 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_SetParameter_test_005, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_SetParameter_test_005 start"; + // check param name length + char key1[] = "test.param.name.xxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxx"; + char value[] = "test.value.xxxx"; + int ret = SetParameter(key1, value); + EXPECT_EQ(ret, EC_INVALID); + // check param name, Illegal param name + char key2[] = ".test.param.name.xxxxx"; + ret = SetParameter(key2, value); + EXPECT_EQ(ret, EC_INVALID); + char key3[] = "test..param.name.xxxxx"; + ret = SetParameter(key3, value); + EXPECT_EQ(ret, EC_INVALID); + char key4[] = "test..param. .name"; + ret = SetParameter(key4, value); + EXPECT_EQ(ret, EC_INVALID); + // check param name, legal param name + char key5[] = "test.param.name.--__.:::"; + ret = SetParameter(key5, value); + EXPECT_EQ(ret, 0); + EXPECT_STREQ(value, "test.value.xxxx"); + char key6[] = "test.param.name.@@@.---"; + ret = SetParameter(key6, value); + EXPECT_EQ(ret, 0); + EXPECT_STREQ(value, "test.value.xxxx"); + // not const param, check param value, bool 8, int 32, other 96 + char key7[] = "test.param.name.xxxx"; + char value1[] = "test.value.xxxxxxxxx.xxxxxxxxxxxxx.xxxxxxxxxxxx.xxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxx"; + ret = SetParameter(key7, value1); + EXPECT_EQ(ret, SYSPARAM_INVALID_VALUE); + char key8[] = "startup.service.ctl.test.int"; + char value2[] = "111111111111111111111111111111111"; + ret = SetParameter(key8, value2); + EXPECT_EQ(ret, SYSPARAM_INVALID_VALUE); + GTEST_LOG_(INFO) << "Syspara_SetParameter_test_005 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_Getparameter_test_006, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_Getparameter_test_006 start"; + string key = "test.param.set.001"; + string value = "xxx.xxx.xxx"; + bool ret = system::SetParameter(key, value); + EXPECT_TRUE(ret); + string testValue = system::GetParameter(key, ""); + EXPECT_STREQ(testValue.c_str(), value.c_str()); + // not read param value,the result is default + testValue = system::GetParameter("test.param.set.002", "aaa.aaa.aaa"); + EXPECT_STREQ(testValue.c_str(), "aaa.aaa.aaa"); + testValue = system::GetParameter("test.param.set.003", ""); + EXPECT_STREQ(testValue.c_str(), ""); + // correct set value + string key1 = "test.param.set.bool"; + ret = system::SetParameter(key1, "1"); + EXPECT_TRUE(ret); + EXPECT_TRUE(system::GetBoolParameter(key1, false)); + ret = system::SetParameter(key1, "y"); + EXPECT_TRUE(ret); + EXPECT_TRUE(system::GetBoolParameter(key1, false)); + ret = system::SetParameter(key1, "yes"); + EXPECT_TRUE(ret); + EXPECT_TRUE(system::GetBoolParameter(key1, false)); + ret = system::SetParameter(key1, "on"); + EXPECT_TRUE(ret); + EXPECT_TRUE(system::GetBoolParameter(key1, false)); + ret = system::SetParameter(key1, "true"); + EXPECT_TRUE(ret); + EXPECT_TRUE(system::GetBoolParameter(key1, false)); + ret = system::SetParameter(key1, "0"); + EXPECT_TRUE(ret); + EXPECT_FALSE(system::GetBoolParameter(key1, true)); + ret = system::SetParameter(key1, "off"); + EXPECT_TRUE(ret); + EXPECT_FALSE(system::GetBoolParameter(key1, true)); + ret = system::SetParameter(key1, "n"); + EXPECT_TRUE(ret); + EXPECT_FALSE(system::GetBoolParameter(key1, true)); + ret = system::SetParameter(key1, "no"); + EXPECT_TRUE(ret); + EXPECT_FALSE(system::GetBoolParameter(key1, true)); + ret = system::SetParameter(key1, "false"); + EXPECT_TRUE(ret); + EXPECT_FALSE(system::GetBoolParameter(key1, true)); + // set value type not bool,the result get form def + ret = system::SetParameter(key1, "test"); + EXPECT_TRUE(ret); + EXPECT_TRUE(system::GetBoolParameter(key1, true)); + EXPECT_FALSE(system::GetBoolParameter(key1, false)); + GTEST_LOG_(INFO) << "Syspara_Getparameter_test_006 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_SetParameter_test_007, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_SetParameter_test_007 start"; + string key1 = "const.param.test"; + string value1 = "test.param.value.001"; + + int ret = 0; + string vRet = ""; + uint32_t handle1 = FindParameter(key1.c_str()); + cout<<"handle1 is: "<(-1)) { + ret = SetParameter(key1.c_str(), value1.c_str()); + EXPECT_EQ(ret, 0); + vRet = system::GetParameter(key1, ""); + EXPECT_STREQ(vRet.c_str(), value1.c_str()); + } + string value2 = "test.param.value.002"; + ret = SetParameter(key1.c_str(), value2.c_str()); + EXPECT_EQ(ret, EC_INVALID); + + string key2 = "ro.param.test"; + string value3 = "test.param.value.003"; + uint32_t handle2 = FindParameter(key2.c_str()); + cout<<"handle2 is: "<(-1)) { + ret = SetParameter(key2.c_str(), value3.c_str()); + EXPECT_EQ(ret, 0); + vRet = system::GetParameter(key2, ""); + EXPECT_STREQ(vRet.c_str(), value3.c_str()); + } + string value4 = "test.param.value.004"; + ret = SetParameter(key2.c_str(), value4.c_str()); + EXPECT_EQ(ret, EC_INVALID); + GTEST_LOG_(INFO) << "Syspara_SetParameter_test_007 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_GetParameterReIntOrStr_test_008, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_GetParameterReIntOrStr_test_008 start"; + string key = "test1.param.version"; + string value = "v10.1.1"; + int ret = SetParameter(key.c_str(), value.c_str()); + EXPECT_EQ(ret, 0); + char retValue[PARAM_VALUE_LEN_MAX] = {0}; + for (int i = 0; i < THREAD_NUM; ++i) { + std::thread(GetParameterTestReInt, key.c_str(), "", retValue, PARAM_VALUE_LEN_MAX).join(); + } + for (int j = 0; j < THREAD_NUM; ++j) { + std::thread(GetParameterTestFuncReStr, key, "").join(); + } + GTEST_LOG_(INFO) << "Syspara_GetParameterReIntOrStr_test_008 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_WaitParameter_test_009, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_WaitParameter_test_009 start"; + // param already set succeed,waitParamter succeed. + char key[] = "test1.param.wait"; + char value[] = "aaa.bbb.ccc"; + int ret = SetParameter(key, value); + EXPECT_EQ(ret, 0); + ret = WaitParameter(key, value, 5); + EXPECT_EQ(ret, 0); + // param not set,waitParamter will wait param set,return succeed. + char key1[] = "test2.param.wait"; + char value1[] = "aaa.aaa.aaa"; + std::thread(ParamSetFun, key1, value1).join(); + ret = WaitParameter(key1, value1, 5); + EXPECT_EQ(ret, 0); + char key2[] = "test3.param.wait"; + std::thread(ParamSetFun, key2, "*****").join(); + ret = WaitParameter(key2, "*****", 5); + EXPECT_EQ(ret, 0); + // param not set,waitParamter will timeout,return failed. + char key3[] = "test4.param.wait"; + ret = WaitParameter(key3, "*****", 5); + EXPECT_EQ(ret, SYSPARAM_WAIT_TIMEOUT); + GTEST_LOG_(INFO) << "Syspara_WaitParameter_test_009 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_watcherParameter_test_010, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_watcherParameter_test_010 start"; + for (int i = 0; i < THREAD_NUM; ++i) { + std::thread(TestParameterWatchChange).join(); + } + + std::thread(ParamSetFun, "test.param.watcher.test1", "test.param.value.xxx").join(); + + GTEST_LOG_(INFO) << "Syspara_watcherParameter_test_010 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_GetParameter_test_011, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_GetParameter_test_011 start"; + + char key1[] = "test.param.int1"; + char value1[] = "0x111111"; + EXPECT_EQ(SetParameter(key1, value1), 0); + EXPECT_EQ(GetIntParameter(key1, 0), 1118481); // 0x111111 decimalism result + EXPECT_EQ(GetUintParameter(key1, 0), 1118481); + + char key2[] = "test.param.int2"; + char value2[] = "-0x111111"; + EXPECT_EQ(SetParameter(key2, value2), 0); + EXPECT_EQ(GetIntParameter(key2, 0), -1118481); // 0x111111 decimalism result + + GetUintParameter(key2, 0); + + char key3[] = "test.param.int3"; + char value3[] = "9999999"; + EXPECT_EQ(SetParameter(key3, value3), 0); + EXPECT_EQ(GetIntParameter(key3, 0), 9999999); // value3 int result + EXPECT_EQ(GetUintParameter(key3, 0), 9999999); // value3 uint result + + char key4[] = "test.param.int4"; + char value4[] = "-9999999"; + EXPECT_EQ(SetParameter(key4, value4), 0); + EXPECT_EQ(GetIntParameter(key4, 0), -9999999); // value4 int result + EXPECT_EQ(GetUintParameter(key4, 0), 0); + + char key5[] = "test.param.int5"; + char value5[] = "-2147483648"; // INT32_MIN + EXPECT_EQ(SetParameter(key5, value5), 0); + EXPECT_EQ(GetIntParameter(key5, 0), 0); + + char key6[] = "test.param.int6"; + char value6[] = "2147483647"; // INT32_MAX + EXPECT_EQ(SetParameter(key6, value6), 0); + EXPECT_EQ(GetIntParameter(key6, 0), 0); + + char key7[] = "test.param.uint7"; + char value7[] = "4294967295"; // UINT32_MAX + EXPECT_EQ(SetParameter(key7, value7), 0); + EXPECT_EQ(GetUintParameter(key7, 0), 0); + + GTEST_LOG_(INFO) << "Syspara_GetParameter_test_011 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_CacheParameter_test_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_001 start"; + + const char *name = "test.write.1111111.222222"; + CachedHandle cacheHandle = CachedParameterCreate(name, "true"); + EXPECT_NE(cacheHandle, nullptr); + const char *value = CachedParameterGet(cacheHandle); + int ret = SetParameter(name, "false"); + EXPECT_EQ(ret, 0); + + value = CachedParameterGet(cacheHandle); + EXPECT_EQ(strcmp(value, "false"), 0); + CachedParameterDestroy(cacheHandle); + + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_001 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_CacheParameter_test_002, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_002 start"; + + const char *name = "test.write.1111111.333333"; + int ret = SetParameter(name, "3333"); + EXPECT_EQ(ret, 0); + CachedHandle cacheHandle3 = CachedParameterCreate(name, "true"); + EXPECT_NE(cacheHandle3, nullptr); + const char *value = CachedParameterGet(cacheHandle3); + EXPECT_EQ(strcmp(value, "3333"), 0); + + ret = SetParameter(name, "2222222"); + EXPECT_EQ(ret, 0); + int valueChange = 0; + value = CachedParameterGetChanged(cacheHandle3, &valueChange); + EXPECT_EQ(strcmp(value, "2222222"), 0); + EXPECT_EQ(valueChange, 1); + CachedParameterDestroy(cacheHandle3); + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_002 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_SaveParameters_test_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_SaveParameters_test_001 start"; + + char key1[] = "test.param.int1"; + char value1[] = "0x111111"; + EXPECT_EQ(SetParameter(key1, value1), 0); + char key2[] = "persist.test.param.int2"; + char value2[] = "-0x111111"; + EXPECT_EQ(SetParameter(key2, value2), 0); + EXPECT_EQ(SaveParameters(), 0); + + GTEST_LOG_(INFO) << "Syspara_SaveParameters_test_001 end"; +} +} \ No newline at end of file diff --git a/test/moduletest/test_utils.cpp b/test/moduletest/test_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a9bebc609aa8b5d014979c060571f8ef4d623be --- /dev/null +++ b/test/moduletest/test_utils.cpp @@ -0,0 +1,147 @@ +/* + * 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 "test_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "parameters.h" +#include "service_control.h" + +namespace initModuleTest { +namespace { +constexpr size_t MAX_BUFFER_SIZE = 4096; +} + +// File operator +int ReadFileContent(const std::string &fileName, std::string &content) +{ + content.clear(); + auto fp = std::unique_ptr(fopen(fileName.c_str(), "r"), fclose); + if (fp == nullptr) { + std::cout << "Cannot open file " << fileName << std::endl; + return -1; + } + + struct stat st {}; + if (stat(fileName.c_str(), &st) < 0) { + std::cout << "Cannot get " << fileName << " stat\n"; + return -1; + } + + ssize_t n = 0; + char buffer[MAX_BUFFER_SIZE] = {}; + while ((n = fread(buffer, 1, MAX_BUFFER_SIZE, fp.get())) > 0) { + content.append(buffer, n); + } + return feof(fp.get()) ? 0 : -1; +} + +bool StartsWith(const std::string &str, const std::string &prefix) +{ + return ((str.size() > prefix.size()) && (str.substr(0, prefix.size()) == prefix)); +} + +bool EndsWith(const std::string &str, const std::string &suffix) +{ + return ((str.size() > suffix.size()) && (str.substr(str.size() - suffix.size(), suffix.size()) == suffix)); +} + +std::string Trim(const std::string &str) +{ + size_t start = 0; + size_t end = str.size() - 1; + + while (start < str.size()) { + if (!isspace(str[start])) { + break; + } + start++; + } + + while (start < end) { + if (!isspace(str[end])) { + break; + } + end--; + } + + if (end < start) { + return ""; + } + + return str.substr(start, end - start + 1); +} + +std::vector Split(const std::string &str, const std::string &pattern) +{ + std::vector result {}; + size_t pos = std::string::npos; + size_t start = 0; + while (true) { + pos = str.find_first_of(pattern, start); + result.push_back(str.substr(start, pos - start)); + if (pos == std::string::npos) { + break; + } + start = pos + 1; + } + return result; +} + +static std::map g_serviceStatusMap = { + { SERVICE_IDLE, "idle"}, + { SERVICE_STARTING, "starting"}, + { SERVICE_STARTED, "running"}, + { SERVICE_READY, "ready"}, + { SERVICE_STOPPING, "stopping"}, + { SERVICE_STOPPED, "stopped"}, + { SERVICE_ERROR, "error" }, + { SERVICE_SUSPENDED, "suspended" }, + { SERVICE_FREEZED, "freezed" }, + { SERVICE_DISABLED, "disabled" }, + { SERVICE_CRITICAL, "critical" }, +}; + +static inline bool ValidStatus(ServiceStatus status) +{ + return status >= SERVICE_IDLE && status <= SERVICE_CRITICAL; +} + +std::string GetServiceStatus(const std::string &serviceName) +{ + if (serviceName.empty()) { + return ""; + } + const std::string serviceCtlPrefix = "startup.service.ctl."; + const std::string serviceCtlName = serviceCtlPrefix + serviceName; + uint32_t ret = OHOS::system::GetUintParameter(serviceCtlName, 0); + ServiceStatus status = static_cast(ret); + if (!ValidStatus(status)) { + return ""; + } + return g_serviceStatusMap[status]; +} + +} // initModuleTest diff --git a/test/moduletest/test_utils.h b/test/moduletest/test_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..19d1c77be443af79c63d56c96c36042d7e6620b4 --- /dev/null +++ b/test/moduletest/test_utils.h @@ -0,0 +1,29 @@ +/* + * 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 INIT_MODULE_TEST_UTILS_H +#define INIT_MODULE_TEST_UTILS_H +#include +#include + +namespace initModuleTest { +// File operator +int ReadFileContent(const std::string &fileName, std::string &content); +std::string Trim(const std::string &str); +std::vector Split(const std::string &str, const std::string &pattern); +std::string GetServiceStatus(const std::string &serviceName); +} // initModuleTest + +#endif // INIT_MODULE_TEST_UTILS_H diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..3ea5ce65fb88b55cfac3ae7c367492ec27154d8d --- /dev/null +++ b/test/unittest/BUILD.gn @@ -0,0 +1,519 @@ +# Copyright (c) 2021-2023 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/begetd.gni") +import("//build/test.gni") + +config("utest_config") { + visibility = [ ":*" ] + + cflags = [ + "-Wno-implicit-fallthrough", + "-Wno-unused-function", + "-Dprivate=public", + "-Dprotected=public", + "-Dsprintf_s=SprintfStub", + "-Dmount=MountStub", + "-Dumount=UmountStub", + "-Dumount2=Umount2Stub", + "-Dprctl=PrctlStub", + "-Dexecv=ExecvStub", + "-Dlchown=LchownStub", + "-Dkill=KillStub", + "-Dexecve=ExecveStub", + ] + cflags_cc = [ + "-Wno-implicit-fallthrough", + "-fexceptions", + ] +} + +FSCRYPT_PATH = + "//foundation/filemanagement/storage_service/services/storage_daemon" + +ohos_unittest("init_unittest") { + module_out_path = "init/init" + sources = [ + "//base/startup/init/device_info/device_info.cpp", + "//base/startup/init/device_info/device_info_stub.cpp", + "//base/startup/init/interfaces/innerkits/control_fd/control_fd_client.c", + "//base/startup/init/interfaces/innerkits/control_fd/control_fd_service.c", + "//base/startup/init/interfaces/innerkits/fd_holder/fd_holder.c", + "//base/startup/init/interfaces/innerkits/fd_holder/fd_holder_internal.c", + "//base/startup/init/interfaces/innerkits/file/init_file.c", + "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/erofs_mount_overlay.c", + "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/erofs_overlay_common.c", + "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/erofs_remount_overlay.c", + "//base/startup/init/interfaces/innerkits/fs_manager/fstab.c", + "//base/startup/init/interfaces/innerkits/fs_manager/fstab_mount.c", + "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/switch_root.c", + "//base/startup/init/interfaces/innerkits/reboot/init_reboot_innerkits.c", + "//base/startup/init/interfaces/innerkits/socket/init_socket.c", + "//base/startup/init/interfaces/innerkits/syspara/param_comm.c", + "//base/startup/init/interfaces/innerkits/syspara/parameter.c", + "//base/startup/init/interfaces/innerkits/syspara/sysversion.c", + "//base/startup/init/remount/remount_overlay.c", + "//base/startup/init/services/begetctl/begetctl_cmd.c", + "//base/startup/init/services/begetctl/bootchart_cmd.c", + "//base/startup/init/services/begetctl/dump_service.c", + "//base/startup/init/services/begetctl/init_cmd_reboot.c", + "//base/startup/init/services/begetctl/misc_daemon.cpp", + "//base/startup/init/services/begetctl/modulectl.c", + "//base/startup/init/services/begetctl/param_cmd.c", + "//base/startup/init/services/begetctl/sandbox.cpp", + "//base/startup/init/services/begetctl/service_control.c", + "//base/startup/init/services/begetctl/setloglevel.c", + "//base/startup/init/services/begetctl/shell/shell_bas.c", + "//base/startup/init/services/begetctl/shell/shell_main.c", + "//base/startup/init/services/init/adapter/init_adapter.c", + "//base/startup/init/services/init/init_capability.c", + "//base/startup/init/services/init/init_common_cmds.c", + "//base/startup/init/services/init/init_common_service.c", + "//base/startup/init/services/init/init_config.c", + "//base/startup/init/services/init/init_group_manager.c", + "//base/startup/init/services/init/init_service_file.c", + "//base/startup/init/services/init/init_service_manager.c", + "//base/startup/init/services/init/init_service_socket.c", + "//base/startup/init/services/init/standard/bootstagehooker.c", + "//base/startup/init/services/init/standard/device.c", + "//base/startup/init/services/init/standard/fd_holder_service.c", + "//base/startup/init/services/init/standard/init.c", + "//base/startup/init/services/init/standard/init_cmdexecutor.c", + "//base/startup/init/services/init/standard/init_cmds.c", + "//base/startup/init/services/init/standard/init_control_fd_service.c", + "//base/startup/init/services/init/standard/init_jobs.c", + "//base/startup/init/services/init/standard/init_mount.c", + "//base/startup/init/services/init/standard/init_reboot.c", + "//base/startup/init/services/init/standard/init_service.c", + "//base/startup/init/services/init/standard/init_signal_handler.c", + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/services/log/init_log.c", + "//base/startup/init/services/loopevent/idle/le_idle.c", + "//base/startup/init/services/loopevent/loop/le_epoll.c", + "//base/startup/init/services/loopevent/loop/le_loop.c", + "//base/startup/init/services/loopevent/signal/le_signal.c", + "//base/startup/init/services/loopevent/socket/le_socket.c", + "//base/startup/init/services/loopevent/task/le_asynctask.c", + "//base/startup/init/services/loopevent/task/le_streamtask.c", + "//base/startup/init/services/loopevent/task/le_task.c", + "//base/startup/init/services/loopevent/task/le_watchtask.c", + "//base/startup/init/services/loopevent/timer/le_timer.c", + "//base/startup/init/services/loopevent/utils/le_utils.c", + "//base/startup/init/services/modules/bootchart/bootchart.c", + "//base/startup/init/services/modules/bootchart/bootchart_static.c", + "//base/startup/init/services/modules/bootevent/bootevent.c", + "//base/startup/init/services/modules/crashhandler/crash_handler.c", + "//base/startup/init/services/modules/init_eng/init_eng.c", + "//base/startup/init/services/modules/init_eng/init_eng_static.c", + "//base/startup/init/services/modules/init_hook/init_hook.c", + "//base/startup/init/services/modules/init_hook/param_hook.c", + "//base/startup/init/services/modules/reboot/reboot.c", + "//base/startup/init/services/modules/reboot/reboot_misc.c", + "//base/startup/init/services/modules/reboot/reboot_static.c", + "//base/startup/init/services/modules/udid/udid_adp.c", + "//base/startup/init/services/modules/udid/udid_comm.c", + "//base/startup/init/services/modules/udid/udid_static.c", + "//base/startup/init/services/param/adapter/param_dac.c", + "//base/startup/init/services/param/adapter/param_persistadp.c", + "//base/startup/init/services/param/base/param_base.c", + "//base/startup/init/services/param/base/param_comm.c", + "//base/startup/init/services/param/base/param_trie.c", + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/linux/param_msgadp.c", + "//base/startup/init/services/param/linux/param_osadp.c", + "//base/startup/init/services/param/linux/param_request.c", + "//base/startup/init/services/param/linux/param_service.c", + "//base/startup/init/services/param/manager/param_manager.c", + "//base/startup/init/services/param/manager/param_persist.c", + "//base/startup/init/services/param/manager/param_server.c", + "//base/startup/init/services/param/trigger/trigger_checker.c", + "//base/startup/init/services/param/trigger/trigger_manager.c", + "//base/startup/init/services/param/trigger/trigger_processor.c", + "//base/startup/init/services/sandbox/sandbox.c", + "//base/startup/init/services/sandbox/sandbox_namespace.c", + "//base/startup/init/services/utils/init_hashmap.c", + "//base/startup/init/services/utils/init_utils.c", + "//base/startup/init/services/utils/list.c", + "//base/startup/init/ueventd/standard/ueventd_parameter.c", + "//base/startup/init/ueventd/ueventd.c", + "//base/startup/init/ueventd/ueventd_device_handler.c", + "//base/startup/init/ueventd/ueventd_firmware_handler.c", + "//base/startup/init/ueventd/ueventd_read_cfg.c", + "//base/startup/init/ueventd/ueventd_socket.c", + ] + + sources += [ + "${FSCRYPT_PATH}/libfscrypt/src/fscrypt_control.c", + "${FSCRYPT_PATH}/libfscrypt/src/fscrypt_utils.c", + "${FSCRYPT_PATH}/libfscrypt/src/key_control.c", + "${FSCRYPT_PATH}/libfscrypt/src/sysparam_static.c", + ] + + if (defined(build_selinux) && build_selinux) { + sources += [ "//base/startup/init/services/param/adapter/param_selinux.c" ] + } + + if (enable_ohos_startup_init_feature_watcher) { + sources += [ + "//base/startup/init/services/param/watcher/agent/watcher.cpp", + "//base/startup/init/services/param/watcher/agent/watcher_manager_kits.cpp", + "//base/startup/init/services/param/watcher/agent/watcher_manager_proxy.cpp", + "//base/startup/init/services/param/watcher/agent/watcher_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_manager_stub.cpp", + "//base/startup/init/services/param/watcher/proxy/watcher_proxy.cpp", + ] + } + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fs_manager/switch_root/include", + "//base/startup/init/interfaces/innerkits/fs_manager/erofs_overlay/include", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", + "//base/startup/init/interfaces/innerkits/include/fs_manager", + "//base/startup/init/remount/include", + ] + defines = [] + + if (defined(build_seccomp) && build_seccomp) { + sources += [ + "../../services/modules/seccomp/seccomp_policy.c", + "seccomp/seccomp_unittest.cpp", + ] + include_dirs += + [ "//base/startup/init/interfaces/innerkits/seccomp/include" ] + + if (build_variant == "root") { + defines += [ "WITH_SECCOMP_DEBUG" ] + } + + if (use_clang_coverage) { + defines += [ "COVERAGE_TEST" ] + } + + if (init_feature_seccomp_privilege) { + defines += [ "SECCOMP_PRIVILEGE" ] + } + } + + sources += [ + "begetctl/begetctl_unittest.cpp", + "fs_manager/erofs/erofs_common_unittest.cpp", + "fs_manager/erofs/erofs_mount_unittest.cpp", + "fs_manager/erofs/erofs_remount_unittest.cpp", + "init/cmds_unittest.cpp", + "init/group_unittest.cpp", + "init/init_reboot_unittest.cpp", + "init/init_unittest.cpp", + "init/mount_unittest.cpp", + "init/sandbox_unittest.cpp", + "init/service_file_unittest.cpp", + "init/service_socket_unittest.cpp", + "init/service_unittest.cpp", + "init/utils_unittest.cpp", + "innerkits/innerkits_unittest.cpp", + "loopevent/loopevent_unittest.cpp", + "loopevent/loopserver_unittest.cpp", + "loopevent/loopsignal_unittest.cpp", + "loopevent/looptimer_unittest.cpp", + "modules/eng_unittest.cpp", + "modules/modules_unittest.cpp", + "modules/udid_unittest.cpp", + "param/client_unittest.cpp", + "param/dac_unittest.cpp", + "param/param_shell_unittest.cpp", + "param/param_stub.cpp", + "param/param_unittest.cpp", + "param/paramservice_unittest.cpp", + "param/trigger_unittest.cpp", + "remount/remount_overlay_unittest.cpp", + "syspara/syspara_unittest.cpp", + "ueventd/ueventd_config_unittest.cpp", + "ueventd/ueventd_event_unittest.cpp", + ] + + sources += [ + "//base/startup/init/interfaces/innerkits/hookmgr/hookmgr.c", + "//base/startup/init/interfaces/innerkits/init_module_engine/init_modulemgr.c", + "//base/startup/init/interfaces/innerkits/modulemgr/modulemgr.c", + "//base/startup/init/interfaces/innerkits/service_control/service_control.c", + "//base/startup/init/interfaces/innerkits/service_watcher/service_watcher.c", + "//base/startup/init/interfaces/innerkits/syscap/init_syscap.c", + "//base/startup/init/interfaces/innerkits/syspara/param_wrapper.cpp", + "innerkits/hookmgr_unittest.cpp", + "innerkits/modulemgr_unittest.cpp", + "innerkits/strutil_unittest.cpp", + ] + + configs = [ "//base/startup/init/test/unittest:utest_config" ] + + include_dirs += [ + "//base/startup/init/device_info", + "//base/startup/init/services/init/standard", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/interfaces/innerkits/syspara", + "//base/startup/init/interfaces/innerkits/control_fd", + "//base/startup/init/services/begetctl", + "//base/startup/init/services/begetctl/shell", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/init/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/log", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/loopevent/loop", + "//base/startup/init/services/loopevent/socket", + "//base/startup/init/services/loopevent/signal", + "//base/startup/init/services/loopevent/task", + "//base/startup/init/services/loopevent/timer", + "//base/startup/init/services/loopevent/utils", + "//base/startup/init/services/loopevent/idle", + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/bootchart", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/modules/selinux", + "//base/startup/init/services/modules/reboot", + "//base/startup/init/services/modules/udid", + "//base/startup/init/services/modules/crashhandler", + "//base/startup/init/services/modules/init_eng", + "//base/startup/init/services/param/adapter", + "//base/startup/init/services/param/base", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/watcher/agent", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/test/unittest", + "//base/startup/init/test/unittest/param", + "//base/startup/init/ueventd/include", + "//base/startup/init/services/sandbox/include", + "//base/startup/init/interfaces/innerkits/hals", + "//base/startup/init/interfaces/innerkits/include/param", + "${FSCRYPT_PATH}/include/libfscrypt", + ] + + defines += [ + "READ_CHECK", + "INIT_AGENT", + "INIT_DMESG", + "INIT_FILE", + "STARTUP_INIT_TEST", + "PARAM_SUPPORT_DAC", + "_GNU_SOURCE", + "PARAM_SUPPORT_TRIGGER", + "USE_MBEDTLS", + "PARAM_DECODE_GROUPID_FROM_FILE", + "WORKSPACE_AREA_NEED_MUTEX", + "PARAMWORKSPACE_NEED_MUTEX", + "PARAM_SUPPORT_REAL_CHECK", + "DISABLE_INIT_TWO_STAGES", + "INIT_SUPPORT_CHIPSET_INIT", + ] + defines += [ "_GNU_SOURCE" ] + + if (target_cpu == "arm64" || target_cpu == "x86_64" || + target_cpu == "riscv64") { + defines += [ "SUPPORT_64BIT" ] + } + if (use_musl) { + defines += [ "__MUSL__" ] + } + + external_deps = [ + "bounds_checking_function:libsec_static", + "cJSON:cjson", + "c_utils:utils", + "config_policy:configpolicy_util_for_init_static", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "init:libinit_module_engine", + "libunwind:libunwind", + "mbedtls:mbedtls_shared", + "selinux:libselinux", + "zlib:libz", + ] + if (defined(global_parts_info) && + defined(global_parts_info.security_access_token)) { + external_deps += [ + "access_token:libnativetoken", + "access_token:libtoken_setproc", + ] + defines += [ "INIT_SUPPORT_ACCESS_TOKEN" ] + } + if (init_appspawn_client_module && defined(global_parts_info) && + defined(global_parts_info.startup_appspawn)) { + defines += [ "ENABLE_ENTER_APPSPAWN_SANDBOX" ] + external_deps += [ "appspawn:appspawn_client" ] + } + + if (init_feature_ab_partition) { + sources += [ "//base/startup/init/services/begetctl/partitionslot.cpp" ] + external_deps += [ + "drivers_interface_partitionslot:libpartitionslot_proxy_1.0", + "hdf_core:libhdi", + "hdf_core:libpub_utils", + ] + } + + if (!defined(ohos_lite) && enable_ohos_startup_init_feature_watcher) { + sources += [ + "param/watcher_agent_unittest.cpp", + "param/watcher_proxy_unittest.cpp", + ] + external_deps += [ + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + } + + if (defined(build_selinux) && build_selinux) { + sources += [ "param/selinux_unittest.cpp" ] + sources += [ + "//base/startup/init/services/modules/selinux/selinux_adp.c", + "//base/startup/init/services/modules/selinux/selinux_static.c", + ] + external_deps += [ + "selinux:libselinux", + "selinux_adapter:librestorecon", + ] + + defines += [ + "WITH_SELINUX", + "PARAM_SUPPORT_SELINUX", + ] + } + if (enable_ohos_startup_init_feature_deviceinfo) { + sources += [ + "//base/startup/init/device_info/device_info_kits.cpp", + "//base/startup/init/device_info/device_info_load.cpp", + "//base/startup/init/device_info/device_info_proxy.cpp", + ] + if (defined(global_parts_info) && + defined(global_parts_info.security_access_token)) { + external_deps += [ "access_token:libaccesstoken_sdk" ] + defines += [ "INIT_SUPPORT_ACCESS_TOKEN" ] + sources += [ "deviceinfo/DeviceInfoUnittest.cpp" ] + } + if (is_standard_system) { + external_deps += [ "selinux:libselinux" ] + } + + defines += [ "PARAM_FEATURE_DEVICEINFO" ] + } + + sources += [ + "//base/startup/init/services/modules/trace/init_trace.c", + "//base/startup/init/test/unittest/modules/trace_unittest.cpp", + ] + + # for sysevent + sources += [ + "//base/startup/init/services/modules/sysevent/startup_time_event.c", + "//base/startup/init/services/modules/sysevent/sys_event.c", + "//base/startup/init/test/unittest/modules/sysevent_unittest.cpp", + ] + + include_dirs += [ + "//base/startup/init/services/modules/bootevent", + "//base/startup/init/services/modules/init_context", + "//base/startup/init/services/modules/sysevent", + ] + + # test for init sub init_context + sources += [ + "//base/startup/init/services/modules/init_context/init_context.c", + "//base/startup/init/services/modules/init_context/init_context_static.c", + "//base/startup/init/test/unittest/modules/context_unittest.cpp", + ] + + # test atomic operation + sources += [ "//base/startup/init/test/unittest/param/atomic_unittest.cpp" ] + + cflags_cc = [ "-fexceptions" ] +} + +ohos_unittest("init_dmverify_unittest") { + module_out_path = "init/init" + sources = [ + "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c", + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/services/log/init_log.c", + "//base/startup/init/test/mock/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c", + "//base/startup/init/test/unittest/fs_manager/dm_verify/dm_verify_unittest.cpp", + ] + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/include", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/hvb/libhvb/include", + "//base/startup/init/interfaces/innerkits/include/fs_manager", + "//third_party/bounds_checking_function/include", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/include", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", + "//base/startup/init/services/log", + ] + + configs = [ "//base/startup/init/test/unittest:utest_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest", + "hilog:libhilog", + ] + + cflags_cc = [ "-fexceptions" ] +} + +ohos_unittest("init_fshvb_unittest") { + module_out_path = "init/init" + sources = [ + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c", + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/services/utils/init_utils.c", + "//base/startup/init/test/mock/hvb/libhvb/auth/hvb.c", + "//base/startup/init/test/mock/hvb/libhvb/cert/hvb_cert.c", + "//base/startup/init/test/mock/hvb/libhvb/crypto/hvb_hash_sha256.c", + "//base/startup/init/test/mock/hvb/libhvb/crypto/hvb_sm3.c", + "//base/startup/init/test/mock/init/interfaces/innerkits/fs_manager/libfs_dm/fs_dm.c", + "//base/startup/init/test/mock/init/ueventd/ueventd.c", + "//base/startup/init/test/mock/init/ueventd/ueventd_socket.c", + "//base/startup/init/test/unittest/fs_manager/libfs_hvb_unittest.cpp", + ] + + include_dirs = [ + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/include", + "//base/startup/hvb/libhvb/include", + "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", + "//base/startup/init/interfaces/innerkits/include/fs_manager", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/log", + "//base/startup/init/ueventd/include", + "//base/startup/hvb/libhvb/src/crypto", + "//base/startup/init/interfaces/innerkits/include/param", + ] + + defines = [ "STARTUP_INIT_UT_PATH =\"/data/init_ut\"" ] + + configs = [] + + external_deps = [ + "c_utils:utils", + "googletest:gtest", + "hilog:libhilog", + ] + + cflags_cc = [ "-fexceptions" ] +} diff --git a/test/unittest/begetctl/begetctl_unittest.cpp b/test/unittest/begetctl/begetctl_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41075d1e6af249b4c826b033295b57fcda2f8fed --- /dev/null +++ b/test/unittest/begetctl/begetctl_unittest.cpp @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2021 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 "begetctl.h" +#include "param_stub.h" +#include "securec.h" +#include "shell.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +class BegetctlUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(BegetctlUnitTest, Init_TestShellInit_001, TestSize.Level0) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param" + }; + BShellEnvDirectExecute(GetShellHandle(), 1, const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLs_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "ls" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLsWithR_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "ls", "-r" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLsGet_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "get" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellSet_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "set", "aaaaa", "1234567" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellGetWithKey_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "get", "aaaaa" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellWait_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "wait", "aaaaa" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} +HWTEST_F(BegetctlUnitTest, Init_TestShellWaitFalse_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "wait" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellWaitWithKey_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "wait", "aaaaa", "12*", "30" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} +HWTEST_F(BegetctlUnitTest, Init_TestShellParamShell_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + const char *args[] = { + "param", "shell" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} +HWTEST_F(BegetctlUnitTest, Init_TestShellLsWithvalue_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + BShellEnvSetParam(GetShellHandle(), PARAM_REVERESD_NAME_CURR_PARAMETER, "..a", PARAM_STRING, (void *)"..a"); + const char *args[] = { + "param", "ls", PARAM_REVERESD_NAME_CURR_PARAMETER + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} +HWTEST_F(BegetctlUnitTest, Init_TestShellLsWithvalueExist_001, TestSize.Level1) +{ + BShellParamCmdRegister(GetShellHandle(), 0); + BShellEnvSetParam(GetShellHandle(), PARAM_REVERESD_NAME_CURR_PARAMETER, "#", PARAM_STRING, (void *)"#"); + const char *args[] = { + "param", "ls", "-r", PARAM_REVERESD_NAME_CURR_PARAMETER + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_001, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "getslot" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_002, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "getsuffix", "1" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_003, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "setactive", "1" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_004, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "setunboot", "2" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_005, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "setactive" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_006, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "setunboot" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestPartitionSlot_007, TestSize.Level1) +{ + const char *args[] = { + "partitionslot", "getsuffix" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLog_001, TestSize.Level1) +{ + const char *args[] = { + "set", "log", "level", "1" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLog_002, TestSize.Level1) +{ + const char *args[] = { + "get", "log", "level" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLog_003, TestSize.Level1) +{ + const char *args[] = { + "set", "log", "level" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLog_004, TestSize.Level1) +{ + const char *args[] = { + "set", "log", "level", "1000" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestShellLog_005, TestSize.Level1) +{ + const char *args[] = { + "set", "log", "level", "a" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestBootChart_001, TestSize.Level1) +{ + const char *args[] = { + "bootchart", "enable" + }; + SystemWriteParam("persist.init.bootchart.enabled", "1"); + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestBootChart_002, TestSize.Level1) +{ + const char *args[] = { + "bootchart", "start" + }; + + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestBootChart_003, TestSize.Level1) +{ + const char *args[] = { + "bootchart", "stop" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestBootChart_004, TestSize.Level1) +{ + const char *args[] = { + "bootchart", "disable" + }; + SystemWriteParam("persist.init.bootchart.enabled", "0"); + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestBootChart_005, TestSize.Level1) +{ + const char *args[] = { + "bootchart" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpService_001, TestSize.Level1) +{ + const char *args[] = { + "bootevent", "enable" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpService_002, TestSize.Level1) +{ + const char *args[] = { + "bootevent", "disable" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpService_003, TestSize.Level1) +{ + const char *args[] = { + "dump_service", "all" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpService_004, TestSize.Level1) +{ + const char *args[] = { + "dump_service", "param_watcher" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpService_005, TestSize.Level1) +{ + const char *args[] = { + "dump_service", "parameter-service", "trigger" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpNwebSpawn_001, TestSize.Level1) +{ + const char *args[] = { + "dump_nwebspawn", "" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestDumpAppspawn_001, TestSize.Level1) +{ + const char *args[] = { + "dump_appspawn", "" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestMiscDaemon_001, TestSize.Level1) +{ + const char *args[] = { + "misc_daemon", "--write_logo", BOOT_CMD_LINE + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestMiscDaemon_002, TestSize.Level1) +{ + const char *args[] = { + "misc_daemon", "--write_logo1111", "test" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestMiscDaemon_003, TestSize.Level1) +{ + const char *args[] = { + "misc_daemon", "--write_logo", "" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestMiscDaemon_004, TestSize.Level1) +{ + const char *args[] = { + "misc_daemon", "--write_logo" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestMiscDaemon_005, TestSize.Level1) +{ + // clear misc logo + const char *args[] = { + "misc_daemon", "--write_logo", "sssssssss" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestModulectl_001, TestSize.Level1) +{ + const char *args[] = { + "modulectl", "install", "testModule" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestModulectl_002, TestSize.Level1) +{ + const char *args[] = { + "modulectl", "uninstall", "testModule" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestModulectl_003, TestSize.Level1) +{ + const char *args[] = { + "modulectl", "list", "testModule" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestModulectl_004, TestSize.Level1) +{ + const char *args[] = { + "modulectl", "install" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestModulectl_005, TestSize.Level1) +{ + const char *args[] = { + "modulectl", "list" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestModulectl_006, TestSize.Level1) +{ + BShellEnvDirectExecute(GetShellHandle(), 0, nullptr); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_001, TestSize.Level1) +{ + const char *args[] = { + "service_control", "stop", "test" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_002, TestSize.Level1) +{ + const char *args[] = { + "service_control", "start", "test" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_003, TestSize.Level1) +{ + const char *args[] = { + "stop_service", "test" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_004, TestSize.Level1) +{ + const char *args[] = { + "start_service", "test" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_005, TestSize.Level1) +{ + const char *args[] = { + "timer_stop", "test" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_006, TestSize.Level1) +{ + const char *args[] = { + "timer_stop" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_007, TestSize.Level1) +{ + const char *args[] = { + "timer_start", "test-service", "10" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_008, TestSize.Level1) +{ + const char *args[] = { + "timer_start", "test-service", + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_009, TestSize.Level1) +{ + const char *args[] = { + "timer_start", "test-service", "ww" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestServiceControl_010, TestSize.Level1) +{ + const char *args[] = { + "xxxxxxxxxxxxxx", "test-service", "ww" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSetLogLevel_001, TestSize.Level1) +{ + const char *args[] = { + "setloglevel", "1" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSetLogLevel_002, TestSize.Level1) +{ + const char *args[] = { + "getloglevel" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSetLogLevel_003, TestSize.Level1) +{ + const char *args[] = { + "setloglevel", "a" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSetLogLevel_004, TestSize.Level1) +{ + const char *args[] = { + "setloglevel" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSetLogLevel_005, TestSize.Level1) +{ + const char *args[] = { + "setloglevel" + }; + BShellEnvDirectExecute(GetShellHandle(), 0, const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSandbox_001, TestSize.Level1) +{ + const char *args[] = { + "sandbox", "-s", "test", "-n", "test2", "-p", "test3", "-h", "?" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestSandbox_002, TestSize.Level1) +{ + const char *args[] = { + "sandbox", "-b", "1008" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_001, TestSize.Level1) +{ + const char *args[] = { + "reboot" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_002, TestSize.Level1) +{ + const char *args[] = { + "reboot", "shutdown" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_003, TestSize.Level1) +{ + const char *args[] = { + "reboot", "charge" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_004, TestSize.Level1) +{ + const char *args[] = { + "reboot", "updater" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_005, TestSize.Level1) +{ + const char *args[] = { + "reboot", "updater:aaaaaaa" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_006, TestSize.Level1) +{ + const char *args[] = { + "reboot", "flashd:aaaaaaa" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_007, TestSize.Level1) +{ + const char *args[] = { + "reboot", "flashd" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_008, TestSize.Level1) +{ + const char *args[] = { + "reboot", "suspend" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestReboot_009, TestSize.Level1) +{ + const char *args[] = { + "reboot", "222222222" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestGid_001, TestSize.Level1) +{ + const char *args[] = { + "dac", "gid", "logd" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestGid_002, TestSize.Level1) +{ + const char *args[] = { + "dac" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestUid_001, TestSize.Level1) +{ + const char *args[] = { + "dac", "uid", "" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} + +HWTEST_F(BegetctlUnitTest, Init_TestUid_002, TestSize.Level1) +{ + const char *args[] = { + "dac", "uid", "" + }; + BShellEnvDirectExecute(GetShellHandle(), sizeof(args) / sizeof(args[0]), const_cast(args)); +} +} // namespace init_ut diff --git a/test/unittest/deviceinfo/DeviceInfoUnittest.cpp b/test/unittest/deviceinfo/DeviceInfoUnittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddd6e8cbb67c0914fb8874cce776910ab1ebfd1d --- /dev/null +++ b/test/unittest/deviceinfo/DeviceInfoUnittest.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2021 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 "accesstoken_kit.h" +#include "parameter.h" +#include "system_ability_definition.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "parcel.h" +#include "string_ex.h" +#include "device_info_kits.h" +#include "device_info_load.h" +#include "device_info_proxy.h" +#include "idevice_info.h" +#include "device_info_stub.h" +#include "sysparam_errno.h" +#include "deviceinfoservice_ipc_interface_code.h" + +using namespace testing::ext; +using namespace std; +using namespace OHOS; + +int g_tokenType = OHOS::Security::AccessToken::TOKEN_HAP; +int g_tokenVerifyResult = 0; +namespace OHOS { +namespace Security { +namespace AccessToken { +ATokenTypeEnum AccessTokenKit::GetTokenTypeFlag(AccessTokenID tokenID) +{ + return static_cast(g_tokenType); +} +int AccessTokenKit::VerifyAccessToken(AccessTokenID tokenID, const std::string& permissionName) +{ + return g_tokenVerifyResult; +} +} // namespace AccessToken +} // namespace Security +} // namespace OHOS + +const int UDID_LEN = 65; +namespace init_ut { +using DeviceInfoServicePtr = OHOS::device_info::DeviceInfoService *; +class DeviceInfoUnittest : public testing::Test { +public: + DeviceInfoUnittest() {}; + virtual ~DeviceInfoUnittest() {}; + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; + void TestBody(void) {}; + DeviceInfoServicePtr GetDeviceInfoService() + { + static DeviceInfoServicePtr deviceInfoServicePtr = nullptr; + if (deviceInfoServicePtr == nullptr) { + deviceInfoServicePtr = new OHOS::device_info::DeviceInfoService(0, true); + if (deviceInfoServicePtr == nullptr) { + return nullptr; + } + deviceInfoServicePtr->OnStart(); + } + return deviceInfoServicePtr; + } +}; + +HWTEST_F(DeviceInfoUnittest, Init_DevInfoAgentTest_001, TestSize.Level1) +{ + OHOS::device_info::DeviceInfoKits &kits = OHOS::device_info::DeviceInfoKits::GetInstance(); + std::string serial = {}; + int ret = kits.GetSerialID(serial); + EXPECT_EQ(ret, SYSPARAM_PERMISSION_DENIED); + ret = kits.GetUdid(serial); + EXPECT_EQ(ret, SYSPARAM_PERMISSION_DENIED); +} + +HWTEST_F(DeviceInfoUnittest, Init_DevInfoDiedTest_001, TestSize.Level1) +{ + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + DINFO_CHECK(samgr != nullptr, return, "Get samgr failed"); + sptr object = samgr->GetSystemAbility(SYSPARAM_DEVICE_SERVICE_ID); + DINFO_CHECK(object != nullptr, return, "Get deviceinfo manager object from samgr failed"); + OHOS::device_info::DeviceInfoKits &kits = OHOS::device_info::DeviceInfoKits::GetInstance(); + if (kits.GetDeathRecipient() != nullptr) { + kits.GetDeathRecipient()->OnRemoteDied(object); + } + std::string serial = {}; + int ret = kits.GetSerialID(serial); + EXPECT_EQ(ret, SYSPARAM_PERMISSION_DENIED); +} + +HWTEST_F(DeviceInfoUnittest, Init_DevInfoAgentFail_001, TestSize.Level1) +{ + sptr deviceInfoLoad = new (std::nothrow) OHOS::device_info::DeviceInfoLoad(); + ASSERT_NE(deviceInfoLoad, nullptr); + deviceInfoLoad->OnLoadSystemAbilityFail(SYSPARAM_DEVICE_SERVICE_ID); + deviceInfoLoad->OnLoadSystemAbilityFail(SYSPARAM_DEVICE_SERVICE_ID + 1); + + OHOS::device_info::DeviceInfoKits &kits = OHOS::device_info::DeviceInfoKits::GetInstance(); + kits.FinishStartSAFailed(); +} + +HWTEST_F(DeviceInfoUnittest, Init_DeviceInfoServiceInvalidTokenTest_001, TestSize.Level1) +{ + string result; + DeviceInfoServicePtr deviceInfoService = GetDeviceInfoService(); + ASSERT_NE(deviceInfoService, nullptr); + MessageParcel data; + MessageParcel reply; + MessageOption option; + g_tokenType = OHOS::Security::AccessToken::TOKEN_INVALID; + data.WriteInterfaceToken(OHOS::device_info::DeviceInfoStub::GetDescriptor()); + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_UDID), data, reply, option); +} + +HWTEST_F(DeviceInfoUnittest, Init_DeviceInfoServiceFailTest_001, TestSize.Level1) +{ + string result; + DeviceInfoServicePtr deviceInfoService = GetDeviceInfoService(); + ASSERT_NE(deviceInfoService, nullptr); + MessageParcel data; + MessageParcel reply; + MessageOption option; + g_tokenType = OHOS::Security::AccessToken::TOKEN_HAP; + g_tokenVerifyResult = OHOS::Security::AccessToken::TypePermissionState::PERMISSION_DENIED; + + // udid + data.WriteInterfaceToken(OHOS::device_info::DeviceInfoStub::GetDescriptor()); + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_UDID), + data, reply, option); + // serial + data.WriteInterfaceToken(OHOS::device_info::DeviceInfoStub::GetDescriptor()); + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID), + data, reply, option); +} + +HWTEST_F(DeviceInfoUnittest, Init_DeviceInfoServiceTest_001, TestSize.Level1) +{ + string result; + DeviceInfoServicePtr deviceInfoService = GetDeviceInfoService(); + ASSERT_NE(deviceInfoService, nullptr); + MessageParcel data; + MessageParcel reply; + MessageOption option; + g_tokenType = OHOS::Security::AccessToken::TOKEN_HAP; + g_tokenVerifyResult = OHOS::Security::AccessToken::TypePermissionState::PERMISSION_GRANTED; + data.WriteInterfaceToken(OHOS::device_info::DeviceInfoStub::GetDescriptor()); + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_UDID), + data, reply, option); + data.WriteInterfaceToken(OHOS::device_info::DeviceInfoStub::GetDescriptor()); + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID), + data, reply, option); + data.WriteInterfaceToken(OHOS::device_info::DeviceInfoStub::GetDescriptor()); + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID) + 1, + data, reply, option); + + deviceInfoService->OnRemoteRequest + (static_cast (OHOS::device_info::DeviceInfoInterfaceCode::COMMAND_GET_SERIAL_ID) + 1, + data, reply, option); + std::this_thread::sleep_for(std::chrono::seconds(3)); // wait sa unload 3s + deviceInfoService->GetUdid(result); + deviceInfoService->GetSerialID(result); + deviceInfoService->OnStop(); + std::vector args = {}; + deviceInfoService->Dump(STDOUT_FILENO, args); + deviceInfoService->Dump(-1, args); +} + +HWTEST_F(DeviceInfoUnittest, Init_TestInterface_001, TestSize.Level1) +{ + char localDeviceId[UDID_LEN] = {0}; + int ret = AclGetDevUdid(nullptr, UDID_LEN); + ASSERT_NE(ret, 0); + ret = AclGetDevUdid(localDeviceId, 2); // 2 test + ASSERT_NE(ret, 0); + + ret = AclGetDevUdid(localDeviceId, UDID_LEN); + const char *serialNumber = AclGetSerial(); + EXPECT_NE(nullptr, serialNumber); +} + +HWTEST_F(DeviceInfoUnittest, Init_TestDeviceInfoProxy_001, TestSize.Level1) +{ + sptr proxy; + { + OHOS::device_info::DeviceInfoKits &kits = device_info::DeviceInfoKits::GetInstance(); + std::unique_lock lock(kits.lock_); + auto remotePtr = device_info::DeviceInfoKits::GetInstance().GetService(lock); + ASSERT_NE(remotePtr, nullptr); + auto remote = remotePtr->AsObject(); + proxy = new(std::nothrow) device_info::DeviceInfoProxy(remote); + ASSERT_NE(proxy, nullptr); + } + device_info::DeviceInfoKits::GetInstance().FinishStartSASuccess(proxy->AsObject()); + std::string udid; + std::string serialId; + proxy->GetUdid(udid); + proxy->GetSerialID(serialId); + + char localDeviceId[UDID_LEN] = {0}; + (void)AclGetDevUdid(localDeviceId, UDID_LEN); + const char *serialNumber = AclGetSerial(); + EXPECT_NE(nullptr, serialNumber); +} + +HWTEST_F(DeviceInfoUnittest, Init_TestDeviceInfoProxy_002, TestSize.Level1) +{ + sptr proxy = new(std::nothrow) device_info::DeviceInfoProxy(nullptr); + ASSERT_NE(proxy, nullptr); + + std::string udid; + std::string serialId; + proxy->GetUdid(udid); + proxy->GetSerialID(serialId); +} +} // namespace init_ut diff --git a/test/unittest/fs_manager/dm_verify/dm_verify_unittest.cpp b/test/unittest/fs_manager/dm_verify/dm_verify_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc710b453354b683aa4d3207b55edcfc6afec557 --- /dev/null +++ b/test/unittest/fs_manager/dm_verify/dm_verify_unittest.cpp @@ -0,0 +1,134 @@ +/* + * 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 +#include "dm_verity.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class DmVerifyUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(DmVerifyUnitTest, HvbDmVerityinit_001, TestSize.Level0) +{ + int ret; + FstabItem fstabitem = {(char *)"deviceName", (char *)"mountPoint", + (char *)"fsType", (char *)"mountOptions", 1, nullptr}; + Fstab fstab = {&fstabitem}; + + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + setenv("SWTYPE_VALUE", "Test", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + setenv("ENABLE_VALUE", "false", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + setenv("ENABLE_VALUE", "FALSE", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + setenv("ENABLE_VALUE", "orange", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + setenv("ENABLE_VALUE", "ORANGE", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + unsetenv("SWTYPE_VALUE"); + unsetenv("ENABLE_VALUE"); +} + +HWTEST_F(DmVerifyUnitTest, HvbDmVerityinit_002, TestSize.Level0) +{ + int ret; + FstabItem fstabitem = {(char *)"deviceName", (char *)"mountPoint", + (char *)"fsType", (char *)"mountOptions", 1, nullptr}; + Fstab fstab = {&fstabitem}; + + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + setenv("SWTYPE_VALUE", "factory", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + fstabitem.fsManagerFlags = 0x00000010; + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, -1); + + setenv("INIT_VALUE", "on", 1); + ret = HvbDmVerityinit(&fstab); + EXPECT_EQ(ret, 0); + + unsetenv("SWTYPE_VALUE"); + unsetenv("INIT_VALUE"); +} + +HWTEST_F(DmVerifyUnitTest, HvbDmVeritySetUp_001, TestSize.Level0) +{ + int ret; + FstabItem fstabitem = {(char *)"deviceName", (char *)"mountPoint", + (char *)"fsType", (char *)"mountOptions", 1, nullptr}; + + ret = HvbDmVeritySetUp(&fstabitem); + EXPECT_EQ(ret, 0); + + setenv("SWTYPE_VALUE", "factory", 1); + ret = HvbDmVeritySetUp(nullptr); + EXPECT_EQ(ret, -1); + fstabitem.fsManagerFlags = 0x00000009; + ret = HvbDmVeritySetUp(&fstabitem); + EXPECT_EQ(ret, 0); + + fstabitem.fsManagerFlags = 0x00000010; + ret = HvbDmVeritySetUp(&fstabitem); + EXPECT_EQ(ret, -1); + fstabitem.fsManagerFlags = 0x00000018; + ret = HvbDmVeritySetUp(&fstabitem); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "on", 1); + ret = HvbDmVeritySetUp(&fstabitem); + EXPECT_EQ(ret, 0); + + unsetenv("SWTYPE_VALUE"); + unsetenv("HASH_VALUE"); +} + +HWTEST_F(DmVerifyUnitTest, HvbDmVerityFinal_001, TestSize.Level0) +{ + HvbDmVerityFinal(); + + setenv("SWTYPE_VALUE", "factory", 1); + HvbDmVerityFinal(); + + setenv("FINAL_VALUE", "on", 1); + HvbDmVerityFinal(); + + unsetenv("SWTYPE_VALUE"); + unsetenv("FINAL_VALUE"); +} +} // namespace init_ut \ No newline at end of file diff --git a/test/unittest/fs_manager/erofs/erofs_common_unittest.cpp b/test/unittest/fs_manager/erofs/erofs_common_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..615ebb25d7e150144f3aeb63daf0b6320ced8029 --- /dev/null +++ b/test/unittest/fs_manager/erofs/erofs_common_unittest.cpp @@ -0,0 +1,102 @@ +/* +* 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 "erofs_overlay_common.h" +#include "securec.h" +#include "param_stub.h" +using namespace std; +using namespace testing::ext; +namespace init_ut { +class ErofsCommonOverlayUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(ErofsCommonOverlayUnitTest, Init_IsOverlayEnable_001, TestSize.Level0) +{ + const char *cmdLine; + + cmdLine = "test=test"; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + bool ret = IsOverlayEnable(); + EXPECT_EQ(ret, false); + remove(BOOT_CMD_LINE); + + cmdLine = "oemmode=test"; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = IsOverlayEnable(); + EXPECT_EQ(ret, false); + remove(BOOT_CMD_LINE); + + cmdLine = "oemmode=test buildvariant=user"; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = IsOverlayEnable(); + EXPECT_EQ(ret, false); + remove(BOOT_CMD_LINE); + + cmdLine = "oemmode=test buildvariant=eng"; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = IsOverlayEnable(); + EXPECT_EQ(ret, true); + int ret2 = remove(BOOT_CMD_LINE); + PrepareCmdLineData(); +} + +HWTEST_F(ErofsCommonOverlayUnitTest, Init_IsOverlayCheckExt4_001, TestSize.Level0) +{ + bool ret = CheckIsExt4(STARTUP_INIT_UT_PATH "/data/notexistfile", 0); + EXPECT_EQ(ret, false); + + const char *fileName = STARTUP_INIT_UT_PATH "/data/ext4_super_block"; + CheckAndCreateDir(fileName); + ret = CheckIsExt4(fileName, 0); + EXPECT_EQ(ret, false); + + int fd = open(fileName, O_WRONLY); + struct ext4_super_block super; + super.s_magic = EXT4_SUPER_MAGIC; + write(fd, &super, sizeof(ext4_super_block)); + ret = CheckIsExt4(fileName, 0); + EXPECT_EQ(ret, false); + write(fd, &super, sizeof(ext4_super_block)); + ret = CheckIsExt4(fileName, 0); + remove(fileName); +} + +HWTEST_F(ErofsCommonOverlayUnitTest, Init_IsOverlayCheckErofs_001, TestSize.Level0) +{ + bool ret = CheckIsErofs(STARTUP_INIT_UT_PATH"/data/notexistfile"); + EXPECT_EQ(ret, false); + + const char *fileName = STARTUP_INIT_UT_PATH "/data/erofsfile"; + CheckAndCreateDir(fileName); + ret = CheckIsErofs(fileName); + EXPECT_EQ(ret, false); + + int fd = open(fileName, O_WRONLY); + struct ext4_super_block super; + super.s_magic = EXT4_SUPER_MAGIC; + write(fd, &super, sizeof(ext4_super_block)); + ret = CheckIsErofs(fileName); + EXPECT_EQ(ret, false); + + write(fd, &super, sizeof(ext4_super_block)); + ret = CheckIsErofs(fileName); + remove(fileName); +} +} \ No newline at end of file diff --git a/test/unittest/fs_manager/erofs/erofs_mount_unittest.cpp b/test/unittest/fs_manager/erofs/erofs_mount_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..585d71504645e528dbf038933d4bab7c7e40823a --- /dev/null +++ b/test/unittest/fs_manager/erofs/erofs_mount_unittest.cpp @@ -0,0 +1,69 @@ +/* +* 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 "erofs_mount_overlay.h" +#include "securec.h" +#include "param_stub.h" +#include "init_utils.h" +using namespace std; +using namespace testing::ext; +namespace init_ut { +class ErofsMountUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; +HWTEST_F(ErofsMountUnitTest, Init_AllocDmName_001, TestSize.Level0) +{ + char nameExt4[MAX_BUFFER_LEN] = {0}; + char nameRofs[MAX_BUFFER_LEN] = {0}; + const char *devName = STARTUP_INIT_UT_PATH"/data/erofs/mount/rofs"; + AllocDmName(devName, nameRofs, MAX_BUFFER_LEN, nameExt4, MAX_BUFFER_LEN); + EXPECT_STRNE(nameExt4, nameRofs); +} +HWTEST_F(ErofsMountUnitTest, Init_LookupErofsEnd_001, TestSize.Level0) +{ + const char *devMount = STARTUP_INIT_UT_PATH"/data/erofs/mount/lookup"; + int ret = LookupErofsEnd(devMount); + EXPECT_EQ(ret, 0); + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + CheckAndCreatFile(devMount, mode); + int fd = open(devMount, O_WRONLY | O_TRUNC); + void *data = calloc(1, EROFS_SUPER_BLOCK_START_POSITION); + ret = write(fd, data, EROFS_SUPER_BLOCK_START_POSITION); + EXPECT_EQ(ret, EROFS_SUPER_BLOCK_START_POSITION); + + close(fd); + free(data); + ret = LookupErofsEnd(devMount); + EXPECT_EQ(ret, 0); + struct erofs_super_block sb; + sb.magic = EROFS_SUPER_MAGIC; + sb.blocks = 1; + data = calloc(1, sizeof(sb)); + memcpy_s(data, EROFS_SUPER_BLOCK_START_POSITION, &sb, sizeof(sb)); + fd = open(devMount, O_WRONLY | O_APPEND); + ret = write(fd, data, sizeof(sb)); + EXPECT_EQ(ret, sizeof(sb)); + + close(fd); + free(data); + ret = LookupErofsEnd(devMount); + EXPECT_NE(ret, 0); + remove(devMount); +} + +} \ No newline at end of file diff --git a/test/unittest/fs_manager/erofs/erofs_remount_unittest.cpp b/test/unittest/fs_manager/erofs/erofs_remount_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5aa78a53eba2a0a0087c1686d365e2f34269f9b4 --- /dev/null +++ b/test/unittest/fs_manager/erofs/erofs_remount_unittest.cpp @@ -0,0 +1,108 @@ +/* +* 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 "erofs_remount_overlay.h" +#include "securec.h" +#include "param_stub.h" +#include "fs_manager.h" +using namespace std; +using namespace testing::ext; +namespace init_ut { +class ErofsRemountUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(ErofsRemountUnitTest, Init_GetRemountResult_001, TestSize.Level0) +{ + const char *cmdLine; + rmdir(REMOUNT_RESULT_PATH); + SetRemountResultFlag(); + + CheckAndCreateDir(REMOUNT_RESULT_FLAG); + SetRemountResultFlag(); + rmdir(REMOUNT_RESULT_PATH); +} + +HWTEST_F(ErofsRemountUnitTest, Init_Modem2Exchange_001, TestSize.Level0) +{ + const char *srcPath = STARTUP_INIT_UT_PATH"/data/modem2Exchange"; + const char *targetPath = STARTUP_INIT_UT_PATH"/data/modem2Exchangetarget"; + + CheckAndCreateDir(srcPath); + CheckAndCreateDir(targetPath); + + SetStubResult(STUB_MOUNT, -1); + int ret = Modem2Exchange(srcPath, targetPath); + EXPECT_EQ(ret, -1); + + SetStubResult(STUB_MOUNT, 0); + ret = Modem2Exchange(srcPath, targetPath); + EXPECT_EQ(ret, 0); + + rmdir(srcPath); + rmdir(targetPath); +} + +HWTEST_F(ErofsRemountUnitTest, Init_ExchangeToMode_001, TestSize.Level0) +{ + const char *srcPath = STARTUP_INIT_UT_PATH"/data/Exchange2Mode"; + const char *targetPath = STARTUP_INIT_UT_PATH"/data/Exchange2Modetarget"; + + int ret = Exchange2Modem(srcPath, targetPath); + EXPECT_EQ(ret, 0); + + CheckAndCreateDir(srcPath); + CheckAndCreateDir(targetPath); + + SetStubResult(STUB_MOUNT, 0); + SetStubResult(STUB_UMOUNT, 0); + + ret = Exchange2Modem(srcPath, targetPath); + EXPECT_EQ(ret, 0); + + CheckAndCreateDir(targetPath); + SetStubResult(STUB_MOUNT, -1); + SetStubResult(STUB_UMOUNT, -1); + + Exchange2Modem(srcPath, targetPath); + EXPECT_EQ(ret, 0); + + rmdir(srcPath); + rmdir(targetPath); +} + +HWTEST_F(ErofsRemountUnitTest, Init_OverlayRemountVendorPre_001, TestSize.Level0) +{ + CheckAndCreateDir(MODEM_DRIVER_MNT_PATH); + CheckAndCreateDir(MODEM_VENDOR_MNT_PATH); + CheckAndCreateDir(MODEM_FW_MNT_PATH); + OverlayRemountVendorPre(); + rmdir(MODEM_DRIVER_MNT_PATH); + rmdir(MODEM_VENDOR_MNT_PATH); + rmdir(MODEM_FW_MNT_PATH); + + OverlayRemountVendorPost(); +} + +HWTEST_F(ErofsRemountUnitTest, Init_RemountOverlayTest_001, TestSize.Level0) +{ + int ret = RemountOverlay(); + EXPECT_EQ(ret, 0); +} +} \ No newline at end of file diff --git a/test/unittest/fs_manager/libfs_hvb_unittest.cpp b/test/unittest/fs_manager/libfs_hvb_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..134b483ac16baf82b21fb6cc277867664321b167 --- /dev/null +++ b/test/unittest/fs_manager/libfs_hvb_unittest.cpp @@ -0,0 +1,379 @@ +/* +* 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 +#include +#include "fs_hvb.h" +#include "init_utils.h" +#include "fs_manager/ext4_super_block.h" +#include "fs_manager/erofs_super_block.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +class FsHvbUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +void CreateTestFile(const char *fileName, const char *data) +{ + CheckAndCreateDir(fileName); + printf("PrepareParamTestData for %s\n", fileName); + FILE *tmpFile = fopen(fileName, "a+"); + if (tmpFile != nullptr) { + fprintf(tmpFile, "%s", data); + (void)fflush(tmpFile); + fclose(tmpFile); + } +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbInit_001, TestSize.Level0) +{ + const char *cmdLine; + int ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, HVB_ERROR_INVALID_ARGUMENT); + + setenv("VERIFY_VALUE", "PartFail", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, HVB_ERROR_UNSUPPORTED_VERSION); + + setenv("VERIFY_VALUE", "Succeed", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + cmdLine = "ohos.boot.hvb.hash_algo=test "; // HVB_CMDLINE_HASH_ALG + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + cmdLine = "ohos.boot.hvb.digest=1 "; // HVB_CMDLINE_CERT_DIGEST + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + remove(BOOT_CMD_LINE); + + cmdLine = "ohos.boot.hvb.hash_algo=test "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + cmdLine = "ohos.boot.hvb.digest=1234 "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + remove(BOOT_CMD_LINE); + + setenv("HASH_VALUE", "InitFail", 1); // sha256 + cmdLine = "ohos.boot.hvb.hash_algo=sha256 "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + cmdLine = "ohos.boot.hvb.digest=01 "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "UpdateFail", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "FinalFail", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "AllSucceed", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, 0); + remove(BOOT_CMD_LINE); + ret = FsHvbFinal(MAIN_HVB); //clear vd + EXPECT_EQ(ret, 0); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbInit_002, TestSize.Level0) +{ + const char *cmdLine; + setenv("VERIFY_VALUE", "Succeed", 1); + setenv("HASH_VALUE", "InitFail", 1); // sm3 + cmdLine = "ohos.boot.hvb.hash_algo=sm3 "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + cmdLine = "ohos.boot.hvb.digest=01 "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + int ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "UpdateFail", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "FinalFail", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, -1); + + setenv("HASH_VALUE", "AllSucceed", 1); + ret = FsHvbInit(MAIN_HVB); + EXPECT_EQ(ret, 0); + + remove(BOOT_CMD_LINE); + unsetenv("VERIFY_VALUE"); + unsetenv("HASH_VALUE"); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbSetupHashtree_001, TestSize.Level0) +{ + FstabItem fsItem; + char testStr[10] = "testStr"; + char testDev[] = "/dev/block/platform/xxx/by-name/boot"; + fsItem.deviceName = (char *)malloc(sizeof(testDev) + 1); + memcpy_s(fsItem.deviceName, sizeof(testDev) + 1, &testDev[0], sizeof(testDev)); + fsItem.mountPoint = &testStr[0]; + fsItem.fsType = &testStr[0]; + fsItem.mountOptions = &testStr[0]; + fsItem.fsManagerFlags = 1; + fsItem.next = nullptr; + + int ret = FsHvbSetupHashtree(nullptr); + EXPECT_EQ(ret, -1); + + setenv("FSDM_VALUE", "InitFail", 1); + ret = FsHvbSetupHashtree(&fsItem); + EXPECT_EQ(ret, -1); + + setenv("FSDM_VALUE", "CreateFail", 1); + ret = FsHvbSetupHashtree(&fsItem); + EXPECT_EQ(ret, -1); + + setenv("FSDM_VALUE", "AllSucceed", 1); + ret = FsHvbSetupHashtree(&fsItem); + EXPECT_EQ(ret, 0); + + unsetenv("FSDM_VALUE"); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbFinal_001, TestSize.Level0) +{ + int ret = FsHvbFinal(MAIN_HVB); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbGetOps_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + EXPECT_NE(ops, nullptr); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbGetValueFromCmdLine_001, TestSize.Level0) +{ + const char *cmdLine; + char hashAlg[32] = { 0 }; + + int ret = FsHvbGetValueFromCmdLine(nullptr, sizeof(hashAlg), "ohos.boot.hvb.hash_algo"); + EXPECT_EQ(ret, -1); + ret = FsHvbGetValueFromCmdLine(&hashAlg[0], sizeof(hashAlg), nullptr); + EXPECT_EQ(ret, -1); + + cmdLine = "ohos.boot.hvb.hash_algo=sha256 "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = FsHvbGetValueFromCmdLine(&hashAlg[0], sizeof(hashAlg), "ohos.boot.hvb.hash_algo"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(strcmp(hashAlg, "sha256"), 0); + + remove(BOOT_CMD_LINE); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbConstructVerityTarget_001, TestSize.Level0) +{ + DmVerityTarget target; + const char *devName = "test"; + struct hvb_cert cert; + uint8_t digest = 53; + uint8_t salt = 55; + + int ret = FsHvbConstructVerityTarget(nullptr, devName, &cert); + EXPECT_EQ(ret, -1); + ret = FsHvbConstructVerityTarget(&target, nullptr, &cert); + EXPECT_EQ(ret, -1); + ret = FsHvbConstructVerityTarget(&target, devName, nullptr); + EXPECT_EQ(ret, -1); + + cert.image_len = 512; + cert.data_block_size = 0; + ret = FsHvbConstructVerityTarget(&target, devName, &cert); + EXPECT_EQ(ret, -1); + cert.data_block_size = 8; + cert.hash_block_size = 0; + ret = FsHvbConstructVerityTarget(&target, devName, &cert); + EXPECT_EQ(ret, -1); + + cert.hash_block_size = 8; + cert.hashtree_offset = 16; + cert.hash_algo = 4; + ret = FsHvbConstructVerityTarget(&target, devName, &cert); + EXPECT_EQ(ret, -1); + + cert.hash_algo = 0; + cert.hash_payload.digest = &digest; + cert.digest_size = 1; + cert.hash_payload.salt = &salt; + cert.salt_size = 1; + cert.fec_size = 1; + cert.fec_num_roots = 1; + cert.fec_offset = 8; + ret = FsHvbConstructVerityTarget(&target, devName, &cert); + EXPECT_EQ(ret, 0); + + cert.hash_algo = 2; + ret = FsHvbConstructVerityTarget(&target, devName, &cert); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(FsHvbUnitTest, Init_FsHvbDestoryVerityTarget_001, TestSize.Level0) +{ + DmVerityTarget target; + + target.paras = static_cast(calloc(1, 10)); + EXPECT_NE(target.paras, nullptr); + FsHvbDestoryVerityTarget(&target); +} + +HWTEST_F(FsHvbUnitTest, Init_VerifyExtHvbImage_001, TestSize.Level0) +{ + const char *cmdLine; + const char *devPath = "/dev/block/loop0"; + char *outPath = nullptr; + int ret = VerifyExtHvbImage(devPath, "boot", &outPath); + EXPECT_FALSE(ret == 0); + + setenv("VERIFY_VALUE", "Succeed", 1); + setenv("HASH_VALUE", "AllSucceed", 1); + setenv("FSDM_VALUE", "AllSucceed", 1); + cmdLine = "ohos.boot.hvb.ext_rvt=01 "; // HVB_CMDLINE_EXT_CERT_DIGEST + CreateTestFile(BOOT_CMD_LINE, cmdLine); + ret = VerifyExtHvbImage(devPath, "module_update", &outPath); + EXPECT_EQ(ret, -1); + + ret = VerifyExtHvbImage(devPath, "boot", &outPath); + EXPECT_EQ(ret, 0); + + remove(BOOT_CMD_LINE); + unsetenv("VERIFY_VALUE"); + unsetenv("HASH_VALUE"); + unsetenv("FSDM_VALUE"); +} + +HWTEST_F(FsHvbUnitTest, Init_CheckAndGetExt4Size_001, TestSize.Level0) +{ + ext4_super_block superBlock = {0}; + uint64_t imageSize; + + bool ret = CheckAndGetExt4Size(nullptr, &imageSize, "boot"); + EXPECT_FALSE(ret); + + ret = CheckAndGetExt4Size((const char*)&superBlock, &imageSize, "boot"); + EXPECT_FALSE(ret); + + superBlock.s_magic = EXT4_SUPER_MAGIC; + ret = CheckAndGetExt4Size((const char*)&superBlock, &imageSize, "boot"); + EXPECT_TRUE(ret); +} + +HWTEST_F(FsHvbUnitTest, Init_CheckAndGetErofsSize_001, TestSize.Level0) +{ + struct erofs_super_block superBlock = {0}; + uint64_t imageSize; + + bool ret = CheckAndGetErofsSize(nullptr, &imageSize, "boot"); + EXPECT_FALSE(ret); + + ret = CheckAndGetErofsSize((const char*)&superBlock, &imageSize, "boot"); + EXPECT_FALSE(ret); + + superBlock.magic = EROFS_SUPER_MAGIC; + ret = CheckAndGetErofsSize((const char*)&superBlock, &imageSize, "boot"); + EXPECT_TRUE(ret); +} + +HWTEST_F(FsHvbUnitTest, Init_CheckAndGetExtheaderSize_001, TestSize.Level0) +{ + uint64_t imageSize; + bool ret = CheckAndGetExtheaderSize(-1, 0, &imageSize, "boot"); + EXPECT_FALSE(ret); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbReadFromPartition_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + int ret = ops->read_partition(ops, "boot_not_exit", 0, 1, nullptr, nullptr); + EXPECT_EQ(ret, HVB_IO_ERROR_IO); + void *buf = malloc(1); + uint64_t outNumRead; + ret = ops->read_partition(ops, "boot_not_exit", 0, 1, buf, &outNumRead); + EXPECT_EQ(ret, HVB_IO_ERROR_IO); + free(buf); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbWriteToPartition_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + void *buf = malloc(1); + int ret = ops->write_partition(ops, "boot", 0, 1, buf); + EXPECT_EQ(ret, HVB_IO_OK); + free(buf); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbInvaldateKey_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + bool outIsTrusted; + int ret = ops->valid_rvt_key(ops, nullptr, 0, nullptr, 0, nullptr); + EXPECT_EQ(ret, HVB_IO_ERROR_IO); + ret = ops->valid_rvt_key(ops, nullptr, 0, nullptr, 0, &outIsTrusted); + EXPECT_EQ(ret, HVB_IO_OK); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbReadRollbackIdx_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + int ret = ops->read_rollback(ops, 0, nullptr); + uint64_t outRollbackIndex; + EXPECT_EQ(ret, HVB_IO_ERROR_IO); + ret = ops->read_rollback(ops, 0, &outRollbackIndex); + EXPECT_EQ(ret, HVB_IO_OK); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbWriteRollbackIdx_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + int ret = ops->write_rollback(ops, 0, 0); + EXPECT_EQ(ret, HVB_IO_OK); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbReadLockState_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + int ret = ops->read_lock_state(ops, nullptr); + EXPECT_EQ(ret, HVB_IO_OK); +} + +HWTEST_F(FsHvbUnitTest, Init_HvbGetSizeOfPartition_001, TestSize.Level0) +{ + struct hvb_ops *ops = FsHvbGetOps(); + int ret = ops->get_partiton_size(ops, "boot", nullptr); + uint64_t size; + EXPECT_EQ(ret, HVB_IO_ERROR_IO); + ret = ops->get_partiton_size(ops, "boot", &size); + EXPECT_EQ(ret, HVB_IO_OK); +} +} \ No newline at end of file diff --git a/test/unittest/init/cmds_unittest.cpp b/test/unittest/init/cmds_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ab4c3bae8627d48c3b4383955b8e983849ce97a --- /dev/null +++ b/test/unittest/init/cmds_unittest.cpp @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2021 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 "init_cmds.h" +#include "init_param.h" +#include "init_group_manager.h" +#include "param_stub.h" +#include "init_utils.h" +#include "trigger_manager.h" + +using namespace testing::ext; +using namespace std; + +static void DoCmdByName(const char *name, const char *cmdContent) +{ + int cmdIndex = 0; + (void)GetMatchCmd(name, &cmdIndex); + DoCmdByIndex(cmdIndex, cmdContent, nullptr); +} + +namespace init_ut { +class CmdsUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(CmdsUnitTest, TestCmdExecByName1, TestSize.Level1) +{ + DoCmdByName("timer_start ", "media_service|5000"); + DoCmdByName("timer_start ", "|5000"); + DoCmdByName("timer_stop ", "media_service"); + DoCmdByName("exec ", "media_service"); + DoCmdByName("syncexec ", "/system/bin/toybox"); + DoCmdByName("load_access_token_id ", "media_service"); + DoCmdByName("load_access_token_id ", ""); + DoCmdByName("stopAllServices ", "false"); + DoCmdByName("stopAllServices ", "true"); + DoCmdByName("umount ", "/2222222"); + DoCmdByName("mount ", "/2222222"); + DoCmdByName("mount ", "ext4 /2222222 /data wait filecrypt=555"); + DoCmdByName("umount ", "/2222222"); + DoCmdByName("init_global_key ", "/data"); + DoCmdByName("init_global_key ", "arg0 arg1"); + DoCmdByName("init_main_user ", "testUser"); + DoCmdByName("init_main_user ", nullptr); + DoCmdByName("mkswap ", "/data/init_ut"); + DoCmdByName("swapon ", "/data/init_ut"); + DoCmdByName("sync ", ""); + DoCmdByName("restorecon ", ""); + DoCmdByName("restorecon ", "/data /data"); + DoCmdByName("suspend ", ""); + DoCmdByName("wait ", "1"); + DoCmdByName("wait ", "aaa 1"); + DoCmdByName("mksandbox", "/sandbox"); + DoCmdByName("mount_fstab ", "/2222222"); + DoCmdByName("umount_fstab ", "/2222222"); + DoCmdByName("mknode ", "node1 node1 node1 node1 node1"); + DoCmdByName("makedev ", "/device1 device2"); + DoCmdByName("symlink ", "/xxx/xxx/xxx1 /xxx/xxx/xxx2"); + DoCmdByName("load_param ", "aaa onlyadd"); + DoCmdByName("load_persist_params ", ""); + DoCmdByName("load_param ", ""); + DoCmdByName("setparam ", "bbb 0"); + DoCmdByName("ifup ", "aaa, bbb"); + DoCmdByName("insmod ", "a b"); + DoCmdByName("insmod ", "/data /data"); +} + +HWTEST_F(CmdsUnitTest, TestCommonMkdir, TestSize.Level1) +{ + auto checkMkdirCmd = [=](const char *mkdirFile, const char *cmdLine) { + DoCmdByName("mkdir ", cmdLine); + return access(mkdirFile, F_OK); + }; + EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir0", "/data/init_ut/test_dir0"), 0); + EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir1", "/data/init_ut/test_dir1 0755"), 0); + EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir2", "/data/init_ut/test_dir2 0755 system system"), 0); + + // abnormal + EXPECT_NE(checkMkdirCmd("/data/init_ut/test_dir3", ""), 0); + EXPECT_NE(checkMkdirCmd("/data/init_ut/test_dir4", "/data/init_ut/test_dir4 0755 system"), 0); + EXPECT_EQ(checkMkdirCmd("/data/init_ut/test_dir5", "/data/init_ut/test_dir5 0755 error error"), 0); +} + +HWTEST_F(CmdsUnitTest, TestCommonChown, TestSize.Level1) +{ + const char *testFile = "/data/init_ut/test_dir0"; + DoCmdByName("chown ", "system system /data/init_ut/test_dir0"); + struct stat info = {}; + stat(testFile, &info); + const unsigned int systemUidGid = 1000; + EXPECT_EQ(info.st_uid, systemUidGid); + EXPECT_EQ(info.st_gid, systemUidGid); + + // abnormal + DoCmdByName("chown ", "error error /data/init_ut/test_dir0"); + stat(testFile, &info); + EXPECT_EQ(info.st_uid, systemUidGid); + EXPECT_EQ(info.st_gid, systemUidGid); +} + +HWTEST_F(CmdsUnitTest, TestCommonChmod, TestSize.Level1) +{ + const char *testFile = "/data/init_ut/test_dir0/test_file0"; + const mode_t testMode = S_IRWXU | S_IRWXG | S_IRWXO; + int fd = open(testFile, O_CREAT | O_WRONLY, testMode); + ASSERT_GE(fd, 0); + DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file0"); + struct stat info; + stat(testFile, &info); + EXPECT_EQ(testMode, testMode & info.st_mode); + + // abnormal + DoCmdByName("chmod ", "999 /data/init_ut/test_dir0/test_file0"); + stat(testFile, &info); + EXPECT_EQ(testMode, testMode & info.st_mode); + DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file001"); + + close(fd); +} + +HWTEST_F(CmdsUnitTest, TestCommonCopy, TestSize.Level1) +{ + const char *testFile1 = "/data/init_ut/test_dir0/test_file_copy1"; + DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file0 /data/init_ut/test_dir0/test_file_copy1"); + int fd = open(testFile1, O_RDWR); + ASSERT_GE(fd, 0); + write(fd, "aaa", strlen("aaa")); + + const char *testFile2 = "/data/init_ut/test_dir0/test_file_copy2"; + DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy2"); + int ret = access(testFile2, F_OK); + EXPECT_EQ(ret, 0); + close(fd); + // abnormal + DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy1"); + DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy11 /data/init_ut/test_dir0/test_file_copy1"); + DoCmdByName("copy ", "a"); + + DoCmdByName("chmod ", "111 /data/init_ut/test_dir0/test_file_copy1"); + DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy2"); + + DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file_copy1"); + DoCmdByName("chmod ", "111 /data/init_ut/test_dir0/test_file_copy2"); + DoCmdByName("copy ", "/data/init_ut/test_dir0/test_file_copy1 /data/init_ut/test_dir0/test_file_copy2"); + DoCmdByName("chmod ", "777 /data/init_ut/test_dir0/test_file_copy2"); +} + +HWTEST_F(CmdsUnitTest, TestCommonWrite, TestSize.Level1) +{ + const char *testFile1 = "/data/init_ut/test_dir0/test_file_write1"; + int fd = open(testFile1, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + ASSERT_GE(fd, 0); + + DoCmdByName("write ", "/data/init_ut/test_dir0/test_file_write1 aaa"); + const int bufLen = 50; + char buffer[bufLen]; + int length = read(fd, buffer, bufLen - 1); + EXPECT_EQ(length, strlen("aaa")); + close(fd); + // abnormal + DoCmdByName("write ", "/data/init_ut/test_dir0/test_file_write2 aaa 2"); +} + +HWTEST_F(CmdsUnitTest, TestCommonRm, TestSize.Level1) +{ + const char *testFile1 = "/data/init_ut/test_dir0/test_file_write1"; + DoCmdByName("rm ", testFile1); + int ret = access(testFile1, F_OK); + EXPECT_NE(ret, 0); + + testFile1 = "/data/init_ut/test_dir1"; + DoCmdByName("rmdir ", testFile1); + ret = access(testFile1, F_OK); + EXPECT_NE(ret, 0); + + // abnormal + DoCmdByName("rmdir ", testFile1); +} + +HWTEST_F(CmdsUnitTest, TestCommonExport, TestSize.Level1) +{ + DoCmdByName("export ", "TEST_INIT 1"); + EXPECT_STREQ("1", getenv("TEST_INIT")); + unsetenv("TEST_INIT"); + EXPECT_STRNE("1", getenv("TEST_INIT")); +} + +HWTEST_F(CmdsUnitTest, TestCommonMount, TestSize.Level1) +{ + DoCmdByName("mount ", "ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor " + "/vendor wait rdonly barrier=1"); + struct statvfs64 vfs {}; + int ret = statvfs64("/vendor", &vfs); + EXPECT_GE(ret, 0); + EXPECT_GT(vfs.f_bsize, 0); +} + +HWTEST_F(CmdsUnitTest, TestGetCmdKey, TestSize.Level1) +{ + const char *cmd1 = GetCmdKey(0); + EXPECT_STREQ(cmd1, "start "); +} + +HWTEST_F(CmdsUnitTest, TestDoCmdByIndex, TestSize.Level1) +{ + DoCmdByIndex(1, "/data/init_ut/test_cmd_dir0", nullptr); + int ret = access("/data/init_ut/test_cmd_dir0", F_OK); + EXPECT_EQ(ret, 0); + + const int execPos = 17; + DoCmdByIndex(execPos, "sleep 1", nullptr); + DoCmdByIndex(23, "test", nullptr); // 23 is cmd index +} + +HWTEST_F(CmdsUnitTest, TestGetCmdLinesFromJson, TestSize.Level1) +{ + const char *jsonStr = "{\"jobs\":[{\"name\":\"init\",\"cmds\":[\"sleep 1\",100,\"test321 123\"]}]}"; + cJSON* jobItem = cJSON_Parse(jsonStr); + ASSERT_NE(nullptr, jobItem); + cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, "jobs"); + ASSERT_NE(nullptr, cmdsItem); + ASSERT_TRUE(cJSON_IsArray(cmdsItem)); + + cJSON *cmdsItem1 = cJSON_GetArrayItem(cmdsItem, 0); + ASSERT_NE(nullptr, cmdsItem1); + CmdLines **cmdLines = (CmdLines **)calloc(1, sizeof(CmdLines *)); + ASSERT_NE(nullptr, cmdLines); + int ret = GetCmdLinesFromJson(cmdsItem1, cmdLines); + EXPECT_EQ(ret, -1); + cJSON *cmdsItem2 = cJSON_GetObjectItem(cmdsItem1, "cmds"); + ASSERT_NE(nullptr, cmdsItem2); + ret = GetCmdLinesFromJson(cmdsItem2, cmdLines); + EXPECT_EQ(ret, 0); + + cJSON_Delete(jobItem); + if (cmdLines[0] != nullptr) { + free(cmdLines[0]); + cmdLines[0] = nullptr; + } + free(cmdLines); + cmdLines = nullptr; +} + +HWTEST_F(CmdsUnitTest, TestInitCmdFunc, TestSize.Level1) +{ + int ret = GetBootModeFromMisc(); + EXPECT_EQ(ret, 0); + ret = SetFileCryptPolicy(nullptr); + EXPECT_NE(ret, 0); +} + +HWTEST_F(CmdsUnitTest, TestBuildStringFromCmdArg, TestSize.Level1) +{ + int strNum = 3; + struct CmdArgs *ctx = (struct CmdArgs *)calloc(1, sizeof(struct CmdArgs) + sizeof(char *) * (strNum)); + ctx->argc = strNum; + ctx->argv[0] = strdup("123456789012345678901234567890123456789012345678901234567890 \ + 1234567890123456789012345678901234567890123456789012345678901234567"); + ctx->argv[1] = strdup("test"); + ctx->argv[2] = nullptr; + char *options = BuildStringFromCmdArg(ctx, 0); + EXPECT_EQ(options[0], '\0'); + free(options); + + options = BuildStringFromCmdArg(ctx, 1); + EXPECT_STREQ(options, "test"); + free(options); + FreeCmdArg(ctx); +} + +HWTEST_F(CmdsUnitTest, TestInitDiffTime, TestSize.Level1) +{ + INIT_TIMING_STAT stat; + stat.startTime.tv_sec = 2; // 2 is test sec + stat.startTime.tv_nsec = 1000; // 1000 is test nsec + + stat.endTime.tv_sec = 3; // 3 is test sec + stat.endTime.tv_nsec = 0; + + long long diff = InitDiffTime(&stat); + EXPECT_TRUE(diff > 0); +} +} // namespace init_ut diff --git a/test/unittest/init/group_unittest.cpp b/test/unittest/init/group_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ed45d0195eb458c6d4532fa52773b3f45433487 --- /dev/null +++ b/test/unittest/init/group_unittest.cpp @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2021 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 "init_cmds.h" +#include "init_group_manager.h" +#include "init_hashmap.h" +#include "init_param.h" +#include "init_service_manager.h" +#include "init_utils.h" +#include "init_unittest.h" +#include "le_timer.h" +#include "param_stub.h" +#include "securec.h" +#include "control_fd.h" + +using namespace testing::ext; +using namespace std; + +typedef struct { + HashNode node; + char name[0]; +} TestHashNode; + +static int TestHashNodeCompare(const HashNode *node1, const HashNode *node2) +{ + TestHashNode *testNode1 = HASHMAP_ENTRY(node1, TestHashNode, node); + TestHashNode *testNode2 = HASHMAP_ENTRY(node2, TestHashNode, node); + return strcmp(testNode1->name, testNode2->name); +} + +static int TestHashKeyCompare(const HashNode *node1, const void *key) +{ + TestHashNode *testNode1 = HASHMAP_ENTRY(node1, TestHashNode, node); + return strcmp(testNode1->name, reinterpret_cast(const_cast(key))); +} + +static int TestHashNodeFunction(const HashNode *node) +{ + TestHashNode *testNode = HASHMAP_ENTRY(node, TestHashNode, node); + int code = 0; + size_t nameLen = strlen(testNode->name); + for (size_t i = 0; i < nameLen; i++) { + code += testNode->name[i] - 'A'; + } + return code; +} + +static int TestHashKeyFunction(const void *key) +{ + int code = 0; + const char *buff = static_cast(key); + size_t buffLen = strlen(buff); + for (size_t i = 0; i < buffLen; i++) { + code += buff[i] - 'A'; + } + return code; +} + +static void TestHashNodeFree(const HashNode *node, void *context) +{ + TestHashNode *testNode = HASHMAP_ENTRY(node, TestHashNode, node); + printf("TestHashNodeFree %s\n", testNode->name); + free(testNode); +} + +static TestHashNode *TestCreateHashNode(const char *value) +{ + TestHashNode *node = reinterpret_cast(malloc(sizeof(TestHashNode) + strlen(value) + 1)); + if (node == nullptr) { + return nullptr; + } + int ret = strcpy_s(node->name, strlen(value) + 1, value); + if (ret != 0) { + free(node); + return nullptr; + } + HASHMAPInitNode(&node->node); + return node; +} + +static void DoCmdByName(const char *name, const char *cmdContent) +{ + int cmdIndex = 0; + (void)GetMatchCmd(name, &cmdIndex); + DoCmdByIndex(cmdIndex, cmdContent, nullptr); +} + +namespace init_ut { +class InitGroupManagerUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HashInfo g_info = { + TestHashNodeCompare, + TestHashKeyCompare, + TestHashNodeFunction, + TestHashKeyFunction, + TestHashNodeFree, + 2 +}; + +HWTEST_F(InitGroupManagerUnitTest, TestHashMap001, TestSize.Level1) +{ + HashMapHandle handle; + OH_HashMapCreate(&handle, &g_info); + const char *str1 = "Test hash map node 1"; + const char *str2 = "Test hash map node 2"; + const char *str3 = "Test hash map node 3"; + TestHashNode *node1 = TestCreateHashNode(str1); + TestHashNode *node2 = TestCreateHashNode(str2); + OH_HashMapAdd(handle, &node1->node); + OH_HashMapAdd(handle, &node2->node); + HashNode *node = OH_HashMapGet(handle, (const void *)str1); + EXPECT_NE(node != nullptr, 0); + if (node) { + TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); + EXPECT_EQ(strcmp(tmp->name, str1), 0); + } + node = OH_HashMapGet(handle, (const void *)str2); + EXPECT_NE(node != nullptr, 0); + if (node) { + TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); + EXPECT_EQ(strcmp(tmp->name, str2), 0); + } + TestHashNode *node3 = TestCreateHashNode(str3); + OH_HashMapAdd(handle, &node3->node); + node3 = TestCreateHashNode("Test hash map node 4"); + OH_HashMapAdd(handle, &node3->node); + node3 = TestCreateHashNode("Test hash map node 5"); + OH_HashMapAdd(handle, &node3->node); + node = OH_HashMapGet(handle, (const void *)str3); + EXPECT_NE(node != nullptr, 0); + if (node) { + TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); + EXPECT_EQ(strcmp(tmp->name, str3), 0); + } + OH_HashMapIsEmpty(handle); + OH_HashMapTraverse(handle, [](const HashNode *node, const void *context) {return;}, nullptr); + OH_HashMapDestory(handle, nullptr); +} + +HWTEST_F(InitGroupManagerUnitTest, TestHashMap002, TestSize.Level1) +{ + HashMapHandle handle; + OH_HashMapCreate(&handle, &g_info); + TestHashNode *node4 = TestCreateHashNode("pre-init"); + OH_HashMapAdd(handle, &node4->node); + OH_HashMapRemove(handle, "pre-init"); + TestHashNodeFree(&node4->node, nullptr); + + const char *act = "load_persist_props_action"; + TestHashNode *node5 = TestCreateHashNode(act); + OH_HashMapAdd(handle, &node5->node); + HashNode *node = OH_HashMapGet(handle, (const void *)act); + EXPECT_NE(node != nullptr, 0); + if (node) { + TestHashNode *tmp = HASHMAP_ENTRY(node, TestHashNode, node); + EXPECT_EQ(strcmp(tmp->name, act), 0); + } + OH_HashMapIsEmpty(handle); + OH_HashMapTraverse(handle, [](const HashNode *node, const void *context) {return;}, nullptr); + OH_HashMapDestory(handle, nullptr); +} + +HWTEST_F(InitGroupManagerUnitTest, TestInitGroupMgrInit, TestSize.Level1) +{ + InitServiceSpace(); + InitWorkspace *workspace = GetInitWorkspace(); + EXPECT_EQ(workspace->groupMode, GROUP_BOOT); + workspace->groupMode = GROUP_BOOT; + if (strcpy_s(workspace->groupModeStr, GROUP_NAME_MAX_LENGTH, "device.boot.group") != EOK) { + EXPECT_EQ(1, 0); + } + // test read cfgfile + int ret = InitParseGroupCfg(); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(InitGroupManagerUnitTest, TestAddService, TestSize.Level1) +{ + const char *serviceStr = "{" + "\"services\": [{" + "\"name\" : \"test-service\"," + "\"path\" : [\"/dev/test_service\"]," + "\"start-mode\" : \"condition\"," + "\"end-mode\" : \"after-exec\"," + "\"console\":1," + "\"writepid\":[\"/dev/test_service\"]," + "\"jobs\" : {" + "\"on-boot\" : \"boot:bootjob1\"," + "\"on-start\" : \"service:startjob\"," + "\"on-stop\" : \"service:stopjob\"," + "\"on-restart\" : \"service:restartjob\"" + "}" + "},{" + "\"name\" : \"test-service2\"," + "\"path\" : [\"/dev/test_service\"]," + "\"console\":1," + "\"start-mode\" : \"boot\"," + "\"writepid\":[\"/dev/test_service\"]," + "\"jobs\" : {" + "\"on-boot\" : \"boot:bootjob1\"," + "\"on-start\" : \"service:startjob\"," + "\"on-stop\" : \"service:stopjob\"," + "\"on-restart\" : \"service:restartjob\"" + "}" + "}]" + "}"; + + cJSON *fileRoot = cJSON_Parse(serviceStr); + ASSERT_NE(nullptr, fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); + cJSON_Delete(fileRoot); + + Service *service = GetServiceByName("test-service"); + ServiceStartTimer(service, 1); + ServiceStopTimer(service); + ASSERT_NE(service != nullptr, 0); + EXPECT_EQ(service->startMode, START_MODE_CONDITION); + ReleaseService(service); + service = GetServiceByName("test-service2"); + ASSERT_NE(service != nullptr, 0); + EXPECT_EQ(service->startMode, START_MODE_BOOT); + ReleaseService(service); +} + +/** + * @brief + * + + "socket" : [{ + "name" : "ueventd", + "family" : "AF_INET", // AF_INET,AF_INET6,AF_UNIX(AF_LOCAL),AF_NETLINK + "type" : : "SOCK_STREAM", // SOCK_STREAM,SOCK_DGRAM,SOCK_RAW,SOCK_PACKET,SOCK_SEQPACKET + "protocol" : "IPPROTO_TCP", // IPPROTO_TCP,IPPTOTO_UDP,IPPROTO_SCTP,PPROTO_TIPC + "permissions" : "0660", + "uid" : "system", + "gid" : "system", + "option" : { + "passcred" : "true", + "rcvbufforce" : "", + "cloexec" : "", + "nonblock : "" + } + }], + */ +HWTEST_F(InitGroupManagerUnitTest, TestAddServiceDeny, TestSize.Level1) +{ + const char *serviceStr = "{" + "\"services\": [{" + "\"name\" : \"test-service5\"," + "\"path\" : [\"/dev/test_service\"]," + "\"start-mode\" : \"by-condition\"," + "\"end-mode\" : \"ready\"," + "\"console\":1," + "\"writepid\":[\"/dev/test_service\"]," + "\"jobs\" : {" + "\"on-boot\" : \"boot:bootjob1\"," + "\"on-start\" : \"service:startjob\"," + "\"on-stop\" : \"service:stopjob\"," + "\"on-restart\" : \"service:restartjob\"" + "}" + "}]" + "}"; + InitWorkspace *workspace = GetInitWorkspace(); + workspace->groupMode = GROUP_CHARGE; + + cJSON *fileRoot = cJSON_Parse(serviceStr); + ASSERT_NE(nullptr, fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); + cJSON_Delete(fileRoot); + + Service *service = GetServiceByName("test-service5"); + ASSERT_EQ(service, nullptr); + workspace->groupMode = GROUP_BOOT; +} + +HWTEST_F(InitGroupManagerUnitTest, TestAddService2, TestSize.Level1) +{ + const char *serviceStr = "{" + "\"services\": [{" + "\"name\" : \"test-service6\"," + "\"path\" : [\"/dev/test_service\"]," + "\"console\":1," + "\"writepid\":[\"/dev/test_service\"]," + "\"jobs\" : {" + "\"on-boot\" : \"boot:bootjob1\"," + "\"on-start\" : \"service:startjob\"," + "\"on-stop\" : \"service:stopjob\"," + "\"on-restart\" : \"service:restartjob\"" + "}" + "}]" + "}"; + + InitWorkspace *workspace = GetInitWorkspace(); + workspace->groupMode = GROUP_CHARGE; + + InitGroupNode *node = AddGroupNode(NODE_TYPE_SERVICES, "test-service6"); + ASSERT_NE(nullptr, node); + + cJSON *fileRoot = cJSON_Parse(serviceStr); + ASSERT_NE(nullptr, fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); + cJSON_Delete(fileRoot); + char cmdStr[] = "all#bootevent"; + char cmdStr1[] = "parameter_service"; + ProcessControlFd(ACTION_DUMP, "all", nullptr); + ProcessControlFd(ACTION_DUMP, cmdStr, nullptr); + ProcessControlFd(ACTION_DUMP, cmdStr1, nullptr); + ProcessControlFd(ACTION_SANDBOX, cmdStr, nullptr); + ProcessControlFd(ACTION_MODULEMGR, cmdStr, nullptr); + ProcessControlFd(ACTION_MAX, cmdStr, nullptr); + Service *service = GetServiceByName("test-service6"); + ASSERT_NE(service, nullptr); + workspace->groupMode = GROUP_BOOT; +} + +HWTEST_F(InitGroupManagerUnitTest, TestParseServiceCpucore, TestSize.Level1) +{ + const char *jsonStr = "{\"services\":{\"name\":\"test_service22\",\"path\":[\"/data/init_ut/test_service\"]," + "\"importance\":-20,\"uid\":\"root\",\"writepid\":[\"/dev/test_service\"],\"console\":1," + "\"gid\":[\"root\"], \"cpucore\":[5, 2, 4, 1, 2, 0, 1], \"critical\":[1]}}"; + cJSON* jobItem = cJSON_Parse(jsonStr); + ASSERT_NE(nullptr, jobItem); + cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + Service *service = AddService("test_service22"); + const int invalidImportantValue = 20; + SetImportantValue(service, "", invalidImportantValue, 1); + if (service != nullptr) { + int ret = ParseOneService(serviceItem, service); + GetAccessToken(); + DoCmdByName("timer_start ", "test_service22|5000"); + DoCmdByName("timer_start ", "test_service22|aa"); + DoCmdByName("timer_start ", ""); + EXPECT_EQ(ret, 0); + StartServiceByName("test_service22|path"); + ReleaseService(service); + } + cJSON_Delete(jobItem); +} + +HWTEST_F(InitGroupManagerUnitTest, TestUpdaterServiceFds, TestSize.Level1) +{ + Service *service = AddService("test_service8"); + ASSERT_NE(nullptr, service); + int fds[1] = { -1 }; // ServiceStop will release fds + UpdaterServiceFds(nullptr, nullptr, 0); + UpdaterServiceFds(service, fds, 1); + UpdaterServiceFds(service, fds, 0); + UpdaterServiceFds(service, fds, 1); + UpdaterServiceFds(service, nullptr, 1); + UpdaterServiceFds(service, fds, 1); + int ret = UpdaterServiceFds(service, nullptr, 2); // 2 is fd num + ASSERT_NE(ret, 0); + service->attribute = SERVICE_ATTR_TIMERSTART; + ServiceStartTimer(service, 0); +} +HWTEST_F(InitGroupManagerUnitTest, TestProcessWatchEvent, TestSize.Level1) +{ + Service *service = AddService("test_service9"); + ASSERT_NE(nullptr, service); + ServiceSocket servercfg = {.next = nullptr, .sockFd = 0}; + service->socketCfg = &servercfg; + ServiceWatcher watcher; + int ret = AddSocketWatcher(&watcher, service, 0); + ASSERT_EQ(ret, 0); + uint32_t event; + ((WatcherTask *)watcher)->processEvent((WatcherHandle)watcher, 0, &event, service); + service->socketCfg = nullptr; +} + +HWTEST_F(InitGroupManagerUnitTest, TestCheckNodeValid, TestSize.Level1) +{ + int ret = CheckNodeValid(NODE_TYPE_MAX, "charger"); + EXPECT_EQ(ret, -1); + ret = CheckNodeValid(NODE_TYPE_PLUGINS, "charger"); + EXPECT_EQ(ret, -1); +} + +HWTEST_F(InitGroupManagerUnitTest, TestGetGroupHashMap, TestSize.Level1) +{ + HashMapHandle handle = GetGroupHashMap(NODE_TYPE_GROUPS); + EXPECT_TRUE(handle == nullptr); +} +} // namespace init_ut diff --git a/test/unittest/init/init_reboot_unittest.cpp b/test/unittest/init/init_reboot_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aca4010520e433e7136f7d54b4cb6ccc10cc74f6 --- /dev/null +++ b/test/unittest/init/init_reboot_unittest.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021 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 "init_cmds.h" +#include "init_reboot.h" +#include "init_param.h" +#include "param_stub.h" +#include "init_utils.h" +#include "trigger_manager.h" +#include "init_group_manager.h" +#include "init_cmdexecutor.h" +#include "reboot_adp.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class InitRebootUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +#ifndef OHOS_LITE +static int g_result = 0; +HWTEST_F(InitRebootUnitTest, TestAddRebootCmdExt, TestSize.Level1) +{ + auto rebootCallback = [](int id, const char *name, int argc, const char **argv) -> int { + return 0; + }; + int ret = AddRebootCmdExecutor("reboot_cmd1", rebootCallback); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd2", rebootCallback); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd3", rebootCallback); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd4", [](int id, const char *name, int argc, const char **argv)-> int { + g_result = 4; // 4 test index + return 0; + }); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd5", [](int id, const char *name, int argc, const char **argv)-> int { + g_result = 5; // 5 test index + return 0; + }); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd6", [](int id, const char *name, int argc, const char **argv)-> int { + g_result = 6; // 6 test index + return 0; + }); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd7", rebootCallback); + EXPECT_EQ(ret, 0); + ret = AddRebootCmdExecutor("reboot_cmd7", rebootCallback); + EXPECT_NE(ret, 0); + + TestSetParamCheckResult("ohos.servicectrl.reboot", 0777, 0); + // exec + SystemWriteParam("ohos.startup.powerctrl", "reboot,reboot_cmd4"); + EXPECT_EQ(g_result, 4); // 4 test index + SystemWriteParam("ohos.startup.powerctrl", "reboot,reboot_cmd5"); + EXPECT_EQ(g_result, 5); // 5 test index + SystemWriteParam("ohos.startup.powerctrl", "reboot,reboot_cmd6"); + EXPECT_EQ(g_result, 6); // 6 test index + + // invalid test + ret = AddRebootCmdExecutor(nullptr, [](int id, const char *name, int argc, const char **argv)-> int { + printf("reboot_cmd7 %s", name); + return 0; + }); + EXPECT_NE(ret, 0); + ret = AddRebootCmdExecutor(nullptr, nullptr); + EXPECT_NE(ret, 0); +} + +HWTEST_F(InitRebootUnitTest, TestAddRebootCmdNormal, TestSize.Level1) +{ + SystemWriteParam("ohos.startup.powerctrl", "reboot"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,shutdown"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,suspend"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,charge"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,updater"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,updater:2222222"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,flashd"); + SystemWriteParam("ohos.startup.powerctrl", "reboot,flashd:1000000"); +} + +HWTEST_F(InitRebootUnitTest, TestRebootCmdExec, TestSize.Level1) +{ + PARAM_LOGE("TestRebootCmdExec"); + PluginExecCmdByName("reboot", "reboot"); + PluginExecCmdByName("reboot.shutdown", "reboot,shutdown"); + PluginExecCmdByName("reboot.shutdown", "reboot,shutdown:333333333333"); + PluginExecCmdByName("reboot.suspend", "reboot,suspend"); + PluginExecCmdByName("reboot.charge", "reboot,charge"); + PluginExecCmdByName("reboot.updater", "reboot,updater"); + PluginExecCmdByName("reboot.updater", "reboot,updater:2222222"); + PluginExecCmdByName("reboot.flashd", "reboot,flashd"); + PluginExecCmdByName("reboot.flashd", "reboot,flashd:1000000"); + PluginExecCmdByName("reboot.panic", "reboot,panic"); + PluginExecCmdByName("reboot.stop", "reboot,stop"); + PluginExecCmdByName("reboot.other", "reboot,other"); + PARAM_LOGE("TestRebootCmdExec end"); + int ret = UpdateMiscMessage("charge:wwwwwwwwwww", "charge", "charge:", "boot_charge"); + if (ret == 0) { + ret = GetBootModeFromMisc(); + EXPECT_EQ(ret, GROUP_CHARGE); + clearMisc(); + } +} +#endif + +HWTEST_F(InitRebootUnitTest, TestInitReboot, TestSize.Level1) +{ + ExecReboot("reboot"); + ExecReboot("reboot,shutdown"); + ExecReboot("reboot,bootloader"); + ExecReboot("reboot,updater:123"); + ExecReboot("reboot,flash:123"); + ExecReboot("reboot,flashd:123"); + ExecReboot("reboot,suspend:123"); + const char *option = nullptr; + int ret = DoReboot(option); + EXPECT_EQ(ret, 0); + option = "updater"; + ret = DoReboot(option); + EXPECT_EQ(ret, 0); + ret = DoReboot(DEVICE_CMD_SUSPEND); + EXPECT_EQ(ret, 0); + ret = DoReboot(DEVICE_CMD_FREEZE); + EXPECT_EQ(ret, 0); + + ret = DoRebootExt("shutdown", DEVICE_CMD_FREEZE); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(InitRebootUnitTest, TestAbnormalReboot, TestSize.Level1) +{ + int ret = DoRoot_(nullptr, 0); + EXPECT_EQ(ret, 0); + + ret = DoRebootShutdown(0, nullptr, 0, nullptr); + EXPECT_EQ(ret, -1); + + ret = DoRebootFlashed(0, nullptr, 0, nullptr); + EXPECT_EQ(ret, -1); + + ret = DoRebootOther(0, nullptr, 0, nullptr); + EXPECT_EQ(ret, -1); +} +} // namespace init_ut diff --git a/test/unittest/init/init_unittest.cpp b/test/unittest/init/init_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90c73c9a4c5970309e3e787e05f49beca17952f0 --- /dev/null +++ b/test/unittest/init/init_unittest.cpp @@ -0,0 +1,146 @@ +/* + * 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 "init_unittest.h" + +#include +#include +#include + +#include +#include +#include + +#include "init.h" +#include "device.h" +#include "init_cmds.h" +#include "init_log.h" +#include "init_service.h" +#include "init_adapter.h" +#include "init_utils.h" +#include "loop_event.h" +#include "param_stub.h" +#include "fs_manager/fs_manager.h" +#include "fd_holder.h" +#include "fd_holder_service.h" +#include "bootstage.h" +#include "parameter.h" + +using namespace testing::ext; +using namespace std; + +extern "C" { +INIT_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo); +} + +namespace init_ut { +class InitUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(InitUnitTest, TestSignalHandle, TestSize.Level1) +{ + struct signalfd_siginfo siginfo; + siginfo.ssi_signo = SIGCHLD; + ProcessSignal(&siginfo); + siginfo.ssi_signo = SIGTERM; + ProcessSignal(&siginfo); + siginfo.ssi_signo = SIGUSR1; + ProcessSignal(&siginfo); + SUCCEED(); +} + +HWTEST_F(InitUnitTest, TestSystemPrepare, TestSize.Level1) +{ + SetStubResult(STUB_MOUNT, -1); + SetStubResult(STUB_MKNODE, -1); + CreateFsAndDeviceNode(); + + SetStubResult(STUB_MOUNT, 0); + SetStubResult(STUB_MKNODE, 0); + CreateFsAndDeviceNode(); +} + +HWTEST_F(InitUnitTest, TestSystemExecRcs, TestSize.Level1) +{ + SystemExecuteRcs(); + Service *service = GetServiceByName("param_watcher"); + int ret = KeepCapability(service); + EXPECT_EQ(ret, 0); + ret = SetAmbientCapability(34); // CAP_SYSLOG + EXPECT_EQ(ret, 0); +} + +static void TestProcessTimer(const TimerHandle taskHandle, void *context) +{ + static int count = 0; + printf("ProcessTimer %d\n", count); + if (count == 0) { // 2 stop + // set service pid for test + Service *service = GetServiceByName("param_watcher"); + if (service != nullptr) { + service->pid = getpid(); + } + int fds1[] = {1, 0}; + ServiceSaveFd("param_watcher", fds1, ARRAY_LENGTH(fds1)); + ServiceSaveFdWithPoll("param_watcher", fds1, 0); + ServiceSaveFdWithPoll("param_watcher", fds1, ARRAY_LENGTH(fds1)); + EXPECT_EQ(setenv("OHOS_FD_HOLD_param_watcher", "1 0", 0), 0); + + size_t fdCount = 0; + int *fds = ServiceGetFd("param_watcher", &fdCount); + EXPECT_TRUE(fds != nullptr); + free(fds); + + ServiceSaveFd("testservice", fds1, ARRAY_LENGTH(fds1)); + ServiceSaveFd("deviceinfoservice", fds1, ARRAY_LENGTH(fds1)); + } + if (count == 1) { + LE_StopTimer(LE_GetDefaultLoop(), taskHandle); + LE_StopLoop(LE_GetDefaultLoop()); + } + count++; +} + +HWTEST_F(InitUnitTest, TestFdHoldService, TestSize.Level1) +{ + RegisterFdHoldWatcher(-1); + TimerHandle timer = nullptr; + int ret = LE_CreateTimer(LE_GetDefaultLoop(), &timer, TestProcessTimer, nullptr); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(LE_GetDefaultLoop(), timer, 500, 4); + EXPECT_EQ(ret, 0); + SystemRun(); +} + +HWTEST_F(InitUnitTest, TestInitLog, TestSize.Level1) +{ + // test log + CheckAndCreateDir(INIT_LOG_PATH); + SetInitLogLevel(INIT_DEBUG); + INIT_LOGI("TestInitLog"); + INIT_LOGV("TestInitLog"); + INIT_LOGE("TestInitLog"); + INIT_LOGW("TestInitLog"); + INIT_LOGF("TestInitLog"); + // restore log level + int32_t loglevel = GetIntParameter("persist.init.debug.loglevel", INIT_ERROR); + SetInitLogLevel((InitLogLevel)loglevel); +} +} diff --git a/test/unittest/init/mount_unittest.cpp b/test/unittest/init/mount_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6993672a3d00487436d1e3791cebbeb4dee16fd8 --- /dev/null +++ b/test/unittest/init/mount_unittest.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 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 "fs_manager/fs_manager.h" +#include "param_stub.h" +#include "init_mount.h" +#include "init.h" +#include "securec.h" +using namespace std; +using namespace testing::ext; + +namespace init_ut { +class MountUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(MountUnitTest, TestGetBlockDevicePath, TestSize.Level1) +{ + char path[20] = {0}; // 20 is path length + int fd = open("/bin/updater", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRWXU); + if (fd < 0) { + return; + } + GetBlockDevicePath("/test", path, sizeof(path)); + close(fd); + ReadConfig(); + unlink("/bin/updater"); + ReadConfig(); + int ret = GetBlockDeviceByMountPoint(nullptr, nullptr, nullptr, 0); + EXPECT_EQ(ret, -1); + FstabItem fstabitem = {(char *)"deviceName", (char *)"mountPoint", + (char *)"fsType", (char *)"mountOptions", 1, nullptr}; + Fstab fstab = {&fstabitem}; + char devicename[20]; // 20 is devicename length + ret = GetBlockDeviceByMountPoint("notmountpoint", &fstab, devicename, sizeof(devicename)); + EXPECT_EQ(ret, -1); + ret = GetBlockDeviceByMountPoint("mountPoint", &fstab, devicename, 0); + EXPECT_EQ(ret, -1); + ret = GetBlockDeviceByMountPoint("mountPoint", &fstab, devicename, sizeof(devicename)); + EXPECT_EQ(ret, 0); +} +HWTEST_F(MountUnitTest, TestInvalidParam, TestSize.Level1) +{ + int ret = MountRequriedPartitions(nullptr); + EXPECT_NE(ret, 0); +} +} // namespace init_ut diff --git a/test/unittest/init/sandbox_unittest.cpp b/test/unittest/init/sandbox_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd7ced0c4906481c6202eb3e23119a8b19aafc37 --- /dev/null +++ b/test/unittest/init/sandbox_unittest.cpp @@ -0,0 +1,279 @@ +/* + * 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 "init_unittest.h" +#include "cJSON.h" +#include "sandbox.h" +#include "sandbox_namespace.h" +#include "securec.h" + +using namespace testing::ext; +namespace init_ut { +const int NULL_ROOT_PATH = 1; +const int NULL_MOUNT_FLAGS = 2; +const int NULL_MOUNT = 3; +const int NULL_MOUNT_ITEM = 13; +const int LINK_ARRARY_START = 5; +const int LINK_ARRARY_END = 8; +const int FLAGS_NUMBER = 3; + +const char *TEST_SANDBOX_NAME = "test"; +const char *SANDBOX_JSON_NAME = "test-sandbox.json"; + +const char *SANDBOX_CONFIG[] = {"sandbox-root", "mount-bind-paths", "mount-bind-files", "symbol-links"}; +const char *SANDBOX_ROOT[] = { "/mnt/sandbox/test", "/mnt/sandbox/chipset", "/mnt/error"}; +const char *SANDBOX_FLAGS[] = {"bind", "rec", "private"}; +const char *MOUNT_BIND_PATHS[] = {"src-path", "sandbox-path", "sandbox-flags"}; +const char *SYMBOL_LINKS[] = {"target-name", "link-name"}; +const char *APP_PATHS[] = {"/mnt", "/sys", "/proc", "/dev", "/data", + "/system/bin", "/system/lib", "/system/etc", "/system"}; + +int RestartSandbox(const char *sandbox) +{ + if (sandbox == nullptr) { + std::cout << "invalid parameters" << std::endl; + return 0; + } + InitDefaultNamespace(); + std::cout << "init namespace" << std::endl; + if (!InitSandboxWithName(sandbox)) { + CloseDefaultNamespace(); + std::cout << "Failed to init sandbox with name " << sandbox << std::endl; + return 0; + } + std::cout << "init sandbox with name" << std::endl; + DumpSandboxByName(sandbox); + std::cout << "dump sandbox" << std::endl; + if (PrepareSandbox(sandbox) != 0) { + std::cout << "Failed to prepare sandbox " << sandbox << std::endl; + DestroySandbox(sandbox); + CloseDefaultNamespace(); + return 0; + } + std::cout << "prepare sandbox" << std::endl; + if (EnterDefaultNamespace() < 0) { + std::cout << "Failed to set default namespace" << std::endl; + DestroySandbox(sandbox); + CloseDefaultNamespace(); + return 0; + } + std::cout << "enter default namespace" << std::endl; + CloseDefaultNamespace(); + std::cout << "close namespace" << std::endl; + return 1; +} + +cJSON *MakeSandboxJson(const char *sandboxFileName, const int MODE) +{ + cJSON *mJsonSandbox = cJSON_CreateObject(); // json file object + cJSON *mJsonMtBdPth = cJSON_CreateArray(); // mount-bind-paths + cJSON *mJsonMtBdFl = cJSON_CreateArray(); // mount-bind-files + cJSON *mJsonSymLk = cJSON_CreateArray(); // symbol-links + cJSON *mJsonMtBdPthItmSdxFlg = cJSON_CreateArray(); // mount-bind-paths items sandbox-flags + cJSON *mJsonMtBdFlItm = cJSON_CreateObject(); // mount-bind-files items + + if (mJsonSandbox == nullptr || mJsonMtBdPth == nullptr || mJsonMtBdFl == nullptr || + mJsonSymLk == nullptr || mJsonMtBdPthItmSdxFlg == nullptr || mJsonMtBdFlItm == nullptr) { + std::cout << "create json object error" << std::endl; + return nullptr; + } + cJSON *mJsonMtBdPth_Itm; // point to mount-bind-paths items + cJSON *mJsonSymLk_Itm; // point to symbol-links items + + // drop root path + if (MODE != NULL_ROOT_PATH) { + cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[0], cJSON_CreateString(SANDBOX_ROOT[0])); + } + + // assemble SANDBOX_FLAGS + if (MODE != NULL_MOUNT_FLAGS) { + for (int i = 0; i < FLAGS_NUMBER; i++) { + cJSON_AddItemToArray(mJsonMtBdPthItmSdxFlg, cJSON_CreateString(SANDBOX_FLAGS[i])); + } + } + + // assemble mount-bind-paths items + // Append items to mount-bind-paths + for (size_t i = 0; i < (sizeof(APP_PATHS) / sizeof(char *)); i++) { + cJSON_AddItemToArray(mJsonMtBdPth, mJsonMtBdPth_Itm = cJSON_CreateObject()); + int MOUNT_FLAG_COUNT = 2; + if (MODE != NULL_MOUNT_ITEM) { + cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[0], cJSON_CreateString(APP_PATHS[i])); + cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[1], cJSON_CreateString(APP_PATHS[i])); + } else { + cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[0], nullptr); + cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[1], nullptr); + } + cJSON_AddItemToObject(mJsonMtBdPth_Itm, MOUNT_BIND_PATHS[MOUNT_FLAG_COUNT], mJsonMtBdPthItmSdxFlg); + } + if (MODE != NULL_MOUNT) { + cJSON_AddItemToObject(mJsonMtBdFlItm, SANDBOX_CONFIG[1], cJSON_CreateString("/data/init_ut/testsandboxfile")); + // Append items to mount-bind-files + cJSON_AddItemToArray(mJsonMtBdFl, mJsonMtBdFlItm); + // assemble symbol-links items + for (int i = LINK_ARRARY_START; i < LINK_ARRARY_END; i++) { + // Append items to symbol-links + cJSON_AddItemToArray(mJsonSymLk, mJsonSymLk_Itm = cJSON_CreateObject()); + cJSON_AddItemToObject(mJsonSymLk_Itm, SYMBOL_LINKS[0], cJSON_CreateString(APP_PATHS[i])); + cJSON_AddItemToObject(mJsonSymLk_Itm, SYMBOL_LINKS[1], cJSON_CreateString(APP_PATHS[i])); + } + } + + // at last, assemble the json file + int count = 1; + cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[count++], mJsonMtBdPth); + cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[count++], mJsonMtBdFl); + cJSON_AddItemToObject(mJsonSandbox, SANDBOX_CONFIG[count], mJsonSymLk); + return mJsonSandbox; +} + +bool MakeFileByJson(cJSON * mJson, const char *sandboxFileName) +{ + const std::string sandboxJsonPth = std::string("/data/init_ut/") + std::string(sandboxFileName); + const char* cSandboxJsonPth = sandboxJsonPth.c_str(); + int fd = open(cSandboxJsonPth, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); + if (fd < 0) { + std::cout << "open sandbox json file failed" << std::endl; + return false; + } + + char *cjValue1 = cJSON_Print(mJson); + int ret1 = write(fd, cjValue1, strlen(cjValue1)); + if (-1 == ret1) { + std::cout << "Write file ERROR" << errno << " fd is :" << fd << std::endl; + close(fd); + return false; + } + free(cjValue1); + close(fd); + return true; +} + +class SandboxUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(SandboxUnitTest, TestCreateNormalSandbox, TestSize.Level1) { + cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, 0); + if (mJson == nullptr) { + std::cout << "created mJson error, mJson is null." << std::endl; + return; + } + MakeFileByJson(mJson, SANDBOX_JSON_NAME); + int ret = RestartSandbox(TEST_SANDBOX_NAME); + ASSERT_EQ(ret, 0); +} + +HWTEST_F(SandboxUnitTest, TestEnterErrorSandbox, TestSize.Level1) { + int ret1 = EnterSandbox("error_system"); + ASSERT_EQ(ret1, -1); + const char *pname = nullptr; + int ret2 = EnterSandbox(pname); + ASSERT_EQ(ret2, -1); + DestroySandbox(TEST_SANDBOX_NAME); + int ret3 = EnterSandbox(TEST_SANDBOX_NAME); + ASSERT_EQ(ret3, -1); +} + +HWTEST_F(SandboxUnitTest, TestCreateErrorSandbox1, TestSize.Level1) { + const char *pname = nullptr; + std::cout << "test destroy nullptr" << std::endl; + DestroySandbox(pname); + std::cout << "test destroy xapp" << std::endl; + DestroySandbox("xapp"); + std::cout << "test enter xapp" << std::endl; + int ret1 = EnterSandbox("xapp"); + ASSERT_EQ(ret1, -1); + bool result = InitSandboxWithName(pname); + ASSERT_FALSE(result); + DumpSandboxByName(pname); + DumpSandboxByName("xpp"); + result = InitSandboxWithName("xapp"); + ASSERT_FALSE(result); +} + +HWTEST_F(SandboxUnitTest, TestCreateErrorSandbox2, TestSize.Level1) { + cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, NULL_ROOT_PATH); + if (mJson == nullptr) { + std::cout << "created mJson error, mJson is null." << std::endl; + return; + } + bool ret1 = MakeFileByJson(mJson, SANDBOX_JSON_NAME); + ASSERT_TRUE(ret1); + InitSandboxWithName(TEST_SANDBOX_NAME); + int ret = PrepareSandbox(TEST_SANDBOX_NAME); + ASSERT_EQ(ret, -1); + ret = PrepareSandbox("xapp"); + ASSERT_EQ(ret, -1); +} + +HWTEST_F(SandboxUnitTest, TestCreateSandboxNoneJsonError, TestSize.Level1) { + unlink("/etc/sandbox/test-sandbox.json"); + int ret = PrepareSandbox(TEST_SANDBOX_NAME); + ASSERT_EQ(ret, -1); +} + +HWTEST_F(SandboxUnitTest, TestCreateSandboxMountFlagsError, TestSize.Level1) { + cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, NULL_MOUNT_FLAGS); + if (mJson == nullptr) { + std::cout << "created mJson error, mJson is null." << std::endl; + return; + } + MakeFileByJson(mJson, SANDBOX_JSON_NAME); + int ret = PrepareSandbox(TEST_SANDBOX_NAME); + ASSERT_EQ(ret, -1); +} + +HWTEST_F(SandboxUnitTest, TestCreateSandboxMountNULLError, TestSize.Level1) { + cJSON *mJson = MakeSandboxJson(SANDBOX_JSON_NAME, NULL_MOUNT_ITEM); + if (mJson == nullptr) { + std::cout << "created mJson error, mJson is null." << std::endl; + return; + } + MakeFileByJson(mJson, SANDBOX_JSON_NAME); + int ret = PrepareSandbox(TEST_SANDBOX_NAME); + ASSERT_EQ(ret, -1); + InitSandboxWithName(TEST_SANDBOX_NAME); + ASSERT_EQ(ret, -1); +} + +HWTEST_F(SandboxUnitTest, TestUnshareNamespace, TestSize.Level1) { + int ret1 = UnshareNamespace(-1); + ASSERT_EQ(ret1, -1); +} + +HWTEST_F(SandboxUnitTest, TestSetNamespace, TestSize.Level1) { + int ret1 = SetNamespace(-1, 1); + ASSERT_EQ(ret1, -1); + ret1 = SetNamespace(1, -1); + ASSERT_EQ(ret1, -1); +} + +HWTEST_F(SandboxUnitTest, TestGetNamespaceFd, TestSize.Level1) { + int ret1 = GetNamespaceFd(""); + GetNamespaceFd(nullptr); + ASSERT_EQ(ret1, -1); + const std::string sandboxJsonPth = std::string("/mnt/sandbox/") + std::string(TEST_SANDBOX_NAME); + const char* cSandboxJsonPth = sandboxJsonPth.c_str(); + ret1 = GetNamespaceFd(cSandboxJsonPth); + EXPECT_GT(ret1, 1); +} +} diff --git a/test/unittest/init/service_file_unittest.cpp b/test/unittest/init/service_file_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92558d4e00fdd6c14522a01d465e22ca5d4f7879 --- /dev/null +++ b/test/unittest/init/service_file_unittest.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021 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 "init_file.h" +#include "init_service.h" +#include "init_service_file.h" +#include "init_service_manager.h" +#include "param_stub.h" +#include "securec.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class ServiceFileUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(ServiceFileUnitTest, TestServiceFile, TestSize.Level1) +{ + const char *fileName = "/data/filetest"; + ServiceFile *fileOpt = (ServiceFile *)calloc(1, sizeof(ServiceFile) + strlen(fileName) + 1); + ASSERT_NE(fileOpt, nullptr); + fileOpt->next = nullptr; + fileOpt->flags = O_RDWR; + fileOpt->uid = 1000; + fileOpt->gid = 1000; + fileOpt->fd = -1; + fileOpt->perm = 0770; + int ret = strncpy_s(fileOpt->fileName, strlen(fileName) + 1, fileName, strlen(fileName)); + EXPECT_EQ(ret, 0); + Service *service = AddService("test_service8"); + ASSERT_NE(nullptr, service); + + service->fileCfg = fileOpt; + CreateServiceFile(service); + ret = GetControlFile("/data/filetest"); + EXPECT_NE(ret, -1); + ret = strncpy_s(fileOpt->fileName, strlen(fileName) + 1, "fileName", strlen("fileName")); + EXPECT_EQ(ret, 0); + fileOpt->fd = 100; // 100 is fd + CreateServiceFile(service); + CloseServiceFile(fileOpt); + ret = strncpy_s(fileOpt->fileName, strlen(fileName) + 1, "/dev/filetest", strlen("/dev/filetest")); + EXPECT_EQ(ret, 0); + char *wrongName = (char *)malloc(PATH_MAX); + ASSERT_NE(wrongName, nullptr); + EXPECT_EQ(memset_s(wrongName, PATH_MAX, 1, PATH_MAX), 0); + ret = GetControlFile(wrongName); + EXPECT_NE(ret, 0); + GetControlFile("notExist"); + GetControlFile(nullptr); + EXPECT_EQ(setenv("OHOS_FILE_ENV_PREFIX_testPath", "5", 0), 0); + GetControlFile("testPath"); + EXPECT_EQ(setenv("OHOS_FILE_ENV_PREFIX_testPath1", "aaaaaaaa", 0), 0); + GetControlFile("testPath1"); + free(wrongName); + + fileOpt->fd = -1; + CreateServiceFile(service); + CloseServiceFile(fileOpt); + free(fileOpt); + service->fileCfg = nullptr; + ReleaseService(service); +} +} diff --git a/test/unittest/init/service_socket_unittest.cpp b/test/unittest/init/service_socket_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2569158899df59f6d10446d7d5f030c07fb41328 --- /dev/null +++ b/test/unittest/init/service_socket_unittest.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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 "init_service.h" +#include "init_service_manager.h" +#include "init_service_socket.h" +#include "init_socket.h" +#include "param_stub.h" +#include "securec.h" +#include "le_task.h" +using namespace std; +using namespace testing::ext; +namespace init_ut { +class ServiceSocketUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {}; + void TearDown() {}; +}; +HWTEST_F(ServiceSocketUnitTest, TestCreateSocket, TestSize.Level0) +{ + const char *testSocName = "test_socket"; + uint32_t eventid = 1; + Service *service = (Service *)AddService("TestCreateSocket"); + ASSERT_NE(service, nullptr); + service->socketCfg = nullptr; + service->attribute = SERVICE_ATTR_ONDEMAND; + ServiceSocket *sockopt = (ServiceSocket *)calloc(1, sizeof(ServiceSocket) + strlen(testSocName) + 1); + ASSERT_NE(sockopt, nullptr); + sockopt->type = SOCK_STREAM; + sockopt->protocol = 0; + sockopt->family = PF_UNIX; + sockopt->sockFd = -1; + sockopt->uid = 1000; + sockopt->gid = 1000; + sockopt->perm = 0660; + sockopt->option = SOCKET_OPTION_PASSCRED; + errno_t ret = strncpy_s(sockopt->name, strlen(testSocName) + 1, testSocName, strlen(testSocName)); + sockopt->next = nullptr; + EXPECT_EQ(ret, EOK); + if (service->socketCfg == nullptr) { + service->socketCfg = sockopt; + } else { + sockopt->next = service->socketCfg->next; + service->socketCfg->next = sockopt; + } + int ret1 = CreateSocketForService(service); + if (((ServiceSocket *)service->socketCfg)->watcher != nullptr) { + ((WatcherTask *)((ServiceSocket *)service->socketCfg)->watcher)->processEvent( + LE_GetDefaultLoop(), 0, &eventid, service); + } + EXPECT_EQ(ret1, 0); + GetControlSocket(nullptr); + ret1 = GetControlSocket(testSocName); + EXPECT_GE(ret1, -1); + CloseServiceSocket(service); + ReleaseService(service); +} +} // namespace init_ut diff --git a/test/unittest/init/service_unittest.cpp b/test/unittest/init/service_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eba5ef42e4cd5a3b4c38098afdfb7f2b9495b372 --- /dev/null +++ b/test/unittest/init/service_unittest.cpp @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2021 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 "init_cmds.h" +#include "init_service.h" +#include "init_service_manager.h" +#include "init_service_socket.h" +#include "param_stub.h" +#include "init_utils.h" +#include "securec.h" +#include "init_group_manager.h" +#include "trigger_manager.h" +#include "bootstage.h" +#include "init_hook.h" +#include "plugin_adapter.h" + +const char *SERVICE_INFO_JSONSTR = "{" + "\"services\":{" + " \"name\":\"test_service\"," + " \"path\":[\"/data/init_ut/test_service\"]," + " \"importance\":-20," + " \"uid\":\"system\"," + " \"writepid\":[\"/dev/test_service\"]," + " \"console\":1," + " \"caps\":[\"TEST_ERR\"]," + " \"gid\":[\"system\"]," + " \"period\":2," + " \"env\":[{ " + " \"name\":\"test\"," + " \"value\":\"xxxx\"" + " }]," + " \"critical\":1," + " \"jobs\" : {" + " \"pre-start\":\"test_service:pre-start\"" + " }" + "}" +"}"; +const char *JOB_INFO_JSONSTR = "{" + "\"jobs\": [" + " {" + " \"name\" : \"test_service:pre-start\"," + " \"cmds\" : [" + " \"setparam test.test.prestartKey 1\"" + " ]" + " }" + "]" +"}"; +const char *PRE_START_KEY = "test.test.prestartKey"; +static void DoCmdByName(const char *name, const char *cmdContent) +{ + int cmdIndex = 0; + (void)GetMatchCmd(name, &cmdIndex); + DoCmdByIndex(cmdIndex, cmdContent, nullptr); +} + +static void LoadJobs() +{ + cJSON *jobJson = cJSON_Parse(JOB_INFO_JSONSTR); + INIT_ERROR_CHECK(jobJson != NULL, return, "Failed to loadJobs"); + ParseTriggerConfig(jobJson, nullptr, nullptr); + cJSON_Delete(jobJson); +} + +static int ServiceTestTriggerExe(const TriggerNode *trigger, const char *content, uint32_t size) +{ + INIT_ERROR_CHECK(trigger != NULL, return -1, "ParamWriteTriggerExe trigger is NULL"); + CommandNode *cmd = GetNextCmdNode((JobNode *)trigger, NULL); + while (cmd != NULL) { + DoCmdByIndex(cmd->cmdKeyIndex, cmd->content, &cmd->cfgContext); + cmd = GetNextCmdNode((JobNode *)trigger, cmd); + } + return 0; +} + +using namespace testing::ext; +using namespace std; +namespace init_ut { +class ServiceUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + string svcPath = "/data/init_ut/test_service"; + auto fp = std::unique_ptr(fopen(svcPath.c_str(), "wb"), fclose); + if (fp == nullptr) { + cout << "ServiceUnitTest open : " << svcPath << " failed." << errno << endl; + } + sync(); + } + + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(ServiceUnitTest, case01, TestSize.Level1) +{ + cJSON* jobItem = cJSON_Parse(SERVICE_INFO_JSONSTR); + ASSERT_NE(nullptr, jobItem); + cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + Service *service = AddService("test_service"); + int ret = ParseOneService(serviceItem, service); + EXPECT_EQ(ret, 0); + + LoadJobs(); + RegisterTriggerExec(TRIGGER_UNKNOW, ServiceTestTriggerExe); + + ret = ServiceStart(service, &service->pathArgs); + EXPECT_EQ(ret, 0); + + char value[PARAM_VALUE_LEN_MAX] = {0}; + u_int32_t len = sizeof(value); + ret = SystemGetParameter(PRE_START_KEY, value, &len); + EXPECT_EQ(ret, 0); + EXPECT_EQ(0, strcmp("1", value)); + + ret = ServiceStop(service); + EXPECT_EQ(ret, 0); + + ReleaseService(service); + cJSON_Delete(jobItem); +} + +HWTEST_F(ServiceUnitTest, case02, TestSize.Level1) +{ + const char *jsonStr = "{\"services\":{\"name\":\"test_service8\",\"path\":[\"/data/init_ut/test_service\"]," + "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1," + "\"gid\":[\"system\", \"shell\", \"root\"],\"caps\":[10, 4294967295, 10000],\"cpucore\":[1]}}"; + cJSON* jobItem = cJSON_Parse(jsonStr); + ASSERT_NE(nullptr, jobItem); + cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + Service *service = AddService("test_service8"); + ASSERT_NE(nullptr, service); + int ret = ParseOneService(serviceItem, service); + EXPECT_EQ(ret, 0); + + int fds[1] = {-1}; // ServiceStop will release fds + UpdaterServiceFds(service, fds, 1); + service->attribute = SERVICE_ATTR_ONDEMAND; + ret = ServiceStart(service, &service->pathArgs); + EXPECT_EQ(ret, 0); + CmdLines *cmdline = (CmdLines *)malloc(sizeof(CmdLines) + sizeof(CmdLine)); + ASSERT_NE(nullptr, cmdline); + cmdline->cmdNum = 1; + cmdline->cmds[0].cmdIndex = 0; + service->restartArg = cmdline; + ServiceSocket tmpSock = { .next = nullptr, .sockFd = 0 }; + ServiceSocket tmpSock1 = { .next = &tmpSock, .sockFd = 0 }; + service->socketCfg = &tmpSock1; + ServiceReap(service); + service->socketCfg = nullptr; + service->attribute &= SERVICE_ATTR_NEED_RESTART; + service->firstCrashTime = 0; + ServiceReap(service); + DoCmdByName("reset ", "test_service8"); + // reset again + DoCmdByName("reset ", "test_service8"); + service->pid = 0xfffffff; // 0xfffffff is not exist pid + service->attribute = SERVICE_ATTR_TIMERSTART; + ret = ServiceStop(service); + EXPECT_EQ(ret, 0); + ReleaseService(service); + cJSON_Delete(jobItem); +} + +HWTEST_F(ServiceUnitTest, TestServiceStartAbnormal, TestSize.Level1) +{ + const char *jsonStr = "{\"services\":{\"name\":\"test_service1\",\"path\":[\"/data/init_ut/test_service\"]," + "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1," + "\"gid\":[\"system\"],\"caps\":[\"\"]}}"; + cJSON* jobItem = cJSON_Parse(jsonStr); + ASSERT_NE(nullptr, jobItem); + cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + Service *service = AddService("test_service1"); + ASSERT_NE(nullptr, service); + int ret = ParseOneService(serviceItem, service); + EXPECT_EQ(ret, 0); + + ret = ServiceStart(service, &service->pathArgs); + EXPECT_EQ(ret, 0); + + service->attribute &= SERVICE_ATTR_INVALID; + ret = ServiceStart(service, &service->pathArgs); + EXPECT_EQ(ret, 0); + + service->pid = -1; + ret = ServiceStop(service); + EXPECT_EQ(ret, 0); + ReleaseService(service); + cJSON_Delete(jobItem); +} + +HWTEST_F(ServiceUnitTest, TestServiceReap, TestSize.Level1) +{ + Service *service = AddService("test_service2"); + ASSERT_NE(nullptr, service); + EXPECT_EQ(service->attribute, 0); + service->attribute = SERVICE_ATTR_ONDEMAND; + ServiceReap(service); + service->attribute = 0; + + service->restartArg = (CmdLines *)calloc(1, sizeof(CmdLines)); + ASSERT_NE(nullptr, service->restartArg); + ServiceReap(service); + EXPECT_EQ(service->attribute, SERVICE_ATTR_TIMERSTART); + + const int crashCount = 241; + service->crashCnt = crashCount; + ServiceReap(service); + EXPECT_EQ(service->attribute, SERVICE_ATTR_TIMERSTART); + + service->attribute |= SERVICE_ATTR_ONCE; + ServiceReap(service); + EXPECT_EQ(service->attribute, (SERVICE_ATTR_ONCE | SERVICE_ATTR_TIMERSTART)); + service->attribute = SERVICE_ATTR_CRITICAL; + service->crashCount = 1; + ServiceReap(service); + ReleaseService(service); +} + +HWTEST_F(ServiceUnitTest, TestServiceReapOther, TestSize.Level1) +{ + const char *serviceStr = "{\"services\":{\"name\":\"test_service4\",\"path\":[\"/data/init_ut/test_service\"]," + "\"onrestart\":[\"sleep 1\"],\"console\":1,\"writepid\":[\"/dev/test_service\"]}}"; + + cJSON* jobItem = cJSON_Parse(serviceStr); + ASSERT_NE(nullptr, jobItem); + cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + Service *service = AddService("test_service4"); + ASSERT_NE(nullptr, service); + int ret = ParseOneService(serviceItem, service); + EXPECT_EQ(ret, 0); + + ServiceReap(service); + EXPECT_NE(service->attribute, 0); + + service->attribute |= SERVICE_ATTR_CRITICAL; + ServiceReap(service); + EXPECT_NE(service->attribute, 0); + + service->attribute |= SERVICE_ATTR_NEED_STOP; + ServiceReap(service); + EXPECT_NE(service->attribute, 0); + + service->attribute |= SERVICE_ATTR_INVALID; + ServiceReap(service); + EXPECT_NE(service->attribute, 0); + + ret = ServiceStop(service); + EXPECT_EQ(ret, 0); + ReleaseService(service); + cJSON_Delete(jobItem); +} + +HWTEST_F(ServiceUnitTest, TestServiceManagerRelease, TestSize.Level1) +{ + Service *service = nullptr; + ReleaseService(service); + EXPECT_TRUE(service == nullptr); + service = AddService("test_service5"); + ASSERT_NE(nullptr, service); + service->pathArgs.argv = (char **)malloc(sizeof(char *)); + ASSERT_NE(nullptr, service->pathArgs.argv); + service->pathArgs.count = 1; + const char *path = "/data/init_ut/test_service_release"; + service->pathArgs.argv[0] = strdup(path); + + service->writePidArgs.argv = (char **)malloc(sizeof(char *)); + ASSERT_NE(nullptr, service->writePidArgs.argv); + service->writePidArgs.count = 1; + service->writePidArgs.argv[0] = strdup(path); + + service->servPerm.caps = (unsigned int *)malloc(sizeof(unsigned int)); + ASSERT_NE(nullptr, service->servPerm.caps); + service->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t)); + ASSERT_NE(nullptr, service->servPerm.gIDArray); + service->socketCfg = (ServiceSocket *)malloc(sizeof(ServiceSocket)); + ASSERT_NE(nullptr, service->socketCfg); + service->socketCfg->sockFd = 0; + service->socketCfg->next = nullptr; + service->fileCfg = (ServiceFile *)malloc(sizeof(ServiceFile)); + ASSERT_NE(nullptr, service->fileCfg); + service->fileCfg->fd = 0; + service->fileCfg->next = nullptr; + service->env = (ServiceEnv*)malloc(sizeof(ServiceEnv)); + ASSERT_NE(nullptr, service->env); + int ret = strcpy_s(service->env->name, MAX_ENV_NAME, "test5"); + EXPECT_EQ(ret, EOK); + ret = strcpy_s(service->env->value, MAX_ENV_VALUE, "xxxxx"); + EXPECT_EQ(ret, EOK); + ReleaseService(service); + service = nullptr; +} + +HWTEST_F(ServiceUnitTest, TestServiceManagerGetService, TestSize.Level1) +{ + Service *service = GetServiceByPid(1); + StopAllServices(1, nullptr, 0, nullptr); + EXPECT_TRUE(service == nullptr); + const char *jsonStr = "{\"services\":{\"name\":\"test_service2\",\"path\":[\"/data/init_ut/test_service\"]," + "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1," + "\"gid\":[\"system\"], \"critical\":[1,2]}}"; + cJSON* jobItem = cJSON_Parse(jsonStr); + ASSERT_NE(nullptr, jobItem); + cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + service = AddService("test_service2"); + ASSERT_NE(nullptr, service); + int ret = ParseOneService(serviceItem, service); + EXPECT_NE(ret, 0); + cJSON_Delete(jobItem); + const char *jsonStr1 = "{\"services\":{\"name\":\"test_service3\",\"path\":[\"/data/init_ut/test_service\"]," + "\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1," + "\"gid\":[\"system\"], \"critical\":[\"on\"]}}"; + jobItem = cJSON_Parse(jsonStr1); + ASSERT_NE(nullptr, jobItem); + serviceItem = cJSON_GetObjectItem(jobItem, "services"); + ASSERT_NE(nullptr, serviceItem); + service = AddService("test_service3"); + ASSERT_NE(nullptr, service); + ret = ParseOneService(serviceItem, service); + EXPECT_NE(ret, 0); + cJSON_Delete(jobItem); +} + +/** +* @tc.name: TestServiceBootEventHook +* @tc.desc: test bootevent module exec correct +* @tc.type: FUNC +* @tc.require: issueI5NTX4 +* @tc.author: +*/ +HWTEST_F(ServiceUnitTest, TestServiceBootEventHook, TestSize.Level1) +{ + const char *serviceStr = "{" + "\"services\": [{" + "\"name\" : \"test-service\"," + "\"path\" : [\"/dev/test_service\"]," + "\"start-mode\" : \"condition\"," + "\"writepid\":[\"/dev/test_service\"]," + "\"bootevents\" : \"bootevent2\"" + "},{" + "\"name\" : \"test-service\"," + "\"path\" : [\"/dev/test_service\"]," + "\"start-mode\" : \"condition\"," + "\"writepid\":[\"/dev/test_service\"]," + "\"bootevents\" : \"bootevent.bootevent2\"" + "},{" + "\"name\" : \"test-service2\"," + "\"path\" : [\"/dev/test_service\"]," + "\"console\":1," + "\"start-mode\" : \"boot\"," + "\"writepid\":[\"/dev/test_service\"]," + "\"bootevents\" : [\"bootevent.bootevent1\", \"bootevent.bootevent2\"]" + "}]" + "}"; + + SERVICE_INFO_CTX serviceInfoContext; + serviceInfoContext.serviceName = "test-service2"; + serviceInfoContext.reserved = "bootevent"; + HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr); + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&serviceInfoContext), nullptr); + cJSON *fileRoot = cJSON_Parse(serviceStr); + ASSERT_NE(nullptr, fileRoot); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllServices(fileRoot, &context); + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), nullptr); + serviceInfoContext.reserved = nullptr; + (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), nullptr); + const char *initBootevent[] = {"init", "test"}; + PluginExecCmd("bootevent", ARRAY_LENGTH(initBootevent), initBootevent); + const char *initBooteventDup[] = {"init", "test"}; + PluginExecCmd("bootevent", ARRAY_LENGTH(initBooteventDup), initBooteventDup); + const char *initBooteventErr[] = {"init"}; + PluginExecCmd("bootevent", ARRAY_LENGTH(initBooteventErr), initBooteventErr); + SystemWriteParam("bootevent.bootevent1", "true"); + SystemWriteParam("bootevent.bootevent2", "true"); + SystemWriteParam("bootevent.bootevent2", "true"); + SystemWriteParam("persist.init.bootevent.enable", "false"); + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, nullptr, nullptr); + cJSON_Delete(fileRoot); +} + +HWTEST_F(ServiceUnitTest, TestSetServiceContent, TestSize.Level1) +{ + (void)WatchConsoleDevice(nullptr); + Service service; + (void)WatchConsoleDevice(&service); + int fd = open("/dev/console", O_RDWR); + if (fd >= 0) { + (void)write(fd, "0", 1); + (void)close(fd); + } + PluginExecCmdByName("setServiceContent", "netmanager"); + StopServiceByName("netmanager"); +} + +HWTEST_F(ServiceUnitTest, TestServiceExec, TestSize.Level1) +{ + Service *service = AddService("test_service7"); + ASSERT_NE(nullptr, service); + + service->pathArgs.argv = (char **)malloc(sizeof(char *)); + ASSERT_NE(service->pathArgs.argv, nullptr); + service->pathArgs.count = 1; + const char *path = "/data/init_ut/test_service_release"; + service->pathArgs.argv[0] = strdup(path); + service->importance = 20; + service->servPerm.gIDCnt = -1; + service->servPerm.uID = 0; + unsigned int *caps = (unsigned int *)calloc(1, sizeof(unsigned int) * 1); + ASSERT_NE(nullptr, caps); + caps[0] = FULL_CAP; + service->servPerm.caps = caps; + service->servPerm.capsCnt = 1; + IsEnableSandbox(); + EnterServiceSandbox(service); + int ret = ServiceExec(service, &service->pathArgs); + EXPECT_EQ(ret, 0); + + const int invalidImportantValue = 20; + ret = SetImportantValue(service, "", invalidImportantValue, 1); + EXPECT_EQ(ret, -1); + ReleaseService(service); +} +} // namespace init_ut diff --git a/test/unittest/init/utils_unittest.cpp b/test/unittest/init/utils_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2ebed61c68c407fe61068147051b1ccbdabde62 --- /dev/null +++ b/test/unittest/init/utils_unittest.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 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 "param_stub.h" +#include "init_utils.h" +#include "init_service_socket.h" +#include "init_socket.h" +#include "securec.h" +using namespace std; +using namespace testing::ext; + +extern "C" { +float ConvertMicrosecondToSecond(int x); +} +#define MAX_BUFFER_FOR_TEST 128 + +namespace init_ut { +class UtilsUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(UtilsUnitTest, TestMakeDir, TestSize.Level0) +{ + const char *dir = "/data/init_ut/mkdir_test"; + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH; + int ret = MakeDirRecursive(dir, mode); + EXPECT_EQ(ret, 0); + dir = nullptr; + ret = MakeDirRecursive(dir, mode); + EXPECT_EQ(ret, -1); + ret = MakeDir(dir, 9999); + EXPECT_EQ(ret, -1); +} + +HWTEST_F(UtilsUnitTest, TestString, TestSize.Level0) +{ + const char *str = nullptr; + int defaultValue = 1; + int ret = StringToInt(str, defaultValue); + EXPECT_EQ(ret, 1); + str = "10"; + ret = StringToInt(str, defaultValue); + EXPECT_EQ(ret, 10); + char rStr[] = "abc"; + char oldChr = 'a'; + char newChr = 'd'; + ret = StringReplaceChr(rStr, oldChr, newChr); + EXPECT_EQ(ret, 0); + EXPECT_STREQ(rStr, "dbc"); +} +HWTEST_F(UtilsUnitTest, TestUtilsApi, TestSize.Level0) +{ + float sec = ConvertMicrosecondToSecond(1000000); // 1000000 microseconds + EXPECT_EQ(sec, 1); + EXPECT_EQ(WriteAll(2, "test", strlen("test")), 4); + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + CheckAndCreatFile("/data/init_ut/testcreatfile", mode); + CheckAndCreatFile("/data/init_ut/nodir/testcreatfile", mode); + char testStr[] = ".trim"; + EXPECT_STREQ(TrimHead(testStr, '.'), "trim"); +} +} // namespace init_ut diff --git a/test/unittest/init_unittest.h b/test/unittest/init_unittest.h new file mode 100644 index 0000000000000000000000000000000000000000..e02be3ca6ca425af8e57e49e03ec5854253125ad --- /dev/null +++ b/test/unittest/init_unittest.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021 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 INIT_UNITTEST_CONST_H +#define INIT_UNITTEST_CONST_H +#include +#include +#include +#include +#include +#include + +#endif // INIT_UNITTEST_CONST_H diff --git a/test/unittest/innerkits/hookmgr_unittest.cpp b/test/unittest/innerkits/hookmgr_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..03d091770c48eec26a188aa863d4d2bd4bcb2a62 --- /dev/null +++ b/test/unittest/innerkits/hookmgr_unittest.cpp @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2021 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 "hookmgr.h" +#include "bootstage.h" +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class HookMgrUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +struct HookExecCtx { + int result; + int retErr; +}; + +static int OhosHookTestCommon(void *executionContext, int result) +{ + struct HookExecCtx *ctx; + + if (executionContext == nullptr) { + return 0; + } + + ctx = (struct HookExecCtx *)executionContext; + ctx->result = result; + if (ctx->retErr) { + return -1; + } + return 0; +} + +static int OhosTestHookRetOK(const HOOK_INFO *hookInfo, void *executionContext) +{ + return OhosHookTestCommon(executionContext, 1); +} + +static int OhosTestHookRetOKEx(const HOOK_INFO *hookInfo, void *executionContext) +{ + return OhosHookTestCommon(executionContext, 2); +} + +static int OhosTestHookRetOKEx2(const HOOK_INFO *hookInfo, void *executionContext) +{ + return OhosHookTestCommon(executionContext, 3); +} + +static void OhosHookPrint(const HOOK_INFO *hookInfo, void *traversalCookie) +{ + printf("\tstage[%02d] prio[%02d].\n", hookInfo->stage, hookInfo->prio); +} + +static void dumpAllHooks(HOOK_MGR *hookMgr) +{ + printf("----------All Hooks---------------\n"); + HookMgrTraversal(hookMgr, nullptr, OhosHookPrint); + printf("----------------------------------\n\n"); +} + +#define STAGE_TEST_ONE 0 + +HWTEST_F(HookMgrUnitTest, HookMgrAdd_one_stage_unitest, TestSize.Level1) +{ + int ret; + int cnt; + + cnt = HookMgrGetStagesCnt(nullptr); + EXPECT_EQ(cnt, 0); + + // Add the first hook + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + cnt = HookMgrGetStagesCnt(nullptr); + EXPECT_EQ(cnt, 1); + dumpAllHooks(nullptr); + + // Add the same hook with the same priority again + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + dumpAllHooks(nullptr); + + // Add the same hook with different priority + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 2); + dumpAllHooks(nullptr); + + // Add the another hook + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOKEx); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 3); + dumpAllHooks(nullptr); + + // Add the same hook with the same priority again + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 3); + dumpAllHooks(nullptr); + + // Add the same hook with the same priority again + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 3); + dumpAllHooks(nullptr); + + // Add the another hook + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOKEx); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 3); + dumpAllHooks(nullptr); + + // Insert to the end of already exist prio + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 4); + dumpAllHooks(nullptr); + + // Insert to the end of already exist prio + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx2); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 5); + dumpAllHooks(nullptr); + + // Insert a new prio hook + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 5, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 6); + dumpAllHooks(nullptr); + + // Insert a new prio hook to the beginning + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, -5, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 7); + dumpAllHooks(nullptr); + + // All hooks are in the same stage + cnt = HookMgrGetStagesCnt(nullptr); + EXPECT_EQ(cnt, 1); + + // Delete all hooks in stage 0 + HookMgrDel(nullptr, STAGE_TEST_ONE, nullptr); + cnt = HookMgrGetHooksCnt(nullptr, 0); + EXPECT_EQ(cnt, 0); + cnt = HookMgrGetStagesCnt(nullptr); + EXPECT_EQ(cnt, 0); + + dumpAllHooks(nullptr); + HookMgrDestroy(nullptr); +} + +HWTEST_F(HookMgrUnitTest, HookMgrDel_unitest, TestSize.Level1) +{ + int ret; + int cnt; + + HOOK_MGR *hookMgr = HookMgrCreate("test"); + ASSERT_NE(hookMgr, nullptr); + + // Add one, delete one + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + + HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOK); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 0); + + // Add three same hook with different prio, delete together + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 5, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 2); + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 10, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 3); + dumpAllHooks(hookMgr); + + HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOK); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 0); + + // Add three different hook with same prio, delete one by one + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 2); + ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx2); + EXPECT_EQ(ret, 0); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 3); + dumpAllHooks(hookMgr); + + HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOK); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 2); + dumpAllHooks(hookMgr); + HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOKEx2); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 1); + dumpAllHooks(hookMgr); + HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOKEx); + cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE); + EXPECT_EQ(cnt, 0); + + HookMgrDestroy(hookMgr); +} + +HWTEST_F(HookMgrUnitTest, HookMgrExecute_unitest, TestSize.Level1) +{ + int ret; + struct HookExecCtx ctx; + HOOK_EXEC_OPTIONS options; + + ctx.result = 0; + ctx.retErr = 0; + + options.flags = 0; + options.preHook = nullptr; + options.postHook = nullptr; + + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK); + EXPECT_EQ(ret, 0); + ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr); + EXPECT_EQ(ret, 0); + EXPECT_EQ(ctx.result, 1); + + // Check ignore error + ctx.retErr = 1; + ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr); + EXPECT_EQ(ret, 0); + EXPECT_EQ(ctx.result, 1); + + // Do not ignore return errors + ctx.retErr = 1; + options.flags = HOOK_EXEC_EXIT_WHEN_ERROR; + ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, &options); + ASSERT_NE(ret, 0); + EXPECT_EQ(ctx.result, 1); + options.flags = 0; + + // Add another hook with same priority + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx); + EXPECT_EQ(ret, 0); + ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr); + EXPECT_EQ(ret, 0); + EXPECT_EQ(ctx.result, 2); + + // Add another hook with higher priority + ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, -1, OhosTestHookRetOKEx); + EXPECT_EQ(ret, 0); + ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr); + EXPECT_EQ(ret, 0); + EXPECT_EQ(ctx.result, 2); + + HookMgrDel(nullptr, STAGE_TEST_ONE, OhosTestHookRetOKEx); + ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr); + EXPECT_EQ(ret, 0); + EXPECT_EQ(ctx.result, 1); +} + +HWTEST_F(HookMgrUnitTest, HookMgrExecuteInit_unitest, TestSize.Level1) +{ + HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr); + HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, nullptr, nullptr); +} +} // namespace init_ut diff --git a/test/unittest/innerkits/innerkits_unittest.cpp b/test/unittest/innerkits/innerkits_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36a70e8a0d90c62dae53128c4160c0495f0b5d7e --- /dev/null +++ b/test/unittest/innerkits/innerkits_unittest.cpp @@ -0,0 +1,486 @@ +/* + * 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 "fs_manager/fs_manager.h" +#include "init_log.h" +#include "init_param.h" +#include "param_stub.h" +#include "securec.h" +#include "systemcapability.h" +#include "service_control.h" +#include "control_fd.h" +#include "loop_event.h" +#include "fd_holder.h" +#include "fd_holder_internal.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { + +extern "C" { +void CmdDisConnectComplete(const TaskHandle client); +void CmdOnSendMessageComplete(const TaskHandle task, const BufferHandle handle); +void CmdOnClose(const TaskHandle task); +void CmdOnConnectComplete(const TaskHandle client); +void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen); +void ProcessPtyRead(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context); +void ProcessPtyWrite(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context); +int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server); +CmdAgent *CmdAgentCreate(const char *server); +void CmdClientOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen); +int SendCmdMessage(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName); +int SendMessage(LoopHandle loop, TaskHandle task, const char *message); +int *GetFdsFromMsg(size_t *outFdCount, pid_t *requestPid, struct msghdr msghdr); +int BuildSendData(char *buffer, size_t size, const char *serviceName, bool hold, bool poll); +int CheckSocketPermission(const TaskHandle task); +} + +class InnerkitsUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +static int CallbackSendMsgProcessTest(const CmdAgent *agent, uint16_t type, const char *cmd, const char *ptyName) +{ + return 0; +} + +/** +* @tc.name: ReadFstabFromFile_unitest +* @tc.desc: read fstab from test file. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ReadFstabFromFile001, TestSize.Level1) +{ + Fstab *fstab = nullptr; + const std::string fstabFile1 = "/data/fstab.updater1"; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + EXPECT_EQ(fstab, nullptr); + const std::string fstabFile2 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable"; + fstab = ReadFstabFromFile(fstabFile2.c_str(), false); + EXPECT_NE(fstab, nullptr); + ParseFstabPerLine(const_cast("test"), fstab, true, nullptr); + ReleaseFstab(fstab); +} + +/** +* @tc.name: FindFstabItemForPath_unitest +* @tc.desc: read fstab from test file, then find item according to path. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_FindFstabItemForPath001, TestSize.Level1) +{ + const std::string fstabFile1 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable"; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); + FstabItem* item = nullptr; + const std::string path1 = ""; + item = FindFstabItemForPath(*fstab, path1.c_str()); + if (item == nullptr) { + SUCCEED(); + } + const std::string path2 = "/data"; + item = FindFstabItemForPath(*fstab, path2.c_str()); + if (item != nullptr) { + SUCCEED(); + } + const std::string path3 = "/data2"; + item = FindFstabItemForPath(*fstab, path3.c_str()); + if (item == nullptr) { + SUCCEED(); + } + const std::string path4 = "/data2/test"; + item = FindFstabItemForPath(*fstab, path4.c_str()); + if (item != nullptr) { + SUCCEED(); + } + ReleaseFstab(fstab); + fstab = nullptr; +} + +/** +* @tc.name: FindFstabItemForMountPoint_unitest +* @tc.desc: read fstab from test file, then find item that matches with the mount point. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_FindFstabItemForMountPoint001, TestSize.Level1) +{ + const std::string fstabFile1 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable"; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); + FstabItem* item = nullptr; + const std::string mp1 = "/data"; + const std::string mp2 = "/data2"; + item = FindFstabItemForMountPoint(*fstab, mp2.c_str()); + if (item == nullptr) { + SUCCEED(); + } + const std::string mp3 = "/data"; + item = FindFstabItemForMountPoint(*fstab, mp3.c_str()); + if (item != nullptr) { + SUCCEED(); + } + ReleaseFstab(fstab); + fstab = nullptr; +} + +/** +* @tc.name: GetMountFlags_unitest +* @tc.desc: read fstab from test file, then find the item and get mount flags. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_GetMountFlags001, TestSize.Level1) +{ + const std::string fstabFile1 = STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable"; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), true); + ASSERT_NE(fstab, nullptr); + struct FstabItem* item = nullptr; + const std::string mp = "/hos"; + item = FindFstabItemForMountPoint(*fstab, mp.c_str()); + if (item == nullptr) { + SUCCEED(); + } + const int bufferSize = 512; + char fsSpecificOptions[bufferSize] = {0}; + unsigned long flags = GetMountFlags(item->mountOptions, fsSpecificOptions, bufferSize, item->mountPoint); + EXPECT_EQ(flags, static_cast(MS_NOSUID | MS_NODEV | MS_NOATIME)); + ReleaseFstab(fstab); + fstab = nullptr; +} + +/** +* @tc.name: GetSlotInfo_unittest +* @tc.desc: get the number of slots and get current slot. +* @tc.type: FUNC +* @tc.require:issueI5NTX2 +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_GetSlotInfo001, TestSize.Level1) +{ + EXPECT_NE(GetBootSlots(), -1); + EXPECT_NE(GetCurrentSlot(), -1); +} + +/** +* @tc.name: LoadFstabFromCommandLine_unittest +* @tc.desc: get fstab from command line. +* @tc.type: FUNC +* @tc.require:issueI5NTX2 +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_LoadFstabFromCommandLine001, TestSize.Level1) +{ + EXPECT_NE(LoadFstabFromCommandLine(), (Fstab *)nullptr); +} + +/** +* @tc.name: GetBlockDevicePath_unittest +* @tc.desc: get block device path according to valid or invalid partition. +* @tc.type: FUNC +* @tc.require:issueI5NTX2 +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_GetBlockDevicePath001, TestSize.Level1) +{ + char devicePath[MAX_BUFFER_LEN] = {0}; + EXPECT_EQ(GetBlockDevicePath("/vendor", devicePath, MAX_BUFFER_LEN), 0); + EXPECT_EQ(GetBlockDevicePath("/misc", devicePath, MAX_BUFFER_LEN), 0); + EXPECT_EQ(GetBlockDevicePath("/invalid", devicePath, MAX_BUFFER_LEN), -1); + unlink(BOOT_CMD_LINE); + EXPECT_EQ(GetBlockDevicePath("/invalid", devicePath, MAX_BUFFER_LEN), -1); + GetCurrentSlot(); + // restore cmdline + PrepareCmdLineData(); +} + +/** +* @tc.name: DoFormat_unittest +* @tc.desc: format file system, includes ext4 and f2fs type. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_DoFormat001, TestSize.Level1) +{ + EXPECT_NE(DoFormat("/testpath", "ext4"), -1); + EXPECT_NE(DoFormat("/testpath", "f2fs"), -1); + EXPECT_EQ(DoFormat("/testpath", "notFs"), -1); + EXPECT_EQ(DoFormat(nullptr, nullptr), -1); +} + +/** +* @tc.name: MountAllWithFstabFile_unittest +* @tc.desc: mount partitions according to fstab that read from file. +* @tc.type: FUNC +* @tc.require:issueI5NTX2 +* @tc.author: +*/ +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_MountAllWithFstabFile001, TestSize.Level1) +{ + EXPECT_NE(MountAllWithFstabFile(STARTUP_INIT_UT_PATH"/etc/fstab.required", 0), 1); + EXPECT_NE(UmountAllWithFstabFile(STARTUP_INIT_UT_PATH"/etc/fstab.required"), 1); + EXPECT_EQ(MountAllWithFstabFile("/testErrorFile", 0), -1); + EXPECT_EQ(MountAllWithFstabFile(nullptr, 0), -1); + EXPECT_EQ(GetMountStatusForMountPoint(nullptr), -1); + FstabItem fstabItem = {}; + fstabItem.fsType = strdup("notSupport"); + fstabItem.mountPoint = strdup(""); + EXPECT_EQ(MountOneItem(nullptr), -1); + EXPECT_EQ(MountOneItem(&fstabItem), 0); + if (fstabItem.fsType != nullptr) { + free(fstabItem.fsType); + fstabItem.fsType = nullptr; + } + if (fstabItem.mountPoint != nullptr) { + free(fstabItem.mountPoint); + fstabItem.mountPoint = nullptr; + } +} + +#define SYSCAP_MAX_SIZE 100 + +// TestSysCap +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_TestSysCap001, TestSize.Level1) +{ + bool ret = HasSystemCapability("test.cap"); + EXPECT_EQ(ret, false); + ret = HasSystemCapability(nullptr); + EXPECT_EQ(ret, false); + ret = HasSystemCapability("ArkUI.ArkUI.Napi"); + EXPECT_EQ(ret, true); + ret = HasSystemCapability("SystemCapability.ArkUI.ArkUI.Napi"); + EXPECT_EQ(ret, true); + char *wrongName = reinterpret_cast(malloc(SYSCAP_MAX_SIZE)); + ASSERT_NE(wrongName, nullptr); + EXPECT_EQ(memset_s(wrongName, SYSCAP_MAX_SIZE, 1, SYSCAP_MAX_SIZE), 0); + HasSystemCapability(wrongName); + free(wrongName); +} + +// TestControlService +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ControlService001, TestSize.Level1) +{ + TestSetParamCheckResult("startup.service.ctl.", 0777, 0); + ServiceControl("deviceinfoservice", START); + SystemWriteParam("startup.service.ctl.deviceinfoservice", "2"); + ServiceControl("deviceinfoservice", RESTART); + ServiceControl("deviceinfoservice", STOP); + SystemWriteParam("startup.service.ctl.deviceinfoservice", "0"); + ServiceControl("param_watcher", RESTART); + EXPECT_EQ(ServiceControl(nullptr, RESTART), -1); + const char *argv[] = {"testArg"}; + ServiceControlWithExtra("deviceinfoservice", RESTART, argv, 1); + ServiceControlWithExtra(nullptr, RESTART, argv, 1); + ServiceControlWithExtra(nullptr, 3, argv, 1); // 3 is action + ServiceControlWithExtra("notservie", RESTART, argv, 1); + ServiceControlWithExtra("deviceinfoservice", 3, argv, 1); // 3 is action + ServiceSetReady("deviceinfoservice"); + ServiceSetReady(nullptr); + ServiceWaitForStatus("deviceinfoservice", SERVICE_READY, 1); + ServiceWaitForStatus("deviceinfoservice", SERVICE_READY, -1); + ServiceWaitForStatus(nullptr, SERVICE_READY, 1); + StartServiceByTimer("deviceinfoservice", 1); + StartServiceByTimer("deviceinfoservice", 0); + StartServiceByTimer(nullptr, 0); + StopServiceTimer("deviceinfoservice"); +} + +static int TestIncommingConnect(const LoopHandle loop, const TaskHandle server) +{ + UNUSED(loop); + UNUSED(server); + return 0; +} + +// TestControlFd +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ControlFd001, TestSize.Level1) +{ + CmdClientInit("/data/testSock1", ACTION_DUMP, "cmd", nullptr); + CmdClientInit("/data/testSock1", ACTION_DUMP, "cmd", CallbackSendMsgProcessTest); + CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_DUMP, nullptr, nullptr); + CmdClientInit(nullptr, ACTION_DUMP, "cmd", nullptr); + + CmdDisConnectComplete(nullptr); + CmdOnSendMessageComplete(nullptr, nullptr); + CmdOnConnectComplete(nullptr); + CmdClientOnRecvMessage(nullptr, nullptr, 0); + CmdAgentCreate(nullptr); + CmdAgent *agent = CmdAgentCreate(INIT_CONTROL_FD_SOCKET_PATH); + EXPECT_NE(agent, nullptr); + SendCmdMessage(agent, ACTION_DUMP, "cmd", "test"); + SendCmdMessage(agent, ACTION_DUMP, "cmd", nullptr); + SendMessage(nullptr, nullptr, nullptr); + uint32_t events = 0; + InitPtyInterface(agent, 0, "cmd", nullptr); + InitPtyInterface(agent, 0, "cmd", CallbackSendMsgProcessTest); + InitPtyInterface(agent, 0, nullptr, nullptr); + InitPtyInterface(nullptr, 0, nullptr, nullptr); + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + CheckAndCreatFile("/data/init_ut/testInput", mode); + int fd = open("/data/init_ut/testInput", O_RDWR); + perror("write failed"); + EXPECT_GT(fd, 0); + EXPECT_GT(write(fd, "test", strlen("test")), 0); + perror("write failed"); + lseek(fd, 0, SEEK_SET); + ProcessPtyRead(nullptr, fd, &events, (void *)agent); + ProcessPtyRead(nullptr, fd, &events, (void *)agent); + ProcessPtyRead(nullptr, STDERR_FILENO, &events, nullptr); + lseek(fd, 0, SEEK_SET); + ProcessPtyWrite(nullptr, fd, &events, (void *)agent); + ProcessPtyWrite(nullptr, fd, &events, (void *)agent); + ProcessPtyWrite(nullptr, STDERR_FILENO, &events, nullptr); + close(fd); + + if (agent) { + CmdOnClose(agent->task); + } +} + +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_ControlFdServer001, TestSize.Level1) +{ + CmdServiceInit(nullptr, nullptr, nullptr); + CmdServiceInit("/data/testSock1", [](uint16_t type, const char *serviceCmd, const void *context) { + UNUSED(type); + UNUSED(serviceCmd); + UNUSED(context); + }, LE_GetDefaultLoop()); + + TaskHandle testServer = nullptr; + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE | TASK_TEST; + info.server = (char *)"/data/testSock1"; + info.socketId = -1; + info.baseInfo.close = nullptr; + info.disConnectComplete = nullptr; + info.incommingConnect = TestIncommingConnect; + info.sendMessageComplete = nullptr; + info.recvMessage = nullptr; + (void)LE_CreateStreamServer(LE_GetDefaultLoop(), &testServer, &info); + CmdOnIncommingConnect(LE_GetDefaultLoop(), testServer); + + CmdOnRecvMessage(testServer, nullptr, 0); + CmdMessage *cmdMsg = (CmdMessage *)malloc(sizeof(CmdMessage) + strlen("test")); + cmdMsg->type = ACTION_DUMP; + cmdMsg->ptyName[0] = '\0';; + CmdOnRecvMessage(testServer, (uint8_t *)(&cmdMsg), 0); + cmdMsg->type = ACTION_DUMP; + cmdMsg->cmd[0] = 'a'; + cmdMsg->ptyName[0] = 'a'; + CmdOnRecvMessage(testServer, (uint8_t *)(&cmdMsg), 0); + CmdServiceProcessDelClient(0); + CmdServiceProcessDelClient(0); + free(cmdMsg); +} + +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_HoldFd001, TestSize.Level1) +{ + CheckSocketPermission(nullptr); + CmdServiceProcessDestroyClient(); +} + +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_HoldFd002, TestSize.Level1) +{ + int fds1[] = {1, 0}; + ServiceSaveFd("testServiceName", fds1, ARRAY_LENGTH(fds1)); + ServiceSaveFd(nullptr, fds1, ARRAY_LENGTH(fds1)); + ServiceSaveFdWithPoll("testServiceName", fds1, 0); + ServiceSaveFdWithPoll(nullptr, fds1, 0); + ServiceSaveFdWithPoll("testServiceName", fds1, ARRAY_LENGTH(fds1)); + EXPECT_EQ(setenv("OHOS_FD_HOLD_testServiceName", "1 0", 0), 0); + + size_t fdCount = 0; + int *fds = nullptr; + ServiceGetFd("testService", nullptr); + ServiceGetFd("testService", &fdCount); + char *wrongName = (char *)malloc(MAX_FD_HOLDER_BUFFER + 1); + ASSERT_NE(wrongName, nullptr); + EXPECT_EQ(memset_s(wrongName, MAX_FD_HOLDER_BUFFER + 1, 1, MAX_FD_HOLDER_BUFFER + 1), 0); + ServiceGetFd(wrongName, &fdCount); + BuildSendData(wrongName, 1, "testService", 0, 1); + BuildSendData(wrongName, 1, "testService", 0, 0); + BuildSendData(nullptr, 1, "testService", 0, 0); + free(wrongName); + + fds = ServiceGetFd("testServiceName", &fdCount); + EXPECT_NE(fds, nullptr); + struct msghdr msghdr = {}; + BuildControlMessage(nullptr, nullptr, 1, 0); + BuildControlMessage(&msghdr, nullptr, 1, 0); + if (msghdr.msg_control != nullptr) { + free(msghdr.msg_control); + msghdr.msg_control = nullptr; + } + BuildControlMessage(&msghdr, fds, -1, 0); + if (msghdr.msg_control != nullptr) { + free(msghdr.msg_control); + msghdr.msg_control = nullptr; + } + BuildControlMessage(&msghdr, fds, -1, 1); + if (msghdr.msg_control != nullptr) { + free(msghdr.msg_control); + msghdr.msg_control = nullptr; + } + if (fds != nullptr) + { + free(fds); + fds = nullptr; + } +} + +HWTEST_F(InnerkitsUnitTest, Init_InnerkitsTest_HoldFd003, TestSize.Level1) +{ + size_t fdCount = 0; + int *fds = nullptr; + char buffer[MAX_FD_HOLDER_BUFFER + 1] = {}; + pid_t requestPid = -1; + struct msghdr msghdr = {}; + GetFdsFromMsg(&fdCount, &requestPid, msghdr); + msghdr.msg_flags = MSG_TRUNC; + GetFdsFromMsg(&fdCount, &requestPid, msghdr); + struct iovec iovec = { + .iov_base = buffer, + .iov_len = MAX_FD_HOLDER_BUFFER, + }; + ReceiveFds(0, iovec, &fdCount, false, &requestPid); + fds = ReceiveFds(0, iovec, &fdCount, true, &requestPid); + if (fds != nullptr) + { + free(fds); + fds = nullptr; + } + if (msghdr.msg_control != nullptr) { + free(msghdr.msg_control); + } +} + +} // namespace init_ut diff --git a/test/unittest/innerkits/modulemgr_unittest.cpp b/test/unittest/innerkits/modulemgr_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..852571c8dff36d9b6ed44ef03c962fa7e389a8d0 --- /dev/null +++ b/test/unittest/innerkits/modulemgr_unittest.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 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 "bootstage.h" +#include "init_cmds.h" +#include "init_group_manager.h" +#include "init_hashmap.h" +#include "init_param.h" +#include "init_module_engine.h" +#include "init_cmdexecutor.h" +#include "param_stub.h" +#include "init_utils.h" +#include "securec.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class ModuleMgrUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +int g_cmdExecId = 0; +int TestCmdExecutor(int id, const char *name, int argc, const char **argv) +{ + printf("TestCmdExecutor id %d, name %s \n", id, name); + g_cmdExecId = id; + return 0; +} + +HWTEST_F(ModuleMgrUnitTest, Init_ModuleMgrTest_PluginAddCmd001, TestSize.Level1) +{ + InitServiceSpace(); + const char *testName = "testCmd1"; + const char *cmdContent = "testCmd1 test1 test2 test3"; + const char *cmdContentNotValid = "testCmd1 t e s t 1 t e s t 2 t"; + int cmdExecId1 = AddCmdExecutor(testName, TestCmdExecutor); + ASSERT_NE(cmdExecId1 > 0, 0); + int cmdExecId2 = AddCmdExecutor("testCmd2", TestCmdExecutor); + ASSERT_NE(cmdExecId2 > 0, 0); + cmdExecId2 = AddCmdExecutor("testCmd3", TestCmdExecutor); + ASSERT_NE(cmdExecId2 > 0, 0); + int cmdExecId4 = AddCmdExecutor("testCmd4", TestCmdExecutor); + ASSERT_NE(cmdExecId4 > 0, 0); + PluginExecCmd("testCmd4", 0, nullptr); + + int cmdIndex = 0; + const char *cmdName = PluginGetCmdIndex(cmdContent, &cmdIndex); + ASSERT_EQ(strcmp(cmdName, testName), 0); + printf("TestCmdExecutor cmdIndex 0x%04x, name %s \n", cmdIndex, cmdName); + ASSERT_NE(GetPluginCmdNameByIndex(cmdIndex), nullptr); + + // exec + g_cmdExecId = -1; + PluginExecCmdByName(cmdName, cmdContent); + ASSERT_EQ(cmdExecId1, g_cmdExecId); + PluginExecCmdByName(cmdName, nullptr); + PluginExecCmdByName(cmdName, cmdContentNotValid); + g_cmdExecId = -1; + PluginExecCmdByCmdIndex(cmdIndex, cmdContent, nullptr); + ASSERT_EQ(cmdExecId1, g_cmdExecId); + const char *argv[] = {"test.value"}; + PluginExecCmd("install", 1, argv); + PluginExecCmd("uninstall", 1, argv); + PluginExecCmd("setloglevel", 1, argv); + + // del + RemoveCmdExecutor("testCmd4", cmdExecId4); + AddCareContextCmdExecutor("", nullptr); + RemoveCmdExecutor("testCmd4", -1); +} + +static void TestModuleDump(const MODULE_INFO *moduleInfo) +{ + printf("%s\n", moduleInfo->name); +} + +HWTEST_F(ModuleMgrUnitTest, Init_ModuleMgrTest_ModuleTraversal001, TestSize.Level1) +{ + // Create module manager + MODULE_MGR *moduleMgr = ModuleMgrCreate("init"); + ASSERT_NE(moduleMgr, nullptr); + int cnt = ModuleMgrGetCnt(moduleMgr); + ASSERT_EQ(cnt, 0); + // Install one module + int ret = ModuleMgrInstall(moduleMgr, "libbootchart", 0, nullptr); + ASSERT_EQ(ret, 0); + cnt = ModuleMgrGetCnt(moduleMgr); + ASSERT_EQ(cnt, 1); + ModuleMgrTraversal(nullptr, nullptr, nullptr); + ModuleMgrTraversal(moduleMgr, nullptr, TestModuleDump); + InitModuleMgrDump(); + + InitModuleMgrInstall("/"); + + // Scan all modules + ModuleMgrScan(nullptr); + ModuleMgrScan("/"); + moduleMgr = ModuleMgrScan("init"); + moduleMgr = ModuleMgrScan(STARTUP_INIT_UT_PATH MODULE_LIB_NAME "/autorun"); + ASSERT_NE(moduleMgr, nullptr); + cnt = ModuleMgrGetCnt(moduleMgr); + ASSERT_GE(cnt, 0); + + ModuleMgrUninstall(moduleMgr, nullptr); + cnt = ModuleMgrGetCnt(moduleMgr); + ASSERT_EQ(cnt, 0); + + ModuleMgrGetArgs(); + ModuleMgrDestroy(moduleMgr); +} + +HWTEST_F(ModuleMgrUnitTest, Init_ModuleMgrTest_ModuleAbnormal001, TestSize.Level1) +{ + int ret = InitModuleMgrInstall(nullptr); + ASSERT_EQ(ret, -1); +} +} // namespace init_ut diff --git a/test/unittest/innerkits/strutil_unittest.cpp b/test/unittest/innerkits/strutil_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a0adf790812a3b07b10963e1c2f708ebcfaed804 --- /dev/null +++ b/test/unittest/innerkits/strutil_unittest.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2021 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 "init_utils.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class StrUtilUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(StrUtilUnitTest, StrArrayGetIndex_unit_test, TestSize.Level1) +{ + int ret; + const char *strArray[] = { "a1", "a2", "a3", NULL}; + + // Invalid arguments test + ret = OH_StrArrayGetIndex(NULL, "test", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(NULL, NULL, 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, NULL, 0); + EXPECT_EQ(ret, -1); + + // Matched + ret = OH_StrArrayGetIndex(strArray, "a1", 0); + EXPECT_EQ(ret, 0); + ret = OH_StrArrayGetIndex(strArray, "a2", 0); + EXPECT_EQ(ret, 1); + ret = OH_StrArrayGetIndex(strArray, "a3", 0); + EXPECT_EQ(ret, 2); + + // Not matched + ret = OH_StrArrayGetIndex(strArray, "aa1", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, "A1", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, "A2", 0); + EXPECT_EQ(ret, -1); + ret = OH_StrArrayGetIndex(strArray, "A3", 0); + EXPECT_EQ(ret, -1); + + // Ignore case + ret = OH_StrArrayGetIndex(strArray, "A1", 1); + EXPECT_EQ(ret, 0); + ret = OH_StrArrayGetIndex(strArray, "A2", 2); + EXPECT_EQ(ret, 1); + ret = OH_StrArrayGetIndex(strArray, "A3", 3); + EXPECT_EQ(ret, 2); +} + +HWTEST_F(StrUtilUnitTest, OH_ExtendableStrArrayGetIndex_unitest, TestSize.Level1) +{ + int ret; + const char *strArray[] = { "a1", "a2", "a3", NULL}; + const char *extendStrArray[] = { "a4", "a5", "a6", NULL}; + + // Matched + ret = OH_ExtendableStrArrayGetIndex(strArray, "a4", 0, extendStrArray); + EXPECT_EQ(ret, 3); + ret = OH_ExtendableStrArrayGetIndex(strArray, "a5", 0, extendStrArray); + EXPECT_EQ(ret, 4); + ret = OH_ExtendableStrArrayGetIndex(strArray, "a6", 0, extendStrArray); + EXPECT_EQ(ret, 5); + + // Not matched + ret = OH_ExtendableStrArrayGetIndex(strArray, "aa1", 0, extendStrArray); + EXPECT_EQ(ret, -1); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A4", 0, extendStrArray); + EXPECT_EQ(ret, -1); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A5", 0, extendStrArray); + EXPECT_EQ(ret, -1); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A6", 0, extendStrArray); + EXPECT_EQ(ret, -1); + + // Ignore case + ret = OH_ExtendableStrArrayGetIndex(strArray, "A4", 1, extendStrArray); + EXPECT_EQ(ret, 3); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A5", 2, extendStrArray); + EXPECT_EQ(ret, 4); + ret = OH_ExtendableStrArrayGetIndex(strArray, "A6", 3, extendStrArray); + EXPECT_EQ(ret, 5); +} + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_array, TestSize.Level1) +{ + int ret; + void *res; + const char *strArray[] = { "a1", "a2", "a3", NULL}; + + // Invalid arguments test + res = OH_StrDictGet(NULL, 0, "test", 0); + EXPECT_EQ(res, NULL); + res = OH_StrDictGet(NULL, 0, NULL, 0); + EXPECT_EQ(res, NULL); + res = OH_StrDictGet((void **)strArray, 1, NULL, 0); + EXPECT_EQ(res, NULL); + res = OH_StrDictGet((void **)strArray, 3, NULL, 0); + EXPECT_EQ(res, NULL); + + // Matched + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "a1", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a1"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "a2", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a2"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "a3", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a3"); + EXPECT_EQ(ret, 0); + + // Not matched + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A1", 0); + EXPECT_EQ(res, nullptr); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A2", 0); + EXPECT_EQ(res, nullptr); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A1", 1); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a1"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A2", 2); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a2"); + EXPECT_EQ(ret, 0); + res = OH_StrDictGet((void **)strArray, sizeof(const char *), "A3", 3); + ASSERT_NE(res, nullptr); + ret = strcmp(*(const char **)res, "a3"); + EXPECT_EQ(ret, 0); +} + +using STRING_INT_DICT = struct { + const char *key; + int val; +}; + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_int_dict, TestSize.Level1) +{ + const STRING_INT_DICT *res; + const STRING_INT_DICT strIntDict[] = { + {"a1", 1}, + {"a2", 2}, + {"a3", 3}, + {NULL, 0} + }; + + // Matched + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "a1", 0); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 1); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "a2", 0); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 2); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "a3", 0); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 3); + + // Not matched + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A2", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A1", 3); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 1); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A2", 2); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 2); + res = (const STRING_INT_DICT *)OH_StrDictGet((void **)strIntDict, sizeof(STRING_INT_DICT), "A3", 1); + ASSERT_NE(res, nullptr); + EXPECT_EQ(res->val, 3); +} + +using STRING_STRING_DICT = struct { + const char *key; + const char *val; +}; + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_str_dict, TestSize.Level1) +{ + int ret; + const STRING_STRING_DICT *res; + const STRING_STRING_DICT strStrDict[] = { + {"a1", "val1"}, + {"a2", "val2"}, + {"a3", "val3"}, + {NULL, NULL} + }; + + // Matched + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "a1", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "a2", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "a3", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); + + // Not matched + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A2", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A1", 3); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A2", 2); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + res = (const STRING_STRING_DICT *)OH_StrDictGet((void **)strStrDict, + sizeof(STRING_STRING_DICT), "A3", 1); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); +} + +using STRING_HYBRID_DICT = struct { + const char *key; + int cnt; + const char *val; +}; + +HWTEST_F(StrUtilUnitTest, StrDictGet_unit_test_str_hybrid_dict, TestSize.Level1) +{ + int ret; + const STRING_HYBRID_DICT *res; + const STRING_HYBRID_DICT strHybridDict[] = { + {"a1", 1, "val1"}, + {"a2", 2, "val2"}, + {"a3", 3, "val3"}, + {NULL, 0, NULL} + }; + + // string array Matched + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a1", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 1); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a2", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 2); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a3", 0); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 3); + + // Not matched + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "aa1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A1", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A2", 0); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A3", 0); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A1", 3); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val1"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 1); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A2", 2); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val2"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 2); + res = (const STRING_HYBRID_DICT *)OH_StrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A3", 1); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val3"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 3); +} + +HWTEST_F(StrUtilUnitTest, ExtendableStrDictGet_unit_test, TestSize.Level1) +{ + int ret; + const STRING_HYBRID_DICT *res; + const STRING_HYBRID_DICT strHybridDict[] = { + {"a1", 1, "val1"}, + {"a2", 2, "val2"}, + {"a3", 3, "val3"}, + {NULL, 0, NULL} + }; + const STRING_HYBRID_DICT extendHybridDict[] = { + {"a4", 4, "val4"}, + {"a5", 5, "val5"}, + {"a6", 6, "val6"}, + {NULL, 0, NULL} + }; + + // string array Matched + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a4", 0, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val4"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 4); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a5", 0, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val5"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 5); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "a6", 0, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val6"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 6); + + // Not matched + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "aa1", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A4", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A5", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A6", 0, (void **)extendHybridDict); + EXPECT_EQ(res, nullptr); + + // Ignore case + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A4", 3, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val4"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 4); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A5", 2, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val5"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 5); + res = (const STRING_HYBRID_DICT *)OH_ExtendableStrDictGet((void **)strHybridDict, + sizeof(STRING_HYBRID_DICT), "A6", 1, (void **)extendHybridDict); + ASSERT_NE(res, nullptr); + ret = strcmp(res->val, "val6"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(res->cnt, 6); +} +} // namespace init_ut diff --git a/test/unittest/lite/BUILD.gn b/test/unittest/lite/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..1f92813719f0480b5cf98804245d68cefbbd1fc7 --- /dev/null +++ b/test/unittest/lite/BUILD.gn @@ -0,0 +1,254 @@ +# Copyright (c) 2020-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. +if (defined(ohos_lite)) { + import("//base/startup/init/begetd.gni") + import("//build/lite/config/component/lite_component.gni") + import("//build/lite/config/test.gni") + if (ohos_kernel_type == "linux" || ohos_kernel_type == "liteos_a") { + init_common_sources = [ + "//base/startup/init/services/init/adapter/init_adapter.c", + "//base/startup/init/services/init/init_capability.c", + "//base/startup/init/services/init/init_common_cmds.c", + "//base/startup/init/services/init/init_common_service.c", + "//base/startup/init/services/init/init_config.c", + "//base/startup/init/services/init/init_group_manager.c", + "//base/startup/init/services/init/init_service_file.c", + "//base/startup/init/services/init/init_service_manager.c", + "//base/startup/init/services/init/init_service_socket.c", + "//base/startup/init/services/init/lite/init.c", + "//base/startup/init/services/init/lite/init_cmds.c", + "//base/startup/init/services/init/lite/init_jobs.c", + "//base/startup/init/services/init/lite/init_reboot.c", + "//base/startup/init/services/init/lite/init_service.c", + "//base/startup/init/services/init/lite/init_signal_handler.c", + "//base/startup/init/services/log/init_log.c", + "//base/startup/init/services/utils/init_utils.c", + ] + } + param_common_sources = [ + "//base/startup/init/services/modules/init_hook/param_hook.c", + "//base/startup/init/services/modules/udid/udid_adp.c", + "//base/startup/init/services/modules/udid/udid_comm.c", + "//base/startup/init/services/param/manager/param_manager.c", + "//base/startup/init/services/param/manager/param_persist.c", + "//base/startup/init/services/param/manager/param_server.c", + ] + + base_sources = [ + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/services/param/base/param_base.c", + "//base/startup/init/services/param/base/param_comm.c", + "//base/startup/init/services/param/base/param_trie.c", + "//base/startup/init/services/utils/init_hashmap.c", + "//base/startup/init/services/utils/list.c", + ] + + sysparam_source = [ + "//base/startup/init/interfaces/innerkits/syspara/param_comm.c", + "//base/startup/init/interfaces/innerkits/syspara/parameter.c", + "//base/startup/init/interfaces/innerkits/syspara/sysversion.c", + ] + + unittest("init_test") { + output_extension = "bin" + output_dir = "$root_out_dir/test/unittest/startup" + ldflags = [ + "-lstdc++", + "-lpthread", + "-lm", + ] + defines = [ + "OHOS_LITE", + "__MUSL__", + "_GNU_SOURCE", + "READ_CHECK", + "STARTUP_INIT_TEST", + "PARAM_SUPPORT_DAC", + "USE_MBEDTLS", + ] + if (storage_type == "emmc") { + defines += [ "USE_EMMC_STORAGE" ] + } + + include_dirs = [ + "//base/startup/init/services/begetctl", + "//base/startup/init/services/begetctl/shell", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/init/include", + "//base/startup/init/services/log", + "//base/startup/init/services/loopevent/include", + "//base/startup/init/services/loopevent/timer", + "//base/startup/init/services/loopevent/task", + "//base/startup/init/services/loopevent/utils", + "//base/startup/init/services/loopevent/loop", + "//base/startup/init/services/param/adapter", + "//base/startup/init/services/param/base", + "//base/startup/init/services/param/linux", + "//base/startup/init/services/param/include", + "//base/startup/init/services/param/watcher/agent", + "//base/startup/init/services/param/watcher/include", + "//base/startup/init/services/param/watcher/proxy", + "//base/startup/init/services/modules", + "//base/startup/init/services/modules/init_hook", + "//base/startup/init/services/modules/selinux", + "//base/startup/init/test/unittest", + "//base/startup/init/test/unittest/param", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/syspara", + "//base/startup/init/interfaces/innerkits/init_module_engine/include", + "//base/startup/init/interfaces/innerkits/syspara", + "//base/startup/init/ueventd", + "//base/startup/init/ueventd/include", + "//third_party/cJSON", + "//base/hiviewdfx/hilog_lite/interfaces/native/kits", + "//base/startup/init/interfaces/innerkits/fd_holder", + "//base/startup/init/interfaces/hals", + "//base/startup/init/services/modules/udid", + ] + + sources = sysparam_source + sources += param_common_sources + sources += base_sources + deps = [] + external_deps = [ "bounds_checking_function:libsec_static" ] + + if (init_feature_begetctl_liteos) { + defines += [ "LITEOS_SUPPORT" ] + } + + if (ohos_kernel_type == "liteos_a") { + defines += [ + "__LITEOS_A__", + "STARTUP_INIT_UT_PATH =\"/userdata/init_ut\"", + ] + include_dirs += [ + "//kernel/liteos_a/syscall", + "//base/startup/init/interfaces/kits/syscap", + "//base/startup/init/initsync/include", + ] + sources += init_common_sources + sources += [ + "//base/startup/init/services/param/liteos/param_client.c", + "//base/startup/init/services/param/liteos/param_litedac.c", + "//base/startup/init/services/param/liteos/param_osadp.c", + "//base/startup/init/services/param/liteos/param_persistadp.c", + "//base/startup/init/services/param/liteos/param_service.c", + ] + + sources += [ + "../param/client_unittest.cpp", + "../param/param_stub.cpp", + "../param/param_unittest.cpp", + "../syspara/syspara_unittest.cpp", + "cmd_func_test.cpp", + ] + + # add cfg.h + if (init_feature_begetctl_liteos) { + PRODUCT_HAL_SYSPARAM_PATH = + rebase_path("${ohos_product_adapter_dir}/utils/sys_param") + cmd = "if [ -f ${PRODUCT_HAL_SYSPARAM_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + PRODUCT_HAL_SYSPARAM_EXISTS = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (PRODUCT_HAL_SYSPARAM_EXISTS) { + deps += [ "$ohos_product_adapter_dir/utils/sys_param:hal_sysparam" ] + } + deps += [ + "//base/startup/init/interfaces/hals/utils/sys_param:hal_sys_param", + ] + deps += + [ "//base/startup/init/services/param/liteos:lite_ohos_param_to" ] + include_dirs += [ "$root_out_dir/gen/init" ] + defines += [ "PARAM_LOAD_CFG_FROM_CODE" ] + } + deps += [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/initsync:initsync", + "//base/startup/init/services/loopevent:loopevent", + "//build/lite/config/component/cJSON:cjson_static", + ] + external_deps += [ "mbedtls:mbedtls_static" ] + } + + if (ohos_kernel_type == "liteos_m") { + defines += [ + "__LITEOS_M__", + "STARTUP_INIT_UT_PATH =\"/\"", + ] + sources += [ + "//base/startup/init/services/param/liteos/param_client.c", + "//base/startup/init/services/param/liteos/param_hal.c", + "//base/startup/init/services/param/liteos/param_litedac.c", + "//base/startup/init/services/param/liteos/param_osadp.c", + "//base/startup/init/services/param/liteos/param_service.c", + ] + if (init_lite_use_posix_file_api) { + defines += [ "PARAM_SUPPORT_POSIX" ] + } + sources += [ + "../param/dac_unittest.cpp", + "../param/param_stub.cpp", + "../param/param_unittest.cpp", + "../syspara/syspara_unittest.cpp", + ] + + # add cfg.h + if (init_feature_begetctl_liteos) { + deps += + [ "//base/startup/init/services/param/liteos:lite_ohos_param_to" ] + include_dirs += [ "$root_out_dir/gen/init" ] + defines += [ "PARAM_LOAD_CFG_FROM_CODE" ] + } + deps += [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_static" ] + external_deps += [ "mbedtls:mbedtls_static" ] + } + if (ohos_kernel_type == "linux") { + defines += [ + "__LINUX__", + "STARTUP_INIT_UT_PATH =\"/data/init_ut\"", + ] + + sources += init_common_sources + sources += [ + "//base/startup/init/services/param/adapter/param_dac.c", + "//base/startup/init/services/param/linux/param_message.c", + "//base/startup/init/services/param/linux/param_msgadp.c", + "//base/startup/init/services/param/linux/param_osadp.c", + "//base/startup/init/services/param/linux/param_request.c", + "//base/startup/init/services/param/linux/param_service.c", + "//base/startup/init/services/param/liteos/param_persistadp.c", + "//base/startup/init/services/param/trigger/trigger_checker.c", + "//base/startup/init/services/param/trigger/trigger_manager.c", + "//base/startup/init/services/param/trigger/trigger_processor.c", + ] + sources += [ + "../param/client_unittest.cpp", + "../param/dac_unittest.cpp", + "../param/param_stub.cpp", + "../param/param_unittest.cpp", + "../param/paramservice_unittest.cpp", + "cmd_func_test.cpp", + ] + if (init_feature_begetctl_liteos) { + sources += [ "../syspara/syspara_unittest.cpp" ] + } + deps += [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/services/loopevent:loopevent", + "//build/lite/config/component/cJSON:cjson_static", + ] + external_deps += [ "mbedtls:mbedtls_static" ] + } + } +} diff --git a/services/test/unittest/common/cmd_func_test.cpp b/test/unittest/lite/cmd_func_test.cpp similarity index 68% rename from services/test/unittest/common/cmd_func_test.cpp rename to test/unittest/lite/cmd_func_test.cpp index 28cf07f5e4948dd15f301a4d508fb72bbfcfac31..19a65c6e3f42a75abdf23181811c556f3927689b 100644 --- a/services/test/unittest/common/cmd_func_test.cpp +++ b/test/unittest/lite/cmd_func_test.cpp @@ -12,19 +12,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include +#include #include #include #include +#include #include #include #include + #include "cJSON.h" -#include "gtest/gtest.h" -#include "securec.h" -#include "init_jobs.h" +#include "init_cmds.h" +#include "init_jobs_internal.h" +#include "init_log.h" #include "init_service_manager.h" +#include "param_stub.h" +#include "securec.h" +using namespace std; using namespace testing::ext; namespace OHOS { @@ -34,12 +39,13 @@ const std::string TEST_DRI = ROOT_DIR + "StartInitTestDir"; const std::string TEST_FILE = TEST_DRI + "/test.txt"; const std::string TEST_CFG_ILLEGAL = TEST_DRI + "/illegal.cfg"; const std::string TEST_PROC_MOUNTS = "/proc/mounts"; +#ifndef USE_EMMC_STORAGE const uid_t TEST_FILE_UID = 999; const gid_t TEST_FILE_GID = 999; const mode_t TEST_FILE_MODE = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; -const mode_t DEFAULT_DIR_MODE = 0755; +#endif -// init.cfg releated +// init.cfg related const std::string CFG_FILE = "/etc/init.cfg"; const std::string SERVICE_ARR_NAME_IN_JSON = "services"; const std::string JOBS_ARR_NAME_IN_JSON = "jobs"; @@ -47,21 +53,24 @@ const std::string CMDS_ARR_NAME_IN_JSON = "cmds"; const uid_t CFG_FILE_UID = 0; const gid_t CFG_FILE_GID = 0; const mode_t CFG_FILE_MODE = S_IRUSR; -const int JOBS_IN_FILE_COUNT = 3; // pre-init, init, post-init +const int JOBS_IN_FILE_COUNT = 3; // pre-init, init, post-init const int MAX_SERVICES_COUNT_IN_FILE = 100; const int MAX_CAPS_CNT_FOR_ONE_SERVICE = 100; -const unsigned int MAX_CAPABILITY_VALUE = 4294967295; // 0xFFFFFFFF -const unsigned int MAX_JSON_FILE_LEN = 102400; // max init.cfg size 100KB -const int MAX_PATH_ARGS_CNT = 20; // max path and args count -const int MAX_ONE_ARG_LEN = 64; // max length of one param/path -const int CAT_BUF_SIZE = 512; // standard Cat buffer size from vfs_shell_cmd - -// job test releated -const pid_t INVALID_PID = -1; +const unsigned int MAX_JSON_FILE_LEN = 102400; // max init.cfg size 100KB +const int TEST_MAX_PATH_ARGS_CNT = 20; // max path and args count +const int TEST_MAX_ONE_ARG_LEN = 64; // max length of one param/path +const int CAT_BUF_SIZE = 512; // standard Cat buffer size from vfs_shell_cmd + +// job test related const std::string PRE_INIT_DIR = ROOT_DIR + "preInitDir/"; const std::string INIT_DIR = PRE_INIT_DIR + "initDir"; const std::string POST_INIT_DIR = INIT_DIR + "postInitDir"; +using TestCmdLine = struct { + char name[MAX_CMD_NAME_LEN + 1]; + char cmdContent[MAX_CMD_CONTENT_LEN + 1]; +}; + class StartupInitUTest : public testing::Test { public: static void SetUpTestCase() @@ -72,85 +81,107 @@ public: g_supportedCmds.push_back(std::string("chown ")); g_supportedCmds.push_back(std::string("mount ")); g_supportedCmds.push_back(std::string("loadcfg ")); - - mode_t mode = DEFAULT_DIR_MODE; + const mode_t mode = 0755; if (mkdir(TEST_DRI.c_str(), mode) != 0) { if (errno != EEXIST) { - printf("[----------] StartupInitUTest, mkdir for %s failed, error %d.\n",\ - TEST_DRI.c_str(), errno); return; } } - FILE* testFile = fopen(TEST_FILE.c_str(), "w+"); + FILE *testFile = fopen(TEST_FILE.c_str(), "w+"); if (testFile == nullptr) { - printf("[----------] StartupInitUTest, open file %s failed, error %d.\n",\ - TEST_FILE.c_str(), errno); return; } std::string writeContent = "This is a test file for startup subsystem init module."; if (fwrite(writeContent.c_str(), writeContent.length(), 1, testFile) != 1) { - printf("[----------] StartupInitUTest, open file %s failed, error %d.\n", TEST_FILE.c_str(), errno); - fclose(testFile); + (void)fclose(testFile); return; } - fclose(testFile); + (void)fclose(testFile); #ifndef USE_EMMC_STORAGE // emmc storage does not support chmod/chown if (chmod(TEST_FILE.c_str(), TEST_FILE_MODE) != 0) { - printf("[----------] StartupInitUTest, chmod for file %s failed, error %d.\n", TEST_FILE.c_str(), errno); return; } if (chown(TEST_FILE.c_str(), TEST_FILE_UID, TEST_FILE_GID) != 0) { - printf("[----------] StartupInitUTest, chown for file %s failed, error %d.\n", TEST_FILE.c_str(), errno); return; } - #endif // USE_EMMC_STORAGE - - printf("[----------] StartupInitUTest, cmd func test setup.\n"); + PrepareInitUnitTestEnv(); } static void TearDownTestCase() { if (remove(TEST_FILE.c_str()) != 0) { - printf("[----------] StartupInitUTest, remove %s failed, error %d.\n", TEST_FILE.c_str(), errno); + return; } - if (remove(TEST_DRI.c_str()) != 0) { - printf("[----------] StartupInitUTest, remove %s failed, error %d.\n", TEST_DRI.c_str(), errno); + return; } - printf("[----------] StartupInitUTest, cmd func test teardown.\n"); } - void SetUp() {} + void SetUp() + { + EnableInitLog(INIT_FATAL); + } void TearDown() {} }; +void ParseCmdLine(const char *content, TestCmdLine *resCmd) +{ + if (content == nullptr || resCmd == nullptr) { + return; + } + + const struct CmdTable *cmd = GetCmdByName(content); + if (cmd == nullptr) { + (void)memset_s(resCmd, sizeof(TestCmdLine), 0, sizeof(TestCmdLine)); + return; + } + if (strlen(content) <= (strlen(cmd->name) + 1)) { + (void)memset_s(resCmd, sizeof(TestCmdLine), 0, sizeof(TestCmdLine)); + return; + } + int ret1 = strcpy_s(resCmd->name, MAX_CMD_NAME_LEN, cmd->name); + int ret2 = strcpy_s(resCmd->cmdContent, MAX_CMD_CONTENT_LEN, content + strlen(cmd->name)); + if (ret1 || ret2) { + (void)memset_s(resCmd, sizeof(TestCmdLine), 0, sizeof(TestCmdLine)); + return; + } +} + +void DoCmd(const TestCmdLine *resCmd) +{ + if (resCmd == nullptr) { + return; + } + int cmdIndex = 0; + (void)GetMatchCmd(resCmd->name, &cmdIndex); + DoCmdByIndex(cmdIndex, resCmd->cmdContent, nullptr); +} + /* - ** @tc.name: cmdFuncParseCmdTest_001 - ** @tc.desc: parse function, nullptr test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_001, TestSize.Level1) + * @tc.name: cmdFuncParseCmdTest_001 + * @tc.desc: parse function, nullptr test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_001, TestSize.Level0) { // do not crash ParseCmdLine(nullptr, nullptr); }; /* - ** @tc.name: cmdFuncParseCmdTest_002 - ** @tc.desc: parse function, invalid strings test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_002, TestSize.Level1) + * @tc.name: cmdFuncParseCmdTest_002 + * @tc.desc: parse function, invalid strings test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_002, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); ParseCmdLine(nullptr, &curCmdLine); EXPECT_EQ(0, strlen(curCmdLine.name)); @@ -170,15 +201,14 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_002, TestSize.Level1) } /* - ** @tc.name: cmdFuncParseCmdTest_003 - ** @tc.desc: parse function, cmd content empty test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_003, TestSize.Level1) + * @tc.name: cmdFuncParseCmdTest_003 + * @tc.desc: parse function, cmd content empty test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_003, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); for (size_t i = 0; i < g_supportedCmds.size(); ++i) { ParseCmdLine(g_supportedCmds[i].c_str(), &curCmdLine); @@ -188,24 +218,24 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_003, TestSize.Level1) } /* - ** @tc.name: cmdFuncParseCmdTest_004 - ** @tc.desc: parse function, cmd content too long test - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level1) + * @tc.name: cmdFuncParseCmdTest_004 + * @tc.desc: parse function, cmd content too long test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); char toLongContent[MAX_CMD_CONTENT_LEN + 10]; - memset_s(toLongContent, MAX_CMD_CONTENT_LEN + 10, 'x', MAX_CMD_CONTENT_LEN + 9); + int ret = memset_s(toLongContent, MAX_CMD_CONTENT_LEN + 10, 'x', MAX_CMD_CONTENT_LEN + 9); + EXPECT_EQ(0, ret); + toLongContent[MAX_CMD_CONTENT_LEN + 9] = '\0'; for (size_t i = 0; i < g_supportedCmds.size(); ++i) { size_t curCmdLen = g_supportedCmds[i].length(); - char* curCmd = (char*)malloc(curCmdLen + MAX_CMD_CONTENT_LEN + 10); + char *curCmd = (char *)malloc(curCmdLen + MAX_CMD_CONTENT_LEN + 10); if (curCmd == nullptr) { - printf("[----------] StartupInitUTest, cmdFuncParseCmdTest004, malloc failed.\n"); break; } errno_t ret = memcpy_s(curCmd, curCmdLen + MAX_CMD_CONTENT_LEN + 10, \ @@ -213,7 +243,6 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level1) errno_t ret2 = memcpy_s(curCmd + curCmdLen, MAX_CMD_CONTENT_LEN + 10, \ toLongContent, strlen(toLongContent)); if (ret != EOK || ret2 != EOK) { - printf("[----------] StartupInitUTest, cmdFuncParseCmdTest004, memcpy_s failed.\n"); free(curCmd); curCmd = nullptr; break; @@ -229,15 +258,14 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level1) } /* - ** @tc.name: cmdFuncParseCmdTest_005 - ** @tc.desc: parse function, parse success test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_005, TestSize.Level1) + * @tc.name: cmdFuncParseCmdTest_005 + * @tc.desc: parse function, parse success test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_005, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); ParseCmdLine("start InitTestService", &curCmdLine); EXPECT_EQ(0, strcmp("start ", curCmdLine.name)); @@ -261,56 +289,55 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_005, TestSize.Level1) }; /* - ** @tc.name: cmdFuncDoCmdTest_001 - ** @tc.desc: do cmd function, nullptr test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_001, TestSize.Level1) + * @tc.name: cmdFuncDoCmdTest_001 + * @tc.desc: do cmd function, nullptr test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_001, TestSize.Level0) { // do not crash here DoCmd(nullptr); } /* - ** @tc.name: cmdFuncDoCmdTest_002 - ** @tc.desc: do cmd function, do start fail test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_002, TestSize.Level1) + * @tc.name: cmdFuncDoCmdTest_002 + * @tc.desc: do cmd function, do start fail test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_002, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); std::string cmdStr = "start "; std::string cmdContentStr = "NameNotExist"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); } /* - ** @tc.name: cmdFuncDoCmdTest_003 - ** @tc.desc: do cmd function, do mkdir fail test - ** @tc.type: FUNC - ** @tc.require: AR000F733E - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level1) + * @tc.name: cmdFuncDoCmdTest_003 + * @tc.desc: do cmd function, do mkdir fail test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); std::string cmdStr = "mkdir "; std::string cmdContentStr = "/DirNotExist/DirNotExist/DirNotExist"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); // make sure that the directory does not exist - DIR* dirTmp = opendir(cmdContentStr.c_str()); + DIR *dirTmp = opendir(cmdContentStr.c_str()); EXPECT_TRUE(dirTmp == nullptr); EXPECT_TRUE(errno == ENOENT); if (dirTmp != nullptr) { // just in case @@ -320,7 +347,8 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level1) // error argument count, bad format cmdContentStr = " /storage/data/cmdFuncDoCmdTest003 0755 system"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); @@ -336,43 +364,47 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level1) } /* - ** @tc.name: cmdFuncDoCmdTest_004 - ** @tc.desc: do cmd function, do chmod fail test - ** @tc.type: FUNC - ** @tc.require: AR000F732P - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_004, TestSize.Level1) + * @tc.name: cmdFuncDoCmdTest_004 + * @tc.desc: do cmd function, do chmod fail test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_004, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); std::string cmdStr = "chmod "; std::string cmdContentStr = "755 " + TEST_FILE; // should be 0755, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); cmdContentStr = "0855 " + TEST_FILE; // should not exceed 0777, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command .c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); cmdContentStr = "07b5 " + TEST_FILE; // non-digital character, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); cmdContentStr = "075 " + TEST_FILE; // should be 0xxx, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); cmdContentStr = "0755 " + TEST_FILE; // too many spaces, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); @@ -388,25 +420,26 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_004, TestSize.Level1) } /* - ** @tc.name: cmdFuncDoCmdTest_005 - ** @tc.desc: do cmd function, do chown fail test - ** @tc.type: FUNC - ** @tc.require: AR000F732P - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_005, TestSize.Level1) + * @tc.name: cmdFuncDoCmdTest_005 + * @tc.desc: do cmd function, do chown fail test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_005, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); std::string cmdStr = "chown "; std::string cmdContentStr = "888 " + TEST_FILE; // uid or gid missing, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); cmdContentStr = "888 8b9 " + TEST_FILE; // non-digital character, wrong format here - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); DoCmd(&curCmdLine); @@ -423,19 +456,19 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_005, TestSize.Level1) } /* - ** @tc.name: cmdFuncDoCmdTest_006 - ** @tc.desc: do cmd function, do success test - ** @tc.type: FUNC - ** @tc.require: AR000F732P - **/ -HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level1) + * @tc.name: cmdFuncDoCmdTest_006 + * @tc.desc: do cmd function, do success test + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level0) { - CmdLine curCmdLine; + TestCmdLine curCmdLine; // mkdir success std::string cmdStr = "mkdir "; std::string cmdContentStr = TEST_DRI + "/cmdFuncDoCmdTest006"; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); @@ -447,16 +480,12 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level1) dirTmp = nullptr; } - // delete dir - if (remove(cmdContentStr.c_str()) != 0) { - printf("[----------] StartupInitUTest, cmdFuncDoCmdTest006 remove %s failed, error %d.\n",\ - TEST_DRI.c_str(), errno); - } - + remove(cmdContentStr.c_str()); // chmod success cmdStr = "chmod "; cmdContentStr = "0440 " + TEST_FILE; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); @@ -473,7 +502,8 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level1) // chown success cmdStr = "chown "; cmdContentStr = "888 888 " + TEST_FILE; - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); @@ -488,12 +518,11 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level1) } /* - ** @tc.name: cfgCheckStat_001 - ** @tc.desc: init.cfg file state check - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cfgCheckStat_001, TestSize.Level1) + * @tc.name: cfgCheckStat_001 + * @tc.desc: init.cfg file state check + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cfgCheckStat_001, TestSize.Level0) { struct stat fileStat = {0}; EXPECT_EQ(0, stat(CFG_FILE.c_str(), &fileStat)); @@ -506,8 +535,8 @@ HWTEST_F(StartupInitUTest, cfgCheckStat_001, TestSize.Level1) static char* ReadFileToBuf() { - char* buffer = nullptr; - FILE* fd = nullptr; + char *buffer = nullptr; + FILE *fd = nullptr; struct stat fileStat = {0}; (void)stat(CFG_FILE.c_str(), &fileStat); do { @@ -536,9 +565,9 @@ static char* ReadFileToBuf() return buffer; } -static cJSON* GetArrItem(const cJSON* fileRoot, int& arrSize, const std::string& arrName) +static cJSON *GetArrItem(const cJSON *fileRoot, int &arrSize, const std::string &arrName) { - cJSON* arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName.c_str()); + cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName.c_str()); arrSize = cJSON_GetArraySize(arrItem); if (arrSize <= 0) { return nullptr; @@ -546,7 +575,7 @@ static cJSON* GetArrItem(const cJSON* fileRoot, int& arrSize, const std::string& return arrItem; } -static int IsForbidden(const char* fieldStr) +static int IsForbidden(const char *fieldStr) { size_t fieldLen = strlen(fieldStr); size_t forbidStrLen = strlen("/bin/sh"); @@ -574,37 +603,37 @@ static void CheckService(const cJSON* curItem) return; } - char* nameStr = cJSON_GetStringValue(cJSON_GetObjectItem(curItem, "name")); + char *nameStr = cJSON_GetStringValue(cJSON_GetObjectItem(curItem, "name")); if (nameStr == nullptr) { EXPECT_TRUE(nameStr != nullptr); } else { EXPECT_TRUE(strlen(nameStr) > 0); } - cJSON* pathArgsItem = cJSON_GetObjectItem(curItem, "path"); + cJSON *pathArgsItem = cJSON_GetObjectItem(curItem, "path"); EXPECT_TRUE(cJSON_IsArray(pathArgsItem)); int pathArgsCnt = cJSON_GetArraySize(pathArgsItem); EXPECT_TRUE(pathArgsCnt > 0); - EXPECT_TRUE(pathArgsCnt <= MAX_PATH_ARGS_CNT); + EXPECT_TRUE(pathArgsCnt <= TEST_MAX_PATH_ARGS_CNT); for (int i = 0; i < pathArgsCnt; ++i) { - char* curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathArgsItem, i)); - EXPECT_TRUE(curParam != NULL); + char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathArgsItem, i)); + EXPECT_TRUE(curParam != nullptr); EXPECT_TRUE(strlen(curParam) > 0); - EXPECT_TRUE(strlen(curParam) <= MAX_ONE_ARG_LEN); + EXPECT_TRUE(strlen(curParam) <= TEST_MAX_ONE_ARG_LEN); if (i == 0) { EXPECT_TRUE(IsForbidden(curParam) == 0); } } - cJSON* filedJ = cJSON_GetObjectItem(curItem, "uid"); - EXPECT_TRUE(cJSON_IsNumber(filedJ)); - EXPECT_TRUE(cJSON_GetNumberValue(filedJ) >= 0.0); + cJSON *filedJ = cJSON_GetObjectItem(curItem, "uid"); + EXPECT_TRUE(cJSON_IsNumber(filedJ) || cJSON_IsString(filedJ)); + EXPECT_TRUE(cJSON_GetNumberValue(filedJ) >= 0.0 || cJSON_GetStringValue(filedJ)); filedJ = cJSON_GetObjectItem(curItem, "gid"); - EXPECT_TRUE(cJSON_IsNumber(filedJ)); - EXPECT_TRUE(cJSON_GetNumberValue(filedJ) >= 0.0); + EXPECT_TRUE(cJSON_IsNumber(filedJ) || cJSON_IsArray(filedJ)); + EXPECT_TRUE(cJSON_GetNumberValue(filedJ) >= 0.0 || cJSON_GetArraySize(filedJ) >= 0); filedJ = cJSON_GetObjectItem(curItem, "once"); EXPECT_TRUE(cJSON_IsNumber(filedJ)); @@ -617,35 +646,27 @@ static void CheckService(const cJSON* curItem) int capsCnt = cJSON_GetArraySize(filedJ); EXPECT_TRUE(capsCnt <= MAX_CAPS_CNT_FOR_ONE_SERVICE); for (int i = 0; i < capsCnt; ++i) { - cJSON* capJ = cJSON_GetArrayItem(filedJ, i); - EXPECT_TRUE(cJSON_IsNumber(capJ)); - EXPECT_TRUE(cJSON_GetNumberValue(capJ) >= 0.0); - - // only shell can have all capabilities - if ((unsigned int)cJSON_GetNumberValue(capJ) == MAX_CAPABILITY_VALUE) { - if (nameStr != nullptr) { - EXPECT_EQ(0, strcmp(nameStr, "shell")); - } - EXPECT_EQ(1, capsCnt); - } + cJSON *capJ = cJSON_GetArrayItem(filedJ, i); + EXPECT_TRUE(cJSON_IsNumber(capJ) || cJSON_GetStringValue(capJ)); + EXPECT_TRUE(cJSON_GetNumberValue(capJ) >= 0.0 || cJSON_GetStringValue(capJ)); } } -static void CheckServices(const cJSON* fileRoot) +static void CheckServices(const cJSON *fileRoot) { int servArrSize = 0; - cJSON* serviceArr = GetArrItem(fileRoot, servArrSize, SERVICE_ARR_NAME_IN_JSON); + cJSON *serviceArr = GetArrItem(fileRoot, servArrSize, SERVICE_ARR_NAME_IN_JSON); EXPECT_TRUE(serviceArr != nullptr); EXPECT_TRUE(servArrSize <= MAX_SERVICES_COUNT_IN_FILE); for (int i = 0; i < servArrSize; ++i) { - cJSON* curItem = cJSON_GetArrayItem(serviceArr, i); + cJSON *curItem = cJSON_GetArrayItem(serviceArr, i); EXPECT_TRUE(curItem != nullptr); CheckService(curItem); } } -static void CheckCmd(const CmdLine* resCmd) +static void CheckCmd(const TestCmdLine *resCmd) { EXPECT_TRUE(strlen(resCmd->name) > 0); EXPECT_TRUE(strlen(resCmd->cmdContent) > 0); @@ -656,7 +677,6 @@ static void CheckCmd(const CmdLine* resCmd) } } else if (strcmp("mkdir ", resCmd->name) == 0) { for (size_t i = 0; i < strlen(resCmd->cmdContent); ++i) { - EXPECT_NE(' ', resCmd->cmdContent[i]); // no spaces in path string EXPECT_NE('.', resCmd->cmdContent[i]); // no dots in path string } } else if (strcmp("chmod ", resCmd->name) == 0) { @@ -668,7 +688,6 @@ static void CheckCmd(const CmdLine* resCmd) } for (size_t i = 5; i < strlen(resCmd->cmdContent); ++i) { // target starts from index 5 EXPECT_NE(' ', resCmd->cmdContent[i]); // no spaces allowed - EXPECT_NE('.', resCmd->cmdContent[i]); // no dots allowed } } else if (strcmp("chown ", resCmd->name) == 0) { EXPECT_TRUE(strlen(resCmd->cmdContent) >= 5); // x y z at least 5 characters @@ -677,31 +696,36 @@ static void CheckCmd(const CmdLine* resCmd) size_t spacePos = 0; size_t spaceCnt = 0; for (size_t i = 1; i < strlen(resCmd->cmdContent); ++i) { - if (resCmd->cmdContent[i] == ' ') { - ++spaceCnt; - if (spacePos != 0) { - EXPECT_NE(spacePos + 1, i); // consecutive spaces should not appear - } - spacePos = i; + if (resCmd->cmdContent[i] != ' ') { + continue; + } + ++spaceCnt; + if (spacePos != 0) { + EXPECT_NE(spacePos + 1, i); // consecutive spaces should not appear } + spacePos = i; } EXPECT_EQ(spaceCnt, 2); // 2 spaces allowed in cmd content } else if (strcmp("mount ", resCmd->name) == 0) { EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space } else if (strcmp("loadcfg ", resCmd->name) == 0) { EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space + } else if (strcmp("export ", resCmd->name) == 0) { + EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space + } else if (strcmp("exec ", resCmd->name) == 0) { + EXPECT_NE(' ', resCmd->cmdContent[0]); // should not start with space } else { // unknown cmd EXPECT_TRUE(false); } } -static void CheckJob(const cJSON* jobItem) +static void CheckJob(const cJSON *jobItem) { if (jobItem == nullptr) { return; } - cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON.c_str()); + cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON.c_str()); EXPECT_TRUE(cmdsItem != nullptr); EXPECT_TRUE(cJSON_IsArray(cmdsItem)); @@ -709,11 +733,11 @@ static void CheckJob(const cJSON* jobItem) EXPECT_TRUE(cmdLinesCnt <= MAX_CMD_CNT_IN_ONE_JOB); for (int i = 0; i < cmdLinesCnt; ++i) { - char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i)); + char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i)); EXPECT_TRUE(cmdLineStr != nullptr); EXPECT_TRUE(strlen(cmdLineStr) > 0); - CmdLine resCmd; + TestCmdLine resCmd; (void)memset_s(&resCmd, sizeof(resCmd), 0, sizeof(resCmd)); ParseCmdLine(cmdLineStr, &resCmd); CheckCmd(&resCmd); @@ -723,7 +747,7 @@ static void CheckJob(const cJSON* jobItem) static void CheckJobs(const cJSON* fileRoot) { int jobArrSize = 0; - cJSON* jobArr = GetArrItem(fileRoot, jobArrSize, JOBS_ARR_NAME_IN_JSON); + cJSON *jobArr = GetArrItem(fileRoot, jobArrSize, JOBS_ARR_NAME_IN_JSON); EXPECT_TRUE(jobArr != nullptr); EXPECT_TRUE(jobArrSize == JOBS_IN_FILE_COUNT); @@ -731,9 +755,9 @@ static void CheckJobs(const cJSON* fileRoot) bool findInit = false; bool findPostInit = false; for (int i = 0; i < jobArrSize; ++i) { - cJSON* jobItem = cJSON_GetArrayItem(jobArr, i); + cJSON *jobItem = cJSON_GetArrayItem(jobArr, i); EXPECT_TRUE(jobItem != nullptr); - char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name")); + char *jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name")); EXPECT_TRUE(jobNameStr != nullptr); if (strcmp(jobNameStr, "pre-init") == 0) { findPreInit = true; @@ -753,20 +777,19 @@ static void CheckJobs(const cJSON* fileRoot) } /* - ** @tc.name: cfgCheckContent_001 - ** @tc.desc: init.cfg file content check - ** @tc.type: FUNC - ** @tc.require: AR000F733F - **/ -HWTEST_F(StartupInitUTest, cfgCheckContent_001, TestSize.Level1) + * @tc.name: cfgCheckContent_001 + * @tc.desc: init.cfg file content check + * @tc.type: FUNC + */ +HWTEST_F(StartupInitUTest, cfgCheckContent_001, TestSize.Level0) { - char* fileBuf = ReadFileToBuf(); + char *fileBuf = ReadFileToBuf(); if (fileBuf == nullptr) { EXPECT_TRUE(fileBuf != nullptr); return; } - cJSON* fileRoot = cJSON_Parse(fileBuf); + cJSON *fileRoot = cJSON_Parse(fileBuf); free(fileBuf); fileBuf = nullptr; @@ -782,36 +805,32 @@ HWTEST_F(StartupInitUTest, cfgCheckContent_001, TestSize.Level1) * @tc.name: CreateIllegalCfg * @tc.desc: Create illegal Config file for testing * @tc.type: FUNC - * @tc.require: AR000F861Q */ static void CreateIllegalCfg() { - FILE* testCfgFile = fopen(TEST_CFG_ILLEGAL.c_str(), "w+"); + FILE *testCfgFile = fopen(TEST_CFG_ILLEGAL.c_str(), "w+"); if (testCfgFile == nullptr) { - printf("[----------] StartupInitUTest, open file %s failed, error %d.\n", TEST_CFG_ILLEGAL.c_str(), errno); return; } std::string writeContent = "mount zpfs /patch/etc:/etc /etc"; if (fwrite(writeContent.c_str(), writeContent.length(), 1, testCfgFile) != 1) { - printf("[----------] StartupInitUTest, open file %s failed, error %d.\n", TEST_CFG_ILLEGAL.c_str(), errno); - fclose(testCfgFile); + (void)fclose(testCfgFile); return; } - fclose(testCfgFile); + (void)fclose(testCfgFile); } /* * @tc.name: cmdFuncDoLoadCfgTest_001 * @tc.desc: parse function, parse success test * @tc.type: FUNC - * @tc.require: AR000F861Q */ -HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level1) +HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level0) { - CmdLine curCmdLine; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + TestCmdLine curCmdLine; + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); ParseCmdLine("loadcfg /patch/fstab.cfg", &curCmdLine); EXPECT_EQ(0, strcmp("loadcfg ", curCmdLine.name)); @@ -822,17 +841,17 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level1) * @tc.name: cmdFuncDoLoadCfgTest_002 * @tc.desc: fstab.cfg file fail test * @tc.type: FUNC - * @tc.require: AR000F861Q */ -HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level1) +HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level0) { - CmdLine curCmdLine; + TestCmdLine curCmdLine; std::string cmdStr = "loadcfg "; std::string cmdContentStr = "/patch/file_not_exist.cfg"; struct stat testCfgStat = {0}; - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); stat(cmdContentStr.c_str(), &testCfgStat); @@ -841,39 +860,35 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level1) cmdContentStr = TEST_CFG_ILLEGAL; CreateIllegalCfg(); - memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + (void)memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine)); + command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); EXPECT_EQ(0, stat(cmdContentStr.c_str(), &testCfgStat)); EXPECT_TRUE(testCfgStat.st_size > 0); DoCmd(&curCmdLine); - // remove tmp file - if (remove(TEST_CFG_ILLEGAL.c_str()) != 0) { - printf("[----------] StartupInitUTest, remove %s failed, error %d.\n",\ - TEST_CFG_ILLEGAL.c_str(), errno); - } + remove(TEST_CFG_ILLEGAL.c_str()); } /* * @tc.name: cmdFuncDoLoadCfgTest_003 * @tc.desc: fstab.cfg file success test * @tc.type: FUNC - * @tc.require: AR000F861Q */ -HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level1) +HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level0) { - CmdLine curCmdLine; + TestCmdLine curCmdLine; std::string cmdStr = "loadcfg "; std::string cmdContentStr = "/patch/fstab.cfg"; char buf[CAT_BUF_SIZE] = {0}; struct stat testCfgStat = {0}; - FILE* fd = nullptr; + FILE *fd = nullptr; size_t size; bool hasZpfs = false; - - ParseCmdLine((cmdStr + cmdContentStr).c_str(), &curCmdLine); + std::string command = cmdStr + cmdContentStr; + ParseCmdLine(command.c_str(), &curCmdLine); EXPECT_EQ(0, strcmp(cmdStr.c_str(), curCmdLine.name)); EXPECT_EQ(0, strcmp(cmdContentStr.c_str(), curCmdLine.cmdContent)); @@ -900,7 +915,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level1) break; } } while (size > 0); - EXPECT_TRUE(hasZpfs == true); + EXPECT_TRUE(hasZpfs); fclose(fd); } } @@ -909,21 +924,18 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level1) * @tc.name: cmdJobTest_001 * @tc.desc: job functions test * @tc.type: FUNC - * @tc.require: AR000F733F */ -HWTEST_F(StartupInitUTest, cmdJobTest_001, TestSize.Level1) +HWTEST_F(StartupInitUTest, cmdJobTest_001, TestSize.Level0) { // functions do not crash - ParseAllJobs(nullptr); + ParseAllJobs(nullptr, nullptr); DoJob(nullptr); DoJob("job name does not exist"); ReleaseAllJobs(); - RegisterServices(nullptr, 0); StartServiceByName("service name does not exist"); - StopAllServices(); - ReapServiceByPID(INVALID_PID); + StopAllServices(0, nullptr, 0, nullptr); ServiceReap(nullptr); - EXPECT_NE(0, ServiceStart(nullptr)); + EXPECT_NE(0, ServiceStart(nullptr, nullptr)); EXPECT_NE(0, ServiceStop(nullptr)); } @@ -931,9 +943,8 @@ HWTEST_F(StartupInitUTest, cmdJobTest_001, TestSize.Level1) * @tc.name: cmdJobTest_002 * @tc.desc: job functions test * @tc.type: FUNC - * @tc.require: AR000F733F */ -HWTEST_F(StartupInitUTest, cmdJobTest_002, TestSize.Level1) +HWTEST_F(StartupInitUTest, cmdJobTest_002, TestSize.Level0) { std::string cfgJson = "{\"jobs\":[{\"name\":\"pre-init\",\"cmds\":[\"mkdir " + PRE_INIT_DIR + "\"]},{\"name\":\"init\",\"cmds\":[\"mkdir " + INIT_DIR + @@ -941,10 +952,10 @@ HWTEST_F(StartupInitUTest, cmdJobTest_002, TestSize.Level1) cJSON* jobItem = cJSON_Parse(cfgJson.c_str()); EXPECT_NE(nullptr, jobItem); if (jobItem == nullptr) { - printf("[----------] StartupInitUTest, job test, parse %s failed.\n", cfgJson.c_str()); return; } - ParseAllJobs(jobItem); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ParseAllJobs(jobItem, &context); DoJob("pre-init"); DoJob("init"); DoJob("post-init"); @@ -958,7 +969,6 @@ HWTEST_F(StartupInitUTest, cmdJobTest_002, TestSize.Level1) if (remove(POST_INIT_DIR.c_str()) != 0 || remove(INIT_DIR.c_str()) != 0 || remove(PRE_INIT_DIR.c_str()) != 0) { - printf("[----------] StartupInitUTest, job test, remove failed, error %d.\n", errno); } ReleaseAllJobs(); } diff --git a/test/unittest/loopevent/loopevent_unittest.cpp b/test/unittest/loopevent/loopevent_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81b277da29cd2805e4f19edf19492f3281d9b803 --- /dev/null +++ b/test/unittest/loopevent/loopevent_unittest.cpp @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2021 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 "begetctl.h" +#include "init.h" +#include "init_hashmap.h" +#include "init_param.h" +#include "init_utils.h" +#include "le_epoll.h" +#include "le_loop.h" +#include "le_socket.h" +#include "le_task.h" +#include "loop_event.h" +#include "param_manager.h" +#include "param_message.h" +#include "param_utils.h" +#include "trigger_manager.h" + +using namespace testing::ext; +using namespace std; + +using HashTab = struct { + HashNodeCompare nodeCompare; + HashKeyCompare keyCompare; + HashNodeFunction nodeHash; + HashKeyFunction keyHash; + HashNodeOnFree nodeFree; + int maxBucket; + uint32_t tableId; + HashNode *buckets[0]; +}; + +static LE_STATUS TestHandleTaskEvent(const LoopHandle loop, const TaskHandle task, uint32_t oper) +{ + return LE_SUCCESS; +} + +static void OnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread) +{ + UNUSED(task); + UNUSED(buffer); + UNUSED(nread); +} + +static void ProcessAsyncEvent(const TaskHandle taskHandle, uint64_t eventId, const uint8_t *buffer, uint32_t buffLen) +{ + UNUSED(taskHandle); + UNUSED(eventId); + UNUSED(buffer); + UNUSED(buffLen); +} + +static int IncomingConnect(LoopHandle loop, TaskHandle server) +{ + UNUSED(loop); + UNUSED(server); + return 0; +} + +static void ProcessWatchEventTest(WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) +{ + UNUSED(taskHandle); + UNUSED(fd); + UNUSED(events); + UNUSED(context); +} + +namespace init_ut { +class LoopEventUnittest : public testing::Test { +public: + LoopEventUnittest() {}; + virtual ~LoopEventUnittest() {}; + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; + void TestBody(void) {}; + int CreateServerTask() + { + CheckTaskFlags(nullptr, EVENT_WRITE); + ParamStreamInfo info = {}; + info.server = const_cast(PIPE_NAME); + info.close = nullptr; + info.recvMessage = nullptr; + info.incomingConnect = OnIncomingConnect; + return ParamServerCreate(&serverTask_, &info); + } + + void StreamTaskTest () + { + LE_StreamInfo streamInfo = {}; + streamInfo.recvMessage = OnReceiveRequest; + streamInfo.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT | TASK_TEST; + streamInfo.server = (char *)"/data/testpipea"; + TaskHandle clientTaskHandle = nullptr; + LE_AcceptStreamClient(LE_GetDefaultLoop(), (TaskHandle)serverTask_, &clientTaskHandle, &streamInfo); + if (clientTaskHandle == nullptr) { + return; + } + ((StreamConnectTask *)clientTaskHandle)->stream.base.handleEvent(LE_GetDefaultLoop(), + (TaskHandle)clientTaskHandle, 0); + ((StreamConnectTask *)clientTaskHandle)->stream.base.handleEvent(LE_GetDefaultLoop(), + (TaskHandle)clientTaskHandle, EVENT_READ); + + TaskHandle clientTaskHandlec = nullptr; + streamInfo.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_SERVER; + streamInfo.server = (char *)"0.0.0.0:10110"; + LE_CreateStreamClient(LE_GetDefaultLoop(), &clientTaskHandlec, &streamInfo); + if (clientTaskHandlec == nullptr) { + return; + } + TaskHandle clientTaskHandled = nullptr; + streamInfo.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_CONNECT; + streamInfo.server = (char *)"127.0.0.1:10111"; + LE_CreateStreamClient(LE_GetDefaultLoop(), &clientTaskHandled, &streamInfo); + if (clientTaskHandled == nullptr) { + return; + } + } + void LeTaskTest() + { + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER | TASK_TEST; + info.server = (char *)"/data/testpipe"; + info.baseInfo.close = nullptr; + info.incommingConnect = IncomingConnect; + LE_CreateStreamServer(LE_GetDefaultLoop(), &serverTask_, &info); + if (serverTask_ == nullptr) { + return; + } + ((StreamServerTask *)serverTask_)->base.handleEvent(LE_GetDefaultLoop(), serverTask_, EVENT_READ); + + uint64_t eventId = 0; + ParamStreamInfo paramStreamInfo = {}; + paramStreamInfo.flags = PARAM_TEST_FLAGS; + paramStreamInfo.server = nullptr; + paramStreamInfo.close = nullptr; + paramStreamInfo.recvMessage = ProcessMessage; + paramStreamInfo.incomingConnect = nullptr; + ParamTaskPtr client = nullptr; + int ret = ParamStreamCreate(&client, serverTask_, ¶mStreamInfo, sizeof(ParamWatcher)); + PARAM_CHECK(ret == 0, return, "Failed to create client"); + + BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), 1 + sizeof(eventId)); + LE_Buffer *buffer = (LE_Buffer *)handle; + AddBuffer((StreamTask *)client, buffer); + ((StreamConnectTask *)client)->stream.base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)(client), EVENT_WRITE); + EXPECT_NE(LE_GetSendResult(handle), 0); + + ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, "name", sizeof(ParamMessage)); + ((StreamConnectTask *)client)->recvMessage(LE_GetDefaultLoop(), reinterpret_cast(request), + sizeof(ParamMessage)); + + LE_Buffer *next = nullptr; + EXPECT_EQ(GetNextBuffer((StreamTask *)client, next), nullptr); + ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(client); + PARAM_CHECK(watcher != nullptr, return, "Failed to get watcher"); + OH_ListInit(&watcher->triggerHead); + LE_FreeBuffer(LE_GetDefaultLoop(), (TaskHandle)client, nullptr); + return; + } + void ProcessEventTest() + { + ProcessEvent((EventLoop *)LE_GetDefaultLoop(), 1, EVENT_READ); + LE_BaseInfo info = {TASK_EVENT, nullptr}; + int testfd = 65535; // 65535 is not exist fd + BaseTask *task = CreateTask(LE_GetDefaultLoop(), testfd, &info, sizeof(StreamClientTask)); + if (task != nullptr) { + task->handleEvent = TestHandleTaskEvent; + ProcessEvent((EventLoop *)LE_GetDefaultLoop(), testfd, EVENT_READ); + } + } + void ProcessasynEvent() + { + TaskHandle asynHandle = nullptr; + LE_CreateAsyncTask(LE_GetDefaultLoop(), &asynHandle, ProcessAsyncEvent); + if (asynHandle == nullptr) { + return; + } + ((AsyncEventTask *)asynHandle)->stream.base.handleEvent(LE_GetDefaultLoop(), asynHandle, EVENT_READ); + ((AsyncEventTask *)asynHandle)->stream.base.handleEvent(LE_GetDefaultLoop(), asynHandle, EVENT_WRITE); + LE_StopAsyncTask(LE_GetDefaultLoop(), asynHandle); + } + void ProcessWatcherTask() + { + WatcherHandle handle = nullptr; + LE_WatchInfo info = {}; + info.fd = -1; + info.flags = WATCHER_ONCE; + info.events = EVENT_READ; + info.processEvent = ProcessWatchEventTest; + LE_StartWatcher(LE_GetDefaultLoop(), &handle, &info, nullptr); + if (handle == nullptr) { + return; + } + ((WatcherTask *)handle)->base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)handle, EVENT_READ); + ((WatcherTask *)handle)->base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)handle, 0); + ((WatcherTask *)handle)->base.flags = WATCHER_ONCE; + ((WatcherTask *)handle)->base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)handle, EVENT_READ); + LE_RemoveWatcher(LE_GetDefaultLoop(), handle); + } + void CreateSocketTest() + { + ParamTaskPtr serverTask = nullptr; + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_PIPE | TASK_CONNECT | TASK_TEST; + info.server = (char *)"/data/testpipe"; + info.baseInfo.close = nullptr; + info.incommingConnect = IncomingConnect; + info.socketId = 1111; // 1111 is test fd + LE_CreateStreamServer(LE_GetDefaultLoop(), &serverTask, &info); + EXPECT_NE(serverTask, nullptr); + if (serverTask == nullptr) { + return; + } + ((StreamServerTask *)serverTask)->base.taskId.fd = -1; + OnIncomingConnect(LE_GetDefaultLoop(), serverTask); + LE_GetSocketFd(serverTask); + AcceptSocket(-1, TASK_PIPE); + AcceptSocket(-1, TASK_TCP); + AcceptSocket(-1, TASK_TEST); + } + +private: + ParamTaskPtr serverTask_ = nullptr; +}; + +HWTEST_F(LoopEventUnittest, Init_LeTaskTest_001, TestSize.Level1) +{ + LoopEventUnittest loopevtest = LoopEventUnittest(); + loopevtest.LeTaskTest(); +} +HWTEST_F(LoopEventUnittest, Init_TestRunServer_001, TestSize.Level1) +{ + LoopEventUnittest loopevtest = LoopEventUnittest(); + loopevtest.ProcessEventTest(); +} +HWTEST_F(LoopEventUnittest, Init_TestProcessasynEvent_001, TestSize.Level1) +{ + LoopEventUnittest loopevtest = LoopEventUnittest(); + loopevtest.ProcessasynEvent(); +} +HWTEST_F(LoopEventUnittest, Init_TestCreateSocketTest_001, TestSize.Level1) +{ + LoopEventUnittest loopevtest = LoopEventUnittest(); + loopevtest.CreateSocketTest(); +} +HWTEST_F(LoopEventUnittest, Init_TestProcessWatcherTask_001, TestSize.Level1) +{ + LoopEventUnittest loopevtest = LoopEventUnittest(); + loopevtest.ProcessWatcherTask(); +} + +static LoopHandle g_loop = nullptr; +static int g_timeCount = 0; +static void Test_ProcessTimer(const TimerHandle taskHandle, void *context) +{ + g_timeCount++; + printf("Test_ProcessTimer %d\n", g_timeCount); + if (g_timeCount > 1) { + LE_StopLoop(g_loop); + } +} + +HWTEST_F(LoopEventUnittest, Init_TestLoopAbnormal_001, TestSize.Level1) +{ + LE_StartWatcher(nullptr, nullptr, nullptr, nullptr); + LE_WatchInfo info = {}; + info.fd = -1; + info.flags = WATCHER_ONCE; + info.events = EVENT_READ; + info.processEvent = nullptr; + LE_StartWatcher(LE_GetDefaultLoop(), nullptr, &info, nullptr); + LE_StartWatcher(LE_GetDefaultLoop(), nullptr, nullptr, nullptr); +} + +HWTEST_F(LoopEventUnittest, Init_TestLoopIdle_001, TestSize.Level1) +{ + int ret = LE_DelayProc(LE_GetDefaultLoop(), nullptr, nullptr); + ASSERT_NE(ret, 0); + LE_DelIdle(nullptr); +} + +HWTEST_F(LoopEventUnittest, Init_TestLEFreeBuffer_001, TestSize.Level1) +{ + uint64_t eventId = 0; + BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), 1 + sizeof(eventId)); + ASSERT_NE(handle, nullptr); + LE_FreeBuffer(LE_GetDefaultLoop(), nullptr, handle); +} +} // namespace init_ut diff --git a/test/unittest/loopevent/loopserver_unittest.cpp b/test/unittest/loopevent/loopserver_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4335eb31b0055f489831b24aa4429f845b118cc --- /dev/null +++ b/test/unittest/loopevent/loopserver_unittest.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2021 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 "begetctl.h" +#include "cJSON.h" +#include "init.h" +#include "init_hashmap.h" +#include "init_param.h" +#include "init_utils.h" +#include "le_epoll.h" +#include "le_loop.h" +#include "le_socket.h" +#include "le_task.h" +#include "loop_event.h" +#include "param_manager.h" +#include "param_message.h" +#include "param_utils.h" +#include "trigger_manager.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +const std::string TCP_SERVER = "127.0.0.1:7777"; +const std::string PIPE_SERVER = STARTUP_INIT_UT_PATH "/dev/unix/socket/testsocket"; +const std::string WATCHER_FILE = STARTUP_INIT_UT_PATH "/test_watcher_file"; +const std::string FORMAT_STR = "{ \"cmd\":%d, \"message\":\"%s\" }"; + +static LoopHandle g_loopClient_ = nullptr; +static LoopHandle g_loopServer_ = nullptr; +static int g_maxCount = 0; +static int g_timeCount = 0; +static int g_cmd = 2; +static void DecodeMessage(const char *buffer, size_t nread, uint32_t &cmd) +{ + cJSON *root = cJSON_ParseWithLength(buffer, nread); + if (root == nullptr) { + EXPECT_NE(root, nullptr); + printf("Invalid message %s \n", buffer); + return; + } + printf("Message: %s \n", cJSON_GetStringValue(cJSON_GetObjectItem(root, "message"))); + cmd = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "cmd")); + printf("cmd: %d \n", cmd); + cJSON_Delete(root); + return; +} + +static void SendMessage(const LoopHandle loopHandle, const TaskHandle taskHandle, const char *message, ...) +{ + uint32_t bufferSize = 1024; // 1024 buffer size + BufferHandle handle = LE_CreateBuffer(loopHandle, bufferSize); + char *buffer = (char *)LE_GetBufferInfo(handle, nullptr, &bufferSize); + + va_list vargs; + va_start(vargs, message); + if (vsnprintf_s(buffer, bufferSize, bufferSize - 1, message, vargs) == -1) { + LE_FreeBuffer(loopHandle, taskHandle, handle); + va_end(vargs); + EXPECT_EQ(1, 0); + return; + } + va_end(vargs); + int ret = LE_Send(loopHandle, taskHandle, handle, bufferSize); + EXPECT_EQ(ret, 0); +} + +static void TestOnClose(const TaskHandle taskHandle) +{ +} + +static LE_STATUS TestHandleTaskEvent(const LoopHandle loop, const TaskHandle task, uint32_t oper) +{ + return LE_SUCCESS; +} + +static void TestOnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread) +{ + EXPECT_NE(buffer, nullptr); + if (buffer == nullptr) { + return; + } + printf("Server receive message %s \n", reinterpret_cast(buffer)); + uint32_t cmd = 0; + DecodeMessage(reinterpret_cast(buffer), nread, cmd); + SendMessage(g_loopServer_, task, reinterpret_cast(buffer)); +} + +static void TestClientOnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread) +{ + printf("Client receive message %s \n", reinterpret_cast(buffer)); + EXPECT_NE(buffer, nullptr); + if (buffer == nullptr) { + return; + } + uint32_t cmd = 0; + DecodeMessage(reinterpret_cast(buffer), nread, cmd); + if (cmd == 5 || cmd == 2) { // 2 5 close server + LE_StopLoop(g_loopClient_); + } +} + +static void ProcessAsyncEvent(const TaskHandle taskHandle, uint64_t eventId, const uint8_t *buffer, uint32_t buffLen) +{ + UNUSED(taskHandle); + UNUSED(eventId); + UNUSED(buffer); + UNUSED(buffLen); +} + +static void TestSendMessageComplete(const TaskHandle taskHandle, BufferHandle handle) +{ + printf("SendMessage result %d \n", LE_GetSendResult(handle)); + uint32_t bufferSize = 1024; // 1024 buffer size + char *buffer = (char *)LE_GetBufferInfo(handle, nullptr, &bufferSize); + uint32_t cmd = 0; + DecodeMessage(reinterpret_cast(buffer), bufferSize, cmd); + if (cmd == 5) { // 5 close server + LE_StopLoop(g_loopServer_); + } +} + +static int TestTcpIncomingConnect(LoopHandle loop, TaskHandle server) +{ + PARAM_CHECK(server != nullptr, return -1, "Error server"); + printf("Tcp connect incoming \n"); + TaskHandle stream; + LE_StreamInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_CONNECT; + info.baseInfo.close = TestOnClose; + info.baseInfo.userDataSize = 0; + info.disConnectComplete = nullptr; + info.sendMessageComplete = TestSendMessageComplete; + info.recvMessage = TestOnReceiveRequest; + LE_STATUS ret = LE_AcceptStreamClient(loop, server, &stream, &info); + EXPECT_EQ(ret, 0); + return 0; +} + +static int TestPipIncomingConnect(LoopHandle loop, TaskHandle server) +{ + PARAM_CHECK(server != nullptr, return -1, "Error server"); + printf("Pipe connect incoming \n"); + TaskHandle stream; + LE_StreamInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; + info.baseInfo.close = TestOnClose; + info.baseInfo.userDataSize = 0; + info.disConnectComplete = nullptr; + info.sendMessageComplete = TestSendMessageComplete; + info.recvMessage = TestOnReceiveRequest; + LE_STATUS ret = LE_AcceptStreamClient(loop, server, &stream, &info); + EXPECT_EQ(ret, 0); + return 0; +} + +static void TestConnectComplete(const TaskHandle client) +{ + printf("Connect complete \n"); +} + +static void TestDisConnectComplete(const TaskHandle client) +{ + printf("DisConnect complete \n"); + LE_StopLoop(g_loopClient_); +} + +static void TestProcessTimer(const TimerHandle taskHandle, void *context) +{ + g_timeCount++; + printf("ProcessTimer %d\n", g_timeCount); + if (g_maxCount == 2) { // 2 stop + if (g_timeCount >= g_maxCount) { + LE_StopLoop(g_loopClient_); + } + } + if (g_maxCount == 3) { // 3 stop timer + if (g_timeCount >= g_maxCount) { + LE_StopTimer(g_loopClient_, taskHandle); + LE_StopLoop(g_loopClient_); + } + } + if (g_maxCount == 10) { // 10 write watcher file + FILE *tmpFile = fopen(WATCHER_FILE.c_str(), "wr"); + if (tmpFile != nullptr) { + fprintf(tmpFile, "%s", "test watcher file 22222222222"); + (void)fflush(tmpFile); + fclose(tmpFile); + } + LE_StopTimer(g_loopClient_, taskHandle); + LE_StopLoop(g_loopClient_); + } +} + +static void ProcessWatchEventTest(WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) +{ + UNUSED(taskHandle); + UNUSED(fd); + UNUSED(events); + UNUSED(context); + printf("Process watcher event \n"); + LE_StopLoop(g_loopClient_); +} + +class LoopServerUnitTest : public testing::Test { +public: + LoopServerUnitTest() {}; + virtual ~LoopServerUnitTest() {}; + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; + void TestBody(void) {}; + + // for thread to create tcp\pipe server + void RunServer(void) + { + TaskHandle tcpServer = nullptr; + TaskHandle pipeServer = nullptr; + LE_STATUS ret = LE_CreateLoop(&g_loopServer_); + EXPECT_EQ(ret, 0); + // create server for tcp + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_SERVER; + info.socketId = -1; + info.server = const_cast(TCP_SERVER.c_str()); + info.baseInfo.close = TestOnClose; + info.incommingConnect = TestTcpIncomingConnect; + ret = LE_CreateStreamServer(g_loopServer_, &tcpServer, &info); + EXPECT_EQ(ret, 0); + + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER; + info.socketId = -1; + info.server = const_cast(PIPE_SERVER.c_str()); + info.baseInfo.close = TestOnClose; + info.incommingConnect = TestPipIncomingConnect; + ret = LE_CreateStreamServer(g_loopServer_, &pipeServer, &info); + EXPECT_EQ(ret, 0); + + printf("Run server pipeServer_ \n"); + // run loop for server + LE_RunLoop(g_loopServer_); + + printf("Run server pipeServer_ \n"); + LE_CloseStreamTask(g_loopServer_, pipeServer); + pipeServer = nullptr; + LE_CloseStreamTask(g_loopServer_, tcpServer); + tcpServer = nullptr; + LE_CloseLoop(g_loopServer_); + g_loopServer_ = nullptr; + } + + void StartServer() + { + std::thread(&LoopServerUnitTest::RunServer, this).detach(); + sleep(1); + } + + TaskHandle CreateConnect(const char *tcpServer, uint32_t flags) + { + if (g_loopClient_ == nullptr) { + LE_STATUS ret = LE_CreateLoop(&g_loopClient_); + EXPECT_EQ(ret, 0); + } + + TaskHandle task = nullptr; + LE_StreamInfo info = {}; + info.baseInfo.flags = TASK_STREAM | flags | TASK_CONNECT; + info.server = const_cast(tcpServer); + info.baseInfo.userDataSize = 0; + info.baseInfo.close = TestOnClose; + info.disConnectComplete = TestDisConnectComplete; + info.connectComplete = TestConnectComplete; + info.sendMessageComplete = nullptr; + info.recvMessage = TestClientOnReceiveRequest; + LE_STATUS status = LE_CreateStreamClient(g_loopClient_, &task, &info); + EXPECT_EQ(status, 0); + return task; + } + + WatcherHandle CreateWatcherTask(int fd, const char *fileName) + { + if (g_loopClient_ == nullptr) { + LE_STATUS ret = LE_CreateLoop(&g_loopClient_); + EXPECT_EQ(ret, 0); + } + WatcherHandle handle = nullptr; + LE_WatchInfo info = {}; + info.fd = fd; + info.flags = WATCHER_ONCE; + info.events = EVENT_READ | EVENT_WRITE; + info.processEvent = ProcessWatchEventTest; + LE_STATUS status = LE_StartWatcher(g_loopClient_, &handle, &info, nullptr); + EXPECT_EQ(status, 0); + return handle; + } + + TimerHandle CreateTimerTask(int repeat) + { + if (g_loopClient_ == nullptr) { + LE_STATUS ret = LE_CreateLoop(&g_loopClient_); + EXPECT_EQ(ret, 0); + } + TimerHandle timer = nullptr; + int ret = LE_CreateTimer(g_loopClient_, &timer, TestProcessTimer, nullptr); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loopClient_, timer, 500, repeat); // 500 ms + EXPECT_EQ(ret, 0); + return timer; + } +private: + std::thread *serverThread_ = nullptr; +}; + +HWTEST_F(LoopServerUnitTest, Init_TestRunServer_001, TestSize.Level1) +{ + LoopServerUnitTest test; + test.StartServer(); +} + +HWTEST_F(LoopServerUnitTest, Init_TestPipConnect_001, TestSize.Level1) +{ + g_cmd = 2; // 2 only close client + LoopServerUnitTest test; + TaskHandle pipe = test.CreateConnect(PIPE_SERVER.c_str(), TASK_PIPE); + EXPECT_NE(pipe, nullptr); + SendMessage(g_loopClient_, pipe, FORMAT_STR.c_str(), g_cmd, "connect success"); + LE_RunLoop(g_loopClient_); + LE_CloseStreamTask(g_loopClient_, pipe); + LE_CloseLoop(g_loopClient_); + g_loopClient_ = nullptr; +} + +HWTEST_F(LoopServerUnitTest, Init_TestTcpConnect_001, TestSize.Level1) +{ + g_cmd = 2; // 2 only close client + LoopServerUnitTest test; + TaskHandle tcp = test.CreateConnect(TCP_SERVER.c_str(), TASK_TCP); + EXPECT_NE(tcp, nullptr); + SendMessage(g_loopClient_, tcp, FORMAT_STR.c_str(), g_cmd, "connect success"); + LE_RunLoop(g_loopClient_); + LE_CloseStreamTask(g_loopClient_, tcp); + LE_CloseLoop(g_loopClient_); + g_loopClient_ = nullptr; +} + +HWTEST_F(LoopServerUnitTest, Init_TestTimer_001, TestSize.Level1) +{ + LoopServerUnitTest test; + g_maxCount = 2; // 2 stop + TimerHandle timer = test.CreateTimerTask(2); + EXPECT_NE(timer, nullptr); + LE_RunLoop(g_loopClient_); + LE_CloseLoop(g_loopClient_); + g_loopClient_ = nullptr; +} + +HWTEST_F(LoopServerUnitTest, Init_TestTimer_002, TestSize.Level1) +{ + LoopServerUnitTest test; + g_maxCount = 3; // 3 stop timer + TimerHandle timer = test.CreateTimerTask(3); + EXPECT_NE(timer, nullptr); + LE_RunLoop(g_loopClient_); + LE_CloseLoop(g_loopClient_); + g_loopClient_ = nullptr; +} + +HWTEST_F(LoopServerUnitTest, Init_TestWatcher_001, TestSize.Level1) +{ + int fd = open(WATCHER_FILE.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd >= 0) { + write(fd, WATCHER_FILE.c_str(), WATCHER_FILE.size()); + } + EXPECT_GE(fd, 0); + printf("Watcher fd %d \n", fd); + LoopServerUnitTest test; + WatcherHandle watcher = test.CreateWatcherTask(3, WATCHER_FILE.c_str()); + EXPECT_NE(watcher, nullptr); + g_maxCount = 10; // 10 write watcher file + TimerHandle timer = test.CreateTimerTask(1); + EXPECT_NE(timer, nullptr); + + LE_RunLoop(g_loopClient_); + LE_RemoveWatcher(g_loopClient_, watcher); + close(fd); + LE_CloseLoop(g_loopClient_); + g_loopClient_ = nullptr; +} + +HWTEST_F(LoopServerUnitTest, Init_TestStopServer_001, TestSize.Level1) +{ + g_cmd = 5; // 5 close server + LoopServerUnitTest test; + TaskHandle pip = test.CreateConnect(PIPE_SERVER.c_str(), TASK_PIPE); + EXPECT_NE(pip, nullptr); + SendMessage(g_loopClient_, pip, FORMAT_STR.c_str(), g_cmd, "connect success"); + LE_RunLoop(g_loopClient_); + LE_CloseStreamTask(g_loopClient_, pip); + LE_CloseLoop(g_loopClient_); + g_loopClient_ = nullptr; +} + +HWTEST_F(LoopServerUnitTest, Init_TestServerTimeout_001, TestSize.Level1) +{ + int flag = TASK_STREAM | TASK_PIPE | TASK_SERVER | TASK_TEST; + int serverSock = CreateSocket(flag, "/data/test1pipe"); + EXPECT_NE(serverSock, -1); + int ret = AcceptSocket(serverSock, flag); + EXPECT_EQ(ret, -1); +} +} // namespace init_ut diff --git a/test/unittest/loopevent/loopsignal_unittest.cpp b/test/unittest/loopevent/loopsignal_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b28822e8ee0c13d3be87dca48c350f7c1576ac84 --- /dev/null +++ b/test/unittest/loopevent/loopsignal_unittest.cpp @@ -0,0 +1,66 @@ +/* + * 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 "init_unittest.h" +#include "init.h" +#include "loop_event.h" +#include "le_epoll.h" +#include "le_signal.h" +#include "init_hashmap.h" + +using namespace testing::ext; +using namespace std; + +static SignalHandle g_sigHandler = nullptr; + +static void TestProcessSignal(const struct signalfd_siginfo *siginfo) +{ + return; +} + +namespace init_ut { +class LoopSignalUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(LoopSignalUnitTest, Init_TestSignalInitTestRmSig_001, TestSize.Level1) +{ + static LoopHandle loopClient = nullptr; + LE_STATUS status = LE_CreateLoop(&loopClient); + EXPECT_EQ(status, 0); + LE_CreateSignalTask(loopClient, &g_sigHandler, TestProcessSignal); + ASSERT_NE(g_sigHandler, nullptr); + int ret = LE_AddSignal(loopClient, g_sigHandler, SIGUSR1); + ASSERT_EQ(ret, 0); + LE_AddSignal(loopClient, g_sigHandler, SIGUSR1); + LE_AddSignal(loopClient, g_sigHandler, SIGUSR2); + ret = LE_RemoveSignal(loopClient, g_sigHandler, SIGUSR1); + ASSERT_EQ(ret, 0); + LE_RemoveSignal(loopClient, g_sigHandler, SIGUSR1); + LE_RemoveSignal(loopClient, g_sigHandler, SIGUSR2); + ((BaseTask *)g_sigHandler)->handleEvent(loopClient, (TaskHandle)&g_sigHandler, EVENT_WRITE); + LE_CloseSignalTask(loopClient, g_sigHandler); + ASSERT_EQ(ret, 0); + LE_StopLoop(loopClient); + LE_CloseLoop(loopClient); + loopClient = nullptr; +} +} diff --git a/test/unittest/loopevent/looptimer_unittest.cpp b/test/unittest/loopevent/looptimer_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54d3c371af60c78d64f0548a9f3a06aa0cbef340 --- /dev/null +++ b/test/unittest/loopevent/looptimer_unittest.cpp @@ -0,0 +1,178 @@ +/* + * 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 +#include +#include +#include +#include +#include "le_loop.h" +#include "loop_event.h" +#include "le_timer.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class LoopTimerUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +static LoopHandle g_loop = NULL; +int32_t g_maxCount = 0; +static void Test_ProcessTimer(const TimerHandle taskHandle, void *context) +{ + g_maxCount--; + if (g_maxCount <= 0) { + LE_StopLoop(g_loop); + } + printf("WaitTimeout count %d\n", g_maxCount); +} + +static void TimeoutCancel(const TimerHandle taskHandle, void *context) +{ + printf("TimeoutCancel count %d", g_maxCount); + LE_StopTimer(LE_GetDefaultLoop(), taskHandle); +} + +HWTEST_F(LoopTimerUnitTest, Init_Timer_001, TestSize.Level0) +{ + EXPECT_EQ(LE_CreateLoop(&g_loop), 0); + + TimerHandle timer = NULL; + int ret = LE_CreateTimer(NULL, &timer, Test_ProcessTimer, NULL); + EXPECT_NE(ret, 0); + + ret = LE_CreateTimer(g_loop, NULL, Test_ProcessTimer, NULL); + EXPECT_NE(ret, 0); + + ret = LE_CreateTimer(g_loop, &timer, NULL, NULL); + EXPECT_NE(ret, 0); + + CancelTimer(timer); + + uint64_t time = GetCurrentTimespec(0); + EXPECT_GT(time, 0); + + time = GetMinTimeoutPeriod(NULL); + EXPECT_EQ(time, 0); + + EventLoop *loop = reinterpret_cast(g_loop); + DestroyTimerList(loop); + printf("Init_Timer_001 %d end", g_maxCount); +} + +HWTEST_F(LoopTimerUnitTest, Init_Timer_002, TestSize.Level0) +{ + EXPECT_EQ(LE_CreateLoop(&g_loop), 0); + EventLoop *loop = reinterpret_cast(g_loop); + + TimerHandle timer = NULL; + g_maxCount = 1; + int ret = LE_CreateTimer(g_loop, &timer, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer, 200, 1); + EXPECT_EQ(ret, 0); + usleep(200000); + CheckTimeoutOfTimer(loop, GetCurrentTimespec(0)); + EXPECT_EQ(g_maxCount, 0); + LE_CloseLoop(g_loop); + + printf("Init_Timer_002 %d end", g_maxCount); +} + +HWTEST_F(LoopTimerUnitTest, Init_Timer_003, TestSize.Level0) +{ + EXPECT_EQ(LE_CreateLoop(&g_loop), 0); + + TimerHandle timer = NULL; + int ret = LE_CreateTimer(g_loop, &timer, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer, 200, 2); + EXPECT_EQ(ret, 0); + g_maxCount = 2; + LE_RunLoop(g_loop); + EXPECT_EQ(g_maxCount, 0); + LE_CloseLoop(g_loop); + + printf("Init_Timer_003 %d end", g_maxCount); +} + +HWTEST_F(LoopTimerUnitTest, Init_Timer_004, TestSize.Level0) +{ + EXPECT_EQ(LE_CreateLoop(&g_loop), 0); + + g_maxCount = 3; + TimerHandle timer = NULL; + int ret = LE_CreateTimer(g_loop, &timer, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer, 100, 1); + EXPECT_EQ(ret, 0); + + TimerHandle timer1 = NULL; + ret = LE_CreateTimer(g_loop, &timer1, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer1, 150, 1); + EXPECT_EQ(ret, 0); + + TimerHandle timer2 = NULL; + ret = LE_CreateTimer(g_loop, &timer2, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer2, 300, 1); + EXPECT_EQ(ret, 0); + + usleep(150); + LE_RunLoop(g_loop); + EXPECT_EQ(g_maxCount, 0); + LE_CloseLoop(g_loop); + + printf("Init_Timer_004 %d end", g_maxCount); +} + +HWTEST_F(LoopTimerUnitTest, Init_Timer_005, TestSize.Level0) +{ + EXPECT_EQ(LE_CreateLoop(&g_loop), 0); + + g_maxCount = 3; + TimerHandle timer = NULL; + int ret = LE_CreateTimer(g_loop, &timer, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer, 100, 2); + EXPECT_EQ(ret, 0); + + TimerHandle timer1 = NULL; + ret = LE_CreateTimer(g_loop, &timer1, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer1, 150, 2); + EXPECT_EQ(ret, 0); + + TimerHandle timer2 = NULL; + ret = LE_CreateTimer(g_loop, &timer2, Test_ProcessTimer, NULL); + EXPECT_EQ(ret, 0); + ret = LE_StartTimer(g_loop, timer2, 300, 1); + EXPECT_EQ(ret, 0); + + CancelTimer(timer); + LE_RunLoop(g_loop); + EXPECT_EQ(g_maxCount, 0); + LE_CloseLoop(g_loop); + + printf("Init_Timer_005 %d end", g_maxCount); +} +} \ No newline at end of file diff --git a/test/unittest/modules/context_unittest.cpp b/test/unittest/modules/context_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0286ee9c0c9f48b3963031c11d58a8cb41d9bf6d --- /dev/null +++ b/test/unittest/modules/context_unittest.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2023 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 "init_context.h" + +#include "param_stub.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +extern "C" { +struct ForkArgs { + int (*childFunc)(const SubInitForkArg *arg); + SubInitForkArg args; +}; +static pid_t g_pid = 1000; +static pthread_t g_thread = 0; + +static void *ThreadFunc(void *arg) +{ + printf("Create thread %d \n", gettid()); + struct ForkArgs *forkArg = static_cast(arg); + forkArg->childFunc(&forkArg->args); + printf("Exit thread %d %d \n", forkArg->args.type, gettid()); + free(forkArg); + g_thread = 0; + return nullptr; +} + +pid_t SubInitFork(int (*childFunc)(const SubInitForkArg *arg), const SubInitForkArg *args) +{ + if (g_pid >= 0) { + struct ForkArgs *forkArg = static_cast(malloc(sizeof(struct ForkArgs))); + if (forkArg == nullptr) { + return -1; + } + forkArg->childFunc = childFunc; + forkArg->args.socket[0] = args->socket[0]; + forkArg->args.socket[1] = args->socket[1]; + forkArg->args.type = args->type; + int ret = pthread_create(&g_thread, nullptr, ThreadFunc, forkArg); + if (ret != 0) { + printf("Failed to create thread %d \n", errno); + free(forkArg); + return -1; + } + usleep(100); // 100 wait + } + g_pid++; + return g_pid; +} +} + +namespace init_ut { +class InitContextUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(InitContextUnitTest, InitSubContextTest_01, TestSize.Level1) +{ + g_pid = -3; // -3 test data + int ret = StartSubInit(INIT_CONTEXT_CHIPSET); + EXPECT_NE(ret, 0); + ret = StartSubInit(INIT_CONTEXT_MAIN); + EXPECT_NE(ret, 0); + g_pid = 100; // 100 test data +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_02, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_CHIPSET }; + int ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_EQ(ret, 0); + ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext1"); + EXPECT_EQ(ret, 0); + ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext2"); + EXPECT_EQ(ret, 0); + ret = ExecuteCmdInSubInit(&context, "mkdir", nullptr); + EXPECT_EQ(ret, 0); + context.type = INIT_CONTEXT_MAIN; + ret = ExecuteCmdInSubInit(&context, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_NE(ret, 0); + + // fail + ret = ExecuteCmdInSubInit(nullptr, "mkdir", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_EQ(ret, -1); + ret = ExecuteCmdInSubInit(&context, nullptr, STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_EQ(ret, -1); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_03, TestSize.Level1) +{ + int ret = StartSubInit(INIT_CONTEXT_CHIPSET); + EXPECT_EQ(ret, 0); + if (g_thread != 0) { + pthread_join(g_thread, nullptr); + g_thread = 0; + } + SubInitInfo *subInfo = GetSubInitInfo(INIT_CONTEXT_CHIPSET); + if (subInfo == nullptr) { + EXPECT_EQ(1, 0); + } else { + EXPECT_EQ(2, subInfo->state); + StopSubInit(subInfo->subPid); + } + subInfo = GetSubInitInfo(INIT_CONTEXT_MAIN); + if (subInfo != nullptr) { + EXPECT_EQ(1, 0); + } +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_04, TestSize.Level1) +{ + int ret = StartSubInit(INIT_CONTEXT_CHIPSET); + EXPECT_EQ(ret, 0); + if (g_thread != 0) { + pthread_join(g_thread, nullptr); + g_thread = 0; + } + SubInitInfo *subInfo = GetSubInitInfo(INIT_CONTEXT_CHIPSET); + if (subInfo != nullptr) { + EXPECT_EQ(2, subInfo->state); + StopSubInit(subInfo->subPid); + } else { + EXPECT_EQ(1, 0); + } + // close + subInfo = GetSubInitInfo(INIT_CONTEXT_CHIPSET); + if (subInfo != nullptr) { + EXPECT_EQ(0, subInfo->state); + } + + SubInitContext *subContext = GetSubInitContext(INIT_CONTEXT_CHIPSET); + if (subContext == nullptr) { + EXPECT_EQ(0, -1); + return; + } + ret = subContext->executeCmdInSubInit(INIT_CONTEXT_CHIPSET, "mkdir-2", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_NE(ret, 0); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_05, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_CHIPSET }; + int ret = ExecuteCmdInSubInit(&context, "mkdir-2", STARTUP_INIT_UT_PATH"/testsubcontext"); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_06, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_CHIPSET }; + int index = 0; + const char *cmd = GetMatchCmd("mkdir ", &index); + if (cmd == nullptr || strstr(cmd, "mkdir ") == nullptr) { + EXPECT_EQ(1, 0); + return; + } + DoCmdByIndex(index, STARTUP_INIT_UT_PATH"/testsubcontext", &context); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_07, TestSize.Level1) +{ + ConfigContext context = { INIT_CONTEXT_MAIN }; + int index = 0; + const char *cmd = GetMatchCmd("mkdir ", &index); + if (cmd == nullptr || strstr(cmd, "mkdir ") == nullptr) { + EXPECT_EQ(1, 0); + return; + } + DoCmdByIndex(index, STARTUP_INIT_UT_PATH"/testsubcontext", &context); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_09, TestSize.Level1) +{ + int ret = SetSubInitContext(nullptr, "serviceName"); + EXPECT_EQ(ret, -1); + ConfigContext context = { INIT_CONTEXT_MAIN }; + ret = SetSubInitContext(&context, "serviceName"); + EXPECT_EQ(ret, 0); + context = { INIT_CONTEXT_CHIPSET }; + ret = SetSubInitContext(&context, "serviceName"); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(InitContextUnitTest, InitSubContextTest_10, TestSize.Level1) +{ + int ret = InitSubInitContext(INIT_CONTEXT_MAIN, nullptr); + EXPECT_EQ(ret, -1); + ret = InitSubInitContext(INIT_CONTEXT_CHIPSET, nullptr); + EXPECT_EQ(ret, -1); + + SubInitContext *subContext = GetSubInitContext(INIT_CONTEXT_CHIPSET); + if (subContext == nullptr) { + EXPECT_EQ(0, -1); + return; + } + ret = subContext->startSubInit(INIT_CONTEXT_MAIN); + EXPECT_NE(ret, 0); + ret = subContext->executeCmdInSubInit(INIT_CONTEXT_CHIPSET, nullptr, nullptr); + EXPECT_NE(ret, 0); + ret = subContext->executeCmdInSubInit(INIT_CONTEXT_MAIN, nullptr, nullptr); + EXPECT_NE(ret, 0); +} +} // namespace init_ut diff --git a/test/unittest/modules/eng_unittest.cpp b/test/unittest/modules/eng_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1846e048c7d528ac5f7b64a7d438d968baf433b0 --- /dev/null +++ b/test/unittest/modules/eng_unittest.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2023 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 "init_eng.h" +#include "init_utils.h" +#include "param_stub.h" +#include "bootstage.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +static const std::string SRC_FILE_PATH = STARTUP_INIT_UT_PATH"/eng/source/test.txt"; +static const std::string TARGET_PATH = STARTUP_INIT_UT_PATH"/eng/link_name"; +static const std::string ENG_ROOT_PATH = STARTUP_INIT_UT_PATH"/eng/"; + +static bool RemoveDir(const std::string &path) +{ + if (path.empty()) { + return false; + } + std::string strPath = path; + if (strPath.at(strPath.length() - 1) != '/') { + strPath.append("/"); + } + DIR *d = opendir(strPath.c_str()); + if (d != nullptr) { + struct dirent *dt = nullptr; + dt = readdir(d); + while (dt != nullptr) { + if (strcmp(dt->d_name, "..") == 0 || strcmp(dt->d_name, ".") == 0) { + dt = readdir(d); + continue; + } + struct stat st {}; + auto file_name = strPath + std::string(dt->d_name); + stat(file_name.c_str(), &st); + if (S_ISDIR(st.st_mode)) { + RemoveDir(file_name); + } else { + remove(file_name.c_str()); + } + dt = readdir(d); + } + closedir(d); + } + return rmdir(strPath.c_str()) == 0 ? true : false; +} + +static bool IsFileExist(const std::string &path) +{ + if (path.empty()) { + return false; + } + struct stat st {}; + if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { + return true; + } + return false; +} + +static bool IsDirExist(const std::string &path) +{ + if (path.empty()) { + return false; + } + struct stat st {}; + if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) { + return true; + } + return false; +} + +class EngUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(EngUnitTest, TestFilesOverlay, TestSize.Level1) +{ + bool isDel = false; + bool isExist = IsDirExist(ENG_ROOT_PATH.c_str()); + if (isExist) { + isDel = RemoveDir(ENG_ROOT_PATH.c_str()); + EXPECT_EQ(isDel, true); + } + isExist = IsDirExist(TARGET_PATH.c_str()); + if (isExist) { + isDel = RemoveDir(TARGET_PATH.c_str()); + EXPECT_EQ(isDel, true); + } + DebugFilesOverlay(ENG_ROOT_PATH.c_str(), TARGET_PATH.c_str()); + + CreateTestFile(SRC_FILE_PATH.c_str(), "test"); + isExist = IsFileExist(SRC_FILE_PATH.c_str()); + EXPECT_EQ(isExist, true); + + DebugFilesOverlay(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str()); + isExist = IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_REG); + EXPECT_EQ(isExist, true); + + + if (IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK)) { + if (unlink(TARGET_PATH.c_str()) < 0) { + EXPECT_TRUE(false); + } + } + int ret = symlink(ENG_ROOT_PATH.c_str(), TARGET_PATH.c_str()); + EXPECT_EQ(ret, 0); + isExist = IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK); + EXPECT_EQ(isExist, true); + DebugFilesOverlay(TARGET_PATH.c_str(), ENG_ROOT_PATH.c_str()); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(EngUnitTest, TestBindMountFile, TestSize.Level1) +{ + BindMountFile("data/init_ut", ""); + BindMountFile("data", "target"); + BindMountFile("/data/init_ut//", "/"); + BindMountFile("/data/init_ut", "/"); + BindMountFile("/data", "/"); + BindMountFile("/data/", "/"); + + bool isExist = false; + if (!IsFileExist(SRC_FILE_PATH.c_str())) { + CreateTestFile(SRC_FILE_PATH.c_str(), "test reg file mount"); + isExist = IsFileExist(SRC_FILE_PATH.c_str()); + EXPECT_EQ(isExist, true); + BindMountFile(SRC_FILE_PATH.c_str(), "/"); + } + BindMountFile(SRC_FILE_PATH.c_str(), "/"); + + if (IsFileExist(SRC_FILE_PATH.c_str())) { + RemoveDir(STARTUP_INIT_UT_PATH"/eng/source"); + isExist = IsFileExist(SRC_FILE_PATH.c_str()); + EXPECT_EQ(isExist, false); + } + if (IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK)) { + if (unlink(TARGET_PATH.c_str()) < 0) { + EXPECT_TRUE(false); + } + } + + bool isLinkFile = IsFileExist(TARGET_PATH.c_str()); + EXPECT_EQ(isLinkFile, false); + BindMountFile(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str()); + + int ret = symlink(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str()); + EXPECT_EQ(ret, 0); + isLinkFile = IsFileExistWithType(TARGET_PATH.c_str(), TYPE_LINK); + EXPECT_EQ(isLinkFile, true); + BindMountFile(SRC_FILE_PATH.c_str(), TARGET_PATH.c_str()); + BindMountFile(TARGET_PATH.c_str(), SRC_FILE_PATH.c_str()); +} + +HWTEST_F(EngUnitTest, TestMountCmd, TestSize.Level1) +{ + char mountCmd[MOUNT_CMD_MAX_LEN] = {}; + MountEngPartitions(); + BuildMountCmd(mountCmd, MOUNT_CMD_MAX_LEN, "/eng/source", "/eng/target", "ext4"); + BuildMountCmd(mountCmd, 0, "/eng/source", "/eng/target", "ext4"); +} + +HWTEST_F(EngUnitTest, TestFileType, TestSize.Level1) +{ + std::string targetFile = "/data/init_ut/eng/target_file"; + std::string linkName = "/data/init_ut/eng/link_name_test"; + bool isExist = false; + + if (!IsFileExist(SRC_FILE_PATH.c_str())) { + CreateTestFile(SRC_FILE_PATH.c_str(), "test"); + isExist = IsFileExist(SRC_FILE_PATH.c_str()); + EXPECT_EQ(isExist, true); + } + + EXPECT_EQ(IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_REG), true); + EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_DIR), true); + + EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_LINK), false); + EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_REG), false); + EXPECT_EQ(IsFileExistWithType(STARTUP_INIT_UT_PATH"/eng", TYPE_ANY), true); + EXPECT_EQ(IsFileExistWithType(SRC_FILE_PATH.c_str(), TYPE_DIR), false); + + if (IsFileExist(targetFile)) { + if (unlink(targetFile.c_str()) < 0) { + std::cout << "Failed to unlink file " << targetFile << " err = " << errno << std::endl; + EXPECT_TRUE(false); + } + } + int fd = open(targetFile.c_str(), O_CREAT | O_CLOEXEC | O_WRONLY, 0644); + if (fd < 0) { + std::cout << "Failed to create file " << targetFile << " err = " << errno << std::endl; + EXPECT_TRUE(false); + } else { + std::string buffer = "hello"; + write(fd, buffer.c_str(), buffer.size()); + close(fd); // avoid leak + } + + if (IsFileExist(linkName)) { + if (unlink(linkName.c_str()) < 0) { + std::cout << "Failed to unlink file " << linkName << " err = " << errno << std::endl; + EXPECT_TRUE(false); + } + } + + int ret = symlink(targetFile.c_str(), linkName.c_str()); + EXPECT_EQ(ret, 0); + bool isFileExist = IsFileExistWithType(linkName.c_str(), TYPE_LINK); + EXPECT_EQ(isFileExist, true); + + isFileExist = IsFileExistWithType("/eng/target", TYPE_LINK); + EXPECT_EQ(isFileExist, false); + + isFileExist = IsFileExistWithType("/eng/target", TYPE_REG); + EXPECT_EQ(isFileExist, false); +} + +HWTEST_F(EngUnitTest, TestHook, TestSize.Level1) +{ + HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr); + PrepareCmdLineData(); + HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr); + const char *cmdLine = "ohos.boot.root_package=off "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); + HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr); +} +} // namespace init_ut diff --git a/test/unittest/modules/modules_unittest.cpp b/test/unittest/modules/modules_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9adf9205a2a22ff465a238e9c1c18b4b40b5ed15 --- /dev/null +++ b/test/unittest/modules/modules_unittest.cpp @@ -0,0 +1,118 @@ +/* + * 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 "bootchart.h" +#include "bootstage.h" +#include "init_utils.h" +#include "param_stub.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +extern "C" { +long long GetJiffies(void); +char *ReadFileToBuffer(const char *fileName, char *buffer, uint32_t bufferSize); +void BootchartLogHeader(void); +void BootchartLogFile(FILE *log, const char *procfile); +void BootchartLogProcessStat(FILE *log, pid_t pid); +void bootchartLogProcess(FILE *log); +void *BootchartThreadMain(void *data); +void BootchartDestory(void); +int DoBootchartStart(void); +int DoBootchartStop(void); +int DoBootchartCmd(int id, const char *name, int argc, const char **argv); +int BootchartInit(void); +void BootchartExit(void); +} + +class ModulesUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(ModulesUnitTest, TestBootchartInit, TestSize.Level1) +{ + EXPECT_EQ(BootchartInit(), 0); + EXPECT_NE(GetJiffies(), -1); + EXPECT_NE(DoBootchartStart(), 1); + EXPECT_EQ(DoBootchartStop(), 0); + BootchartExit(); +} + +HWTEST_F(ModulesUnitTest, TestReadFileToBuffer, TestSize.Level1) +{ + const char *fileName = "ModulesTest"; + char buffer[MAX_BUFFER_LEN] = {0}; + EXPECT_EQ(ReadFileToBuffer(fileName, buffer, MAX_BUFFER_LEN), nullptr); + buffer[1] = 'a'; + EXPECT_EQ(ReadFileToBuffer(nullptr, buffer, MAX_BUFFER_LEN), nullptr); + EXPECT_EQ(ReadFileToBuffer(nullptr, nullptr, MAX_BUFFER_LEN), nullptr); +} + +HWTEST_F(ModulesUnitTest, TestBootchartLogFile, TestSize.Level1) +{ + DoBootchartStart(); + FILE *log = fopen("/data/init_ut/ModulesTest.log", "w"); + if (log) { + BootchartLogFile(log, "/proc/stat"); + (void)fflush(log); + (void)fclose(log); + } +} + +HWTEST_F(ModulesUnitTest, TestBootchartLogProcessStat, TestSize.Level1) +{ + FILE *log = fopen("/data/init_ut/ModulesTest.log", "w"); + pid_t selfPid = getpid(); + if (log != nullptr) { + BootchartLogProcessStat(log, selfPid); + (void)fflush(log); + (void)fclose(log); + } +} + +HWTEST_F(ModulesUnitTest, TestbootchartLogProcess, TestSize.Level1) +{ + FILE *log = fopen("/data/init_ut/ModulesTest.log", "w"); + if (log) { + bootchartLogProcess(log); + (void)fflush(log); + (void)fclose(log); + } +} + +HWTEST_F(ModulesUnitTest, TestDoBootchartCmd, TestSize.Level1) +{ + const char *argv1[] = { "start" }; + const char *argv2[] = { "stop" }; + EXPECT_NE(DoBootchartCmd(0, "bootchart", 1, argv1), 1); + EXPECT_NE(DoBootchartCmd(0, "bootchart", 1, argv2), 1); +} + +HWTEST_F(ModulesUnitTest, TestDoBootchartInsall, TestSize.Level1) +{ + TestSetParamCheckResult("ohos.servicectrl.", 0777, 0); + SystemWriteParam("persist.init.bootchart.enabled", "1"); + SystemWriteParam("persist.init.debug.dump.trigger", "1"); + SystemWriteParam("persist.init.debug.loglevel", "6"); + SystemWriteParam("ohos.servicectrl.cmd", "setloglevel 10"); + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, nullptr, nullptr); +} +} // namespace init_ut diff --git a/test/unittest/modules/sysevent_unittest.cpp b/test/unittest/modules/sysevent_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..497d773caca77934ba69ab53ee9c50973b7cd6b2 --- /dev/null +++ b/test/unittest/modules/sysevent_unittest.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023 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 "bootevent.h" +#include "init_param.h" +#include "init_utils.h" +#include "list.h" +#include "param_stub.h" +#include "securec.h" +#include "sys_event.h" +#include "init_cmdexecutor.h" + +using namespace std; +using namespace testing::ext; +extern "C" { +extern void ReportBootEventComplete(ListNode *events); +} + +static void AddBootEvent(ListNode *events, const char *name, int32_t type) +{ + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM)); + if (item == nullptr) { + return; + } + OH_ListInit(&item->node); + item->paramName = strdup(name); + if (item->paramName == nullptr) { + free(item); + return; + } + (void)clock_gettime(CLOCK_MONOTONIC, &(item->timestamp[BOOTEVENT_FORK])); + (void)clock_gettime(CLOCK_MONOTONIC, &(item->timestamp[BOOTEVENT_READY])); + item->flags = type; + OH_ListAddTail(events, (ListNode *)&item->node); +} + +static void BootEventDestroyProc(ListNode *node) +{ + if (node == nullptr) { + return; + } + BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node; + OH_ListRemove(node); + OH_ListInit(node); + free(item->paramName); + free(item); +} + +namespace init_ut { +class SysEventUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(SysEventUnitTest, SysEventTest_001, TestSize.Level1) +{ + ReportBootEventComplete(nullptr); +} + +HWTEST_F(SysEventUnitTest, SysEventTest_002, TestSize.Level1) +{ + ListNode events = { &events, &events }; + // empty event + ReportBootEventComplete(&events); +} + +HWTEST_F(SysEventUnitTest, SysEventTest_003, TestSize.Level1) +{ + ListNode events = { &events, &events }; + // create event and report + AddBootEvent(&events, "bootevent.11111.xxxx", BOOTEVENT_TYPE_JOB); + AddBootEvent(&events, "bootevent.22222222.xxxx", BOOTEVENT_TYPE_SERVICE); + AddBootEvent(&events, "bootevent.33333333333.xxxx", BOOTEVENT_TYPE_SERVICE); + AddBootEvent(&events, "bootevent.44444444444444", BOOTEVENT_TYPE_SERVICE); + AddBootEvent(&events, "bootevent.44444444444444.6666666666.777777", BOOTEVENT_TYPE_SERVICE); + SystemWriteParam("ohos.boot.bootreason", "-1"); + ReportBootEventComplete(&events); + OH_ListRemoveAll(&events, BootEventDestroyProc); +} + +HWTEST_F(SysEventUnitTest, SysEventTest_004, TestSize.Level1) +{ + struct timespec curr = {0}; + if (clock_gettime(CLOCK_MONOTONIC, &curr) != 0) { + return; + } + StartupTimeEvent startupTime = {}; + startupTime.event.type = STARTUP_TIME; + startupTime.totalTime = curr.tv_sec; + startupTime.totalTime = startupTime.totalTime * MSECTONSEC; + startupTime.totalTime += curr.tv_nsec / USTONSEC; + startupTime.detailTime = const_cast("buffer"); + startupTime.reason = const_cast(""); + startupTime.firstStart = 1; + ReportSysEvent(&startupTime.event); +} + +HWTEST_F(SysEventUnitTest, SysEventTest_005, TestSize.Level1) +{ + struct timespec curr = {0}; + if (clock_gettime(CLOCK_MONOTONIC, &curr) != 0) { + return; + } + StartupTimeEvent startupTime = {}; + startupTime.event.type = STARTUP_EVENT_MAX; + startupTime.totalTime = curr.tv_sec; + startupTime.totalTime = startupTime.totalTime * MSECTONSEC; + startupTime.totalTime += curr.tv_nsec / USTONSEC; + startupTime.detailTime = const_cast("buffer"); + startupTime.reason = const_cast(""); + startupTime.firstStart = 1; + ReportSysEvent(&startupTime.event); +} + +HWTEST_F(SysEventUnitTest, SysEventTest_006, TestSize.Level1) +{ + ReportSysEvent(nullptr); +} + +HWTEST_F(SysEventUnitTest, SysEventTest_007, TestSize.Level1) +{ + const char *appfwkReady[] = {"bootevent.appfwk.ready"}; + int ret = PluginExecCmd("unset_bootevent", 1, appfwkReady); + printf("SysEventTest_007:%d\n", ret); +} +} // namespace init_ut diff --git a/test/unittest/modules/trace_unittest.cpp b/test/unittest/modules/trace_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d5b191a56ab01e257c6e66e58812abf3462c8c8 --- /dev/null +++ b/test/unittest/modules/trace_unittest.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2023 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 "bootstage.h" +#include "init_utils.h" +#include "init_cmds.h" +#include "init_cmdexecutor.h" +#include "param_stub.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +static const char *g_content = + "\"KERNEL\" : [" + "{" + "\"name\" : \"disk\"," + "\"description\" : \"Disk I/O\"," + "\"tag\" : 0," + "\"type\" : \"KERNEL\"," + "\"sys-files\" : [" + "\"events/f2fs/f2fs_sync_file_enter/enable\"," + "\"events/f2fs/f2fs_sync_file_exit/enable\"," + "\"events/f2fs/f2fs_write_begin/enable\"," + "\"events/f2fs/f2fs_write_end/enable\"," + "\"events/ext4/ext4_da_write_begin/enable\"," + "\"events/ext4/ext4_da_write_end/enable\"," + "\"events/ext4/ext4_sync_file_enter/enable\"," + "\"events/ext4/ext4_sync_file_exit/enable\"," + "\"events/block/block_rq_issue/enable\"," + "\"events/block/block_rq_complete/enable\"" + "]" + "}," + "{" + "\"name\" : \"mmc\"," + "\"description\" : \"eMMC commands\"," + "\"tag\" : 0," + "\"type\" : \"KERNEL\"," + "\"sys-files\" : [" + "\"events/mmc/enable\"" + "]" + "}," + "{" + "\"name\" : \"test\"," + "\"description\" : \"test\"," + "\"tag\" : 0," + "\"type\" : \"KERNEL\"," + "\"sys-files\" : [" + "]" + "}" + "]," + "\"USER\" : [" + "{" + "\"name\" : \"ohos\"," + "\"description\" : \"OpenHarmony\"," + "\"tag\" : 30," + "\"type\" : \"USER\"," + "\"sys-files\" : [" + "]" + "}," + "{" + "\"name\" : \"ability\"," + "\"description\" : \"Ability Manager\"," + "\"tag\" : 31," + "\"type\" : \"USER\"," + "\"sys-files\" : [" + "]" + "}," + "{" + "\"name\" : \"usb\"," + "\"description\" : \"usb subsystem\"," + "\"tag\" : 19," + "\"type\" : \"USER\"," + "\"sys-files\" : [" + "]" + "}" + "]" +"}"; +void CreateInitTraceConfig(int compress) +{ + std::string config = "{ \"compress\" : "; + if (!compress) { + config += "false,"; + } else { + config += "true, "; + } + config += g_content; + // create trace cfg + CreateTestFile(STARTUP_INIT_UT_PATH"/system/etc/init_trace.cfg", config.c_str()); +} + +class TraceUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(TraceUnitTest, TraceTest_001, TestSize.Level1) +{ + // open switch for trace + uint32_t dataIndex = 0; + WriteParam("persist.init.bootevent.enable", "true", &dataIndex, 0); + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, nullptr, nullptr); + // close switch for trace + WriteParam("persist.init.bootevent.enable", "false", &dataIndex, 0); + HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, nullptr, nullptr); +} + +HWTEST_F(TraceUnitTest, TraceTest_002, TestSize.Level1) +{ + CreateInitTraceConfig(1); + // start trace + PluginExecCmdByName("init_trace", "start"); + // for run 1 s + sleep(1); + // stop trace + PluginExecCmdByName("init_trace", "stop"); +} + +HWTEST_F(TraceUnitTest, TraceTest_003, TestSize.Level1) +{ + CreateInitTraceConfig(0); + // start trace + PluginExecCmdByName("init_trace", "start"); + // for run 1 s + sleep(1); + // stop trace + PluginExecCmdByName("init_trace", "stop"); +} + +HWTEST_F(TraceUnitTest, TraceTest_004, TestSize.Level1) +{ + std::string cmdArgs = "/system/etc/init_trace.cfg "; + cmdArgs += STARTUP_INIT_UT_PATH"/system/etc/init_trace.cfg"; + int cmdIndex = 0; + (void)GetMatchCmd("copy ", &cmdIndex); + DoCmdByIndex(cmdIndex, cmdArgs.c_str(), nullptr); + + // start trace + PluginExecCmdByName("init_trace", "start"); + // for run 1 s + sleep(1); + // stop trace + PluginExecCmdByName("init_trace", "stop"); +} + +HWTEST_F(TraceUnitTest, TraceTest_005, TestSize.Level1) +{ + // start trace + PluginExecCmdByName("init_trace", "start"); + // for run 1 s + sleep(1); + // interrupt trace + PluginExecCmdByName("init_trace", "1"); +} + +HWTEST_F(TraceUnitTest, TraceTest_006, TestSize.Level1) +{ + std::string cmdArgs = "/bin/test "; + cmdArgs += STARTUP_INIT_UT_PATH"/bin/test"; + int cmdIndex = 0; + (void)GetMatchCmd("copy ", &cmdIndex); + DoCmdByIndex(cmdIndex, cmdArgs.c_str(), nullptr); + + // start trace + PluginExecCmdByName("init_trace", "start"); + // for run 1 s + sleep(1); + // stop trace + PluginExecCmdByName("init_trace", "stop"); +} + +HWTEST_F(TraceUnitTest, TraceTest_007, TestSize.Level1) +{ + CreateInitTraceConfig(0); + // other case + PluginExecCmdByName("init_trace", "other"); +} +} // namespace init_ut diff --git a/test/unittest/modules/udid_unittest.cpp b/test/unittest/modules/udid_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a998d6a189a8b805d6fce8e8a477800cf7371cad --- /dev/null +++ b/test/unittest/modules/udid_unittest.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 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 "udid.h" +#include "param_stub.h" +#include "sysparam_errno.h" +#include "securec.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +extern "C" { +int GetSha256Value(const char *input, char *udid, uint32_t udidSize); +void SetDevUdid(); +int CalcDevUdid(char *udid, uint32_t size); +} + +class UdidUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; +}; + +HWTEST_F(UdidUnitTest, TestUDID_001, TestSize.Level1) +{ + SetDevUdid(); +} + +HWTEST_F(UdidUnitTest, TestUDID_002, TestSize.Level1) +{ + int ret = GetSha256Value(nullptr, nullptr, 0); + EXPECT_EQ(ret, EC_FAILURE); +} + +HWTEST_F(UdidUnitTest, TestUDID_003, TestSize.Level1) +{ + char udid[66] = {0}; + int ret = CalcDevUdid(udid, 6); + EXPECT_EQ(ret, EC_FAILURE); + ret = CalcDevUdid(udid, 66); + EXPECT_EQ(ret, EC_SUCCESS); +} +} // namespace init_ut diff --git a/test/unittest/param/atomic_unittest.cpp b/test/unittest/param/atomic_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74ed7ffb69c931dad5adfc6226c1d2655469c90f --- /dev/null +++ b/test/unittest/param/atomic_unittest.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 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 "param_atomic.h" +#include "param_common.h" +#include "param_utils.h" + +using namespace testing::ext; +const int THREAD_NUM = 5; +const int MAX_NUM = 10; + +namespace init_ut { +class AtomicUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +/** + * 测试方法: + * 1,create 线程,执行全局变量写操作 + * store with dirty + * sleep + * store clear dirty + * store commit ++ + * 2,read 现成,执行全局变量读参数 + * + */ +using AtomicTestData = struct { + ATOMIC_UINT32 commitId; + uint32_t data; +}; + +static AtomicTestData g_testData = { 0, 0 }; + +static void *TestSetData(void *args) +{ + while (g_testData.data < MAX_NUM) { + uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&g_testData.commitId, MEMORY_ORDER_RELAXED); + ATOMIC_STORE_EXPLICIT(&g_testData.commitId, commitId | PARAM_FLAGS_MODIFY, MEMORY_ORDER_RELAXED); + g_testData.data++; + usleep(200 * 1000); // 200 * 1000 wait + printf("TestSetData data: %d commit: %d \n", g_testData.data, g_testData.commitId & PARAM_FLAGS_COMMITID); + uint32_t flags = commitId & ~PARAM_FLAGS_COMMITID; + ATOMIC_STORE_EXPLICIT(&g_testData.commitId, (++commitId) | flags, MEMORY_ORDER_RELEASE); + futex_wake(&g_testData.commitId, INT_MAX); + usleep(100); // 100 wait + } + return nullptr; +} + +static inline uint32_t TestReadCommitId(AtomicTestData *entry) +{ + uint32_t commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); + while (commitId & PARAM_FLAGS_MODIFY) { + futex_wait(&entry->commitId, commitId); + commitId = ATOMIC_LOAD_EXPLICIT(&entry->commitId, MEMORY_ORDER_ACQUIRE); + } + return commitId & PARAM_FLAGS_COMMITID; +} + +static inline int TestReadParamValue(AtomicTestData *entry, uint32_t *commitId) +{ + uint32_t data; + uint32_t id = *commitId; + do { + *commitId = id; + data = entry->data; + id = TestReadCommitId(entry); + } while (*commitId != id); // if change, must read + return data; +} + +static void *TestReadData(void *args) +{ + uint32_t data = 0; + while (data < MAX_NUM) { + uint32_t commitId = TestReadCommitId(&g_testData); + data = TestReadParamValue(&g_testData, &commitId); + printf("[ %d] TestReadData data: %d commit: %d \n", gettid(), data, commitId); + usleep(10); // 10 wait + } + return nullptr; +} + +HWTEST_F(AtomicUnitTest, Init_AtomicUnitTest_001, TestSize.Level0) +{ + printf("AtomicUnitTest_001 \n"); + pthread_t writeThread = 0; + pthread_t readThread[THREAD_NUM] = { 0 }; + pthread_create(&writeThread, nullptr, TestSetData, nullptr); + for (size_t i = 0; i < THREAD_NUM; i++) { + pthread_create(&readThread[i], nullptr, TestReadData, nullptr); + } + pthread_join(writeThread, nullptr); + printf("AtomicUnitTest_001 end \n"); +} +} \ No newline at end of file diff --git a/test/unittest/param/client_unittest.cpp b/test/unittest/param/client_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8303612750c609cb046404c911b787df3862d718 --- /dev/null +++ b/test/unittest/param/client_unittest.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2021 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 "init_param.h" +#include "init_utils.h" +#include "param_stub.h" +#include "param_init.h" + +using namespace std; +using namespace testing::ext; + +static void ClientCheckParamValue(const char *name, const char *expectValue) +{ + char tmp[PARAM_BUFFER_SIZE] = {0}; + u_int32_t len = sizeof(tmp); + int ret = SystemGetParameter(name, tmp, &len); + PARAM_LOGI("ClientCheckParamValue name %s value: \'%s\' expectValue:\'%s\' ", name, tmp, expectValue); + if (ret == 0 && len > 0) { + EXPECT_NE((int)strlen(tmp), 0); + if (expectValue != nullptr) { + EXPECT_EQ(strcmp(tmp, expectValue), 0); + } + } +} + +// 多线程测试 +static void *TestSendParamSetMsg(void *args) +{ + if (args == nullptr) { + return nullptr; + } + std::string name = (char *)args; + PARAM_LOGI("TestSendParamSetMsg name :\'%s\' ", name.c_str()); + int ret = SystemSetParameter(name.c_str(), name.c_str()); + EXPECT_EQ(ret, 0); + return nullptr; +} + +static void *TestSendParamWaitMsg(void *args) +{ + if (args == nullptr) { + return nullptr; + } + std::string name = "Wati."; + name = name + (char *)args; + PARAM_LOGI("TestSendParamWaitMsg name :\'%s\' \n", name.c_str()); + int ret = SystemWaitParameter(name.c_str(), name.c_str(), 1); + EXPECT_GE(ret, 0); + return nullptr; +} + +static void TestForMultiThread() +{ + static const int threadMaxNumer = 2; + PARAM_LOGI("TestForMultiThread \n"); + pthread_t tids[threadMaxNumer + threadMaxNumer]; + const char *names[] = { + "thread.1111.2222.3333.4444.5555", + "thread.2222.1111.2222.3333.4444", + "thread.3333.1111.2222.4444.5555", + "thread.4444.5555.1111.2222.3333", + "thread.5555.1111.2222.3333.4444" + }; + for (size_t i = 0; i < threadMaxNumer; i++) { + pthread_create(&tids[i], nullptr, TestSendParamSetMsg, + reinterpret_cast(const_cast(names[i % ARRAY_LENGTH(names)]))); + } + for (size_t i = threadMaxNumer; i < threadMaxNumer + threadMaxNumer; i++) { + pthread_create(&tids[i], nullptr, TestSendParamWaitMsg, + reinterpret_cast(const_cast(names[i % ARRAY_LENGTH(names)]))); + } + for (size_t i = 0; i < threadMaxNumer + threadMaxNumer; i++) { + pthread_join(tids[i], nullptr); + } +} + +static void TestParamTraversal() +{ + SystemTraversalParameter( + "", + [](ParamHandle handle, void *cookie) { + char value[PARAM_BUFFER_SIZE + PARAM_BUFFER_SIZE] = {0}; + uint32_t commitId = 0; + int ret = SystemGetParameterCommitId(handle, &commitId); + EXPECT_EQ(ret, 0); + SystemGetParameterName(handle, value, PARAM_BUFFER_SIZE); + u_int32_t len = PARAM_BUFFER_SIZE; + SystemGetParameterValue(handle, ((char *)value) + PARAM_BUFFER_SIZE, &len); + printf("$$$$$$$$Param %s=%s \n", (char *)value, ((char *)value) + PARAM_BUFFER_SIZE); + }, + nullptr); +} + +static void TestPermission() +{ + const char *testName = "persist.111.ffff.bbbb.cccc.dddd.eeee.55555"; + char tmp[PARAM_BUFFER_SIZE] = {0}; + int ret; + + ParamSecurityOps *paramSecurityOps = GetParamSecurityOps(0); + EXPECT_NE(paramSecurityOps, nullptr); + paramSecurityOps->securityCheckParamPermission = TestCheckParamPermission; + SetTestPermissionResult(DAC_RESULT_FORBIDED); + if ((GetParamSecurityLabel() != nullptr)) { + GetParamSecurityLabel()->flags[0] = LABEL_CHECK_IN_ALL_PROCESS; + ret = SystemSetParameter(testName, "22202"); +#ifdef __LITEOS_A__ + EXPECT_EQ(ret, DAC_RESULT_FORBIDED); +#else + EXPECT_EQ(ret, 0); // 本地不在校验 +#endif + } + paramSecurityOps->securityFreeLabel = TestFreeLocalSecurityLabel; + paramSecurityOps->securityCheckParamPermission = TestCheckParamPermission; + SetTestPermissionResult(0); + SystemWriteParam(testName, "22202"); + ret = SystemSetParameter(testName, "22202"); + ClientCheckParamValue(testName, "22202"); + + const int testResult = 201; + SetTestPermissionResult(testResult); + ret = SystemSetParameter(testName, "3333"); +#ifdef __LITEOS_A__ + EXPECT_EQ(ret, testResult); +#else + EXPECT_EQ(ret, 0); // 本地不在校验 +#endif + + u_int32_t len = sizeof(tmp); + SetTestPermissionResult(DAC_RESULT_FORBIDED); + ret = SystemGetParameter(testName, tmp, &len); + EXPECT_EQ(ret, DAC_RESULT_FORBIDED); + RegisterSecurityOps(0); + SetTestPermissionResult(0); // recover testpermission result +} + +void TestClientApi(char testBuffer[], uint32_t size, const char *name, const char *value) +{ + ParamHandle handle; + int ret = SystemFindParameter(name, &handle); + SystemWriteParam(name, value); + SystemSetParameter(name, value); + ret = SystemFindParameter(name, &handle); + EXPECT_EQ(ret, 0); + uint32_t commitId = 0; + ret = SystemGetParameterCommitId(handle, &commitId); + EXPECT_EQ(ret, 0); + ret = SystemGetParameterName(handle, testBuffer, size); + EXPECT_EQ(ret, 0); + EXPECT_EQ(strcmp(testBuffer, name), 0); + ret = SystemGetParameterValue(handle, testBuffer, &size); + EXPECT_EQ(ret, 0); + EXPECT_EQ(strcmp(testBuffer, value), 0); +} + +namespace init_ut { +class ClientUnitTest : public ::testing::Test { +public: + ClientUnitTest() {} + virtual ~ClientUnitTest() {} + static void SetUpTestCase(void) {} + void SetUp(void) + { + if (GetParamSecurityLabel() != nullptr) { + GetParamSecurityLabel()->cred.uid = 1000; // 1000 test uid + GetParamSecurityLabel()->cred.gid = 1000; // 1000 test gid + } + } + void TearDown(void) {} + void TestBody(void) {} +}; + +HWTEST_F(ClientUnitTest, Init_TestClient_001, TestSize.Level0) +{ + const std::string name = "test.add.client.001.001"; + const std::string value = "test.add.client.value.001.001"; + // direct write + SystemWriteParam(name.c_str(), value.c_str()); + SystemSetParameter(name.c_str(), value.c_str()); + ClientCheckParamValue(name.c_str(), value.c_str()); + SystemWaitParameter(name.c_str(), value.c_str(), 1); + // wait + SystemWaitParameter(name.c_str(), value.c_str(), 1); + SystemWaitParameter(name.c_str(), nullptr, 0); + + // error + SystemWaitParameter(nullptr, nullptr, 0); + SystemWaitParameter("@@@@", value.c_str(), 1); +} + +HWTEST_F(ClientUnitTest, Init_TestParamValue_001, TestSize.Level0) +{ + // support empty string + const char *name = "test_readonly.dddddddddddddddddd.fffffffffffffffffff"; + int ret = SystemSetParameter(name, ""); + EXPECT_EQ(ret, 0); + ret = SystemSetParameter(name, "111111111"); + EXPECT_EQ(ret, 0); + ret = SystemSetParameter(name, ""); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(ClientUnitTest, Init_TestClient_002, TestSize.Level0) +{ + char testBuffer[PARAM_BUFFER_SIZE] = {0}; + const std::string value = "test.add.client.value.001"; + const std::string name = "test.add.client.001.003"; + TestClientApi(testBuffer, PARAM_BUFFER_SIZE, name.c_str(), value.c_str()); +} + +HWTEST_F(ClientUnitTest, Init_TestClient_003, TestSize.Level0) +{ + // 3 Traversal test + TestParamTraversal(); + SystemDumpParameters(1, -1, nullptr); +} + +HWTEST_F(ClientUnitTest, Init_TestClient_004, TestSize.Level0) +{ + const std::string name = "test.add.client.001.004"; + int ret = WatchParamCheck(name.c_str()); +#ifndef OHOS_LITE + EXPECT_EQ(ret, 0); +#endif + ret = WatchParamCheck("&&&&&.test.tttt"); + EXPECT_NE(ret, 0); + + ret = WatchParamCheck(nullptr); +#ifndef OHOS_LITE + EXPECT_EQ(ret, 100); +#endif + // test permission + TestPermission(); +} + +HWTEST_F(ClientUnitTest, Init_TestClient_005, TestSize.Level0) +{ + TestForMultiThread(); +} + +HWTEST_F(ClientUnitTest, Init_TestClient_006, TestSize.Level0) +{ + int ret = SystemSetParameter("test.type.string.xxx", "xxxxxxx"); + EXPECT_EQ(ret, 0); + ret = SystemSetParameter("test.type.string...xxx", "xxxxxxx"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_NAME); + ret = SystemSetParameter("test.type.string*xxx", "xxxxxxx"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_NAME); +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + ret = SystemSetParameter("test.type.bool.xxx", "xxxxxxxxxxxxxxxx"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE); + char value[PARAM_VALUE_LEN_MAX] = {0}; + u_int32_t len = sizeof(value); + ret = SystemGetParameter("test.permission.watcher.xxx", value, &len); + EXPECT_EQ(ret, DAC_RESULT_FORBIDED); + ret = SystemGetParameter("test.type.xxx", value, &len); + EXPECT_EQ(ret, PARAM_CODE_NOT_FOUND); +#endif +} +} // namespace init_ut \ No newline at end of file diff --git a/test/unittest/param/dac_unittest.cpp b/test/unittest/param/dac_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0468e92dda43b540ea5ed7fa56da448948e6c4e3 --- /dev/null +++ b/test/unittest/param/dac_unittest.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2021 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 "param_manager.h" +#include "param_security.h" +#include "param_stub.h" +#include "param_utils.h" +#include "securec.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class DacUnitTest : public ::testing::Test { +public: + DacUnitTest() {} + virtual ~DacUnitTest() {} + + void SetUp() {} + void TearDown() {} + void TestBody() {} + + int TestDacInitLocalLabel() + { + int ret = RegisterSecurityDacOps(nullptr, LABEL_INIT_FOR_INIT); + EXPECT_NE(ret, 0); + ret = RegisterSecurityDacOps(&initParamSecurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + + if (initParamSecurityOps.securityInitLabel == nullptr || initParamSecurityOps.securityFreeLabel == nullptr) { + return -1; + } + ParamSecurityLabel label = {}; + ret = initParamSecurityOps.securityInitLabel(&label, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + ret = initParamSecurityOps.securityFreeLabel(&label); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestDacGetLabel() + { + int ret = RegisterSecurityDacOps(&initParamSecurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + if (initParamSecurityOps.securityGetLabel == nullptr) { + return -1; + } + // get label from file + ret = initParamSecurityOps.securityGetLabel(STARTUP_INIT_UT_PATH "/system/etc/param/ohos.para.dac"); + return ret; + } + + int TestDacCheckFilePermission(const char *fileName) + { + int ret = RegisterSecurityDacOps(&initParamSecurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + if (initParamSecurityOps.securityCheckFilePermission == nullptr) { + return -1; + } + ParamSecurityLabel label = {}; + ret = initParamSecurityOps.securityInitLabel(&label, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + ret = initParamSecurityOps.securityCheckFilePermission(&label, fileName, DAC_WRITE); + EXPECT_EQ(ret, 0); + ret = initParamSecurityOps.securityFreeLabel(&label); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestDacCheckParaPermission(const char *name, ParamDacData *dacData, int mode) + { + int ret = RegisterSecurityDacOps(&initParamSecurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + if (initParamSecurityOps.securityCheckFilePermission == nullptr) { + return -1; + } + ParamAuditData auditData = {}; + auditData.name = name; + ret = memcpy_s(&auditData.dacData, sizeof(auditData.dacData), dacData, sizeof(auditData.dacData)); + EXPECT_EQ(ret, 0); + ret = AddSecurityLabel(&auditData); + EXPECT_EQ(ret, 0); + ParamSecurityLabel srclabel = {}; + ret = initParamSecurityOps.securityInitLabel(&srclabel, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + ret = initParamSecurityOps.securityCheckParamPermission(TestGetParamLabelIndex(name), &srclabel, name, mode); + initParamSecurityOps.securityFreeLabel(&srclabel); + return ret; + } + + int TestClientDacCheckFilePermission(const char *fileName) + { + int ret = RegisterSecurityDacOps(&clientParamSercurityOps, 0); + EXPECT_EQ(ret, 0); + if (clientParamSercurityOps.securityGetLabel != nullptr) { + EXPECT_EQ(1, 0); + } + if (clientParamSercurityOps.securityCheckFilePermission == nullptr) { + EXPECT_EQ(1, 0); + return -1; + } + ParamSecurityLabel label = {}; + ret = clientParamSercurityOps.securityInitLabel(&label, 0); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityCheckFilePermission(&label, fileName, DAC_READ); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityFreeLabel(&label); + EXPECT_EQ(ret, 0); + return 0; + } + +private: + ParamSecurityOps initParamSecurityOps {}; + ParamSecurityOps clientParamSercurityOps {}; +}; + +HWTEST_F(DacUnitTest, Init_TestDacInitLocalLabel_001, TestSize.Level0) +{ + DacUnitTest test; + test.TestDacInitLocalLabel(); +} + +HWTEST_F(DacUnitTest, Init_TestDacCheckFilePermission_001, TestSize.Level0) +{ + DacUnitTest test; + test.TestDacCheckFilePermission(STARTUP_INIT_UT_PATH "/trigger_test.cfg"); +} + +HWTEST_F(DacUnitTest, Init_TestDacCheckUserParaPermission_001, TestSize.Level0) +{ + // 相同用户 + DacUnitTest test; + ParamDacData dacData; + dacData.gid = getegid(); + dacData.uid = geteuid(); + // read + dacData.mode = 0400; + int ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_READ); + EXPECT_EQ(ret, 0); + dacData.mode = 0400; + ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_WRITE); + EXPECT_NE(ret, 0); + dacData.mode = 0400; + ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_WATCH); + EXPECT_NE(ret, 0); + + // write + dacData.mode = 0200; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_READ); + EXPECT_NE(ret, 0); + dacData.mode = 0200; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_WRITE); + EXPECT_EQ(ret, 0); + dacData.mode = 0200; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_WATCH); + EXPECT_NE(ret, 0); + + // watch + dacData.mode = 0100; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_READ); + EXPECT_NE(ret, 0); + dacData.mode = 0100; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_WRITE); + EXPECT_NE(ret, 0); + dacData.mode = 0100; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_WATCH); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(DacUnitTest, Init_TestDacCheckGroupParaPermission_001, TestSize.Level0) +{ + // 相同组 + DacUnitTest test; + ParamDacData dacData; + dacData.gid = getegid(); + dacData.uid = 13333; + // read + dacData.mode = 0040; + int ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_READ); + EXPECT_EQ(ret, 0); + dacData.mode = 0040; + ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_WRITE); + EXPECT_NE(ret, 0); + dacData.mode = 0040; + ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_WATCH); + EXPECT_NE(ret, 0); + + // write + dacData.mode = 0020; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_READ); + EXPECT_NE(ret, 0); + dacData.mode = 0020; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_WRITE); + EXPECT_EQ(ret, 0); + dacData.mode = 0020; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_WATCH); + EXPECT_NE(ret, 0); + + // watch + dacData.mode = 0010; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_READ); + EXPECT_NE(ret, 0); + dacData.mode = 0010; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_WRITE); + EXPECT_NE(ret, 0); + dacData.mode = 0010; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_WATCH); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(DacUnitTest, Init_TestDacCheckOtherParaPermission_001, TestSize.Level0) +{ + // 其他用户 + DacUnitTest test; + ParamDacData dacData; + dacData.gid = 13333; + dacData.uid = 13333; + // read + dacData.mode = 0004; + int ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_READ); + EXPECT_EQ(ret, 0); + dacData.mode = 0004; + ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_WRITE); + EXPECT_NE(ret, 0); + dacData.mode = 0004; + ret = test.TestDacCheckParaPermission("test.permission.read.aaa", &dacData, DAC_WATCH); + EXPECT_NE(ret, 0); + + // write + dacData.mode = 0002; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_READ); + EXPECT_NE(ret, 0); + dacData.mode = 0002; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_WRITE); + EXPECT_EQ(ret, 0); + dacData.mode = 0002; + ret = test.TestDacCheckParaPermission("test.permission.write.aaa", &dacData, DAC_WATCH); + EXPECT_NE(ret, 0); + + // watch + dacData.mode = 0001; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_READ); + EXPECT_NE(ret, 0); + dacData.mode = 0001; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_WRITE); + EXPECT_NE(ret, 0); + dacData.mode = 0001; + ret = test.TestDacCheckParaPermission("test.permission.watch.aaa", &dacData, DAC_WATCH); + EXPECT_EQ(ret, 0); +} + +HWTEST_F(DacUnitTest, Init_TestClientDacCheckFilePermission_001, TestSize.Level0) +{ + DacUnitTest test; + test.TestClientDacCheckFilePermission(STARTUP_INIT_UT_PATH "/trigger_test.cfg"); +} +} \ No newline at end of file diff --git a/test/unittest/param/param_shell_unittest.cpp b/test/unittest/param/param_shell_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1db1aa58faa62dcc1511ad3719b58cdf1c6521c --- /dev/null +++ b/test/unittest/param/param_shell_unittest.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2021 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 "begetctl.h" +#include "securec.h" +#include "shell.h" +#include "shell_utils.h" +#include "shell_bas.h" +#include "init_param.h" +#include "param_init.h" + +using namespace std; +using namespace testing::ext; + +namespace init_ut { +class ParamShellUnitTest : public testing::Test { +public: + ParamShellUnitTest() {}; + virtual ~ParamShellUnitTest() {}; + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; + void TestBody(void) {}; + void TestInitParamShell() + { + SystemSetParameter("aaa", "aaa"); + BShellHandle bshd = GetShellHandle(); + if (bshd == nullptr) { + return; + } + const char *args[] = {"paramshell", "\n"}; + const ParamInfo *param = BShellEnvGetReservedParam(bshd, PARAM_REVERESD_NAME_CURR_PARAMETER); + int ret = BShellEnvSetParam(bshd, PARAM_REVERESD_NAME_CURR_PARAMETER, "..a", PARAM_STRING, (void *)"..a"); + EXPECT_EQ(ret, 0); + SetParamShellPrompt(bshd, args[1]); + SetParamShellPrompt(bshd, ".."); + + ret = BShellEnvSetParam(bshd, param->name, param->desc, param->type, (void *)""); + SetParamShellPrompt(bshd, ".."); + + SetParamShellPrompt(bshd, ".a"); + SetParamShellPrompt(bshd, "."); + SetParamShellPrompt(bshd, args[1]); + BShellParamCmdRegister(bshd, 1); + BShellEnvStart(bshd); + ret = BShellEnvOutputPrompt(bshd, "testprompt"); + ret = BShellEnvOutputPrompt(bshd, "testprompt1111111111111111111111111111111111111111111111111111111111"); + BShellEnvOutputByte(bshd, 'o'); + EXPECT_EQ(ret, 0); + } + void TestParamShellCmd() + { + BShellHandle bshd = GetShellHandle(); + BShellKey *key = BShellEnvGetDefaultKey('\n'); + EXPECT_NE(key, nullptr); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "cd const") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + int ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "cat aaa") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "testnotcmd") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + // test param start with " + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "\"ls") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + // test argc is 0 + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), ",ls") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "$test$") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "exit") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + } + void TestParamShellCmd1() + { + BShellHandle bshd = GetShellHandle(); + BShellKey *key = BShellEnvGetDefaultKey('\n'); + EXPECT_NE(key, nullptr); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "pwd") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + int ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "help") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "dump") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "dump verbose") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\n'); + EXPECT_EQ(ret, 0); + } + void TestParamShellcmdEndkey() + { + BShellHandle bshd = GetShellHandle(); + bshd->input(nullptr, 0); + BShellKey *key = BShellEnvGetDefaultKey('\b'); + EXPECT_NE(key, nullptr); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "testbbackspace") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + bshd->cursor = strlen("testb"); + int ret = key->keyHandle(bshd, '\b'); + EXPECT_EQ(ret, 0); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "testbbackspace") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + bshd->cursor = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\b'); + EXPECT_EQ(ret, 0); + + key = BShellEnvGetDefaultKey('\t'); + if (strcpy_s(bshd->buffer, sizeof(bshd->buffer), "testtab") != EOK) { + return; + } + bshd->length = strlen(bshd->buffer); + ret = key->keyHandle(bshd, '\t'); + EXPECT_NE(key, nullptr); + BShellEnvProcessInput(bshd, (char)3); // 3 is ctrl c + BShellEnvProcessInput(bshd, '\e'); + BShellEnvProcessInput(bshd, '['); + bshd->length = 1; + bshd->cursor = 1; + BShellEnvProcessInput(bshd, 'C'); + BShellEnvProcessInput(bshd, 'D'); + } +}; + +HWTEST_F(ParamShellUnitTest, Init_TestInitParamShell_001, TestSize.Level1) +{ + ParamShellUnitTest test; + test.TestInitParamShell(); + test.TestParamShellCmd(); + test.TestParamShellCmd1(); +} +HWTEST_F(ParamShellUnitTest, Init_TestParamShellInput_001, TestSize.Level1) +{ + BShellHandle bshd = GetShellHandle(); + BShellEnvProcessInput(bshd, '\n'); + + BShellEnvProcessInput(bshd, 'l'); + bshd->length = BSH_COMMAND_MAX_LENGTH; + + BShellEnvProcessInput(bshd, 'l'); + bshd->length = sizeof('l'); + bshd->cursor = 0; + BShellEnvProcessInput(bshd, 's'); + BShellEnvProcessInput(bshd, '\n'); + + BShellEnvProcessInput(bshd, '\n'); // test bshd buff length is 0 + + int ret = BShellEnvRegisterKeyHandle(bshd, 'z', (BShellkeyHandle)(void*)0x409600); // 0x409600 construct address + EXPECT_EQ(ret, 0); +} +HWTEST_F(ParamShellUnitTest, Init_TestParamShellcmd_001, TestSize.Level1) +{ + ParamShellUnitTest test; + test.TestParamShellcmdEndkey(); + GetSystemCommitId(); + BShellEnvLoop(nullptr); + BShellEnvErrString(GetShellHandle(), 1); + BShellEnvOutputResult(GetShellHandle(), 1); +} +} // namespace init_ut diff --git a/test/unittest/param/param_stub.cpp b/test/unittest/param/param_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00dfb6138566b12a61681af6706092dac82ddba7 --- /dev/null +++ b/test/unittest/param/param_stub.cpp @@ -0,0 +1,768 @@ +/* + * Copyright (c) 2021 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 "param_stub.h" +#include +#include +#include + +#include "begetctl.h" +#include "bootstage.h" +#include "init.h" +#include "init_log.h" +#include "init_param.h" +#ifndef OHOS_LITE +#include "init_mount.h" +#endif +#include "hookmgr.h" +#include "parameter.h" +#include "param_manager.h" +#include "param_security.h" +#include "param_utils.h" +#include "init_group_manager.h" +#include "init_module_engine.h" +#ifdef PARAM_LOAD_CFG_FROM_CODE +#include "param_cfg.h" +#endif +#include "ueventd.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +static int g_stubResult[STUB_MAX] = { 0 }; +static int g_testRandom = 2; // 2 is test random + +static int g_testPermissionResult = DAC_RESULT_PERMISSION; +void SetTestPermissionResult(int result) +{ + g_testPermissionResult = result; +} + +static const char *selinuxLabels[][2] = { + {"test.permission.read", "u:object_r:test_read:s0"}, + {"test.permission.write", "u:object_r:test_write:s0"}, + {"test.permission.watch", "u:object_r:test_watch:s0"}, +}; + +static int TestGenHashCode(const char *buff) +{ + int code = 0; + size_t buffLen = strlen(buff); + for (size_t i = 0; i < buffLen; i++) { + code += buff[i] - 'A'; + } + return code; +} + +static void TestSetSelinuxLogCallback(void) {} + +static int TestSetParamCheck(const char *paraName, const char *context, const SrcInfo *info) +{ + BEGET_LOGI("TestSetParamCheck %s result %d", paraName, g_testPermissionResult); + return g_testPermissionResult; +} + +static const char *TestGetParamLabel(const char *paraName) +{ + BEGET_LOGI("TestGetParamLabel %s", paraName); + if (paraName == nullptr) { + return nullptr; + } + for (size_t i = 0; i < ARRAY_LENGTH(selinuxLabels); i++) { + if (strncmp(selinuxLabels[i][0], paraName, strlen(selinuxLabels[i][0])) == 0) { + return selinuxLabels[i][1]; + } + } + int code = TestGenHashCode(paraName); + code = code % (ARRAY_LENGTH(selinuxLabels)); + return selinuxLabels[code][1]; +} + +static int32_t TestGetSelinuxLabelIndex(const char *paraName) +{ + for (size_t i = 0; i < ARRAY_LENGTH(selinuxLabels); i++) { + if (strncmp(selinuxLabels[i][0], paraName, strlen(selinuxLabels[i][0])) == 0) { + return i; + } + } + int code = TestGenHashCode(paraName); + code = code % (ARRAY_LENGTH(selinuxLabels)); + return code; +} + +static const char *g_forbidReadParamName[] = { + "ohos.servicectrl.", + // "test.permission.write", +}; +static int TestReadParamCheck(const char *paraName) +{ + // forbid to read ohos.servicectrl. + for (size_t i = 0; i < ARRAY_LENGTH(g_forbidReadParamName); i++) { + if (strncmp(paraName, g_forbidReadParamName[i], strlen(g_forbidReadParamName[i])) == 0) { + return 1; + } + } + return g_testPermissionResult; +} +static void TestDestroyParamList(ParamContextsList **list) +{ +#ifdef PARAM_SUPPORT_SELINUX + ParamContextsList *head = *list; + while (head != nullptr) { + ParamContextsList *next = head->next; + free((void *)head->info.paraName); + free((void *)head->info.paraContext); + free(head); + head = next; + } +#endif +} +static ParamContextsList *TestGetParamList(void) +{ +#ifdef PARAM_SUPPORT_SELINUX + ParamContextsList *head = (ParamContextsList *)malloc(sizeof(ParamContextsList)); + BEGET_ERROR_CHECK(head != nullptr, return nullptr, "Failed to alloc ParamContextsList"); + head->info.paraName = strdup(selinuxLabels[0][0]); + head->info.paraContext = strdup(selinuxLabels[0][1]); + head->info.index = 0; + head->next = nullptr; + for (size_t i = 1; i < ARRAY_LENGTH(selinuxLabels); i++) { + ParamContextsList *node = (ParamContextsList *)malloc(sizeof(ParamContextsList)); + BEGET_ERROR_CHECK(node != nullptr, TestDestroyParamList(&head); + return nullptr, "Failed to alloc ParamContextsList"); + node->info.paraName = strdup(selinuxLabels[i][0]); + node->info.paraContext = strdup(selinuxLabels[i][1]); + node->info.index = i; + node->next = head->next; + head->next = node; + } + // test error, no node paraName + ParamContextsList *node = (ParamContextsList *)malloc(sizeof(ParamContextsList)); + BEGET_ERROR_CHECK(node != nullptr, TestDestroyParamList(&head); + return nullptr, "Failed to alloc ParamContextsList"); + node->info.paraName = nullptr; + node->info.paraContext = strdup(selinuxLabels[0][1]); + node->next = head->next; + head->next = node; + + // test error, no node paraContext + node = (ParamContextsList *)malloc(sizeof(ParamContextsList)); + BEGET_ERROR_CHECK(node != nullptr, TestDestroyParamList(&head); + return nullptr, "Failed to alloc ParamContextsList"); + node->info.paraName = strdup(selinuxLabels[0][0]); + node->info.paraContext = nullptr; + node->next = head->next; + head->next = node; + + // test error, repeat + node = (ParamContextsList *)malloc(sizeof(ParamContextsList)); + BEGET_ERROR_CHECK(node != nullptr, TestDestroyParamList(&head); + return nullptr, "Failed to alloc ParamContextsList"); + node->info.paraName = strdup(selinuxLabels[0][0]); + node->info.paraContext = strdup(selinuxLabels[0][1]); + node->info.index = 0; + node->next = head->next; + head->next = node; + return head; +#else + return nullptr; +#endif +} + +void TestSetSelinuxOps(void) +{ +#ifdef PARAM_SUPPORT_SELINUX + SelinuxSpace *selinuxSpace = &GetParamWorkSpace()->selinuxSpace; + selinuxSpace->setSelinuxLogCallback = TestSetSelinuxLogCallback; + selinuxSpace->setParamCheck = TestSetParamCheck; + selinuxSpace->getParamLabel = TestGetParamLabel; + selinuxSpace->readParamCheck = TestReadParamCheck; + selinuxSpace->getParamList = TestGetParamList; + selinuxSpace->destroyParamList = TestDestroyParamList; + selinuxSpace->getParamLabelIndex = TestGetSelinuxLabelIndex; +#endif +} + +void TestSetParamCheckResult(const char *prefix, uint16_t mode, int result) +{ + ParamAuditData auditData = {}; + auditData.name = prefix; + auditData.dacData.gid = 202; // 202 test dac gid + auditData.dacData.uid = 202; // 202 test dac uid + auditData.dacData.mode = mode; + AddSecurityLabel(&auditData); + SetTestPermissionResult(result); +} + +void CreateTestFile(const char *fileName, const char *data) +{ + CheckAndCreateDir(fileName); + PARAM_LOGV("PrepareParamTestData for %s", fileName); + FILE *tmpFile = fopen(fileName, "wr"); + if (tmpFile != nullptr) { + fprintf(tmpFile, "%s", data); + (void)fflush(tmpFile); + fclose(tmpFile); + } +} +static void PrepareUeventdcfg(void) +{ + const char *ueventdcfg = "[device]\n" + "/dev/test 0666 1000 1000\n" + "[device]\n" + "/dev/test1 0666 1000\n" + "[device]\n" + "/dev/test2 0666 1000 1000 1000 1000\n" + "[sysfs]\n" + "/dir/to/nothing attr_nowhere 0666 1000 1000\n" + "[sysfs]\n" + " #/dir/to/nothing attr_nowhere 0666\n" + "[sysfs\n" + "/dir/to/nothing attr_nowhere 0666\n" + "[firmware]\n" + "/etc\n" + "[device]\n" + "/dev/testbinder 0666 1000 1000 const.dev.binder\n" + "[device]\n" + "/dev/testbinder1 0666 1000 1000 const.dev.binder\n" + "[device]\n" + "/dev/testbinder2 0666 1000 1000 const.dev.binder\n" + "[device]\n" + "/dev/testbinder3 0666 1000 1000 const.dev.binder\n"; + mkdir("/data/ueventd_ut", S_IRWXU | S_IRWXG | S_IRWXO); + CreateTestFile(STARTUP_INIT_UT_PATH"/ueventd_ut/valid.config", ueventdcfg); +} +static void PrepareModCfg(void) +{ + const char *modCfg = "testinsmod"; + CreateTestFile(STARTUP_INIT_UT_PATH"/test_insmod", modCfg); +} +static void PrepareInnerKitsCfg() +{ + const char *innerKitsCfg = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/system /system " + "ext4 ro,barrier=1 wait\n" + "/dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor /vendor " + "ext4 ro,barrier=1 wait\n" + "/dev/block/platform/soc/10100000.himci.eMMC/by-name/hos " + "/hos ntfs nosuid,nodev,noatime,barrier=1,data=ordered wait\n" + "/dev/block/platform/soc/10100000.himci.eMMC/by-name/userdata /data ext4 " + "nosuid,nodev,noatime,barrier=1,data=ordered,noauto_da_alloc " + "wait,reservedsize=104857600\n" + " aaaa\n" + "aa aa\n" + "aa aa aa\n" + "aa aa aa aa\n"; + const char *fstabRequired = "# fstab file.\n" + "# \n" + "/dev/block/platform/fe310000.sdhci/by-name/testsystem /usr ext4 ro,barrier=1 wait,required,nofail\n" + "/dev/block/platform/fe310000.sdhci/by-name/testvendor /vendor ext4 ro,barrier=1 wait,required\n" + "/dev/block/platform/fe310000.sdhci/by-name/testuserdata1 /data f2fs noatime,nosuid,nodev wait,check,quota\n" + "/dev/block/platform/fe310000.sdhci/by-name/testuserdata2 /data ext4 noatime,fscrypt=xxx wait,check,quota\n" + "/dev/block/platform/fe310000.sdhci/by-name/testmisc /misc none none wait,required"; + mkdir("/data/init_ut/mount_unitest/", S_IRWXU | S_IRWXG | S_IRWXO); + CreateTestFile(STARTUP_INIT_UT_PATH"/mount_unitest/ReadFstabFromFile1.fstable", innerKitsCfg); + CreateTestFile(STARTUP_INIT_UT_PATH"/etc/fstab.required", fstabRequired); + CreateTestFile(STARTUP_INIT_UT_PATH"/system/etc/fstab.required", fstabRequired); +} +static void PrepareGroupTestCfg() +{ + const char *data = "{" + "\"jobs\": [\"param:job1\", \"param:job2\", \"param:job4\"]," + "\"services\": [\"service:service1\", \"service:service3\", \"service:service2\"]," + "\"groups\": [\"subsystem.xxx1.group\", \"subsystem.xxx2.group\", \"subsystem.xxx4.group\"]" + "}"; + const char *xxx1 = "{" + "\"groups\": [\"subsystem.xxx11.group\"" + "}"; + const char *xxx11 = "{" + "\"groups\": [\"subsystem.xxx12.group\"" + "}"; + const char *xxx12 = "{" + "\"groups\": [\"subsystem.xxx13.group\"" + "}"; + const char *xxx13 = "{" + "\"groups\": [\"subsystem.xxx14.group\"" + "}"; + const char *xxx14 = "{" + "\"groups\": [\"subsystem.xxx11.group\"" + "}"; + CreateTestFile(GROUP_DEFAULT_PATH "/device.boot.group.cfg", data); + CreateTestFile(GROUP_DEFAULT_PATH "/subsystem.xxx1.group.cfg", xxx1); + CreateTestFile(GROUP_DEFAULT_PATH "/subsystem.xxx11.group.cfg", xxx11); + CreateTestFile(GROUP_DEFAULT_PATH "/subsystem.xxx12.group.cfg", xxx12); + CreateTestFile(GROUP_DEFAULT_PATH "/subsystem.xxx13.group.cfg", xxx13); + CreateTestFile(GROUP_DEFAULT_PATH "/subsystem.xxx14.group.cfg", xxx14); +} +static bool IsDir(const std::string &path) +{ + struct stat st {}; + if (stat(path.c_str(), &st) < 0) { + return false; + } + return S_ISDIR(st.st_mode); +} +static bool DeleteDir(const std::string &path) +{ + auto pDir = std::unique_ptr(opendir(path.c_str()), closedir); + if (pDir == nullptr) { + return false; + } + + struct dirent *dp = nullptr; + while ((dp = readdir(pDir.get())) != nullptr) { + std::string currentName(dp->d_name); + if (currentName[0] != '.') { + std::string tmpName(path); + tmpName.append("/" + currentName); + if (IsDir(tmpName)) { + DeleteDir(tmpName); + } + remove(tmpName.c_str()); + } + } + if (remove(path.c_str()) != 0) { + return false; + } + return true; +} +static void LoadParamFromCfg(void) +{ +#ifdef PARAM_LOAD_CFG_FROM_CODE + for (size_t i = 0; i < ARRAY_LENGTH(g_paramDefCfgNodes); i++) { + PARAM_LOGI("InitParamClient name %s = %s", g_paramDefCfgNodes[i].name, g_paramDefCfgNodes[i].value); + uint32_t dataIndex = 0; + int ret = WriteParam(g_paramDefCfgNodes[i].name, g_paramDefCfgNodes[i].value, &dataIndex, 0); + PARAM_CHECK(ret == 0, continue, "Failed to set param %d name %s %s", + ret, g_paramDefCfgNodes[i].name, g_paramDefCfgNodes[i].value); + } +#endif +} + +static const char *g_triggerData = "{" + "\"jobs\" : [{" + " \"name\" : \"early-init\"," + " \"cmds\" : [" + " \" write '/proc/sys/kernel/sysrq 0'\"," + " \" load_persist_params \"," + " \" load_persist_params \"," + " \" # load_persist_params \"," + " \" restorecon /postinstall\"," + " \"mkdir /acct/uid\"," + " \"chown root system /dev/memcg/memory.pressure_level\"," + " \"chmod 0040 /dev/memcg/memory.pressure_level\"," + " \"mkdir /dev/memcg/apps/ 0755 system system\"," + " \"mkdir /dev/memcg/system 0550 system system\"," + " \"start ueventd\"," + " \"exec_start apexd-bootstrap\"," + " \"setparam sys.usb.config ${persist.sys.usb.config}\"" + " ]" + " }," + " {" + " \"name\" : \"param:trigger_test_1\"," + " \"condition\" : \"test.sys.boot_from_charger_mode=5\"," + " \"cmds\" : [" + " \"class_stop charger\"," + " \"trigger late-init\"" + " ]" + " }," + " {" + " \"name\" : \"param:trigger_test_2\"," + " \"condition\" : \"test.sys.boot_from_charger_mode=1 " + " || test.sys.boot_from_charger_mode=2 || test.sys.boot_from_charger_mode=3\"," + " \"cmds\" : [" + " \"class_stop charger\"," + " \"trigger late-init\"" + " ]" + " }," + " {" + " \"name\" : \"load_persist_params_action\"," + " \"cmds\" : [" + " \"load_persist_params\"," + " \"start logd\"," + " \"start logd-reinit\"" + " ]" + " }," + " {" + " \"name\" : \"firmware_mounts_complete\"," + " \"cmds\" : [" + " \"rm /dev/.booting\"" + " ]" + " }" + "]" + "}"; + +void PrepareCmdLineData() +{ + const char *cmdLine = "bootgroup=device.boot.group earlycon=uart8250,mmio32,0xfe660000 " + "root=PARTUUID=614e0000-0000 rw rootwait rootfstype=ext4 console=ttyFIQ0 hardware=rk3568 " + "BOOT_IMAGE=/kernel init=/init default_boot_device=fe310000.sdhci bootslots=2 currentslot=1 initloglevel=2 " + "ohos.required_mount.system=" + "/dev/block/platform/fe310000.sdhci/by-name/system@/usr@ext4@ro,barrier=1@wait,required " + "ohos.required_mount.vendor=" + "/dev/block/platform/fe310000.sdhci/by-name/vendor@/vendor@ext4@ro,barrier=1@wait,required " + "ohos.required_mount.misc=" + "/dev/block/platform/fe310000.sdhci/by-name/misc@none@none@none@wait,required ohos.boot.eng_mode=on "; + CreateTestFile(BOOT_CMD_LINE, cmdLine); +} + +static void PrepareAreaSizeFile(void) +{ + const char *ohosParamSize = "default_param=1024\n" + "hilog_param=2048\n" + "const_product_param=2048\n" + "startup_param=20480\n" + "persist_param=2048\n" + "const_param=20480\n" + "test_watch=102400\n" + "test_write=102400\n" + "const_param***=20480\n" + "persist_sys_param=2048\n" + "test_write=102400\n"; + CreateTestFile(PARAM_AREA_SIZE_CFG, ohosParamSize); +} + +static void PrepareTestGroupFile(void) +{ + std::string groupData = "root:x:0:\n" + "bin:x:2:\n" + "system:x:1000:\n" + "log:x:1007:\n" + "deviceinfo:x:1102:\n" + "samgr:x:5555:\n" + "hdf_devmgr:x:3044:\n\n" + "power_host:x:3025:\n" + "servicectrl:x:1050:root, shell,system, samgr, hdf_devmgr \n" + "powerctrl:x:1051:root, shell,system, update,power_host\r\n" + "bootctrl:x:1052:root,shell,system\n" + "deviceprivate:x:1053:root,shell,system,samgr,hdf_devmgr,deviceinfo," + "dsoftbus,dms,account,useriam,access_token,device_manager,foundation,dbms,deviceauth,huks_server\n" + "hiview:x:1201:\n" + "hidumper_service:x:1212:\n" + "shell:x:2000:\n" + "cache:x:2001:\n" + "net_bw_stats:x:3006:\n"; + + CreateTestFile(STARTUP_INIT_UT_PATH "/etc/group", groupData.c_str()); +} + +static void PrepareDacData() +{ + // for dac + std::string dacData = "ohos.servicectrl. = system:servicectrl:0775 \n"; + dacData += "startup.service.ctl. = system:servicectrl:0775:int\n"; + dacData += "test.permission. = root:root:0770\n"; + dacData += "test.permission.read. = root:root:0774\n"; + dacData += "test.permission.write.= root:root:0772\n"; + dacData += "test.permission.watcher. = root:root:0771\n"; + dacData += "test.test1. = system:test1:0771\n"; + dacData += "test.test2.watcher. = test2:root:0771\n"; + dacData += "test.type.int. = root:root:0777:int\n"; + dacData += "test.type.bool. = root:root:0777:bool\n"; + dacData += "test.type.string. = root:root:0777\n"; + dacData += "test.invalid.int. = root:root:\n"; + dacData += "test.invalid.int. = root::\n"; + dacData += "test.invalid.int. = ::\n"; + dacData += "test.invalid.int. = \n"; + dacData += "test.invalid.int. \n"; + CreateTestFile(STARTUP_INIT_UT_PATH "/system/etc/param/ohos.para.dac", dacData.c_str()); + CreateTestFile(STARTUP_INIT_UT_PATH "/system/etc/param/ohos.para.dac_1", dacData.c_str()); +} + +static int TestHook(const HOOK_INFO *hookInfo, void *cookie) +{ + return 0; +} + +void PrepareInitUnitTestEnv(void) +{ + static int evnOk = 0; + if (evnOk) { + return; + } + printf("PrepareInitUnitTestEnv \n"); +#ifdef PARAM_SUPPORT_SELINUX + RegisterSecuritySelinuxOps(nullptr, 0); +#endif + +#ifndef OHOS_LITE + InitAddGlobalInitHook(0, TestHook); + InitAddPreParamServiceHook(0, TestHook); + InitAddPreParamLoadHook(0, TestHook); + InitAddPreCfgLoadHook(0, TestHook); + InitAddPostCfgLoadHook(0, TestHook); + InitAddPostPersistParamLoadHook(0, TestHook); +#endif + // read default parameter from system + LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL); + LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL); + LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD); + + // read ut parameters + LoadDefaultParams(STARTUP_INIT_UT_PATH "/system/etc/param/ohos_const", LOAD_PARAM_NORMAL); + LoadDefaultParams(STARTUP_INIT_UT_PATH "/vendor/etc/param", LOAD_PARAM_NORMAL); + LoadDefaultParams(STARTUP_INIT_UT_PATH "/system/etc/param", LOAD_PARAM_ONLY_ADD); + LoadParamsFile(STARTUP_INIT_UT_PATH "/system/etc/param", LOAD_PARAM_ONLY_ADD); + LoadParamFromCfg(); + + int32_t loglevel = GetIntParameter("persist.init.debug.loglevel", INIT_ERROR); + SetInitLogLevel((InitLogLevel)loglevel); + + // for test int get + SystemWriteParam("test.int.get", "-101"); + SystemWriteParam("test.uint.get", "101"); + SystemWriteParam("test.string.get", "101"); + SystemWriteParam("test.bool.get.true", "true"); + SystemWriteParam("test.bool.get.false", "false"); + + evnOk = 1; +} + +int TestCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode) +{ + // DAC_RESULT_FORBIDED + return g_testPermissionResult; +} + +int TestFreeLocalSecurityLabel(ParamSecurityLabel *srcLabel) +{ + return 0; +} + +void SetStubResult(STUB_TYPE type, int result) +{ + g_stubResult[type] = result; +} + +#ifndef OHOS_LITE +static void TestBeforeInit(void) +{ + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + EXPECT_NE(paramSpace, nullptr); + InitParamService(); + CloseParamWorkSpace(); + paramSpace = GetParamWorkSpace(); + EXPECT_NE(paramSpace, nullptr); + + // test read cmdline + Fstab *stab = LoadRequiredFstab(); + ReleaseFstab(stab); +} +#endif + +static pid_t g_currPid = 0; +static __attribute__((constructor(101))) void ParamTestStubInit(void) +{ + g_currPid = getpid(); + printf("Init unit test start %u \n", g_currPid); + EnableInitLog(INIT_INFO); + InitParseGroupCfg(); + // prepare data + mkdir(STARTUP_INIT_UT_PATH, S_IRWXU | S_IRWXG | S_IRWXO); + CheckAndCreateDir(STARTUP_INIT_UT_PATH MODULE_LIB_NAME "/autorun/"); + int cmdIndex = 0; + (void)GetMatchCmd("copy ", &cmdIndex); + DoCmdByIndex(cmdIndex, MODULE_LIB_NAME"/libbootchart.z.so " + STARTUP_INIT_UT_PATH MODULE_LIB_NAME "/libbootchart.z.so", nullptr); + DoCmdByIndex(cmdIndex, MODULE_LIB_NAME"/libbootchart.z.so " + STARTUP_INIT_UT_PATH MODULE_LIB_NAME "/autorun/libbootchart.z.so", nullptr); + PrepareUeventdcfg(); + PrepareInnerKitsCfg(); + PrepareModCfg(); + PrepareGroupTestCfg(); + PrepareDacData(); + CreateTestFile(STARTUP_INIT_UT_PATH"/trigger_test.cfg", g_triggerData); + PrepareAreaSizeFile(); + PrepareTestGroupFile(); + PrepareCmdLineData(); + TestSetSelinuxOps(); + + PARAM_LOGI("TestSetSelinuxOps \n"); +#ifndef OHOS_LITE + TestBeforeInit(); +#endif +#ifndef __LITEOS_A__ + SystemInit(); +#endif + PARAM_LOGI("SystemConfig \n"); + SystemConfig(NULL); + PrepareInitUnitTestEnv(); +} + +__attribute__((destructor)) static void ParamTestStubExit(void) +{ + PARAM_LOGI("ParamTestStubExit %u %u \n", g_currPid, getpid()); + if (g_currPid != getpid()) { + return; + } +#ifndef OHOS_LITE + StopParamService(); + + HookMgrExecute(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, nullptr, nullptr); + CloseUeventConfig(); + CloseServiceSpace(); + demoExit(); + LE_CloseLoop(LE_GetDefaultLoop()); + HookMgrDestroy(GetBootStageHookMgr()); +#endif +} + +#ifdef OHOS_LITE +void __attribute__((weak))LE_DoAsyncEvent(const LoopHandle loopHandle, const TaskHandle taskHandle) +{ +} + +const char* HalGetSerial(void) +{ + static const char *serial = "1234567890"; + return serial; +} +#endif + +int __attribute__((weak))SprintfStub(char *buffer, size_t size, const char *fmt, ...) +{ + int len = -1; + va_list vargs; + va_start(vargs, fmt); + len = vsnprintf_s(buffer, size, size - 1, fmt, vargs); + va_end(vargs); + return len; +} + +int __attribute__((weak))MountStub(const char* source, const char* target, + const char* filesystemtype, unsigned long mountflags, const void * data) +{ + return g_stubResult[STUB_MOUNT]; +} + +int __attribute__((weak))UmountStub(const char *target) +{ + return 0; +} + +int __attribute__((weak))Umount2Stub(const char *target, int flags) +{ + return 0; +} + +int __attribute__((weak))SymlinkStub(const char * oldpath, const char * newpath) +{ + return 0; +} + +int PrctlStub(int option, ...) +{ + if (option == PR_SET_SECUREBITS) { + static int count = 0; + count++; + return (count % g_testRandom == 1) ? 0 : -1; + } + if (option == PR_CAP_AMBIENT) { + static int count1 = 0; + count1++; + return (count1 % g_testRandom == 1) ? 0 : -1; + } + return 0; +} + +int ExecvStub(const char *pathname, char *const argv[]) +{ + printf("ExecvStub %s \n", pathname); + return 0; +} + +int LchownStub(const char *pathname, uid_t owner, gid_t group) +{ + return 0; +} + +int KillStub(pid_t pid, int signal) +{ + return 0; +} + +int ExecveStub(const char *pathname, char *const argv[], char *const envp[]) +{ + printf("ExecveStub %s \n", pathname); + return 0; +} + +int LoadPolicy() +{ + return 0; +} + +static int g_selinuxOptResult = 0; +int setcon(const char *name) +{ + g_selinuxOptResult++; + return g_selinuxOptResult % g_testRandom; +} + +int RestoreconRecurse(const char *name) +{ + g_selinuxOptResult++; + return g_selinuxOptResult % g_testRandom; +} + +int setexeccon(const char *name) +{ + g_selinuxOptResult++; + return g_selinuxOptResult % g_testRandom; +} + +int setsockcreatecon(const char *name) +{ + g_selinuxOptResult++; + return g_selinuxOptResult % g_testRandom; +} + +int setfilecon(const char *name, const char *content) +{ + g_selinuxOptResult++; + return g_selinuxOptResult % g_testRandom; +} + +ParamLabelIndex *TestGetParamLabelIndex(const char *name) +{ + static ParamLabelIndex labelIndex = {0}; + uint32_t index = 0; + ParamWorkSpace *paramWorkspace = GetParamWorkSpace(); + if (paramWorkspace == nullptr) { + return &labelIndex; + } +#ifdef PARAM_SUPPORT_SELINUX + if (paramWorkspace->selinuxSpace.getParamLabelIndex == nullptr) { + return &labelIndex; + } + index = (uint32_t)paramWorkspace->selinuxSpace.getParamLabelIndex(name) + WORKSPACE_INDEX_BASE; + if (index >= paramWorkspace->maxLabelIndex) { + return &labelIndex; + } +#endif + labelIndex.workspace = paramWorkspace->workSpace[index]; + PARAM_CHECK(labelIndex.workspace != nullptr, return nullptr, "Invalid workSpace"); + labelIndex.selinuxLabelIndex = labelIndex.workspace->spaceIndex; + (void)FindTrieNode(paramWorkspace->workSpace[0], name, strlen(name), &labelIndex.dacLabelIndex); + return &labelIndex; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif diff --git a/test/unittest/param/param_stub.h b/test/unittest/param/param_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..0beeed841d8d2c8fbd583cd453e9cdd6b17caa5d --- /dev/null +++ b/test/unittest/param/param_stub.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 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 PARAM_TEST_STUB +#define PARAM_TEST_STUB +#include +#include +#include +#include +#include +#include + +#ifndef OHOS_LITE +#include "init_eng.h" +#include "init_context.h" +#endif +#include "param_manager.h" +#include "param_security.h" +#include "param_utils.h" +#include "securec.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#ifdef SUPPORT_64BIT +#define MODULE_LIB_NAME "/system/lib64/init" +#else +#define MODULE_LIB_NAME "/system/lib/init" +#endif + +#define DEFAULT_ERROR (-65535) + +#ifndef PARAM_SUPPORT_SELINUX +typedef struct ParameterNode { + const char *paraName; + const char *paraContext; + int index; +} ParameterNode; + +typedef struct ParamContextsList { + struct ParameterNode info; + struct ParamContextsList *next; +} ParamContextsList; + +typedef struct SrcInfo { + int sockFd; + struct ucred uc; +} SrcInfo; +#endif + +void CreateTestFile(const char *fileName, const char *data); +void PrepareInitUnitTestEnv(void); +void TestSetSelinuxOps(void); +void SetTestPermissionResult(int result); +void TestSetParamCheckResult(const char *prefix, uint16_t mode, int result); +int TestCheckParamPermission(const ParamLabelIndex *labelIndex, + const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode); +int TestFreeLocalSecurityLabel(ParamSecurityLabel *srcLabel); + +typedef enum { + STUB_SPRINTF, + STUB_MOUNT, + STUB_MKNODE, + STUB_EXECV, + STUB_UMOUNT, + STUB_MAX +} STUB_TYPE; +void SetStubResult(STUB_TYPE type, int result); +void PrepareCmdLineData(); +ParamLabelIndex *TestGetParamLabelIndex(const char *name); + +// for test +void HandleUevent(const struct Uevent *uevent); + +#ifndef OHOS_LITE +void EngineerOverlay(void); +void DebugFilesOverlay(const char *source, const char *target); +void BindMountFile(const char *source, const char *target); +void MountEngPartitions(void); +void BuildMountCmd(char *buffer, size_t len, const char *mp, const char *dev, const char *fstype); +bool IsFileExistWithType(const char *file, FileType type); + +int DoRoot_(const char *jobName, int type); +int DoRebootShutdown(int id, const char *name, int argc, const char **argv); +int DoRebootFlashed(int id, const char *name, int argc, const char **argv); +int DoRebootOther(int id, const char *name, int argc, const char **argv); + +//remount_overlay +bool MntNeedRemount(const char *mnt); +bool IsSkipRemount(const struct mntent mentry); +int ExecCommand(int argc, char **argv); +int GetDevSize(const char *fsBlkDev, uint64_t *devSize); +int FormatExt4(const char *fsBlkDev, const char *fsMntPoint); +void OverlayRemountPre(const char *mnt); +void OverlayRemountPost(const char *mnt); +bool DoRemount(struct mntent *mentry); +bool DirectoryExists(const char *path); +bool DoSystemRemount(struct mntent *mentry); + +//remount +int Modem2Exchange(const char *modemPath, const char *exchangePath); +int Exchange2Modem(const char *modemPath, const char *exchangePath); + +SubInitContext *GetSubInitContext(InitContextType type); +uint64_t LookupErofsEnd(const char *dev); +void AllocDmName(const char *name, char *nameRofs, const uint64_t nameRofsLen, + char *nameExt4, const uint64_t nameExt4Len); +#endif +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // PARAM_TEST_STUB_ diff --git a/test/unittest/param/param_unittest.cpp b/test/unittest/param/param_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1991ebc4cc468821f74284f557a3c253e3615a8 --- /dev/null +++ b/test/unittest/param/param_unittest.cpp @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2021 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 "init_param.h" +#include "param_base.h" +#include "param_message.h" +#include "param_stub.h" +#include "param_init.h" +#include "trigger_manager.h" +#include "param_utils.h" +#include "param_osadp.h" +#include "param_manager.h" +#include "sys_param.h" + +using namespace testing::ext; +using namespace std; + +extern "C" { +void ParamWorBaseLog(InitLogLevel logLevel, uint32_t domain, const char *tag, const char *fmt, ...); +static void OnClose(const TaskHandle taskHandle) +{ +} +} + +static int CheckServerParamValue(const char *name, const char *expectValue) +{ + char tmp[PARAM_BUFFER_SIZE] = {0}; + u_int32_t len = sizeof(tmp); + SystemReadParam(name, tmp, &len); + printf("CheckParamValue name %s value: \'%s\' expectValue:\'%s\' \n", name, tmp, expectValue); + EXPECT_GE((int)strlen(tmp), 0); + if (expectValue != nullptr) { + EXPECT_EQ(strcmp(tmp, expectValue), 0); + } + return 0; +} + +namespace init_ut { +class ParamUnitTest : public ::testing::Test { +public: + ParamUnitTest() {} + virtual ~ParamUnitTest() {} + + static void SetUpTestCase(void) {} + void SetUp() {} + void TearDown() {} + void TestBody() {} + + int TestSetParams(const char *params[][1 + 1], int num) + { + for (int i = 0; i < num; i++) { + SystemWriteParam(params[i][0], params[i][1]); + } + + // check + for (int i = 0; i < num; i++) { + CheckServerParamValue(params[i][0], params[i][1]); + } + + for (int i = num - 1; i >= 0; i--) { + CheckServerParamValue(params[i][0], params[i][1]); + } + return 0; + } + + int TestAddSecurityLabel1() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label1.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + uint32_t labelIndex = 0; + SystemWriteParam(name, value); + // get root + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + (void)FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ(node->gid, DAC_DEFAULT_GROUP); + return 0; + } + + // 添加一个label,最长匹配到这个节点 + int TestAddSecurityLabel2() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label2.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + ParamAuditData auditData = {}; + auditData.name = "label2.test.aaa"; + auditData.dacData.gid = 202; // 202 test dac gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + uint32_t labelIndex = 0; + AddSecurityLabel(&auditData); + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + (void)FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ(node->gid, auditData.dacData.gid); + return 0; + } + + // 添加一个label,最长匹配到最后一个相同节点 + int TestAddSecurityLabel3() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label3.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + ParamAuditData auditData = {}; + auditData.name = "label3.test.aaa"; + auditData.dacData.gid = 203; // 203 test gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + AddSecurityLabel(&auditData); + + auditData.name = "label3.test.aaa.bbb.ccc.dddd.eee.dddd"; + auditData.dacData.gid = 202; // 202 test dac gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + AddSecurityLabel(&auditData); + + uint32_t labelIndex = 0; + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + ParamTrieNode *paramNode = FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (paramNode == nullptr || node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ((int)node->gid, 203); // 203 test gid + return 0; + } + + // 添加一个label,完全匹配 + int TestAddSecurityLabel4() + { +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) + ResetParamSecurityLabel(); +#endif + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label4.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + ParamAuditData auditData = {}; + auditData.name = "label4.test.aaa.bbb.ccc.dddd.eee"; + auditData.dacData.gid = 203; // 203 test gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + uint32_t labelIndex = 0; + AddSecurityLabel(&auditData); + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + ParamTrieNode *paramNode = FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (paramNode == nullptr || node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ(node->gid, auditData.dacData.gid); + return 0; + } + + void TestBufferValue(char *buffer, uint32_t len) + { + const int printBase = 10; + for (uint32_t index = 0; index <= len; index++) { + buffer[index] = '0' + index % printBase; + if (index != 0 && index % printBase == 0) { + buffer[index] = '.'; + } + } + buffer[len] = '\0'; + } + + int TestNameIsValid() + { + char buffer[PARAM_BUFFER_SIZE]; + // set name length = 127 + TestBufferValue(buffer, PARAM_NAME_LEN_MAX - 1); + int ret = SystemWriteParam(buffer, "1111"); + EXPECT_EQ(ret, 0); + TestBufferValue(buffer, PARAM_NAME_LEN_MAX); + ret = SystemWriteParam(buffer, "1111"); + EXPECT_NE(ret, 0); + TestBufferValue(buffer, PARAM_NAME_LEN_MAX + 1); + ret = SystemWriteParam(buffer, "1111"); + EXPECT_NE(ret, 0); + + // 保存一个只读的属性,大于最大值 + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("const.test_readonly.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_EQ(ret, 0); + + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX + 1); + ret = SystemWriteParam("const.test_readonly.aaaaaaaaaaaaaaaaaa.fffffffffffffffffff", buffer); + EXPECT_EQ(ret, 0); + + // 更新只读项目 + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("const.test_readonly.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + + // 写普通属性 + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("test.bigvalue.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_EQ(ret, 0); + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX + 1); + ret = SystemWriteParam("test.bigvalue.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + + // invalid name + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("test.invalidname..fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + ret = SystemWriteParam("test.invalidname.%fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + ret = SystemWriteParam("test.invalidname.$fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + return 0; + } + + int TestParamTraversal() + { + char value[PARAM_BUFFER_SIZE + PARAM_BUFFER_SIZE] = {0}; + SystemTraversalParameter( + "", + [](ParamHandle handle, void *cookie) { + SystemGetParameterName(handle, (char *)cookie, PARAM_BUFFER_SIZE); + u_int32_t len = PARAM_BUFFER_SIZE; + SystemGetParameterValue(handle, ((char *)cookie) + PARAM_BUFFER_SIZE, &len); + printf("$$$$$$$$Param %s=%s \n", (char *)cookie, ((char *)cookie) + PARAM_BUFFER_SIZE); + }, + (void *)value); + return 0; + } + + int TestUpdateParam(const char *name, const char *value) + { + SystemWriteParam(name, value); + SystemWriteParam(name, value); + SystemWriteParam(name, value); + SystemWriteParam(name, value); + CheckServerParamValue(name, value); + return 0; + } + + int TestPersistParam() + { + ParamAuditData auditData = {}; + auditData.name = "persist."; + auditData.dacData.gid = 0; + auditData.dacData.uid = 0; + auditData.dacData.mode = 0777; // 0777 test mode + AddSecurityLabel(&auditData); + + LoadPersistParams(); + SystemWriteParam("persist.111.ffff.bbbb.cccc.dddd.eeee", "1101"); + SystemWriteParam("persist.111.aaaa.bbbb.cccc.dddd.eeee", "1102"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.eeee", "1103"); + CheckServerParamValue("persist.111.bbbb.cccc.dddd.eeee", "1103"); + + SystemWriteParam("persist.111.cccc.bbbb.cccc.dddd.eeee", "1104"); + SystemWriteParam("persist.111.eeee.bbbb.cccc.dddd.eeee", "1105"); + CheckServerParamValue("persist.111.ffff.bbbb.cccc.dddd.eeee", "1101"); + SystemWriteParam("persist.111.ffff.bbbb.cccc.dddd.eeee", "1106"); + CheckServerParamValue("persist.111.ffff.bbbb.cccc.dddd.eeee", "1106"); + sleep(1); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1107", "1107"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1108", "1108"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1109", "1108"); + sleep(1); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1110", "1108"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1111", "1108"); + TimerCallbackForSave(nullptr, nullptr); + LoadPersistParams(); + return 0; + } + + int TestPrivatePersistParam() + { + LoadPrivatePersistParams(); + SystemWriteParam("persist.test.111.aaa.bbb.ccc", "111"); + SystemWriteParam("persist.test.222.aaa.bbb.ccc", "222"); + SystemWriteParam("persist.test.333.aaa.bbb.ccc", "333"); + CheckServerParamValue("persist.test.333.aaa.bbb.ccc", "333"); + sleep(1); + TimerCallbackForSave(nullptr, nullptr); + LoadPrivatePersistParams(); + return 0; + } + + int TestDumpParamMemory() + { + SystemDumpParameters(1, -1, nullptr); + return 0; + } + + uint32_t GetWorkSpaceIndex(const char *name) + { +#ifdef PARAM_SUPPORT_SELINUX + ParamWorkSpace *paramSpace = GetParamWorkSpace(); + PARAM_CHECK(paramSpace != nullptr, return (uint32_t)-1, "Invalid paramSpace"); + return (paramSpace->selinuxSpace.getParamLabelIndex != nullptr) ? + paramSpace->selinuxSpace.getParamLabelIndex(name) + WORKSPACE_INDEX_BASE : (uint32_t)-1; +#else + return 0; +#endif + } +}; + +HWTEST_F(ParamUnitTest, Init_TestPersistParam_001, TestSize.Level0) +{ + ParamUnitTest test; + test.TestPersistParam(); +} + +HWTEST_F(ParamUnitTest, Init_TestPersistParam_002, TestSize.Level0) +{ + ParamUnitTest test; + test.TestPrivatePersistParam(); +} + +HWTEST_F(ParamUnitTest, Init_TestSetParam_001, TestSize.Level0) +{ + ParamUnitTest test; + const char *params[][2] = {{"111.2222", "1"}, + {"111.2222.3333", "2"}, + {"111.2222.3333.4444", "3"}, + {"111.2222.3333.4444.666", "4"}, + {"111.2222.3333.4444.666.777", "5"}}; + test.TestSetParams(params, 5); +} + +HWTEST_F(ParamUnitTest, Init_TestSetParam_002, TestSize.Level0) +{ + ParamUnitTest test; + const char *params[][2] = {{"111.2222.xxxx.xxx.xxx", "1_1"}, + {"111.2222.3333.xxx", "1_2"}, + {"111.2222.xxxx.3333.4444", "1_3"}, + {"111.2222.3333.xxxx.4444.666", "1_4"}, + {"111.2222.3333.4444.666.xxxxx.777", "1_5"}}; + test.TestSetParams(params, 5); + + const char *ctrlParams[][2] = {{"ctl.start.111.2222.xxxx.xxx.xxx", "2_1"}, + {"ctl.start.111.2222.3333.xxx", "2_2"}, + {"ctl.start.111.2222.xxxx.3333.4444", "2_3"}, + {"ctl.start.111.2222.3333.xxxx.4444.666", "2_4"}, + {"ctl.start.111.2222.3333.4444.666.xxxxx.777", "2_5"}}; + test.TestSetParams(ctrlParams, 5); + + const char *sysParams[][2] = {{"ohos.startup.powerctrl.111.2222.xxxx.xxx.xxx", "3_1"}, + {"ohos.startup.powerctrl.111.2222.3333.xxx", "3_2"}, + {"ohos.startup.powerctrl.111.2222.xxxx.3333.4444", "3_3"}, + {"ohos.startup.powerctrl.111.2222.3333.xxxx.4444.666", "3_4"}, + {"ohos.startup.powerctrl.111.2222.3333.4444.666.xxxxx.777", "3_5"}}; + test.TestSetParams(sysParams, 5); +} + +HWTEST_F(ParamUnitTest, Init_TestNameIsValid_001, TestSize.Level0) +{ + ParamUnitTest test; + test.TestNameIsValid(); +} + +HWTEST_F(ParamUnitTest, Init_TestParamValue_001, TestSize.Level0) +{ + // support empty string + const char *name = "test_readonly.dddddddddddddddddd.fffffffffffffffffff"; + int ret = SystemWriteParam(name, ""); + EXPECT_EQ(ret, 0); + CheckServerParamValue(name, ""); + ret = SystemWriteParam(name, "111111111"); + EXPECT_EQ(ret, 0); + CheckServerParamValue(name, "111111111"); + ret = SystemWriteParam(name, ""); + EXPECT_EQ(ret, 0); + CheckServerParamValue(name, ""); +} + +HWTEST_F(ParamUnitTest, Init_TestAddSecurityLabel_001, TestSize.Level0) +{ + ParamUnitTest test; + test.TestAddSecurityLabel1(); +} + +HWTEST_F(ParamUnitTest, Init_TestAddSecurityLabel_002, TestSize.Level0) +{ + ParamUnitTest test; + test.TestAddSecurityLabel2(); +} + +HWTEST_F(ParamUnitTest, Init_TestAddSecurityLabel_003, TestSize.Level0) +{ + ParamUnitTest test; + test.TestAddSecurityLabel3(); +} + +HWTEST_F(ParamUnitTest, Init_TestAddSecurityLabel_004, TestSize.Level0) +{ + ParamUnitTest test; + test.TestAddSecurityLabel4(); +} + +HWTEST_F(ParamUnitTest, Init_TestUpdateParam_001, TestSize.Level0) +{ + ParamUnitTest test; + test.TestUpdateParam("test.aaa.bbb.ccc.ddd", "100"); + test.TestUpdateParam("test.aaa.bbb.ccc.ddd", "101"); + test.TestUpdateParam("test.aaa.bbb.ccc.ddd", "102"); + test.TestUpdateParam("test.aaa.bbb.ccc.ddd", "103"); + test.TestUpdateParam("net.tcp.default_init_rwnd", "60"); +} + +HWTEST_F(ParamUnitTest, Init_TestParamTraversal_001, TestSize.Level0) +{ + ParamUnitTest test; + test.TestParamTraversal(); +} + +HWTEST_F(ParamUnitTest, Init_TestDumpParamMemory_001, TestSize.Level0) +{ + ParamUnitTest test; + test.TestDumpParamMemory(); +} + +HWTEST_F(ParamUnitTest, Init_TestLinuxRWLock_001, TestSize.Level0) +{ + ParamRWMutexCreate(nullptr); + ParamRWMutexWRLock(nullptr); + ParamRWMutexRDLock(nullptr); + ParamRWMutexUnlock(nullptr); + ParamRWMutexDelete(nullptr); + ParamMutexDelete(nullptr); +} + +HWTEST_F(ParamUnitTest, Init_TestWorkSpace_001, TestSize.Level0) +{ + int ret = AddWorkSpace("test.workspace.1", GetWorkSpaceIndex("test.workspace.1"), 0, PARAM_WORKSPACE_DEF); + EXPECT_EQ(ret, 0); + ret = AddWorkSpace("test.workspace.2", GetWorkSpaceIndex("test.workspace.2"), 0, PARAM_WORKSPACE_DEF); + EXPECT_EQ(ret, 0); + ret = AddWorkSpace("test.workspace.3", GetWorkSpaceIndex("test.workspace.3"), 0, PARAM_WORKSPACE_DEF); + EXPECT_EQ(ret, 0); + WorkSpace *space = GetWorkSpace(GetWorkSpaceIndex("test.workspace.1")); + EXPECT_NE(space, nullptr); + CloseWorkSpace(nullptr); +} + +HWTEST_F(ParamUnitTest, Init_TestWorkSpace_002, TestSize.Level0) +{ + const char *spaceName = "test.workspace2"; + const size_t size = strlen(spaceName) + 1; + WorkSpace *workSpace = (WorkSpace *)malloc(sizeof(WorkSpace) + size); + if (workSpace == nullptr) { + EXPECT_NE(workSpace, nullptr); + return; + } + workSpace->flags = 0; + workSpace->area = nullptr; + int ret = PARAM_STRCPY(workSpace->fileName, size, spaceName); + EXPECT_EQ(ret, 0); + CloseWorkSpace(workSpace); + free(workSpace); +} + +#if !(defined __LITEOS_A__ || defined __LITEOS_M__) // can not support parameter type +HWTEST_F(ParamUnitTest, Init_TestParamValueType_001, TestSize.Level0) +{ + int ret = SystemWriteParam("test.type.int.1000", "10000"); + EXPECT_EQ(ret, 0); + + ret = SystemWriteParam("test.type.int.1001", "-1111111144444444444441111111666666661"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE); + ret = SystemWriteParam("test.type.int.1001", "1111111111444444444444411111166666666"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE); +} + +HWTEST_F(ParamUnitTest, Init_TestParamValueType_002, TestSize.Level0) +{ + int ret = SystemWriteParam("test.type.bool.1000", "10000"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE); + + ret = SystemWriteParam("test.type.bool.1001", "-1111111111111111"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE); + ret = SystemWriteParam("test.type.bool.1001", "1111111111111111"); + EXPECT_EQ(ret, PARAM_CODE_INVALID_VALUE); + ret = SystemWriteParam("test.type.bool.1001", "true"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "false"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "1"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "0"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "on"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "off"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "yes"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "no"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "y"); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam("test.type.bool.1001", "n"); + EXPECT_EQ(ret, 0); +} +#endif + +HWTEST_F(ParamUnitTest, Init_TestGetServiceCtlName_001, TestSize.Level0) +{ + ServiceCtrlInfo *serviceInfo = nullptr; + GetServiceCtrlInfo("ohos.startup.powerctrl", "reboot,updater", &serviceInfo); + if (serviceInfo != nullptr) { + EXPECT_STREQ(serviceInfo->realKey, "ohos.servicectrl.reboot.updater.reboot,updater"); + free(serviceInfo); + } + GetServiceCtrlInfo("ohos.ctl.stop", "test", &serviceInfo); + if (serviceInfo != nullptr) { + EXPECT_STREQ(serviceInfo->realKey, "ohos.servicectrl.stop.test"); + free(serviceInfo); + } + GetServiceCtrlInfo("ohos.servicectrl.stop", "test", &serviceInfo); + if (serviceInfo != nullptr) { + EXPECT_STREQ(serviceInfo->realKey, "ohos.servicectrl.stop.test"); + free(serviceInfo); + } + ParamWorBaseLog(INIT_DEBUG, PARAN_DOMAIN, "PARAM", "%s", "ParamWorBaseLog"); +} + +HWTEST_F(ParamUnitTest, Init_TestFindTrieNode_001, TestSize.Level0) +{ + int ret = AddWorkSpace("test.workspace.1", GetWorkSpaceIndex("test.workspace.1"), 0, PARAM_WORKSPACE_DEF); + EXPECT_EQ(ret, 0); + WorkSpace *space = GetWorkSpaceByName("test.workspace.1"); + ASSERT_NE(space, nullptr); + ParamTrieNode *node = FindTrieNode(nullptr, nullptr, 0, nullptr); + ASSERT_EQ(node, nullptr); + node = FindTrieNode(space, nullptr, 0, nullptr); + ASSERT_EQ(node, nullptr); + node = FindTrieNode(space, "111111", 0, nullptr); + ASSERT_EQ(node, nullptr); + node = FindTrieNode(space, "find.test.111111", strlen("find.test.111111"), nullptr); + ASSERT_EQ(node, nullptr); +} + +#ifndef OHOS_LITE +HWTEST_F(ParamUnitTest, Init_TestConnectServer_001, TestSize.Level0) +{ + int ret = ConnectServer(-1, CLIENT_PIPE_NAME); + EXPECT_NE(ret, 0); + int fd = socket(PF_UNIX, SOCK_STREAM, 0); + ret = ConnectServer(fd, ""); + EXPECT_NE(ret, 0); + ret = ConnectServer(fd, CLIENT_PIPE_NAME); + EXPECT_EQ(ret, 0); + close(fd); +} + +HWTEST_F(ParamUnitTest, Init_TestRequestMessage_001, TestSize.Level0) +{ + const int maxSize = 1024 * 64 + 10; + const int msgSize = sizeof(ParamMessage) + 128; // 128 TEST + ParamMessage *msg = CreateParamMessage(0, nullptr, msgSize); + EXPECT_EQ(msg, nullptr); + msg = CreateParamMessage(0, "nullptr", maxSize); + EXPECT_EQ(msg, nullptr); + msg = CreateParamMessage(0, "22222222222222222222222222222222222222222" + "333333333333333333333333333333333333333333333333333333333333333333333" + "555555555555555555555555555555555555555555555555555555555555555555555", msgSize); + EXPECT_EQ(msg, nullptr); + + // success + msg = CreateParamMessage(0, "22222222222222222222222222222222222222222", msgSize); + EXPECT_NE(msg, nullptr); + uint32_t start = 0; + int ret = FillParamMsgContent(nullptr, &start, 0, nullptr, 0); + EXPECT_NE(ret, 0); + ret = FillParamMsgContent(msg, nullptr, 0, nullptr, 0); + EXPECT_NE(ret, 0); + ret = FillParamMsgContent(msg, &start, 0, nullptr, 0); + EXPECT_NE(ret, 0); + ret = FillParamMsgContent(msg, &start, 0, "22222", 0); + EXPECT_EQ(ret, 0); + ret = FillParamMsgContent(msg, &start, 0, "22222", msgSize); + EXPECT_NE(ret, 0); + // fill success + ret = FillParamMsgContent(msg, &start, 0, "22222", strlen("22222")); + EXPECT_EQ(ret, 0); + msg->msgSize = start + sizeof(ParamMessage); + + uint32_t offset = 0; + ParamMsgContent *content = GetNextContent(nullptr, &offset); + EXPECT_EQ(content, nullptr); + content = GetNextContent(msg, nullptr); + EXPECT_EQ(content, nullptr); + offset = 0; + content = GetNextContent(msg, &offset); + EXPECT_NE(content, nullptr); + content = GetNextContent(msg, &offset); + EXPECT_NE(content, nullptr); + free(msg); +} + +HWTEST_F(ParamUnitTest, Init_TestServerTaskFail_001, TestSize.Level0) +{ + ParamTaskPtr serverTask = nullptr; + ParamStreamInfo info = {}; + info.server = const_cast(PIPE_NAME); + info.close = nullptr; + info.recvMessage = nullptr; + info.incomingConnect = nullptr; + int ret = ParamServerCreate(nullptr, &info); + EXPECT_NE(ret, 0); + ret = ParamServerCreate(&serverTask, nullptr); + EXPECT_NE(ret, 0); + ret = ParamServerCreate(&serverTask, &info); + EXPECT_NE(ret, 0); +} + +HWTEST_F(ParamUnitTest, Init_TestStreamTaskFail_001, TestSize.Level0) +{ + ParamTaskPtr client = nullptr; + ParamStreamInfo info = {}; + info.flags = PARAM_TEST_FLAGS; + info.server = nullptr; + info.close = OnClose; + info.recvMessage = ProcessMessage; + info.incomingConnect = nullptr; + + int ret = ParamStreamCreate(&client, nullptr, &info, sizeof(ParamWatcher)); + EXPECT_NE(ret, 0); + ret = ParamStreamCreate(&client, GetParamService()->serverTask, nullptr, sizeof(ParamWatcher)); + EXPECT_NE(ret, 0); + info.close = nullptr; + ret = ParamStreamCreate(&client, GetParamService()->serverTask, &info, sizeof(ParamWatcher)); + EXPECT_NE(ret, 0); + info.close = OnClose; + info.recvMessage = nullptr; + ret = ParamStreamCreate(&client, GetParamService()->serverTask, &info, sizeof(ParamWatcher)); + EXPECT_NE(ret, 0); + ret = ParamStreamCreate(&client, nullptr, nullptr, sizeof(ParamWatcher)); + EXPECT_NE(ret, 0); + + void *data = ParamGetTaskUserData(client); + EXPECT_EQ(data, nullptr); + + ret = ParamTaskSendMsg(nullptr, nullptr); + EXPECT_NE(ret, 0); + ret = ParamTaskSendMsg(GetParamService()->serverTask, nullptr); + EXPECT_NE(ret, 0); +} + +HWTEST_F(ParamUnitTest, Init_TestParamCache_001, TestSize.Level0) +{ + const char *value = CachedParameterGet(nullptr); + EXPECT_EQ(value, nullptr); + const char *name = "test.write.1111111.222222"; + CachedHandle cacheHandle = CachedParameterCreate(name, "true"); + EXPECT_NE(cacheHandle, nullptr); + value = CachedParameterGet(cacheHandle); + EXPECT_EQ(strcmp(value, "true"), 0); + uint32_t dataIndex = 0; + int ret = WriteParam(name, "false", &dataIndex, 0); + EXPECT_EQ(ret, 0); + value = CachedParameterGet(cacheHandle); + EXPECT_EQ(strcmp(value, "false"), 0); + CachedParameterDestroy(cacheHandle); + + // cache 2, for parameter exist + CachedHandle cacheHandle3 = CachedParameterCreate(name, "true"); + EXPECT_NE(cacheHandle3, nullptr); + value = CachedParameterGet(cacheHandle3); + EXPECT_EQ(strcmp(value, "false"), 0); + ret = WriteParam(name, "2222222", &dataIndex, 0); + EXPECT_EQ(ret, 0); + int valueChange = 0; + value = CachedParameterGetChanged(cacheHandle3, &valueChange); + EXPECT_EQ(strcmp(value, "2222222"), 0); + EXPECT_EQ(valueChange, 1); + CachedParameterGetChanged(cacheHandle3, nullptr); + CachedParameterDestroy(cacheHandle3); +} +#endif +} diff --git a/test/unittest/param/paramservice_unittest.cpp b/test/unittest/param/paramservice_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b41e3ba3ae167b92d72cb284dec92648f8ecc992 --- /dev/null +++ b/test/unittest/param/paramservice_unittest.cpp @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2021 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 "init_param.h" +#include "param_message.h" +#include "param_stub.h" +#include "param_init.h" +#include "trigger_manager.h" +#include "le_timer.h" + +using namespace testing::ext; +using namespace std; + +static int TestTriggerExecute(TriggerNode *trigger, const char *content, uint32_t size) +{ + return 0; +} + +static int CheckServerParamValue(const char *name, const char *expectValue) +{ + char tmp[PARAM_BUFFER_SIZE] = {0}; + u_int32_t len = sizeof(tmp); + SystemReadParam(name, tmp, &len); + printf("CheckParamValue name %s value: \'%s\' expectValue:\'%s\' \n", name, tmp, expectValue); + EXPECT_NE((int)strlen(tmp), 0); + if (expectValue != nullptr) { + EXPECT_EQ(strcmp(tmp, expectValue), 0); + } + return 0; +} + +namespace init_ut { +static ParamTaskPtr g_worker = nullptr; +class ParamServiceUnitTest : public ::testing::Test { +public: + ParamServiceUnitTest() {} + virtual ~ParamServiceUnitTest() {} + + static void SetUpTestCase(void) {} + + void SetUp() + { + if (GetParamSecurityLabel() != nullptr) { + GetParamSecurityLabel()->cred.uid = 1000; // 1000 test uid + GetParamSecurityLabel()->cred.gid = 1000; // 1000 test gid + } + } + void TearDown() {} + void TestBody() {} + + int TestSetParams(const char *params[][1 + 1], int num) + { + for (int i = 0; i < num; i++) { + SystemWriteParam(params[i][0], params[i][1]); + } + + // check + for (int i = 0; i < num; i++) { + CheckServerParamValue(params[i][0], params[i][1]); + } + + for (int i = num - 1; i >= 0; i--) { + CheckServerParamValue(params[i][0], params[i][1]); + } + return 0; + } + + int TestAddSecurityLabel1() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label1.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + uint32_t labelIndex = 0; + SystemWriteParam(name, value); + // 获取到跟属性 + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + (void)FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ(node->gid, 0); + return 0; + } + + // 添加一个label,最长匹配到这个节点 + int TestAddSecurityLabel2() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label2.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + ParamAuditData auditData = {}; + auditData.name = "label2.test.aaa"; + auditData.dacData.gid = 202; // 202 test dac gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + uint32_t labelIndex = 0; + AddSecurityLabel(&auditData); + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + (void)FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ(node->gid, auditData.dacData.gid); + return 0; + } + + // 添加一个label,最长匹配到最后一个相同节点 + int TestAddSecurityLabel3() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label3.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + ParamAuditData auditData = {}; + auditData.name = "label3.test.aaa"; + auditData.dacData.gid = 203; // 203 test gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + AddSecurityLabel(&auditData); + + auditData.name = "label3.test.aaa.bbb.ccc.dddd.eee.dddd"; + auditData.dacData.gid = 202; // 202 test dac gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + AddSecurityLabel(&auditData); + + uint32_t labelIndex = 0; + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + ParamTrieNode *paramNode = FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (paramNode == nullptr || node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ((int)node->gid, 203); // 203 test gid + return 0; + } + + // 添加一个label,完全匹配 + int TestAddSecurityLabel4() + { + GetParamSecurityLabel()->cred.gid = 9999; // 9999 test gid + const char *name = "label4.test.aaa.bbb.ccc.dddd.eee"; + const char *value = "2001"; + ParamAuditData auditData = {}; + auditData.name = "label4.test.aaa.bbb.ccc.dddd.eee"; + auditData.dacData.gid = 203; // 203 test gid + auditData.dacData.uid = geteuid(); + auditData.dacData.mode = 0666; // 0666 test mode + SystemWriteParam(name, value); + uint32_t labelIndex = 0; + AddSecurityLabel(&auditData); + WorkSpace *workspace = GetWorkSpace(WORKSPACE_INDEX_DAC); + ParamTrieNode *paramNode = FindTrieNode(workspace, name, strlen(name), &labelIndex); + ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(workspace, labelIndex); + if (paramNode == nullptr || node == nullptr) { + EXPECT_EQ(1, 0); + return 0; + } + EXPECT_EQ(node->gid, auditData.dacData.gid); + return 0; + } + + void TestBufferValue(char *buffer, uint32_t len) + { + const int printBase = 10; + for (uint32_t index = 0; index <= len; index++) { + buffer[index] = '0' + index % printBase; + if (index != 0 && index % printBase == 0) { + buffer[index] = '.'; + } + } + buffer[len] = '\0'; + } + + int TestNameIsValid() + { + char buffer[PARAM_BUFFER_SIZE]; + // set name length = 127 + TestBufferValue(buffer, PARAM_NAME_LEN_MAX - 1); + int ret = SystemWriteParam(buffer, "1111"); + EXPECT_EQ(ret, 0); + TestBufferValue(buffer, PARAM_NAME_LEN_MAX); + ret = SystemWriteParam(buffer, "1111"); + EXPECT_NE(ret, 0); + TestBufferValue(buffer, PARAM_NAME_LEN_MAX + 1); + ret = SystemWriteParam(buffer, "1111"); + EXPECT_NE(ret, 0); + + ret = SystemWriteParam(" ", "1111"); + EXPECT_NE(ret, 0); + ret = SystemWriteParam("__.__..", "1111"); + EXPECT_NE(ret, 0); + ret = SystemWriteParam(".__..", "1111"); + EXPECT_NE(ret, 0); + ret = SystemWriteParam("test.-@:_", "1111"); + EXPECT_EQ(ret, 0); + + // 保存一个只读的属性,大于最大值 + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("const.test_readonly.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_EQ(ret, 0); + + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX + 1); + ret = SystemWriteParam("const.test_readonly.aaaaaaaaaaaaaaaaaa.fffffffffffffffffff", buffer); + EXPECT_EQ(ret, 0); + + // 更新只读项目 + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("const.test_readonly.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + + // 写普通属性 + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("test.bigvalue.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_EQ(ret, 0); + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX + 1); + ret = SystemWriteParam("test.bigvalue.dddddddddddddddddd.fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + + // invalid name + TestBufferValue(buffer, PARAM_VALUE_LEN_MAX - 1); + ret = SystemWriteParam("test.invalidname..fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + ret = SystemWriteParam("test.invalidname.%fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + ret = SystemWriteParam("test.invalidname.$fffffffffffffffffff", buffer); + EXPECT_NE(ret, 0); + return 0; + } + + int TestParamTraversal() + { + char value[PARAM_BUFFER_SIZE + PARAM_BUFFER_SIZE] = {0}; + SystemTraversalParameter( + "", + [](ParamHandle handle, void *cookie) { + SystemGetParameterName(handle, (char *)cookie, PARAM_BUFFER_SIZE); + u_int32_t len = PARAM_BUFFER_SIZE; + SystemGetParameterValue(handle, ((char *)cookie) + PARAM_BUFFER_SIZE, &len); + printf("$$$$$$$$Param %s=%s \n", (char *)cookie, ((char *)cookie) + PARAM_BUFFER_SIZE); + }, + (void *)value); + return 0; + } + + int TestUpdateParam(const char *name, const char *value) + { + SystemWriteParam(name, value); + SystemWriteParam(name, value); + SystemWriteParam(name, value); + SystemWriteParam(name, value); + CheckServerParamValue(name, value); + return 0; + } + + int TestPersistParam() + { + RegisterPersistParamOps(nullptr); + LoadPersistParams(); + SystemWriteParam("persist.111.ffff.bbbb.cccc.dddd.eeee", "1101"); + SystemWriteParam("persist.111.aaaa.bbbb.cccc.dddd.eeee", "1102"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.eeee", "1103"); + CheckServerParamValue("persist.111.bbbb.cccc.dddd.eeee", "1103"); + SystemWriteParam("persist.111.cccc.bbbb.cccc.dddd.eeee", "1104"); + SystemWriteParam("persist.111.eeee.bbbb.cccc.dddd.eeee", "1105"); + CheckServerParamValue("persist.111.ffff.bbbb.cccc.dddd.eeee", "1101"); + SystemWriteParam("persist.111.ffff.bbbb.cccc.dddd.eeee", "1106"); + CheckServerParamValue("persist.111.ffff.bbbb.cccc.dddd.eeee", "1106"); + + SystemWriteParam("persist.111.bbbb.cccc.dddd.1107", "1107"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1108", "1108"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1109", "1108"); + + SystemWriteParam("persist.111.bbbb.cccc.dddd.1110", "1108"); + SystemWriteParam("persist.111.bbbb.cccc.dddd.1111", "1108"); + TimerCallbackForSave(nullptr, nullptr); + LoadPersistParams(); + return 0; + } + + ParamTaskPtr CreateAndGetStreamTask() + { + OnIncomingConnect(LE_GetDefaultLoop(), GetParamService()->serverTask); + EXPECT_NE(GetParamService()->watcherTask, nullptr); + return GetParamService()->watcherTask; + } + + int TestServiceProcessMessage(const char *name, const char *value, int userLabel) + { + if (g_worker == nullptr) { + g_worker = CreateAndGetStreamTask(); + } + if (g_worker == nullptr) { + return 0; + } + ParamSecurityOps *paramSecurityOps = GetParamSecurityOps(0); + if (userLabel && paramSecurityOps != nullptr) { + paramSecurityOps->securityFreeLabel = TestFreeLocalSecurityLabel; + paramSecurityOps->securityCheckParamPermission = TestCheckParamPermission; + } + uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + PARAM_ALIGN(strlen(value) + 1); + ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, name, msgSize); + PARAM_CHECK(request != nullptr, return -1, "Failed to malloc for connect"); + do { + request->type = MSG_SET_PARAM; + uint32_t offset = 0; + int ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value)); + PARAM_CHECK(ret == 0, break, "Failed to fill value"); + ProcessMessage((const ParamTaskPtr)g_worker, (const ParamMessage *)request); + } while (0); + free(request); + RegisterSecurityOps(1); + return 0; + } + + int AddWatch(int type, const char *name, const char *value) + { + if (g_worker == nullptr) { + g_worker = CreateAndGetStreamTask(); + } + if (g_worker == nullptr) { + return 0; + } + uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + sizeof(ParamMsgContent) + + PARAM_ALIGN(strlen(value) + 1) + sizeof(uint32_t); + ParamMessage *request = (ParamMessage *)(ParamMessage *)CreateParamMessage(type, name, msgSize); + PARAM_CHECK(request != nullptr, return -1, "Failed to malloc for connect"); + do { + uint32_t offset = 0; + int ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value)); + PARAM_CHECK(ret == 0, break, "Failed to fill value"); + + ParamMsgContent *content = (ParamMsgContent *)(request->data + offset); + content->type = PARAM_WAIT_TIMEOUT; + content->contentSize = sizeof(uint32_t); + *((uint32_t *)(content->content)) = 100; // 100 is test value + offset += sizeof(ParamMsgContent) + sizeof(uint32_t); + request->msgSize = offset + sizeof(ParamMessage); + + ProcessMessage((const ParamTaskPtr)g_worker, (const ParamMessage *)request); + } while (0); + free(request); + return 0; + } + + // 无匹配 + int TestAddParamWait1() + { + const char *name = "wait.aaa.bbb.ccc.111"; + const char *value = "wait1"; + AddWatch(MSG_WAIT_PARAM, name, value); + SystemWriteParam(name, value); + // execute trigger + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + return 0; + } + + // 模糊匹配 + int TestAddParamWait2() + { + const char *name = "wait.aaa.bbb.ccc.222"; + const char *value = "wait2"; + AddWatch(MSG_WAIT_PARAM, name, "*"); + SystemWriteParam(name, value); + // execute trigger + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + return 0; + } + + // 属性存在 + int TestAddParamWait3() + { + const char *name = "wait.aaa.bbb.ccc.333"; + const char *value = "wait3"; + SystemWriteParam(name, value); + AddWatch(MSG_WAIT_PARAM, name, value); + // execute trigger + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + return 0; + } + + int TestAddParamWatch1() + { + const char *name = "watch.aaa.bbb.ccc.111"; + const char *value = "watch1"; + AddWatch(MSG_ADD_WATCHER, name, value); + std::string newName = name; + newName += ".test.test.test"; + SystemWriteParam(newName.c_str(), value); + // execute trigger + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + return 0; + } + + int TestAddParamWatch2() + { + const char *name = "watch.aaa.bbb.ccc.222"; + const char *value = "watch2"; + AddWatch(MSG_ADD_WATCHER, name, "*"); + SystemWriteParam(name, value); + // execute trigger + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + return 0; + } + + int TestAddParamWatch3() + { + const char *name = "watch.aaa.bbb.ccc.333"; + const char *value = "watch3"; + std::string newName = name; + newName += ".test.test.test"; + SystemWriteParam(newName.c_str(), value); + AddWatch(MSG_ADD_WATCHER, name, value); + char buffer[] = "testbuff"; + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM_WATCH, buffer, strlen(buffer), TestTriggerExecute); + AddWatch(MSG_DEL_WATCHER, name, value); + return 0; + } + + int TestCloseTriggerWatch() + { +#ifdef PARAM_SUPPORT_TRIGGER + SystemDumpTriggers(1, nullptr); +#endif + ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(g_worker); + ClearWatchTrigger(watcher, TRIGGER_PARAM_WAIT); + ParamTaskClose(g_worker); + g_worker = nullptr; + ParamTaskClose(g_worker); + SystemWriteParam("init.svc.param_watcher", "stopped"); + return 0; + } + + int TestServiceCtrl(const char *serviceName, uint16_t mode) + { + // service forbid + TestSetParamCheckResult("ohos.servicectrl.", mode, 1); + return SystemWriteParam("ohos.ctl.start", serviceName); + } + + int TestPowerCtrl(const char *reboot, uint16_t mode) + { + // service forbid + TestSetParamCheckResult("ohos.servicectrl.reboot", mode, 1); + return SystemWriteParam("ohos.startup.powerctrl", reboot); + } +}; + +HWTEST_F(ParamServiceUnitTest, Init_TestPersistParam_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestPersistParam(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestReadCmdline_001, TestSize.Level0) +{ + const char *snData = "222222222222222222222"; + CreateTestFile(STARTUP_INIT_UT_PATH "/system/etc/sn", snData); + // for cmdline + std::string cmdLineForSn = "bootgroup=device.charge.group earlycon=uart8250,mmio32,0xfe660000 " + "root=PARTUUID=614e0000-0000 rw rootwait rootfstype=ext4 console=ttyFIQ0 hardware=rk3568" + " BOOT_IMAGE=/kernel init=/init"; + std::string snWithPath = cmdLineForSn + "ohos.boot.sn=" + STARTUP_INIT_UT_PATH "/system/etc/sn"; + CreateTestFile(BOOT_CMD_LINE, snWithPath.c_str()); + LoadParamFromCmdLine(); + std::string snWithSN = cmdLineForSn + "ohos.boot.sn=" + snData; + CreateTestFile(BOOT_CMD_LINE, snWithSN.c_str()); + LoadParamFromCmdLine(); + CreateTestFile(BOOT_CMD_LINE, cmdLineForSn.c_str()); + LoadParamFromCmdLine(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestServiceProcessMessage_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestServiceProcessMessage("wertt.qqqq.wwww.rrrr", "wwww.eeeee", 1); + test.TestServiceProcessMessage("wertt.2222.wwww.3333", "wwww.eeeee", 0); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestAddParamWait_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestAddParamWait1(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestAddParamWait_002, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestAddParamWait2(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestAddParamWait_003, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestAddParamWait3(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestAddParamWatch_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestAddParamWatch1(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestAddParamWatch_002, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestAddParamWatch2(); +} + +#ifndef OHOS_LITE +HWTEST_F(ParamServiceUnitTest, Init_TestAddParamWatch_003, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestAddParamWatch3(); + int hashCode = CheckWatchTriggerTimeout(); + EXPECT_EQ(hashCode, 0); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestCloseTriggerWatch_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + test.TestCloseTriggerWatch(); +} + +HWTEST_F(ParamServiceUnitTest, Init_TestServiceCtrl_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + int ret = test.TestServiceCtrl("server1", 0770); + EXPECT_NE(ret, 0); +#ifdef PARAM_SUPPORT_SELINUX + // selinux forbid + ret = test.TestServiceCtrl("server2", 0772); + EXPECT_NE(ret, 0); +#endif + ret = 0; +} + +HWTEST_F(ParamServiceUnitTest, Init_TestPowerCtrl_001, TestSize.Level0) +{ + ParamServiceUnitTest test; + int ret = test.TestPowerCtrl("reboot,shutdown", 0770); + EXPECT_NE(ret, 0); + ret = test.TestPowerCtrl("reboot,shutdown", 0772); +#ifdef PARAM_SUPPORT_SELINUX + // selinux forbid + EXPECT_NE(ret, 0); +#endif + ret = test.TestPowerCtrl("reboot,updater", 0770); + EXPECT_NE(ret, 0); + ret = test.TestPowerCtrl("reboot,updater", 0772); +#ifdef PARAM_SUPPORT_SELINUX + // selinux forbid + EXPECT_NE(ret, 0); +#endif + ret = test.TestPowerCtrl("reboot,flashd", 0770); + EXPECT_NE(ret, 0); + ret = test.TestPowerCtrl("reboot,flashd", 0772); +#ifdef PARAM_SUPPORT_SELINUX + // selinux forbid + EXPECT_NE(ret, 0); +#endif + + ret = test.TestPowerCtrl("reboot", 0770); + EXPECT_NE(ret, 0); + ret = test.TestPowerCtrl("reboot", 0772); +#ifdef PARAM_SUPPORT_SELINUX + // selinux forbid + EXPECT_NE(ret, 0); +#endif + + ParamServiceStop(); +} +#endif +} // namespace init_ut diff --git a/test/unittest/param/selinux_unittest.cpp b/test/unittest/param/selinux_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..394e5ccbbd54d5f44108be21c7ac5e6037aa737c --- /dev/null +++ b/test/unittest/param/selinux_unittest.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2021 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 "param_manager.h" +#include "param_security.h" +#include "param_stub.h" +#include "param_utils.h" +#include "securec.h" + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class SelinuxUnitTest : public ::testing::Test { +public: + SelinuxUnitTest() {} + virtual ~SelinuxUnitTest() {} + + void SetUp() + { + SetTestPermissionResult(0); + } + void TearDown() {} + void TestBody() {} + + int TestSelinuxInitLocalLabel() + { + int ret = RegisterSecuritySelinuxOps(nullptr, 0); + EXPECT_NE(ret, 0); + + ret = RegisterSecuritySelinuxOps(&initParamSercurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + + if (initParamSercurityOps.securityInitLabel == nullptr || initParamSercurityOps.securityFreeLabel == nullptr) { + return -1; + } + ParamSecurityLabel label = {}; + ret = initParamSercurityOps.securityInitLabel(&label, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + ret = initParamSercurityOps.securityFreeLabel(&label); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestSelinuxCheckFilePermission(const char *fileName) + { + int ret = RegisterSecuritySelinuxOps(&initParamSercurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + if (initParamSercurityOps.securityCheckFilePermission == nullptr) { + return -1; + } + ParamSecurityLabel label = {}; + ret = initParamSercurityOps.securityInitLabel(&label, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + ret = initParamSercurityOps.securityCheckFilePermission(&label, fileName, DAC_WRITE); + EXPECT_EQ(ret, 0); + ret = initParamSercurityOps.securityFreeLabel(&label); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestSelinuxCheckParaPermission(const char *name, const char *label) + { + int ret = RegisterSecuritySelinuxOps(&initParamSercurityOps, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + if (initParamSercurityOps.securityCheckFilePermission == nullptr) { + return -1; + } + ParamSecurityLabel srclabel = {}; + ret = initParamSercurityOps.securityInitLabel(&srclabel, LABEL_INIT_FOR_INIT); + EXPECT_EQ(ret, 0); + + ret = initParamSercurityOps.securityCheckParamPermission( + TestGetParamLabelIndex(name), &srclabel, name, DAC_WRITE); + EXPECT_EQ(ret, 0); + ret = initParamSercurityOps.securityFreeLabel(&srclabel); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestClientSelinuxCheckFilePermission(const char *fileName) + { + int ret = RegisterSecuritySelinuxOps(&clientParamSercurityOps, 0); + EXPECT_EQ(ret, 0); + if (clientParamSercurityOps.securityCheckFilePermission == nullptr) { + EXPECT_EQ(1, 0); + return -1; + } + ParamSecurityLabel label = {}; + ret = clientParamSercurityOps.securityInitLabel(&label, 0); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityCheckFilePermission(&label, fileName, DAC_READ); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityFreeLabel(&label); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestClientSelinuxCheckParaPermissionWrite(const char *name, const char *label) + { + int ret = RegisterSecuritySelinuxOps(&clientParamSercurityOps, 0); + EXPECT_EQ(ret, 0); + + if (clientParamSercurityOps.securityCheckFilePermission == nullptr) { + return -1; + } + ParamSecurityLabel srclabel = {}; + ret = clientParamSercurityOps.securityInitLabel(&srclabel, 0); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityCheckParamPermission( + TestGetParamLabelIndex(name), &srclabel, name, DAC_WRITE); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityFreeLabel(&srclabel); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestClientSelinuxCheckParaPermissionRead(const char *name, const char *label) + { + int ret = RegisterSecuritySelinuxOps(&clientParamSercurityOps, 0); + EXPECT_EQ(ret, 0); + if (clientParamSercurityOps.securityCheckFilePermission == nullptr) { + return -1; + } + ParamSecurityLabel srclabel = {}; + ret = clientParamSercurityOps.securityInitLabel(&srclabel, 0); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityCheckParamPermission( + TestGetParamLabelIndex(name), &srclabel, name, DAC_READ); + EXPECT_EQ(ret, 0); + ret = clientParamSercurityOps.securityFreeLabel(&srclabel); + EXPECT_EQ(ret, 0); + uint8_t updateMode = GetParamWorkSpace()->ops.updaterMode; + GetParamWorkSpace()->ops.updaterMode = 1; // 1 test updater mode + RegisterSecuritySelinuxOps(&clientParamSercurityOps, 0); + if (clientParamSercurityOps.securityCheckParamPermission != nullptr) { + clientParamSercurityOps.securityCheckParamPermission(TestGetParamLabelIndex(name), nullptr, nullptr, 0); + } + GetParamWorkSpace()->ops.updaterMode = updateMode; + return 0; + } + +private: + ParamSecurityOps initParamSercurityOps {}; + ParamSecurityOps clientParamSercurityOps {}; +}; + +HWTEST_F(SelinuxUnitTest, Init_TestSelinuxInitLocalLabel_001, TestSize.Level0) +{ + SelinuxUnitTest test; + test.TestSelinuxInitLocalLabel(); +} + +HWTEST_F(SelinuxUnitTest, Init_TestSelinuxCheckFilePermission_001, TestSize.Level0) +{ + SelinuxUnitTest test; + test.TestSelinuxCheckFilePermission(STARTUP_INIT_UT_PATH "/trigger_test.cfg"); +} + +HWTEST_F(SelinuxUnitTest, Init_TestSelinuxCheckParaPermission_001, TestSize.Level0) +{ + SelinuxUnitTest test; + test.TestSelinuxCheckParaPermission("aaa.bbb.bbb.ccc", "user:group1:r"); +} + +HWTEST_F(SelinuxUnitTest, Init_TestClientDacCheckFilePermission_001, TestSize.Level0) +{ + SelinuxUnitTest test; + test.TestClientSelinuxCheckFilePermission(STARTUP_INIT_UT_PATH "/trigger_test.cfg"); +} + +HWTEST_F(SelinuxUnitTest, Init_TestClientDacCheckParaPermission_001, TestSize.Level0) +{ + SelinuxUnitTest test; + test.TestClientSelinuxCheckParaPermissionWrite("aaa.bbb.bbb.ccc", "user:group1:r"); + test.TestClientSelinuxCheckParaPermissionRead("aaa.bbb.bbb.ccc", "user:group1:r"); +} +} \ No newline at end of file diff --git a/test/unittest/param/trigger_unittest.cpp b/test/unittest/param/trigger_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98bff5d203714339f2d75db52013b3a156a808ef --- /dev/null +++ b/test/unittest/param/trigger_unittest.cpp @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2021 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 "bootstage.h" +#include "init_jobs_internal.h" +#include "init_log.h" +#include "init_param.h" +#include "init_utils.h" +#include "init_hashmap.h" +#include "loop_event.h" +#include "param_manager.h" +#include "param_stub.h" +#include "param_utils.h" +#include "securec.h" +#include "trigger_checker.h" +#include "trigger_manager.h" + +using namespace testing::ext; +using namespace std; + +static const int triggerBuffer = 512; +static uint32_t g_execCmdId = 0; +static int g_matchTrigger = 0; +static char g_matchTriggerName[triggerBuffer] = { 0 }; +static void BootStateChange(int start, const char *content) +{ + UNUSED(content); + return; +} + +static int TestCmdExec(const TriggerNode *trigger, const char *content, uint32_t size) +{ + PARAM_CHECK(trigger != nullptr, return -1, "Invalid trigger"); + PARAM_LOGI("DoTriggerExecute_ trigger type: %d %s", trigger->type, GetTriggerName(trigger)); + PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return -1, "Invalid trigger type %d", trigger->type); + CommandNode *cmd = GetNextCmdNode(reinterpret_cast(trigger), nullptr); + while (cmd != nullptr) { + g_execCmdId = cmd->cmdKeyIndex; + cmd = GetNextCmdNode(reinterpret_cast(trigger), cmd); + } + return 0; +} + +static int TestTriggerExecute(TriggerNode *trigger, const char *content, uint32_t size) +{ + JobNode *node = reinterpret_cast(trigger); + int ret = memcpy_s(g_matchTriggerName, (int)sizeof(g_matchTriggerName) - 1, node->name, strlen(node->name)); + EXPECT_EQ(ret, 0); + g_matchTriggerName[strlen(node->name)] = '\0'; + g_matchTrigger++; + return 0; +} + +static void Test_JobParseHook(JOB_PARSE_CTX *jobParseCtx) +{ + return; +} + +class TriggerUnitTest : public ::testing::Test { +public: + TriggerUnitTest() {} + virtual ~TriggerUnitTest() {} + + void SetUp() + { + SetTestPermissionResult(0); + } + void TearDown() {} + void TestBody() {} + + int ParseInitCfg(const char *configFile) + { + char *fileBuf = ReadFileToBuf(configFile); + INIT_ERROR_CHECK(fileBuf != nullptr, return -1, "Failed to read file content %s", configFile); + cJSON *fileRoot = cJSON_Parse(fileBuf); + INIT_ERROR_CHECK(fileRoot != nullptr, return -1, "Failed to parse json file %s", configFile); + ParseTriggerConfig(fileRoot, nullptr, nullptr); + cJSON_Delete(fileRoot); + free(fileBuf); + fileBuf = nullptr; + return 0; + } + + int TestLoadTrigger() + { + RegisterBootStateChange(BootStateChange); + InitAddJobParseHook(Test_JobParseHook); + + int cmdKeyIndex = 0; + const char *matchCmd = GetMatchCmd("setparam aaaa aaaa", &cmdKeyIndex); + printf("cmd %d \n", matchCmd != nullptr); + EXPECT_NE(matchCmd, nullptr); + + ReadConfig(); + ParseInitCfg(STARTUP_INIT_UT_PATH "/trigger_test.cfg"); + // trigger + PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init")); + PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init")); + PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init")); + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + return 0; + } + + TriggerHeader *GetTriggerHeader(int type) + { + return &GetTriggerWorkSpace()->triggerHead[type]; + } + + JobNode *AddTrigger(int type, const char *name, const char *condition, uint32_t size) + { + return UpdateJobTrigger(GetTriggerWorkSpace(), type, condition, name); + } + + int TestAddTriggerForBoot() + { + JobNode *node = AddTrigger(TRIGGER_BOOT, "init-later", "", 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), "init-later"); + EXPECT_EQ(node, trigger); + if (trigger == nullptr) { + return -1; + } + EXPECT_EQ(strcmp(trigger->name, "init-later"), 0); + + // add command + int cmdIndex = 0; + GetMatchCmd("reboot ", &cmdIndex); + int ret = AddCommand(trigger, cmdIndex, nullptr, nullptr); + EXPECT_EQ(ret, 0); + ret = AddCommand(trigger, cmdIndex, "update: aaaaaaa", nullptr); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestAddTriggerForParm() + { + const char *triggerName = "param:test_param.000"; + int id = 0; + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, "test_param.000=1", 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + GetTriggerHeader(TRIGGER_PARAM)->compareData(reinterpret_cast(trigger), &id); + EXPECT_EQ(trigger, node); + if (trigger == nullptr) { + return -1; + } + EXPECT_EQ(strcmp(trigger->name, triggerName), 0); + + // add command + int cmdIndex = 0; + GetMatchCmd("reboot ", &cmdIndex); + int ret = AddCommand(trigger, cmdIndex, nullptr, nullptr); + EXPECT_EQ(ret, 0); + ret = AddCommand(trigger, cmdIndex, "update: aaaaaaa", nullptr); + EXPECT_EQ(ret, 0); + return 0; + } + + int TestParamEvent() + { + PostParamTrigger(EVENT_TRIGGER_PARAM, "net.tcp.default_init_rwnd", "60"); + const char *sysctrl = "ohos.startup.powerctrl=reboot, shutdown"; + PostTrigger(EVENT_TRIGGER_PARAM, sysctrl, strlen(sysctrl)); + PostParamTrigger(EVENT_TRIGGER_PARAM, "ohos.startup.powerctrl", "reboot, shutdown"); + + const char *startCmd = "ohos.ctl.start=hdc -t"; + PostTrigger(EVENT_TRIGGER_PARAM, startCmd, strlen(startCmd)); + PostParamTrigger(EVENT_TRIGGER_PARAM, "ohos.ctl.start", "hdc -t"); + + const char *stopCmd = "ohos.ctl.stop=hdc -t"; + PostTrigger(EVENT_TRIGGER_PARAM, stopCmd, strlen(stopCmd)); + PostParamTrigger(EVENT_TRIGGER_PARAM, "ohos.ctl.stop", "hdc -t"); + return 0; + } + + int TestBootEvent(const char *boot) + { + PostTrigger(EVENT_TRIGGER_BOOT, boot, strlen(boot)); + return 0; + } + + int TestCheckParamTrigger1() + { + const char *triggerName = "param:test_param.111"; + const char *param = "test_param.aaa.111.2222"; + const char *value = "1"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, value); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + + g_matchTrigger = 0; + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, "2"); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(0, g_matchTrigger); + + g_matchTrigger = 0; + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, value); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + + // check for bug + g_matchTrigger = 0; + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", "2222", value); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(0, g_matchTrigger); + + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM_WATCH, buffer, strlen(buffer), TestTriggerExecute); + return 0; + } + + int TestCheckParamTrigger2() + { + const char *triggerName = "param:test_param.222"; + const char *param = "test_param.aaa.222.2222"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=*", param); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + + g_matchTrigger = 0; + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, "2"); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + + g_matchTrigger = 0; + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, param, strlen(param), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + return 0; + } + + int TestCheckParamTrigger3() + { + const char *triggerName = "param:test_param.333"; + const char *param1 = "test_param.aaa.333.2222=1"; + const char *param2 = "test_param.aaa.333.3333=2"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s || %s", param1, param2); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + + g_matchTrigger = 0; + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, param1, strlen(param1), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + + g_matchTrigger = 0; + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, param2, strlen(param2), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + return 0; + } + + int TestCheckParamTrigger4() + { + const char *triggerName = "param:test_param.444"; + const char *param1 = "test_param.aaa.444.2222"; + const char *param2 = "test_param.aaa.444.3333"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=%s && %s=%s", param1, "1", param2, "2"); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + DoJobNow(triggerName); + ClearTrigger(nullptr, 0); + g_matchTrigger = 0; + SystemWriteParam(param1, "1"); + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param1, "1"); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(0, g_matchTrigger); + + SystemWriteParam(param2, "2"); + g_matchTrigger = 0; + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param2, "2"); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + return 0; + } + + // test for trigger aaaa:test_param.aaa 被加入unknown执行 + int TestCheckParamTrigger5() + { + const char *triggerName = "aaaa:test_param.aaa"; + const char *param1 = "test_param.aaa.aaa.2222"; + const char *param2 = "test_param.aaa.aaa.3333"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "aaaa && %s=%s && %s=%s", param1, "1", param2, "2"); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_UNKNOW, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + + g_matchTrigger = 0; + SystemWriteParam(param1, "1"); + ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param1, "1"); + EXPECT_GE(ret, 0); + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_PARAM, buffer, strlen(buffer), TestTriggerExecute); + EXPECT_EQ(0, g_matchTrigger); + + SystemWriteParam(param2, "2"); + g_matchTrigger = 0; + CheckTrigger(GetTriggerWorkSpace(), TRIGGER_UNKNOW, "aaaa", strlen("aaaa"), TestTriggerExecute); + EXPECT_EQ(1, g_matchTrigger); + EXPECT_EQ(0, strcmp(triggerName, g_matchTriggerName)); + return 0; + } + + int TestComputeCondition(const char *condition) + { + u_int32_t size = strlen(condition) + CONDITION_EXTEND_LEN; + char *prefix = reinterpret_cast(malloc(size)); + if (prefix == nullptr) { + printf("prefix is null.\n"); + return -1; + } + ConvertInfixToPrefix(condition, prefix, size); + printf("prefix %s \n", prefix); + free(prefix); + return 0; + } + + // 普通的属性trigger + int TestExecuteParamTrigger1() + { + const char *triggerName = "aaaa:test_param.eee"; + const char *param = "test_param.eee.aaa.1111"; + const char *value = "eee"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, value); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + + const uint32_t cmdIndex = 100; + ret = AddCommand(trigger, cmdIndex, value, nullptr); + EXPECT_EQ(ret, 0); + // 修改命令为测试执行 + RegisterTriggerExec(TRIGGER_PARAM, TestCmdExec); + SystemWriteParam(param, value); + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + EXPECT_EQ(g_execCmdId, cmdIndex); + return 0; + } + + int TestExecuteParamTrigger2() + { + const char *triggerName = "param:test_param.dddd"; + const char *param = "test_param.dddd.aaa.2222"; + const char *value = "2222"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, value); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + const uint32_t cmdIndex = 102; + ret = AddCommand(trigger, cmdIndex, value, nullptr); + EXPECT_EQ(ret, 0); + RegisterTriggerExec(TRIGGER_PARAM, TestCmdExec); + SystemWriteParam(param, value); + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + EXPECT_EQ(g_execCmdId, cmdIndex); + return 0; + } + + // 测试执行后立刻删除 + int TestExecuteParamTrigger3() + { + const char *triggerName = "param:test_param.3333"; + const char *param = "test_param.dddd.aaa.3333"; + const char *value = "3333"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, value); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + if (trigger == nullptr) { + return -1; + } + const uint32_t cmdIndex = 103; + ret = AddCommand(trigger, cmdIndex, value, nullptr); + EXPECT_EQ(ret, 0); + TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_ONCE); + SystemWriteParam(param, value); + + RegisterTriggerExec(TRIGGER_PARAM, TestCmdExec); + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + EXPECT_EQ(g_execCmdId, cmdIndex); + trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + if (trigger != nullptr) { + EXPECT_EQ(1, 0); + } + return 0; + } + + // 测试删除队列中的trigger + int TestExecuteParamTrigger4() + { + const char *triggerName = "param:test_param.4444"; + const char *param = "test_param.dddd.aaa.4444"; + const char *value = "4444"; + char buffer[triggerBuffer]; + int ret = sprintf_s(buffer, sizeof(buffer), "%s=%s", param, value); + EXPECT_GE(ret, 0); + JobNode *node = AddTrigger(TRIGGER_PARAM, triggerName, buffer, 0); + JobNode *trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + EXPECT_EQ(trigger, node); + if (trigger == nullptr) { + return -1; + } + const uint32_t cmdIndex = 105; + ret = AddCommand(trigger, cmdIndex, value, nullptr); + EXPECT_EQ(ret, 0); + TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_ONCE); + SystemWriteParam(param, value); + + RegisterTriggerExec(TRIGGER_PARAM, TestCmdExec); + FreeTrigger(GetTriggerWorkSpace(), reinterpret_cast(trigger)); + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + EXPECT_NE(g_execCmdId, cmdIndex); + trigger = GetTriggerByName(GetTriggerWorkSpace(), triggerName); + if (trigger != nullptr) { + EXPECT_EQ(1, 0); + } + return 0; + } + + // 测试执行后检查子trigger执行 + int TestExecuteParamTrigger5() + { + const char *boot = "boot2"; + const char *triggerName = "boot2:test_param.5555"; + const char *param = "test_param.dddd.aaa.5555"; + const char *value = "5555"; + JobNode *trigger = AddTrigger(TRIGGER_BOOT, boot, nullptr, 0); + const int testCmdIndex = 1105; + int ret = AddCommand(trigger, testCmdIndex, value, nullptr); + EXPECT_EQ(ret, 0); + if (trigger == nullptr) { + return -1; + } + TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_SUBTRIGGER); + + char buffer[triggerBuffer]; + ret = sprintf_s(buffer, sizeof(buffer), "boot2 && %s=%s", param, value); + EXPECT_GE(ret, 0); + trigger = AddTrigger(TRIGGER_UNKNOW, triggerName, buffer, 0); + const int testCmdIndex2 = 105; + ret = AddCommand(trigger, testCmdIndex2, value, nullptr); + + RegisterTriggerExec(TRIGGER_UNKNOW, TestCmdExec); + SystemWriteParam(param, value); + + TestBootEvent(boot); + LE_DoAsyncEvent(LE_GetDefaultLoop(), GetTriggerWorkSpace()->eventHandle); + EXPECT_EQ(g_execCmdId, (uint32_t)testCmdIndex2); + return 0; + } + + int TestDumpTrigger() + { + (void)AddCompleteJob("param:ohos.servicectrl.display", "ohos.servicectrl.display=*", "display system"); + DoTriggerExec("param:ohos.servicectrl.display"); + return 0; + } +}; + +HWTEST_F(TriggerUnitTest, Init_TestLoadTrigger_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestLoadTrigger(); +} + +HWTEST_F(TriggerUnitTest, Init_TestBootEvent_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestBootEvent("pre-init"); + test.TestBootEvent("init"); + test.TestBootEvent("post-init"); + test.TestBootEvent("early-init"); +} + +HWTEST_F(TriggerUnitTest, Init_TestAddTriggerForBoot_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestAddTriggerForBoot(); +} + +HWTEST_F(TriggerUnitTest, Init_TestAddTriggerForParm_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestAddTriggerForParm(); +} + +HWTEST_F(TriggerUnitTest, Init_TestCheckParamTrigger_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestCheckParamTrigger1(); +} + +HWTEST_F(TriggerUnitTest, Init_TestCheckParamTrigger_002, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestCheckParamTrigger2(); +} + +HWTEST_F(TriggerUnitTest, Init_TestCheckParamTrigger_003, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestCheckParamTrigger3(); +} + +HWTEST_F(TriggerUnitTest, Init_TestCheckParamTrigger_004, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestCheckParamTrigger4(); +} + +HWTEST_F(TriggerUnitTest, Init_TestCheckParamTrigger_005, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestCheckParamTrigger5(); +} + +HWTEST_F(TriggerUnitTest, Init_TestParamEvent_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestParamEvent(); +} + +HWTEST_F(TriggerUnitTest, Init_TestComputerCondition_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestComputeCondition("aaa=111||aaa=222||aaa=333"); + test.TestComputeCondition("aaa=111||aaa=222&&aaa=333"); + test.TestComputeCondition("(aaa=111||aaa=222)&&aaa=333"); + test.TestComputeCondition("aaa=111||(aaa=222&&aaa=333)"); +} + +HWTEST_F(TriggerUnitTest, Init_TestExecuteParamTrigger_001, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestExecuteParamTrigger1(); +} + +HWTEST_F(TriggerUnitTest, Init_TestExecuteParamTrigger_002, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestExecuteParamTrigger2(); +} + +HWTEST_F(TriggerUnitTest, Init_TestExecuteParamTrigger_003, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestExecuteParamTrigger3(); +} + +HWTEST_F(TriggerUnitTest, Init_TestExecuteParamTrigger_004, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestExecuteParamTrigger4(); +} + +HWTEST_F(TriggerUnitTest, Init_TestExecuteParamTrigger_005, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestExecuteParamTrigger5(); +} + +HWTEST_F(TriggerUnitTest, Init_TestExecuteParamTrigger_006, TestSize.Level0) +{ + TriggerUnitTest test; + test.TestDumpTrigger(); + +} diff --git a/test/unittest/param/watcher_agent_unittest.cpp b/test/unittest/param/watcher_agent_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62233f55785cee2111f507fac8fb0755f992bae8 --- /dev/null +++ b/test/unittest/param/watcher_agent_unittest.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2021 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 "if_system_ability_manager.h" +#include "init_param.h" +#include "iservice_registry.h" +#include "iwatcher.h" +#include "iwatcher_manager.h" +#include "message_parcel.h" +#include "parameter.h" +#include "param_manager.h" +#include "param_stub.h" +#include "param_utils.h" +#include "system_ability_definition.h" +#include "watcher.h" +#include "watcher_manager_kits.h" +#include "watcher_manager_proxy.h" +#include "service_watcher.h" + +using namespace testing::ext; +using namespace std; +using namespace OHOS; +using namespace OHOS::init_param; + +int g_callbackCount = 0; +static void TestParameterChange(const char *key, const char *value, void *context) +{ + printf("TestParameterChange key:%s %s \n", key, value); + g_callbackCount++; +} + +static void TestWatcherCallBack(const char *key, const ServiceInfo *status) +{ + printf("TestWatcherCallBack key:%s %d", key, status->status); +} + +class WatcherAgentUnitTest : public ::testing::Test { +public: + WatcherAgentUnitTest() {} + virtual ~WatcherAgentUnitTest() {} + + void SetUp() + { + if (GetParamSecurityLabel() != nullptr) { + GetParamSecurityLabel()->cred.uid = 1000; // 1000 test uid + GetParamSecurityLabel()->cred.gid = 1000; // 1000 test gid + } + SetTestPermissionResult(0); + } + void TearDown() {} + void TestBody() {} + + int TestAddWatcher0(size_t index) + { + int ret = 0; + // has beed deleted + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_NE(ret, 0); + + // delete all + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + index++; + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + ret = RemoveParameterWatcher("test.permission.watcher.test1", nullptr, nullptr); + EXPECT_EQ(ret, 0); + // 非法 + ret = SystemWatchParameter("test.permission.watcher.tes^^^^t1*", TestParameterChange, nullptr); + EXPECT_EQ(ret, PARAM_CODE_INVALID_NAME); + ret = SystemWatchParameter("test.permission.read.test1*", TestParameterChange, nullptr); + EXPECT_EQ(ret, DAC_RESULT_FORBIDED); + return ret; + } + int TestAddWatcher() + { + size_t index = 1; + int ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test1*", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + // repeat add, return fail + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_NE(ret, 0); + index++; + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + index++; + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + + // delete + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + index--; + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + index--; + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + return TestAddWatcher0(index); + } + + int TestDelWatcher() + { + size_t index = 1; + int ret = SystemWatchParameter("test.permission.watcher.test3.1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.1*", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.2", + TestParameterChange, reinterpret_cast(index)); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.2", TestParameterChange, + reinterpret_cast(index)); + EXPECT_EQ(ret, PARAM_WATCHER_CALLBACK_EXIST); + ret = SystemWatchParameter("test.permission.watcher.test3.1", nullptr, nullptr); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.1*", nullptr, nullptr); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.2", nullptr, nullptr); + EXPECT_EQ(ret, 0); + + // 非法 + ret = SystemWatchParameter("test.permission.watcher.tes^^^^t1*", nullptr, nullptr); + EXPECT_EQ(ret, PARAM_CODE_INVALID_NAME); + ret = SystemWatchParameter("test.permission.read.test1*", nullptr, nullptr); + EXPECT_EQ(ret, DAC_RESULT_FORBIDED); + return 0; + } + + int TestRecvMessage(const std::string &name) + { + MessageParcel data; + MessageParcel reply; + MessageOption option; + data.WriteInterfaceToken(IWatcher::GetDescriptor()); + data.WriteString(name); + data.WriteString(name); + data.WriteString("watcherId"); + g_callbackCount = 0; + int ret = SystemWatchParameter(name.c_str(), TestParameterChange, nullptr); + EXPECT_EQ(ret, 0); + WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); + if (instance.remoteWatcher_ != nullptr) { + instance.remoteWatcher_->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); + instance.remoteWatcher_->OnRemoteRequest(IWatcher::PARAM_CHANGE + 1, data, reply, option); + instance.remoteWatcher_->OnParameterChange(name.c_str(), "testname", "testvalue"); + EXPECT_EQ(g_callbackCount, 2); // 2 is callback Count + instance.remoteWatcher_->OnParameterChange(name.c_str(), "testname.2", "testvalue"); + EXPECT_EQ(g_callbackCount, 3); // 3 is callback Count + instance.remoteWatcher_->OnParameterChange(name.c_str(), "testname.2", "testvalue"); + EXPECT_EQ(g_callbackCount, 3); // 3 is callback Count + + // prefix not exit + instance.remoteWatcher_->OnParameterChange("44444444444444444444", "testname.2", "testvalue"); + } + EXPECT_EQ(g_callbackCount, 3); // 3 is callback Count + return 0; + } + + int TestResetService() + { + sptr samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + WATCHER_CHECK(samgr != nullptr, return -1, "Get samgr failed"); + sptr object = samgr->GetSystemAbility(PARAM_WATCHER_DISTRIBUTED_SERVICE_ID); + WATCHER_CHECK(object != nullptr, return -1, "Get watcher manager object from samgr failed"); + OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); + if (instance.GetDeathRecipient() != nullptr) { + instance.GetDeathRecipient()->OnRemoteDied(object); + } + return 0; + } + + void TestWatcherProxy() + { + sptr watcherManager = new(std::nothrow) WatcherManagerProxy(nullptr); + ASSERT_NE(watcherManager, nullptr); + + WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); + sptr remoteWatcher = new OHOS::init_param::WatcherManagerKits::RemoteWatcher(&instance); + ASSERT_NE(remoteWatcher, nullptr); + + MessageParcel data; + MessageParcel reply; + MessageOption option; + data.WriteInterfaceToken(IWatcher::GetDescriptor()); + data.WriteString("name"); + data.WriteString("name"); + data.WriteString("watcherId"); + remoteWatcher->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); + + // invalid parameter + data.WriteInterfaceToken(IWatcher::GetDescriptor()); + data.WriteString("name"); + data.WriteString("watcherId"); + remoteWatcher->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); + + data.WriteInterfaceToken(IWatcher::GetDescriptor()); + data.WriteString("name"); + remoteWatcher->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); + + data.WriteInterfaceToken(IWatcher::GetDescriptor()); + remoteWatcher->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); + + data.WriteInterfaceToken(IWatcher::GetDescriptor()); + data.WriteString("name"); + data.WriteString("name"); + data.WriteString("watcherId"); + remoteWatcher->OnRemoteRequest(IWatcher::PARAM_CHANGE + 1, data, reply, option); + remoteWatcher->OnRemoteRequest(IWatcher::PARAM_CHANGE + 1, data, reply, option); + + uint32_t watcherId = watcherManager->AddRemoteWatcher(1000, remoteWatcher); + // add watcher + int ret = watcherManager->AddWatcher("test.watcher.proxy", watcherId); + ASSERT_EQ(ret, 0); + ret = watcherManager->DelWatcher("test.watcher.proxy", watcherId); + ASSERT_EQ(ret, 0); + ret = watcherManager->RefreshWatcher("test.watcher.proxy", watcherId); + ASSERT_EQ(ret, 0); + watcherManager->DelRemoteWatcher(watcherId); + } +}; + +HWTEST_F(WatcherAgentUnitTest, Init_TestAddWatcher_001, TestSize.Level0) +{ + WatcherAgentUnitTest test; + test.TestAddWatcher(); +} + +HWTEST_F(WatcherAgentUnitTest, Init_TestRecvMessage_001, TestSize.Level0) +{ + WatcherAgentUnitTest test; + test.TestRecvMessage("test.permission.watcher.agent.test1"); +} + +HWTEST_F(WatcherAgentUnitTest, Init_TestDelWatcher_001, TestSize.Level0) +{ + WatcherAgentUnitTest test; + test.TestDelWatcher(); +} + +HWTEST_F(WatcherAgentUnitTest, Init_TestResetService_001, TestSize.Level0) +{ + WatcherAgentUnitTest test; + test.TestResetService(); +} + +HWTEST_F(WatcherAgentUnitTest, Init_TestWatcherService_001, TestSize.Level0) +{ + const char *errstr = "111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; + ServiceWatchForStatus("param_watcher", TestWatcherCallBack); + ServiceWaitForStatus("param_watcher", SERVICE_STARTED, 1); + EXPECT_NE(ServiceWatchForStatus(errstr, TestWatcherCallBack), 0); + EXPECT_NE(ServiceWatchForStatus(nullptr, TestWatcherCallBack), 0); + WatchParameter("testParam", nullptr, nullptr); + WatchParameter(nullptr, nullptr, nullptr); +} + +HWTEST_F(WatcherAgentUnitTest, Init_TestInvalidWatcher_001, TestSize.Level0) +{ + int ret = SystemWatchParameter(nullptr, TestParameterChange, nullptr); + ASSERT_NE(ret, 0); + ret = RemoveParameterWatcher(nullptr, nullptr, nullptr); + ASSERT_NE(ret, 0); +} + +HWTEST_F(WatcherAgentUnitTest, Init_TestWatcherProxy_001, TestSize.Level0) +{ + WatcherAgentUnitTest test; + test.TestWatcherProxy(); +} diff --git a/test/unittest/param/watcher_proxy_unittest.cpp b/test/unittest/param/watcher_proxy_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f9f710535ecb74657b61afdda9426dc08ea1796 --- /dev/null +++ b/test/unittest/param/watcher_proxy_unittest.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2021 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 "if_system_ability_manager.h" +#include "param_stub.h" +#include "iservice_registry.h" +#include "iwatcher.h" +#include "iwatcher_manager.h" +#include "message_parcel.h" +#include "param_message.h" +#include "init_param.h" +#include "param_utils.h" +#include "parcel.h" +#include "securec.h" +#include "system_ability_definition.h" +#include "string_ex.h" +#include "watcher.h" +#include "watcher_manager.h" +#include "watcher_proxy.h" +#include "watcher_utils.h" + +using namespace testing::ext; +using namespace std; +using namespace OHOS; +using namespace OHOS::init_param; + +class TestWatcher final : public Watcher { +public: + TestWatcher() {} + ~TestWatcher() = default; + + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) override + { + printf("TestWatcher::OnParameterChange name %s %s \n", name.c_str(), value.c_str()); + } +}; + +using WatcherManagerPtr = WatcherManager *; +class WatcherProxyUnitTest : public ::testing::Test { +public: + WatcherProxyUnitTest() {} + virtual ~WatcherProxyUnitTest() {} + + void SetUp() + { + if (GetParamSecurityLabel() != nullptr) { + GetParamSecurityLabel()->cred.uid = 0; + GetParamSecurityLabel()->cred.gid = 0; + } + SetTestPermissionResult(0); + } + void TearDown() {} + void TestBody() {} + + int TestAddRemoteWatcher(uint32_t agentId, uint32_t &watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + sptr watcher = new TestWatcher(); + bool ret = data.WriteRemoteObject(watcher->AsObject()); + WATCHER_CHECK(ret, return 0, "Can not get remote"); + data.WriteUint32(agentId); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::ADD_REMOTE_AGENT), data, reply, option); + watcherId = reply.ReadUint32(); + EXPECT_NE(watcherId, 0); + + auto remoteWatcher = watcherManager->GetRemoteWatcher(watcherId); + if (remoteWatcher != nullptr) { + EXPECT_EQ(remoteWatcher->GetAgentId(), agentId); + } else { + EXPECT_EQ(0, agentId); + } + return 0; + } + + int TestDelRemoteWatcher(uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteUint32(watcherId); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::DEL_REMOTE_AGENT), data, reply, option); + EXPECT_EQ(reply.ReadInt32(), 0); + EXPECT_EQ(watcherManager->GetRemoteWatcher(watcherId) == nullptr, 1); + return 0; + } + + int TestAddWatcher(const std::string &keyPrefix, uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + data.WriteUint32(watcherId); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::ADD_WATCHER), data, reply, option); + EXPECT_EQ(reply.ReadInt32(), 0); + EXPECT_EQ(watcherManager->GetWatcherGroup(keyPrefix) != nullptr, 1); + return 0; + } + + int TestRefreshWatcher(const std::string &keyPrefix, uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + data.WriteUint32(watcherId); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::REFRESH_WATCHER), data, reply, option); + EXPECT_EQ(reply.ReadInt32(), 0); + EXPECT_EQ(watcherManager->GetWatcherGroup(keyPrefix) != nullptr, 1); + return 0; + } + + int TestDelWatcher(const std::string &keyPrefix, uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + data.WriteUint32(watcherId); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::DEL_WATCHER), data, reply, option); + EXPECT_EQ(reply.ReadInt32(), 0); + return 0; + } + + int TestProcessWatcherMessage(const std::string &name, uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + const std::string value("test.value"); + uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + value.size(); + msgSize = PARAM_ALIGN(msgSize); // align + std::vector buffer(msgSize, 0); + ParamMessage *msg = reinterpret_cast(buffer.data()); + WATCHER_CHECK(msg != nullptr, return -1, "Invalid msg"); + msg->type = MSG_NOTIFY_PARAM; + msg->msgSize = msgSize; + msg->id.watcherId = watcherId; + int ret = memcpy_s(msg->key, sizeof(msg->key), name.c_str(), name.size()); + WATCHER_CHECK(ret == 0, return -1, "Failed to fill value"); + uint32_t offset = 0; + ret = FillParamMsgContent(msg, &offset, PARAM_VALUE, value.c_str(), value.size()); + WATCHER_CHECK(ret == 0, return -1, "Failed to fill value"); + watcherManager->ProcessWatcherMessage(msg); + return 0; + } + + int TestWatchProxy(const std::string &name, const std::string &value) + { + sptr systemMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(systemMgr, nullptr); + sptr remoteObj = systemMgr->GetSystemAbility(PARAM_WATCHER_DISTRIBUTED_SERVICE_ID); + EXPECT_NE(remoteObj, nullptr); + WatcherProxy *watcher = new WatcherProxy(remoteObj); + if (watcher != nullptr) { + watcher->OnParameterChange(name, name, value); + delete watcher; + } + return 0; + } + + int TestWatchAgentDump(const std::string &keyPrefix) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + // dump watcher + std::vector args = {}; + watcherManager->Dump(STDOUT_FILENO, args); + // dump parameter + args.push_back(Str8ToStr16("-h")); + watcherManager->Dump(STDOUT_FILENO, args); + args.clear(); + args.push_back(Str8ToStr16("-k")); + args.push_back(Str8ToStr16(keyPrefix.c_str())); + watcherManager->Dump(STDOUT_FILENO, args); + return 0; + } + + int TestWatchAgentDied(uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get manager"); + auto remoteWatcher = watcherManager->GetRemoteWatcher(watcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return -1, "Failed to get remote watcher"); + if (watcherManager->GetDeathRecipient() != nullptr) { + watcherManager->GetDeathRecipient()->OnRemoteDied(remoteWatcher->GetWatcher()->AsObject()); + } + EXPECT_EQ(watcherManager->GetRemoteWatcher(watcherId) == nullptr, 1); + return 0; + } + + int TestInvalid(const std::string &keyPrefix) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + data.WriteUint32(0); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::REFRESH_WATCHER) + 1, data, reply, option); + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + watcherManager->OnRemoteRequest( + static_cast (ParamWatcherInterfaceCode::REFRESH_WATCHER) + 1, data, reply, option); + return 0; + } + + int TestStop() + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get manager"); + watcherManager->OnStop(); + watcherManager->Clear(); + return 0; + } + + WatcherManagerPtr GetWatcherManager() + { + static WatcherManagerPtr watcherManager_ = nullptr; + if (watcherManager_ == nullptr) { + watcherManager_ = new WatcherManager(0, true); + if (watcherManager_ == nullptr) { + return nullptr; + } + watcherManager_->OnStart(); + } + return watcherManager_; + } +}; + +HWTEST_F(WatcherProxyUnitTest, Init_TestAddWatcher_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.test1", watcherId); + test.TestRefreshWatcher("test.permission.watcher.test1", watcherId); + test.TestProcessWatcherMessage("test.permission.watcher.test1", watcherId); + test.TestWatchAgentDump("test.permission.watcher.test1"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestAddWatcher_002, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.test2", watcherId); + test.TestAddWatcher("test.permission.watcher.test2", watcherId); + test.TestAddWatcher("test.permission.watcher.test2", watcherId); + test.TestRefreshWatcher("test.permission.watcher.test2", watcherId); + test.TestWatchAgentDump("test.permission.watcher.test2"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestAddWatcher_003, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.test3", watcherId); + test.TestWatchAgentDump("test.permission.watcher.test3"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestAddWatcher_004, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + SystemWriteParam("test.watcher.test4", "1101"); + SystemWriteParam("test.watcher.test4.test", "1102"); + test.TestAddWatcher("test.watcher.test4*", watcherId); + test.TestWatchAgentDump("test.watcher.test4*"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestAddWatcher_005, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.test5", watcherId); + SystemWriteParam("test.permission.watcher.test5", "1101"); + test.TestWatchAgentDump("test.permission.watcher.test5"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestDelWatcher_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.testDel", watcherId); + test.TestDelWatcher("test.permission.watcher.testDel", watcherId); + test.TestDelRemoteWatcher(watcherId); + test.TestWatchAgentDump("test.permission.watcher.testDel"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestDiedWatcher_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.testdied", watcherId); + test.TestDelWatcher("test.permission.watcher.testdied", watcherId); + test.TestWatchAgentDied(watcherId); + test.TestWatchAgentDump("test.permission.watcher.testdied"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestSendLocalChange_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.watcher*", watcherId); + test.TestAddWatcher("test.watcher.", watcherId); + test.TestWatchAgentDump("test.watcher."); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestWatchProxy_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + test.TestWatchProxy("test.permission.watcher.test1", "watcherId"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestInvalid_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + test.TestInvalid("test.permission.watcher.test1"); +} + +HWTEST_F(WatcherProxyUnitTest, Init_TestStop_001, TestSize.Level0) +{ + WatcherProxyUnitTest test; + uint32_t watcherId = 0; + fdsan_set_error_level(FDSAN_ERROR_LEVEL_DISABLED); + + test.TestAddRemoteWatcher(getpid(), watcherId); + test.TestAddWatcher("test.permission.watcher.stop", watcherId); + test.TestStop(); +} \ No newline at end of file diff --git a/test/unittest/remount/remount_overlay_unittest.cpp b/test/unittest/remount/remount_overlay_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0178fe4211e2979c9a3ab4384b94dcfb415e2258 --- /dev/null +++ b/test/unittest/remount/remount_overlay_unittest.cpp @@ -0,0 +1,117 @@ +/* +* 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 "remount_overlay.h" +#include "securec.h" +#include "param_stub.h" +#include "mntent.h" +using namespace std; +using namespace testing::ext; +namespace init_ut { +class RemountOverlayUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp(void) {}; + void TearDown(void) {}; +}; + +HWTEST_F(RemountOverlayUnitTest, Init_MntNeedRemountTest_001, TestSize.Level0) +{ + char *path = "/test"; + bool ret = MntNeedRemount(path); + EXPECT_EQ(ret, false); + + char *path2 = "/"; + ret = MntNeedRemount(path2); + EXPECT_EQ(ret, true); +} + +HWTEST_F(RemountOverlayUnitTest, Init_IsSkipRemountTest_001, TestSize.Level0) +{ + struct mntent mentry; + bool ret = IsSkipRemount(mentry); + EXPECT_EQ(ret, true); + + mentry.mnt_type = "ufs"; + mentry.mnt_dir = "test"; + ret = IsSkipRemount(mentry); + EXPECT_EQ(ret, true); + + mentry.mnt_dir = "/"; + ret = IsSkipRemount(mentry); + EXPECT_EQ(ret, true); + + mentry.mnt_type = "er11ofs"; + ret = IsSkipRemount(mentry); + EXPECT_EQ(ret, true); + + mentry.mnt_type = "erofs"; + mentry.mnt_fsname = "/dev/block/ndm-"; + ret = IsSkipRemount(mentry); + EXPECT_EQ(ret, true); + + mentry.mnt_fsname = "/dev/block/dm-1"; + ret = IsSkipRemount(mentry); + EXPECT_EQ(ret, false); +} + +HWTEST_F(RemountOverlayUnitTest, Init_ExecCommand_001, TestSize.Level0) +{ + char *nullArgv[] = {NULL}; // A valid command + int result = ExecCommand(0, nullArgv); + EXPECT_NE(result, 0); // Expect success + + char *validArgv[] = {"/bin/ls", NULL}; // A valid command + result = ExecCommand(1, validArgv); + EXPECT_NE(result, 0); // Expect success + + char *invalidArgv[] = {"/notexit/ls", NULL}; // A valid command + result = ExecCommand(1, invalidArgv); + EXPECT_NE(result, 0); // Expect success +} + +HWTEST_F(RemountOverlayUnitTest, Init_GetDevSizeTest_001, TestSize.Level0) +{ + const char *fileName = ""; + int ret = GetDevSize(fileName, NULL); + EXPECT_EQ(ret, -1); + fileName = STARTUP_INIT_UT_PATH "/data/getDevSize"; + CheckAndCreateDir(fileName); + ret = GetDevSize(fileName, NULL); + EXPECT_EQ(ret, -1); + + uint64_t devSize; + ret = GetDevSize(fileName, &devSize); + EXPECT_NE(ret, 0); + remove(fileName); +} +HWTEST_F(RemountOverlayUnitTest, Init_FormatExt4Test_001, TestSize.Level0) +{ + const char *fileName = ""; + int ret = GetDevSize(fileName, NULL); + EXPECT_EQ(ret, -1); + fileName = STARTUP_INIT_UT_PATH "/data/getDevSize"; + CheckAndCreateDir(fileName); + ret = GetDevSize(fileName, NULL); + EXPECT_EQ(ret, -1); + + uint64_t devSize; + ret = GetDevSize(fileName, &devSize); + EXPECT_NE(ret, 0); + remove(fileName); +} + +} \ No newline at end of file diff --git a/test/unittest/seccomp/seccomp_unittest.cpp b/test/unittest/seccomp/seccomp_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67a9e946a88f23e06a5a1589a8edfc5e26f4901e --- /dev/null +++ b/test/unittest/seccomp/seccomp_unittest.cpp @@ -0,0 +1,1181 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "seccomp_policy.h" + +using SyscallFunc = bool (*)(void); +constexpr int SLEEP_TIME_100MS = 100000; // 100ms +constexpr int SLEEP_TIME_1S = 1; + +using namespace testing::ext; +using namespace std; + +namespace init_ut { +class SeccompUnitTest : public testing::Test { +public: + SeccompUnitTest() {}; + virtual ~SeccompUnitTest() {}; + static void SetUpTestCase() {}; + static void TearDownTestCase() {}; + + void SetUp() + { + /* + * Wait for 1 second to prevent the generated crash file + * from being overwritten because the crash interval is too short + * and the crash file's name is constructed by time stamp. + */ + sleep(SLEEP_TIME_1S); + }; + + void TearDown() {}; + void TestBody(void) {}; + + static pid_t StartChild(SeccompFilterType type, const char *filterName, SyscallFunc func) + { + pid_t pid = fork(); + if (pid == 0) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) { + std::cout << "PR_SET_NO_NEW_PRIVS set fail " << std::endl; + exit(EXIT_FAILURE); + } + + if (!SetSeccompPolicyWithName(type, filterName)) { + std::cout << "SetSeccompPolicy set fail fiterName is " << filterName << std::endl; + exit(EXIT_FAILURE); + } + + if (!func()) { + std::cout << "func excute fail" << std::endl; + exit(EXIT_FAILURE); + } + + std::cout << "func excute success" << std::endl; + + exit(EXIT_SUCCESS); + } + return pid; + } + + static int CheckStatus(int status, bool isAllow) + { + if (WEXITSTATUS(status) == EXIT_FAILURE) { + return -1; + } + + if (WIFSIGNALED(status)) { + if (WTERMSIG(status) == SIGSYS) { + std::cout << "child process exit with SIGSYS" << std::endl; + return isAllow ? -1 : 0; + } + } else { + std::cout << "child process finished normally" << std::endl; + return isAllow ? 0 : -1; + } + + return -1; + } + + static int CheckSyscall(SeccompFilterType type, const char *filterName, SyscallFunc func, bool isAllow) + { + sigset_t set; + int status; + pid_t pid; + int flag = 0; + struct timespec waitTime = {5, 0}; + + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, nullptr); + sigaddset(&set, SIGSYS); + if (signal(SIGCHLD, SIG_DFL) == nullptr) { + std::cout << "signal failed:" << strerror(errno) << std::endl; + } + if (signal(SIGSYS, SIG_DFL) == nullptr) { + std::cout << "signal failed:" << strerror(errno) << std::endl; + } + + /* Sleeping for avoiding influencing child proccess wait for other threads + * which were created by other unittests to release global rwlock. The global + * rwlock will be used by function dlopen in child process */ + usleep(SLEEP_TIME_100MS); + + pid = StartChild(type, filterName, func); + if (pid == -1) { + std::cout << "fork failed:" << strerror(errno) << std::endl; + return -1; + } + if (sigtimedwait(&set, nullptr, &waitTime) == -1) { /* Wait for 5 seconds */ + if (errno == EAGAIN) { + flag = 1; + } else { + std::cout << "sigtimedwait failed:" << strerror(errno) << std::endl; + } + + if (kill(pid, SIGKILL) == -1) { + std::cout << "kill failed::" << strerror(errno) << std::endl; + } + } + + if (waitpid(pid, &status, 0) != pid) { + std::cout << "waitpid failed:" << strerror(errno) << std::endl; + return -1; + } + + if (flag != 0) { + std::cout << "Child process time out" << std::endl; + } + + return CheckStatus(status, isAllow); + } + + static bool CheckUnshare() + { + int ret = unshare(CLONE_NEWPID); + if (ret) { + return false; + } + return true; + } + + static bool CheckSetns() + { + int fd = open("/proc/1/ns/mnt", O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return false; + } + + if (setns(fd, CLONE_NEWNS) != 0) { + close(fd); + return false; + } + + close(fd); + return true; + } + + static int ChildFunc(void *arg) + { + exit(0); + } + + static bool CheckCloneNs(int flag) + { + const int stackSize = 65536; + + char *stack = static_cast(malloc(stackSize)); + if (stack == nullptr) { + return false; + } + char *stackTop = stack + stackSize; + pid_t pid = clone(ChildFunc, stackTop, flag | SIGCHLD, nullptr); + if (pid == -1) { + free(stack); + return false; + } + return true; + } + + static bool CheckClonePidNs(void) + { + return CheckCloneNs(CLONE_NEWPID); + } + + static bool CheckCloneMntNs(void) + { + return CheckCloneNs(CLONE_NEWNS); + } + + static bool CheckCloneNetNs(void) + { + return CheckCloneNs(CLONE_NEWNET); + } + + static bool CheckCloneCgroupNs(void) + { + return CheckCloneNs(CLONE_NEWCGROUP); + } + + static bool CheckCloneUtsNs(void) + { + return CheckCloneNs(CLONE_NEWUTS); + } + + static bool CheckCloneIpcNs(void) + { + return CheckCloneNs(CLONE_NEWIPC); + } + + static bool CheckCloneUserNs(void) + { + return CheckCloneNs(CLONE_NEWUSER); + } + +#if defined __aarch64__ + static bool CheckMqOpen() + { + int ret = (int)syscall(__NR_mq_open, nullptr, 0); + if (ret < 0) { + return false; + } + + return true; + } + + static bool CheckGetpid() + { + pid_t pid = 1; + pid = syscall(__NR_getpid); + if (pid > 1) { + return true; + } + return false; + } + + static bool CheckGetuid() + { + uid_t uid = 0; + uid = syscall(__NR_getuid); + if (uid >= 0) { + return true; + } + + return false; + } + + static bool CheckSetresuidArgsInRange() + { + int ret = syscall(__NR_setresuid, 20000, 20000, 20000); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuidArgsOutOfRange() + { + int ret = syscall(__NR_setresuid, 800, 800, 800); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid() + { + int uid = syscall(__NR_setuid, 1); + if (uid == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid64ForUidFilter1() + { + int ret = syscall(__NR_setuid, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid64ForUidFilter2() + { + int ret = syscall(__NR_setuid, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid64ForUidFilter1() + { + int ret = syscall(__NR_setreuid, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid64ForUidFilter2() + { + int ret = syscall(__NR_setreuid, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid64ForUidFilter3() + { + int ret = syscall(__NR_setreuid, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid64ForUidFilter4() + { + int ret = syscall(__NR_setreuid, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetfsuid64ForUidFilter1() + { + int ret = syscall(__NR_setfsuid, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetfsuid64ForUidFilter2() + { + int ret = syscall(__NR_setfsuid, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter1() + { + int ret = syscall(__NR_setresuid, 0, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter2() + { + int ret = syscall(__NR_setresuid, 2, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter3() + { + int ret = syscall(__NR_setresuid, 0, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter4() + { + int ret = syscall(__NR_setresuid, 0, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter5() + { + int ret = syscall(__NR_setresuid, 0, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter6() + { + int ret = syscall(__NR_setresuid, 2, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter7() + { + int ret = syscall(__NR_setresuid, 2, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid64ForUidFilter8() + { + int ret = syscall(__NR_setresuid, 2, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + void TestSystemSycall() + { + // system blocklist + int ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckMqOpen, false); + EXPECT_EQ(ret, 0); + + // system allowlist + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckGetpid, true); + EXPECT_EQ(ret, 0); + } + + void TestSystemSyscallForUidFilter() + { + // system_uid_filter_64bit_test + int ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetuid64ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetuid64ForUidFilter2, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid64ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid64ForUidFilter2, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid64ForUidFilter3, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid64ForUidFilter4, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetfsuid64ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetfsuid64ForUidFilter2, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter2, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter3, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter4, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter5, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter6, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter7, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid64ForUidFilter8, true); + EXPECT_EQ(ret, 0); + } + + void TestSetUidGidFilter() + { + // system blocklist + int ret = CheckSyscall(INDIVIDUAL, APPSPAWN_NAME, CheckSetresuidArgsOutOfRange, false); + EXPECT_EQ(ret, 0); + + // system allowlist + ret = CheckSyscall(INDIVIDUAL, APPSPAWN_NAME, CheckSetresuidArgsInRange, true); + EXPECT_EQ(ret, 0); + } + + void TestAppSycall() + { + // app blocklist + int ret = CheckSyscall(APP, APP_NAME, CheckSetuid, false); + EXPECT_EQ(ret, 0); + + // app allowlist + ret = CheckSyscall(APP, APP_NAME, CheckGetpid, true); + EXPECT_EQ(ret, 0); + } +#ifdef SECCOMP_PRIVILEGE + void TestSeccompPrivilegeSyscall() + { + int ret = CheckSyscall(APP, APP_PRIVILEGE, CheckSetuid64ForUidFilter1, true); + EXPECT_EQ(ret, 0); + } +#endif + +#elif defined __arm__ + static bool CheckGetuid32() + { + uid_t uid = syscall(__NR_getuid32); + if (uid >= 0) { + return true; + } + return false; + } + + static bool CheckGetuid() + { + uid_t uid = syscall(__NR_getuid); + if (uid >= 0) { + return true; + } + return false; + } + + static bool CheckSetuid32() + { + int ret = syscall(__NR_setuid32, 1); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ArgsInRange() + { + int ret = syscall(__NR_setresuid32, 20000, 20000, 20000); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ArgsOutOfRange() + { + int ret = syscall(__NR_setresuid32, 800, 800, 800); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid32ForUidFilter1() + { + int ret = syscall(__NR_setuid32, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid32ForUidFilter2() + { + int ret = syscall(__NR_setuid32, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid16ForUidFilter1() + { + int ret = syscall(__NR_setuid, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetuid16ForUidFilter2() + { + int ret = syscall(__NR_setuid, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid32ForUidFilter1() + { + int ret = syscall(__NR_setreuid32, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid32ForUidFilter2() + { + int ret = syscall(__NR_setreuid32, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid32ForUidFilter3() + { + int ret = syscall(__NR_setreuid32, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid32ForUidFilter4() + { + int ret = syscall(__NR_setreuid32, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid16ForUidFilter1() + { + int ret = syscall(__NR_setreuid, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid16ForUidFilter2() + { + int ret = syscall(__NR_setreuid, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid16ForUidFilter3() + { + int ret = syscall(__NR_setreuid, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetreuid16ForUidFilter4() + { + int ret = syscall(__NR_setreuid, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetfsuid32ForUidFilter1() + { + int ret = syscall(__NR_setfsuid32, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetfsuid32ForUidFilter2() + { + int ret = syscall(__NR_setfsuid32, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetfsuid16ForUidFilter1() + { + int ret = syscall(__NR_setfsuid, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetfsuid16ForUidFilter2() + { + int ret = syscall(__NR_setfsuid, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter1() + { + int ret = syscall(__NR_setresuid32, 0, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter2() + { + int ret = syscall(__NR_setresuid32, 2, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter3() + { + int ret = syscall(__NR_setresuid32, 0, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter4() + { + int ret = syscall(__NR_setresuid32, 0, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter5() + { + int ret = syscall(__NR_setresuid32, 0, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter6() + { + int ret = syscall(__NR_setresuid32, 2, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter7() + { + int ret = syscall(__NR_setresuid32, 2, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid32ForUidFilter8() + { + int ret = syscall(__NR_setresuid32, 2, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter1() + { + int ret = syscall(__NR_setresuid, 0, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter2() + { + int ret = syscall(__NR_setresuid, 2, 0, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter3() + { + int ret = syscall(__NR_setresuid, 0, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter4() + { + int ret = syscall(__NR_setresuid, 0, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter5() + { + int ret = syscall(__NR_setresuid, 0, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter6() + { + int ret = syscall(__NR_setresuid, 2, 0, 2); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter7() + { + int ret = syscall(__NR_setresuid, 2, 2, 0); + if (ret == 0) { + return true; + } + + return false; + } + + static bool CheckSetresuid16ForUidFilter8() + { + int ret = syscall(__NR_setresuid, 2, 2, 2); + if (ret == 0) { + return true; + } + + return false; + } + + void TestSystemSycall() + { + // system blocklist + int ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckGetuid, false); + EXPECT_EQ(ret, 0); + + // system allowlist + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckGetuid32, true); + EXPECT_EQ(ret, 0); + } + + void TestSystemSyscallForUidFilter32Bit() + { + // system_uid_filter_32bit_test + int ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetuid32ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetuid32ForUidFilter2, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid32ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid32ForUidFilter2, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid32ForUidFilter3, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid32ForUidFilter4, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetfsuid32ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetfsuid32ForUidFilter2, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter2, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter3, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter4, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter5, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter6, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter7, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid32ForUidFilter8, true); + EXPECT_EQ(ret, 0); + } + + void TestSystemSyscallForUidFilter16Bit() + { + // system_uid_filter_16bit_test + int ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetuid16ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetuid16ForUidFilter2, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid16ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid16ForUidFilter2, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid16ForUidFilter3, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetreuid16ForUidFilter4, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetfsuid16ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetfsuid16ForUidFilter2, true); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter1, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter2, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter3, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter4, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter5, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter6, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter7, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(SYSTEM_SA, SYSTEM_NAME, CheckSetresuid16ForUidFilter8, true); + EXPECT_EQ(ret, 0); + } + + void TestSystemSyscallForUidFilter() + { + TestSystemSyscallForUidFilter32Bit(); + TestSystemSyscallForUidFilter16Bit(); + } + + void TestSetUidGidFilter() + { + // system blocklist + int ret = CheckSyscall(INDIVIDUAL, APPSPAWN_NAME, CheckSetresuid32ArgsOutOfRange, false); + EXPECT_EQ(ret, 0); + + // system allowlist + ret = CheckSyscall(INDIVIDUAL, APPSPAWN_NAME, CheckSetresuid32ArgsInRange, true); + EXPECT_EQ(ret, 0); + } + + void TestAppSycall() + { + // app blocklist + int ret = CheckSyscall(APP, APP_NAME, CheckSetuid32, false); + EXPECT_EQ(ret, 0); + + // app allowlist + ret = CheckSyscall(APP, APP_NAME, CheckGetuid32, true); + EXPECT_EQ(ret, 0); + } + +#ifdef SECCOMP_PRIVILEGE + void TestSeccompPrivilegeSyscall() + { + int ret = CheckSyscall(APP, APP_PRIVILEGE, CheckSetuid32ForUidFilter1, true); + EXPECT_EQ(ret, 0); + } +#endif +#endif + void TestAppSycallNs() + { + int ret = CheckSyscall(APP, APP_NAME, CheckUnshare, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckSetns, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckClonePidNs, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckCloneMntNs, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckCloneCgroupNs, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckCloneIpcNs, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckCloneUserNs, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckCloneNetNs, false); + EXPECT_EQ(ret, 0); + + ret = CheckSyscall(APP, APP_NAME, CheckCloneUtsNs, false); + EXPECT_EQ(ret, 0); + } +}; + +/** + * @tc.name: TestSystemSycall + * @tc.desc: Verify the system seccomp policy. + * @tc.type: FUNC + * @tc.require: issueI5IUWJ + */ +HWTEST_F(SeccompUnitTest, Init_Seccomp_SystemSycall001, TestSize.Level1) +{ + SeccompUnitTest test; + test.TestSystemSycall(); +} + +/** + * @tc.name: TestSetUidGidFilter + * @tc.desc: Verify the uid gid seccomp policy. + * @tc.type: FUNC + * @tc.require: issueI5IUWJ + */ +HWTEST_F(SeccompUnitTest, Init_Seccomp_SetUidGidFilter001, TestSize.Level1) +{ + SeccompUnitTest test; + test.TestSetUidGidFilter(); +} + +/** + * @tc.name: TestAppSycall + * @tc.desc: Verify the app seccomp policy. + * @tc.type: FUNC + * @tc.require: issueI5MUXD + */ +HWTEST_F(SeccompUnitTest, Init_Seccomp_AppSycall001, TestSize.Level1) +{ + SeccompUnitTest test; + test.TestAppSycall(); +} + +/** + * @tc.name: TestSystemSyscallForUidFilter + * @tc.desc: Verify the system seccomp policy. + * @tc.type: FUNC + * @tc.require: issueI7QET2 + */ +HWTEST_F(SeccompUnitTest, Init_Seccomp_SystemSyscallForUidFilter001, TestSize.Level1) +{ + SeccompUnitTest test; + test.TestSystemSyscallForUidFilter(); +} + +/** + * @tc.name: TestAppSycallNs + * @tc.desc: Verify the app seccomp policy about namespace. + * @tc.type: FUNC + * @tc.require: issueI8LZTC + */ +HWTEST_F(SeccompUnitTest, Init_Seccomp_AppSycallNs001, TestSize.Level1) +{ + SeccompUnitTest test; + test.TestAppSycallNs(); +} +#ifdef SECCOMP_PRIVILEGE +/** + * @tc.name: TestSeccompPrivilegeSyscall + * @tc.desc: Verify the privilege syscall of app and appspawn. + * @tc.type: FUNC + * @tc.require: issueIAVQ2P + */ +HWTEST_F(SeccompUnitTest, Init_Seccomp_SeccompPrivilegeSycall001, TestSize.Level1) +{ + SeccompUnitTest test; + test.TestSeccompPrivilegeSyscall(); +} +#endif +} diff --git a/test/unittest/syspara/syspara_unittest.cpp b/test/unittest/syspara/syspara_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..880bb6017c3ee4f754d0cbc1eb90c81c4f249b4f --- /dev/null +++ b/test/unittest/syspara/syspara_unittest.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2021 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 "gtest/gtest.h" + +#include "init_param.h" +#include "init_utils.h" +#include "parameter.h" +#include "param_comm.h" +#include "param_stub.h" +#ifndef OHOS_LITE +#include "param_wrapper.h" +#include "parameters.h" +#endif +#include "sysversion.h" +#include "sysparam_errno.h" + +using namespace testing::ext; + +namespace OHOS { +constexpr int TEST_VALUE = 101; +class SysparaUnitTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() + { + SetTestPermissionResult(0); + } + void TearDown() {} +}; + +HWTEST_F(SysparaUnitTest, parameterTest001, TestSize.Level0) +{ + printf("Device type =%s\n", GetDeviceType()); + printf("Manufacture =%s\n", GetManufacture()); + printf("GetBrand =%s\n", GetBrand()); + printf("MarketName =%s\n", GetMarketName()); + printf("ProductSeries =%s\n", GetProductSeries()); + printf("ProductModel =%s\n", GetProductModel()); + printf("ProductModelAlias =%s\n", GetProductModelAlias()); + printf("SoftwareModel =%s\n", GetSoftwareModel()); + printf("HardwareModel =%s\n", GetHardwareModel()); + printf("Software profile =%s\n", GetHardwareProfile()); + printf("Serial =%s\n", GetSerial()); + printf("OS full name =%s\n", GetOSFullName()); + printf("OS Release type =%s\n", GetOsReleaseType()); + printf("Display version =%s\n", GetDisplayVersion()); + printf("bootloader version =%s\n", GetBootloaderVersion()); + printf("secure patch level =%s\n", GetSecurityPatchTag()); +} + +HWTEST_F(SysparaUnitTest, parameterTest001_1, TestSize.Level0) +{ + printf("secure patch level =%s\n", GetSecurityPatchTag()); + printf("abi list =%s\n", GetAbiList()); + printf("first api version =%d\n", GetFirstApiVersion()); + printf("SDK api version =%d\n", GetSdkApiVersion()); + printf("Incremental version = %s\n", GetIncrementalVersion()); + printf("formal id =%s\n", GetVersionId()); + printf("build type =%s\n", GetBuildType()); + printf("build user =%s\n", GetBuildUser()); + printf("Build host = %s\n", GetBuildHost()); + printf("build time =%s\n", GetBuildTime()); + printf("build root later..., %s\n", GetBuildRootHash()); +} + +HWTEST_F(SysparaUnitTest, parameterTest001_2, TestSize.Level0) +{ + EXPECT_STRNE(GetDeviceType(), nullptr); + EXPECT_STRNE(GetManufacture(), nullptr); + EXPECT_STRNE(GetBrand(), nullptr); + EXPECT_STRNE(GetMarketName(), nullptr); + EXPECT_STRNE(GetProductSeries(), nullptr); + EXPECT_STRNE(GetProductModel(), nullptr); + EXPECT_STRNE(GetProductModelAlias(), nullptr); + EXPECT_STRNE(GetSoftwareModel(), nullptr); + EXPECT_STRNE(GetHardwareModel(), nullptr); + EXPECT_STRNE(GetHardwareProfile(), nullptr); + EXPECT_STRNE(GetOSFullName(), nullptr); + EXPECT_STRNE(GetOsReleaseType(), nullptr); + EXPECT_STRNE(GetDisplayVersion(), nullptr); + EXPECT_STRNE(GetBootloaderVersion(), nullptr); + EXPECT_STRNE(GetSecurityPatchTag(), nullptr); +} + +HWTEST_F(SysparaUnitTest, parameterTest001_3, TestSize.Level0) +{ + EXPECT_STRNE(GetSecurityPatchTag(), nullptr); + EXPECT_STRNE(GetAbiList(), nullptr); + EXPECT_GT(GetFirstApiVersion(), 0); + EXPECT_GT(GetSdkApiVersion(), 0); + EXPECT_STRNE(GetIncrementalVersion(), nullptr); + EXPECT_STRNE(GetVersionId(), nullptr); + EXPECT_STRNE(GetBuildType(), nullptr); + EXPECT_STRNE(GetBuildUser(), nullptr); + EXPECT_STRNE(GetBuildHost(), nullptr); + EXPECT_STRNE(GetBuildTime(), nullptr); + EXPECT_STRNE(GetBuildRootHash(), nullptr); +} + +HWTEST_F(SysparaUnitTest, parameterTest002, TestSize.Level0) +{ + char key1[] = "test.ro.sys.version"; + char value1[] = "set read only key"; + int ret = SetParameter(key1, value1); + EXPECT_EQ(ret, EC_SUCCESS); + ret = SetParameter(nullptr, nullptr); + EXPECT_EQ(ret, EC_INVALID); +} + +HWTEST_F(SysparaUnitTest, parameterTest003, TestSize.Level0) +{ + char key2[] = "rw.sys.version*%version"; + char value2[] = "set value with illegal key"; + int ret = SetParameter(key2, value2); + EXPECT_EQ(ret, EC_INVALID); +} + +/* key = 32 */ +HWTEST_F(SysparaUnitTest, parameterTest004, TestSize.Level0) +{ + char key3[] = "rw.sys.version.utilskvparameter0"; + char value3[] = "set with key = 32"; + int ret = SetParameter(key3, value3); + EXPECT_EQ(ret, EC_SUCCESS); +} + +/* value > 128 */ +HWTEST_F(SysparaUnitTest, parameterTest005, TestSize.Level0) +{ + char key4[] = "rw.sys.version.version"; + char value4[] = "rw.sys.version.version.version.version flash_offset = *(hi_u32 *)DT_SetGetU32(&g_Element[0], 0)a\ + size = *(hi_u32 *)DT_SetGetU32(&g_Element[1], 0)a"; + int ret = SetParameter(key4, value4); + EXPECT_EQ(ret, SYSPARAM_INVALID_VALUE); +} + +HWTEST_F(SysparaUnitTest, parameterTest006, TestSize.Level0) +{ + char key1[] = "rw.product.not.exist"; + char value1[64] = {0}; + char defValue1[] = "value of key not exist..."; + int ret = GetParameter(key1, defValue1, value1, 64); + EXPECT_EQ(ret, static_cast(strlen(defValue1))); +} + +HWTEST_F(SysparaUnitTest, parameterTest007, TestSize.Level0) +{ + char key2[] = "rw.sys.version.version.version.version"; + char value2[64] = {0}; + char defValue2[] = "value of key > 32 ..."; + int ret = GetParameter(key2, defValue2, value2, 64); + EXPECT_EQ(ret, static_cast(strlen(defValue2))); +} + +HWTEST_F(SysparaUnitTest, parameterTest008, TestSize.Level0) +{ + char key4[] = "test.rw.sys.version"; + char* value4 = nullptr; + char defValue3[] = "value of key > 32 ..."; + int ret = GetParameter(key4, defValue3, value4, 0); + EXPECT_EQ(ret, EC_INVALID); +} + +HWTEST_F(SysparaUnitTest, parameterTest009, TestSize.Level0) +{ + char key5[] = "test.rw.product.type.2222222"; + char value5[] = "rw.sys.version.version.version.version \ + flash_offset = *(hi_u32 *)DT_SetGetU32(&g_Element[0], 0)"; + int ret = SetParameter(key5, value5); + EXPECT_EQ(ret, SYSPARAM_INVALID_VALUE); + char valueGet[2] = {0}; + char defValue3[] = "value of key > 32 ..."; + ret = GetParameter(key5, defValue3, valueGet, 2); + EXPECT_EQ(ret, EC_INVALID); +} + +HWTEST_F(SysparaUnitTest, parameterTest0010, TestSize.Level0) +{ + char key1[] = "test.rw.sys.version"; + char value1[] = "10.1.0"; + int ret = SetParameter(key1, value1); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam(key1, value1); + EXPECT_EQ(ret, 0); + char valueGet1[32] = {0}; + ret = GetParameter(key1, "version=10.1.0", valueGet1, 32); + EXPECT_EQ(ret, static_cast(strlen(valueGet1))); + + char key2[] = "test.rw.product.type"; + char value2[] = "wifi_iot"; + ret = SetParameter(key2, value2); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam(key2, value2); + EXPECT_EQ(ret, 0); + char valueGet2[32] = {0}; + ret = GetParameter(key2, "version=10.1.0", valueGet2, 32); + EXPECT_EQ(ret, static_cast(strlen(valueGet2))); + + char key3[] = "test.rw.product.manufacturer"; + char value3[] = "TEST MANUFACTURER"; + ret = SetParameter(key3, value3); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam(key3, value3); + EXPECT_EQ(ret, 0); + char valueGet3[32] = {0}; + ret = GetParameter(key3, "version=10.1.0", valueGet3, 32); + EXPECT_EQ(ret, static_cast(strlen(valueGet3))); + + char key4[] = "test.rw.product.marketname"; + char value4[] = "TEST MARKETNAME"; + ret = SetParameter(key4, value4); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam(key4, value4); + EXPECT_EQ(ret, 0); + char valueGet4[32] = {0}; + ret = GetParameter(key4, "version=10.1.0", valueGet4, 32); + EXPECT_EQ(ret, static_cast(strlen(valueGet4))); +} + +HWTEST_F(SysparaUnitTest, parameterTest0011, TestSize.Level0) +{ + char key1[] = "test.rw.sys.version.wait1"; + char value1[] = "10.1.0"; + int ret = SetParameter(key1, value1); + EXPECT_EQ(ret, 0); + ret = SystemWriteParam(key1, value1); + EXPECT_EQ(ret, 0); + ret = WaitParameter(key1, value1, 10); + EXPECT_EQ(ret, 0); + ret = WaitParameter(key1, "*", 10); + EXPECT_EQ(ret, 0); + char key2[] = "test.rw.sys.version.wait2"; + ret = WaitParameter(key2, "*", 1); + EXPECT_EQ(ret, SYSPARAM_WAIT_TIMEOUT); +} + +HWTEST_F(SysparaUnitTest, parameterTest0012, TestSize.Level0) +{ + char key1[] = "test.rw.sys.version.version1"; + char value1[] = "10.1.0"; + int ret = SetParameter(key1, value1); + EXPECT_EQ(ret, 0); + + ret = SystemWriteParam(key1, value1); + EXPECT_EQ(ret, 0); + // success + unsigned int handle = FindParameter(key1); + EXPECT_NE(handle, static_cast(-1)); + char valueGet1[32] = {0}; + ret = GetParameterValue(handle, valueGet1, 32); + EXPECT_EQ(ret, static_cast(strlen(valueGet1))); + char nameGet1[32] = {0}; + ret = GetParameterName(handle, nameGet1, 32); + EXPECT_EQ(ret, static_cast(strlen(nameGet1))); + + // fail + char key2[] = "test.rw.sys.version.version2"; + handle = FindParameter(key2); + EXPECT_EQ(handle, static_cast(-1)); + ret = GetParameterValue(handle, valueGet1, 32); + EXPECT_EQ(ret, SYSPARAM_NOT_FOUND); + ret = GetParameterName(handle, nameGet1, 32); + EXPECT_EQ(ret, SYSPARAM_NOT_FOUND); + ret = GetParameterValue(handle, nullptr, 32); + EXPECT_EQ(ret, EC_INVALID); + ret = GetParameterCommitId(handle); + EXPECT_EQ(ret, -1); +} + +HWTEST_F(SysparaUnitTest, parameterTest0013, TestSize.Level0) +{ + long long int out = 0; + unsigned long long int uout = 0; + GetParameter_(nullptr, nullptr, nullptr, 0); + EXPECT_EQ(GetIntParameter("test.int.get", 0) == -TEST_VALUE, 1); + EXPECT_EQ(GetUintParameter("test.int.get", 0), 0); + EXPECT_EQ(GetIntParameter("test.uint.get", 0), TEST_VALUE); + EXPECT_EQ(GetUintParameter("test.uint.get", 0), TEST_VALUE); + EXPECT_EQ(GetIntParameter("test.int.default", 10), 10); // key not find,value = default + EXPECT_EQ(GetUintParameter("test.uint.default", 10), 10); // key not find,value = default + EXPECT_EQ(IsValidParamValue(nullptr, 0), 0); + EXPECT_EQ(IsValidParamValue("testvalue", strlen("testvalue") + 1), 1); + EXPECT_EQ(StringToLL("0x11", &out), 0); + EXPECT_EQ(StringToULL("0x11", &uout), 0); + EXPECT_EQ(StringToLL("not vailed", &out), -1); + EXPECT_EQ(StringToULL("not vailed", &uout), -1); + char udid[UDID_LEN] = {0}; + GetDevUdid(udid, UDID_LEN); + EXPECT_NE(GetMajorVersion(), 0); + int ret = GetDevUdid(nullptr, UDID_LEN); + EXPECT_EQ(ret, EC_FAILURE); + GetSeniorVersion(); + GetFeatureVersion(); + GetBuildVersion(); +} + +#ifndef OHOS_LITE +// for test param_wrapper.cpp +HWTEST_F(SysparaUnitTest, parameterTest0014, TestSize.Level0) +{ + const std::string key1 = "test.int.get"; + OHOS::system::SetParameter(std::string("testKey"), std::string("testValue")); + int v = OHOS::system::GetIntParameter(key1, 0); + EXPECT_EQ(v, -TEST_VALUE); + int8_t v1 = OHOS::system::GetIntParameter(key1, 0, -127, 128); // -127, 128 range + EXPECT_EQ(v1, -TEST_VALUE); + int16_t v2 = OHOS::system::GetIntParameter(key1, 0, -127, 128); // -127, 128 range + EXPECT_EQ(v2, -TEST_VALUE); + int32_t v3 = OHOS::system::GetIntParameter(key1, 0, -127, 128); // -127, 128 range + EXPECT_EQ(v3, -TEST_VALUE); + int64_t v4 = OHOS::system::GetIntParameter(key1, 0, -127, 128); // -127, 128 range + EXPECT_EQ(v4, -TEST_VALUE); + + int8_t v5 = OHOS::system::GetIntParameter(key1, 0, -10, 10); // -10, 10 range + EXPECT_EQ(v5, 0); + + const std::string key2 = "test.uint.get"; + uint8_t u1 = OHOS::system::GetUintParameter(key2, 0, (uint8_t)255); // 255 max value + EXPECT_EQ(u1, TEST_VALUE); + uint16_t u2 = OHOS::system::GetUintParameter(key2, 0, (uint16_t)255); // 255 max value + EXPECT_EQ(u2, TEST_VALUE); + uint32_t u3 = OHOS::system::GetUintParameter(key2, 0, (uint32_t)255); // 255 max value + EXPECT_EQ(u3, TEST_VALUE); + uint64_t u4 = OHOS::system::GetUintParameter(key2, 0, (uint64_t)255); // 255 max value + EXPECT_EQ(u4 == TEST_VALUE, 1); + const std::string key3 = "test.uint.get3"; + u1 = OHOS::system::GetUintParameter(key3, 0, (uint8_t)255); // 255 max value + EXPECT_EQ(u1, 0); + u1 = OHOS::system::GetUintParameter(key2, 0, (uint8_t)10); // 10 max value + EXPECT_EQ(u1, 0); +} + +HWTEST_F(SysparaUnitTest, parameterTest0015, TestSize.Level0) +{ + std::string type = OHOS::system::GetDeviceType(); + printf("device type %s \n", type.c_str()); + + const std::string key1 = "test.string.get"; + std::string v1 = OHOS::system::GetParameter(key1, ""); + EXPECT_EQ(strcmp(v1.c_str(), "101"), 0); + + const std::string key2 = "test.string.get2"; + v1 = OHOS::system::GetParameter(key2, "test2"); + EXPECT_EQ(strcmp(v1.c_str(), "test2"), 0); + + int ret = OHOS::system::GetStringParameter(key1, v1, ""); + EXPECT_EQ(ret, 0); + EXPECT_EQ(strcmp(v1.c_str(), "101"), 0); + ret = OHOS::system::GetStringParameter(key2, v1, "test2"); + EXPECT_EQ(ret, 0); + EXPECT_EQ(strcmp(v1.c_str(), "test2"), 0); +} + +HWTEST_F(SysparaUnitTest, parameterTest0016, TestSize.Level0) +{ + const std::string key1 = "test.bool.get.true"; + bool ret = OHOS::system::GetBoolParameter(key1, false); + EXPECT_EQ(ret, true); + const std::string key2 = "test.bool.get.false"; + ret = OHOS::system::GetBoolParameter(key2, true); + EXPECT_EQ(ret, false); + const std::string key3 = "test.bool.get3"; + ret = OHOS::system::GetBoolParameter(key3, false); + EXPECT_EQ(ret, false); +} + +HWTEST_F(SysparaUnitTest, parameterTest0017, TestSize.Level0) +{ + printf("distributionOS name =%s\n", GetDistributionOSName()); + EXPECT_STRNE(GetDistributionOSName(), nullptr); + printf("distributionOS version =%s\n", GetDistributionOSVersion()); + EXPECT_STRNE(GetDistributionOSVersion(), nullptr); + printf("distributionOS api version =%d\n", GetDistributionOSApiVersion()); + EXPECT_GT(GetDistributionOSApiVersion(), 0); + printf("distributionOS name =%s\n", GetDistributionOSReleaseType()); + EXPECT_STRNE(GetDistributionOSReleaseType(), nullptr); + printf("distributionOS name =%s\n", GetDistributionOSApiName()); +} +#endif + +HWTEST_F(SysparaUnitTest, parameterTest0018, TestSize.Level0) +{ + char key1[] = "test.ro.sys.version"; + char value1[] = "set read only key"; + int ret = SetParameter(key1, value1); + EXPECT_EQ(ret, EC_SUCCESS); + char key2[] = "persist.test.ro.sys.version"; + char value2[] = "set persist read only key"; + ret = SetParameter(key2, value2); + EXPECT_EQ(ret, EC_SUCCESS); + ret = SaveParameters(); + EXPECT_EQ(ret, 0); +} +} // namespace OHOS diff --git a/test/unittest/tools/prepare_testdata.sh b/test/unittest/tools/prepare_testdata.sh new file mode 100755 index 0000000000000000000000000000000000000000..e3081bd6f47aad13cd9104239bd1bee0c5ef1f10 --- /dev/null +++ b/test/unittest/tools/prepare_testdata.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# Copyright (c) 2021 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. + +# This Script used to push test data to devices +# Usage: +# ./prepare_testdata.sh path +# path is the rootdir of ohos projects. +set -e + +if [ $# -lt 1 ];then + echo "Usage $0 " + echo "example $0 rk3568" + exit 1 +fi + +function hdc_shell_cmd() { + # do nothing if there are not any arguments + if [ $# -eq 0 ];then + return; + fi + echo "Running command $@" + hdc shell $@ +} + +function get_root_dir() { + local cur_path=$(pwd) + while [ "${cur_path}" != "" ] + do + cur_path=${cur_path%/*} + if [ "${cur_path}" == "" ];then + echo "[error] get code root dir fail" + exit 1 + fi + if [ "$(basename ${cur_path})" == "base" ]; then + ohos_root=${cur_path%/*} + return + fi + done +} + +get_root_dir +product_name=$1 + +if [ ! -d "${ohos_root}/out/${product_name}" ]; then + echo "product ${product_name} not exist" + exit 1 +fi + +hdc target mount +sleep 0.2 +hdc_shell_cmd "mount -o remount,rw /" +ut_target_path="/data/init_ut" +echo "Remove ${ut_target_path}" +hdc_shell_cmd "rm -rf ${ut_target_path}" +hdc_shell_cmd "rm /bin/init_unittest" + +echo "Create ${ut_target_path}" +hdc_shell_cmd "umask 022" +hdc_shell_cmd "mkdir -p ${ut_target_path}" +hdc_shell_cmd "mkdir -p ${ut_target_path}/proc" + +ohos_init="${ohos_root}/base/startup" + +hdc_shell_cmd "mkdir -p ${ut_target_path}/coverage" +sleep 0.25 + +# copy file to test +hdc file send ${ohos_root}/out/${product_name}/tests/unittest/startup/init/init_unittest /data/init_ut/init_unittest +sleep 0.25 +hdc_shell_cmd "cp /data/init_ut/init_unittest /bin/init_unittest" + +hdc_shell_cmd "chmod 777 /data/init_ut/* -R" +sleep 0.2 +hdc_shell_cmd "chmod 777 /bin/init_unittest" + +hdc_shell_cmd "export GCOV_PREFIX=${ut_target_path}/coverage&&export GCOV_PREFIX_STRIP=15&&init_unittest" +sleep 0.2 + +if [ $? -ne 0 ]; then + echo "Execute init_unittest in device failed. please check the log" +fi +echo "Running init unittests end..." +echo "Ready to generate coverage..." +pushd ${ohos_init} +rm -rf ./g.sh +rm -rf *.gcno +rm -rf *.gcda +echo "Copy .gcta files to ${ohos_init}}" + +for file in $(hdc_shell_cmd ls /data/init_ut/coverage/*.gcda); do + hdc file recv ${file} ${ohos_init}/${file:23} + chmod 777 ${ohos_init}/${file:23} +done + + +echo "Find out all gcno files and copy to ${ohos_init}" +find ${ohos_root}/out/${product_name}/obj/base/startup/ -name "*.gcno" -type f -exec cp {} . \; +if [ $? -ne 0 ]; then + echo "find gcno failed." + popd 2>&1 > /dev/null + exit 1 +fi + +if [ ! -f "${ohos_init}/g.sh" ]; then + echo "create g.sh" + touch ${ohos_init}/g.sh + echo "${ohos_root}/prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-cov gcov \$@" > ${ohos_init}/g.sh + chmod 755 ${ohos_init}/g.sh +fi + +echo "Running command lcov" +lcov -d . -o "${ohos_init}/init_ut_tmp.info" -b . -c --gcov-tool ${ohos_init}/g.sh + +if [ $? -ne 0 ]; then + echo "Run command lcov failed" + popd 2>&1 > /dev/null +fi + +echo "Filter out don\'t cared dir" +lcov --remove init_ut_tmp.info "*foundation*" "*init/adapter/init_adapter.c*" "*third_party*" \ + "*device.c*" "*prebuilts*" "*test/unittest/*" "*utils/native/*" "*utils/system/*" \ + "*init.c*" "*init_signal_handler.c*" "*ueventd.c*" \ + "*ueventd_device_handler.c*" "*ueventd_firmware_handler.c*" "*ueventd_socket.c*" -o ${ohos_init}/init_ut.info + +genhtml -o ${HOME}/init_coverage init_ut.info +if [ $? -ne 0 ]; then + echo "Run genhtml failed." + popd 2>&1 > /dev/null + exit 1 +fi +echo "Clear tmp files" +rm -rf ./g.sh *.gcno *.gcda init_ut.info init_ut_tmp.info +hdc_shell_cmd "rm -rf ${ut_target_path}" +echo +echo "Generate init ut coverage done." +echo "Check coverage in ${HOME}/init_coverage." +echo +popd 2>&1 > /dev/null diff --git a/test/unittest/ueventd/ueventd_config_unittest.cpp b/test/unittest/ueventd/ueventd_config_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..284f256df01bb6a1a16aa51932cad681fe2edbe2 --- /dev/null +++ b/test/unittest/ueventd/ueventd_config_unittest.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021 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 "param_stub.h" +#include "init_utils.h" +#include "ueventd_read_cfg.h" +#include "ueventd_parameter.h" + +extern "C" { +bool IsMatch(const char *target, const char *pattern); +} + +using namespace std; +using namespace testing::ext; + +namespace UeventdUt { +class UeventdConfigUnitTest : public testing::Test { +public: +static void SetUpTestCase(void) {}; +static void TearDownTestCase(void) {}; +void SetUp() {}; +void TearDown() {}; +}; + +HWTEST_F(UeventdConfigUnitTest, Init_UeventdConfigTest_SectionConfigParse001, TestSize.Level0) +{ + ParseUeventdConfigFile(STARTUP_INIT_UT_PATH"/ueventd_ut/valid.config"); + uid_t uid = 0; + gid_t gid = 0; + mode_t mode = 0; + GetDeviceNodePermissions("/dev/test", &uid, &gid, &mode); + EXPECT_EQ(uid, 1000); + EXPECT_EQ(gid, 1000); + EXPECT_EQ(mode, 0666); + uid = 999; + gid = 999; + mode = 0777; + // /dev/test1 is not a valid item, miss gid + // UGO will be default value. + GetDeviceNodePermissions("/dev/test1", &uid, &gid, &mode); + EXPECT_EQ(uid, 999); + EXPECT_EQ(gid, 999); + EXPECT_EQ(mode, 0777); + // /dev/test2 is not a valid item, too much items + // UGO will be default value. + GetDeviceNodePermissions("/dev/test2", &uid, &gid, &mode); + EXPECT_EQ(uid, 999); + EXPECT_EQ(gid, 999); + EXPECT_EQ(mode, 0777); + ChangeSysAttributePermissions("/dev/test2"); + ChangeSysAttributePermissions("/dir/to/nothing"); +} + +HWTEST_F(UeventdConfigUnitTest, Init_UeventdConfigTest_ConfigEntry001, TestSize.Level0) +{ + string file = "[device"; + int rc = ParseUeventConfig(const_cast(file.c_str())); // Invalid section + EXPECT_EQ(rc, -1); + file = "[unknown]"; + rc = ParseUeventConfig(const_cast(file.c_str())); // Unknown section + EXPECT_EQ(rc, -1); + file = "[device]"; + rc = ParseUeventConfig(const_cast(file.c_str())); // valid section + EXPECT_EQ(rc, 0); +} + +HWTEST_F(UeventdConfigUnitTest, Init_UeventdConfigTest_Parameter001, TestSize.Level0) +{ + ParseUeventdConfigFile(STARTUP_INIT_UT_PATH"/ueventd_ut/valid.config"); + SetUeventDeviceParameter("/dev/testbinder1", 0); + SetUeventDeviceParameter("/dev/testbinder2", 0); + SetUeventDeviceParameter("/dev/testbinder3", 0); + SetUeventDeviceParameter("/notpath", 0); + SetUeventDeviceParameter(nullptr, 1); + GetDeviceUdevConfByDevNode(nullptr); + int ret = IsMatch("testtarget", "te?*a"); + IsMatch("testtarget", "a"); + ret = IsMatch("test", "t****"); + EXPECT_EQ(ret, true); +} +} // namespace UeventdUt diff --git a/test/unittest/ueventd/ueventd_event_unittest.cpp b/test/unittest/ueventd/ueventd_event_unittest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffe8f2f8c1af97c2a41b848af320eb0cf9f795c4 --- /dev/null +++ b/test/unittest/ueventd/ueventd_event_unittest.cpp @@ -0,0 +1,651 @@ +/* + * 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 "param_stub.h" +#include "ueventd.h" +#include "ueventd_device_handler.h" +#include "ueventd_socket.h" + +using namespace testing::ext; + +namespace UeventdUt { +namespace { + std::string g_testRoot{"/data/ueventd"}; + int g_oldRootFd = -1; +} + +class UeventdEventUnitTest : public testing::Test { +public: +static void SetUpTestCase(void) +{ + struct stat st{}; + bool isExist = true; + + if (stat(g_testRoot.c_str(), &st) < 0) { + if (errno != ENOENT) { + std::cout << "Cannot get stat of " << g_testRoot << std::endl; + // If we cannot get root for ueventd tests + // There is no reason to continue. + ASSERT_TRUE(false); + } + isExist = false; + } + + if (isExist) { + RemoveDir(g_testRoot); + } + int ret = mkdir(g_testRoot.c_str(), S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (ret < 0) { + std::cout << "Cannot create directory " << g_testRoot << " err = " << errno << std::endl; + ASSERT_TRUE(0); + } + if (SwitchRoot() < 0) { + // If we cannot do this, there is not reason to continue + ASSERT_TRUE(0); + } +} + +static void TearDownTestCase(void) +{ + // Switch back to old root + if (g_oldRootFd < 0) { + std::cout << "Old root directory is not valid\n"; + return; + } + + if (fchdir(g_oldRootFd) < 0) { + std::cout << "Failed to change working directory to '/', err = " << errno << std::endl; + } + + if (chroot(".") < 0) { + std::cout << "Failed to change root directory to '/', err = " << errno << std::endl; + } + close(g_oldRootFd); + g_oldRootFd = -1; + std::cout << "Change root back done\n"; + // Remove test data + if (RemoveDir(g_testRoot) < 0) { + std::cout << "Failed to remove " << g_testRoot << ", err = " << errno << std::endl; + } +} + +static int RemoveDir(const std::string &path) +{ + if (path.empty()) { + // Treat it as OK + return 0; + } + auto dir = std::unique_ptr(opendir(path.c_str()), closedir); + if (dir == nullptr) { + std::cout << "Cannot open dir " << path << ", err = " << errno << std::endl; + return -1; + } + + struct dirent *dp = nullptr; + while ((dp = readdir(dir.get())) != nullptr) { + // Skip hidden files + if (dp->d_name[0] == '.') { + continue; + } + bool endsWithSlash = (path.find_last_of("/") == path.size() - 1); + std::string fullPath {}; + if (endsWithSlash) { + fullPath = path + dp->d_name; + } else { + fullPath = path + "/" + dp->d_name; + } + struct stat st {}; + if (stat(fullPath.c_str(), &st) < 0) { + std::cout << "Failed to get stat of " << fullPath << std::endl; + continue; // Should we continue? + } + if (S_ISDIR(st.st_mode)) { + if (RemoveDir(fullPath) < 0) { + std::cout << "Failed to remove directory " << fullPath << std::endl; + return -1; + } + } else { + if (unlink(fullPath.c_str()) < 0) { + std::cout << "Failed to unlink file " << fullPath << std::endl; + return -1; + } + } + } + return rmdir(path.c_str()); +} + +static int SwitchRoot() +{ + if (g_oldRootFd >= 0) { + close(g_oldRootFd); + g_oldRootFd = -1; + } + // Save old root + DIR *dir = opendir("/"); + if (dir == nullptr) { + std::cout << "Failed to open root directory\n"; + return -1; + } + g_oldRootFd = dirfd(dir); + if (g_oldRootFd < 0) { + std::cout << "Failed to pen root directory, err = " << errno << std::endl; + return -1; + } + + // Changing working directory to "/data/ueventd" + if (chdir(g_testRoot.c_str()) < 0) { + std::cout << "Failed to change working directory to " << g_testRoot << ", err = " << errno << std::endl; + close(g_oldRootFd); + g_oldRootFd = -1; + } + + if (chroot(g_testRoot.c_str()) < 0) { + std::cout << "Failed to change root directory to " << g_testRoot << ", err = " << errno << std::endl; + close(g_oldRootFd); + g_oldRootFd = -1; + } + std::cout << "Change root to " << g_testRoot << " done\n"; + return 0; +} + +void SetUp() {}; +void TearDown() {}; +}; + +// Generate uevent buffer from struct uevent. +// extra data used to break uevent buffer to check +// if ueventd will handle this situation correctly +std::string GenerateUeventBuffer(struct Uevent &uevent, std::vector &extraData) +{ + std::string ueventdBuffer{}; + if (uevent.syspath != nullptr) { + ueventdBuffer.append(std::string("DEVPATH=") + uevent.syspath + '\000'); + } + if (uevent.subsystem != nullptr) { + ueventdBuffer.append(std::string("SUBSYSTEM=") + uevent.subsystem + '\000'); + } + ueventdBuffer.append(std::string("ACTION=") + ActionString(uevent.action) + '\000'); + if (uevent.deviceName != nullptr) { + ueventdBuffer.append(std::string("DEVNAME=") + uevent.deviceName + '\000'); + } + if (uevent.partitionName != nullptr) { + ueventdBuffer.append(std::string("PARTNAME=") + uevent.partitionName + '\000'); + } + ueventdBuffer.append(std::string("PARTN=") + std::to_string(uevent.partitionNum) + '\000'); + ueventdBuffer.append(std::string("MAJOR=") + std::to_string(uevent.major) + '\000'); + ueventdBuffer.append(std::string("MINOR=") + std::to_string(uevent.minor) + '\000'); + ueventdBuffer.append(std::string("DEVUID=") + std::to_string(uevent.ug.uid) + '\000'); + ueventdBuffer.append(std::string("DEVGID=") + std::to_string(uevent.ug.gid) + '\000'); + if (uevent.firmware != nullptr) { + ueventdBuffer.append(std::string("FIRMWARE=") + uevent.firmware + '\000'); + } + ueventdBuffer.append(std::string("BUSNUM=") + std::to_string(uevent.busNum) + '\000'); + ueventdBuffer.append(std::string("DEVNUM=") + std::to_string(uevent.devNum) + '\000'); + + if (!extraData.empty()) { + for (const auto &data : extraData) { + ueventdBuffer.append(data); + } + } + return ueventdBuffer; +} + +bool IsFileExist(const std::string &file) +{ + struct stat st{}; + if (file.empty()) { + return false; + } + + if (stat(file.c_str(), &st) < 0) { + if (errno == ENOENT) { + std::cout << "File " << file << " is not exist\n"; + } + return false; + } + return true; +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_ParseUeventdEvent001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "block", + .syspath = "/block/mmc/test", + .deviceName = "test", + .partitionName = "userdata", + .firmware = "", + .action = ACTION_ADD, + .partitionNum = 3, + .major = 1, + .minor = 2, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + + std::vector extraData{}; + auto ueventBuffer = GenerateUeventBuffer(uevent, extraData); + std::cout << "ueventBuffer = [" << ueventBuffer << "]. size = " << ueventBuffer.length() << std::endl; + struct Uevent outEvent; + ParseUeventMessage(ueventBuffer.data(), ueventBuffer.length(), &outEvent); + EXPECT_EQ(outEvent.action, ACTION_ADD); + EXPECT_EQ(outEvent.busNum, 1); + EXPECT_STREQ(outEvent.subsystem, "block"); + EXPECT_STREQ(outEvent.deviceName, "test"); + EXPECT_EQ(outEvent.devNum, 2); + EXPECT_EQ(outEvent.major, 1); + EXPECT_EQ(outEvent.minor, 2); + EXPECT_EQ(outEvent.partitionNum, 3); + EXPECT_STREQ(outEvent.partitionName, "userdata"); + EXPECT_STREQ(outEvent.syspath, "/block/mmc/test"); + EXPECT_EQ(outEvent.ug.gid, 0); + EXPECT_EQ(outEvent.ug.uid, 0); + HandleUevent(&outEvent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_Actions001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "block", + .syspath = "/block/mmc/test", + .deviceName = "test", + .partitionName = "userdata", + .action = ACTION_UNKNOWN, + }; + std::vector extraData {}; + auto ueventBuffer = GenerateUeventBuffer(uevent, extraData); + std::cout << "ueventBuffer = [" << ueventBuffer << "]. size = " << ueventBuffer.length() << std::endl; + struct Uevent outEvent; + ParseUeventMessage(ueventBuffer.data(), ueventBuffer.length(), &outEvent); + EXPECT_EQ(outEvent.action, ACTION_UNKNOWN); + HandleUevent(&outEvent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleBlockDevicesInvalidParameters001, TestSize.Level1) +{ + HandleBlockDeviceEvent(nullptr); + // Not block device + struct Uevent noBlockUevent = { + .subsystem = "char", + }; + HandleBlockDeviceEvent(&noBlockUevent); + + struct Uevent invalidDevNoUevent = { + .subsystem = "block", + .major = -1, + .minor = -1, + }; + HandleBlockDeviceEvent(&invalidDevNoUevent); + + struct Uevent invalidSysPathUevent = { + .subsystem = "block", + .syspath = nullptr, + .major = 1, + .minor = 1, + }; + HandleBlockDeviceEvent(&invalidSysPathUevent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleBlockDevicesValidParameters002, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "block", + .syspath = "/block/mmc/block_device_test", + .deviceName = "block_device_test", + .partitionName = "block_device_test", + .firmware = "", + .action = ACTION_ADD, + .partitionNum = 3, + .major = 5, + .minor = 15, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + + HandleBlockDeviceEvent(&uevent); + // Check results + std::string blockDevice = "/dev/block/block_device_test"; + struct stat st{}; + int ret = stat(blockDevice.c_str(), &st); + EXPECT_EQ(ret, 0); + bool isBlock = S_ISBLK(st.st_mode); + EXPECT_TRUE(isBlock); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleBlockDevicesRemoved001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "block", + .syspath = "/block/mmc/block_device_test", + .deviceName = "block_device_test", + .partitionName = "block_device_test", + .firmware = "", + .action = ACTION_REMOVE, + .partitionNum = 3, + .major = 5, + .minor = 15, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + std::string blockDevice = "/dev/block/block_device_test"; + struct stat st{}; + int ret = stat(blockDevice.c_str(), &st); + if (ret < 0) { + // This should not happen actually, because we've created the device node before. + std::cout << "Warning. Block device " << blockDevice << " is not exist.\n"; + } + HandleBlockDeviceEvent(&uevent); + ret = stat(blockDevice.c_str(), &st); + EXPECT_EQ(ret, -1); + EXPECT_EQ(errno, ENOENT); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleBlockDevicesChanged001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "block", + .syspath = "/block/mmc/block_device_test", + .deviceName = "block_device_test", + .partitionName = "block_device_test", + .firmware = "", + .action = ACTION_REMOVE, + .partitionNum = 3, + .major = 5, + .minor = 15, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + HandleBlockDeviceEvent(&uevent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleOtherDevicesInvalidParameters001, TestSize.Level1) +{ + HandleOtherDeviceEvent(nullptr); + // Not Character device + struct Uevent invalidDevNoUevent = { + .subsystem = "test", + .major = -1, + .minor = -1, + }; + HandleOtherDeviceEvent(&invalidDevNoUevent); + + struct Uevent invalidSysPathUevent = { + .subsystem = "test", + .syspath = nullptr, + .major = 5, + .minor = 9, + }; + HandleOtherDeviceEvent(&invalidSysPathUevent); + + struct Uevent invalidSubsystemUevent = { + .subsystem = "", + .syspath = "/devices/test/char", + .major = 5, + .minor = 9, + }; + HandleOtherDeviceEvent(&invalidSubsystemUevent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleOtherDevicesValidParameters001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "extcon3", + .syspath = "/devices/platform/headset/extcon/extcon3", + .deviceName = "extcon3-1", + .major = 5, + .minor = 9, + }; + HandleOtherDeviceEvent(&uevent); + auto exist = IsFileExist("/dev/extcon3-1"); + EXPECT_TRUE(exist); + exist = IsFileExist("/dev/extcon3"); + EXPECT_FALSE(exist); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleUsbDevicesWithDeviceName001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "usb", + .syspath = "/devices/platform/headset/extcon/usb-dev", + .deviceName = "usb-dev", + .major = 8, + .minor = 9, + }; + HandleOtherDeviceEvent(&uevent); + auto exist = IsFileExist("/dev/usb-dev"); + EXPECT_TRUE(exist); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleInvalidUsbDevices001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "usb", + .syspath = "/devices/platform/headset/extcon/usb-dev-1", + .major = 8, + .minor = 10, + .busNum = -1, + .devNum = -1, + }; + HandleOtherDeviceEvent(&uevent); + auto exist = IsFileExist("/dev/usb-dev-1"); + EXPECT_FALSE(exist); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_HandleUsbDevicesWithBusNo001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "usb", + .syspath = "/devices/platform/headset/extcon/usb-dev", + .major = 8, + .minor = 9, + .busNum = 3, + .devNum = 4, + }; + HandleOtherDeviceEvent(&uevent); + auto exist = IsFileExist("/dev/bus/usb/003/004"); + EXPECT_TRUE(exist); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_Handle001, TestSize.Level1) +{ + char path[] = {"/data/ueventd"}; + RetriggerUeventByPath(g_oldRootFd, path); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_FirmwareUevent001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "firmware", + .syspath = "/block/mmc/test", + .deviceName = "test", + .partitionName = "userdata", + .firmware = "", + .action = ACTION_ADD, + .partitionNum = 3, + .major = 1, + .minor = 2, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + + std::vector extraData{}; + auto ueventBuffer = GenerateUeventBuffer(uevent, extraData); + struct Uevent outEvent; + ParseUeventMessage(ueventBuffer.data(), ueventBuffer.length(), &outEvent); + EXPECT_EQ(outEvent.action, ACTION_ADD); + EXPECT_EQ(outEvent.busNum, 1); + EXPECT_STREQ(outEvent.subsystem, "firmware"); + EXPECT_STREQ(outEvent.deviceName, "test"); + EXPECT_EQ(outEvent.devNum, 2); + EXPECT_EQ(outEvent.major, 1); + EXPECT_EQ(outEvent.minor, 2); + EXPECT_EQ(outEvent.partitionNum, 3); + EXPECT_STREQ(outEvent.partitionName, "userdata"); + EXPECT_STREQ(outEvent.syspath, "/block/mmc/test"); + EXPECT_EQ(outEvent.ug.gid, 0); + EXPECT_EQ(outEvent.ug.uid, 0); + HandleUevent(&outEvent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventTest_PlatformEvent001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "platform", + .syspath = "/block/mmc/test", + .deviceName = "test", + .partitionName = "userdata", + .firmware = "", + .action = ACTION_ADD, + .partitionNum = 3, + .major = 1, + .minor = 2, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + + std::vector extraData{}; + auto ueventBuffer = GenerateUeventBuffer(uevent, extraData); + struct Uevent outEvent; + ParseUeventMessage(ueventBuffer.data(), ueventBuffer.length(), &outEvent); + EXPECT_EQ(outEvent.action, ACTION_ADD); + EXPECT_EQ(outEvent.busNum, 1); + EXPECT_STREQ(outEvent.subsystem, "platform"); + EXPECT_STREQ(outEvent.deviceName, "test"); + EXPECT_EQ(outEvent.devNum, 2); + EXPECT_EQ(outEvent.major, 1); + EXPECT_EQ(outEvent.minor, 2); + EXPECT_EQ(outEvent.partitionNum, 3); + EXPECT_STREQ(outEvent.partitionName, "userdata"); + EXPECT_STREQ(outEvent.syspath, "/block/mmc/test"); + EXPECT_EQ(outEvent.ug.gid, 0); + EXPECT_EQ(outEvent.ug.uid, 0); + HandleUevent(&outEvent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_PlatformEventUsb001, TestSize.Level1) +{ + struct Uevent uevent = { + .subsystem = "usb", + .syspath = "/block/mmc/test", + .deviceName = "test", + .partitionName = "userdata", + .firmware = "", + .action = ACTION_ADD, + .partitionNum = 3, + .major = 1, + .minor = 2, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + + std::vector extraData{}; + auto ueventBuffer = GenerateUeventBuffer(uevent, extraData); + struct Uevent outEvent; + ParseUeventMessage(ueventBuffer.data(), ueventBuffer.length(), &outEvent); + EXPECT_EQ(outEvent.action, ACTION_ADD); + EXPECT_EQ(outEvent.busNum, 1); + EXPECT_STREQ(outEvent.subsystem, "usb"); + EXPECT_STREQ(outEvent.deviceName, "test"); + EXPECT_EQ(outEvent.devNum, 2); + EXPECT_EQ(outEvent.major, 1); + EXPECT_EQ(outEvent.minor, 2); + EXPECT_EQ(outEvent.partitionNum, 3); + EXPECT_STREQ(outEvent.partitionName, "userdata"); + EXPECT_STREQ(outEvent.syspath, "/block/mmc/test"); + EXPECT_EQ(outEvent.ug.gid, 0); + EXPECT_EQ(outEvent.ug.uid, 0); + HandleUevent(&outEvent); +} + +static void TestUeventAction(ACTION action) +{ + struct Uevent uevent = { + .subsystem = "block", + .syspath = "/block/mmc/test", + .deviceName = "test", + .partitionName = "userdata", + .firmware = "", + .action = action, + .partitionNum = 3, + .major = 1, + .minor = 2, + .ug = { + .uid = 0, + .gid = 0, + }, + .busNum = 1, + .devNum = 2, + }; + + std::vector extraData{}; + auto ueventBuffer = GenerateUeventBuffer(uevent, extraData); + struct Uevent outEvent; + ParseUeventMessage(ueventBuffer.data(), ueventBuffer.length(), &outEvent); + EXPECT_EQ(outEvent.action, action); + HandleUevent(&outEvent); +} + +HWTEST_F(UeventdEventUnitTest, Init_UeventdEventUnitTest_ActionAdd001, TestSize.Level1) +{ + TestUeventAction(ACTION_ADD); + TestUeventAction(ACTION_REMOVE); + TestUeventAction(ACTION_CHANGE); + TestUeventAction(ACTION_MOVE); + TestUeventAction(ACTION_ONLINE); + + TestUeventAction(ACTION_OFFLINE); + TestUeventAction(ACTION_BIND); + TestUeventAction(ACTION_UNBIND); + TestUeventAction(ACTION_UNKNOWN); +} +} // UeventdUt \ No newline at end of file diff --git a/ueventd/BUILD.gn b/ueventd/BUILD.gn old mode 100755 new mode 100644 index 5d725eff9dc11259cb8dead521bf21f4303553d2..aa7b8c1d4ed400242147784abd02219fab5c0ddf --- a/ueventd/BUILD.gn +++ b/ueventd/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-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 @@ -10,31 +10,142 @@ # 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/begetd.gni") -if (!defined(ohos_lite)) { +if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux") { + service_ueventd_deps = [ + "//base/startup/init/interfaces/innerkits/socket:libsocket", + "//base/startup/init/services/log:init_log", + "//base/startup/init/services/param/base:param_base", + "//base/startup/init/services/utils:libinit_utils", + ] + + executable("ueventd_linux") { + sources = [ + "//base/startup/init/services/utils/init_utils.c", + "//base/startup/init/ueventd/lite/ueventd_parameter.c", + "//base/startup/init/ueventd/ueventd.c", + "//base/startup/init/ueventd/ueventd_device_handler.c", + "//base/startup/init/ueventd/ueventd_firmware_handler.c", + "//base/startup/init/ueventd/ueventd_main.c", + "//base/startup/init/ueventd/ueventd_read_cfg.c", + "//base/startup/init/ueventd/ueventd_socket.c", + ] + defines = [ "__MUSL__" ] + defines += [ "_GNU_SOURCE" ] + + include_dirs = [ + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/services/utils", + "//base/startup/init/ueventd/include", + ] + + deps = service_ueventd_deps + deps += [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared" ] + deps += [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + external_deps = [ "bounds_checking_function:libsec_static" ] + } + copy("ueventd.config") { + sources = [ "etc/ueventd_l1.config" ] + outputs = [ "$root_out_dir/etc/ueventd.config" ] + } + } +} else { import("//build/ohos.gni") + service_ueventd_sources = [ + "//base/startup/init/ueventd/ueventd.c", + "//base/startup/init/ueventd/ueventd_device_handler.c", + "//base/startup/init/ueventd/ueventd_firmware_handler.c", + "//base/startup/init/ueventd/ueventd_read_cfg.c", + "//base/startup/init/ueventd/ueventd_socket.c", + ] - ohos_executable("ueventd") { - sources = [ - "list.c", - "ueventd.c", - "ueventd_device_handler.c", - "ueventd_firmware_handler.c", - "ueventd_read_cfg.c", - "ueventd_socket.c", - "ueventd_utils.c", - ] + service_ueventd_include = [ + "//base/startup/init/services/log", + "//base/startup/init/interfaces/innerkits/include", + "//base/startup/init/services/utils", + "//base/startup/init/ueventd/include", + ] - include_dirs = [ - "include", - "//third_party/bounds_checking_function/include", - "//base/startup/init_lite/services/log", - ] + service_ueventd_deps = [ + "//base/startup/init/interfaces/innerkits/socket:libsocket", + "//base/startup/init/services/log:init_log", + "//base/startup/init/services/utils:libinit_utils", + ] - deps = [ - "//base/startup/init_lite/services/log:init_log", - "//third_party/bounds_checking_function:libsec_static", + service_ueventd_ramdisk_deps = [ + "//base/startup/init/interfaces/innerkits/socket:libsocket", + "//base/startup/init/services/utils:libinit_utils", + ] + + # + # exported include directories + # + config("libueventd_exported_config") { + visibility = [ ":*" ] + include_dirs = [ "./include" ] + } + ohos_static_library("libueventd_ramdisk_static") { + sources = service_ueventd_sources + include_dirs = service_ueventd_include + deps = service_ueventd_deps + defines = [ "__RAMDISK__" ] + external_deps = [] + cflags = [] + if (build_selinux) { + external_deps += [ "selinux_adapter:librestorecon" ] + cflags += [ "-DWITH_SELINUX" ] + } + external_deps += [ "selinux:libselinux" ] + external_deps += [ "bounds_checking_function:libsec_static" ] + public_configs = [ ":libueventd_exported_config" ] + part_name = "init" + subsystem_name = "startup" + } + + ohos_static_library("libueventd_ramdisk_static_real") { + sources = service_ueventd_sources + include_dirs = service_ueventd_include + deps = service_ueventd_ramdisk_deps + defines = [ "__RAMDISK__" ] + external_deps = [] + cflags = [] + if (build_selinux) { + external_deps += [ "selinux_adapter:librestorecon_static" ] + cflags += [ "-DWITH_SELINUX" ] + } + external_deps += [ "selinux:libselinux_static" ] + external_deps += [ "bounds_checking_function:libsec_static" ] + public_configs = [ ":libueventd_exported_config" ] + part_name = "init" + subsystem_name = "startup" + } + + ohos_executable("ueventd") { + sources = service_ueventd_sources + sources += [ + "//base/startup/init/ueventd/standard/ueventd_parameter.c", + "//base/startup/init/ueventd/ueventd_main.c", ] + include_dirs = service_ueventd_include + include_dirs += [ + "//base/startup/init/interfaces/innerkits/include/param", + "//base/startup/init/interfaces/innerkits/include", + ] + deps = service_ueventd_deps + deps += [ "//base/startup/init/services/param/linux:param_client" ] + external_deps = [ "selinux:libselinux" ] + external_deps += [ "bounds_checking_function:libsec_static" ] + cflags = [] + deps += [ "//base/startup/init/services/param/base:param_base" ] + deps += [ "//base/startup/init/interfaces/innerkits:libbegetutil" ] + if (build_selinux) { + external_deps += [ "selinux_adapter:librestorecon" ] + cflags += [ "-DWITH_SELINUX" ] + } install_images = [ "system", @@ -42,14 +153,35 @@ if (!defined(ohos_lite)) { ] install_enable = true part_name = "init" + subsystem_name = "startup" } ohos_prebuilt_etc("ueventd.config") { - source = "//base/startup/init_lite/ueventd/etc/ueventd.config" + source = "//base/startup/init/ueventd/etc/ueventd.config" part_name = "init" + subsystem_name = "startup" install_images = [ "system", "updater", ] } } + +group("startup_ueventd") { + if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux") { + deps = [ + ":ueventd.config", + ":ueventd_linux", + ] + } else { + deps = [] + } + } else { + deps = [ + "//base/startup/init/ueventd:libueventd_ramdisk_static", + "//base/startup/init/ueventd:ueventd", + "//base/startup/init/ueventd:ueventd.config", + ] + } +} diff --git a/ueventd/etc/ueventd.config b/ueventd/etc/ueventd.config old mode 100755 new mode 100644 index 771075ae83305433598136d6552083e1f44355fa..275ded308765434823ecf94201b528837a17fd90 --- a/ueventd/etc/ueventd.config +++ b/ueventd/etc/ueventd.config @@ -12,12 +12,15 @@ # limitations under the License. [device] -# +# +/dev/bus/usb/* 0660 3023 3023 +/dev/null 0666 0 0 /dev/binder 0666 0 0 -/dev/input/event0 0660 0 0 -/dev/input/event1 0660 0 1004 -/dev/input/mice 0660 0 1004 -/dev/input/mouse0 0660 0 0 +/dev/hwbinder 0666 0 0 +/dev/vndbinder 0666 0 0 +/dev/input/event* 0660 0 input +/dev/input/mice 0660 0 input +/dev/input/mouse0 0660 0 input /dev/snd/timer 0660 1000 1005 /dev/zero 0666 0 0 /dev/full 0666 0 0 @@ -32,7 +35,7 @@ /dev/mmz_userdev 0644 1000 1005 /dev/graphics/fb0 0660 1000 1003 /dev/mem 0660 1000 1005 -/dev/ion 0666 1000 1000 +/dev/ion 0664 1000 1000 /dev/btusb0 0660 1002 1002 /dev/uhid 0660 3011 3011 /dev/tc_ns_client 0660 1000 1005 @@ -57,20 +60,26 @@ /dev/vi 0660 1000 1005 /dev/vo 0660 1000 1005 /dev/vpss 0660 1000 1005 -/dev/i2c-0 0660 1000 1006 -/dev/i2c-1 0660 1000 1006 -/dev/i2c-2 0660 1000 1006 -/dev/i2c-3 0660 1000 1006 -/dev/i2c-4 0660 1000 1006 -/dev/i2c-5 0660 1000 1006 -/dev/i2c-6 0660 1000 1006 -/dev/i2c-7 0660 1000 1006 +/dev/i2c-* 0660 1000 1006 /dev/vgs 0666 1000 1005 /dev/dri/card0 0666 0 1003 /dev/dri/card0-DSI-1 0666 0 1003 /dev/dri/card0-HDMI-A-1 0666 0 1003 /dev/dri/renderD128 0666 0 1003 -/dev/rtc0 0640 1000 1000 +/dev/rtc0 0640 3819 3819 /dev/tty0 0660 0 1000 /dev/uinput 0660 3011 3011 - +/dev/access_token_id 0666 3020 3020 +/dev/auth_ctrl 0660 system system +/dev/block/sdd19 0660 0 0 +/dev/watchdog 0660 watchdog watchdog +/dev/hdf_input_event* 0660 3029 3029 +/dev/HDF* 0666 0 0 +/dev/ttyS* 0666 0 0 +/dev/ttyACM* 0666 0 0 +/dev/ttyUSB* 0666 0 0 +/dev/video* 0660 camera_host camera_host +/dev/btdev* 0660 dsoftbus dsoftbus +/dev/block/by-name/misc 0660 update update +/dev/block/by-name/bootctrl 0660 update update +/dev/video* 0660 clearplay_host clearplay_host diff --git a/ueventd/etc/ueventd_l1.config b/ueventd/etc/ueventd_l1.config new file mode 100755 index 0000000000000000000000000000000000000000..d3150260dd00b0691c1b5bb071ef916d20628547 --- /dev/null +++ b/ueventd/etc/ueventd_l1.config @@ -0,0 +1,20 @@ +# Copyright (c) 2021-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. + +[device] +# +/dev/binder 0666 0 0 +/dev/random 0666 0 0 +/dev/urandom 0666 0 0 +/dev/mmz_userdev 0666 0 0 +/dev/watchdog 0660 watchdog watchdog diff --git a/ueventd/ueventd.h b/ueventd/include/ueventd.h old mode 100755 new mode 100644 similarity index 70% rename from ueventd/ueventd.h rename to ueventd/include/ueventd.h index 76cb3be40d4b175b4572250c6e583b58f0062a4b..880c75d4392b7635a168cdbff39ef7c55e155db9 --- a/ueventd/ueventd.h +++ b/ueventd/include/ueventd.h @@ -16,6 +16,11 @@ #ifndef BASE_STARTUP_INITLITE_UEVENTD_H #define BASE_STARTUP_INITLITE_UEVENTD_H #include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif // Refer to linux kernel kobject.h typedef enum ACTION { @@ -60,5 +65,22 @@ typedef enum SUBYSTEM { SUBSYSTEM_OTHERS = 3, } SUBSYSTEMTYPE; +#define CMDLINE_VALUE_LEN_MAX 512 +#define PROCESS_NAME_MAX_LENGTH 1024 +#define UEVENTD_POLL_TIME (5 * 60 * 1000) +#define UEVENTD_FLAG "/dev/.ueventd_trigger_done" + +extern char bootDevice[CMDLINE_VALUE_LEN_MAX]; + const char *ActionString(ACTION action); -#endif // BASE_STARTUP_INITLITE_UEVENTD_H \ No newline at end of file +void ParseUeventMessage(const char *buffer, ssize_t length, struct Uevent *uevent); +void RetriggerUevent(int sockFd, char **devices, int num); +void RetriggerUeventByPath(int sockFd, char *path); +void ProcessUevent(int sockFd, char **devices, int num); +void CloseUeventConfig(void); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif // BASE_STARTUP_INITLITE_UEVENTD_H diff --git a/ueventd/ueventd_device_handler.h b/ueventd/include/ueventd_device_handler.h old mode 100755 new mode 100644 similarity index 88% rename from ueventd/ueventd_device_handler.h rename to ueventd/include/ueventd_device_handler.h index ab34db61bb08ae8e381bcfde20958330cc6687fd..f4fa67db5cba4e3c3e4327e22fb71995fef7f7e8 --- a/ueventd/ueventd_device_handler.h +++ b/ueventd/include/ueventd_device_handler.h @@ -16,7 +16,18 @@ #ifndef BASE_STARTUP_INITLITE_UEVENTD_DEVICE_HANDLER_H #define BASE_STARTUP_INITLITE_UEVENTD_DEVICE_HANDLER_H #include "ueventd.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + void HandleBlockDeviceEvent(const struct Uevent *uevent); void HandleOtherDeviceEvent(const struct Uevent *uevent); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif #endif // BASE_STARTUP_INITLITE_UEVENTD_DEVICE_HANDLER_H diff --git a/ueventd/ueventd_firmware_handler.h b/ueventd/include/ueventd_firmware_handler.h old mode 100755 new mode 100644 similarity index 85% rename from ueventd/ueventd_firmware_handler.h rename to ueventd/include/ueventd_firmware_handler.h index 1f7e16850ea197243b4907b56fd1be3c34203e7a..7ccfb6d66446b7f30b94c78b99df7ca12702c4ff --- a/ueventd/ueventd_firmware_handler.h +++ b/ueventd/include/ueventd_firmware_handler.h @@ -16,5 +16,17 @@ #ifndef BASE_STARTUP_INITLITE_UEVENTD_FIRMWARE_HANDLER_H #define BASE_STARTUP_INITLITE_UEVENTD_FIRMWARE_HANDLER_H #include "ueventd.h" +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + void HandleFimwareDeviceEvent(const struct Uevent *uevent); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* MODULE_REBOOT_ADP_H */ #endif // BASE_STARTUP_INITLITE_UEVENTD_FIRMWARE_HANDLER_H diff --git a/ueventd/include/ueventd_parameter.h b/ueventd/include/ueventd_parameter.h new file mode 100644 index 0000000000000000000000000000000000000000..605c3fdbde2754323b2d791f019faa0b74ec0c1c --- /dev/null +++ b/ueventd/include/ueventd_parameter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 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_UEVENTD_PARAMETER_H +#define BASE_STARTUP_INITLITE_UEVENTD_PARAMETER_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int SetUeventDeviceParameter(const char *devNode, int action); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/ueventd/ueventd_read_cfg.h b/ueventd/include/ueventd_read_cfg.h old mode 100755 new mode 100644 similarity index 79% rename from ueventd/ueventd_read_cfg.h rename to ueventd/include/ueventd_read_cfg.h index c87476c2a6569425bfa32b9c3ed97a6215007be8..f94b37edbe838c4aedd9ad4346413217034375ec --- a/ueventd/ueventd_read_cfg.h +++ b/ueventd/include/ueventd_read_cfg.h @@ -29,7 +29,10 @@ struct DeviceUdevConf { mode_t mode; uid_t uid; gid_t gid; + const char *parameter; + int action; struct ListNode list; + struct ListNode paramNode; }; struct SysUdevConf { @@ -45,7 +48,16 @@ struct FirmwareUdevConf { const char *fmPath; struct ListNode list; }; + +#ifdef __cplusplus +extern "C" { +#endif void ParseUeventdConfigFile(const char *file); -void GetDeviceNodePermissions(const char *devNode, uid_t *uid, gid_t *gid, mode_t *mode); +int GetDeviceNodePermissions(const char *devNode, uid_t *uid, gid_t *gid, mode_t *mode); void ChangeSysAttributePermissions(const char *sysPath); +int ParseUeventConfig(char *buffer); +struct DeviceUdevConf *GetDeviceUdevConfByDevNode(const char *devNode); +#ifdef __cplusplus +} +#endif #endif /* __UEVENTD_READ_CFG_H */ diff --git a/ueventd/ueventd_socket.h b/ueventd/include/ueventd_socket.h old mode 100755 new mode 100644 similarity index 83% rename from ueventd/ueventd_socket.h rename to ueventd/include/ueventd_socket.h index 922a94ce18f25a6f34f5c58afa541ef31caa6452..3e4a47cfadf3a2465f9abeb2185db059d88a4427 --- a/ueventd/ueventd_socket.h +++ b/ueventd/include/ueventd_socket.h @@ -16,6 +16,18 @@ #ifndef BASE_STARTUP_INITLITE_UEVENTD_SOCKET_H #define BASE_STARTUP_INITLITE_UEVENTD_SOCKET_H #include -int UeventdSocketInit(); +#include +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +int UeventdSocketInit(void); ssize_t ReadUeventMessage(int sockFd, char *buffer, size_t length); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif #endif // BASE_STARTUP_INITLITE_LIST_H diff --git a/ueventd/ueventd_utils.h b/ueventd/include/ueventd_utils.h old mode 100755 new mode 100644 similarity index 84% rename from ueventd/ueventd_utils.h rename to ueventd/include/ueventd_utils.h index e8593f2346256e4936d69a015d4c779014fc139b..5d303feb1e58681e16589c13f518772e1c57bd59 --- a/ueventd/ueventd_utils.h +++ b/ueventd/include/ueventd_utils.h @@ -18,12 +18,11 @@ #include #include #include +#include "init_utils.h" -#define DECIMALISM 10 -#define OCTONARY 8 #define DEVICE_FILE_SIZE 128U #define SYSPATH_SIZE 512U -#define BLOCKDEVICE_LINKS 3 +#define BLOCKDEVICE_LINKS 4 #define STARTSWITH(str, prefix) (strncmp((str), (prefix), strlen(prefix)) == 0) #define STRINGEQUAL(src, tgt) (strcmp((src), (tgt)) == 0) @@ -33,7 +32,4 @@ // Default device mode is 0660 #define DEVMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) -int MakeDirRecursive(const char *dir, mode_t mode); -int MakeDir(const char *dir, mode_t mode); -int StringToInt(const char *str, int defaultValue); #endif // BASE_STARTUP_INITLITE_UEVENTD_UTILS_H \ No newline at end of file diff --git a/ueventd/lite/ueventd_parameter.c b/ueventd/lite/ueventd_parameter.c new file mode 100644 index 0000000000000000000000000000000000000000..75b3a011382a7992a2bbafa26474448c9476f501 --- /dev/null +++ b/ueventd/lite/ueventd_parameter.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 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 "ueventd_parameter.h" + +// lite release not support set parameter. +int SetUeventDeviceParameter(const char *devNode, int action) +{ + (void)(devNode); + (void)(action); + return 0; +} diff --git a/ueventd/standard/ueventd_parameter.c b/ueventd/standard/ueventd_parameter.c new file mode 100644 index 0000000000000000000000000000000000000000..4145c80d4e5644a2bea8073f71175415d3a04b5c --- /dev/null +++ b/ueventd/standard/ueventd_parameter.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 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 "ueventd_parameter.h" + +#include +#include + +#define INIT_LOG_TAG "ueventd" +#include "init_log.h" +#include "list.h" +#include "init_param.h" +#include "ueventd.h" +#include "ueventd_read_cfg.h" +#include "securec.h" + +typedef struct { + int inited; + int shutdown; + int empty; + pthread_mutex_t lock; + pthread_cond_t hasData; + pthread_mutex_t parameterLock; + struct ListNode parameterList; + pthread_t threadId; +} DeviceParameterCtrl; + +static DeviceParameterCtrl g_parameterCtrl = { + .inited = 1, + .shutdown = 0, + .empty = 1, + .lock = PTHREAD_MUTEX_INITIALIZER, + .hasData = PTHREAD_COND_INITIALIZER, + .parameterLock = PTHREAD_MUTEX_INITIALIZER, + .parameterList = {&g_parameterCtrl.parameterList, &g_parameterCtrl.parameterList}, + .threadId = 0 +}; + +static struct DeviceUdevConf *GetFirstParameter(DeviceParameterCtrl *parameterCtrl) +{ + struct DeviceUdevConf *conf = NULL; + pthread_mutex_lock(&(parameterCtrl->parameterLock)); + if (!ListEmpty(parameterCtrl->parameterList)) { + conf = ListEntry(parameterCtrl->parameterList.next, struct DeviceUdevConf, paramNode); + OH_ListRemove(&conf->paramNode); + OH_ListInit(&conf->paramNode); + } + pthread_mutex_unlock(&(parameterCtrl->parameterLock)); + return conf; +} + +static void *ThreadRun(void *data) +{ + DeviceParameterCtrl *parameterCtrl = (DeviceParameterCtrl *)data; + INIT_LOGV("[uevent] ThreadRun %d %d", parameterCtrl->empty, parameterCtrl->shutdown); + char paramName[PARAM_NAME_LEN_MAX] = {0}; + while (1) { + pthread_mutex_lock(&(parameterCtrl->lock)); + if (parameterCtrl->empty) { + struct timespec abstime = {0}; + struct timeval now = {0}; + const long timeout = 5000; // wait time 5000ms + gettimeofday(&now, NULL); + long long nsec = (long long)now.tv_usec * 1000 + (timeout % 1000) * 1000000; // 1000 unit 1000000 unit nsec + abstime.tv_sec = now.tv_sec + nsec / 1000000000 + timeout / 1000; // 1000 unit 1000000000 unit nsec + abstime.tv_nsec = nsec % 1000000000; // 1000000000 unit nsec + pthread_cond_timedwait(&(parameterCtrl->hasData), &(parameterCtrl->lock), &abstime); + } + if (parameterCtrl->shutdown) { + break; + } + pthread_mutex_unlock(&(parameterCtrl->lock)); + struct DeviceUdevConf *config = GetFirstParameter(parameterCtrl); + if (config == NULL) { + parameterCtrl->empty = 1; + continue; + } + parameterCtrl->empty = 0; + const char *paramValue = (config->action == ACTION_ADD) ? "added" : "removed"; + INIT_LOGI("[uevent] SystemSetParameter %s act %s", config->parameter, paramValue); + int len = sprintf_s(paramName, sizeof(paramName), "startup.uevent.%s", config->parameter); + if ((len <= 0) || (SystemSetParameter(paramName, paramValue) != 0)) { + INIT_LOGE("[uevent] SystemSetParameter %s failed", config->parameter); + pthread_mutex_lock(&(parameterCtrl->parameterLock)); + OH_ListAddTail(¶meterCtrl->parameterList, &config->paramNode); + pthread_mutex_unlock(&(parameterCtrl->parameterLock)); + parameterCtrl->empty = 1; + } + } + return NULL; +} + +static void AddParameter(DeviceParameterCtrl *parameterCtrl, struct DeviceUdevConf *config) +{ + pthread_mutex_lock(&(parameterCtrl->parameterLock)); + if (ListEmpty(config->paramNode)) { + OH_ListAddTail(¶meterCtrl->parameterList, &config->paramNode); + } + pthread_mutex_unlock(&(parameterCtrl->parameterLock)); + if (parameterCtrl->threadId == 0) { + int ret = pthread_create(&(parameterCtrl->threadId), NULL, ThreadRun, (void *)parameterCtrl); + INIT_ERROR_CHECK(ret == 0, return, "[uevent] pthread_create failed, ret:%d", ret); + } + pthread_mutex_lock(&(parameterCtrl->lock)); + parameterCtrl->empty = 0; + pthread_cond_signal(&(parameterCtrl->hasData)); + pthread_mutex_unlock(&(parameterCtrl->lock)); +} + +int SetUeventDeviceParameter(const char *devNode, int action) +{ + if (devNode == NULL) { + return -1; + } + struct DeviceUdevConf *config = GetDeviceUdevConfByDevNode(devNode); + if ((config != NULL) && (config->parameter != NULL)) { + INIT_LOGI("[uevent] SetUeventDeviceParameter parameter %s", config->parameter); + config->action = action; + AddParameter(&g_parameterCtrl, config); + } + return 0; +} diff --git a/ueventd/ueventd.c b/ueventd/ueventd.c old mode 100755 new mode 100644 index 98ab43e55731cffa7cd9cc2d6a5e158dccc563c2..5de46c3c26cbcd4a7684821d04939c7e29fea8ed --- a/ueventd/ueventd.c +++ b/ueventd/ueventd.c @@ -18,10 +18,12 @@ #include #include #include -#include #include #include +#include +#include #include + #include "ueventd_device_handler.h" #include "ueventd_firmware_handler.h" #include "ueventd_read_cfg.h" @@ -30,9 +32,12 @@ #include "securec.h" #define INIT_LOG_TAG "ueventd" #include "init_log.h" +#include "init_utils.h" // buffer size refer to kernel kobject uevent #define UEVENT_BUFFER_SIZE (2048 + 1) +char bootDevice[CMDLINE_VALUE_LEN_MAX] = { 0 }; +#define WRITE_SIZE 4 static const char *actions[] = { [ACTION_ADD] = "add", @@ -43,7 +48,7 @@ static const char *actions[] = { [ACTION_OFFLINE] = "offline", [ACTION_BIND] = "bind", [ACTION_UNBIND] = "unbind", - [ACTION_UNKNOWN] = "unknow", + [ACTION_UNKNOWN] = "unknown", }; static SUBSYSTEMTYPE GetSubsystemType(const char *subsystem) @@ -95,7 +100,7 @@ static ACTION GetUeventAction(const char *action) } } -static void HandleUevent(const struct Uevent *uevent) +STATIC void HandleUevent(const struct Uevent *uevent) { if (uevent->action == ACTION_ADD || uevent->action == ACTION_CHANGE || uevent->action == ACTION_ONLINE) { ChangeSysAttributePermissions(uevent->syspath); @@ -117,12 +122,98 @@ static void HandleUevent(const struct Uevent *uevent) } } -static void AddUevent(struct Uevent *uevent, const char *event, size_t len) +#define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) + +typedef struct { + const char *dev; + mode_t mode; +} DYNAMIC_DEVICE_NODE; + +#define DEV_NODE_PATH_PREFIX "/dev/" +#define DEV_NODE_PATH_PREFIX_LEN 5 + +static const DYNAMIC_DEVICE_NODE DYNAMIC_DEVICES[] = { + { DEV_NODE_PATH_PREFIX"tty", S_IFCHR | DEFAULT_RW_MODE }, + { DEV_NODE_PATH_PREFIX"binder", S_IFCHR | DEFAULT_RW_MODE }, + { DEV_NODE_PATH_PREFIX"console", S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP }, + { DEV_NODE_PATH_PREFIX"mapper/control", S_IFCHR | DEFAULT_RW_MODE } +}; + +static void HandleRequiredDynamicDeviceNodes(const struct Uevent *uevent) { - if (uevent == NULL || uevent == NULL || len == 0) { + mode_t mask; + size_t idx = 0; + + if (uevent->deviceName == NULL) { return; } + while (idx < sizeof(DYNAMIC_DEVICES) / sizeof(DYNAMIC_DEVICES[0])) { + if (strcmp(uevent->deviceName, DYNAMIC_DEVICES[idx].dev + DEV_NODE_PATH_PREFIX_LEN) != 0) { + idx++; + continue; + } + + if (strcmp(uevent->deviceName, "mapper/control") == 0) { + HandleOtherDeviceEvent(uevent); + return; + } + + // Matched + mask = umask(0); + if (mknod(DYNAMIC_DEVICES[idx].dev, DYNAMIC_DEVICES[idx].mode, + makedev((unsigned int)uevent->major, (unsigned int)uevent->minor)) != 0) { + INIT_LOGE("Create device node %s failed. %s", DYNAMIC_DEVICES[idx].dev, strerror(errno)); + } + // Restore umask + umask(mask); + break; + } +} + +static void HandleRequiredBlockDeviceNodes(const struct Uevent *uevent, char **devices, int num) +{ + for (int i = 0; i < num; i++) { + if (uevent->partitionName == NULL) { + if (strstr(devices[i], uevent->deviceName) != NULL) { + INIT_LOGI("%s match with required partition %s success, now handle it", devices[i], uevent->deviceName); + HandleBlockDeviceEvent(uevent); + return; + } + } else if (strstr(devices[i], uevent->partitionName) != NULL || + strstr(uevent->partitionName, "vendor") != NULL || + strstr(uevent->partitionName, "system") != NULL || + strstr(uevent->partitionName, "chipset") != NULL || + strstr(uevent->partitionName, "boot") != NULL || + strstr(uevent->partitionName, "ramdisk") != NULL || + strstr(uevent->partitionName, "rvt") != NULL || + strstr(uevent->partitionName, "dtbo") != NULL) { + INIT_LOGI("Handle required partitionName %s", uevent->partitionName); + HandleBlockDeviceEvent(uevent); + return; + } + } + INIT_LOGW("Not found device for partitionName %s ", uevent->partitionName); +} + +static void HandleUeventRequired(const struct Uevent *uevent, char **devices, int num) +{ + INIT_ERROR_CHECK(devices != NULL && num > 0, return, "Fault parameters"); + if (uevent->action == ACTION_ADD) { + ChangeSysAttributePermissions(uevent->syspath); + } + SUBSYSTEMTYPE type = GetSubsystemType(uevent->subsystem); + if (type == SUBSYSTEM_BLOCK) { + HandleRequiredBlockDeviceNodes(uevent, devices, num); + } else if (type == SUBSYSTEM_OTHERS) { + HandleRequiredDynamicDeviceNodes(uevent); + } else { + return; + } +} + +static void AddUevent(struct Uevent *uevent, const char *event, size_t len) +{ if (STARTSWITH(event, "DEVPATH=")) { uevent->syspath = event + strlen("DEVPATH="); } else if (STARTSWITH(event, "SUBSYSTEM=")) { @@ -140,9 +231,9 @@ static void AddUevent(struct Uevent *uevent, const char *event, size_t len) } else if (STARTSWITH(event, "MINOR=")) { uevent->minor = StringToInt(event + strlen("MINOR="), -1); } else if (STARTSWITH(event, "DEVUID")) { - uevent->ug.uid = StringToInt(event + strlen("DEVUID="), 0); + uevent->ug.uid = (uid_t)StringToInt(event + strlen("DEVUID="), 0); } else if (STARTSWITH(event, "DEVGID")) { - uevent->ug.gid = StringToInt(event + strlen("DEVGID="), 0); + uevent->ug.gid = (gid_t)StringToInt(event + strlen("DEVGID="), 0); } else if (STARTSWITH(event, "FIRMWARE=")) { uevent->firmware = event + strlen("FIRMWARE="); } else if (STARTSWITH(event, "BUSNUM=")) { @@ -150,17 +241,34 @@ static void AddUevent(struct Uevent *uevent, const char *event, size_t len) } else if (STARTSWITH(event, "DEVNUM=")) { uevent->devNum = StringToInt(event + strlen("DEVNUM="), -1); } + // Ignore other events + INIT_LOGV("got uevent message:\n" + "subsystem: %s\n" + "parition: %s:%d\n" + "action: %s\n" + "devpath: %s\n" + "devname: %s\n" + "devnode: %d:%d\n" + "id: %d:%d", + uevent->subsystem, + uevent->partitionName, uevent->partitionNum, + uevent->action, + uevent->syspath, + uevent->deviceName, + uevent->major, uevent->minor, + uevent->ug.uid, uevent->ug.gid); } -static void ParseUeventMessage(char *buffer, ssize_t length, struct Uevent *uevent) +void ParseUeventMessage(const char *buffer, ssize_t length, struct Uevent *uevent) { if (buffer == NULL || uevent == NULL || length == 0) { // Ignore invalid buffer return; } - // reset parititon number, major and minor. + // reset partition number, major and minor. + uevent->partitionName = NULL; uevent->partitionNum = -1; uevent->major = -1; uevent->minor = -1; @@ -168,7 +276,7 @@ static void ParseUeventMessage(char *buffer, ssize_t length, struct Uevent *ueve uevent->devNum = -1; ssize_t pos = 0; while (pos < length) { - char *event = buffer + pos; + const char *event = buffer + pos; size_t len = strlen(event); if (len == 0) { break; @@ -178,7 +286,7 @@ static void ParseUeventMessage(char *buffer, ssize_t length, struct Uevent *ueve } } -static void ProcessUevent(int sockFd) +void ProcessUevent(int sockFd, char **devices, int num) { // One more bytes for '\0' char ueventBuffer[UEVENT_BUFFER_SIZE] = {}; @@ -187,106 +295,89 @@ static void ProcessUevent(int sockFd) while ((n = ReadUeventMessage(sockFd, ueventBuffer, sizeof(ueventBuffer) - 1)) > 0) { ParseUeventMessage(ueventBuffer, n, &uevent); if (uevent.syspath == NULL) { - INIT_LOGD("Ignore unexpected uevent"); + INIT_LOGV("Ignore unexpected uevent"); return; } - HandleUevent(&uevent); + if (devices != NULL && num > 0) { + HandleUeventRequired(&uevent, devices, num); + } else { + HandleUevent(&uevent); + } } } -static int g_triggerDone = 0; -static void DoTrigger(const char *ueventPath, int sockFd) +static void DoTrigger(const char *ueventPath, int sockFd, char **devices, int num) { if (ueventPath == NULL || ueventPath[0] == '\0') { return; } + INIT_LOGV("------------------------\n" + "\nTry to trigger \" %s \" now ...", ueventPath); int fd = open(ueventPath, O_WRONLY | O_CLOEXEC); if (fd < 0) { INIT_LOGE("Open \" %s \" failed, err = %d", ueventPath, errno); - } else { - ssize_t n = write(fd, "add\n", 4); - if (n < 0) { - INIT_LOGE("Write \" %s \" failed, err = %d", ueventPath, errno); - close(fd); - } else { - close(fd); - // uevent triggered, now handle it. - if (sockFd >= 0) { - ProcessUevent(sockFd); - } - } + return; } -} -static void Trigger(const char *path, int sockFd) -{ - DIR *dir = opendir(path); - if (dir != NULL) { - struct dirent *dirent = NULL; - while ((dirent = readdir(dir)) != NULL) { - if (dirent->d_name[0] == '.') { - continue; - } - if (dirent->d_type == DT_DIR) { - char pathBuffer[PATH_MAX]; - if (snprintf_s(pathBuffer, PATH_MAX, PATH_MAX - 1, "%s/%s", path, dirent->d_name) == -1) { - continue; - } - Trigger(pathBuffer, sockFd); - } else { - if (!strcmp(dirent->d_name, "uevent")) { - char ueventBuffer[PATH_MAX]; - if (snprintf_s(ueventBuffer, PATH_MAX, PATH_MAX - 1, "%s/%s", path, "uevent") == -1) { - INIT_LOGW("Cannnot build uevent path under %s", path); - continue; - } - DoTrigger(ueventBuffer, sockFd); - } - } - } - closedir(dir); + ssize_t n = write(fd, "add\n", WRITE_SIZE); + close(fd); + if (n < 0) { + INIT_LOGE("Write \" %s \" failed, err = %d", ueventPath, errno); + return; } -} -static void RetriggerUevent(int sockFd) -{ - if (!g_triggerDone) { - Trigger("/sys/block", sockFd); - Trigger("/sys/class", sockFd); - Trigger("/sys/devices", sockFd); - g_triggerDone = 1; + // uevent triggered, now handle it. + if (sockFd >= 0) { + ProcessUevent(sockFd, devices, num); } } -int main(int argc, char **argv) +static void Trigger(const char *path, int sockFd, char **devices, int num) { - char *ueventdConfigs[] = {"/etc/ueventd.config", NULL}; - int i = 0; - int ret = -1; - while (ueventdConfigs[i] != NULL) { - ParseUeventdConfigFile(ueventdConfigs[i++]); + if (path == NULL) { + return; } - int ueventSockFd = UeventdSocketInit(); - if (ueventSockFd < 0) { - INIT_LOGE("Failed to create uevent socket"); - return -1; + DIR *dir = opendir(path); + if (dir == NULL) { + return; } - - RetriggerUevent(ueventSockFd); - struct pollfd pfd = {}; - pfd.events = POLLIN; - pfd.fd = ueventSockFd; - - while (1) { - pfd.revents = 0; - ret = poll(&pfd, 1, -1); - if (ret <= 0) { + struct dirent *dirent = NULL; + while ((dirent = readdir(dir)) != NULL) { + if (dirent->d_name[0] == '.') { continue; } - if (pfd.revents & POLLIN) { - ProcessUevent(ueventSockFd); + if (dirent->d_type == DT_DIR) { + char pathBuffer[PATH_MAX]; + if (snprintf_s(pathBuffer, PATH_MAX, PATH_MAX - 1, "%s/%s", path, dirent->d_name) == -1) { + continue; + } + Trigger(pathBuffer, sockFd, devices, num); + } else { + if (strcmp(dirent->d_name, "uevent") != 0) { + continue; + } + char ueventBuffer[PATH_MAX]; + if (snprintf_s(ueventBuffer, PATH_MAX, PATH_MAX - 1, "%s/%s", path, "uevent") == -1) { + INIT_LOGW("Cannot build uevent path under %s", path); + continue; + } + DoTrigger(ueventBuffer, sockFd, devices, num); } } - return 0; + closedir(dir); +} + +void RetriggerUeventByPath(int sockFd, char *path) +{ + Trigger(path, sockFd, NULL, 0); +} + +void RetriggerUevent(int sockFd, char **devices, int num) +{ + int ret = GetParameterFromCmdLine("default_boot_device", bootDevice, CMDLINE_VALUE_LEN_MAX); + INIT_CHECK_ONLY_ELOG(ret == 0, "Failed get default_boot_device value from cmdline"); + Trigger("/sys/block", sockFd, devices, num); + Trigger("/sys/class", sockFd, devices, num); + Trigger("/sys/devices", sockFd, devices, num); } diff --git a/ueventd/ueventd_device_handler.c b/ueventd/ueventd_device_handler.c old mode 100755 new mode 100644 index bd0dc3d1f0a42c421d252a451d04feb1ad7b9aee..7dee269143195c0a3f2b2052201f41d74deea260 --- a/ueventd/ueventd_device_handler.c +++ b/ueventd/ueventd_device_handler.c @@ -14,20 +14,43 @@ */ #include "ueventd_device_handler.h" + #include #include +#include #include #include #include #include #include -#include "list.h" +#include "init_utils.h" #include "ueventd.h" +#ifndef __RAMDISK__ +#include "ueventd_parameter.h" +#endif #include "ueventd_read_cfg.h" #include "ueventd_utils.h" #include "securec.h" #define INIT_LOG_TAG "ueventd" #include "init_log.h" +#ifdef WITH_SELINUX +#include +#include +#endif + +static inline void AdjustDeviceNodePermissions(const char *deviceNode, uid_t uid, gid_t gid, mode_t mode) +{ + if (INVALIDSTRING(deviceNode)) { + return; + } + if (chown(deviceNode, uid, gid) != 0) { + INIT_LOGW("Failed to change \" %s \" owner, errno %d", deviceNode, errno); + } + + if (chmod(deviceNode, mode) != 0) { + INIT_LOGW("Failed to change \" %s \" mode, errno %d", deviceNode, errno); + } +} static void CreateSymbolLinks(const char *deviceNode, char **symLinks) { @@ -35,43 +58,92 @@ static void CreateSymbolLinks(const char *deviceNode, char **symLinks) return; } + uid_t uid = 0; + gid_t gid = 0; + mode_t mode = DEVMODE; + for (int i = 0; symLinks[i] != NULL; i++) { const char *linkName = symLinks[i]; char linkBuf[DEVICE_FILE_SIZE] = {}; + if (strstr(linkName, "/dev/block/by-name") != NULL) { + int res = GetDeviceNodePermissions(linkName, &uid, &gid, &mode); + INIT_CHECK(res != 0, AdjustDeviceNodePermissions(deviceNode, uid, gid, mode)); + } + if (strncpy_s(linkBuf, DEVICE_FILE_SIZE - 1, linkName, strlen(linkName)) != EOK) { INIT_LOGE("Failed to copy link name"); return; } const char *linkDir = dirname(linkBuf); if (MakeDirRecursive(linkDir, DIRMODE) < 0) { - INIT_LOGE("[uevent] Failed to create dir \" %s \", err = %d", linkDir, errno); + INIT_LOGE("[uevent] Failed to create dir \" %s \", err = %d", linkDir, errno); + return; } + errno = 0; + INIT_LOGI("symlink %s->%s", deviceNode, linkName); int rc = symlink(deviceNode, linkName); if (rc != 0) { - if (errno == EEXIST) { - INIT_LOGW("Link \" %s \" already linked to other target", linkName); - } else { + if (errno != EEXIST) { INIT_LOGE("Failed to link \" %s \" to \" %s \", err = %d", deviceNode, linkName, errno); } } } } -static inline void AdjustDeviceNodePermissions(const char *deviceNode, uid_t uid, gid_t gid, mode_t mode) +#if defined(WITH_SELINUX) && !defined(__RAMDISK__) +static void SetDeviceLable(const char *path, char **symLinks) { - if (INVALIDSTRING(deviceNode)) { - return; + int rc = 0; + char buffer[PATH_MAX] = {}; + const char *p = NULL; + char *slash = NULL; + + p = path; + slash = strchr(path, '/'); + while (slash != NULL) { + int gap = slash - p; + p = slash + 1; + if (gap == 0) { + slash = strchr(p, '/'); + continue; + } + if (gap < 0) { // end with '/' + return; + } + + if (memcpy_s(buffer, PATH_MAX, path, p - path - 1) != EOK) { + INIT_LOGE("[uevent] Failed to memcpy path %s", path); + return; + } + rc += Restorecon(buffer); + slash = strchr(p, '/'); } - if (chown(deviceNode, uid, gid) != 0) { - INIT_LOGW("Failed to change \" %s \" owner", deviceNode); + + rc += Restorecon(path); + if (rc != 0) { + INIT_LOGE("[uevent] Failed to Restorecon \" %s \"", path); } - if (chmod(deviceNode, mode) != 0) { - INIT_LOGW("Failed to change \" %s \" mode", deviceNode); + INIT_CHECK_ONLY_RETURN(symLinks != NULL); + char *context = NULL; + for (int i = 0; symLinks[i] != NULL; i++) { + const char *linkName = symLinks[i]; + const char *byNamePath = "/dev/block/by-name"; + if (strncmp(linkName, byNamePath, strlen(byNamePath)) == 0) { + (void)Restorecon(linkName); + lgetfilecon(linkName, &context); + if (context != NULL) { + setfilecon(path, context); + } + return; + } } + + return; } +#endif static int CreateDeviceNode(const struct Uevent *uevent, const char *deviceNode, char **symLinks, bool isBlock) { @@ -104,23 +176,26 @@ static int CreateDeviceNode(const struct Uevent *uevent, const char *deviceNode, INIT_LOGE("Create path \" %s \" failed", devicePath); return rc; } - - GetDeviceNodePermissions(deviceNode, &uid, &gid, &mode); + + (void)GetDeviceNodePermissions(deviceNode, &uid, &gid, &mode); mode |= isBlock ? S_IFBLK : S_IFCHR; - dev_t dev = makedev(major, minor); + dev_t dev = makedev((unsigned int)major, (unsigned int)minor); setegid(0); rc = mknod(deviceNode, mode, dev); if (rc < 0) { if (errno != EEXIST) { - INIT_LOGE("Create device node[%s %d, %d] failed", deviceNode, major, minor, errno); + INIT_LOGE("Create device node[%s %d, %d] failed. %d", deviceNode, major, minor, errno); return rc; } } AdjustDeviceNodePermissions(deviceNode, uid, gid, mode); - if (symLinks) { + if (symLinks != NULL) { CreateSymbolLinks(deviceNode, symLinks); } - // No matter what result the symbol links returns, +#if defined(WITH_SELINUX) && !defined(__RAMDISK__) + SetDeviceLable(deviceNode, symLinks); +#endif + // No matter what result the symbol links returns, // as long as create device node done, just returns success. rc = 0; return rc; @@ -128,30 +203,103 @@ static int CreateDeviceNode(const struct Uevent *uevent, const char *deviceNode, static int RemoveDeviceNode(const char *deviceNode, char **symLinks) { - int rc = -1; if (INVALIDSTRING(deviceNode)) { INIT_LOGE("Invalid device node"); - return rc; + return -1; } if (symLinks != NULL) { for (int i = 0; symLinks[i] != NULL; i++) { - char realPath[DEVICE_FILE_SIZE] = {}; + char realPath[DEVICE_FILE_SIZE] = {0}; const char *linkName = symLinks[i]; ssize_t ret = readlink(linkName, realPath, DEVICE_FILE_SIZE - 1); if (ret < 0) { continue; } if (STRINGEQUAL(deviceNode, realPath)) { + INIT_LOGI("unlink %s", linkName); unlink(linkName); } } } + INIT_LOGI("unlink %s", deviceNode); return unlink(deviceNode); } +static char *FindPlatformDeviceName(char *path) +{ + if (INVALIDSTRING(path)) { + return NULL; + } + + if (STARTSWITH(path, "/sys/devices/platform/")) { + path += strlen("/sys/devices/platform/"); + return path; + } + + // Some platform devices may not be registered under platform device. + if (STARTSWITH(path, "/sys/devices/")) { + path += strlen("/sys/devices/"); + return path; + } + return NULL; +} + +static int BuildDeviceSymbolLinks(char **links, int linkNum, const char *parent, + const char *partitionName, const char *deviceName) +{ + int num = linkNum; + links[num] = calloc(DEVICE_FILE_SIZE, sizeof(char)); + if (links[num] == NULL) { + INIT_LOGE("Failed to allocate memory for link, err = %d", errno); + return num; + } + + // If a block device without partition name. + // For now, we will not create symbol link for it. + if (!INVALIDSTRING(partitionName)) { + if (snprintf_s(links[num], DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, + "/dev/block/platform/%s/by-name/%s", parent, partitionName) == -1) { + INIT_LOGE("Failed to build link"); + } + if (STRINGEQUAL(parent, bootDevice)) { + num = linkNum + 1; + links[num] = calloc(DEVICE_FILE_SIZE, sizeof(char)); + if (links[num] == NULL) { + INIT_LOGE("Failed to allocate memory for link, err = %d", errno); + return linkNum; + } + if (snprintf_s(links[num], DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, + "/dev/block/by-name/%s", partitionName) == -1) { + INIT_LOGE("Failed to build link"); + } + } else { + INIT_LOGI("%s and %s is not match", parent, bootDevice); + } + } else if (!INVALIDSTRING(deviceName)) { + if (snprintf_s(links[num], DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, + "/dev/block/platform/%s/%s", parent, deviceName) == -1) { + INIT_LOGE("Failed to build link"); + } + } + + return num; +} + +static void FreeSymbolLinks(char **links, int length) +{ + if (links != NULL) { + for (int i = 0; i < length && links[i] != NULL; i++) { + free(links[i]); + links[i] = NULL; + } + free(links); + links = NULL; + } +} + static char **GetBlockDeviceSymbolLinks(const struct Uevent *uevent) { - if (uevent == NULL || !STRINGEQUAL(uevent->subsystem, "block")) { + if (uevent == NULL || uevent->subsystem == NULL || STRINGEQUAL(uevent->subsystem, "block") == 0) { INIT_LOGW("Invalid arguments, Skip to get device symbol links."); return NULL; } @@ -163,77 +311,50 @@ static char **GetBlockDeviceSymbolLinks(const struct Uevent *uevent) // For block device under one platform device. // check subsystem file under directory, see if it links to bus/platform. // For now, only support platform device. - char sysPath[SYSPATH_SIZE] = {}; + char sysPath[SYSPATH_SIZE] = {}; if (snprintf_s(sysPath, SYSPATH_SIZE, SYSPATH_SIZE - 1, "/sys%s", uevent->syspath) == -1) { INIT_LOGE("Failed to build sys path for device %s", uevent->syspath); return NULL; } - - char **links = calloc(sizeof(char *), BLOCKDEVICE_LINKS); + char **links = calloc(BLOCKDEVICE_LINKS, sizeof(char *)); int linkNum = 0; if (links == NULL) { INIT_LOGE("Failed to allocate memory for links, err = %d", errno); + return NULL; } - // Reverse walk through sysPath, and check subystem file under each directory. + // Reverse walk through sysPath, and check subsystem file under each directory. char *parent = dirname(sysPath); while (parent != NULL && !STRINGEQUAL(parent, "/") && !STRINGEQUAL(parent, ".")) { char subsystem[SYSPATH_SIZE]; if (snprintf_s(subsystem, SYSPATH_SIZE, SYSPATH_SIZE - 1, "%s/subsystem", parent) == -1) { INIT_LOGE("Failed to build subsystem path for device \" %s \"", uevent->syspath); + FreeSymbolLinks(links, BLOCKDEVICE_LINKS); return NULL; } - - char *bus = realpath(subsystem, NULL); + char *bus = GetRealPath(subsystem); if (bus == NULL) { - goto loop; + parent = dirname(parent); + continue; } - if (STRINGEQUAL(bus, "/sys/bus/platform")) { - INIT_LOGD("Find a platform device: %s", parent); - if (STARTSWITH(parent, "/sys/devices/platform/")) { - parent += strlen("/sys/devices/platform/"); - if (linkNum > BLOCKDEVICE_LINKS - 1) { - INIT_LOGW("Too much links, ignore"); - break; - } - links[linkNum] = calloc(sizeof(char), DEVICE_FILE_SIZE); - if (links[linkNum] == NULL) { - INIT_LOGE("Failed to allocate memory for link, err = %d", errno); - break; - } - // If a block device without partition name. - // For now, we will not create symbol link for it. - if (!INVALIDSTRING(uevent->partitionName)) { - if (snprintf_s(links[linkNum], DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, - "/dev/block/platform/%s/by-name/%s", parent, uevent->partitionName) == -1) { - INIT_LOGE("Failed to build link"); - break; - } - } + INIT_LOGV("Find a platform device: %s", parent); + parent = FindPlatformDeviceName(parent); + if (parent != NULL) { + INIT_WARNING_CHECK(linkNum < BLOCKDEVICE_LINKS - 1, links[linkNum] = NULL; + return links, "Too many links, ignore"); + linkNum = BuildDeviceSymbolLinks(links, linkNum, parent, uevent->partitionName, uevent->deviceName); linkNum++; } } -loop: + free(bus); parent = dirname(parent); - continue; } + links[linkNum] = NULL; return links; } -static void FreeSymbolLinks(char **links) -{ - if (links != NULL) { - for (int i = 0; links[i] != NULL; i++) { - free(links[i]); - links[i] = NULL; - } - free(links); - links = NULL; - } -} - static void HandleDeviceNode(const struct Uevent *uevent, const char *deviceNode, bool isBlock) { ACTION action = uevent->action; @@ -249,16 +370,28 @@ static void HandleDeviceNode(const struct Uevent *uevent, const char *deviceNode if (action == ACTION_ADD) { if (CreateDeviceNode(uevent, deviceNode, symLinks, isBlock) < 0) { INIT_LOGE("Create device \" %s \" failed", deviceNode); + } else { +#ifndef __RAMDISK__ + if (SetUeventDeviceParameter(deviceNode, action) != 0) { + INIT_LOGE("Set device parameter added failed"); + } +#endif } } else if (action == ACTION_REMOVE) { if (RemoveDeviceNode(deviceNode, symLinks) < 0) { INIT_LOGE("Remove device \" %s \" failed", deviceNode); + } else { +#ifndef __RAMDISK__ + if (SetUeventDeviceParameter(deviceNode, action) != 0) { + INIT_LOGE("Set device parameter removed failed"); + } +#endif } } else if (action == ACTION_CHANGE) { - INIT_LOGI("Device %s changed", uevent->syspath); + INIT_LOGV("Device %s changed", uevent->syspath); } // Ignore other actions - FreeSymbolLinks(symLinks); + FreeSymbolLinks(symLinks, BLOCKDEVICE_LINKS); } static const char *GetDeviceName(char *sysPath, const char *deviceName) @@ -270,7 +403,7 @@ static const char *GetDeviceName(char *sysPath, const char *deviceName) } if (deviceName != NULL && deviceName[0] != '\0') { // if device name reported by kernel includes '/', skip it. - // TODO: use entire device name reported by kernel + // use entire device name reported by kernel devName = basename((char *)deviceName); char *p = strrchr(deviceName, '/'); if (p != NULL) { // device name includes slash @@ -303,12 +436,14 @@ static const char *GetDeviceBasePath(const char *subsystem) devPath = "/dev/input"; } else if (STRINGEQUAL(subsystem, "drm")) { devPath = "/dev/dri"; - } else if (STRINGEQUAL(subsystem, "input")) { - devPath = "/dev/input"; } else if (STRINGEQUAL(subsystem, "graphics")) { devPath = "/dev/graphics"; } else if (STRINGEQUAL(subsystem, "sound")) { devPath = "/dev/snd"; + } else if (STRINGEQUAL(subsystem, "functionfs")) { + devPath = "/dev/functionfs"; + } else if (STRINGEQUAL(subsystem, "dma_heap")) { + devPath = "/dev/dma_heap"; } else { devPath = "/dev"; } @@ -324,7 +459,7 @@ void HandleBlockDeviceEvent(const struct Uevent *uevent) } if (strcmp(uevent->subsystem, "block") != 0) { - INIT_LOGE("Unexpceted uevent subsystem \" %s \" received in block device handler", uevent->subsystem); + INIT_LOGE("Unexpected uevent subsystem \" %s \" received in block device handler", uevent->subsystem); return; } @@ -338,6 +473,9 @@ void HandleBlockDeviceEvent(const struct Uevent *uevent) char deviceNode[DEVICE_FILE_SIZE] = {}; char sysPath[SYSPATH_SIZE] = {}; + if (uevent->syspath == NULL) { + return; + } if (strncpy_s(sysPath, SYSPATH_SIZE - 1, uevent->syspath, strlen(uevent->syspath) != EOK)) { INIT_LOGE("Failed to copy sys path"); return; @@ -357,7 +495,7 @@ void HandleBlockDeviceEvent(const struct Uevent *uevent) void HandleOtherDeviceEvent(const struct Uevent *uevent) { - if (uevent == NULL || uevent->subsystem == NULL) { + if (uevent == NULL || uevent->subsystem == NULL || uevent->syspath == NULL) { INIT_LOGE("Invalid uevent received"); return; } @@ -368,7 +506,7 @@ void HandleOtherDeviceEvent(const struct Uevent *uevent) char deviceNode[DEVICE_FILE_SIZE] = {}; char sysPath[SYSPATH_SIZE] = {}; - if (strncpy_s(sysPath, SYSPATH_SIZE - 1, uevent->syspath, strlen(uevent->syspath) != EOK)) { + if (strncpy_s(sysPath, SYSPATH_SIZE - 1, uevent->syspath, strlen(uevent->syspath)) != EOK) { INIT_LOGE("Failed to copy sys path"); return; } @@ -379,12 +517,12 @@ void HandleOtherDeviceEvent(const struct Uevent *uevent) INIT_LOGE("Cannot get device path or device name"); return; } - INIT_LOGD("HandleOtherDeviceEvent, devPath = %s, devName = %s", devPath, devName); + INIT_LOGV("HandleOtherDeviceEvent, devPath = %s, devName = %s", devPath, devName); - // For usb devices, should take care of it specially. - // if usb devices report DEVNAME, just create device node. - // otherwise, create deviceNode with bus number and device number. - if (STRINGEQUAL(uevent->subsystem, "usb")) { + // For usb devices, should take care of it specially. + // if usb devices report DEVNAME, just create device node. + // otherwise, create deviceNode with bus number and device number. + if (STRINGEQUAL(uevent->subsystem, "usb")) { if (uevent->deviceName != NULL) { if (snprintf_s(deviceNode, DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, "/dev/%s", uevent->deviceName) == -1) { INIT_LOGE("Make device file for device [%d : %d]", uevent->major, uevent->minor); @@ -396,19 +534,22 @@ void HandleOtherDeviceEvent(const struct Uevent *uevent) INIT_LOGE("usb device with invalid bus number or device number"); return; } - if (snprintf_s(deviceNode, DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, + if (snprintf_s(deviceNode, DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, "/dev/bus/usb/%03d/%03d", uevent->busNum, uevent->devNum) == -1) { - INIT_LOGE("Make usb device node for device [%d : %d]", uevent->busNum, uevent->devNum); + INIT_LOGE("Make usb device node for device [%d : %d]", uevent->busNum, uevent->devNum); } } - } else if (STARTSWITH(uevent->subsystem, "usb")) { - // Other usb devies, do not handle it. - return; - } else { + } else if (STARTSWITH(uevent->subsystem, "usb")) { + // Other usb devies, do not handle it. + return; + } else { + if (strcmp(uevent->deviceName, "mapper/control") == 0) { + devName = "mapper/control"; + } if (snprintf_s(deviceNode, DEVICE_FILE_SIZE, DEVICE_FILE_SIZE - 1, "%s/%s", devPath, devName) == -1) { INIT_LOGE("Make device file for device [%d : %d]", uevent->major, uevent->minor); return; } - } - HandleDeviceNode(uevent, deviceNode, false); + } + HandleDeviceNode(uevent, deviceNode, false); } diff --git a/ueventd/ueventd_firmware_handler.c b/ueventd/ueventd_firmware_handler.c old mode 100755 new mode 100644 index 16b4fffed2292cfaf2aa8716c94fa2452337e627..e40cbc2cd18d9221e3a6c8a1b073ccfc7e23a12f --- a/ueventd/ueventd_firmware_handler.c +++ b/ueventd/ueventd_firmware_handler.c @@ -13,17 +13,34 @@ * limitations under the License. */ -#include -#include -#include - #include "ueventd_firmware_handler.h" + +#include +#include +#include +#include #include "ueventd.h" #define INIT_LOG_TAG "ueventd" #include "init_log.h" +#include "securec.h" void HandleFimwareDeviceEvent(const struct Uevent *uevent) { - // TODO, implement it later. - INIT_LOGI("Firmware handler not implemented yet."); + char fwLoadingPath[PATH_MAX] = {}; + + if (snprintf_s(fwLoadingPath, PATH_MAX, PATH_MAX - 1, "/sys%s/loading", uevent->syspath) == -1) { + INIT_LOGE("Failed to build firmware loading path"); + return; + } + char realPath[PATH_MAX] = { 0 }; + realpath(fwLoadingPath, realPath); + int fd = open(realPath, O_WRONLY | O_CLOEXEC); + if (fd < 0) { + INIT_LOGE("Failed to open %s, err = %d", fwLoadingPath, errno); + return; + } + + char *endCode = "-1"; + (void)write(fd, "-1", strlen(endCode)); + close(fd); } diff --git a/ueventd/ueventd_main.c b/ueventd/ueventd_main.c new file mode 100644 index 0000000000000000000000000000000000000000..eb7c9eec26e3119e950036103f33bc2018cbcf63 --- /dev/null +++ b/ueventd/ueventd_main.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2021 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 "ueventd.h" +#include "ueventd_read_cfg.h" +#include "ueventd_socket.h" +#define INIT_LOG_TAG "ueventd" +#include "init_log.h" +#include "init_socket.h" +#include "parameter.h" + +static bool IsComplete() +{ + static bool complete = false; + if (complete) { + return true; + } + char enable[8] = {0}; + int ret = GetParameter("bootevent.boot.completed", "", enable, sizeof(enable)); + if (ret != 0) { + INIT_LOGE("Failed to get param value"); + return false; + } + if (strcmp(enable, "true") == 0) { + INIT_LOGI("boot completed"); + complete = true; + return true; + } + return false; +} + +static void PollUeventdSocketTimeout(int ueventSockFd, bool ondemand) +{ + struct pollfd pfd = {}; + pfd.events = POLLIN; + pfd.fd = ueventSockFd; + int timeout = ondemand ? UEVENTD_POLL_TIME : -1; + int ret = -1; + + while (1) { + pfd.revents = 0; + ret = poll(&pfd, 1, timeout); + if (ret == 0) { + if (IsComplete()) { + INIT_LOGI("poll ueventd socket timeout, ueventd exit"); + return; + } + INIT_LOGI("poll ueventd socket timeout, but init not complete"); + } else if (ret < 0) { + INIT_LOGE("Failed to poll ueventd socket!"); + return; + } + if (pfd.revents & (POLLIN | POLLERR)) { + ProcessUevent(ueventSockFd, NULL, 0); // Not require boot devices + } + } +} + +static int UeventdRetrigger(void) +{ + const char *ueventdConfigs[] = {"/etc/ueventd.config", "/vendor/etc/ueventd.config", NULL}; + int i = 0; + while (ueventdConfigs[i] != NULL) { + ParseUeventdConfigFile(ueventdConfigs[i++]); + } + int ueventSockFd = UeventdSocketInit(); + if (ueventSockFd < 0) { + INIT_LOGE("Failed to create uevent socket!"); + return -1; + } + RetriggerUevent(ueventSockFd, NULL, 0); // Not require boot devices + return 0; +} + +static int UeventdDaemon(int listen_only) +{ + // start log + EnableInitLog(INIT_INFO); + const char *ueventdConfigs[] = {"/etc/ueventd.config", "/vendor/etc/ueventd.config", NULL}; + int i = 0; + while (ueventdConfigs[i] != NULL) { + ParseUeventdConfigFile(ueventdConfigs[i++]); + } + bool ondemand = true; + int ueventSockFd = GetControlSocket("ueventd"); + if (ueventSockFd < 0) { + INIT_LOGW("Failed to get uevent socket, try to create"); + ueventSockFd = UeventdSocketInit(); + ondemand = false; + } + if (ueventSockFd < 0) { + INIT_LOGE("Failed to create uevent socket!"); + return -1; + } + if (!listen_only && access(UEVENTD_FLAG, F_OK)) { + INIT_LOGI("Ueventd started, trigger uevent"); + RetriggerUevent(ueventSockFd, NULL, 0); // Not require boot devices + int fd = open(UEVENTD_FLAG, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + INIT_LOGE("Failed to create ueventd flag!"); + return -1; + } + (void)close(fd); + } else { + INIT_LOGI("ueventd start to process uevent message"); + ProcessUevent(ueventSockFd, NULL, 0); // Not require boot devices + } + PollUeventdSocketTimeout(ueventSockFd, ondemand); + CloseUeventConfig(); + return 0; +} + +static int UeventdEarlyBoot(void) +{ + int ueventSockFd = UeventdSocketInit(); + if (ueventSockFd < 0) { + return -1; + } + + char *devices[] = { + "/dev/block/vdb", + "/dev/block/vdc" + }; + + RetriggerUevent(ueventSockFd, devices, 2); + close(ueventSockFd); + return 0; +} + +#define UEVENTD_MODE_DEAMON 0 +#define UEVENTD_MODE_EARLY_BOOT 1 +#define UEVENTD_MODE_RETRIGGER 2 +#define UEVENTD_MODE_LISTEN 3 + +static void usage(const char *name) +{ + if (name == NULL || strlen(name) > PROCESS_NAME_MAX_LENGTH) { + return ; + } + printf("Usage: %s [OPTION]\n" + "Listening kernel uevent to create device node.\n" + "It will read configs from {/,/system,/chipset}/etc/ueventd.config.\n\n" + "The options may be used to set listening mode.\n" + " -d, --daemon working in deamon mode(default mode)\n" + " -b, --boot working in early booting mode, create required device nodes\n" + " -l, --listen listen in verbose mode\n" + " -r, --retrigger retrigger all uevents\n" + " -v, --verbose log level\n" + " -h, --help print this help info\n", name); +} + +static void UeventdLogPrint(int logLevel, uint32_t domain, const char *tag, const char *fmt, va_list vargs) +{ + if (logLevel < (int)GetInitLogLevel()) { + return; + } + vprintf(fmt, vargs); + printf("\n"); +} + +int main(int argc, char *argv[]) +{ + int opt; + int daemon = UEVENTD_MODE_DEAMON; + + while ((opt = getopt(argc, argv, "drblv:h")) != -1) { + switch (opt) { + case 'd': + daemon = UEVENTD_MODE_DEAMON; + break; + case 'r': + SetInitCommLog(UeventdLogPrint); + daemon = UEVENTD_MODE_RETRIGGER; + break; + case 'b': + SetInitCommLog(UeventdLogPrint); + daemon = UEVENTD_MODE_EARLY_BOOT; + break; + case 'v': + EnableInitLog(atoi(optarg)); + SetInitCommLog(UeventdLogPrint); + break; + case 'l': + EnableInitLog(0); + SetInitCommLog(UeventdLogPrint); + daemon = UEVENTD_MODE_LISTEN; + break; + case 'h': + usage(argv[0]); + exit(0); + break; + default: /* '?' */ + fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n", + argv[0]); + exit(EXIT_FAILURE); + } + } + + if (daemon == UEVENTD_MODE_DEAMON) { + return UeventdDaemon(0); + } else if (daemon == UEVENTD_MODE_RETRIGGER) { + return UeventdRetrigger(); + } else if (daemon == UEVENTD_MODE_LISTEN) { + return UeventdDaemon(1); + } else { + UeventdEarlyBoot(); + } + + return 0; +} diff --git a/ueventd/ueventd_read_cfg.c b/ueventd/ueventd_read_cfg.c old mode 100755 new mode 100644 index ef938be08f15a481061fe186f1521fc0935a79ce..69d884e1ccfdb1aa519b571a09233b5b8d0e2f92 --- a/ueventd/ueventd_read_cfg.c +++ b/ueventd/ueventd_read_cfg.c @@ -14,13 +14,16 @@ */ #include "ueventd_read_cfg.h" + #include #include +#include #include #include #include #include #include +#include "init_utils.h" #include "list.h" #include "ueventd_utils.h" #include "securec.h" @@ -28,7 +31,9 @@ #include "init_log.h" // default item count in config files -#define DEFAULTITEMCOUNT (100) +#define DEFAULTITEMCOUNT (50) +#define MAX_CONFIGURE_SIZE (1024 * 1024 * 16) + typedef enum SECTION { SECTION_INVALID = -1, SECTION_DEVICE = 0, @@ -38,7 +43,7 @@ typedef enum SECTION { typedef int (*ParseConfigFunc)(char *); typedef struct FunctionMapper { - char *name; + const char *name; ParseConfigFunc func; } FUNCTIONMAPPER; @@ -57,177 +62,109 @@ struct ListNode g_firmwares = { .prev = &g_firmwares, }; -static void FreeConfigItems(char **items, int count) -{ - if (items != NULL) { - for (int i = 0; i < count; i++) { - if (items[i] != NULL) { - free(items[i]); - } - } - free(items); - items = NULL; - } -} - -static char **SplitUeventConfig(char *buffer, const char *del, int *returnCount, int maxItemCount) -{ - char *rest = NULL; - int count = 0; - char *p = strtok_r(buffer, del, &rest); - if (maxItemCount < 0) { - return NULL; - } - if (maxItemCount > DEFAULTITEMCOUNT) { - maxItemCount = DEFAULTITEMCOUNT; - } - char **items = (char **)malloc(sizeof(char*) * maxItemCount); - if (items == NULL) { - INIT_LOGE("No enough memory to store uevent config"); - return NULL; - } - while (p != NULL) { - if (count > maxItemCount - 1) { - maxItemCount += (maxItemCount / 2) + 1; - INIT_LOGD("Too many items,expand size"); - char **expand = (char **)(realloc(items, sizeof(char *) * maxItemCount)); - if (expand == NULL) { - INIT_LOGE("Failed to expand memory for uevent config parser"); - FreeConfigItems(items, count); - return NULL; - } - items = expand; - } - size_t len = strlen(p); - items[count] = (char *)malloc(len + 1); - if (items[count] == NULL) { - FreeConfigItems(items, count); - return NULL; - } - if (strncpy_s(items[count], len + 1, p, len) != EOK) { - INIT_LOGE("Copy string failed"); - FreeConfigItems(items, count); - return NULL; - } - items[count][strlen(p)] = '\0'; - count++; - p = strtok_r(NULL, del, &rest); - } - items[count] = NULL; - *returnCount = count; - return items; -} - static int ParseDeviceConfig(char *p) { - INIT_LOGD("Parse device config info: %s", p); + INIT_LOGV("Parse device config info: %s", p); char **items = NULL; int count = -1; - // format: - int expectedCount = 4; + // format: + const int expectedCount = 5; - if (INVALIDSTRING(p)) { - INIT_LOGE("Invalid argument"); - } - items = SplitUeventConfig(p, " ", &count, expectedCount); - if (count != expectedCount) { + INIT_CHECK_ONLY_ELOG(!INVALIDSTRING(p), "Invalid argument"); + items = SplitStringExt(p, " ", &count, expectedCount); + if ((count != expectedCount) && (count != expectedCount - 1)) { INIT_LOGE("Ignore invalid item: %s", p); - FreeConfigItems(items, count); + FreeStringVector(items, count); return 0; } struct DeviceUdevConf *config = calloc(1, sizeof(struct DeviceUdevConf)); if (config == NULL) { errno = ENOMEM; - FreeConfigItems(items, count); + FreeStringVector(items, count); return -1; } config->name = strdup(items[0]); // device node + INIT_ERROR_CHECK(config->name != NULL, FreeStringVector(items, count); + free(config); return -1, "failed dup config name"); errno = 0; - config->mode = strtoul(items[1], NULL, OCTONARY); - if (errno != 0) { - INIT_LOGE("Invalid mode in config file for device node %s. use default mode", config->name); - config->mode = DEVMODE; + config->mode = strtoul(items[1], NULL, OCTAL_BASE); // mode + INIT_ERROR_CHECK(errno == 0, config->mode = DEVMODE, + "Invalid mode in config file for device node %s. use default mode", config->name); + config->uid = (uid_t)DecodeUid(items[2]); // uid + config->gid = (gid_t)DecodeGid(items[3]); // gid + if (count == expectedCount) { + config->parameter = strdup(items[4]); // device parameter + INIT_ERROR_CHECK(config->parameter != NULL, FreeStringVector(items, count); + free((void*)config->name); free(config); return -1, "failed dup parameter"); + } else { + config->parameter = NULL; } - config->uid = StringToInt(items[2], 0); - config->gid = StringToInt(items[3], 0); - ListAddTail(&g_devices, &config->list); - FreeConfigItems(items, count); + OH_ListInit(&config->paramNode); + OH_ListAddTail(&g_devices, &config->list); + FreeStringVector(items, count); return 0; } static int ParseSysfsConfig(char *p) { - INIT_LOGD("Parse sysfs config info: %s", p); + INIT_LOGV("Parse sysfs config info: %s", p); char **items = NULL; int count = -1; // format: - int expectedCount = 5; + const int expectedCount = 5; - if (INVALIDSTRING(p)) { - INIT_LOGE("Invalid argument"); - } - items = SplitUeventConfig(p, " ", &count, expectedCount); + INIT_CHECK_ONLY_ELOG(!INVALIDSTRING(p), "Invalid argument"); + items = SplitStringExt(p, " ", &count, expectedCount); if (count != expectedCount) { INIT_LOGE("Ignore invalid item: %s", p); - FreeConfigItems(items, count); + FreeStringVector(items, count); return 0; } struct SysUdevConf *config = calloc(1, sizeof(struct SysUdevConf)); if (config == NULL) { errno = ENOMEM; - FreeConfigItems(items, count); + FreeStringVector(items, count); return -1; } config->sysPath = strdup(items[0]); // sys path + INIT_ERROR_CHECK(config->sysPath != NULL, FreeStringVector(items, count); + free(config); return -1, "failed to dup syspath"); config->attr = strdup(items[1]); // attribute + INIT_ERROR_CHECK(config->attr != NULL, FreeStringVector(items, count); + free((void*)config->sysPath); free(config); return -1, "failed to dup attr"); errno = 0; - config->mode = strtoul(items[2], NULL, OCTONARY); - if (errno != 0) { - INIT_LOGE("Invalid mode in config file for sys path %s. use default mode", config->sysPath); - config->mode = DEVMODE; - } - config->uid = StringToInt(items[3], 0); - config->gid = StringToInt(items[4], 0); - ListAddTail(&g_sysDevices, &config->list); + config->mode = strtoul(items[2], NULL, OCTAL_BASE); // mode + INIT_ERROR_CHECK(errno == 0, config->mode = DEVMODE, + "Invalid mode in config file for sys path %s. use default mode", config->sysPath); + config->uid = (uid_t)DecodeUid(items[3]); // uid + config->gid = (gid_t)DecodeGid(items[4]); // gid + OH_ListAddTail(&g_sysDevices, &config->list); + FreeStringVector(items, count); return 0; } static int ParseFirmwareConfig(char *p) { - INIT_LOGD("Parse firmware config info: %s", p); - if (INVALIDSTRING(p)) { - INIT_LOGE("Invalid argument"); - } - struct FirmwareUdevConf *config = calloc(1, sizeof(struct FirmwareUdevConf)); - if (config == NULL) { - errno = ENOMEM; - return -1; - } + INIT_LOGV("Parse firmware config info: %s", p); + INIT_ERROR_CHECK(!INVALIDSTRING(p), return -1, "Invalid argument"); // Sanity checks struct stat st = {}; - if (stat(p, &st) != 0) { - INIT_LOGE("Invalid firware file: %s, err = %d", p, errno); - return -1; - } - - if (!S_ISDIR(st.st_mode)) { - INIT_LOGE("Expect directory in firmware config"); - return -1; - } - + INIT_ERROR_CHECK(stat(p, &st) == 0, return -1, "Invalid firmware file: %s, err = %d", p, errno); + INIT_ERROR_CHECK(S_ISDIR(st.st_mode), return -1, "Expect directory in firmware config"); + struct FirmwareUdevConf *config = calloc(1, sizeof(struct FirmwareUdevConf)); + INIT_CHECK(config != NULL, errno = ENOMEM; + return -1); config->fmPath = strdup(p); - ListAddTail(&g_firmwares, &config->list); + INIT_ERROR_CHECK(config->fmPath != NULL, free(config); return -1, "failed to dup fmpath"); + OH_ListAddTail(&g_firmwares, &config->list); return 0; } -static SECTION GetSection(char *section) +static SECTION GetSection(const char *section) { - if (INVALIDSTRING(section)) { - return SECTION_INVALID; - } - + INIT_CHECK_RETURN_VALUE(!INVALIDSTRING(section), SECTION_INVALID); if (STRINGEQUAL(section, "device")) { return SECTION_DEVICE; } else if (STRINGEQUAL(section, "sysfs")) { @@ -239,7 +176,7 @@ static SECTION GetSection(char *section) } } -static FUNCTIONMAPPER funcMapper[3] = { +static const FUNCTIONMAPPER funcMapper[3] = { {"device", ParseDeviceConfig}, {"sysfs", ParseSysfsConfig}, {"firmware", ParseFirmwareConfig} @@ -253,9 +190,7 @@ int ParseUeventConfig(char *buffer) char *p = buffer; SECTION type; - if (INVALIDSTRING(buffer)) { - return -1; - } + INIT_CHECK_RETURN_VALUE(!INVALIDSTRING(buffer), -1); if (*p == '[') { p++; if ((right = strchr(p, ']')) == NULL) { @@ -264,7 +199,7 @@ int ParseUeventConfig(char *buffer) } *right = '\0'; // Replace ']' with '\0'; section = p; - INIT_LOGD("section is [%s]", section); + INIT_LOGV("section is [%s]", section); if ((type = GetSection(section)) == SECTION_INVALID) { INIT_LOGE("Invalid section \" %s \"", section); callback = NULL; // reset callback @@ -273,17 +208,17 @@ int ParseUeventConfig(char *buffer) callback = funcMapper[type].func; return 0; } - return callback != NULL ? callback(p) : -1; + return (callback != NULL) ? callback(p) : -1; } -static void DoUeventConfigParse(char *buffer) +static void DoUeventConfigParse(char *buffer, size_t length) { char **items = NULL; int count = -1; - int maxItemCount = DEFAULTITEMCOUNT; + const int maxItemCount = DEFAULTITEMCOUNT; - items = SplitUeventConfig(buffer, "\n", &count, maxItemCount); - INIT_LOGD("Dump items count = %d", count); + items = SplitStringExt(buffer, "\n", &count, maxItemCount); + INIT_LOGV("Dump items count = %d", count); for (int i = 0; i < count; i++) { char *p = items[i]; // Skip lead white space @@ -301,20 +236,17 @@ static void DoUeventConfigParse(char *buffer) } } // release memory - FreeConfigItems(items, count); + FreeStringVector(items, count); } void ParseUeventdConfigFile(const char *file) { - if (INVALIDSTRING(file)) { - return; - } - - int fd = open(file, O_RDONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (fd < 0) { - INIT_LOGE("Read from %s failed", file); - return; - } + INIT_CHECK_ONLY_RETURN(!INVALIDSTRING(file)); + char *config = GetRealPath(file); + INIT_CHECK_ONLY_RETURN(config != NULL); + int fd = open(config, O_RDONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + free(config); + INIT_ERROR_CHECK(fd >= 0, return, "Read from %s failed", file); struct stat st; if (fstat(fd, &st) < 0) { @@ -324,6 +256,11 @@ void ParseUeventdConfigFile(const char *file) } // st_size should never be less than 0 + if (st.st_size < 0 || st.st_size > MAX_CONFIGURE_SIZE) { + INIT_LOGE("Invalid configure file with size"); + close(fd); + return; + } size_t size = (size_t)st.st_size; char *buffer = malloc(size + 1); if (buffer == NULL) { @@ -341,31 +278,103 @@ void ParseUeventdConfigFile(const char *file) } buffer[size] = '\0'; - DoUeventConfigParse(buffer); + DoUeventConfigParse(buffer, size); free(buffer); buffer = NULL; close(fd); } -void GetDeviceNodePermissions(const char *devNode, uid_t *uid, gid_t *gid, mode_t *mode) +// support '*' to match all characters +// '?' match one character. +bool IsMatch(const char *target, const char *pattern) +{ + INIT_CHECK_RETURN_VALUE(target != NULL, false); + INIT_CHECK_RETURN_VALUE(pattern != NULL, true); + + const char *t = target; + const char *p = pattern; + const char *plast = NULL; + bool reMatch = false; + while (*t != '\0') { + if (*t == *p) { + t++; + p++; + continue; + } + + // Match one character. + if (*p == '?') { + p++; + t++; + continue; + } + + if (*p == '\0') { + return reMatch; + } + + if (*p == '*') { + reMatch = true; + // Met '*', record where we will start over. + // plast point to next character that we will compare it again. + plast = ++p; + t++; + continue; + } + + if (reMatch) { + // Start over. + p = plast; + t++; + } else { + return false; + } + } + + while (*p == '*') { + p++; + } + return (*p == '\0'); +} + +struct DeviceUdevConf *GetDeviceUdevConfByDevNode(const char *devNode) { if (INVALIDSTRING(devNode)) { - return; + return NULL; } struct ListNode *node = NULL; if (!ListEmpty(g_devices)) { ForEachListEntry(&g_devices, node) { struct DeviceUdevConf *config = ListEntry(node, struct DeviceUdevConf, list); - if (STRINGEQUAL(config->name, devNode)) { + if (IsMatch(devNode, config->name)) { + return config; + } + } + } + + return NULL; +} + +int GetDeviceNodePermissions(const char *devNode, uid_t *uid, gid_t *gid, mode_t *mode) +{ + if (INVALIDSTRING(devNode)) { + return -1; + } + + struct ListNode *node = NULL; + if (!ListEmpty(g_devices)) { + ForEachListEntry(&g_devices, node) { + struct DeviceUdevConf *config = ListEntry(node, struct DeviceUdevConf, list); + if (IsMatch(devNode, config->name)) { *uid = config->uid; *gid = config->gid; *mode = config->mode; - break; + return 0; } } } - return; + return -1; } void ChangeSysAttributePermissions(const char *sysPath) @@ -376,16 +385,18 @@ void ChangeSysAttributePermissions(const char *sysPath) struct ListNode *node = NULL; struct SysUdevConf *config = NULL; + int matched = 0; if (!ListEmpty(g_sysDevices)) { ForEachListEntry(&g_sysDevices, node) { config = ListEntry(node, struct SysUdevConf, list); if (STRINGEQUAL(config->sysPath, sysPath)) { - break; + matched = 1; + break; } } } - if (config == NULL) { + if (matched == 0) { return; } char sysAttr[SYSPATH_SIZE] = {}; @@ -401,3 +412,34 @@ void ChangeSysAttributePermissions(const char *sysPath) INIT_LOGE("[uevent][error] chmod for file %s failed, err = %d", sysAttr, errno); } } + +static void FreeDeviceConfig(ListNode *node) +{ + struct DeviceUdevConf *config = ListEntry(node, struct DeviceUdevConf, list); + free((void *)config->name); + free((void *)config->parameter); + OH_ListRemove(&config->paramNode); + free(config); +} + +static void FreeSysUdevConf(ListNode *node) +{ + struct SysUdevConf *config = ListEntry(node, struct SysUdevConf, list); + free((void *)config->sysPath); + free((void *)config->attr); + free(config); +} + +static void FreeFirmwareUdevConf(ListNode *node) +{ + struct FirmwareUdevConf *config = ListEntry(node, struct FirmwareUdevConf, list); + free((void *)config->fmPath); + free(config); +} + +void CloseUeventConfig(void) +{ + OH_ListRemoveAll(&g_devices, FreeDeviceConfig); + OH_ListRemoveAll(&g_sysDevices, FreeSysUdevConf); + OH_ListRemoveAll(&g_firmwares, FreeFirmwareUdevConf); +} \ No newline at end of file diff --git a/ueventd/ueventd_socket.c b/ueventd/ueventd_socket.c old mode 100755 new mode 100644 index 2243aa7f37e8b48fe647ab2b06f46f6b1bacd7c1..43c5094073d4ed89fa4f02994bca8abdd95b08e1 --- a/ueventd/ueventd_socket.c +++ b/ueventd/ueventd_socket.c @@ -14,39 +14,32 @@ */ #include -#include -#include #include #include #include -#include -#include #include -#include #include -#include -#include #include "securec.h" #define INIT_LOG_TAG "ueventd" #include "init_log.h" -int UeventdSocketInit() +#define UEVENT_SOCKET_BUFF_SIZE (256 * 1024) + +int UeventdSocketInit(void) { struct sockaddr_nl addr; - int sockfd; - int buffSize = 256 * 1024; + int buffSize = UEVENT_SOCKET_BUFF_SIZE; int on = 1; - if (memset_s(&addr, sizeof(addr), 0, sizeof(addr) != EOK)) { - INIT_LOGE("Faild to clear socket address"); + if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) { + INIT_LOGE("Failed to clear socket address"); return -1; } addr.nl_family = AF_NETLINK; addr.nl_pid = getpid(); addr.nl_groups = 0xffffffff; - sockfd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); - + int sockfd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); if (sockfd < 0) { INIT_LOGE("Create socket failed, err = %d", errno); return -1; @@ -55,10 +48,12 @@ int UeventdSocketInit() setsockopt(sockfd, SOL_SOCKET, SO_RCVBUFFORCE, &buffSize, sizeof(buffSize)); setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); - if(bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { INIT_LOGE("Bind socket failed, err = %d", errno); +#ifndef STARTUP_INIT_TEST close(sockfd); return -1; +#endif } return sockfd; } @@ -66,11 +61,10 @@ int UeventdSocketInit() ssize_t ReadUeventMessage(int sockFd, char *buffer, size_t length) { ssize_t n = -1; - struct msghdr msghdr; + struct msghdr msghdr = {}; struct iovec iov; struct sockaddr_nl addr; char credMsg[CMSG_SPACE(sizeof(struct ucred))]; - struct cmsghdr *cmsghdr; // sanity check if (sockFd < 0 || buffer == NULL) { @@ -90,7 +84,7 @@ ssize_t ReadUeventMessage(int sockFd, char *buffer, size_t length) if (n <= 0) { return n; } - cmsghdr = CMSG_FIRSTHDR(&msghdr); + struct cmsghdr *cmsghdr = CMSG_FIRSTHDR(&msghdr); if (cmsghdr == NULL || cmsghdr->cmsg_type != SCM_CREDENTIALS) { INIT_LOGE("Unexpected control message, ignored"); // Drop this message diff --git a/watchdog/BUILD.gn b/watchdog/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3458ef72225a72373c560b9a4b2c614d0cd53db4 --- /dev/null +++ b/watchdog/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2021-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. + +if (defined(ohos_lite)) { + executable("watchdog_service") { + sources = [ + "//base/startup/init/services/log/init_commlog.c", + "//base/startup/init/watchdog/init_watchdog.c", + ] + deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init/services/log:init_log", + ] + external_deps = [ "bounds_checking_function:libsec_static" ] + defines = [ + "_GNU_SOURCE", + "OHOS_LITE_WATCHDOG", + ] + if (ohos_kernel_type == "linux") { + defines += [ "LINUX_WATCHDOG" ] + } + } +} else { + import("//build/ohos.gni") + ohos_executable("watchdog_service") { + sources = [ + "//base/startup/init/services/log/init_commlog.c", + "init_watchdog.c", + ] + deps = [ "//base/startup/init/services/log:init_log" ] + + external_deps = [ "bounds_checking_function:libsec_shared" ] + + defines = [ "LINUX_WATCHDOG" ] + defines += [ "_GNU_SOURCE" ] + install_enable = true + part_name = "init" + subsystem_name = "startup" + } +} + +group("watchdog") { + if (defined(ohos_lite)) { + if (ohos_kernel_type == "linux" || ohos_kernel_type == "liteos_a") { + deps = [ ":watchdog_service" ] + } else { + deps = [] + } + } else { + deps = [ ":watchdog_service" ] + } +} diff --git a/watchdog/init_watchdog.c b/watchdog/init_watchdog.c new file mode 100644 index 0000000000000000000000000000000000000000..6aef64d408193a81f15ba4b38acbd53a51c66b09 --- /dev/null +++ b/watchdog/init_watchdog.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021-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 + +#ifdef LINUX_WATCHDOG +#include +#else +#include +#define WDIOC_KEEPALIVE _IO('W', 5) +#define WDIOC_SETTIMEOUT _IOWR('W', 6, int) +#define WDIOC_GETTIMEOUT _IOR('W', 7, int) +#endif + +#include "init_log.h" + +#define WAIT_MAX_COUNT 20 +#define DEFAULT_INTERVAL 3 +#define DEFAULT_GAP 3 +#define CONVERSION_BASE 1000000U + +#define PRETIMEOUT_GAP 5 +#define PRETIMEOUT_DIV 2 + +static void WaitAtStartup(const char *source) +{ + unsigned int count = 0; + struct stat sourceInfo; + const unsigned int waitTime = 500000; + do { + usleep(waitTime); + count++; + } while ((stat(source, &sourceInfo) < 0) && (errno == ENOENT) && (count < WAIT_MAX_COUNT)); + if (count == WAIT_MAX_COUNT) { + INIT_LOGE("wait for file:%s failed after %u seconds.", source, (WAIT_MAX_COUNT * waitTime) / CONVERSION_BASE); + } + return; +} + +#ifdef WDIOC_SETPRETIMEOUT +int GetWatcherDogCfg(int interval, int timeoutGet, int fd) +{ + int preTimeout = 0; + int preTimeoutGet = 0; + preTimeout = timeoutGet - PRETIMEOUT_GAP; // ensure pretimeout smaller then timeout + if (preTimeout > 0) { + int ret = ioctl(fd, WDIOC_SETPRETIMEOUT, &preTimeout); + if (ret) { + INIT_LOGE("Failed to set pretimeout to %d\n", preTimeout); + } + ret = ioctl(fd, WDIOC_GETPRETIMEOUT, &preTimeoutGet); + if (ret) { + INIT_LOGE("Failed to get pretimeout\n"); + } + } + + if (preTimeoutGet > 0 && preTimeoutGet < interval) { + interval = preTimeoutGet / PRETIMEOUT_DIV; + } + return interval; +} +#endif + +int main(int argc, const char *argv[]) +{ + EnableInitLog(INIT_INFO); + WaitAtStartup("/dev/watchdog"); + int fd = open("/dev/watchdog", O_RDWR); + if (fd == -1) { + INIT_LOGE("Can't open /dev/watchdog."); + return 1; + } + + int interval = 0; + if (argc >= 2) { // Argument nums greater than or equal to 2. + interval = atoi(argv[1]); + if (interval < 0 || interval > INT16_MAX) { + interval = DEFAULT_INTERVAL; + } + } + interval = (interval > 0) ? interval : DEFAULT_INTERVAL; + + int gap = 0; + if (argc >= 3) { // Argument nums greater than or equal to 3. + gap = atoi(argv[2]); // 2 second parameter. + } + gap = (gap > 0) ? gap : DEFAULT_GAP; + + INIT_LOGI("Watchdog started (interval %d, margin %d), fd = %d\n", interval, gap, fd); +#ifdef OHOS_LITE_WATCHDOG +#ifndef LINUX_WATCHDOG + if (setpriority(PRIO_PROCESS, 0, 14) != 0) { // 14 is process priority + INIT_LOGE("setpriority failed err=%d\n", errno); + } +#endif +#endif + int timeoutSet = interval + gap; + int timeoutGet = 0; + + int ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeoutSet); + if (ret) { + INIT_LOGE("Failed to set timeout to %d\n", timeoutSet); + } + ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeoutGet); + if (ret) { + INIT_LOGE("Failed to get timeout\n"); + } + + if (timeoutGet > 0) { + interval = (timeoutGet > gap) ? (timeoutGet - gap) : 1; + } + +#ifdef WDIOC_SETPRETIMEOUT + interval = GetWatcherDogCfg(interval, timeoutGet, fd); +#endif + + while (1) { + ioctl(fd, WDIOC_KEEPALIVE); + sleep(interval); + } + close(fd); + return -1; +}