Я не устаю ссылаться на книгу “Mac OS X Internals. A Systems Approach“, которую мне посоветовал alexmak. Эта книга – очень достойный источник информации для желающих разобраться в работе Mac OS X.
Сегодня я хочу продемонстрировать пример из книги, показывающий работу с Disk Arbitration (я надеюсь, что приводя пример, я способствую увеличению количества читателей этой книги; также я написал Amit Singh, автору книги с просьбой дать разрешение на использование на сайте его кода).
Подсистема Disk Arbitration управляет дисками и образами дисков. Она содержит демон diskarbitrationd и фреймворк DiskArbitration.framework, используя который, можно взаимодействовать с демоном. diskarbitrationd выполняет такие задачи:
- обрабатывает подключенные к системе диски на предмет возможности монтирования разделов
- уведомляет клиентов, подписанных на нотификации, о появлении и исчезновении дисков и разделов
- выступает арбитром, разрешающим или запрещающим доступ к дискам
Ранее я описал, как можно отключить возможность подключения внешних USB-носителей, удаляя соответствующий модуль kext. Но более правильный метод основан как раз на взаимодействии с diskarbitrationd. Привожу пример из книги:
// dissent_mount.c
#include
#define OUT_ON_NULL(ptr, msg) \
if (!ptr) { fprintf(stderr, "%s\n", msg); goto out; }
DADissenterRef
mountApprovalCallback(DADiskRef disk, void *context)
{
// В ответ на любой запрос монтирования выдать запрет
DADissenterRef dissenter = DADissenterCreate(kCFAllocatorDefault,
kDAReturnNotPermitted,
CFSTR("mount disallowed"));
printf("%s: mount disallowed\n", DADiskGetBSDName(disk));
return dissenter;
}
int main(void)
{
DAApprovalSessionRef session = DAApprovalSessionCreate(kCFAllocatorDefault);
OUT_ON_NULL(session, "failed to create Disk Arbitration session");
// Зарегистрировать callback-функцию, вызываемую при монтировании
DARegisterDiskMountApprovalCallback(session,
NULL, // matches all disk objects
mountApprovalCallback,
NULL); // context
DAApprovalSessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
// Программа работает 30 секунд, после чего производится выход
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 30 /* seconds */, false);
DAApprovalSessionUnscheduleFromRunLoop(session, CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
DAUnregisterApprovalCallback(session, mountApprovalCallback, NULL);
out:
if (session)
CFRelease(session);
exit(0);
}
Компиляция:
$ gcc -Wall -o dissent_mount dissent_mount.c \ -framework DiskArbitration -framework CoreFoundation
Запуск:
$ ./dissent_mount disk3s2: mount disallowed disk3s2: mount disallowed
Программа запускается на 30 секунд и не даёт ничего смонтировать, пока она работает. Например, те же USB-диски подключить будет невозможно. В качестве развития программы можно выборочно анализировать тип подключаемых дисков, и, допустим, разрешать монтировать образы, но запрещать монтировать диски. Также можно запустить программу при старте системы, в итоге пользователи без административных прав не смогут её отключить.
Более жёсткий метод борьбы с монтированием приводится на Mac OS X Forensics. Нет запущенного diskarbitrationd – нет проблемы:
$ sudo launchctl unload \ /System/Library/LaunchDaemons/com.apple.diskarbitrationd.plist

