1# NDK涉及的musl libc接口使用限制的说明
2
3## 概述
4
5开发者使用DevEco Studio或者NDK进行应用开发时,可能涉及到使用musl libc的接口能力,因为musl libc的个别接口可能受多种系统和环境的限制而无法使用,此时可以通过本文档进行接口问题排查。
6
7<!--RP1--><!--RP1End-->
8
9## Seccomp机制影响的musl接口 <!--Del-->
10   Seccomp机制可参考[Seccomp策略使能开发指导](../../../device-dev/subsystems/subsys-boot-init-seccomp.md)。<!--DelEnd-->
11
12### 确定进程因为Seccomp机制终止的方法
13
14- 查看进程faultlog日志,如果报错原因是`signal:SIGSYS`,且栈顶在`ld-musl-{架构}.so.1`库里,则进程终止可能是由Seccomp机制引起的。
15    ```
16    cat /data/log/faultlog/faultlogger/cppcrash-xxxx
17    ```
18    错误示例:
19    ```
20    Process name:com.example.myapplication
21    Reason:Signal:SIGSYS(UNKNOWN)
22    Fault thread Info:
23    Tid:13893, Name:e.myapplication
24    #00 pc 000a5d30 /system/lib/ld-musl-arm.so.1(sethostname+16)(584c9d0a0e9000497bb0d66799a9526a)
25    #01 pc 00002f68 /data/storage/el1/bundle/libs/arm/libentry.so(test()+64)
26    ```
27<!--Del-->
28- 关闭Seccomp机制,如果进程能正常运行,则进程终止是由Seccomp机制引起的。
29
30    当设备系统版本是ENG版本,且处于root模式下,执行shell命令设置系统参数,关闭整个系统的Seccomp机制。
31    ```shell
32    # 设置相关系统参数关闭Seccomp机制后重启
33    param set persist.init.debug.seccomp.enable 0
34    reboot
35    # 设置相关系统参数开启Seccomp机制后重启
36    param set persist.init.debug.seccomp.enable 1
37    reboot
38    ```
39<!--DelEnd-->
40
41### 常见可能受Seccomp机制影响的接口列表如下
42
43| 头文件        | musl接口名称      |
44| ------------ | ----------------- |
45| fcntl.h      | name_to_handle_at |
46| fcntl.h      | open_by_handle_at |
47| grp.h        | initgroups        |
48| grp.h        | setgroups         |
49| sched.h      | setns             |
50| sched.h      | unshare           |
51| sys/fanotify.h | fanotify_init   |
52| sys/fanotify.h | fanotify_mark   |
53| sys/fsuid.h  | setfsgid          |
54| sys/fsuid.h  | setfsuid          |
55| sys/klog.h   | klogctl           |
56| sys/mount.h  | mount             |
57| sys/mount.h  | umount2           |
58| sys/mount.h  | umount            |
59| sys/msg.h    | msgctl            |
60| sys/msg.h    | msgget            |
61| sys/msg.h    | msgrcv            |
62| sys/msg.h    | msgsnd            |
63| sys/reboot.h | reboot            |
64| sys/sem.h    | semctl            |
65| sys/sem.h    | semget            |
66| sys/sem.h    | semop             |
67| sys/sem.h    | semtimedop        |
68| sys/shm.h    | shmat             |
69| sys/shm.h    | shmctl            |
70| sys/shm.h    | shmdt             |
71| sys/shm.h    | shmget            |
72| sys/stat.h   | mkfifo            |
73| sys/stat.h   | mkfifoat          |
74| sys/stat.h   | mknod             |
75| sys/stat.h   | mknodat           |
76| sys/swap.h   | swapoff           |
77| sys/swap.h   | swapon            |
78| time.h       | clock_settime     |
79| sys/time.h   | settimeofday      |
80| sys/timex.h  | adjtimex          |
81| sys/timex.h  | clock_adjtime     |
82| unistd.h     | acct              |
83| unistd.h     | chroot            |
84| unistd.h     | pause             |
85| unistd.h     | setdomainname     |
86| unistd.h     | setegid           |
87| unistd.h     | setgid            |
88| unistd.h     | sethostname       |
89| unistd.h     | setregid          |
90| unistd.h     | setresgid         |
91| unistd.h     | setreuid          |
92| unistd.h     | setuid            |
93| None         | pivot_root        |
94| None         | init_module       |
95| None         | delete_module     |
96
97
98## 内核没有对外开放影响的musl接口
99
100| 头文件          | musl接口名称   |
101| -------------- | -------------- |
102| sys/fanotify.h | fanotify_init  |
103| sys/fanotify.h | fanotify_mark  |
104| unistd.h       | acct           |
105
106## SELinux机制影响的musl接口 <!--Del-->
107   SELinux的说明可参考[OpenHarmony SELinux概述](../../../device-dev/subsystems/subsys-security-selinux-overview.md)。<!--DelEnd-->
108
109### 确定接口因为SELinux机制报错的方法
110- 引入errno.h头文件,检查errno错误状态码,如果错误状态码是EACCES,则接口报错可能是由SELinux机制引起的。
111<!--Del-->
112- 检查内核avc日志,排查type=1400的SELinux拦截日志,判断接口报错是否由SELinux机制引起的。
113
114    ```shell
115    # 搜索type=1400的内核Selinux日志(注意:因为执行效率的原因,内核会舍弃部分日志)
116    dmesg -w | grep "pid=2854" | grep "type=1400"
117    # 受SELinux机制影响的日志示例
118    audit: type=1400 audit(1502785908.269:47562): avc:  denied  { ioctl } for  pid=2854 comm="sh" path="/dev/tty" dev="tmpfs" ino=40 ioctlcmd=0x5403 scontext=u:r:su:s0 tcontext=u:object_r:tty_device:s0 tclass=chr_file permissive=0
119    # 日志解读
120    ioctl                               # 访问客体的操作权限
121    pid=2854                            # 主体进程号
122    comm="sh"                           # 主体进程名
123    path="/dev/tty"                     # 被访问的客体
124    dev="tmpfs"                         # 被访问客体的文件系统
125    ino=40                              # 文件节点编号
126    ioctlcmd=0x5403                     # ioctl操作命令
127    scontext=u:r:su:s0                  # 主体SELinux标签
128    tcontext=u:object_r:tty_device:s0   # 客体SELinux标签
129    tclass=chr_file                     # 权限类别,字符设备文件
130    permissive=0                        # 0是严格模式,拦截访问;1是宽容模式,只记录日志
131    # 日志结论
132    主体进程(2854)访问客体(/dev/tty),调用客体的ioctl操作,因为进程缺少ioctlcmd=0x5403命令的执行权限,且由于当前SELinux机制处于严格模式下,所以内核拦截了进程操作,并且将errno设置成EACCES错误。
133    ```
134
135- 关闭SELinux机制,如果接口调用成功,则接口报错是由SELinux机制引起的。
136
137    当设备处于root模式下,执行shell命令设置系统参数,临时关闭整个系统的SELinux机制。
138    ```shell
139    # 设置相关系统参数关闭SELinux机制
140    setenforce 0
141    # 设置相关系统参数开启SELinux机制
142    setenforce 1
143    ```
144<!--DelEnd-->
145
146### 常见可能受SELinux机制影响的接口列表如下
147
148| 头文件         |  musl接口名称   |
149| -------------- | -------------- |
150| net/if.h       | if_indextoname |
151| net/if.h       | if_nametoindex |
152| pty.h          | forkpty        |
153| pty.h          | openpty        |
154| semaphore.h    | sem_open       |
155| semaphore.h    | sem_unlink     |
156| stdlib.h       | ptsname        |
157| stdlib.h       | ptsname_r      |
158| stdlib.h       | posix_openpt   |
159| stdlib.h       | unlockpt       |
160| stdio.h        | popen          |
161| stdio.h        | pclose         |
162| sys/ioctl.h    | ioctl          |
163| sys/mman.h     | shm_open       |
164| sys/mman.h     | shm_unlink     |
165| sys/mount.h    | mount          |
166| sys/mount.h    | umount         |
167| sys/mount.h    | umount2        |
168| sys/msg.h      | msgctl         |
169| sys/msg.h      | msgget         |
170| sys/msg.h      | msgrcv         |
171| sys/msg.h      | msgsnd         |
172| sys/sem.h      | semget         |
173| sys/sem.h      | semctl         |
174| sys/sem.h      | semop          |
175| sys/sem.h      | semtimedop     |
176| sys/shm.h      | shmget         |
177| sys/shm.h      | shmat          |
178| sys/shm.h      | shmdt          |
179| sys/shm.h      | shmctl         |
180| sys/stat.h     | mkfifo         |
181| sys/stat.h     | mkfifoat       |
182| sys/stat.h     | mknod          |
183| sys/stat.h     | mknodat        |
184| termios.h      | tcgetattr      |
185| termios.h      | tcsetattr      |
186| termios.h      | tcsendbreak    |
187| termios.h      | tcdrain        |
188| termios.h      | tcflush        |
189| termios.h      | tcflow         |
190| termios.h      | tcgetsid       |
191| unistd.h       | link           |
192| unistd.h       | linkat         |
193| unistd.h       | readlink       |
194| unistd.h       | readlinkat     |
195| unistd.h       | symlink        |
196| unistd.h       | symlinkat      |
197| unistd.h       | tcgetpgrp      |
198| unistd.h       | tcsetpgrp      |
199| utmp.h         | login_tty      |
200
201
202## 沙箱机制影响的musl接口
203
204沙箱机制可参考 [应用沙箱目录](../../file-management/app-sandbox-directory.md)。
205
206引入errno.h头文件,检查errno错误状态码,如果错误状态码是ENOENT,则接口报错可能是由沙箱机制引起的。
207
208常见可能受沙箱机制影响的接口列表如下:
209
210|  头文件        | musl接口名称 |
211| -------------- | ----------- |
212| fcntl.h        | open        |
213| fcntl.h        | openat      |
214| nl_types.h     | catopen     |
215| stdio.h        | fopen       |
216| stdio.h        | freopen     |
217| stdio.h        | rename      |
218| stdio.h        | renameat    |
219| stdio.h        | renameat2   |
220| stdio.h        | tmpfile     |
221| stdio.h        | tmpfile64   |
222
223
224## 空实现或默认失败的musl接口
225
226| 头文件         |  musl接口名称  |
227| -------------- | ------------- |
228| netdb.h        | getnetbyaddr  |
229| netdb.h        | getnetbyname  |
230| stdio_ext.h    | __fsetlocking |
231| unistd.h       | brk           |
232| utmp.h         | getutent      |
233| utmp.h         | pututline     |
234| utmp.h         | setutent      |
235| utmp.h         | pututline     |
236| utmp.h         | utmpname      |
237
238
239## 需要特殊权限才能执行的musl接口
240
241引入errno.h头文件,检查errno错误状态码,如果错误状态码是EPERM,则接口报错可能是由系统Capabilities安全机制引起的,也有可能是其他内核安全管控引起的。
242
243常见可能受Capabilities机制影响的接口如下:
244
245| 头文件         |  musl接口名称      | Capabilities权限     |
246| -------------- | ----------------- | -------------------- |
247| None           | pivot_root        | CAP_SYS_ADMIN        |
248| None           | init_module       | CAP_SYS_MODULE       |
249| None           | delete_module     | CAP_SYS_MODULE       |
250| fcntl.h        | open_by_handle_at | CAP_DAC_READ_SEARCH  |
251| sys/klog.h     | klogctl           | CAP_SYS_ADMIN        |
252| sys/mount.h    | mount             | CAP_SYS_ADMIN        |
253| sys/mount.h    | umount            | CAP_SYS_ADMIN        |
254| sys/mount.h    | umount2           | CAP_SYS_ADMIN        |
255| sys/reboot.h   | reboot            | CAP_SYS_BOOT         |
256| sys/swap.h     | swapon            | CAP_SYS_ADMIN        |
257| sys/swap.h     | swapoff           | CAP_SYS_ADMIN        |
258| sys/time.h     | settimeofday      | CAP_SYS_TIME         |
259| unistd.h       | setdomainname     | CAP_SYS_ADMIN        |
260| unistd.h       | sethostname       | CAP_SYS_ADMIN        |
261| unistd.h       | chroot            | CAP_SYS_CHROOT       |
262