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