How to find out what Linux capabilities a process requires to work?
Asked Answered
B

5

42

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?

Brindabrindell answered 17/2, 2016 at 22:27 Comment(5)
I'd expect the installer to configure the required capabilities.Madi
Maybe if you explained exactly what the process does...?Shook
@Shook ok let's make a concrete exmaple: # capsh --drop=cap_net_raw -- -c "ping localhost" ping: icmp open socket: Operation not permitted In this case, i drop the cap required for ping and then execute a ping. Of course, it doesn't work. Given this scenario, how do I find out that ping needs cap_net_raw? There are situation where a process does something that requires a specific cap. How can I found out which one?Brindabrindell
Did you write the program? If so, you should know what capabilities it needs. If not, then it's a sysadmin question rather than a programming one.Continence
Yes, if only there was something like selinux' permissive mode.Hannis
P
40

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.

Polymer answered 21/9, 2020 at 21:18 Comment(6)
Thanks @RtmY. Greate update on recent libcap2 development. Btw that's the source of getpcaps: git.kernel.org/pub/scm/libs/libcap/libcap.gitBrindabrindell
See also capsh --printMatte
You might also like to checkout captree which might help you understand the relationship between processes and threads that are trying to use capabilities in your system.Floreneflorentia
For a one-liner, I'm doing something like this to inspect effective capabilities of a PID: gawk '/^CapEff/ {print $2}' /proc/<PID>/status | xargs -n1 -I {} capsh --decode={}Cannot
This answer doesn't solve the original question. Using this method you will get the current capabilities for a particular process, but if you run the process dropping all capabilities, using something like this capsh --drop=all --print -- -c "/usr/bin/ping -c 4 8.8.8.8" you won't find the specific capability that we are looking for, which is cap_net_rawPastrami
I think that the answer provides 2 different ways for "How to find out what linux capabilities a process requires to work?" Plus it was verified by the origin questioner.Polymer
R
21

Another 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.

Rajkot answered 27/12, 2017 at 11:46 Comment(0)
B
19

Turns out it is easier than expected. Install libcap-ng (https://people.redhat.com/sgrubb/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
Brindabrindell answered 18/2, 2016 at 15:7 Comment(2)
This is not working for python processes, is there a way to list which capabilities a python process requires?Yand
@Yand yes it works for all process/binaries, pscap -a will list allSedgewinn
L
1

I 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'
Leena answered 3/3, 2023 at 14:47 Comment(0)
L
0

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
Leena answered 3/3, 2023 at 18:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.