Создание обработки
Для файловой системы большинство интересных действий по обеспечению безопасности выполняется во время обработки IRP_MJ_CREATE . Именно на этом шаге необходимо проанализировать входящий запрос, определить, имеет ли вызывающий объект соответствующие права на выполнение операции, а также предоставить или отклонить операцию соответствующим образом. К счастью, для разработчиков файловых систем большая часть механизма принятия решений реализована в эталонный монитор безопасности. Таким образом, в большинстве случаев файловой системе требуется вызывать только соответствующие подпрограммы эталонного монитора безопасности, чтобы правильно определить доступ. Риск для файловой системы возникает, когда она не может вызвать эти подпрограммы по мере необходимости и неуместно предоставляет доступ вызывающему объекту.
Для стандартной файловой системы, такой как файловая система FAT, проверки, которые выполняются в рамках IRP_MJ_CREATE, в основном являются проверками семантики. Например, файловая система FAT выполняет многочисленные проверки, чтобы убедиться, что обработка IRP_MJ_CREATE разрешена в зависимости от состояния файла или каталога. Эти проверки, выполняемые файловой системой FAT, включают проверку наличия носителей, доступных только для чтения (например, попытки выполнения разрушительных операций создания, таких как перезапись или замена, на носителе, доступном только для чтения, не допускаются), проверки доступа к совместному доступу и проверки блокировки. Одна из самых сложных частей этого анализа заключается в том, чтобы понять, что операция на одном уровне (например, на уровне файла) может быть запрещена из-за состояния ресурса другого уровня (например, уровня тома). Например, файл может быть не открыт, если другой процесс заблокировал том исключительно. Распространенные случаи проверка включают:
Совместим ли уровень открытия файла с состоянием уровня тома? Блокировка на уровне тома должна соблюдаться. Таким образом, если один процесс содержит монопольную блокировку на уровне тома, только потоки в этом процессе могут открывать файлы. Потоки из других процессов не должны открывать файлы.
Совместим ли уровень открытия файла с состоянием мультимедиа? Некоторые операции создания изменяют файл как часть операции "создать". Это будет включать перезапись, замену и даже обновление времени последнего доступа к файлу. Эти операции создания не допускаются на носителях, доступных только для чтения, и время последнего доступа не обновляется.
Совместим ли уровень открытия тома с состоянием уровня файла? Открытие монопольного тома не будет разрешено, если на томе открыты существующие файлы. Это распространенная проблема для новых разработчиков, так как они пытаются открыть том и обнаружить, что он завершается ошибкой. В случае сбоя FSCTL_DISMOUNT_VOLUME можно использовать для отмены открытых дескрипторов и принудительного отключения, что обеспечивает монопольный доступ к вновь подключенному тому.
Кроме того, атрибуты файла должны быть совместимы. Файл с атрибутом только для чтения не может быть открыт для доступа на запись. Обратите внимание, что требуемый доступ следует проверять после расширения универсальных прав. Например, этот проверка в файловой системе FASTFAT находится в функции FatCheckFileAccess (см. исходный файл Acchksup.c из примеров fastfat, содержащихся в WDK).
Следующий пример кода специфичен для семантики FAT. Файловая система, которая также реализует списки DACL, будет выполнять дополнительные проверка безопасности с помощью подпрограмм эталонного монитора безопасности (например, SeAccessCheck).
//
// check for a read-only Dirent
//
if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
//
// Check the desired access for a read-only Dirent
// Don't allow
// WRITE, FILE_APPEND_DATA, FILE_ADD_FILE,
// FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD
//
if (FlagOn(*DesiredAccess, ~(DELETE |
READ_CONTROL |
WRITE_OWNER |
WRITE_DAC |
SYNCHRONIZE |
ACCESS_SYSTEM_SECURITY |
FILE_READ_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES |
FILE_EXECUTE |
FILE_LIST_DIRECTORY |
FILE_TRAVERSE))) {
DebugTrace(0, Dbg, "Cannot open readonly\n", 0);
try_return( Result = FALSE );
}
Более тонкий проверка, реализованный FASTFAT, заключается в том, чтобы доступ, запрошенный вызывающим, был тем, о чем известно файловой системе FAT (в функции FatCheckFileAccess в Acchksup.c из примера fastfat, содержащегося в WDK):
В следующем примере кода демонстрируется важная концепция безопасности файловой системы. Убедитесь, что то, что передается в файловую систему, не выходит за рамки ожидаемого. Консервативный и правильный подход с точки зрения безопасности заключается в том, что если вы не понимаете запрос на доступ, следует отклонить этот запрос.
//
// Check the desired access for the object.
// Reject what we do not understand.
// The model of file systems using ACLs is that
// they do not type the ACL to the object that the
// ACL is on.
// Permissions are not checked for consistency vs.
// the object type - dir/file.
//
if (FlagOn(*DesiredAccess, ~(DELETE |
READ_CONTROL |
WRITE_OWNER |
WRITE_DAC |
SYNCHRONIZE |
ACCESS_SYSTEM_SECURITY |
FILE_WRITE_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY |
FILE_TRAVERSE |
FILE_DELETE_CHILD |
FILE_APPEND_DATA))) {
DebugTrace(0, Dbg, "Cannot open object\n", 0);
try_return( Result = FALSE );
}
К счастью для файловых систем, после выполнения проверка безопасности во время первоначальной обработки создания последующие проверки безопасности выполняются диспетчером ввода-вывода. Так, например, диспетчер ввода-вывода гарантирует, что приложения пользовательского режима не выполняют операцию записи в файл, открытый только для чтения. Фактически, файловая система не должна пытаться применить семантику только для чтения к объекту файла, даже если он был открыт только для чтения, во время процедуры IRP_MJ_WRITE диспетчеризации. Это связано с тем, как диспетчер памяти связывает определенный файловый объект с заданным объектом раздела. Последующие записи в этом разделе будут отправляться как IRP_MJ_WRITE операции с объектом файла, даже если файл был открыт только для чтения. Иными словами, принудительное применение доступа выполняется, когда дескриптор файла преобразуется в соответствующий объект файла в точках входа системной службы Nt с помощью ObReferenceObjectByHandle.
В файловой системе есть два дополнительных места, где необходимо выполнять семантические проверки безопасности, аналогичные обработке "create":
Во время переименования или жесткой обработки ссылок.
При обработке операций управления файловой системой.
Обработка переименований и обработка управления файловой системой рассматриваются в последующих разделах.
Обратите внимание, что это не исчерпывающий список семантических проблем, связанных с обработкой "создания". Цель этого раздела — привлечь внимание разработчиков файловой системы к этим проблемам. Все семантические проблемы должны быть определены для определенной файловой системы, реализованы в соответствии с конкретной семантикой и протестированы, чтобы убедиться, что реализация обрабатывает различные варианты.