I am in a difficult situation where I don't know what Linux capabilities a process requires to work.
What is the best way, or any way, to find out what capability is required?
The only thing I can think of right now is using capsh and drop all capabilities on a process. The process then fails and I start to add capabilities (by removing --drop=CAP_XZY) until it works.
Any better suggestions?
55 Answers
Based on recent libcap2 update
1: (Short option): getpcaps
Description:
From here:
getpcaps displays the capabilities on the processes indicated by the pid value(s) given on the command line.
Example:
$ getpcaps <PID> PID: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+i 2: (A bit longer option): /proc status and capsh
Description:
proc is a process information pseudo-filesystem or in other words - a directory where you can view information on all processes.
About capsh:
Linux capability support and use can be explored and constrained with this tool. This tool provides a handy wrapper for certain types of capability testing and environment creation.
It also provides some debugging features useful for summarizing capability state.
Example:
$ cat /proc/<PID>/status | grep Cap And you'll get (on most systems):
CapInh: 00000000a80425fb (Inherited capabilities) CapPrm: 0000000000000000 (Permitted capabilities) CapEff: 0000000000000000 (Effective capabilities) CapBnd: 00000000a80425fb (Bounding set) CapAmb: 000000000000000 (Ambient capabilities set) Use the capsh utility to decode from hexadecimal numbers into the capabilities name:
capsh --decode=00000000a80425fb 0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap (*) You can download capsh with: sudo apt-get install git libpcap-dev.
Turns out it is easier than expected. Install libcap-ng () and use pscap.
In Ubuntu 16.04, it can be installed with:
sudo apt-get install libcap-ng-utils Sample output excerpt:
Run command: netcap
ppid pid name command capabilities 1 468 root systemd-journal chown, dac_override, dac_read_search, fowner, setgid, setuid, sys_ptrace, sys_admin, audit_control, mac_override, syslog, audit_read 1 480 root lvmetad full 1 492 root systemd-udevd full 1 1040 root rpc.idmapd full 1 1062 root rpc.gssd full 1 1184 messagebus dbus-daemon audit_write + 1 1209 root NetworkManager dac_override, kill, setgid, setuid, net_bind_service, net_admin, net_raw, sys_module, sys_chroot, audit_write 2Another method, that I've come across a while ago in this blog post by Brendan Gregg is to use capabilities tracer - capable.
Below is a sample output:
$ sudo /usr/share/bcc/tools/capable TIME UID PID COMM CAP NAME AUDIT 11:31:54 0 2467 capable 21 CAP_SYS_ADMIN 1 11:31:54 0 2467 capable 21 CAP_SYS_ADMIN 1 11:31:59 1000 2468 ls 1 CAP_DAC_OVERRIDE 1 11:31:59 1000 2468 ls 2 CAP_DAC_READ_SEARCH 1 11:32:02 0 1421 timesync 25 CAP_SYS_TIME 1 11:32:05 1000 2469 sudo 7 CAP_SETUID 1 11:32:05 0 2469 sudo 6 CAP_SETGID 1 It has a significant advantage of recording capability checks made by kernel for a given process. This allows to profile the application against the capabilities that it actually requires, e.g. to narrow down the privileges and execute it as an unprivileged user.
While pscap allows to list the effective capabilities of all running processes, it does not offer a reliable method of checking which capabilities are in fact required by the process, because:
- A process may have capability X in its permitted set and only raise it to the effective set for a short time to perform a privileged operation.
- A process could have started with broader set of capabilities, do the initialization requiring elevated privileges, and drop some (or all) capabilities (e.g. ping opening a raw socket).
- It works only for processes that are already running in capabilities-based manner. What if you had to determine the minimal capability set required for your newly developed application?
- It does not allow to correlate privilege checks made for application with the operations it performs, with capable you get timestamps for ever single check.
The sources for capable are available on github. Installation instructions for BCC (including capable) are available here. For further description please refer to the blog post mentioned at the beginning, please also note that capable requires kernel 4.4+, an alternative for older kernels is available in the blog post as well.
Note: I'm not the author, nor am I affiliated with the tool developers in any way. I just wanted to bring it to wider audience, since I have personally used it to develop a capabilities profile for a complex monitoring application that previously required full root privileges to run, and found this tracer to be of tremendous help.
0I did this: drop all capabilities, and re-enable them one by one (just by commenting out a line) and retrying the script.
It's a bit hit-and-miss to guess the CAP which causes the failure.
#!/bin/bash D="cap_audit_control" D="${D},cap_audit_read" D="${D},cap_audit_write" D="${D},cap_block_suspend" D="${D},cap_chown" D="${D},cap_dac_override" D="${D},cap_dac_read_search" D="${D},cap_fowner" D="${D},cap_fsetid" D="${D},cap_ipc_lock" D="${D},cap_ipc_owner" D="${D},cap_kill" D="${D},cap_lease" D="${D},cap_linux_immutable" D="${D},cap_mac_admin" D="${D},cap_mac_override" D="${D},cap_mknod" D="${D},cap_net_admin" D="${D},cap_net_bind_service" D="${D},cap_net_broadcast" D="${D},cap_net_raw" D="${D},cap_setfcap" D="${D},cap_setgid" D="${D},cap_setpcap" D="${D},cap_setuid" D="${D},cap_sys_admin" D="${D},cap_sys_boot" D="${D},cap_sys_chroot" D="${D},cap_syslog" D="${D},cap_sys_module" D="${D},cap_sys_nice" D="${D},cap_sys_pacct" D="${D},cap_sys_ptrace" D="${D},cap_sys_rawio" D="${D},cap_sys_resource" D="${D},cap_sys_time" D="${D},cap_sys_tty_config" D="${D},cap_wake_alarm" # capsh in debian package: libcap2-bin /usr/sbin/capsh --drop=${D} -- -c 'ping -c 1 8.8.8.8' Further: to list syscalls associated with capabilities, I searched the provided manpages for mentions (this is obviously not an exhaustive list).
With a file 'caps' listing the 38 CAPS_* identiers:
$ head caps CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE CAP_BLOCK_SUSPEND CAP_CHOWN ... I can search like this (the '2' section of the manpages list syscalls):
$ find /usr/share/man/man2 -type f -name \*\.gz | while read M ; do zgrep -wf caps $M | tr -c 'A-Z_' '\n' | grep -wf caps | sort -u | sed "s|$| = $M|;s|/usr/share/man/man2/||;s|.2.gz||" ; done | sort -u CAP_BLOCK_SUSPEND = epoll_ctl CAP_CHOWN = chown CAP_DAC_OVERRIDE = mount CAP_DAC_OVERRIDE = utime CAP_DAC_OVERRIDE = utimensat CAP_DAC_READ_SEARCH = link CAP_DAC_READ_SEARCH = open CAP_DAC_READ_SEARCH = open_by_handle_at CAP_FOWNER = chmod CAP_FOWNER = ioctl_iflags CAP_FOWNER = open CAP_FOWNER = rename CAP_FOWNER = rmdir CAP_FOWNER = unlink CAP_FOWNER = utime CAP_FOWNER = utimensat CAP_FSETID = chmod CAP_IPC_LOCK = mlock CAP_IPC_LOCK = shmctl CAP_IPC_LOCK = shmget CAP_IPC_OWNER = msgctl CAP_IPC_OWNER = msgget CAP_IPC_OWNER = msgop CAP_IPC_OWNER = semctl CAP_IPC_OWNER = semget CAP_IPC_OWNER = semop CAP_IPC_OWNER = shmctl CAP_IPC_OWNER = shmget CAP_IPC_OWNER = shmop CAP_KILL = kill CAP_LEASE = fcntl CAP_LINUX_IMMUTABLE = ioctl_iflags CAP_MKNOD = mknod CAP_MKNOD = rename CAP_SETGID = clone CAP_SETGID = getgroups CAP_SETGID = seteuid CAP_SETGID = setfsgid CAP_SETGID = setgid CAP_SETGID = setresuid CAP_SETGID = setreuid CAP_SETPCAP = capget CAP_SETPCAP = prctl CAP_SETUID = clone CAP_SETUID = keyctl CAP_SETUID = seteuid CAP_SETUID = setfsuid CAP_SETUID = setresuid CAP_SETUID = setreuid CAP_SETUID = setuid CAP_SYS_ADMIN = bdflush CAP_SYS_ADMIN = bpf CAP_SYS_ADMIN = clone CAP_SYS_ADMIN = fanotify_init CAP_SYS_ADMIN = getdomainname CAP_SYS_ADMIN = gethostname CAP_SYS_ADMIN = getrlimit CAP_SYS_ADMIN = ioctl_getfsmap CAP_SYS_ADMIN = ioctl_tty CAP_SYS_ADMIN = ioprio_set CAP_SYS_ADMIN = io_submit CAP_SYS_ADMIN = keyctl CAP_SYS_ADMIN = lookup_dcookie CAP_SYS_ADMIN = madvise CAP_SYS_ADMIN = mount CAP_SYS_ADMIN = msgctl CAP_SYS_ADMIN = open_by_handle_at CAP_SYS_ADMIN = pciconfig_read CAP_SYS_ADMIN = perf_event_open CAP_SYS_ADMIN = pivot_root CAP_SYS_ADMIN = prctl CAP_SYS_ADMIN = ptrace CAP_SYS_ADMIN = quotactl CAP_SYS_ADMIN = seccomp CAP_SYS_ADMIN = semctl CAP_SYS_ADMIN = setns CAP_SYS_ADMIN = shmctl CAP_SYS_ADMIN = swapon CAP_SYS_ADMIN = syslog CAP_SYS_ADMIN = umount CAP_SYS_ADMIN = unshare CAP_SYS_BOOT = kexec_load CAP_SYS_BOOT = reboot CAP_SYS_CHROOT = chroot CAP_SYS_CHROOT = setns CAP_SYSLOG = syslog CAP_SYS_MODULE = create_module CAP_SYS_MODULE = delete_module CAP_SYS_MODULE = init_module CAP_SYS_NICE = getpriority CAP_SYS_NICE = ioprio_set CAP_SYS_NICE = mbind CAP_SYS_NICE = migrate_pages CAP_SYS_NICE = move_pages CAP_SYS_NICE = nice CAP_SYS_NICE = sched_setaffinity CAP_SYS_NICE = sched_setparam CAP_SYS_NICE = spu_create CAP_SYS_PACCT = acct CAP_SYS_PTRACE = get_robust_list CAP_SYS_PTRACE = kcmp CAP_SYS_PTRACE = ptrace CAP_SYS_PTRACE = userfaultfd CAP_SYS_RAWIO = ioperm CAP_SYS_RAWIO = iopl CAP_SYS_RESOURCE = fcntl CAP_SYS_RESOURCE = getrlimit CAP_SYS_RESOURCE = ioctl_iflags CAP_SYS_RESOURCE = msgctl CAP_SYS_RESOURCE = msgop CAP_SYS_RESOURCE = prctl CAP_SYS_TIME = adjtimex CAP_SYS_TIME = gettimeofday CAP_SYS_TIME = stime CAP_SYS_TTY_CONFIG = ioctl_console CAP_SYS_TTY_CONFIG = vhangup CAP_WAKE_ALARM = timer_create CAP_WAKE_ALARM = timerfd_create So the missing CAP_'s are:
$ cat syscap | cut -d' ' -f 1 | sort -u | grep -vwf - caps CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETFCAP And only make mention of 88 of 347 syscalls on my system
$ cat syscap | cut -d' ' -f 3 | sort -u | wc -l 88