Авторизация ядра
Mac OS X 10.4 Тайгера представил новую подсистему ядра, Kernel Authorization или Kauth для краткости для управления авторизацией в ядре. Подсистема Kauth экспортирует интерфейс программирования ядра (KPI), позволяющий сторонним разработчикам ядра авторизовывать действия в ядре, изменять решения об авторизации и расширять среду авторизации ядра. Это может также использоваться в качестве механизма уведомления.
Если Вы пишете код, взаимодействующий с частями BSD ядра Mac OS X, необходимо считать этот technote для получения передающего знакомства с Kauth. Если необходимо выполнить какой-либо список задач выше, Вы захотите изучить этот technote подробно. Наконец при разработке антивирусного продукта для Mac OS X Вам будет нужна информация, содержавшаяся в этом technote для реализации «на доступе» и «сканировании файла» модификации сообщения.
Основные принципы Kauth
Система Kauth была представлена в Mac OS X 10.4 Тайгера. Это было реализовано прежде всего для упрощения реализации списков управления доступом (ACLs), главной новой функции ядра Тайгера. Поскольку оценка ACL является сложной задачей, кодом для того, чтобы сделать, это было абстрагировано из каждого плагина файловой системы и перемещено в надлежащее ядро. Kauth делает это общим и гибким способом.
В то время как Kauth был первоначально разработан для поддержки ACLs, это - общий механизм авторизации ядра и может использоваться для множества других задач. Одно такое использование как простой механизм уведомления для антивирусных разработчиков (см. Антивирусный Сканер).
Для понимания Kauth необходимо будет понять много базовых понятий.
объемы — объем является сферой интересов для авторизации в ядре. Например, объем
KAUTH_SCOPE_VNODEиспользуется для всей авторизации на уровне VFS. Объемы позволяют Вам регистрировать интерес к некоторому подмножеству решений об авторизации ядра, не будучи вовлеченным во все решения об авторизации.Объемы являются строками, отформатированными с помощью обратной нотации DNS (например,
KAUTH_SCOPE_VNODE"com.apple.kauth.vnode"), таким образом, можно определить собственный объем, если Вам нравится.действия — действие является работой в объеме. Например, подсистема VFS определяет действие,
KAUTH_VNODE_READ_DATA, который определяет, разрешают ли Вам считать данные из объекта файловой системы. Действия указаны целочисленными константами (фактический типkauth_action_t) и каждый объем имеет свое собственное пространство имен действия.Комбинация объема и действия определяет работу, авторизация которой может быть проверена.
агенты — агент является объектом, это выполняет работу.
учетные данные — Учетные данные являются информацией, идентифицирующей агента. Учетные данные указаны непрозрачным типом,
kauth_cred_t. Существуют многочисленные функции средства доступа, позволяющие Вам воздействовать на этот тип. Например,kauth_cred_getuidвозвращает эффективный идентификатор пользователя (EUID) из учетных данных.запрос — В контексте этого документа, агент выполняет запросы для выполнения действия в определенном объеме.
слушатель — слушатель является обратным вызовом, делающим решение об авторизации для запроса. Существенно слушатель авторизовывает запрос на основе учетных данных агента. Слушатель свободен использовать безотносительно объема - и зависимая от действия информация, необходимая для принятия того решения.
Существует слушатель по умолчанию для каждого встроенного объема. Этот слушатель реализует стандартную модель авторизации BSD для всех действий в том объеме. Кроме того, можно зарегистрировать собственных слушателей для объема.
Реализация слушателя
Прототип для слушателя показан в Перечислении 1.
Прототип перечисления 1 для слушателя
static int MyListener(
kauth_cred_t credential,
void * idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3
); |
Значение первых трех параметров является тем же для всех объемов.
credentialссылка на учетные данные агента.idatacookie (или refCon) данные, которыми Вы снабдили при регистрации слушателя (см. Регистрацию Слушателя).actionтребуемое действие (например,KAUTH_VNODE_READ_DATA).
Значение остающихся параметров является зависимым объема. Я буду обсуждать их подробно в более поздних разделах. Однако в большинстве случаев эти параметры дают Вам дополнительную информацию, которые позволяют Вам делать решение об авторизации. Например, для объема VFS (KAUTH_SCOPE_VNODE), arg1 ссылка на vnode (типа vnode_t) на этом управляют.
Обратный вызов слушателя должен возвратить одно из следующих значений.
KAUTH_RESULT_DEFER— Это значение указывает, что слушатель задерживает решение об этом запросе другим слушателям (и в конечном счете слушателю по умолчанию).KAUTH_RESULT_ALLOW— Это значение указывает, что, насколько этот слушатель заинтересован, запрос позволяется.KAUTH_RESULT_DENY— Это значение указывает, что должен быть отклонен запрос.
Для запроса, который будет позволен, должен возвратиться по крайней мере один слушатель KAUTH_RESULT_ALLOW и никакие слушатели не могут возвратиться KAUTH_RESULT_DENY. Это имеет много последствий.
Всех слушателей вызывают для всех запросов (потому что просто мог бы возвратиться последний слушатель
KAUTH_RESULT_DENY).Поскольку слушатель не может позволить запрос, это отклонено любым другим слушателем, слушатель не по умолчанию может только сжать безопасность.
При записи слушателю существует много важных моментов, которые необходимо иметь в виду. Они обсуждены в подробности в Глюках Слушателя.
Регистрация слушателя
Можно зарегистрировать слушателя для существующего использования объема kauth_listen_scope.
Перечисление 2 kauth_listen_scope
extern kauth_listener_t kauth_listen_scope( const char * identifier, kauth_scope_callback_t callback, void * idata ); |
Параметры следующие:
identifierимя объема. Подпрограмма не делает копию строки указанной этим параметром. Это не проблема при передаче постоянной строки; однако, при вычислении строки во время выполнения необходимо удостовериться, что строка сохраняется, пока Вы не избавляетесь от получающегосяkauth_listener_t.callbackадрес Вашей функции обратного вызова слушателя, с прототипом, показанным в Перечислении 1.idatacookie (или refCon) для Вашего обратного вызова слушателя.
На ошибке результат NULL. На успехе результатом является ссылка на слушателя; можно использовать это для вычеркивания из списка слушателя.
Это не ошибка зарегистрировать слушателя, прежде чем будет зарегистрирован соответствующий объем. Система будет помнить Вашего слушателя и применять его, как только появляется объем.
Вычеркивание из списка слушателя
Можно вычеркнуть из списка слушателя, использующего kauth_unlisten_scope.
Перечисление 3 kauth_unlisten_scope
extern void kauth_unlisten_scope(kauth_listener_t listener); |
Параметры следующие:
listenerссылка на слушателя, от которого Вы добралисьkauth_listen_scope.
Регистрация нового объема
Можно зарегистрировать новое использование объема kauth_register_scope.
Перечисление 4 kauth_register_scope
extern kauth_scope_t kauth_register_scope( const char * identifier, kauth_scope_callback_t callback, void * idata ); |
Параметры следующие:
identifierимя объема. Это - ошибка зарегистрировать уже существующий объем. Подпрограмма не делает копию строки указанной этим параметром. Это не проблема при передаче постоянной строки; однако, при вычислении строки во время выполнения необходимо удостовериться, что строка сохраняется, по крайней мере, пока Вы не избавляетесь от получающегосяkauth_scope_t.callbackадрес функции обратного вызова слушателя для этого объема; это становится слушателем объема по умолчанию. Этот параметр может бытьNULL, когда всегда возвращающийся обратный вызовKAUTH_RESULT_DEFERпринят.idatacookie (или refCon) для обратного вызова слушателя.
На ошибке результат NULL. На успехе результатом является ссылка на объем; можно использовать это для вычеркивания из списка объема.
Вычеркивание из списка объема
Можно вычеркнуть из списка использование объема kauth_deregister_scope:
Перечисление 5 kauth_deregister_scope
extern void kauth_deregister_scope(kauth_scope_t scope); |
Параметры следующие:
scopeссылка на объем, от которого Вы добралисьkauth_register_scope.
Любые другие слушатели (не по умолчанию), зарегистрированные на объеме, пойдут бездействующие; если объем будет повторно зарегистрирован, они будут повторно активированы.
Авторизация действия
Можно сделать использование запроса авторизации kauth_authorize_action.
Перечисление 6 kauth_authorize_action
extern int kauth_authorize_action(
kauth_scope_t scope,
kauth_cred_t credential,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3
); |
Параметры следующие:
scopeссылка на объем, в котором определяется действие. Вы получаете это значение от результатаkauth_register_scope.credentialссылка на учетные данные агента. Обычно у Вас или уже была бы эта информация, или Вы вызоветеkauth_cred_getполучить учетные данные для текущего потока.actionтребуемое действие.arg0черезarg3передаются неизмененные обратным вызовам слушателя.
Если Ваше расширение ядра поддерживает плагины и те плагины вызов kauth_authorize_action, у Вас должен быть путь к Вашим плагинам для обнаружения ссылки объема (kauth_scope_t). Самый простой способ сделать это должно экспортировать функцию обертки, это адаптируется в соответствии с Вашими определенными требованиями.
Встроенные объемы
Этот раздел перечисляет все объемы, встроенные к ядру Mac OS X.
Объем процесса
Объем процесса (KAUTH_SCOPE_PROCESS, который является "com.apple.kauth.process") является самым простым понять. Это определяет всего два действия.
KAUTH_PROCESS_CANTRACE— Авторизовывает, может ли текущий процесс проследить целевой процесс.arg0(типаproc_t) прослеживаемый процесс.arg1(типа(int *)) указатель на код ошибки errno-стиля; если слушатель отклоняет запрос, он должен установить это значение в ненулевое значение.KAUTH_PROCESS_CANSIGNAL— Авторизовывает, может ли текущий процесс сигнализировать целевой процесс.arg0(типаproc_t) процесс, который будет сообщен.arg1(типаint) сигнал, который это отправляется.
Ядро также экспортирует a kauth_authorize_action обертка для этого объема, а именно, kauth_authorize_process.
Перечисление 7 kauth_authorize_process
extern int kauth_authorize_process(
kauth_cred_t credential,
kauth_action_t action,
proc_t process,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3
); |
Эта обертка вокруг kauth_authorize_action делает две полезных вещи:
Это предоставляет надлежащий параметр объема.
Это избавляет от необходимости бросать
process(типаproc_t) кarg0(типаuintptr_t).
Обычно это не полезно для сторонних разработчиков.
Универсальный объем
Универсальный объем (KAUTH_SCOPE_GENERIC, который является "com.apple.kauth.generic") имеет единственное действие, KAUTH_GENERIC_ISSUSER, который ядро запрашивает протестировать, имеет ли агент полномочия суперпользователя. Ни один из универсальных параметров (arg0 через arg3) являются значительными.
Ядро также экспортирует a kauth_authorize_action обертка для этого объема, а именно, kauth_authorize_generic.
Перечисление 8 kauth_authorize_generic
extern int kauth_authorize_generic( kauth_cred_t credential, kauth_action_t action ); |
Обычно это не полезно для сторонних разработчиков.
Объем работы файла
Объем работы файла (KAUTH_SCOPE_FILEOP, который является "com.apple.kauth.fileop") отличается от других объемов, в которых это не используется для фактической авторизации работы; скорее система использует этот объем для уведомления слушателей значительных операций файловой системы. Это может использоваться для реализации программы сканирования антивируса, как описано в Антивирусном Сканере.
KAUTH_SCOPE_FILEOP определяет следующие действия.
KAUTH_FILEOP_OPEN— Уведомляет, что был открыт объект файловой системы (файл или каталог).arg0(типаvnode_t) vnode ссылка.arg1(типа(const char *)) указатель на полный путь объекта.KAUTH_FILEOP_CLOSE— Уведомляет, что объект файловой системы собирается быть закрытым.arg0(типаvnode_t) vnode ссылка.arg1(типа(const char *)) указатель на полный путь объекта.arg2(типаint) ряд битовых флагов; единственный флаг, в настоящее время определяемый,KAUTH_FILEOP_CLOSE_MODIFIED, если измененный файл закрывается, который установлен.KAUTH_FILEOP_RENAME— Уведомляет, что был переименован объект файловой системы.arg0(типа(const char *)) указатель на предыдущий полный путь объекта.arg1(типа(const char *)) указатель на новый полный путь объекта.KAUTH_FILEOP_EXCHANGE— Уведомляет, что двумя файлами обменялись (через exchangedata).arg0(типа(const char *)) указатель на полный путь первого файла.arg1(типа(const char *)) указатель на полный путь второго файла.KAUTH_FILEOP_LINK— Уведомляет, что новая жесткая ссылка была добавлена к файлу (через системный вызов ссылки).arg0(типа(const char *)) указатель на полный путь исходного файла.arg1(типа(const char *)) указатель на полный путь недавно создаваемой ссылки.KAUTH_FILEOP_EXEC— Уведомляет, что программа была выполнена (через execve системный вызов).arg0(типаvnode_t) vnode ссылка выполняемой программы (для Мужественных исполнимых программ, это - фактическая исполнимая программа; для приложений CFM это будет всегда ссылатьсяLaunchCFMApp; для интерпретируемых сценариев, таких как оболочка или perl сценарии, это - сценарий, не интерпретатор).arg1(типа(const char *)) указатель на полный путь программного файла.
При установке слушателя в этом объеме его вызовут для уведомления Вас относительно этих событий. Ядро игнорирует возвращаемое значение Вашего слушателя, несмотря на то, что мы рекомендуем всегда возвращаться KAUTH_RESULT_DEFER.
Эта проблема была решена в Mac OS X 10.5.
Ядро также экспортирует a kauth_authorize_action обертка для этого объема, а именно, kauth_authorize_fileop.
Перечисление 9 kauth_authorize_fileop
extern int kauth_authorize_fileop( kauth_cred_t credential, kauth_action_t action, uintptr_t arg0, uintptr_t arg1 ); |
Обычно kauth_authorize_fileop не полезно для сторонних разработчиков. Однако при вызове его примите во внимание следующее неочевидное поведение. arg0 параметр kauth_authorize_fileop a vnode_t. kauth_authorize_fileop передачи это vnode_t к arg0 параметр слушателя. Это также получает путь к этому vnode и передачи это к arg1 параметр слушателя. Наконец, для KAUTH_FILEOP_CLOSE действие, kauth_authorize_fileop передачи arg1 параметр к arg2 параметр слушателя.
Объем Vnode
Объем vnode (KAUTH_SCOPE_VNODE, который является "com.apple.kauth.vnode") самый сложный объем, в настоящее время определяемый. Первая вещь отметить состоит в том, что в объеме vnode действия не являются перечислениями, а скорее битовыми полями. Таким образом совершенно разумно объединить действия осуществлением операции ИЛИ их вместе. Например, действие KAUTH_VNODE_READ_DATA | KAUTH_VNODE_EXECUTE указывает, что агент хочет и считать и выполнить файл.
Для авторизации действия в объеме vnode Вы вызвали бы vnode_authorize.
Перечисление 10 vnode_authorize
extern int vnode_authorize( vnode_t vp, vnode_t dvp, kauth_action_t action, vfs_context_t context ); |
Параметры следующие:
vpvnode, на котором выполняется действие.dvpvnode родительского каталога. Во многих случаях этоNULL, указание, что родитель неизвестен или не важен.actionвыполняемая работа; это обсуждено подробно ниже.contextконтекст VFS, связанный с агентом. Это - непрозрачная структура данных, это глубоко связывается к реализации VFS. Большинство точек входа VFS передается этот контекст. Кроме того, существуют многочисленные подпрограммы контекста VFS, определенные в <sys/vnode.h>.
vnode_authorize довольно простая обертка вокруг kauth_authorize_action. Это выполняет две полезных функции:
Это собирает корректные параметры слушателя объема (
arg0черезarg3). Они обсуждены ниже.Это гарантирует, что код ошибки корректен. В частности это переводит
EPERMошибка, возвращеннаяkauth_authorize_actionвEACCES(который является надлежащей ошибкой для функций файловой системы). Кроме того, если слушатель отклоняет запрос и обеспечивает определенный код ошибки (черезarg3, посмотрите ниже), это возвращает ту ошибку.
Параметры слушателя объема за объем vnode следующие:
arg0, из типаvfs_context_t,context— Контекст VFS, описанный выше.arg1, из типаvnode_t,vp— Сам vnode.arg2, из типаvnode_t,dvp— Родитель vnode, при наличии. Это может бытьNULL.arg3, из типа(int *),errPtr— Указатель на ошибку errno-стиля. Если Ваш обратный вызов отклоняет запрос, он может установить это значение для указания ошибки возвратиться к клиенту. Если Вы не устанавливаете это, клиент добираетсяEACCES.
В объеме vnode определяются следующие стандартные действия.
KAUTH_VNODE_READ_DATA(такжеKAUTH_VNODE_LIST_DIRECTORY) — Если vnode является каталогом, разрешает агента перечислять содержание того каталога. Иначе, разрешает агента читать содержание файла.KAUTH_VNODE_WRITE_DATA(такжеKAUTH_VNODE_ADD_FILE) — Если vnode является каталогом, разрешает агента добавлять файл к тому каталогу.vpкаталог, к которому добавляется файл;dvpNULL. Иначе, разрешает агента писать содержание файла.KAUTH_VNODE_EXECUTE(такжеKAUTH_VNODE_SEARCH) — Если vnode является каталогом, разрешает агента зондировать для существования элемента в каталоге как часть поиска пути. Иначе, разрешает агента выполнять содержание файла.KAUTH_VNODE_DELETE— Разрешает агента удалять элемент из каталога.vpэлемент, который будет удален иdvpкаталог, из которого это удаляется.KAUTH_VNODE_APPEND_DATA(такжеKAUTH_VNODE_ADD_SUBDIRECTORY) — Если vnode является каталогом, разрешает агента добавлять каталог к нему. Иначе, это действие предназначается, чтобы разрешить агента добавлять данные к содержанию файла; однако, этот аспект в настоящее время не реализуется.KAUTH_VNODE_DELETE_CHILD— Когда используется в ACL каталога, это разрешение управляет, может ли агент удалить элемент из каталога. Т.е. для агента, чтобы быть в состоянии удалить элемент, они должны иметьKAUTH_VNODE_DELETEразрешение на элементе иKAUTH_VNODE_DELETE_CHILDразрешение на родительском каталоге элемента.Слушатель Kauth, однако, редко видит это действие. Когда агент удаляет элемент, ядро просто авторизовывает
KAUTH_VNODE_DELETEдействие с самим элементом; это не авторизовывает отдельноеKAUTH_VNODE_DELETE_CHILDдействие с родительским каталогом. Скорее слушатель по умолчанию для объема vnode проверитKAUTH_VNODE_DELETE_CHILDразрешение на родительском каталоге непосредственно, без другого проходят через Kauth. Это улучшает производительность и избегает потенциального состояния состязания.С другой стороны, a
KAUTH_VNODE_DELETE_CHILDдействие сгенерировано в ответ на системный вызов доступа с_RMFILE_OKфлаг.KAUTH_VNODE_READ_ATTRIBUTES— Разрешает агента читать стандартные атрибуты vnode (такие как метки времени).KAUTH_VNODE_WRITE_ATTRIBUTES— Разрешает агента изменять стандартные атрибуты vnode (такие как метки времени).KAUTH_VNODE_READ_EXTATTRIBUTES— Разрешает агента читать расширенные атрибуты vnode (те, через которых получают доступgetxattr, включая ветвь ресурсов).KAUTH_VNODE_WRITE_EXTATTRIBUTES— Разрешает агента изменяться (или добавлять) расширенные атрибуты vnode (те, через которых получают доступgetxattr, включая ветвь ресурсов).KAUTH_VNODE_READ_SECURITY— Разрешает агента читать ACL vnode.KAUTH_VNODE_WRITE_SECURITY— Разрешает агента изменять ACL vnode.KAUTH_VNODE_TAKE_OWNERSHIP— Разрешает агента изменять владение vnode.KAUTH_VNODE_SYNCHRONIZE— Это представляет разрешение ACL, определяющееся для совместимости с другими платформами. Это сохраняется, но не тестируется Mac OS X. Следовательно, это никогда не используется в качестве действия Kauth.KAUTH_VNODE_LINKTARGET— Разрешает агента делать новую жесткую ссылку на vnode.KAUTH_VNODE_CHECKIMMUTABLE— Разрешает агента изменять файл (вSF_IMMUTABLEсмысл; см. chflags). Этот флаг установлен, если другие проверки были уже осуществлены, чтобы проверить, что файл может измененным, но модификация должна все еще перестать работать для неизменных файлов.KAUTH_VNODE_ACCESS— Это - специальный флаг. Если этот флаг установлен, запрос авторизации является консультацией (например, для удовлетворения системного вызова доступа), а не авторитетный. Слушатель может использовать это, чтобы избежать выполнять дополнительную работу в консультативном случае.KAUTH_VNODE_NOIMMUTABLE— Это - специальный флаг. Это передается слушателю вместе сKAUTH_VNODE_WRITE_SECURITYбит (и никакие другие), чтобы указать, что агент хочет измениться один или больше неизменных флагов, и что состояние этих флагов нельзя рассмотреть при авторизации запроса.
Глюки объема Vnode
Помните, что действия в объеме vnode являются битовым полем. Таким образом слушателя объема vnode можно вызвать для авторизации многократных действий одновременно.
Объем vnode является чрезвычайно горячим. Если Ваш слушатель объема vnode будет медленным, то это значительно замедлит все операции файловой системы. При установке слушателя объема vnode необходимо работать для создания его максимально эффективным.
Когда запись vnode определяет объем слушателя, знает, что не каждая операция файловой системы инициирует запрос авторизации. Например, если агент успешно запрашивает KAUTH_VNODE_SEARCH на каталоге система может кэшировать тот результат и предоставить будущие запросы, не вызывая Вашего слушателя для каждого.
Для получения дополнительной информации о ловушках записи слушателя, посмотрите Глюки Слушателя.
Глюки слушателя
При записи слушателю существует много важных моментов, которые необходимо иметь в виду. Они обсуждены в следующих разделах.
Контекст
В большинстве случаев Вашего слушателя вызовет поток пользователя. Т.е. пользовательский поток сделал системный вызов, заставивший его вводить ядро для выполнения работы, инициировавшей запрос Kauth. Так, возможно получить информацию об агенте на основе текущего потока или процесса. Например, можно вызвать proc_self получить ссылку на текущий процесс и затем извлечь полезную информацию из этого.
Однако необходимо попытаться избежать делать это. Скорее Ваш слушатель должен принять его решение на основе учетных данных агента (как передано ему в credentials параметр) и, если Вы слушаете в объеме vnode, контексте VFS.
Существует две причины этой рекомендации.
Насколько полный проект ядра затронут, это более чисто для Вашего слушателя для принятия решений на основе его входных параметров, а не на неявных параметрах как текущий поток.
В некоторых случаях для работы ядра возможно быть выполненным другим потоком от имени пользователя. Этот вид вещи уже происходит для асинхронного I/O, где ядро поддерживает пул асинхронных потоков I/O, выполняющих асинхронные запросы к файловой системе. В настоящее время эти потоки фактически не делают запросы авторизации, но долгосрочное направление ясно.
Предотвращение мертвой блокировки
Вашего слушателя вызывает поток, это выполняет работу, таким образом, возможно блокировать поток при обработке запроса. Однако это - обоюдоострый меч. Это позволяет Вашему слушателю передавать запрос внешнему агенту (демон пространства пользователя, например) и блок, ожидающий результатов. Однако выполнение так влечет за собой значительный риск заведения в тупик системы.
Эта проблема обычно неожиданно возникает при записи слушателю для vnode или объемов работы файла. Типичный пример:
Вы устанавливаете слушателя для объема работы файла.
Нормальный процесс открывает файл.
С Вашим слушателем вызывают
KAUTH_FILEOP_OPEN. Это передает запрос демону пространства пользователя и ожидает результата.Демон пространства пользователя вызывает некоторую системную подпрограмму что RPCs системному демону. Например, это могло бы вызвать getpwuid, фактически реализованный внутри lookupd.
Системный демон открывает файл.
Это заставляет ядро вызывать Вашего слушателя, и цикл запускается снова.
Эта проблема намного хуже, чем это кажется. В частности:
Системные демоны вызывают других системных демонов. Например,
lookupdзависит от DirectoryService, который может поочередно зависеть от других демонов.Вы не можете просто твердый код список возможных системных демонов, потому что дерево зависимостей варьируется от от выпуска к выпуску; в любое время Apple может добавить новые зависимости.
Для Вашего демона невозможно не зависеть от любых системных демонов. Каждый раз, когда Вы касаетесь листаемой памяти, Вы могли бы инициировать выделение страничного файла, зависящего от dynamic_pager.
Существует множество способов избежать этой мертвой блокировки. Лучшее для Вашего слушателя для предотвращения, делают любую обработку, если запрос прибывает из потока, работающего как корень (т.е. где kauth_cred_getuid поскольку учетные данные агента возвращаются 0). Поскольку все критически настроенные системные демоны будут обязательно работать как корень, Вы находите выход из тупика на шаге 6 выше.
Однако этот метод может не быть надлежащим во всех случаях. Например, антивирусный сканер особенно хотел бы отсканировать файлы, открываемые потоком, работающим с поднятыми полномочиями. В этом случае единственное правильное решение для сканера для работы полностью в ядре.
Производительность
Некоторые объемы Kauth являются очень горячими. Т.е. типичная система будет делать запросы авторизации в том объеме часто. Например, система, копирующая файлы, могла бы заставить тысячи vnode определить объем запросов авторизации в секунду. При регистрации слушателя для объема его можно вызвать для каждого запроса. Если Ваш слушатель будет медленным, то это значительно ухудшит производительность системы.
Два горячих объема на Mac OS X являются объемом vnode и объемом работы файла. Если Вы устанавливаете слушателя для любого из этих объемов, несомненно, измерят эффект, который Ваш слушатель имеет на полную производительность системы, и оптимизируйте своего слушателя соответственно.
Поваренная книга Kauth
В этом разделе описывается использовать Kauth для реализования некоторых обычно требуемых опций.
Отклонение отладчика
Можно использовать Kauth для реализации расширения ядра, предотвращающего пользователей, присоединяющих к процессам с отладчиком. Все, что необходимо сделать, зарегистрировать слушателя для KAUTH_SCOPE_PROCESS определите объем и ищите KAUTH_PROCESS_CANTRACE действие. Перечисление 11 показывает слушателю в качестве примера, отрицающему отлаживать для всех кроме корня. Можно использовать подобный метод для предотвращения присоединения отладчика к определенным процессам.
Перечисление 11 , Отклоняющее отладчик
static int KauthDenyDebugListener(
kauth_cred_t credential,
void * idata,
kauth_action_t action,
uintptr_t arg0,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3
)
// We register this listener for the KAUTH_SCOPE_PROCESS scope.
// The system calls this listener whenever it needs to authorize
// an action within that scope. We look for
// KAUTH_PROCESS_CANTRACE action and deny it if the requesting
// user is not root.
{
int result;
result = KAUTH_RESULT_DEFER;
switch (action) {
case KAUTH_PROCESS_CANTRACE:
{
proc_t targetProc;
int * errPtr;
targetProc = (proc_t) arg0;
errPtr = (int *) arg1;
if (kauth_cred_getuid(credential) != 0) {
printf(
"Denied P_TRACE from %d to %d by %d.\n",
proc_selfpid(),
proc_pid(targetProc),
kauth_cred_getuid(credential)
);
*errPtr = EPERM;
result = KAUTH_RESULT_DENY;
}
}
break;
default:
// do nothing
break;
}
return result;
} |
Антивирусный сканер
Kauth позволяет Вам реализовывать антивирусную программу, поддерживающую и «на доступе» и «сканировании файла» модификации сообщения. Последний прост: все, что необходимо сделать, зарегистрировать слушателя для KAUTH_SCOPE_FILEOP объем и часы для KAUTH_FILEOP_CLOSE действие. Если Вы видите, что измененный файл закрывается, можно передать тот файл демону пространства пользователя для сканирования. Поскольку сканирование продолжается асинхронно в фоновом режиме, не должно быть никаких проблем с мертвой блокировкой.
При реализации «на доступе» сканирование более сложно. Ваш подход зависит от того, можно ли всегда фиксировать файл. Если это так, можно прислушаться KAUTH_FILEOP_OPEN (в KAUTH_SCOPE_FILEOP) и отсканируйте файл сразу после того, как он будет открыт. Однако результат Вашего слушателя всегда игнорируется, таким образом, нет никакого способа запретить доступа агента к тому файлу.
Если Вы не можете всегда фиксировать файл, и таким образом можно хотеть запретить доступа агента к файлу, необходимо прислушаться к надлежащим мерам в KAUTH_SCOPE_VNODE объем. Если Вы сканируете файл, обнаруживаете, что он заражен и не может фиксировать его, необходимо возвратиться KAUTH_RESULT_DENY препятствовать тому, чтобы агент использовал его.
Трудность с обоими из них «на доступе» подходы избегает мертвой блокировки. Посмотрите Реализацию Слушателя для детального обсуждения этой проблемы.
Новая подсистема ядра
При реализации полностью новой подсистемы ядра (например, сложный стек протоколов), можно решить реализовать использование авторизации Kauth. Существует семь шагов к этому:
Выберите имя объема. Необходимо использовать обратное имя стиля DNS, как проиллюстрировано встроенными объемами, описанными в этом документе.
Выберите ряд действий. Можно принять решение использовать любого перечисление (как сделано объемом операций файла) или битовая маска (как используется объемом vnode).
Для каждого действия необходимо решить что специфичные для запроса параметры (типа
arg0черезarg3) являются подходящими для того действия. Является самым простым, если параметрами является то же для всех действий в Вашем объеме, но это не требуется.Запишите слушателю по умолчанию для Вашего объема. Этот слушатель должен быть в состоянии сделать решения об авторизации на основе:
идентификационные данные агента (как представлено слушателем
credentialsпараметр)требуемое действие
специфичные для запроса параметры
Ваш слушатель может извлечь информацию из учетных данных с помощью функций, определяемых средства доступа в <sys/kauth.h>.
Создайте свой объем и зарегистрируйте своего слушателя как слушателя по умолчанию, с помощью
kauth_register_scope.Создайте специфичную для объема функцию обертки для
kauth_authorize_actionэто:предоставляет ссылку на объем, создаваемый на предыдущем шаге
бросает Ваши специфичные для объема параметры универсальным параметрам (
arg0черезarg3) используемыйkauth_authorize_action
Вызовите свою специфичную для объема функцию обертки для авторизации определенных действий в надлежащих местах в подсистеме ядра.
Пример кода KauthORama
Пример кода 'KauthORama' является большим инструментом для исследования Kauth. Это позволяет Вам регистрировать фиктивного слушателя для любого объема. Слушатель всегда возвращается KAUTH_RESULT_DEFER, и так не имеет никакого эффекта на решения об авторизации, но это распечатывает запись запроса авторизации. Используя это Вы видите, как Kauth взаимодействует с высокоуровневыми операциями, как перечисление каталогов или копирование файлов. Чтение выборки меня файл имеет инструкции для того, чтобы сделать это.
История версии документа
| Дата | Примечания |
|---|---|
| 23.03.2010 | Незначительное обновление для обращения некоторых точек беспорядка. Во-первых, KAUTH_PROCESS_CANSIGNAL не реализован ни на какой версии Mac OS X, не просто Mac OS X 10.4 (r. 7724502). Во-вторых, поведение kauth_authorize_fileop неочевидно, и это обновление разъясняет свое поведение (r. 5777071). Наконец, были некоторые незначительные изменения для учета очень небольших различий в Kauth начиная с Mac OS X 10.4. |
| 16.01.2007 | Задокументируйте ошибку ядра, заставляющую определенные параметры быть NULL. |
| 21.03.2006 | Исправленные проблемы с символами неASCII. |
| 03.06.2005 | Новый документ, описывающий авторизацию ядра (kauth) подсистема и ее связанный KPI. |