Проверка привилегий traverse в IRP_MJ_CREATE
Одной из основных проблем, IRP_MJ_CREATE проверок, является то, имеет ли вызывающий объект права доступа к пути к объекту. То есть вызывающий объект может иметь доступ к объекту файла, например dirA/dirB/file, но не иметь разрешения на доступ к содержимому каталогов по пути к объекту файла (dirA и dirA/dirB).
По умолчанию Windows предоставляет права прохода всем пользователям. Константой "Право пользователя" является SeChangeNotifyPrivilege, которая сопоставляется с FILE_TRAVERSE в ACCESS_MASK. В качестве функции безопасности системные администраторы могут удалить привилегии обхода у пользователя.
Так как большинство вызывающих объектов имеют привилегию обхода, одной из первых проверок, которую обычно выполняет файловая система, является проверка для этой привилегии в поле AccessState-Flags> контекста безопасности IRP:
BOOLEAN traverseCheck =
!(IrpContext->IrpSp->Parameters.Create.SecurityContext->AccessState->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE);
Файловая система использует флаги для отслеживания того, какие права доступа были предоставлены в ходе выполнения операции. Затем файловая система может просто быстро проверка биты состояния доступа и избежать расходов на доступ проверка вызова, если доступ уже предоставлен (traverseCheck = 0).
Если разрешение обхода ранее не было предоставлено, файловая система должна выполнить обход проверка по каждому каталогу по пути к открываемой папке. В приведенном ниже фрагменте кода обход проверка выполняется с помощью универсальной подпрограммы, обычно используемой для большинства проверок безопасности:
{
// accessParams is passed to the file system and is normally based
// on the fields of the same name from the IRP.
// Only one thread can be looking at this data structure in memory
// at a time (and potentially changing it), so acquire a lock on it.
SeLockSubjectContext(
&accessParams.AccessState->SubjectSecurityContext);
// Check whether the desired access can be granted.
// For this example, assume desiredAccess = FILE_TRAVERSE
granted = SeAccessCheck( Fcb->SecurityDescriptor,
&AccessParams.AccessState->SubjectSecurityContext,
TRUE,
AccessParams.desiredAccess,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
AccessParams.AccessMode,
&AccessParams.GrantedAccess,
&AccessParams.status );
// The file system uses AccessState to cache access privileges
// that have been granted thus far along the operation's code
// path. Update AccessState with the newly acquired Privileges.
if (Privileges != NULL) {
(void) SeAppendPrivileges(AccessParams.AccessState, Privileges );
SeFreePrivileges( Privileges );
Privileges = NULL;
}
if (granted) {
//
// The desired access was granted, so clear the
// granted bits from desiredAccess.
//
AccessParams.desiredAccess &=
~(AccessParams.GrantedAccess | MAXIMUM_ALLOWED);
if (!checkOnly) {
//
// The caller wants to modify the access state for this
// request
//
AccessParams.AccessState->PreviouslyGrantedAccess |=
AccessParams.GrantedAccess;
}
if (maxDesired) {
maxDelete =
(BOOLEAN)(AccessParams.AccessState->PreviouslyGrantedAccess &
DELETE);
maxReadAttr =
(BOOLEAN)(AccessParams.AccessState->PreviouslyGrantedAccess &
FILE_READ_ATTRIBUTES);
}
AccessParams.AccessState->RemainingDesiredAccess &=
~(AccessParams.GrantedAccess | MAXIMUM_ALLOWED);
}
// Release the lock on the security context
SeUnlockSubjectContext(&accessParams.AccessState->SubjectSecurityContext);
}
Эта функция выполняет универсальную проверка безопасности. При этом эта функция должна решать следующие проблемы:
Он должен указать правильный дескриптор безопасности, используемый для проверка.
Он должен передавать контекст безопасности (это учетные данные сущности, выполняющей операцию).
Он должен обновить состояние доступа на основе результатов проверка безопасности.
Он должен учитывать параметр MAXIMUM_ALLOWED (см. ntifs.h). Параметр MAXIMUM_ALLOWED указывает, что файловая система должна установить для доступа максимально возможный доступ, разрешенный файловой системой (например, для чтения, записи и удаления). Очень немногие приложения используют параметр MAXIMUM_ALLOWED, так как этот параметр не поддерживается в файловой системе FASTFAT. Так как бит параметра MAXIMUM_ALLOWED не является одним из битов доступа, распознаемых файловой системой FASTFAT, он отклоняет запросы на доступ к указанному файлу. Приложение, которое пытается открыть файл на томе FASTFAT с набором параметров MAXIMUM_ALLOWED, обнаружит, что запрос завершится ошибкой. Дополнительные сведения см. в функции FatCheckFileAccess в исходном файле Acchksup.c примера кода FASTFAT, который содержит WDK.
Обратите внимание, что для простого обхода проверка запрошенный доступ будет FILE_TRAVERSE, а дескриптором безопасности будет каталог, через который вызывающий объект пытается пройти, а не запрошенный доступ из исходного IRP_MJ_CREATE IRP.