Analyze the ELF disassembly code to obtain the call relationship, collect statistics on the APIs that call the libc library, and then parse the LibC library to obtain the call relationship between the LibC APIs and the system call numbers. In this way, you will obtain the system call numbers used by the ELF file.|
Statistics collection is supported for system calls in abnormal branches. |
Parsing of call relationship is not supported for pointer functions. |
+| Strace statistics | Use Strace to trace service processes or test processes when the device is running. During the trace, the invoked system calls are recorded into logs. Collect the logs after the trace is complete, and use a script to parse the logs and generate a Seccomp policy file.| Easy to use. | System calls can be completely collected only when all code branches are traversed. |
+| Audit statistics | After the Seccomp policy is enabled for a process, Seccomp intercepts invalid system calls and records audit log information containing the system call numbers into kernel logs. Collect the logs after the trace is complete, and use a script to parse the logs and generate a Seccomp policy file.| This method can be used as a supplement to the preceding methods. | Logs may be lost.
System calls can be completely collected only when all code branches are traversed. |
+
+> **Disclaimer: Using Third-Party Software or Websites**
+>
+> We may recommend software, information, products, or websites owned or operated by third parties. A recommendation is usually provided via a hyperlink or other methods to help you access third-party resources.
+> We strive to direct you to useful and trusted resources, but it is beyond our reach to guarantee the software, information, products, or services provided by or at third-party resources, or to track changes in these resources. Therefore, we are unable to assume the responsibility for the compliance, accuracy, and completeness of the content or results of any third-party resources, nor for any loss or damage caused by the use or failure of products or services provided by third-party resources.
+
+#### Static Analysis
+
+1. Prepare the environment.
+ 1. Prepare a Linux environment.
+ 2. Download the cross compilers arm-linux-musleabi and aarch64-linux-musl.
+ ```shell
+ # Add the tool execution path to the environment variable.
+ export PATH=$PATH:/path/to/arm-linux-musleabi-cross/bin
+ export PATH=$PATH:/path/to/aarch64-linux-musl-cross/bin
+ ```
+
+ 3. Download the OpenHarmony source code.
+ For details, see [Obtaining Source Code](../get-code/sourcecode-acquire.md).
+
+2. Compile **seccomp_filter** to obtain the dependency files **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**.
+
+ **seccomp_filter** is declared in **base/startup/init/services/modules/seccomp/BUILD.gn** and is used to build the basic dynamic policy library of Seccomp. After the compilation is complete, dependency files are generated in **//out/Product name /gen/base/startup/init/services/modules/seccomp/gen_system_filter/**.
+ ```shell
+ ./build.sh --product-name *product name* --ccache --build-target seccomp_filter --target-cpu *specified CPU*
+
+ # Copy the dependency files to the tool folder for later use.
+ cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/
+ ```
+
+3. Copy the **generate_code_from_policy.py** script file to the tool folder. This script is available at **//base/startup/init/services/modules/seccomp/scripts/**.
+ ```shell
+ # Go to the root directory of the OpenHarmony source code.
+ cd /root/to/OpenharmonyCode;
+ # Go to the directory where the **generate_code_from_policy.py** script file is located.
+ cd base/startup/init/services/modules/seccomp/scripts/;
+ # Copy the **generate_code_from_policy.py** script file.
+ cp generate_code_from_policy.py tools/;
+ ```
+
+4. Compile ELF files related to the service code. In the 32-bit architecture, the implementation of disassembly code redirection for ELF files is complex. Therefore, ELF files are all compiled into 64-bit ELF files to parse the function call relationship.
+ ```shell
+ ./build.sh --product-name *product file* --ccache --target-cpu arm64 --build-target *target file*
+ ```
+
+5. Modify the **collect_elf_syscall.py** script file, and change the paths of the objdump and readelf tools to their absolute paths in the Linux environment. The tools are stored in **//prebuilts**, and more particularly, **//prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin**.
+ ```python
+ #modified the path of objdump and readelf path
+ def get_obj_dump_path():
+ obj_dump_path = '/path/to/prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin/llvm-objdump'
+ return obj_dump_path
+
+
+ def get_read_elf_path():
+ read_elf_path = '/path/to/prebuilts/clang/ohos/linux-x86_64/15.0.4/llvm/bin/llvm-readelf'
+ return read_elf_path
+ ```
+
+6. Use the **collect_elf_syscall.py** script file to parse and generate the corresponding policy file **xxx.seccomp.policy**.
+
+ The script file is available at **//base/startup/init/services/modules/seccomp/scripts/tools/**.
+
+ **Table 7** Parameters in the collect_elf_syscall.py script file
+ | Parameter | Description |
+ | --- | --- |
+ | --src-elf-path | Folder where the ELF file is located, for example, **~/ohcode/out/rk3568**. Do not end the value with a slash (/).|
+ | --elf-name| ELF file name, for example, **libmedia_service.z.so**.|
+ | --src-syscall-path | **libsyscall_to_nr_arm** or **libsyscall_to_nr_arm64**, which corresponds to the architecture specified by **--target-cpu**. |
+ | --target-cpu | CPU architecture, that is, the architecture for which system calls are collected. This parameter determines the architecture for libC file parsing. Its value can be **arm** or **arm64**. |
+ | --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
+
+ Use **collect_elf_syscall.py** to parse ELF files.
+
+ ```
+ # The following example considers **rk3568** as the product and **libmedia_service.z.so** as the ELF file.
+ python3 collect_elf_syscall.py --src-elf-path ~/ohcode/out/rk3568 --elf-name libmedia_service.z.so --src-syscall-path libsyscall_to_nr_arm64 --target-cpu arm64 --filter-name media_service
+ ```
+
+ Example result of xxx.seccomp.policy
+ ```
+ @allowList
+ getcwd;arm64
+ eventfd2;arm64
+ epoll_create1;arm64
+ epoll_ctl;arm64
+ dup;arm64
+ dup3;arm64
+ fcntl;arm64
+ ioctl;arm64
+ ...
+ ```
+
+#### Strace Statistics
+
+1. Use the cross compilers arm-linux-musleabi and aarch64-linux-musl to build the Strace tool for the 32-bit and 64-bit architectures, respectively.
+2. [Trace the test process](#tracing-the-test-process) to obtain Strace logs.
+3. [Trace the service process](#tracing-the-service-process) to obtain the Strace logs.
+4. [Parse Strace logs](#parsing-strace-logs) by using scripts to obtain the Seccomp policy file.
+
+##### Tracing the Test Process
+
+1. Push the Strace tool to the device.
+ ```shell
+ hdc shell mount -rw -o remount /
+ hdc file send /path/to/strace /system/bin/
+ hdc shell chmod a+x /system/bin/strace
+ ```
+
+2. Modify the local embedded code in the [developer test framework](https://gitee.com/openharmony/testfwk_developer_test) so that Strace is executed in the test suite to trace the test process.
+
+ Modify the **_init_gtest** and **_run_gtest** functions in **src/core/driver/drivers.py** as follows. If a line starts with a plus sign (+), the line is added; if a line starts with a hyphen (-), the line is deleted.
+
+ ```python
+ --- a/src/core/driver/drivers.py
+ +++ b/src/core/driver/drivers.py
+ @@ -500,6 +500,8 @@ class CppTestDriver(IDriver):
+ "rm -rf %s" % self.config.target_test_path)
+ self.config.device.execute_shell_command(
+ "mkdir -p %s" % self.config.target_test_path)
+ + self.config.device.execute_shell_command(
+ + "mkdir -p /data/strace")
+ self.config.device.execute_shell_command(
+ "mount -o rw,remount,rw /")
+ if "fuzztest" == self.config.testtype[0]:
+ @@ -539,10 +541,11 @@ class CppTestDriver(IDriver):
+ test_para,
+ seed)
+ else:
+ - command = "cd %s; rm -rf %s.xml; chmod +x *; ./%s %s" % (
+ + command = "cd %s; rm -rf %s.xml; chmod +x *; strace -ff -o /data/strace/%s.strace.log ./%s %s" % (
+ self.config.target_test_path,
+ filename,
+ filename,
+ + filename,
+ test_para)
+ else:
+ coverage_outpath = self.config.coverage_outpath
+ ```
+3. Execute related service test cases.
+4. Obtain Strace logs from **/data/strace** on the device.
+ ```shell
+ hdc file recv /data/strace /path/to/base/startup/init/services/modules/seccomp/scripts/tools/
+ ```
+
+##### Tracing the Service Process
+
+1. Modify the embedded code in the init repository. Specifically, add the following content to **//base/startup/init/services/init/init_common_service.c** before executing the **SetSystemseccompPolicy** function to set the Seccomp policy. If the line starts with a plus sign (+), the line is added; if the line starts with a hyphen (-), the line is deleted. **xxxx** must be the same as the value of **Services name** in the [boot configuration file](subsys-boot-init-cfg.md) of the process.
+ ```c
+ --- a/services/init/init_common_service.c
+ +++ b/services/init/init_common_service.c
+ @@ -155,7 +155,19 @@ static int SetPerms(const Service *service)
+ // set seccomp policy before setuid
+ INIT_ERROR_CHECK(SetSystemseccompPolicy(service) == SERVICE_SUCCESS, return SERVICE_FAILURE,
+ "set seccomp policy failed for service %s", service->name);
+ -
+ + if (strncmp(service->name, "xxxx", strlen("xxxx")) == 0) {
+ + pid_t pid = getpid();
+ + pid_t pid_child = fork();
+ + if (pid_child == 0) {
+ + char pidStr[9] = {0};
+ + sprintf_s(pidStr, 6, "%d", pid);
+ + if (execl("/system/bin/strace", "/system/bin/strace", "-p", (const char *)pidStr, "-ff", "-o", "/data/strace/xxxx.strace.log", NULL) !=0 ) {
+ + INIT_LOGE("strace failed");
+ + }
+ + }
+ + sleep(5);
+ + }
+ 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);
+ ```
+2. Perform a full build, and burn the image.
+3. Disable SElinux, and push Strace to the device.
+ ```shell
+ hdc shell setenforce 0
+ hdc shell mount -rw -o remount /
+ hdc file send /path/to/strace /system/bin/
+ hdc shell chmod a+x /system/bin/strace
+ ```
+4. Create a folder for storing Strace logs.
+ ```shell
+ hdc shell mkdir -p /data/strace
+ ```
+5. Terminate the service process, and restart it. In the following command, **xxx** indicates the service process name.
+ ```shell
+ kill -9 $(pidof xxx)
+ ```
+6. Perform service operations on the device. Make sure that all code is covered.
+7. Obtain Strace logs from **/data/strace** on the device, and save them to the directory where the parsing script is located.
+ ```shell
+ hdc file recv /data/strace /path/to/base/startup/init/services/modules/seccomp/scripts/tools/
+ ```
+
+##### Parsing Strace Logs
+
+1. Copy the dependency files to the Strace log folder for later use. The dependency files are those generated in step 2 in [Static Analysis](#static-analysis).
+ ```shell
+ cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/strace/
+ ```
+
+2. Use the **strace_log_analysis.py** script file to parse and generate the corresponding policy file **xxx.seccomp.policy**.
+
+ The script file is available at **//base/startup/init/services/modules/seccomp/scripts/tools/**.
+
+ **Table 8** Parameters in the strace_log_analysis.py script file
+ | Parameter | Description |
+ | --- | --- |
+ | --src-path | Folder for storing log files. It must contain **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**. The folder name must not end with a slash (/), for example, **./strace**.|
+ | --target-cpu | CPU architecture, which is the same as that of the traced process. Its value can be **arm** or **arm64**. |
+ | --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
+
+ Use the **strace_log_analysis.py** script file to parse Strace logs.
+ ```shell
+ cd base/startup/init/services/modules/seccomp/scripts/tools;
+ python3 strace_log_analysis.py --src-path strace --target-cpu *specified CPU* --filter-name xxx
+ ```
+ Example result of xxx.seccomp.policy
+ ```
+ @allowList
+ getcwd;arm64
+ eventfd2;arm64
+ epoll_create1;arm64
+ epoll_ctl;arm64
+ dup;arm64
+ dup3;arm64
+ fcntl;arm64
+ ioctl;arm64
+ ...
+ ```
+
+#### Audit Statistics
+
+1. Enable the initial Seccomp policy. For details, see [Customizing Seccomp Policies for a Process](#customizing-seccomp-policies-for-a-process).
+2. Obtain logs.
+ 1. Create a folder for storing logs.
+ ```shell
+ mkdir -p /data/audit
+ ```
+ 2. Obtain Seccomp-related audit log information from kernel logs. The logs end with **.audit.log**.
+ ```shell
+ cat /proc/kmsg | grep type=1326 > /data/audit/media_service.audit.log
+ ```
+3. Perform service-related operations and segment fault triggering operations.
+ 1. To trigger a segment fault, add the following code to the service code to call **TriggerSegmentFault** at a certain point to rebuild and burn the image:
+ ```c
+ static void TriggerSegmentFault(void)
+ {
+ pid_t pid_child = fork();
+ if (pid_child == 0) {
+ char *test = (char *)0x1234;
+ *test = 1;
+ }
+ }
+ ```
+ 2. After the device is started, run the following shell command to temporarily shut down SELinux and terminate the service process. The process then automatically restarts.
+ ```shell
+ setenforce 0
+ ```
+
+4. Run the hdc command to obtain audit logs from the **/data/audit** on of the device, and save them to the directory where the parsing script is located.
+ ```shell
+ hdc file recv /data/audit /path/to/base/startup/init/services/modules/seccomp/scripts/tools/
+ ```
+5. Parse the audit logs.
+
+ Example audit log:
+ ```shell
+ <5>[ 198.963101] audit: type=1326 audit(1659528178.748:27): auid=4294967295 uid=0 gid=1000 ses=4294967295 subj=u:r:appspawn:s0 pid=2704 comm="config_dialog_s" exe="/system/bin/appspawn" sig=31 arch=40000028 syscall=
+ 208 compat=1 ip=0xf7b79400 code=0x80000000
+ ```
+ **Table 9** Key parameters in audit logs
+ | Parameter | Description |
+ | --- | --- |
+ | type | Type. The value **1326** indicates that the log is of the Seccomp type. |
+ | sig | Semaphore. The value **31** indicates **SIGSYS**, which is the signal sent to the process when Seccomp interception occurs. |
+ | arch | Architecture ID. The value **40000028** indicates **arm**, and the value **c00000b7** indicates **arm64**. |
+ | syscall | System call ID. |
+ | compat | The value **1** indicates the compatibility mode, that is, the arm64 kernel uses arm system calls. |
+
+
+ 1. Copy the dependency files to the log folder for later use. The dependency files are those generated in step 2 in [Static Analysis](#static-analysis).
+ ```shell
+ cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/audit/
+ ```
+ 2. Run the **audit_log_analysis.py** script to parse logs and generate **xxx.seccomp.policy**. The tool is available at **//base/startup/init/services/modules/seccomp/scripts/tools/**.
+
+ **Table 10** Parameters in the audit_log_analysis.py script file
+ | Parameter | Description |
+ | --- | --- |
+ | --src-path | Folder for storing log files. It must contain **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**. The folder name must not end with a slash (/), for example, **./audit**.|
+ | --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
+
+ ```shell
+ cd base/startup/init/services/modules/seccomp/scripts/tools
+ python3 audit_log_analysis.py --src-path audit --filter-name xxx
+ ```
+
+### Combining Multiple Policy Files
+
+During [colltatistics on system calls](#system-call-statistic-methods), multiple policy files may be generated. In these policy files, system calls may be repeated or disordered. To solve these problems, you can combine policy files to sort system calls by arm64/arm and by system call number in ascending order.
+
+**Table 11** Parameters in the merge_policy.py script file
+| Parameter | Description |
+| --- | --- |
+| --src-files | Files to be processed, including **libsyscall_to_nr_arm** and **libsyscall_to_nr_arm64**.|
+| --filter-name | Name of the generated policy file. For example, if the input value is **test**, the generated file name is **test.seccomp.policy**. |
+
+1. Copy the dependency files to the log folder for later use.
+ ```shell
+ cp out/*product name* /gen/base/startup/init/services/modules/seccomp/gen_system_filter/libsyscall_to_nr_arm* base/startup/init/services/modules/seccomp/scripts/tools/
+ ```
+2. Run the **merge_policy.py** script to merge **policy1.seccomp.policy** and **policy2.seccomp.policy** into **xxxx.seccomp.policy**.
+ ```shell
+ python3 merge_policy.py --src-files libsyscall_to_nr_arm --src-files libsyscall_to_nr_arm64 --src-files policy1.seccomp.policy --src-files policy2.seccomp.policy --filter-name xxxx
+ ```
diff --git a/en/device-dev/website.md b/en/device-dev/website.md
index 5cebc561328f432802f2b0ae5a8d6f11f23483d4..ee38efcce1431ad64736dfcd8f6812efd2d547fd 100644
--- a/en/device-dev/website.md
+++ b/en/device-dev/website.md
@@ -427,6 +427,7 @@
- [Plug-in Management](subsystems/subsys-boot-init-plugin.md)
- [omponent-based Startup](subsystems/subsys-boot-init-sub-unit.md)
- [init Run Log Standardization](subsystems/subsys-boot-init-log.md)
+ - [Seccomp Policy Development](subsystems/subsys-boot-init-seccomp.md)
- [appspawn Module](subsystems/subsys-boot-appspawn.md)
- [bootstrap Module](subsystems/subsys-boot-bootstrap.md)
- [FAQs](subsystems/subsys-boot-faqs.md)