Linux capabilities
- 对于权限细节参考
man 7 capabilities
; - 对于
-+= eip
操作符参考man 3 cap_from_text
; - 文档中命令
setcap
、getcap
等都可以通过man命令查看;
我需要在VS Code 调试NuttX应用,它的Sim应用需要cap_net_raw,cap_net_admin
权限,否则就无法正常操作HCI设备。
当然网上有一些帖子尝试将VS Code或者GDB运行在root用户,显然这样操作是非常不优雅的。
所以这里尝试给需要调试的应用利用linux capabilities直接给可执行文件设置权限。
$ sudo setcap 'cap_net_raw,cap_net_admin=ep' nuttx
$ getcap nuttx
nuttx = cap_net_admin,cap_net_raw+ep
此时运行程序,可以通过capsh
或者getcaps
检查进程确认已经设置成功。
$ getpcaps $(pidof nuttx)
283131: = cap_net_admin,cap_net_raw+ep
$ cat /proc/283131/status|grep Cap
CapInh: 0000000000000000
CapPrm: 0000000000003000
CapEff: 0000000000003000
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000
$ capsh --decode=000001ffffffffff
WARNING: libcap needs an update (cap=40 should have a name).
0x000001ffffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,38,39,40
此时通过VS Code启动调试后发现其却没有了需要的文件权限。
$ getpcaps $(pidof nuttx)
284336: =
| | \_ /usr/share/code/code --ms-enable-electron-run-as-node /usr/share/code/resources/app/out/bootstrap-fork --type=ptyHost
| | | \_ /usr/bin/bash
| | | \_ /usr/bin/bash
| | | | \_ /bin/sh /tmp/Microsoft-MIEngine-Cmd-nptpb2ki.pex
| | | | \_ /usr/bin/gdb --interpreter=mi --tty=/dev/pts/4
| | | | \_ /home/lijie/my_project/nuttxspace/nuttx/nuttx
看起来是父进程/usr/bin/gdb
启动nuttx
进程的时候并没有使用其文件文件属性。
直接测试了gdb ./nuttx
确认和上面现象一致,strace确认其通过ptrace创建进程。
ptrace(PTRACE_SETOPTIONS, 285286, NULL, PTRACE_O_TRACESYSGOOD|PTRACE_O_TRACECLONE|PTRACE_O_EXITKILL) = 0
怀疑这里是gdb进程没有cap_sys_ptrace
权限,添加后再次通过VS Code启用nuttx调试发现其进程已经具有我们需要的权限。
$ sudo setcap 'cap_sys_ptrace+eip' /usr/bin/gdb
$ getcap /usr/bin/gdbserver
/usr/bin/gdbserver = cap_sys_ptrace+eip
$ getcap nuttx
nuttx = cap_net_admin,cap_net_raw+ep
还不快抢沙发