---
authors:
  - 
    author: 'Chris Costello'
    email: chris@FreeBSD.org
  - 
    author: 'Robert Watson'
    email: rwatson@FreeBSD.org
description: 'Фреймворк TrustedBSD MAC'
next: books/arch-handbook/vm
params:
  path: /books/arch-handbook/mac/
prev: books/arch-handbook/sysinit
showBookMenu: true
tags: ["TrustedBSD", "MAC"]
title: 'Глава 6. Фреймворк TrustedBSD MAC'
weight: 7
---

[[mac]]
= Фреймворк TrustedBSD MAC
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 6
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/arch-handbook/

ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]

ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]

[[mac-copyright]]
== Авторские права документации MAC

Этот документ был разработан для проекта FreeBSD Крисом Костелло из Safeport Network Services и Network Associates Laboratories, подразделения исследований безопасности Network Associates, Inc., по контракту DARPA/SPAWAR N66001-01-C-8035 ("CBOSS") в рамках исследовательской программы DARPA CHATS.

Redistribution and use in source (SGML DocBook) and 'compiled' forms (SGML, HTML, PDF, PostScript, RTF and so forth) with or without modification, are permitted provided that the following conditions are met:

. Redistributions of source code (SGML DocBook) must retain the above copyright notice, this list of conditions and the following disclaimer as the first lines of this file unmodified.
. Распространение в скомпилированной форме (преобразованное в другие DTD, конвертированное в PDF, PostScript, RTF и другие форматы) должно включать указанное выше уведомление об авторских правах, данный список условий и следующий отказ от ответственности в документации и/или других материалах, предоставляемых вместе с распространением.

[IMPORTANT]
====
ЭТА ДОКУМЕНТАЦИЯ ПРЕДОСТАВЛЯЕТСЯ NETWORKS ASSOCIATES TECHNOLOGY, INC «КАК ЕСТЬ», И ЛЮБЫЕ ЯВНЫЕ ИЛИ ПОДРАЗУМЕВАЕМЫЕ ГАРАНТИИ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ПОДРАЗУМЕВАЕМЫЕ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ И ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ ОТРИЦАЮТСЯ. НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ NETWORKS ASSOCIATES TECHNOLOGY, INC НЕ НЕСЕТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ШТРАФНЫЕ ИЛИ КОСВЕННЫЕ УБЫТКИ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ЗАТРАТЫ НА ЗАМЕНУ ТОВАРОВ ИЛИ УСЛУГ; ПОТЕРЮ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ПРИБЫЛИ; ЛИБО ПРЕРЫВАНИЕ БИЗНЕСА), ВЫЗВАННЫЕ ЛЮБЫМ ОБРАЗОМ И НА ОСНОВАНИИ ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ, БУДЬ ТО В РАМКАХ ДОГОВОРА, СТРОГОЙ ОТВЕТСТВЕННОСТИ ИЛИ ДЕЛИКТА (ВКЛЮЧАЯ НЕБРЕЖНОСТЬ ИЛИ ИНОЕ), ВОЗНИКШИЕ ВСЛЕДСТВИЕ ИСПОЛЬЗОВАНИЯ ЭТОЙ ДОКУМЕНТАЦИИ, ДАЖЕ ЕСЛИ БЫЛО ПРЕДУПРЕЖДЕНИЕ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ.
====

[[mac-synopsis]]
== Обзор

FreeBSD включает экспериментальную поддержку нескольких политик обязательного контроля доступа, а также инфраструктуру для расширяемости безопасности ядра — TrustedBSD MAC Framework. MAC Framework представляет собой модульную инфраструктуру контроля доступа, позволяющую легко встраивать новые политики безопасности в ядро, загружать их при старте системы или динамически во время работы. Инфраструктура предоставляет множество возможностей для упрощения реализации новых политик безопасности, включая возможность легко присваивать метки безопасности (например, информацию о конфиденциальности) объектам системы.

Эта глава представляет фреймворк политик MAC и содержит документацию для образца модуля политики MAC.

[[mac-introduction]]
== Введение

Фреймворк TrustedBSD MAC предоставляет механизм для расширения модели контроля доступа ядра во время компиляции или выполнения. Новые политики системы могут быть реализованы в виде модулей ядра и связаны с ним; если присутствуют несколько модулей политик, их результаты будут объединены. Фреймворк MAC предоставляет различные инфраструктурные сервисы контроля доступа для помощи разработчикам политик, включая поддержку временных и постоянных меток безопасности объектов, не зависящих от политик. В настоящее время эта поддержка считается экспериментальной.

Эта глава предоставляет информацию, предназначенную для разработчиков модулей политик, а также потенциальных пользователей сред с поддержкой MAC, чтобы узнать о том, как MAC Framework поддерживает расширение контроля доступа в ядре.

[[mac-background]]
== Общие сведения о политиках

Мандатное управление доступом (MAC — Mandatory Access Control) относится к набору политик контроля доступа, которые в обязательном порядке применяются операционной системой к пользователям. Политики MAC можно противопоставить защите на основе дискреционного управления доступом (DAC — Discretionary Access Control), при которой непривилегированные пользователи могут (по своему усмотрению) защищать объекты. В традиционных UNIX-системах защита DAC включает права доступа к файлам и списки контроля доступа; защита MAC включает управление процессами, предотвращающее отладку между пользователями, и межсетевые экраны. Различные политики MAC были разработаны создателями операционных систем и исследователями безопасности, включая политику конфиденциальности многоуровневой безопасности (MLS — Multi-Level Security), политику целостности Biba, управление доступом на основе ролей (RBAC — Role-Based Access Control), принудительное применение доменов и типов (DTE — Domain and Type Enforcement) и принудительное применение типов (TE — Type Enforcement). Каждая модель основывает решения на различных факторах, включая идентификатор пользователя, роль и уровень доступа, а также метки безопасности на объектах, представляющих такие концепции, как конфиденциальность и целостность данных.

Фреймворк TrustedBSD MAC способен поддерживать модули политик, реализующие все эти политики, а также широкий класс политик усиления защиты системы, которые могут использовать существующие атрибуты безопасности, такие как идентификаторы пользователей и групп, а также расширенные атрибуты файлов и другие свойства системы. Кроме того, несмотря на название, фреймворк MAC также может использоваться для реализации чисто дискреционных политик, поскольку модулям политик предоставляется значительная гибкость в том, как они авторизуют защиту.

[[mac-framework-kernel-arch]]
== Архитектура MAC Framework в ядре

Фреймворк TrustedBSD MAC позволяет модулям ядра расширять политику безопасности операционной системы, а также предоставляет функциональность инфраструктуры, необходимую многим модулям контроля доступа. Если одновременно загружено несколько политик, фреймворк MAC полезным образом (в некотором смысле полезным) объединит результаты этих политик.

[[mac-framework-kernel-arch-elements]]
=== Элементы ядра

В рамках MAC Framework реализован ряд элементов ядра:

* Интерфейсы управления фреймворком
* Параллелизм и примитивы синхронизации.
* Регистрация политики
* Расширяемая метка безопасности для объектов ядра
* Операторы композиции точки входа политики
* Примитивы управления метками
* Точка входа API, вызываемая службами ядра
* Точка входа API для модулей политик
* Реализации точек входа (жизненный цикл политики, жизненный цикл объекта/управление метками, проверки контроля доступа).
* Системные вызовы, независимые от политик, для управления метками
* `mac_syscall()` мультиплексный системный вызов
* Различные политики безопасности, реализованные в виде модулей политики MAC

[[mac-framework-kernel-arch-management]]
=== Интерфейсы управления фреймворком

Фреймворком TrustedBSD MAC можно напрямую управлять с помощью sysctl, параметров загрузчика и системных вызовов.

В большинстве случаев одноимённые параметры sysctl и настройки загрузчика изменяют одни и те же параметры и управляют поведением, таким как применение защитных механизмов, связанных с различными подсистемами ядра. Кроме того, если в ядро включена поддержка отладки MAC, будет вестись несколько счётчиков для отслеживания выделения меток. Обычно рекомендуется не использовать общие настройки подсистем для управления поведением политик в рабочих средах, так как они широко влияют на работу всех активных политик. Вместо этого следует предпочитать настройки отдельных политик, поскольку они обеспечивают более высокую детализацию и большую операционную согласованность для модулей политик.

Загрузка и выгрузка модулей политики выполняется с использованием системных вызовов управления модулями и других системных интерфейсов, включая переменные загрузчика; модули политики получат возможность влиять на события загрузки и выгрузки, включая предотвращение нежелательной выгрузки политики.

[[mac-framework-kernel-arch-synchronization]]
=== Список политик параллелизма и синхронизации

Поскольку набор активных политик может изменяться во время выполнения, а вызов точек входа не является атомарным, требуется синхронизация для предотвращения загрузки или выгрузки политик во время выполнения вызова точки входа, фиксируя набор активных политик на время выполнения. Это достигается с помощью счетчика занятости фреймворка: при входе в точку входа счетчик увеличивается; при выходе из нее — уменьшается. Пока счетчик занятости повышен, изменения списка политик запрещены, и потоки, пытающиеся изменить список политик, будут ждать, пока список не освободится. Счетчик занятости защищается мьютексом, а условная переменная используется для пробуждения потоков, ожидающих изменений списка политик. Побочным эффектом этой модели синхронизации является то, что рекурсивный вход в MAC Framework из модуля политики разрешен, хотя обычно не используется.

Для снижения накладных расходов счётчика занятости используются различные оптимизации, включая избегание полной стоимости увеличения и уменьшения, если список пуст или содержит только статические записи (политики, загруженные до старта системы, которые нельзя выгрузить). Также предоставляется опция на этапе компиляции, которая предотвращает любые изменения в наборе загруженных политик во время выполнения, что устраняет затраты на блокировку мьютексов, связанные с поддержкой динамически загружаемых и выгружаемых политик, поскольку синхронизация больше не требуется.

Поскольку MAC Framework не может блокировать некоторые точки входа, обычная блокировка сна не может быть использована; в результате попытка загрузки или выгрузки может блокироваться на значительное время, ожидая, пока фреймворк станет свободным.

[[mac-framework-kernel-arch-label-synchronization]]
=== Синхронизация меток

Поскольку к объектам ядра обычно может обращаться более одного потока одновременно, и допускается одновременный вход нескольких потоков в MAC Framework, хранение атрибутов безопасности, поддерживаемое MAC Framework, тщательно синхронизировано. Как правило, существующая синхронизация ядра для данных объектов ядра используется для защиты меток безопасности MAC Framework на объекте: например, метки MAC на сокетах защищаются с помощью существующего мьютекса сокета. Аналогично, семантика параллельного доступа обычно идентична семантике контейнерных объектов: для учетных данных поддерживается семантика копирования при записи для содержимого меток, как и для остальной структуры учетных данных. MAC Framework устанавливает необходимые блокировки на объекты при вызове с ссылкой на объект. Авторам политик необходимо учитывать эти семантики синхронизации, так как они иногда ограничивают типы доступа к меткам: например, когда ссылка только для чтения на учетные данные передается политике через точку входа, разрешены только операции чтения для состояния метки, прикрепленного к учетным данным.

[[mac-framework-kernel-arch-policy-synchronization]]
=== Синхронизация политики и параллелизм

Модули политик должны быть написаны с учетом того, что множество потоков ядра могут одновременно войти в одну или несколько точек входа политики из-за параллельной и вытесняющей природы ядра FreeBSD. Если модуль политики использует изменяемое состояние, это может потребовать применения примитивов синхронизации внутри политики, чтобы предотвратить несогласованные представления этого состояния, ведущие к некорректной работе политики. Политики, как правило, могут использовать существующие примитивы синхронизации FreeBSD для этой цели, включая мьютексы, блокировки с ожиданием, условные переменные и счётные семафоры. Однако политики должны быть написаны так, чтобы применять эти примитивы осторожно, соблюдая существующие порядки блокировок в ядре и учитывая, что некоторые точки входа не допускают ожидания, ограничивая использование примитивов в этих точках входа мьютексами и операциями пробуждения.

Когда модули политики обращаются к другим подсистемам ядра, они обычно должны освобождать любые блокировки внутри политики, чтобы избежать нарушения порядка блокировок ядра или риска рекурсивных блокировок. Это позволит сохранить блокировки политики как конечные блокировки в глобальном порядке блокировок, помогая избежать взаимоблокировки.

[[mac-framework-kernel-arch-registration]]
=== Регистрация политики

Фреймворк MAC поддерживает два списка активных политик: статический список и динамический список. Списки отличаются только в отношении их семантики блокировки: для использования статического списка не требуется повышенный счетчик ссылок. Когда загружаются модули ядра, содержащие политики фреймворка MAC, модуль политики использует `SYSINIT` для вызова функции регистрации; когда модуль политики выгружается, `SYSINIT` аналогично вызывает функцию отмены регистрации. Регистрация может завершиться неудачей, если модуль политики загружается более одного раза, если для регистрации недостаточно ресурсов (например, политика может требовать маркировки, а доступного состояния маркировки может быть недостаточно), или другие предварительные условия политики могут не выполняться (некоторые политики могут быть загружены только до загрузки системы). Аналогично, отмена регистрации может завершиться неудачей, если политика помечена как невыгружаемая.

[[mac-framework-kernel-arch-entrypoints]]
=== Точки входа

Ядро взаимодействует с MAC Framework двумя способами: вызывает набор API для уведомления фреймворка о соответствующих событиях и предоставляет указатель на структуру меток, не зависящую от политики, в объектах, связанных с безопасностью. Указатель метки управляется MAC Framework через точки входа управления метками, что позволяет фреймворку предоставлять службу маркировки модулям политик с относительно минимальными изменениями в подсистеме ядра, управляющей объектом. Например, указатели меток были добавлены к процессам, учетным данным процессов, сокетам, каналам, vnode, Mbuf, сетевым интерфейсам, очередям сборки IP-пакетов и множеству других структур, связанных с безопасностью. Ядро также вызывает MAC Framework при принятии важных решений по безопасности, позволяя модулям политик дополнять эти решения на основе собственных критериев (включая, возможно, данные, хранящиеся в метках безопасности). Большинство этих критически важных решений по безопасности будут явными проверками контроля доступа; однако некоторые влияют на более общие функции принятия решений, такие как сопоставление пакетов для сокетов и переход меток при выполнении программы.

[[mac-framework-kernel-arch-composition]]
=== Композиция политик

Когда в ядро загружено более одного модуля политики одновременно, результаты работы модулей политики будут объединены фреймворком с использованием оператора композиции. Этот оператор в настоящее время жёстко закодирован и требует, чтобы все активные политики одобрили запрос для возврата успешного результата. Поскольку политики могут возвращать различные условия ошибки (успех, доступ запрещён, объект не существует, ...), оператор старшинства выбирает результирующую ошибку из набора ошибок, возвращаемых политиками. В общем случае, ошибки, указывающие на то, что объект не существует, будут предпочтительнее ошибок, указывающих на запрет доступа к объекту. Хотя не гарантируется, что результирующая композиция будет полезной или безопасной, мы обнаружили, что это так для многих полезных наборов политик. Например, традиционные доверенные системы часто поставляются с двумя или более политиками, использующими аналогичную композицию.

[[mac-framework-kernel-arch-labels]]
=== Поддержка меток

Поскольку многие интересные расширения контроля доступа зависят от меток безопасности объектов, MAC Framework предоставляет набор системных вызовов для управления метками, не зависящих от политик, охватывающих различные объекты, доступные пользователю. Общие типы меток включают идентификаторы разделов, метки конфиденциальности, метки целостности, отделы (compartment), домены, роли и типы. Под "не зависящими от политик" подразумевается, что модули политик могут полностью определять семантику метаданных, связанных с объектом. Модули политик участвуют в интернализации и экстернализации строковых меток, предоставляемых пользовательскими приложениями, и могут при необходимости предоставлять приложениям несколько элементов меток.

Метки в памяти хранятся в `struct label`, выделяемой через slab-аллокатор. Эта структура состоит из массива фиксированной длины, содержащего объединения, каждое из которых хранит указатель `void *` и значение типа `long`. Политикам, регистрирующим хранилище меток, назначается идентификатор "слота", который может использоваться для разыменования хранилища меток. Семантика хранилища полностью определяется модулем политики: модулям предоставляется набор точек входа, связанных с жизненным циклом объектов ядра, включая инициализацию, связывание/создание и уничтожение. Используя эти интерфейсы, можно реализовать подсчёт ссылок и другие модели хранения. Прямой доступ к структуре объекта, как правило, не требуется модулям политики для получения метки, поскольку MAC Framework обычно передаёт в точки входа как указатель на объект, так и прямой указатель на метку объекта. Основным исключением из этого правила являются учётные данные процесса, для доступа к метке которых требуется ручное разыменование. Это может измениться в будущих версиях MAC Framework.

Входные точки инициализации часто включают флаг режима сна, указывающий, разрешено ли инициализации переходить в режим сна; если сон не разрешен, может быть возвращена ошибка для отмены выделения метки (и, следовательно, объекта). Это может произойти, например, в сетевом стеке во время обработки прерывания, где сон не разрешен, или пока вызывающий удерживает мьютекс. Из-за затрат производительности на поддержание меток на передаваемых сетевых пакетах (Mbuf), политики должны явно объявлять требование о выделении меток для Mbuf. Динамически загружаемые политики, использующие метки, должны быть способны обрабатывать случай, когда их функция инициализации не была вызвана для объекта, так как объекты могут уже существовать при загрузке политики. MAC Framework гарантирует, что неинициализированные слоты меток будут содержать значение 0 или NULL, что политики могут использовать для обнаружения неинициализированных значений. Однако, поскольку выделение меток для Mbuf условно, политики также должны быть способны обрабатывать указатель на метку NULL для Mbuf, если они были загружены динамически.

В случае меток файловых систем предусмотрена специальная поддержка для постоянного хранения меток безопасности в расширенных атрибутах. Там, где это возможно, используются транзакции расширенных атрибутов, чтобы обеспечить согласованные составные обновления меток безопасности на vnode — в настоящее время такая поддержка присутствует только в файловой системе UFS2. Авторы политик могут выбрать реализацию многометочных меток объектов файловой системы с использованием одного (или нескольких) расширенных атрибутов. По соображениям эффективности метка vnode (`v_label`) является кэшем любой метки на диске; политики могут загружать значения в кэш при создании vnode и обновлять кэш по мере необходимости. В результате нет необходимости напрямую обращаться к расширенному атрибуту при каждой проверке контроля доступа.

[NOTE]
====
В настоящее время, если помеченная политика разрешает динамическую выгрузку, её слот состояния не может быть освобождён, что накладывает строгое (и относительно низкое) ограничение на количество операций выгрузки-перезагрузки для помеченных политик.
====

[[mac-framework-kernel-arch-syscalls]]
=== Системные вызовы

В рамках MAC Framework реализован ряд системных вызовов: большинство из них поддерживают API для получения и управления метками, не зависящий от политики и доступный пользовательским приложениям.

Вызовы управления метками принимают структуру описания метки `struct mac`, которая содержит серию элементов метки MAC. Каждый элемент содержит строку с именем и строку со значением. Каждой политике будет предоставлена возможность запросить определённое имя элемента, позволяя политикам предоставлять несколько независимых элементов, если это необходимо. Модули политик выполняют интернализацию и экстернализацию между метками ядра и метками, предоставленными пользователем, через точки входа, что позволяет использовать различные семантики. Системные вызовы управления метками обычно обёрнуты в функции пользовательской библиотеки для выполнения выделения памяти и обработки ошибок, упрощая пользовательские приложения, которые должны управлять метками.

В ядре FreeBSD есть следующие системные вызовы, связанные с MAC:

* `mac_get_proc()` может использоваться для получения метки текущего процесса.
* `mac_set_proc()` может использоваться, чтобы запросить изменение метки текущего процесса.
* `mac_get_fd()` может использоваться для получения метки объекта (файл, сокет, канал, ...), на который ссылается файловый дескриптор.
* `mac_get_file()` может использоваться для получения метки объекта, на который ссылается путь в файловой системе.
* `mac_set_fd()` может использоваться для запроса изменения метки объекта (файл, сокет, канал, ...), на который ссылается файловый дескриптор.
* `mac_set_file()` может использоваться для запроса изменения метки объекта, указанного по пути в файловой системе.
* `mac_syscall()` позволяет модулям политик создавать новые системные вызовы без изменения таблицы системных вызовов; она принимает имя целевой политики, номер операции и непрозрачный аргумент для использования политикой.
* `mac_get_pid()` может использоваться для запроса метки другого процесса по его идентификатору.
* `mac_get_link()` идентична `mac_get_file()`, но не переходит по символической ссылке, если она является конечным элементом пути, поэтому может использоваться для получения метки на символьной ссылке.
* `mac_set_link()` идентична `mac_set_file()`, за исключением того, что она не следует по символической ссылке, если это конечный элемент пути, поэтому может использоваться для изменения метки на символьной ссылке.
* `mac_execve()` идентична системному вызову `execve()`, но также принимает запрошенную метку, которая будет установлена для процесса при начале выполнения новой программы. Это изменение метки при выполнении называется "переходом".
* `mac_get_peer()`, фактически реализованный через параметр сокета, извлекает метку удалённого узла на сокете, если она доступна.

В дополнение к этим системным вызовам, сетевые ioctl-команды `SIOCSIGMAC` и `SIOCSIFMAC` позволяют получать и устанавливать метки на сетевых интерфейсах.

[[mac-policy-architecture]]
== Архитектура политик MAC

Политики безопасности либо непосредственно встроены в ядро, либо скомпилированы в загружаемые модули ядра, которые могут быть загружены при загрузке системы или динамически с использованием системных вызовов загрузки модулей во время выполнения. Модули политик взаимодействуют с системой через набор объявленных точек входа, предоставляя доступ к потоку системных событий и позволяя политике влиять на решения контроля доступа. Каждая политика содержит ряд элементов:

* Необязательные параметры конфигурации для политики.
* Централизованная реализация логики политики и параметров.
* Необязательная реализация событий жизненного цикла политики, таких как инициализация и уничтожение.
* Необязательная поддержка инициализации, обслуживания и удаления меток на выбранных объектах ядра.
* Дополнительная поддержка проверки процессов пользователя и изменения меток на выбранных объектах.
* Реализация выбранных точек входа контроля доступа, представляющих интерес для политики.
* Объявление идентификатора политики, точек входа модуля и свойств политики.

[[mac-policy-declaration]]
=== Объявление политики

Модули могут быть объявлены с использованием макроса `MAC_POLICY_SET()`, который задаёт имя политики, предоставляет ссылку на вектор точек входа MAC, указывает флаги загрузки, определяющие, как фреймворк политик должен обрабатывать политику, и при необходимости запрашивает выделение состояния метки фреймворком.

[.programlisting]
....
static struct mac_policy_ops mac_policy_ops =
{
        .mpo_destroy = mac_policy_destroy,
        .mpo_init = mac_policy_init,
        .mpo_init_bpfdesc_label = mac_policy_init_bpfdesc_label,
        .mpo_init_cred_label = mac_policy_init_label,
/* ... */
        .mpo_check_vnode_setutimes = mac_policy_check_vnode_setutimes,
        .mpo_check_vnode_stat = mac_policy_check_vnode_stat,
        .mpo_check_vnode_write = mac_policy_check_vnode_write,
};
....

The MAC policy entry point vector, `mac__policy__ops` in this example, associates functions defined in the module with specific entry points. A complete listing of available entry points and their prototypes may be found in the MAC entry point reference section. Of specific interest during module registration are the .mpo_destroy and .mpo_init entry points. .mpo_init will be invoked once a policy is successfully registered with the module framework but prior to any other entry points becoming active. This permits the policy to perform any policy-specific allocation and initialization, such as initialization of any data or locks. .mpo_destroy will be invoked when a policy module is unloaded to permit releasing of any allocated memory and destruction of locks. Currently, these two entry points are invoked with the MAC policy list mutex held to prevent any other entry points from being invoked: this will be changed, but in the mean time, policies should be careful about what kernel primitives they invoke so as to avoid lock ordering or sleeping problems.

Поле имени модуля в объявлении политики существует для того, чтобы модуль мог быть однозначно идентифицирован с целью управления зависимостями модулей. Следует выбрать подходящую строку. Полное имя политики отображается пользователю в журнале ядра при загрузке и выгрузке, а также экспортируется при предоставлении информации о статусе процессам в пользовательском пространстве.

[[mac-policy-flags]]
=== Флаги политик

Поле флагов объявления политики позволяет модулю предоставлять фреймворку информацию о своих возможностях во время загрузки модуля. В настоящее время определены три флага:

MPC_LOADTIME_FLAG_UNLOADOK::
Этот флаг указывает, что модуль политики может быть выгружен. Если этот флаг не указан, то фреймворк политики отклонит запросы на выгрузку модуля. Этот флаг может использоваться модулями, которые выделяют состояние метки и не могут освободить это состояние во время выполнения.

MPC_LOADTIME_FLAG_NOTLATE::
Этот флаг указывает, что модуль политики должен быть загружен и инициализирован на раннем этапе процесса загрузки. Если флаг указан, попытки зарегистрировать модуль после загрузки будут отклонены. Флаг может использоваться политиками, которые требуют повсеместной маркировки всех системных объектов и не могут обрабатывать объекты, не прошедшие надлежащую инициализацию политикой.

MPC_LOADTIME_FLAG_LABELMBUFS::
Этот флаг указывает, что модуль политики требует маркировки Mbuf, и память всегда должна выделяться для хранения меток Mbuf. По умолчанию MAC Framework не выделяет память для хранения меток Mbuf, если хотя бы одна загруженная политика не установила этот флаг. Это заметно улучшает производительность сети, когда политики не требуют маркировки Mbuf. Существует опция ядра `MAC_ALWAYS_LABEL_MBUF`, которая заставляет MAC Framework выделять память для хранения меток Mbuf независимо от установки этого флага, и может быть полезной в некоторых средах.

[NOTE]
====
Политики, использующие `MPC_LOADTIME_FLAG_LABELMBUFS` без установленного флага `MPC_LOADTIME_FLAG_NOTLATE`, должны корректно обрабатывать переданные `NULL` указатели меток Mbuf в точках входа. Это необходимо, так как Mbuf в процессе передачи без хранилища меток могут сохраняться после загрузки политики, включающей маркировку Mbuf. Если политика загружена до активации сетевой подсистемы (т.е. политика не загружается поздно), то все Mbuf гарантированно имеют хранилище меток.
====

[[mac-policy-entry-points]]
=== Точки входа политики

Четыре класса точек входа предоставляются политикам, зарегистрированным в рамках системы: точки входа, связанные с регистрацией и управлением политиками, точки входа, обозначающие инициализацию, создание, уничтожение и другие события жизненного цикла объектов ядра, события, связанные с решениями контроля доступа, на которые политика может влиять, и вызовы, связанные с управлением метками на объектах. Кроме того, предоставляется точка входа `mac_syscall()`, позволяющая политикам расширять интерфейс ядра без регистрации новых системных вызовов.

Авторы модулей политик должны быть осведомлены о стратегии блокировок в ядре, а также о том, какие блокировки объектов доступны на различных точках входа. Им следует избегать сценариев взаимоблокировок, не захватывая нелистовые блокировки внутри точек входа, а также соблюдать протокол блокировок для доступа и изменения объектов. В частности, авторы должны учитывать, что хотя необходимые блокировки для доступа к объектам и их меткам обычно удерживаются, достаточные блокировки для изменения объекта или его метки могут отсутствовать для всех точек входа. Информация о блокировках аргументов документирована в описании точек входа фреймворка MAC.

Точки входа политики будут передавать ссылку на метку объекта вместе с самим объектом. Это позволяет помеченным политикам не знать внутренней структуры объекта, но при этом принимать решения на основе метки. Исключением из этого являются учетные данные процесса, для которые предполагается, что политики понимают их, как объект безопасности первого класса в ядре.

[[mac-entry-point-reference]]
== Справочник по точкам входа политики MAC

[[mac-mpo-general]]
=== Общие точки входа модуля

[[mac-mpo-init]]
==== `mpo_init`

[source, c]
----
void mpo_init(struct mac_policy_conf *conf);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`conf`
|Определение политики MAC
| 
|===

Событие загрузки политики. Мьютекс списка политик удерживается, поэтому операции ожидания выполнить нельзя, а вызовы других подсистем ядра должны осуществляться с осторожностью. Если во время инициализации политики требуются потенциально блокирующие выделения памяти, их следует выполнять с использованием отдельного модуля SYSINIT().

[[mpo-destroy]]
==== `mpo_destroy`

[source, c]
----
void mpo_destroy(struct mac_policy_conf *conf);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`conf`
|Определение политики MAC
| 
|===

Событие загрузки политики. Мьютекс списка политик удерживается, поэтому следует соблюдать осторожность.

[[mac-mpo-syscall]]
==== `mpo_syscall`

[source, c]
----
int mpo_syscall(struct thread *td, int call, void *arg);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`td`
|Вызывающий поток
| 

|`call`
|Номер системного вызова, зависящий от политики
| 

|`arg`
|Указатель на аргументы системного вызова
| 
|===

Этот точку входа предоставляет мультиплексированный системный вызов на основе политик, что позволяет политикам предоставлять дополнительные сервисы пользовательским процессам без регистрации конкретных системных вызовов. Имя политики, указанное при регистрации, используется для демультиплексирования вызовов из пользовательского пространства, а аргументы будут переданы в эту точку входа. При реализации новых сервисов модули безопасности должны убедиться, что вызывают соответствующие проверки контроля доступа из MAC-фреймворка по мере необходимости. Например, если политика реализует расширенную функциональность сигналов, она должна вызывать необходимые проверки контроля доступа сигналов для задействования MAC-фреймворка и других зарегистрированных политик.

[NOTE]
====
Модули в настоящее время должны самостоятельно выполнять `copyin()` для данных системного вызова.
====

[[mac-mpo-thread-userret]]
==== `mpo_thread_userret`

[source, c]
----
void mpo_thread_userret(struct thread *td);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`td`
|Возвращающий поток
| 
|===

Этот точка входа позволяет модулям политики выполнять события, связанные с MAC, когда поток возвращается в пользовательское пространство, через возврат системного вызова, возврат из ловушки или иным образом. Это необходимо для политик, имеющих плавающие метки процессов, так как не всегда возможно получить блокировку процесса в произвольных точках стека во время обработки системного вызова; метки процессов могут представлять традиционные данные аутентификации, информацию об истории процесса или другие данные. Для использования этого механизма предполагаемые изменения метки учётных данных процесса могут быть сохранены в `p_label`, защищённом спин-блокировкой для каждой политики, а затем установить флаг `TDF_ASTPENDING` для потока и флаг `PS_MACPENDM` для процесса, чтобы запланировать вызов точки входа `userret`. С этой точки входа политика может создать замену учётных данных с меньшими опасениями относительно контекста блокировки. Авторам политик следует учитывать, что порядок событий, связанных с планированием AST и выполнением AST, может быть сложным и переплетённым в многопоточных приложениях.

[[mac-label-ops]]
=== Операции с метками

[[mac-mpo-init-bpfdesc]]
==== `mpo_init_bpfdesc_label`

[source, c]
----
void mpo_init_bpfdesc_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 
|===

Инициализировать метку на только что созданном bpfdesc (дескрипторе BPF). Разрешено использование режима сна.

[[mac-mpo-init-cred-label]]
==== `mpo_init_cred_label`

[source, c]
----
void mpo_init_cred_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 
|===

Инициализировать метку для вновь созданных учетных данных пользователя. Разрешено приостанавливать выполнение.

[[mac-mpo-init-devfsdirent]]
==== `mpo_init_devfsdirent_label`

[source, c]
----
void mpo_init_devfsdirent_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 
|===

Инициализировать метку на только что созданной записи devfs. Разрешено использование режима сна.

[[mac-mpo-init-ifnet]]
==== `mpo_init_ifnet_label`

[source, c]
----
void mpo_init_ifnet_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 
|===

Инициализировать метку на только что созданном сетевом интерфейсе. Разрешено приостанавливать выполнение.

[[mac-mpo-init-ipq]]
==== `mpo_init_ipq_label`

[source, c]
----
void mpo_init_ipq_label(struct label *label, int flag);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 

|`flag`
|Спящий/неспящий man:malloc[9]; см. ниже
| 
|===

Инициализировать метку в только что созданной очереди сборки IP-фрагментов. Поле `flag` может принимать одно из значений M_WAITOK или M_NOWAIT и должно использоваться, чтобы избежать выполнения "спящего" man:malloc[9] во время этого вызова инициализации. Выделение очереди сборки IP-фрагментов часто происходит в средах, чувствительных к производительности, и реализация должна избегать "спящих" или длительных операций. Этой точке входа разрешено завершаться неудачей, что приведёт к невозможности выделения очереди сборки IP-фрагментов.

[[mac-mpo-init-mbuf]]
==== `mpo_init_mbuf_label`

[source, c]
----
void mpo_init_mbuf_label(int flag, struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`flag`
|Спящий/неспящий man:malloc[9]; см. ниже
| 

|`label`
|Метка политики для инициализации
| 
|===

Инициализировать на только что созданном заголовке пакета mbuf метку (`mbuf`). Поле `flag` может принимать одно из значений M_WAITOK или M_NOWAIT и должно использоваться, чтобы избежать выполнения "спящего" man:malloc[9] во время этого вызова инициализации. Выделение mbuf часто происходит в чувствительных к производительности средах, и реализация должна избегать "спящего" режима или длительных операций. Этой точке входа разрешено завершаться неудачей, что приведёт к невозможности выделения заголовка mbuf.

[[mac-mpo-init-mount]]
==== `mpo_init_mount_label`

[source, c]
----
void mpo_init_mount_label(struct label *mntlabel, struct label *fslabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mntlabel`
|Метка политики для инициализации самой точки монтирования
| 

|`fslabel`
|Метка политики для инициализации файловой системы
| 
|===

Инициализировать метки на новой точке монтирования. Разрешено приостанавливать выполнение.

[[mac-mpo-init-mount-fs-label]]
==== `mpo_init_mount_fs_label`

[source, c]
----
void mpo_init_mount_fs_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для инициализации
| 
|===

Инициализировать метку на только что смонтированной файловой системе. Разрешено приостановление работы

[[mac-mpo-init-pipe-label]]
==== `mpo_init_pipe_label`

[source, c]
----
void mpo_init_pipe_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для заполнения
| 
|===

Инициализировать метку для только что созданного канала. Разрешено приостановление выполнения.

[[mac-mpo-init-socket]]
==== `mpo_init_socket_label`

[source, c]
----
void mpo_init_socket_label(struct label *label, int flag);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 

|`flag`
|флаги man:malloc[9]
| 
|===

Инициализировать метку для нового сокета. Поле `flag` может принимать одно из значений M_WAITOK или M_NOWAIT и должно использоваться, чтобы избежать выполнения спящего man:malloc[9] во время этого вызова инициализации.

[[mac-mpo-init-socket-peer-label]]
==== `mpo_init_socket_peer_label`

[source, c]
----
void mpo_init_socket_peer_label(struct label *label, int flag);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 

|`flag`
|флаги man:malloc[9]
| 
|===

Инициализировать метку однорангового узла (peer) для вновь созданного сокета. Поле `flag` может принимать одно из значений M_WAITOK или M_NOWAIT и должно использоваться для избежания выполнения спящего man:malloc[9] во время этого вызова инициализации.

[[mac-mpo-init-proc-label]]
==== `mpo_init_proc_label`

[source, c]
----
void mpo_init_proc_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 
|===

Инициализировать метку для вновь созданного процесса. Разрешено приостановление выполнения.

[[mac-mpo-init-vnode]]
==== `mpo_init_vnode_label`

[source, c]
----
void mpo_init_vnode_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Новая метка для инициализации
| 
|===

Инициализировать метку на только что созданном vnode. Разрешено приостанавливать выполнение.

[[mac-mpo-destroy-bpfdesc]]
==== `mpo_destroy_bpfdesc_label`

[source, c]
----
void mpo_destroy_bpfdesc_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|bpfdesc label
| 
|===

Уничтожить метку на дескрипторе BPF. В этой точке входа политика должна освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-cred]]
==== `mpo_destroy_cred_label`

[source, c]
----
void mpo_destroy_cred_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка уничтожается
| 
|===

Уничтожить метку на учетных данных. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-devfsdirent]]
==== `mpo_destroy_devfsdirent_label`

[source, c]
----
void mpo_destroy_devfsdirent_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка уничтожается
| 
|===

Уничтожить метку на записи devfs. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-ifnet-label]]
==== `mpo_destroy_ifnet_label`

[source, c]
----
void mpo_destroy_ifnet_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка уничтожается
| 
|===

Уничтожить метку на удаленном интерфейсе. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-ipq-label]]
==== `mpo_destroy_ipq_label`

[source, c]
----
void mpo_destroy_ipq_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка уничтожается
| 
|===

Уничтожить метку в очереди IP-фрагментов. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-mbuf-label]]
==== `mpo_destroy_mbuf_label`

[source, c]
----
void mpo_destroy_mbuf_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка уничтожается
| 
|===

Уничтожить метку в заголовке mbuf. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-mount-label]]
==== `mpo_destroy_mount_label`

[source, c]
----
void mpo_destroy_mount_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Точка монтирования метки уничтожается
| 
|===

Уничтожить метки на точке монтирования. В этой точке входа модуль политики должен освободить внутреннее хранилище, связанное с `mntlabel`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-mount]]
==== `mpo_destroy_mount_label`

[source, c]
----
void mpo_destroy_mount_label(struct label *mntlabel, struct label *fslabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mntlabel`
|Точка монтирования метки уничтожается
| 

|`fslabel`
|Метка файловой системы уничтожается
| 
|===

Уничтожить метки на точке монтирования. В этой точке входа модуль политики должен освободить внутреннее хранилище, связанное с `mntlabel` и `fslabel`, чтобы их можно было уничтожить.

[[mac-mpo-destroy-socket]]
==== `mpo_destroy_socket_label`

[source, c]
----
void mpo_destroy_socket_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Уничтожение метки сокета
| 
|===

Уничтожить метку на сокете. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-socket-peer-label]]
==== `mpo_destroy_socket_peer_label`

[source, c]
----
void mpo_destroy_socket_peer_label(struct label *peerlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`peerlabel`
|Сокет: метка однорангового узла уничтожается
| 
|===

Уничтожить метку однорангового узла на сокете. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-pipe-label]]
==== `mpo_destroy_pipe_label`

[source, c]
----
void mpo_destroy_pipe_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка канала (pipe)
| 
|===

Уничтожить метку на канале. В этой точке входа модуль политики должен освободить всю внутреннюю память, связанную с `label`, чтобы её можно было уничтожить.

[[mac-mpo-destroy-proc-label]]
==== `mpo_destroy_proc_label`

[source, c]
----
void mpo_destroy_proc_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка процесса
| 
|===

Уничтожить метку на процессе. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-destroy-vnode-label]]
==== `mpo_destroy_vnode_label`

[source, c]
----
void mpo_destroy_vnode_label(struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка процесса
| 
|===

Уничтожить метку на vnode. В этой точке входа модуль политики должен освободить любое внутреннее хранилище, связанное с `label`, чтобы ее можно было уничтожить.

[[mac-mpo-copy-mbuf-label]]
==== `mpo_copy_mbuf_label`

[source, c]
----
void mpo_copy_mbuf_label(struct label *src, struct label *dest);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`src`
|Метка источника
| 

|`dest`
|Метка назначения
| 
|===

Скопировать информацию метки из `src` в `dest`.

[[mac-mpo-copy-pipe-label]]
==== `mpo_copy_pipe_label`

[source, c]
----
void mpo_copy_pipe_label(struct label *src, struct label *dest);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`src`
|Метка источника
| 

|`dest`
|Метка назначения
| 
|===

Скопировать информацию метки из `src` в `dest`.

[[mac-mpo-copy-vnode-label]]
==== `mpo_copy_vnode_label`

[source, c]
----
void mpo_copy_vnode_label(struct label *src, struct label *dest);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`src`
|Метка источника
| 

|`dest`
|Метка назначения
| 
|===

Скопировать информацию метки из `src` в `dest`.

[[mac-mpo-externalize-cred-label]]
==== `mpo_externalize_cred_label`

[source, c]
----
int mpo_externalize_cred_label(struct label *label, char *element_name,
    struct sbuf *sb, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для вынесения во внешний ресурс
| 

|`element_name`
|Имя политики, метка которой должна быть вынесена во внешний ресурс
| 

|`sb`
|Буфер строки для заполнения текстовым представлением метки
| 

|`claimed`
|Должно быть увеличено, когда `element_data` может быть заполнено.
| 
|===

Создать внешнее представление метки на основе переданной структуры метки. Внешнее представление метки состоит из текстового представления содержимого метки, которое может использоваться пользовательскими приложениями и прочитано пользователем. В настоящее время будут вызываться точки входа `externalize` всех политик, поэтому реализация должна проверить содержимое `element_name` перед попыткой заполнить `sb`. Если `element_name` не соответствует имени вашей политики, просто верните 0. Возвращайте ненулевое значение только в случае ошибки при внешнем представлении данных метки. После того как политика заполнит `element_data`, `*claimed` должен быть увеличен.

[[mac-mpo-externalize-ifnet-label]]
==== `mpo_externalize_ifnet_label`

[source, c]
----
int mpo_externalize_ifnet_label(struct label *label, char *element_name,
    struct sbuf *sb, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для вынесения во внешний ресурс
| 

|`element_name`
|Имя политики, метка которой должна быть вынесена во внешний ресурс
| 

|`sb`
|Буфер строки для заполнения текстовым представлением метки
| 

|`claimed`
|Должно быть увеличено, когда `element_data` может быть заполнено.
| 
|===

Создать внешнее представление метки на основе переданной структуры метки. Внешнее представление метки состоит из текстового представления содержимого метки, которое может использоваться пользовательскими приложениями и прочитано пользователем. В настоящее время будут вызываться точки входа `externalize` всех политик, поэтому реализация должна проверить содержимое `element_name` перед попыткой заполнить `sb`. Если `element_name` не соответствует имени вашей политики, просто верните 0. Возвращайте ненулевое значение только в случае ошибки при внешнем представлении данных метки. После того как политика заполнит `element_data`, `*claimed` должен быть увеличен.

[[mac-mpo-externalize-pipe-label]]
==== `mpo_externalize_pipe_label`

[source, c]
----
int mpo_externalize_pipe_label(struct label *label, char *element_name,
    struct sbuf *sb, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для вынесения во внешний ресурс
| 

|`element_name`
|Имя политики, метка которой должна быть вынесена во внешний ресурс
| 

|`sb`
|Буфер строки для заполнения текстовым представлением метки
| 

|`claimed`
|Должно быть увеличено, когда `element_data` может быть заполнено.
| 
|===

Создать внешнее представление метки на основе переданной структуры метки. Внешнее представление метки состоит из текстового представления содержимого метки, которое может использоваться пользовательскими приложениями и прочитано пользователем. В настоящее время будут вызываться точки входа `externalize` всех политик, поэтому реализация должна проверить содержимое `element_name` перед попыткой заполнить `sb`. Если `element_name` не соответствует имени вашей политики, просто верните 0. Возвращайте ненулевое значение только в случае ошибки при внешнем представлении данных метки. После того как политика заполнит `element_data`, `*claimed` должен быть увеличен.

[[mac-mpo-externalize-socket-label]]
==== `mpo_externalize_socket_label`

[source, c]
----
int mpo_externalize_socket_label(struct label *label, char *element_name,
    struct sbuf *sb, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для вынесения во внешний ресурс
| 

|`element_name`
|Имя политики, метка которой должна быть вынесена во внешний ресурс
| 

|`sb`
|Буфер строки для заполнения текстовым представлением метки
| 

|`claimed`
|Должно быть увеличено, когда `element_data` может быть заполнено.
| 
|===

Создать внешнее представление метки на основе переданной структуры метки. Внешнее представление метки состоит из текстового представления содержимого метки, которое может использоваться пользовательскими приложениями и прочитано пользователем. В настоящее время будут вызываться точки входа `externalize` всех политик, поэтому реализация должна проверить содержимое `element_name` перед попыткой заполнить `sb`. Если `element_name` не соответствует имени вашей политики, просто верните 0. Возвращайте ненулевое значение только в случае ошибки при внешнем представлении данных метки. После того как политика заполнит `element_data`, `*claimed` должен быть увеличен.

[[mac-mpo-externalize-socket-peer-label]]
==== `mpo_externalize_socket_peer_label`

[source, c]
----
int mpo_externalize_socket_peer_label(struct label *label, char *element_name,
    struct sbuf *sb, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для вынесения во внешний ресурс
| 

|`element_name`
|Имя политики, метка которой должна быть вынесена во внешний ресурс
| 

|`sb`
|Буфер строки для заполнения текстовым представлением метки
| 

|`claimed`
|Должно быть увеличено, когда `element_data` может быть заполнено.
| 
|===

Создать внешнее представление метки на основе переданной структуры метки. Внешнее представление метки состоит из текстового представления содержимого метки, которое может использоваться пользовательскими приложениями и прочитано пользователем. В настоящее время будут вызываться точки входа `externalize` всех политик, поэтому реализация должна проверить содержимое `element_name` перед попыткой заполнить `sb`. Если `element_name` не соответствует имени вашей политики, просто верните 0. Возвращайте ненулевое значение только в случае ошибки при внешнем представлении данных метки. После того как политика заполнит `element_data`, `*claimed` должен быть увеличен.

[[mac-mpo-externalize-vnode-label]]
==== `mpo_externalize_vnode_label`

[source, c]
----
int mpo_externalize_vnode_label(struct label *label, char *element_name,
    struct sbuf *sb, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для вынесения во внешний ресурс
| 

|`element_name`
|Имя политики, метка которой должна быть вынесена во внешний ресурс
| 

|`sb`
|Буфер строки для заполнения текстовым представлением метки
| 

|`claimed`
|Должно быть увеличено, когда `element_data` может быть заполнено.
| 
|===

Создать внешнее представление метки на основе переданной структуры метки. Внешнее представление метки состоит из текстового представления содержимого метки, которое может использоваться пользовательскими приложениями и прочитано пользователем. В настоящее время будут вызываться точки входа `externalize` всех политик, поэтому реализация должна проверить содержимое `element_name` перед попыткой заполнить `sb`. Если `element_name` не соответствует имени вашей политики, просто верните 0. Возвращайте ненулевое значение только в случае ошибки при внешнем представлении данных метки. После того как политика заполнит `element_data`, `*claimed` должен быть увеличен.

[[mac-mpo-internalize-cred-label]]
==== `mpo_internalize_cred_label`

[source, c]
----
int mpo_internalize_cred_label(struct label *label, char *element_name,
    char *element_data, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для заполнения
| 

|`element_name`
|Имя политики, метка которой должна быть приведена к внутреннему представлению
| 

|`element_data`
|Текстовые данные для преобразования к внутреннему представлению
| 

|`claimed`
|Должно увеличиваться, когда данные могут быть успешно преобразовываться вовнутреннее представление.
| 
|===

Создать внутреннюю структуру меток на основе данных метки вов нешнем представлении в текстовом формате. В настоящее время, при запросе преобразования во внутреннее представление вызываются точки входа `internalize` всех политик, поэтому реализация должна сравнивать содержимое `element_name` со своим именем, чтобы убедиться, что она должна преобразовывать данные в `element_data`. Как и в точках входа `externalize`, точка входа должна возвращать 0, если `element_name` не совпадает с её собственным именем, или когда данные могут быть успешно преобразованы, в этом случае `*claimed` должен быть увеличен.

[[mac-mpo-internalize-ifnet-label]]
==== `mpo_internalize_ifnet_label`

[source, c]
----
int mpo_internalize_ifnet_label(struct label *label, char *element_name,
    char *element_data, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для заполнения
| 

|`element_name`
|Имя политики, метка которой должна быть приведена к внутреннему представлению
| 

|`element_data`
|Текстовые данные для преобразования к внутреннему представлению
| 

|`claimed`
|Должно увеличиваться, когда данные могут быть успешно преобразовываться вовнутреннее представление.
| 
|===

Создать внутреннюю структуру меток на основе данных метки вов нешнем представлении в текстовом формате. В настоящее время, при запросе преобразования во внутреннее представление вызываются точки входа `internalize` всех политик, поэтому реализация должна сравнивать содержимое `element_name` со своим именем, чтобы убедиться, что она должна преобразовывать данные в `element_data`. Как и в точках входа `externalize`, точка входа должна возвращать 0, если `element_name` не совпадает с её собственным именем, или когда данные могут быть успешно преобразованы, в этом случае `*claimed` должен быть увеличен.

[[mac-mpo-internalize-pipe-label]]
==== `mpo_internalize_pipe_label`

[source, c]
----
int mpo_internalize_pipe_label(struct label *label, char *element_name,
    char *element_data, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для заполнения
| 

|`element_name`
|Имя политики, метка которой должна быть приведена к внутреннему представлению
| 

|`element_data`
|Текстовые данные для преобразования к внутреннему представлению
| 

|`claimed`
|Должно увеличиваться, когда данные могут быть успешно преобразовываться вовнутреннее представление.
| 
|===

Создать внутреннюю структуру меток на основе данных метки вов нешнем представлении в текстовом формате. В настоящее время, при запросе преобразования во внутреннее представление вызываются точки входа `internalize` всех политик, поэтому реализация должна сравнивать содержимое `element_name` со своим именем, чтобы убедиться, что она должна преобразовывать данные в `element_data`. Как и в точках входа `externalize`, точка входа должна возвращать 0, если `element_name` не совпадает с её собственным именем, или когда данные могут быть успешно преобразованы, в этом случае `*claimed` должен быть увеличен.

[[mac-mpo-internalize-socket-label]]
==== `mpo_internalize_socket_label`

[source, c]
----
int mpo_internalize_socket_label(struct label *label, char *element_name,
    char *element_data, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для заполнения
| 

|`element_name`
|Имя политики, метка которой должна быть приведена к внутреннему представлению
| 

|`element_data`
|Текстовые данные для преобразования к внутреннему представлению
| 

|`claimed`
|Должно увеличиваться, когда данные могут быть успешно преобразовываться вовнутреннее представление.
| 
|===

Создать внутреннюю структуру меток на основе данных метки вов нешнем представлении в текстовом формате. В настоящее время, при запросе преобразования во внутреннее представление вызываются точки входа `internalize` всех политик, поэтому реализация должна сравнивать содержимое `element_name` со своим именем, чтобы убедиться, что она должна преобразовывать данные в `element_data`. Как и в точках входа `externalize`, точка входа должна возвращать 0, если `element_name` не совпадает с её собственным именем, или когда данные могут быть успешно преобразованы, в этом случае `*claimed` должен быть увеличен.

[[mac-mpo-internalize-vnode-label]]
==== `mpo_internalize_vnode_label`

[source, c]
----
int mpo_internalize_vnode_label(struct label *label, char *element_name,
    char *element_data, int *claimed);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`label`
|Метка для заполнения
| 

|`element_name`
|Имя политики, метка которой должна быть приведена к внутреннему представлению
| 

|`element_data`
|Текстовые данные для преобразования к внутреннему представлению
| 

|`claimed`
|Должно увеличиваться, когда данные могут быть успешно преобразовываться вовнутреннее представление.
| 
|===

Создать внутреннюю структуру меток на основе данных метки вов нешнем представлении в текстовом формате. В настоящее время, при запросе преобразования во внутреннее представление вызываются точки входа `internalize` всех политик, поэтому реализация должна сравнивать содержимое `element_name` со своим именем, чтобы убедиться, что она должна преобразовывать данные в `element_data`. Как и в точках входа `externalize`, точка входа должна возвращать 0, если `element_name` не совпадает с её собственным именем, или когда данные могут быть успешно преобразованы, в этом случае `*claimed` должен быть увеличен.

[[mac-label-events]]
=== События метки

Этот класс точек входа используется фреймворком MAC для разрешения политикам поддерживать информацию о метках на объектах ядра. Для каждого помеченного объекта ядра, представляющего интерес для политики MAC, могут быть зарегистрированы точки входа для соответствующих событий жизненного цикла. Все объекты реализуют хуки инициализации, создания и уничтожения. Некоторые объекты также реализуют перемаркировку, позволяя пользовательским процессам изменять метки на объектах. Некоторые объекты также реализуют специфичные для объекта события, такие как события меток, связанные с повторной сборкой IP. Типичный помеченный объект будет иметь следующий жизненный цикл точек входа:

[.programlisting]
....
Label initialization          o
(object-specific wait)         \
Label creation                  o
                                 \
Relabel events,                   o--<--.
Various object-specific,          |     |
Access control events             ~-->--o
                                         \
Label destruction                         o
....

Инициализация меток позволяет политикам выделять память и устанавливать начальные значения для меток без контекста использования объекта. Слот метки, выделенный для политики, по умолчанию будет обнулен, поэтому некоторым политикам может не потребоваться выполнять инициализацию.

Создание метки происходит, когда структура ядра связывается с реальным объектом ядра. Например, Mbuf могут быть выделены и оставаться неиспользованными в пуле до тех пор, пока они не понадобятся. Выделение mbuf приводит к инициализации метки на mbuf, но создание mbuf происходит, когда mbuf связывается с датаграммой. Обычно для события создания предоставляется контекст, включая обстоятельства создания и метки других значимых объектов в процессе создания. Например, когда mbuf создаётся из сокета, сокет и его метка будут переданы зарегистрированным политикам в дополнение к новому mbuf и его метке. Выделение памяти в событиях создания не рекомендуется, так как это может происходить в чувствительных к производительности участках ядра; кроме того, вызовы создания не могут завершиться неудачей, поэтому невозможность выделить память не может быть сообщена.

События, привящанные к объектам, обычно не попадают в другие классы событий меток, но, как правило, предоставляют возможность изменить или обновить метку объекта на основе дополнительного контекста. Например, метка в очереди сборки IP-фрагментов может быть обновлена во время точки входа `MAC_UPDATE_IPQ` в результате принятия дополнительного mbuf в эту очередь.

События контроля доступа подробно рассматриваются в следующем разделе.

Уничтожение метки позволяет политикам освобождать хранилище или состояние, связанное с меткой во время её ассоциации с объектом, чтобы структуры данных ядра, поддерживающие объект, могли быть повторно использованы или освобождены.

В дополнение к меткам, связанным с определёнными объектами ядра, существует дополнительный класс меток: временные метки. Эти метки используются для хранения информации об обновлениях, отправляемых пользовательскими процессами. Они инициализируются и уничтожаются так же, как и другие типы меток, но событие создания — это `MAC_INTERNALIZE`, которое принимает пользовательскую метку для преобразования во внутреннее представление в ядре.

[[mac-fs-label-event-ops]]
==== Действия с событиями меток объектов файловой системы

[[mac-mpo-associate-vnode-devfs]]
===== `mpo_associate_vnode_devfs`

[source, c]
----
void mpo_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
    struct label *vlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mp`
|Точка монтирования devfs
| 

|`fslabel`
|Метка файловой системы devfs (`mp->mnt_fslabel`)
| 

|`de`
|Запись каталога devfs
| 

|`delabel`
|Метка политики, связанная с `de`
| 

|`vp`
|узел vnode, связанный с `de`
| 

|`vlabel`
|Метка политики, связанная с `vp`
| 
|===

Заполнить метку (`vlabel`) для только что созданного devfs vnode на основе записи каталога devfs, переданной в `de`, и её метки.

[[mac-mpo-associate-vnode-extattr]]
===== `mpo_associate_vnode_extattr`

[source, c]
----
int mpo_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
    struct vnode *vp, struct label *vlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mp`
|Точка монтирования файловой системы
| 

|`fslabel`
|Метка файловой системы
| 

|`vp`
|Узел vnode для метки
| 

|`vlabel`
|Метка политики, связанная с `vp`
| 
|===

Попытка получить метку для `vp` из расширенных атрибутов файловой системы. В случае успеха возвращается значение `0`. Если получение расширенных атрибутов не поддерживается, допустимым резервным вариантом является копирование `fslabel` в `vlabel`. В случае ошибки должно быть возвращено соответствующее значение `errno`.

[[mac-mpo-associate-vnode-singlelabel]]
===== `mpo_associate_vnode_singlelabel`

[source, c]
----
void mpo_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel,
    struct vnode *vp, struct label *vlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mp`
|Точка монтирования файловой системы
| 

|`fslabel`
|Метка файловой системы
| 

|`vp`
|Узел vnode для метки
| 

|`vlabel`
|Метка политики, связанная с `vp`
| 
|===

На файловых системах без поддержки multilabel эта точка входа вызывается для установки метки политики для `vp` на основе метки файловой системы `fslabel`.

[[mac-mpo-create-devfs-device]]
===== `mpo_create_devfs_device`

[source, c]
----
void mpo_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
    struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`dev`
|Устройство, соответствующее `devfs_dirent`
| 

|`devfs_dirent`
|Запись в каталоге devfs, для которой создается метка.
| 

|`label`
|Метка для `devfs_dirent`, которую нужно заполнить.
| 
|===

Заполнить метку на devfs_dirent, создаваемом для переданного устройства. Этот вызов будет выполнен при монтировании файловой системы устройств, её восстановлении или при появлении нового устройства.

[[mac-mpo-create-devfs-directory]]
===== `mpo_create_devfs_directory`

[source, c]
----
void mpo_create_devfs_directory(char *dirname, int dirnamelen,
    struct devfs_dirent *devfs_dirent, struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`dirname`
|Имя создаваемого каталога
| 

|`namelen`
|Длина строки `dirname`
| 

|`devfs_dirent`
|Запись в devfs для создаваемого каталога.
| 
|===

Заполнить метку на devfs_dirent, создаваемом для переданного каталога. Этот вызов будет выполнен при монтировании файловой системы устройств, её восстановлении или при появлении нового устройства, требующего определённой иерархии каталогов.

[[mac-mpo-create-devfs-symlink]]
===== `mpo_create_devfs_symlink`

[source, c]
----
void mpo_create_devfs_symlink(struct ucred *cred, struct mount *mp,
    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
    struct label *delabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`mp`
|Точка монтирования devfs
| 

|`dd`
|Назначения cсылки
| 

|`ddlabel`
|Метка, связанная с `dd`
| 

|`de`
|Символьная ссылка записи
| 

|`delabel`
|Метка, связанная с `de`
| 
|===

Заполнить метку (`delabel`) для новой структуры man:devfs[5] символьной ссылки.

[[mac-mpo-create-vnode-extattr]]
===== `mpo_create_vnode_extattr`

[source, c]
----
int mpo_create_vnode_extattr(struct ucred *cred, struct mount *mp,
    struct label *fslabel, struct vnode *dvp, struct label *dlabel,
    struct vnode *vp, struct label *vlabel, struct componentname *cnp);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`mount`
|Точка монтирования файловой системы
| 

|`label`
|Метка файловой системы
| 

|`dvp`
|Родительский каталог vnode
| 

|`dlabel`
|Метка, связанная с `dvp`
| 

|`vp`
|Вновь созданная vnode
| 

|`vlabel`
|Метка политики, связанная с `vp`
| 

|`cnp`
|Название компонента для `vp`
| 
|===

Записать метку для `vp` в соответствующий расширенный атрибут. Если запись прошла успешно, заполняет `vlabel` меткой и возвращает 0. В противном случае вернет соответствующую ошибку.

[[mac-mpo-create-mount]]
===== `mpo_create_mount`

[source, c]
----
void mpo_create_mount(struct ucred *cred, struct mount *mp, struct label *mnt,
    struct label *fslabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`mp`
|Объект; файловая система, которая монтируется
| 

|`mntlabel`
|Метка политики для заполнения в `mp`
| 

|`fslabel`
|Метка политики для файловой системы, монтируемой в `mp`.
| 
|===

Заполнить метки на точке монтирования, создаваемой переданными учетными данными субъекта. Этот вызов будет выполнен при монтировании новой файловой системы.

[[mac-mpo-create-root-mount]]
===== `mpo_create_root_mount`

[source, c]
----
void mpo_create_root_mount(struct ucred *cred, struct mount *mp,
    struct label *mntlabel, struct label *fslabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

3+|См. crossref:mac[mac-mpo-create-mount, `mpo_create_mount`].
|===

Заполнить метки на точке монтирования, создаваемой переданными учетными данными субъекта. Этот вызов будет выполнен при монтировании корневой файловой системы после `mpo_create_mount;`.

[[mac-mpo-relabel-vnode]]
===== `mpo_relabel_vnode`

[source, c]
----
void mpo_relabel_vnode(struct ucred *cred, struct vnode *vp,
    struct label *vnodelabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|vnode для перемаркировки
| 

|`vnodelabel`
|Существующая метка политики для `vp`
| 

|`newlabel`
|Новая, возможно частичная метка для замены `vnodelabel`
| 
|===

Обновить метку на переданном vnode с учетом переданной обновленной метки vnode и переданных учетных данных субъекта.

[[mac-mpo-setlabel-vnode-extattr]]
===== `mpo_setlabel_vnode_extattr`

[source, c]
----
int mpo_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
    struct label *vlabel, struct label *intlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|vnode, для которой записывается метка
| 

|`vlabel`
|Метка политики, связанная с `vp`
| 

|`intlabel`
|Метка для записи
| 
|===

Записать политику из `intlabel` в расширенный атрибут. Этот метод вызывается из `vop_stdcreatevnode_ea`.

[[mac-mpo-update-devfsdirent]]
===== `mpo_update_devfsdirent`

[source, c]
----
void mpo_update_devfsdirent(struct devfs_dirent *devfs_dirent,
    struct label *direntlabel, struct vnode *vp, struct label *vnodelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`devfs_dirent`
|Объект; каталожная запись devfs
| 

|`direntlabel`
|Метка политики для `devfs_dirent`, которая будет обновлена.
| 

|`vp`
|Родительский vnode
|Заблокирован

|`vnodelabel`
|Метка политики для `vp`
| 
|===

Обновить метку `devfs_dirent` из переданной метки devfs vnode. Этот вызов будет выполнен, когда devfs vnode успешно перемаркирован, чтобы зафиксировать изменение метки, чтобы оно сохранилось, даже если vnode будет переиспользован. Он также будет выполнен при создании символьной ссылки в devfs после вызова `mac_vnode_create_from_vnode` для инициализации метки vnode.

[[mac-ipc-label-ops]]
==== Действия с событиями меток объектов IPC

[[mac-mpo-create-mbuf-from-socket]]
===== `mpo_create_mbuf_from_socket`

[source, c]
----
void mpo_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
    struct mbuf *m, struct label *mbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`socket`
|Сокет
|Блокировка сокетов — работа в процессе

|`socketlabel`
|Метка политики для `socket`
| 

|`m`
|Объект; mbuf
| 

|`mbuflabel`
|Метка политики для заполнения для `m`
| 
|===

Установить метку на только что созданном заголовке mbuf из переданной метки сокета. Этот вызов выполняется, когда новый датаграмма или сообщение генерируется сокетом и сохраняется в переданном mbuf.

[[mac-mpo-create-pipe]]
===== `mpo_create_pipe`

[source, c]
----
void mpo_create_pipe(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Метка политики, связанная с `pipe`
| 
|===

Установить метку на только что созданном канале из переданных учетных данных субъекта. Этот вызов выполняется при создании нового канала.

[[mac-mpo-create-socket]]
===== `mpo_create_socket`

[source, c]
----
void mpo_create_socket(struct ucred *cred, struct socket *so,
    struct label *socketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`so`
|Объект; сокет для добавления метки
| 

|`socketlabel`
|Метка для заполнения для `so`
| 
|===

Установить метку на новом сокете из переданных учетных данных субъекта. Этот вызов выполняется при создании сокета.

[[mac-mpo-create-socket-from-socket]]
===== `mpo_create_socket_from_socket`

[source, c]
----
void mpo_create_socket_from_socket(struct socket *oldsocket,
    struct label *oldsocketlabel, struct socket *newsocket,
    struct label *newsocketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`oldsocket`
|Сокет, вызвавший listen
| 

|`oldsocketlabel`
|Метка политики, связанная с `oldsocket`
| 

|`newsocket`
|Новый сокет
| 

|`newsocketlabel`
|Метка политики, связанная с `newsocketlabel`
| 
|===

Создать метку сокета `newsocket`, только что принявшему соединение через man:accept[2], на основе сокета `oldsocket`, вызвавшего man:listen[2] .

[[mac-mpo-relabel-pipe]]
===== `mpo_relabel_pipe`

[source, c]
----
void mpo_relabel_pipe(struct ucred *cred, struct pipe *pipe,
    struct label *oldlabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`oldlabel`
|Текущая метка политики, связанная с `pipe`
| 

|`newlabel`
|Обновление метки политики для применения к `pipe`
| 
|===

Применить новую метку `newlabel` к `pipe`.

[[mac-mpo-relabel-socket]]
===== `mpo_relabel_socket`

[source, c]
----
void mpo_relabel_socket(struct ucred *cred, struct socket *so,
    struct label *oldlabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`so`
|Объект; сокет
| 

|`oldlabel`
|Текущая метка для `so`
| 

|`newlabel`
|Метка обновления для `so`
| 
|===

Обновить метку на сокете из переданного обновления метки сокета.

[[mpo-set-socket-peer-from-mbuf]]
===== `mpo_set_socket_peer_from_mbuf`

[source, c]
----
void mpo_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
    struct label *oldlabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mbuf`
|Первый датаграмм, полученный через сокет
| 

|`mbuflabel`
|Метка для `mbuf`
| 

|`oldlabel`
|Текущая метка для сокета
| 

|`newlabel`
|Метка политики для заполнения сокета
| 
|===

Установить метку однорангового узла на потоковом сокете из переданной метки mbuf. Этот вызов будет выполнен при получении первого датаграммы потоковым сокетом, за исключением сокетов домена Unix.

[[mac-mpo-set-socket-peer-from-socket]]
===== `mpo_set_socket_peer_from_socket`

[source, c]
----
void mpo_set_socket_peer_from_socket(struct socket *oldsocket,
    struct label *oldsocketlabel, struct socket *newsocket,
    struct label *newsocketpeerlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`oldsocket`
|Локальный сокет
| 

|`oldsocketlabel`
|Метка политики для `oldsocket`
| 

|`newsocket`
|Сокет однорангового узла (peer socket)
| 

|`newsocketpeerlabel`
|Метка политики для заполнения для `newsocket`
| 
|===

Установите метку однорангового узла на потоковом UNIX-сокете из переданной конечной точки удаленного сокета. Этот вызов будет выполнен при соединении пары сокетов и будет произведен для обеих конечных точек.

[[mac-net-labeling-event-ops]]
==== Действия с событиями меток сетевых объектов

[[mac-mpo-create-bpfdesc]]
===== `mpo_create_bpfdesc`

[source, c]
----
void mpo_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
    struct label *bpflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`bpf_d`
|Объект; дескриптор bpf
| 

|`bpf`
|Метка политики для заполнения для `bpf_d`
| 
|===

Установить метку на новом дескрипторе BPF из переданных учётных данных субъекта. Этот вызов будет выполнен при открытии узла устройства BPF процессом с переданными учётными данными субъекта.

[[mac-mpo-create-ifnet]]
===== `mpo_create_ifnet`

[source, c]
----
void mpo_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`ifnet`
|Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для заполнения для `ifnet`
| 
|===

Установить метку на вновь созданном интерфейсе. Этот вызов может быть выполнен, когда новое физическое устройство становится доступным системе, или когда псевдо-интерфейс создаётся во время загрузки или в результате действия пользователя.

[[mac-mpo-create-ipq]]
===== `mpo_create_ipq`

[source, c]
----
void mpo_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
    struct ipq *ipq, struct label *ipqlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`fragment`
|Первый полученный IP-фрагмент
| 

|`fragmentlabel`
|Метка политики для `fragment`
| 

|`ipq`
|Очередь повторной сборки IP, которой добавляетя метка
| 

|`ipqlabel`
|Метка политики для заполнения в `ipq`
| 
|===

Установить метку на вновь созданной очереди сборки IP-фрагментов из заголовка mbuf первого полученного фрагмента.

[[mac-mpo-create-datagram-from-ipq]]
===== `mpo_create_datagram_from_ipq`

[source, c]
----
void mpo_create_create_datagram_from_ipq(struct ipq *ipq,
    struct label *ipqlabel, struct mbuf *datagram, struct label *datagramlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`ipq`
|Очередь повторной сборки IP
| 

|`ipqlabel`
|Метка политики для `ipq`
| 

|`datagram`
|Датаграмма для добавления метки
| 

|`datagramlabel`
|Метка политики для заполнения в `datagramlabel`
| 
|===

Установите метку на вновь собранный IP-датаграмму из очереди сборки IP-фрагментов, из которой он был сгенерирован.

[[mac-mpo-create-fragment]]
===== `mpo_create_fragment`

[source, c]
----
void mpo_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
    struct mbuf *fragment, struct label *fragmentlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`datagram`
|Датаграмма
| 

|`datagramlabel`
|Метка политики для `datagram`
| 

|`fragment`
|Фрагмент, которому будет установлена метка
| 

|`fragmentlabel`
|Метка политики для заполнения для `datagram`
| 
|===

Установить метку на заголовке mbuf вновь созданного IP-фрагмента из метки на заголовке mbuf датаграммы, из которой он был сгенерирован.

[[mac-mpo-create-mbuf-from-mbuf]]
===== `mpo_create_mbuf_from_mbuf`

[source, c]
----
void mpo_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct label *oldmbuflabel,
    struct mbuf *newmbuf, struct label *newmbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`oldmbuf`
|Существующий (исходный) mbuf
| 

|`oldmbuflabel`
|Метка политики для `oldmbuf`
| 

|`newmbuf`
|Новый mbuf для добавления метки
| 

|`newmbuflabel`
|Метка политики для заполнения в `newmbuf`
| 
|===

Установить метку в заголовке mbuf для вновь созданной датаграммы на основе заголовка mbuf существующей датаграммы. Этот вызов может быть выполнен в ряде ситуаций, включая случаи, когда для mbuf заново выделяется память для целей выравнивания.

[[mac-mpo-create-mbuf-linklayer]]
===== `mpo_create_mbuf_linklayer`

[source, c]
----
void mpo_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
    struct mbuf *mbuf, struct label *mbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`ifnet`
|Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnet`
| 

|`mbuf`
|заголовок mbuf для новой датаграммы
| 

|`mbuflabel`
|Метка политики для заполнения для `mbuf`
| 
|===

Установить метку в заголовке mbuf для вновь созданной датаграммы, сгенерированного для целей ответа на канальном уровне для переданного интерфейса. Этот вызов может быть выполнен в ряде ситуаций, включая ответы ARP или ND6 в стеках IPv4 и IPv6.

[[mac-mpo-create-mbuf-from-bpfdesc]]
===== `mpo_create_mbuf_from_bpfdesc`

[source, c]
----
void mpo_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
    struct mbuf *mbuf, struct label *mbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`bpf_d`
|Дескриптор BPF
| 

|`bpflabel`
|Метка политики для `bpflabel`
| 

|`mbuf`
|Новый mbuf для добавления метки
| 

|`mbuflabel`
|Метка политики для заполнения `mbuf`
| 
|===

Установить метку на заголовок mbuf вновь созданной датаграммы, сгенерированной с использованием переданного дескриптора BPF. Этот вызов выполняется при записи в устройство BPF, связанное с переданным дескриптором BPF.

[[mac-mpo-create-mbuf-from-ifnet]]
===== `mpo_create_mbuf_from_ifnet`

[source, c]
----
void mpo_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
    struct mbuf *mbuf, struct label *mbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`ifnet`
|Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnetlabel`
| 

|`mbuf`
|заголовок mbuf для новой датаграммы
| 

|`mbuflabel`
|Метка политики для заполнения для `mbuf`
| 
|===

Установить метку на заголовке mbuf вновь созданной датаграммы, сгенерированной из переданного сетевого интерфейса.

[[mac-mpo-create-mbuf-multicast-encap]]
===== `mpo_create_mbuf_multicast_encap`

[source, c]
----
void mpo_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
    struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
    struct mbuf *newmbuf, struct label *newmbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`oldmbuf`
|Заголовок mbuf для существующего датаграммы
| 

|`oldmbuflabel`
|Метка политики для `oldmbuf`
| 

|`ifnet`
|Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnet`
| 

|`newmbuf`
|Заголовок mbuf для пометки новой датаграммы
| 

|`newmbuflabel`
|Метка политики для заполнения в `newmbuf`
| 
|===

Установить метку в заголовке mbuf для вновь созданной датаграммы, сгенерированной из существующей переданной датаграммы, при её обработке переданным интерфейсом мультикастовой инкапсуляции. Этот вызов происходит при доставке mbuf с использованием виртуального интерфейса.

[[mac-mpo-create-mbuf-netlayer]]
===== `mpo_create_mbuf_netlayer`

[source, c]
----
void mpo_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
    struct mbuf *newmbuf, struct label *newmbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`oldmbuf`
|Полученная датаграмма
| 

|`oldmbuflabel`
|Метка политики для `oldmbuf`
| 

|`newmbuf`
|Вновь созданная датаграмма
| 

|`newmbuflabel`
|Метка политики для `newmbuf`
| 
|===

Установить метку на заголовок mbuf вновь созданной датаграммы, сгенерированной стеком IP в ответ на полученную датаграмму (`oldmbuf`). Этот вызов может быть выполнен в различных ситуациях, включая ответ на датаграммы ICMP-запросов.

[[mac-mpo-fragment-match]]
===== `mpo_fragment_match`

[source, c]
----
int mpo_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
    struct ipq *ipq, struct label *ipqlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`fragment`
|Фрагмент IP-датаграммы
| 

|`fragmentlabel`
|Метка политики для `fragment`
| 

|`ipq`
|Очередь сборки IP-фрагментов
| 

|`ipqlabel`
|Метка политики для `ipq`
| 
|===

Определить, соответствует ли заголовок mbuf, содержащий фрагмент IP-датаграммы (`fragment`), метке переданной очереди сборки IP-фрагментов (`ipq`). Возвращает (1) при успешном совпадении или (0) при отсутствии совпадения. Этот вызов выполняется, когда IP-стек пытается найти существующую очередь сборки фрагментов для вновь полученного фрагмента; если поиск не удаётся, для фрагмента может быть создана новая очередь сборки. Политики могут использовать эту точку входа, чтобы предотвратить сборку в остальном подходящих IP-фрагментов, если политика не разрешает их сборку на основе метки или другой информации.

[[mac-mpo-ifnet-relabel]]
===== `mpo_relabel_ifnet`

[source, c]
----
void mpo_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
    struct label *ifnetlabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`ifnet`
|Объект; Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnet`
| 

|`newlabel`
|Метка обновления для применения к `ifnet`
| 
|===

Обновить метку сетевого интерфейса, `ifnet`, на основе переданной новой метки, `newlabel`, и переданных учетных данных субъекта, `cred`.

[[mac-mpo-update-ipq]]
===== `mpo_update_ipq`

[source, c]
----
void mpo_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
    struct ipq *ipq, struct label *ipqlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`mbuf`
|IP фрагмент
| 

|`mbuflabel`
|Метка политики для `mbuf`
| 

|`ipq`
|Очередь сборки IP-фрагментов
| 

|`ipqlabel`
|Метка политики для обновления для `ipq`
| 
|===

Обновить метку в очереди сборки IP-фрагментов (`ipq`) на основе принятия переданного заголовка IP-фрагмента mbuf (`mbuf`).

[[mac-proc-labeling-event-ops]]
==== Действия с событиями меток процессов

[[mac-mpo-create-cred]]
===== `mpo_create_cred`

[source, c]
----
void mpo_create_cred(struct ucred *parent_cred, struct ucred *child_cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`parent_cred`
|Учетные данные субъекта‐родителя
| 

|`child_cred`
|Учётные данные дочернего субъекта
| 
|===

Установить метку вновь созданного субъекта из переданного субъекта. Этот вызов будет выполнен при вызове man:crcopy[9] для только что созданной структуры `struct ucred`. Этот вызов не следует путать с событием создания или ветвления процесса.

[[mac-mpo-execve-transition]]
===== `mpo_execve_transition`

[source, c]
----
void mpo_execve_transition(struct ucred *old, struct ucred *new,
    struct vnode *vp, struct label *vnodelabel);

----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`old`
|Учетные данные существующего субъекта
|Неизменяемый

|`new`
|Учетные данные нового субъекта для добавления метки
| 

|`vp`
|Файл для выполнения
|Заблокирован

|`vnodelabel`
|Метка политики для `vp`
| 
|===

Обновить метку учетных данных вновь созданного субъекта (`new`) на основе переданных учетных данных существующего субъекта (`old`) в соответствии с переходом метки, вызванным выполнением переданного vnode (`vp`). Этот вызов происходит, когда процесс выполняет переданный vnode, и одна из политик возвращает успех из точки входа `mpo_execve_will_transition`. Политики могут выбрать реализацию этого вызова просто путем вызова `mpo_create_cred` и передачи двух субъектов учетных данных, чтобы не реализовывать событие перехода. Политики не должны оставлять эту точку входа нереализованной, если они реализуют `mpo_create_cred`, даже если они не реализуют `mpo_execve_will_transition`.

[[mac-mpo-execve-will-transition]]
===== `mpo_execve_will_transition`

[source, c]
----
int mpo_execve_will_transition(struct ucred *old, struct vnode *vp,
    struct label *vnodelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`old`
|Учетные данные субъекта перед man:execve[2]
|Неизменяемый

|`vp`
|Файл для выполнения
| 

|`vnodelabel`
|Метка политики для `vp`
| 
|===

Определить, будет ли политика выполнять событие перехода в результате выполнения переданного vnode с использованием переданных учетных данных субъекта. Вернуть 1, если переход требуется, и 0, если нет. Даже если политика возвращает 0, она должна корректно обрабатывать неожиданный вызов `mpo_execve_transition`, так как этот вызов может произойти из-за запроса перехода другой политикой.

[[mac-mpo-create-proc0]]
===== `mpo_create_proc0`

[source, c]
----
void mpo_create_proc0(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта для заполнения
| 
|===

Создать учетные данные субъекта процесса 0, родителя всех процессов ядра.

[[mac-mpo-create-proc1]]
===== `mpo_create_proc1`

[source, c]
----
void mpo_create_proc1(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта для заполнения
| 
|===

Создать учетные данные субъекта процесса 1, родителя всех пользовательских процессов.

[[mac-mpo-relabel-cred]]
===== `mpo_relabel_cred`

[source, c]
----
void mpo_relabel_cred(struct ucred *cred, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`newlabel`
|Обновление метки для применения к `cred`
| 
|===

Обновить метку на учетных данных субъекта из переданной обновляемой метки.

[[mac-access-control-checks]]
=== Проверки контроля доступа

Точки входа контроля доступа позволяют модулям политики влиять на решения по контролю доступа, принимаемые ядром. Обычно, хотя и не всегда, аргументы точки входа контроля доступа включают одно или несколько удостоверяющих полномочий, информацию (возможно, включая метку) для любых других объектов, участвующих в операции. Точка входа контроля доступа может вернуть 0 для разрешения операции или значение ошибки man:errno[2]. Результаты вызова точки входа через различные зарегистрированные модули политики будут объединены следующим образом: если все модули разрешают успешное выполнение операции, будет возвращен успех. Если один или несколько модулей возвращают ошибку, будет возвращена ошибка. Если более одного модуля возвращают ошибку, значение errno, которое будет возвращено пользователю, выбирается с использованием следующего приоритета, реализованного функцией `error_select()` в [.filename]#kern_mac.c#:

[.informaltable]
[cols="1,1", frame="none"]
|===

|Наивысший приоритет
|EDEADLK

| 
|EINVAL

| 
|ESRCH

| 
|EACCES

|Наименьший приоритет
|EPERM
|===

Если ни одно из значений ошибок, возвращаемых всеми модулями, не указано в таблице приоритетов, будет возвращено произвольно выбранное значение из набора. В общем случае правила устанавливают следующий порядок приоритетов ошибок: сбои ядра, неверные аргументы, отсутствие объекта, отсутствие доступа, прочие.

[[mac-mpo-bpfdesc-check-receive-from-ifnet]]
==== `mpo_check_bpfdesc_receive`

[source, c]
----
int mpo_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
    struct ifnet *ifnet, struct label *ifnetlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`bpf_d`
|Субъект; Дескриптор BPF
| 

|`bpflabel`
|Метка политики для `bpf_d`
| 

|`ifnet`
|Объект; сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnet`
| 
|===

Определить, должен ли framework MAC разрешать доставку датаграмм с переданного интерфейса в буферы переданного BPF-дескриптора. Возвращает (0) при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии меток, EPERM при отсутствии привилегий.

[[mac-mpo-check-kenv-dump]]
==== `mpo_check_kenv_dump`

[source, c]
----
int mpo_check_kenv_dump(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 
|===

Определить, следует ли разрешить субъекту получать доступ к окружению ядра (см. man:kenv[2]).

[[mac-mpo-check-kenv-get]]
==== `mpo_check_kenv_get`

[source, c]
----
int mpo_check_kenv_get(struct ucred *cred, char *name);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`name`
|Имя переменной окружения ядра
| 
|===

Определить, следует ли разрешить субъекту получать значение указанной переменной окружения ядра.

[[mac-mpo-check-kenv-set]]
==== `mpo_check_kenv_set`

[source, c]
----
int mpo_check_kenv_set(struct ucred *cred, char *name);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`name`
|Имя переменной окружения ядра
| 
|===

Определить, следует ли разрешить субъекту устанавливать указанную переменную окружения ядра.

[[mac-mpo-check-kenv-unset]]
==== `mpo_check_kenv_unset`

[source, c]
----
int mpo_check_kenv_unset(struct ucred *cred, char *name);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`name`
|Имя переменной окружения ядра
| 
|===

Определить, следует ли разрешить субъекту сбросить указанную переменную окружения ядра.

[[mac-mpo-check-kld-load]]
==== `mpo_check_kld_load`

[source, c]
----
int mpo_check_kld_load(struct ucred *cred, struct vnode *vp,
    struct label *vlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|vnode модуля ядра
| 

|`vlabel`
|Метка, связанная с `vp`
| 
|===

Определить, следует ли разрешить субъекту загружать указанный файл модуля.

[[mac-mpo-check-kld-stat]]
==== `mpo_check_kld_stat`

[source, c]
----
int mpo_check_kld_stat(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 
|===

Определить, следует ли разрешить субъекту получать список загруженных файлов модулей ядра и связанную с ними статистику.

[[mac-mpo-check-kld-unload]]
==== `mpo_check_kld_unload`

[source, c]
----
int mpo_check_kld_unload(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 
|===

Определить, следует ли разрешить субъекту выгружать модуль ядра.

[[mac-mpo-check-pipe-ioctl]]
==== `mpo_check_pipe_ioctl`

[source, c]
----
int mpo_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel, unsigned long cmd, void *data);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Метка политики, связанная с `pipe`
| 

|`cmd`
|команда nman:ioctl[2]
| 

|`data`
|данные man:ioctl[2]
| 
|===

Определить, следует ли разрешить субъекту выполнять указанный вызов man:ioctl[2].

[[mac-mpo-check-pipe-poll]]
==== `mpo_check_pipe_poll`

[source, c]
----
int mpo_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Метка политики, связанная с `pipe`
| 
|===

Определить, следует ли разрешить субъекту опрашивать `pipe`.

[[mac-mpo-check-pipe-read]]
==== `mpo_check_pipe_read`

[source, c]
----
int mpo_check_pipe_read(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Метка политики, связанная с `pipe`
| 
|===

Определить, следует ли разрешить субъекту доступ на чтение к `pipe`.

[[mac-mpo-check-pipe-relabel]]
==== `mpo_check_pipe_relabel`

[source, c]
----
int mpo_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Текущая метка политики, связанная с `pipe`
| 

|`newlabel`
|Обновление метки до `pipelabel`
| 
|===

Определить, следует ли разрешить субъекту изменять метку `pipe`.

[[mac-mpo-check-pipe-stat]]
==== `mpo_check_pipe_stat`

[source, c]
----
int mpo_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Метка политики, связанная с `pipe`
| 
|===

Определить, следует ли разрешить субъекту получать статистику, связанную с `pipe`.

[[mac-mpo-check-pipe-write]]
==== `mpo_check_pipe_write`

[source, c]
----
int mpo_check_pipe_write(struct ucred *cred, struct pipe *pipe,
    struct label *pipelabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`pipe`
|Канал
| 

|`pipelabel`
|Метка политики, связанная с `pipe`
| 
|===

Определить, следует ли разрешить субъекту запись в `pipe`.

[[mac-mpo-cred-check-socket-bind]]
==== `mpo_check_socket_bind`

[source, c]
----
int mpo_check_socket_bind(struct ucred *cred, struct socket *socket,
    struct label *socketlabel, struct sockaddr *sockaddr);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`socket`
|Сокет для привязки
| 

|`socketlabel`
|Метка политики для `socket`
| 

|`sockaddr`
|Адрес `socket`
| 
|===

[[mac-mpo-cred-check-socket-connect]]
==== `mpo_check_socket_connect`

[source, c]
----
int mpo_check_socket_connect(struct ucred *cred, struct socket *socket,
    struct label *socketlabel, struct sockaddr *sockaddr);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`socket`
|Сокет для подключения
| 

|`socketlabel`
|Метка политики для `socket`
| 

|`sockaddr`
|Адрес `socket`
| 
|===

Определить, может ли субъект с учётными данными (`cred`) подключить переданный сокет (`socket`) к переданному адресу сокета (`sockaddr`). Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии меток, EPERM при отсутствии прав.

[[mac-mpo-check-socket-receive]]
==== `mpo_check_socket_receive`

[source, c]
----
int mpo_check_socket_receive(struct ucred *cred, struct socket *so,
    struct label *socketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`so`
|Сокет
| 

|`socketlabel`
|Метка политики, связанная с `so`
| 
|===

Определить, следует ли разрешить субъекту получать информацию из сокета `so`.

[[mac-mpo-check-socket-send]]
==== `mpo_check_socket_send`

[source, c]
----
int mpo_check_socket_send(struct ucred *cred, struct socket *so,
    struct label *socketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`so`
|Сокет
| 

|`socketlabel`
|Метка политики, связанная с `so`
| 
|===

Определить, следует ли разрешить субъекту передавать информацию через сокет `so`.

[[mac-mpo-check-cred-visible]]
==== `mpo_check_cred_visible`

[source, c]
----
int mpo_check_cred_visible(struct ucred *u1, struct ucred *u2);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`u1`
|Учетные данные субъекта
| 

|`u2`
|Учетные данные объекта
| 
|===

Определить, может ли субъект с учётными данными `u1` "видеть" другие субъекты с переданными учётными данными `u2`. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии меток, EPERM при отсутствии привилегий или ESRCH для скрытия видимости. Этот вызов может выполняться в различных ситуациях, включая системные вызовы состояния межпроцессного взаимодействия, используемые `ps`, и при поиске в procfs.

[[mac-mpo-cred-check-socket-visible]]
==== `mpo_check_socket_visible`

[source, c]
----
int mpo_check_socket_visible(struct ucred *cred, struct socket *socket,
    struct label *socketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`socket`
|Объект; сокет
| 

|`socketlabel`
|Метка политики для `socket`
| 
|===

[[mac-mpo-cred-check-ifnet-relabel]]
==== `mpo_check_ifnet_relabel`

[source, c]
----
int mpo_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
    struct label *ifnetlabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`ifnet`
|Объект; сетевой интерфейс
| 

|`ifnetlabel`
|Существующая метка политики для `ifnet`
| 

|`newlabel`
|Обновление метки политики для последующего применения к `ifnet`
| 
|===

Определить, может ли учетные данные субъекта перемаркировать переданный сетевой интерфейс в соответствии с переданным обновлением метки.

[[mac-mpo-cred-check-socket-relabel]]
==== `mpo_check_socket_relabel`

[source, c]
----
int mpo_check_socket_relabel(struct ucred *cred, struct socket *socket,
    struct label *socketlabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`socket`
|Объект; сокет
| 

|`socketlabel`
|Метка существующей политики для `socket`
| 

|`newlabel`
|Обновление метки для последующего применения к `socketlabel`
| 
|===

Определить, могут ли учётные данные субъекта перемаркировать переданный сокет в соответствии с переданным обновлением метки.

[[mac-mpo-cred-check-cred-relabel]]
==== `mpo_check_cred_relabel`

[source, c]
----
int mpo_check_cred_relabel(struct ucred *cred, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`newlabel`
|Обновление метки для последующего применения к `cred`
| 
|===

Определить, могут ли учетные данные субъекта перемаркировать себя в соответствии с переданным обновлением метки.

[[mac-mpo-cred-check-vnode-relabel]]
==== `mpo_check_vnode_relabel`

[source, c]
----
int mpo_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
    struct label *vnodelabel, struct label *newlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`vp`
|Объект; vnode
|Заблокирован

|`vnodelabel`
|Существующая метка политики для `vp`
| 

|`newlabel`
|Обновление метки политики для последующего применения к `vp`
| 
|===

Определить, могут ли учётные данные субъекта изменить метку переданного vnode на переданную обновлённую метку.

[[mpo-cred-check-mount-stat]]
==== `mpo_check_mount_stat`

[source, c]
----
int mpo_check_mount_stat(struct ucred *cred, struct mount *mp,
    struct label *mountlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`mp`
|Объект; точка монтирования файловой системы
| 

|`mountlabel`
|Метка политики для `mp`
| 
|===

Определить, могут ли учетные данные субъекта видеть результаты выполнения statfs для файловой системы. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии меток или EPERM при отсутствии привилегий. Этот вызов может выполняться в различных ситуациях, включая вызовы man:statfs[2] и связанных функций, а также для определения, какие файловые системы исключать из списка, например, при вызове man:getfsstat[2].

[[mac-mpo-cred-check-proc-debug]]
==== `mpo_check_proc_debug`

[source, c]
----
int mpo_check_proc_debug(struct ucred *cred, struct proc *proc);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`proc`
|Объект; процесс
| 
|===

Определить, могут ли учётные данные субъекта отлаживать переданный процесс. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки, EPERM при недостатке прав или ESRCH для скрытия видимости цели. Этот вызов может использоваться в различных ситуациях, включая использование API man:ptrace[2] и man:ktrace[2], а также для некоторых операций с procfs.

[[mac-mpo-cred-check-vnode-access]]
==== `mpo_check_vnode_access`

[source, c]
----
int mpo_check_vnode_access(struct ucred *cred, struct vnode *vp,
    struct label *label, int flags);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`flags`
|флаги man:access[2]
| 
|===

Определить, как должны возвращаться вызовы man:access[2] и связанные вызовы для субъекта с указанными учетными данными при выполнении на переданном vnode с использованием переданных флагов доступа. Обычно это должно быть реализовано с использованием той же семантики, что и в `mpo_check_vnode_open`. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии меток или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-chdir]]
==== `mpo_check_vnode_chdir`

[source, c]
----
int mpo_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|Объект; vnode, в который делается man:chdir[2]
| 

|`dlabel`
|Метка политики для `dvp`
| 
|===

Определить, могут ли учётные данные субъекта изменить рабочий каталог процесса на переданный vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-check-vnode-chroot]]
==== `mpo_check_vnode_chroot`

[source, c]
----
int mpo_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|vnode каталога
| 

|`dlabel`
|Метка политики, связанная с `dvp`
| 
|===

Определить, следует ли разрешить субъекту выполнять man:chroot[2] в указанный каталог (`dvp`).

[[mac-mpo-cred-check-vnode-create]]
==== `mpo_check_vnode_create`

[source, c]
----
int mpo_check_vnode_create(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel, struct componentname *cnp, struct vattr *vap);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|Объект; vnode
| 

|`dlabel`
|Метка политики для `dvp`
| 

|`cnp`
|Название компонента для `dvp`
| 

|`vap`
|атрибуты vnode для `vap`
| 
|===

Определить, могут ли учетные данные субъекта создать vnode с указанной родительской директорией, информацией о имени и атрибутами. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий. Этот вызов может выполняться в различных ситуациях, включая вызовы man:open[2] с O_CREAT, man:mkfifo[2] и другие.

[[mac-mpo-cred-check-vnode-delete]]
==== `mpo_check_vnode_delete`

[source, c]
----
int mpo_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel, struct vnode *vp, void *label,
    struct componentname *cnp);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|Родительский каталог vnode
| 

|`dlabel`
|Метка политики для `dvp`
| 

|`vp`
|Объект; vnode для удаления
| 

|`label`
|Метка политики для `vp`
| 

|`cnp`
|Название компонента для `vp`
| 
|===

Определить, может ли субъект с данными учетными данными удалить vnode из переданного родительского каталога и переданной информации о имени. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий. Этот вызов может быть выполнен в различных ситуациях, включая вызовы man:unlink[2] и man:rmdir[2]. Политики, реализующие эту точку входа, также должны реализовывать `mpo_check_rename_to` для авторизации удаления объектов в результате их переименования.

[[mac-mpo-cred-check-vnode-deleteacl]]
==== `mpo_check_vnode_deleteacl`

[source, c]
----
int mpo_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
    struct label *label, acl_type_t type);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`vp`
|Объект; vnode
|Заблокирован

|`label`
|Метка политики для `vp`
| 

|`type`
|Тип ACL
| 
|===

Определить, могут ли учетные данные субъекта удалить ACL указанного типа из переданного vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-exec]]
==== `mpo_check_vnode_exec`

[source, c]
----
int mpo_check_vnode_exec(struct ucred *cred, struct vnode *vp,
    struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode для выполнения
| 

|`label`
|Метка политики для `vp`
| 
|===

Определить, могут ли учётные данные субъекта выполнить переданный vnode. Проверка права на выполнение осуществляется отдельно от решений о любом переходном событии. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии прав.

[[mpo-cred-check-vnode-getacl]]
==== `mpo_check_vnode_getacl`

[source, c]
----
int mpo_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
    struct label *label, acl_type_t type);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`type`
|Тип ACL
| 
|===

Определить, может ли учётное данное субъекта получить ACL указанного типа из переданного vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-getextattr]]
==== `mpo_check_vnode_getextattr`

[source, c]
----
int mpo_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
    struct label *label, int attrnamespace, const char *name, struct uio *uio);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`attrnamespace`
|Пространство имен расширенных атрибутов
| 

|`name`
|Имя расширенного атрибута
| 

|`uio`
|Указатель структуры ввода-вывода; см. man:uio[9]
| 
|===

Определить, может ли субъект с указанными учетными данными получить расширенный атрибут с заданным пространством имен и именем из указанного vnode. Политики, реализующие маркировку с использованием расширенных атрибутов, могут требовать особой обработки операций с этими атрибутами. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-check-vnode-link]]
==== `mpo_check_vnode_link`

[source, c]
----
int mpo_check_vnode_link(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel, struct vnode *vp, struct label *label,
    struct componentname *cnp);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|vnode каталога
| 

|`dlabel`
|Метка политики, связанная с `dvp`
| 

|`vp`
|vnode целевого линка
| 

|`label`
|Метка политики, связанная с `vp`
| 

|`cnp`
|Имя компонента для создаваемой ссылки
| 
|===

Определить, следует ли разрешить субъекту создавать ссылку на vnode `vp` с именем, указанным в `cnp`.

[[mac-mpo-check-vnode-mmap]]
==== `mpo_check_vnode_mmap`

[source, c]
----
int mpo_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
    struct label *label, int prot);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|vnode для mmap
| 

|`label`
|Метка политики, связанная с `vp`
| 

|`prot`
|Защита mmap (см. man:mmap[2])
| 
|===

Определить, следует ли разрешить субъекту отображать vnode `vp` с указанными в `prot` правами доступа.

[[mac-mpo-check-vnode-mmap-downgrade]]
==== `mpo_check_vnode_mmap_downgrade`

[source, c]
----
void mpo_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
    struct label *label, int *prot);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|См. crossref:mac[mac-mpo-check-vnode-mmap, `mpo_check_vnode_mmap`].
| 

|`vp`
| 
| 

|`label`
| 
| 

|`prot`
|Защита mmap для понижения уровня
| 
|===

Понизить уровень защиты mmap на основе меток субъекта и объекта.

[[mac-mpo-check-vnode-mprotect]]
==== `mpo_check_vnode_mprotect`

[source, c]
----
int mpo_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
    struct label *label, int prot);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Отображенный vnode
| 

|`prot`
|Защита памяти
| 
|===

Определить, следует ли разрешить субъекту устанавливать указанные защиты памяти для памяти, отображенной из vnode `vp`.

[[mac-mpo-check-vnode-poll]]
==== `mpo_check_vnode_poll`

[source, c]
----
int mpo_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
    struct vnode *vp, struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`active_cred`
|Учетные данные субъекта
| 

|`file_cred`
|Учетные данные, связанные со структурой file
| 

|`vp`
|vnode, на котором вызывается poll
| 

|`label`
|Метка политики, связанная с `vp`
| 
|===

Определить, следует ли разрешить субъекту вызывать poll на vnode `vp`.

[[mac-mpo-check-vnode-rename-from]]
==== `mpo_check_vnode_rename_from`

[source, c]
----
int mpo_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel, struct vnode *vp, struct label *label,
    struct componentname *cnp);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|vnode каталога
| 

|`dlabel`
|Метка политики, связанная с `dvp`
| 

|`vp`
|vnode для переименования
| 

|`label`
|Метка политики, связанная с `vp`
| 

|`cnp`
|Название компонента для `vp`
| 
|===

Определить, следует ли разрешить субъекту переименовать vnode `vp` во что-то другое.

[[mac-mpo-check-vnode-rename-to]]
==== `mpo_check_vnode_rename_to`

[source, c]
----
int mpo_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
    struct componentname *cnp);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|vnode каталога
| 

|`dlabel`
|Метка политики, связанная с `dvp`
| 

|`vp`
|vnode, который будет перезаписан
| 

|`label`
|Метка политики, связанная с `vp`
| 

|`samedir`
|Логическое значение; `1`, если исходный и целевой каталоги совпадают
| 

|`cnp`
|Имя компонента назначения
| 
|===

Определить, следует ли разрешить субъекту переименование vnode `vp` в директорию `dvp` или в имя, представленное `cnp`. Если не существует файла для перезаписи, `vp` и `label` будут NULL.

[[mac-mpo-cred-check-socket-listen]]
==== `mpo_check_socket_listen`

[source, c]
----
int mpo_check_socket_listen(struct ucred *cred, struct socket *socket,
    struct label *socketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`socket`
|Объект; сокет
| 

|`socketlabel`
|Метка политики для `socket`
| 
|===

Определить, могут ли учётные данные субъекта прослушивать переданный сокет (вызывать listen). Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-lookup]]
==== `mpo_check_vnode_lookup`

[source, c]
----
int mpo_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel, struct componentname *cnp);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|Объект; vnode
| 

|`dlabel`
|Метка политики для `dvp`
| 

|`cnp`
|Имя компонента, который ищется
| 
|===

Определить, могут ли учётные данные субъекта выполнить поиск указанного имени в каталог с переданном vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-open]]
==== `mpo_check_vnode_open`

[source, c]
----
int mpo_check_vnode_open(struct ucred *cred, struct vnode *vp,
    struct label *label, int acc_mode);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`acc_mode`
|режим доступа от man:open[2]
| 
|===

Определить, могут ли учетные данные субъекта выполнить операцию открытия переданного vnode с указанным режимом доступа. Возвращает 0 в случае успеха или значение errno при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-readdir]]
==== `mpo_check_vnode_readdir`

[source, c]
----
int mpo_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
    struct label *dlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`dvp`
|Объект; vnode каталога
| 

|`dlabel`
|Метка политики для `dvp`
| 
|===

Определить, могут ли учетные данные субъекта выполнить операцию `readdir` для переданного vnode каталога. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-readlink]]
==== `mpo_check_vnode_readlink`

[source, c]
----
int mpo_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
    struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 
|===

Определить, могут ли учетные данные субъекта выполнить операцию `readlink` для переданного символьного vnode. Возвращает 0 в случае успеха или значение `errno` в случае ошибки. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий. Этот вызов может быть выполнен в различных ситуациях, включая явный вызов `readlink` пользовательским процессом или неявный `readlink` во время поиска имени процессом.

[[mac-mpo-cred-check-vnode-revoke]]
==== `mpo_check_vnode_revoke`

[source, c]
----
int mpo_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
    struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 
|===

Определить, могут ли учётные данные субъекта отозвать доступ к переданному vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-setacl]]
==== `mpo_check_vnode_setacl`

[source, c]
----
int mpo_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
    struct label *label, acl_type_t type, struct acl *acl);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`type`
|Тип ACL
| 

|`acl`
|ACL
| 
|===

Определить, могут ли учётные данные субъекта установить переданный ACL указанного типа для переданного vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-setextattr]]
==== `mpo_check_vnode_setextattr`

[source, c]
----
int mpo_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
    struct label *label, int attrnamespace, const char *name, struct uio *uio);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`attrnamespace`
|Пространство имен расширенных атрибутов
| 

|`name`
|Имя расширенного атрибута
| 

|`uio`
|Указатель структуры ввода-вывода; см. man:uio[9]
| 
|===

Определить, могут ли учетные данные субъекта установить расширенный атрибут с переданным именем и пространством имен на переданном vnode. Политики, реализующие метки безопасности, основанные на расширенных атрибутах, могут предусматривать дополнительные защиты для этих атрибутов. Кроме того, политикам следует избегать принятия решений на основе данных, на которые ссылается `uio`, так как существует потенциальное состояние гонки между этой проверкой и фактической операцией. `uio` также может быть `NULL`, если выполняется операция удаления. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-setflags]]
==== `mpo_check_vnode_setflags`

[source, c]
----
int mpo_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
    struct label *label, u_long flags);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`flags`
|Флаги файла; см. man:chflags[2]
| 
|===

Определить, могут ли учётные данные субъекта установить переданные флаги на переданном vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-setmode]]
==== `mpo_check_vnode_setmode`

[source, c]
----
int mpo_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
    struct label *label, mode_t mode);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`mode`
|Режим файла; см. man:chmod[2]
| 
|===

Определить, могут ли учётные данные субъекта установить переданный режим для переданного vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при недостатке привилегий.

[[mac-mpo-cred-check-vnode-setowner]]
==== `mpo_check_vnode_setowner`

[source, c]
----
int mpo_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
    struct label *label, uid_t uid, gid_t gid);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 

|`uid`
|User ID
| 

|`gid`
|Идентификатор группы
| 
|===

Определить, могут ли учетные данные субъекта установить переданный uid и переданный gid в качестве uid файла и gid файла для переданного vnode. Идентификаторы могут быть установлены в (`-1`) для запроса отсутствия обновления. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-vnode-setutimes]]
==== `mpo_check_vnode_setutimes`

[source, c]
----
int mpo_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
    struct label *label, struct timespec atime, struct timespec mtime);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vp
| 

|`label`
|Метка политики для `vp`
| 

|`atime`
|Время доступа; см. man:utimes[2]
| 

|`mtime`
|Время изменения; см. man:utimes[2]
| 
|===

Определить, могут ли учётные данные субъекта установить переданные времена доступа на переданном vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-proc-sched]]
==== `mpo_check_proc_sched`

[source, c]
----
int mpo_check_proc_sched(struct ucred *ucred, struct proc *proc);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`proc`
|Объект; процесс
| 
|===

Определить, могут ли учетные данные субъекта изменить параметры планирования переданного процесса. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки, EPERM при отсутствии привилегий или ESRCH для ограничения видимости.

См. man:setpriority[2] для получения дополнительной информации.

[[mac-mpo-cred-check-proc-signal]]
==== `mpo_check_proc_signal`

[source, c]
----
int mpo_check_proc_signal(struct ucred *cred, struct proc *proc, int signal);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`proc`
|Объект; процесс
| 

|`signal`
|Сигнал; см. man:kill[2]
| 
|===

Определить, могут ли учётные данные субъекта доставить указанный сигнал указанному процессу. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые коды ошибок: EACCES при несоответствии метки, EPERM при недостатке прав или ESRCH для ограничения видимости.

[[mac-mpo-cred-check-vnode-stat]]
==== `mpo_check_vnode_stat`

[source, c]
----
int mpo_check_vnode_stat(struct ucred *cred, struct vnode *vp,
    struct label *label);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Объект; vnode
| 

|`label`
|Метка политики для `vp`
| 
|===

Определить, могут ли учетные данные субъекта выполнять `stat` для переданного vnode. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

См. man:stat[2] для получения дополнительной информации.

[[mac-mpo-cred-check-ifnet-transmit]]
==== `mpo_check_ifnet_transmit`

[source, c]
----
int mpo_check_ifnet_transmit(struct ucred *cred, struct ifnet *ifnet,
    struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`ifnet`
|Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnet`
| 

|`mbuf`
|Объект; mbuf для отправки
| 

|`mbuflabel`
|Метка политики для `mbuf`
| 
|===

Определить, может ли сетевой интерфейс передать mbuf, переданный в качестве параметра. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-cred-check-socket-deliver]]
==== `mpo_check_socket_deliver`

[source, c]
----
int mpo_check_socket_deliver(struct ucred *cred, struct ifnet *ifnet,
    struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`ifnet`
|Сетевой интерфейс
| 

|`ifnetlabel`
|Метка политики для `ifnet`
| 

|`mbuf`
|Объект; mbuf для доставки
| 

|`mbuflabel`
|Метка политики для `mbuf`
| 
|===

Определить, может ли сокет принять датаграмму, хранящуюся в переданном заголовке mbuf. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии метки или EPERM при отсутствии привилегий.

[[mac-mpo-check-socket-visible]]
==== `mpo_check_socket_visible`

[source, c]
----
int mpo_check_socket_visible(struct ucred *cred, struct socket *so,
    struct label *socketlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
|Неизменяемый

|`so`
|Объект; сокет
| 

|`socketlabel`
|Метка политики для `so`
| 
|===

Определить, могут ли учетные данные субъекта cred "видеть" переданный сокет (`socket`), используя функции системного мониторинга, такие как те, что применяются в man:netstat[8] и man:sockstat[1]. Возвращает 0 при успехе или значение `errno` при ошибке. Рекомендуемые ошибки: EACCES при несоответствии меток, EPERM при отсутствии привилегий или ESRCH для скрытия видимости.

[[mac-mpo-check-system-acct]]
==== `mpo_check_system_acct`

[source, c]
----
int mpo_check_system_acct(struct ucred *ucred, struct vnode *vp,
    struct label *vlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`ucred`
|Учетные данные субъекта
| 

|`vp`
|Файл учёта; man:acct[5]
| 

|`vlabel`
|Метка, связанная с `vp`
| 
|===

Определить, следует ли разрешить субъекту включение учёта, основываясь на его метке и метке файла журнала учёта.

[[mac-mpo-check-system-nfsd]]
==== `mpo_check_system_nfsd`

[source, c]
----
int mpo_check_system_nfsd(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 
|===

Определить, следует ли разрешить субъекту вызывать man:nfssvc[2].

[[mac-mpo-check-system-reboot]]
==== `mpo_check_system_reboot`

[source, c]
----
int mpo_check_system_reboot(struct ucred *cred, int howto);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`howto`
|Параметр `howto` из man:reboot[2]
| 
|===

Определить, следует ли разрешить субъекту перезагружать систему указанным способом.

[[mac-mpo-check-system-settime]]
==== `mpo_check_system_settime`

[source, c]
----
int mpo_check_system_settime(struct ucred *cred);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 
|===

Определить, разрешено ли пользователю устанавливать системные часы.

[[mac-mpo-check-system-swapon]]
==== `mpo_check_system_swapon`

[source, c]
----
int mpo_check_system_swapon(struct ucred *cred, struct vnode *vp,
    struct label *vlabel);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`vp`
|Устройство подкачки
| 

|`vlabel`
|Метка, связанная с `vp`
| 
|===

Определить, следует ли разрешить субъекту добавлять `vp` как устройство подкачки.

[[mac-mpo-check-system-sysctl]]
==== `mpo_check_system_sysctl`

[source, c]
----
int mpo_check_system_sysctl(struct ucred *cred, int *name, u_int *namelen,
    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen);
----

[.informaltable]
[cols="1,1,1", frame="none", options="header"]
|===
| Параметр
| Описание
| Блокировка

|`cred`
|Учетные данные субъекта
| 

|`name`
|См. man:sysctl[3]
| 

|`namelen`
| 
| 

|`old`
| 
| 

|`oldlenp`
| 
| 

|`inkernel`
|Логический; `1`, если вызвано из ядра
| 

|`new`
|См. man:sysctl[3]
| 

|`newlen`
| 
| 
|===

Определить, следует ли разрешить субъекту выполнять указанную транзакцию man:sysctl[3].

[[mac-label-management]]
=== Вызовы при управления метками

События изменения метки происходят, когда пользовательский процесс запрашивает изменение метки на объекте. Происходит двухэтапное обновление: сначала выполняется проверка контроля доступа, чтобы определить, является ли обновление допустимым и разрешённым, а затем само обновление выполняется через отдельную точку входа. Точки входа для изменения метки обычно принимают объект, ссылку на метку объекта и новую метку, предоставленную процессом. Выделение памяти во время изменения метки не рекомендуется, так как вызовы изменения метки не могут завершиться неудачей (ошибка должна быть обнаружена ранее на этапе проверки изменения метки).

[[mac-userland-arch]]
== Пользовательская архитектура

В фреймворк TrustedBSD MAC входит ряд элементов, не зависящих от политик, включая интерфейсы MAC-библиотеки для абстрактного управления метками, изменения в управлении системными учетными данными и библиотеках входа в систему для поддержки назначения MAC-меток пользователям, а также набор инструментов для мониторинга и изменения меток процессов, файлов и сетевых интерфейсов. Более подробная информация о пользовательской архитектуре будет добавлена в этот раздел в ближайшее время.

[[mac-userland-labels]]
=== API для управления метками, не зависящими от политики

Фреймворк TrustedBSD MAC предоставляет ряд библиотечных и системных вызовов, позволяющих приложениям управлять метками MAC на объектах с использованием политико-независимого интерфейса. Это позволяет приложениям манипулировать метками для различных политик без необходимости поддержки конкретных политик. Эти интерфейсы используются универсальными инструментами, такими как man:ifconfig[8], man:ls[1] и man:ps[1], для просмотра меток на сетевых интерфейсах, файлах и процессах. API также поддерживают инструменты управления MAC, включая man:getfmac[8], man:getpmac[8], man:setfmac[8], man:setfsmac[8] и man:setpmac[8]. API MAC документированы в man:mac[3].

Приложения обрабатывают метки MAC в двух формах: внутренней форме, используемой для возврата и установки меток для процессов и объектов (`mac_t`), и внешней форме, основанной на строках C, подходящих для хранения в конфигурационных файлах, отображения пользователю или ввода от пользователя. Каждая метка MAC содержит ряд элементов, каждый из которых состоит из пары имя-значение. Модули политик в ядре привязываются к определённым именам и интерпретируют значения специфичным для политики образом. Во внешней строковой форме метки представляются списком пар имя-значение, разделённых запятыми и символом `/`. Метки могут быть напрямую преобразованы в текст и обратно с использованием предоставленных API; при извлечении меток из ядра внутреннее хранилище меток должно быть сначала подготовлено для желаемого набора элементов метки. Обычно это делается одним из двух способов: с использованием man:mac_prepare[3] и произвольного списка желаемых элементов метки, или одной из вариаций вызова, который загружает набор элементов по умолчанию из конфигурационного файла man:mac.conf[5]. Значения по умолчанию для каждого объекта позволяют разработчикам приложений удобно отображать метки, связанные с объектами, без необходимости знать о присутствующих в системе политиках.

[NOTE]
====
В настоящее время прямое манипулирование элементами меток, кроме как путем преобразования в текстовую строку, редактирования строки и обратного преобразования во внутреннюю метку, не поддерживается библиотекой MAC. Такие интерфейсы могут быть добавлены в будущем, если окажется, что они необходимы разработчикам приложений.
====

[[mac-userland-credentials]]
=== Привязка меток к пользователям

Стандартный интерфейс управления контекстом пользователя, man:setusercontext[3], был изменён для получения меток MAC, связанных с классом пользователя, из man:login.conf[5]. Эти метки устанавливаются вместе с остальным контекстом пользователя, когда указан `LOGIN_SETALL` или явно указан `LOGIN_SETMAC`.

[NOTE]
====
Ожидается, что в будущей версии FreeBSD база данных меток MAC будет отделена от абстракции классов пользователей [.filename]#login.conf# и будет поддерживаться в отдельной базе данных. Однако API man:setusercontext[3] должно остаться неизменным после такого изменения.
====

[[mac-conclusion]]
== Заключение

Фреймворк TrustedBSD MAC позволяет модулям ядра расширять политику безопасности системы высокоинтегрированным способом. Они могут делать это на основе существующих свойств объектов или данных меток, которые поддерживаются с помощью фреймворка MAC. Фреймворк достаточно гибкий для реализации различных типов политик, включая политики безопасности информационных потоков, такие как MLS и Biba, а также политики, основанные на существующих учетных данных BSD или защите файлов. Авторам политик может быть полезно ознакомиться с этой документацией, а также с существующими модулями безопасности при реализации новой службы безопасности.
