← Весь справочник

capabilities: getcap и setcap

Выдать программе отдельную привилегию root без setuid — setcap cap_net_bind_service=ep, getcap -r, setcap -r

Права root в Linux разбиты на отдельные capabilities: открыть порт ниже 1024 (cap_net_bind_service), читать любые файлы (cap_dac_override), отправлять сырые пакеты (cap_net_raw) и так далее. Их можно записать прямо в исполняемый файл — тогда программа, запущенная обычным пользователем, получит только эту привилегию, а не все права root, как при setuid. setcap записывает, getcap показывает (пакет libcap2-bin). Хранятся они в расширенном атрибуте security.capability.

Синтаксис

setcap 'cap_имя[,cap_имя…]=флаги' файл    # записать
setcap -r файл                            # удалить
getcap файл…                              # показать
getcap -r каталог                         # найти все файлы с capabilities

Флаги

ФлагНаборСмысл
ppermittedпроцессу разрешено пользоваться привилегией
eeffectiveпривилегия включена сразу при запуске; без e программа должна включить её сама
iinheritableможет передаваться дальше через exec (нужно редко)

Почти всегда пишут =ep: «разрешить и сразу включить». Операторы: = — задать ровно эти флаги, + — добавить, - — убрать. cap_net_raw+ep и cap_net_raw=ep на пустом файле дают одно и то же.

Опции

КомандаЧто делает
setcap -r файлудалить все capabilities файла
setcap -v 'caps' файлпроверить, совпадают ли capabilities; файл: OK и код 0, иначе код 1
setcap -q …не печатать сообщения
setcap - файлпрочитать capabilities из stdin (до пустой строки)
getcap -r каталогрекурсивный поиск; файлы без capabilities не печатаются
getcap -v файлпечатать и файлы без capabilities
getcap -n файлпоказать rootid, если capability записана для user namespace

Частые capabilities

CapabilityЧто разрешает
cap_net_bind_serviceслушать порты ниже 1024 (веб-сервер на 80/443 без root)
cap_net_rawсырые сокеты: ping, tcpdump, arping
cap_net_adminнастраивать сеть: интерфейсы, маршруты, iptables
cap_dac_overrideигнорировать права rwx на файлы и каталоги
cap_dac_read_searchчитать любые файлы и обходить любые каталоги
cap_chown / cap_fownerменять владельца любого файла / действовать как владелец файла
cap_killпосылать сигналы чужим процессам
cap_setuid / cap_setgidменять UID/GID процесса — фактически root
cap_sys_admin«почти root»: mount, многое другое
cap_sys_ptraceотлаживать чужие процессы (strace -p)
cap_sys_niceповышать приоритет (nice ниже нуля)
cap_sys_timeменять системное время

Полный список — man 7 capabilities. Расшифровать маску из /proc/PID/status: capsh --decode=0000000000000400.

Как читать вывод

/usr/bin/ping cap_net_raw=ep
/usr/local/bin/app cap_net_bind_service,cap_net_raw=ep

Путь, затем список capabilities и флаги. Если у файла их нет, getcap ничего не печатает и возвращает 0. В ls -l capabilities не видны — в отличие от setuid (s) и ACL (+).

Capabilities процесса: строки CapPrm/CapEff в /proc/PID/status (шестнадцатеричная маска) или capsh --print для текущей оболочки.

Примеры

# у ping уже есть capability — поэтому он работает без root
getcap /usr/bin/ping

# все файлы с capabilities в системе (аудит безопасности)
getcap -r / 2>/dev/null

# разрешить своему серверу слушать порт 80 без root
setcap 'cap_net_bind_service=ep' /usr/local/bin/myserver
getcap /usr/local/bin/myserver

# несколько capabilities сразу
setcap 'cap_net_bind_service,cap_net_raw=ep' /usr/local/bin/myserver

# проверить в скрипте, что capability на месте
setcap -v 'cap_net_bind_service=ep' /usr/local/bin/myserver && echo ok

# снять
setcap -r /usr/local/bin/myserver

# для интерпретатора — только на реальный файл, не на символическую ссылку
setcap 'cap_net_bind_service=ep' "$(readlink -f /usr/bin/python3)"

# какие capabilities у работающего процесса
grep Cap /proc/$$/status
capsh --decode=$(awk '/CapEff/{print $2}' /proc/$$/status)

Подводные камни

  • setcap заменяет набор целиком. setcap cap_net_raw+ep файл на файле с cap_net_bind_service,cap_net_raw=ep оставит только cap_net_raw. Перечисляй все нужные capabilities в одной команде.
  • Без e привилегия не включится у обычной программы: с =p файл получит право, но cat или python его не активируют и получат «Permission denied». Пиши =ep.
  • Только обычный файл. На символическую ссылку setcap отвечает «Invalid file … for capability operation» — используй readlink -f.
  • Скрипты не работают. Capabilities на script.sh с #!/bin/bash игнорируются: запускается интерпретатор, а у него их нет. Выдают их бинарнику (или интерпретатору — но тогда привилегию получит любой скрипт на этом языке).
  • capabilities слетают при chown, при любой записи в файл (обновление пакета, cp поверх) и не копируются обычным cp. Сохраняют cp -a/--preserve=xattr и rsync -X (rsync -a без -X — нет); tar — только с --xattrs при упаковке и --xattrs --xattrs-include='*' при распаковке. После обновления программы выдай их заново.
  • Ограничение bounding set. Если capability нет в bounding set процесса (в контейнере это норма, например cap_dac_read_search, cap_sys_admin), файл с ней не запустится вовсе: «Operation not permitted». Смотри CapBnd в /proc/self/status.
  • В Docker-контейнере порты ниже 1024 и ping и так доступны обычному пользователю: Docker ставит net.ipv4.ip_unprivileged_port_start=0 и широкий ping_group_range. Проверяй эффект cap_net_bind_service на обычной машине или на другой capability, например cap_dac_override.
  • Ставить capabilities может только root (нужна cap_setfcap), иначе «unable to set CAP_SETFCAP effective capability».
  • cap_setuid, cap_sys_admin, cap_dac_override на интерпретаторе или редакторе равносильны выдаче root — именно их ищут при аудите через getcap -r /.

См. также

chmod · acl · sudo · proc · ping · ss