← Назад к вопросам

Что такое capabilities Linux?

1.0 Junior🔥 81 комментариев
#Виртуализация#Сети и протоколы

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Capabilities в Linux: концепция привилегированного доступа нового поколения

В традиционной модели безопасности Linux используется бинарная система привилегий: процесс либо обладает полными правами суперпользователя (root, UID 0), либо работает с ограниченными правами обычного пользователя. Это "всё или ничего" создавало значительные риски безопасности, поскольку любая уязвимость в программе, запущенной от root, могла привести к полному компрометированию системы. Capabilities (возможности) были введены в ядре Linux, начиная с версии 2.2, как механизм тонкого дробления привилегий суперпользователя на отдельные, независимые права.

Суть и философия Capabilities

Capabilities — это отдельные права на выполнение конкретных привилегированных операций. Вместо одного статуса "root" существует множество (около 40) различных способностей, таких как право изменять системное время, работать с сетевыми сокетами, загружать модули ядра или игнорировать проверки прав доступа к файлам (DAC). Процессу или исполняемому файлу можно назначить строго необходимый для его работы набор capabilities, минимизируя тем самым поверхность атаки.

Типы Capabilities и их хранение

Существует три набора capabilities для каждого процесса, хранящиеся в структуре задач ядра (task_struct):

  1. Effective (E): Фактически используемые в данный момент возможности. Именно этот набор проверяется ядром при попытке выполнения привилегированной операции.
  2. Permitted (P): Максимальный набор возможностей, которые процесс может иметь. Процесс может добавить capability из этого набора в Effective, но не может добавить то, чего нет в Permitted.
  3. Inheritable (I): Набор возможностей, которые могут быть унаследованы при выполнении execve() (запуске новой программы). Чтобы capability действительно перешла в Permitted набор нового процесса, она должна быть и в Inheritable наборе родителя, и в Inheritable наборе исполняемого файла (см. ниже).

Для исполняемых файлов также определены два набора capabilities (хранятся в расширенных атрибутах файла security.capability):

  • Inheritable (I): "Маска наследования". Определяет, какие capabilities из Inheritable набора процесса могут перейти в Permitted набор нового процесса после execve.
  • Permitted (P): Набор capabilities, которые автоматически добавляются в Permitted набор процесса при запуске файла, независимо от возможностей родительского процесса.
  • Effective (E): На самом деле это один бит (флаг), а не набор. Если он установлен, ядро автоматически поднимает все capabilities из нового Permitted набора в Effective набор после execve. Если сброшен — Effective набор после запуска очищается, и процесс должен вручную поднять нужные capabilities (обычно с помощью capset()).

Практическое использование и примеры

Управление capabilities осуществляется с помощью утилит setcap и getcap из пакета libcap, а также программного интерфейса libcap в коде.

Пример 1: Выдача права на использование "привилегированных" портов (ниже 1024) демону без запуска от root. Ранее для этого требовался setuid root.

# Установка capabilities для бинарника my_web_server
# CAP_NET_BIND_SERVICE позволяет биндиться на порты <1024
# CAP_SETPCAP условно, может потребоваться для управления своими же capabilities
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/my_web_server

# Проверка установленных capabilities
getcap /usr/local/bin/my_web_server
# /usr/local/bin/my_web_server = cap_net_bind_service+ep

Теперь пользователь www-data может запустить этот сервер, и он сможет слушать 80-й порт, не имея никаких других прав root.

Пример 2: Написание программы, которая использует capabilities через libcap. Программа временно повышает привилегию, выполняет действие и опускает её.

#include <sys/capability.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    cap_t caps = cap_get_proc(); // Получаем текущие capabilities
    cap_value_t cap_list[] = {CAP_SYS_TIME};

    // Добавляем CAP_SYS_TIME в Effective и Permitted наборы
    if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1 ||
        cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_SET) == -1) {
        perror("cap_set_flag");
        return 1;
    }

    // Применяем изменения к процессу
    if (cap_set_proc(caps) == -1) {
        perror("cap_set_proc");
        return 1;
    }
    cap_free(caps);

    // Теперь мы можем изменить системное время (здесь просто пример)
    printf("Процесс имеет CAP_SYS_TIME.\n");

    // Сбрасываем capability из Effective набора (принцип наименьших привилегий)
    caps = cap_get_proc();
    if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR) == -1) {
        perror("cap_set_flag clear");
        return 1;
    }
    cap_set_proc(caps);
    cap_free(caps);

    printf("Привилегия CAP_SYS_TIME опущена из Effective набора.\n");
    return 0;
}

Компиляция и запуск:

gcc -o cap_test cap_test.c -lcap
sudo setcap 'cap_sys_time=p' cap_test # Даем только Permitted, без Effective
./cap_test

Важность для DevOps и контейнеризации

Capabilities являются краеугольным камнем безопасности контейнеров (Docker, Kubernetes). По умолчанию Docker запускает контейнеры с сильно урезанным набором capabilities (например, удалены CAP_SYS_ADMIN, CAP_NET_RAW, CAP_SYS_MODULE). Это предотвращает множество атак даже в случае компрометации процесса внутри контейнера.

  • Docker: Управление через флаги --cap-add и --cap-drop.
    # Запуск контейнера с минимальными привилегиями
    docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
    
    # Опасный, но иногда необходимый режим (дает все capabilities)
    docker run --privileged my_app
    
  • Kubernetes: Задание в SecurityContext пода или контейнера.
    securityContext:
      capabilities:
        add: ["NET_ADMIN"]
        drop: ["ALL"]
    

Ключевые преимущества и выводы

  • Снижение рисков: Принцип наименьших привилегий (Least Privilege) реализуется на уровне процесса.
  • Гранулярность: Точный контроль над тем, что именно может делать процесс.
  • Наследование: Четкие правила передачи прав дочерним процессам.
  • Независимость от UID: Права привязаны к исполняемому файлу и процессу, а не только к пользователю.
  • Фундамент для контейнеров: Без capabilities современная изоляция workloads была бы гораздо менее безопасной.

Таким образом, capabilities — это эволюция модели безопасности Linux, позволяющая уйти от монолитных привилегий root в сторону безопасной, контролируемой и детализированной системы прав, что абсолютно необходимо для построения отказоустойчивых и безопасных инфраструктур в парадигме DevOps.

Что такое capabilities Linux? | PrepBro