Controlli di sicurezza sulle IRP_MJ_DIRECTORY_CONTROL
La sicurezza è una considerazione durante l'elaborazione di determinate operazioni di controllo della directory, in particolare quelle che gestiscono le notifiche di modifica. Il problema di sicurezza è che una notifica di modifica della directory potrebbe restituire informazioni su file specifici che sono stati modificati. Se l'utente non ha il privilegio di attraversare il percorso della directory, le informazioni sulla modifica non possono essere restituite all'utente. In caso contrario, l'utente ha ora un meccanismo per apprendere informazioni aggiuntive sulla directory che l'utente non deve avere.
Il supporto per la notifica di modifica della directory dalla libreria di runtime del file system consente a un file system di specificare una funzione di callback per eseguire un controllo di attraversamento prima di restituire una notifica di modifica della directory. Questa funzione di callback accetta un numero elevato di parametri. Per considerazioni sulla sicurezza, i tre parametri seguenti sono importanti:
NotifyContext è il contesto della directory in cui è attiva la notifica di modifica. Questo sarà il parametro FsContext passato alla chiamata a FsRtlNotifyFullChangeDirectory.
TargetContext è il contesto del file modificato. Questo sarà il parametro TargetContext passato dal file system quando chiama FsRtlNotifyFilterReportChange.
SubjectContext è il contesto di sicurezza del thread che richiede la notifica di modifica della directory. Si tratta del contesto di sicurezza soggetto acquisito dal file system al momento in cui viene eseguita la chiamata di notifica della modifica della directory a FsRtlNotifyFullChangeDirectory.
Quando si verifica una modifica, il file system indica che si tratta della libreria di runtime del file system. La libreria di runtime del file system chiamerà quindi la funzione di callback fornita dal file system per verificare che il chiamante possa fornire informazioni sulla modifica. Si noti che il file system deve registrare una funzione di callback solo se il controllo è necessario per il chiamante. Si tratta del caso in cui il chiamante non abbia SeChangeNotifyPrivilege abilitato, come indicato dal TOKEN_HAS_TRAVERSE_PRIVILEGE nel token di sicurezza del chiamante.
All'interno della funzione di callback, il file system deve eseguire un controllo di attraversamento dalla directory specificata dal parametro NotifyContext al file modificato, specificato dal parametro TargetContext . La routine di esempio seguente esegue un controllo di questo tipo.
BOOLEAN
FsdNotifyTraverseCheck (
IN PDIRECTORY_CONTEXT OriginalDirectoryContext,
IN PFILE_CONTEXT ModifiedDirectoryContext,
IN PSECURITY_SUBJECT_CONTEXT SubjectContext
)
{
BOOLEAN AccessGranted = TRUE;
PFILE_CONTEXT CurrentDirectoryContext;
ACCESS_MASK GrantedAccess;
NTSTATUS Status;
PPRIVILEGE_SET Privileges = NULL;
PFILE_CONTEXT TopDirectory;
//
// Nothing to do if there is no file context.
//
if (ModifiedDirectoryContext == NULL) {
return TRUE;
}
//
// If the directory that changed is the original directory,
// we can return , since the caller has access.
// Note that the directory context is unique to the specific
// open instance, while the modified directory context
// represents the per-file/directory context.
// How these data structures work in your file system will vary.
//
if (OriginalDirectoryContext->FileContext == ModifiedDirectoryContext) {
return TRUE;
}
//
// Lock the subject context.
//
SeLockSubjectContext(SubjectContext);
for( TopDirectory = OriginalDirectoryContext->FileContext,
CurrentDirectoryContext = ModifiedDirectoryContext;
CurrentDirectoryContext == TopDirectory || !AccessGranted;
CurrentDirectoryContext = CurrentDirectoryContext->ParentDirectory) {
//
// Ensure we have the current security descriptor loaded for
// this directory.
//
FsdLoadSecurity( NULL, CurrentDirectoryContext);
//
// Perform traverse check.
//
AccessGranted = SeAccessCheck(
CurrentDirectoryContext->SecurityDescriptor,
SubjectContext,
TRUE,
FILE_TRAVERSE,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
UserMode,
&GrantedAccess,
&Status);
//
// At this point, exit the loop if access was not granted,
// or if the parent directory is the same as where the change
// notification was made.
//
}
//
// Unlock subject context.
//
SeUnlockSubjectContext(SubjectContext);
return AccessGranted;
}
Questa routine è probabile che sia notevolmente diversa per i file system che memorizzano nella cache le informazioni di sicurezza o che dispongono di strutture di dati diverse per il rilevamento di file e directory, ad esempio file che usano una struttura per il rilevamento dei collegamenti tra file e directory. I file system che supportano i collegamenti non vengono considerati in questo esempio in un tentativo di semplificare l'esempio.