La virtualización de sistemas de archivos es una de las tecnologías más populares que el equipo de desarrollo de controladores de Apriorit construye y adapta para diversos proveedores de tecnología, principalmente de los segmentos de seguridad y gestión de datos.
El sistema de archivos virtuales es una gran técnica para proteger a los usuarios de las complejidades de la gestión del almacenamiento, especialmente cuando los archivos se almacenan en varios puntos de las redes. Cada implementación de sistemas de archivos virtuales permite presentar el almacenamiento de datos al usuario de la forma que desee, utilizando la informática para separar completamente la representación de la forma en que se almacenan realmente los archivos.
Al mismo tiempo, puede manipular la representación de los datos para hacer cumplir los permisos de acceso o proporcionar un procesamiento de operaciones de archivo personalizado que incluya una supervisión avanzada, cambios indirectos de datos con opciones de retroceso, copia en la sombra y otras tareas relacionadas con la seguridad.
En este artículo, describimos la implementación de un sistema de archivos virtual de Windows que puede procesar operaciones de archivos a su manera, proporcionando conceptos básicos y el código para la solución de controladores subyacentes.
Introducción y estructura de la solución
La solución que virtualiza el sistema de archivos, descrita en este artículo, se ha hecho popular debido al rápido desarrollo de servicios como Dropbox y Google Drive para acceder a los archivos de forma remota. Todos los proveedores de almacenamiento en la nube populares ofrecen API de archivos para trabajar con los archivos en la nube de sus aplicaciones. Mediante este tipo de API, un desarrollador puede implementar una unidad lógica que funcione directamente con los archivos del almacenamiento en la nube.
Aquí está la estructura básica de tal solución:
- Controlador de modo de kernel
- Servicio de modo de usuario
- Utilidad de montaje (puede ser una simple aplicación de consola)
El controlador de modo de kernel redirige las solicitudes de operación de archivos al servicio de modo de usuario, que proporciona la interfaz para procesar estas operaciones de archivo en el modo de usuario. Este enfoque permite a un desarrollador abstraer el desarrollo del modo de núcleo y las entidades de archivo y trabajar sólo con operaciones de archivo.
Consideremos cada parte de esta solución de sistema de archivos de virtualización en detalle.
Conductor
El conductor implementa el sistema de archivos. Incluye la lógica para redirigir las operaciones de los archivos y gestionar los discos.
Para nuestros propósitos, durante la instalación este controlador creará algunos dispositivos.
Dispositivo de control
El primer dispositivo que creará el controlador es un dispositivo de control que se utiliza para la administración del disco. Proporciona al desarrollador la capacidad de montar y desmontar unidades.
// crear dispositivo de controlRtlInitUnicodeString(&deviceName, FS_CONTROL_DEVICE_NAME);status = IoCreateDevice(pDriverObject,sizeof(FS_CONTROL_DEVICE_EXTENSION),&deviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&pControlDevice);...
Dispositivo de comunicación
El segundo dispositivo que se creará es un dispositivo de comunicación. Implementa la sincronización entre el conductor y el servicio de modo de usuario. Este servicio envía ciertos códigos al dispositivo para indicar su estado: si va a arrancar o detenerse o si está listo para recibir solicitudes.
// crear dispositivo de comunicaciónRtlInitUnicodeString(&deviceName, FS_COMMUNICATION_DEVICE_NAME);status = IoCreateDevice(pDriverObject,sizeof(FS_COMMUNICATION_DEVICE_EXTENSION),&deviceName,FILE_DEVICE_UNKNOWN,0,TRUE,&pCommDeviceObject);...
Dispositivo redactor
El último dispositivo que se creará es un dispositivo redirector. Captura las solicitudes de operaciones de archivos enviadas a la unidad montada y las redirige al servicio de modo de usuario que debe implementar los manejadores para estas operaciones.
// create redirector deviceRtlInitUnicodeString(&deviceName, FS_REDIRECTOR_DEVICE_NAME);status = IoCreateDevice(pDriverObject,sizeof(FS_REDIR_DEVICE_EXTENSION),&deviceName,FILE_DEVICE_NETWORK_FILE_SYSTEM,FILE_REMOTE_DEVICE,FALSE,&pRedirDevice);...
Manejo de la solicitud del núcleo
Cuando se crean estos tres dispositivos, el controlador se configura con una función de manejo para el procesamiento de solicitudes. Para ello, se utiliza una única función: FSDispatchRequest. Esta es la parte más crucial del controlador y debe ser implementada cuidadosamente.
// Dispatch IRP contextNTSTATUS FSDispatchRequest(IN PFS_IRP_CONTEXT pIrpContext){...switch (pIrpContext->MajorFunction){case IRP_MJ_CREATE:...case IRP_MJ_CLEANUP:...case IRP_MJ_CLOSE:...case IRP_MJ_QUERY_INFORMATION:...case IRP_MJ_DIRECTORY_CONTROL:...case IRP_MJ_QUERY_VOLUME_INFORMATION:...case IRP_MJ_READ:...caso IRP_MJ_WRITE:...caso IRP_MJ_SET_INFORMATION:...caso IRP_MJ_FLUSH_BUFFERS:...caso IRP_MJ_LOCK_CONTROL:...caso IRP_MJ_DEVICE_CONTROL:return FSDeviceControl(pIrpContext);caso IRP_MJ_SET_VOLUME_INFORMATION:...case IRP_MJ_FILE_SYSTEM_CONTROL:...case IRP_MJ_QUERY_SECURITY:...case IRP_MJ_SET_SECURITY:...default:...}...}
Dado que el controlador es un sistema de archivos y no es un filtro de sistema de archivos, debe manejar cada código de operación de archivos por sí mismo – los códigos no pueden ser reenviados a otros sistemas de archivos, sino que sólo pueden ser reenviados al controlador para el almacenamiento en disco que está formateado para este sistema de archivos.
Una vez que el controlador del disco virtual está totalmente inicializado, el Administrador de E/S de Windows puede pedirle que reconozca un nuevo volumen. Si el volumen no es reconocido por ningún sistema de archivos, se asignará el sistema de archivos RAW y se pedirá al usuario que formatee el disco cuando acceda a esa unidad por primera vez. Sin embargo, esto no sucede con nuestro disco virtual! Cuando llega la solicitud de montaje del disco, nuestro sistema de archivos se asigna al nuevo volumen y, a partir de este momento, el administrador de E/S comienza a enviar solicitudes de operación de archivos para el disco montado a nuestro controlador.
Cuando llegan estas solicitudes de operación de archivos, se envían al servicio para ser procesadas en modo de usuario.
// enviar solicitud al estado de servicio = FSSendRequestToService(pIrpContext,FS_REQUEST_CREATE,pCreateFileRequest,sizeof(FS_CREATE_REQUEST) + fileName.Length,NULL,0,TRUE,pIrpContext->IsSynchronous ? &event : NULL);...
Todos los códigos de control (excepto IRP_MJ_DEVICE_CONTROL) corresponden a operaciones de archivos Win32. El código IRP_MJ_DEVICE_CONTROL está diseñado para resolver tareas que no están directamente relacionadas con las operaciones de los archivos. En la solución descrita en este artículo, este código es utilizado por todos los dispositivos para la gestión de discos, la sincronización de servicios y el manejo de códigos de control del sistema de archivos. Para detectar para qué dispositivo se ha enviado una solicitud, se comprueba su cabecera.
Las solicitudes que se envían al dispositivo de comunicación realizan tareas de sincronización de servicio. El servicio envía estas solicitudes para indicar su disposición a recuperar operaciones de archivo para su posterior procesamiento (IOCTL_FS_SEND_REQUEST) y para enviar respuestas relativas a determinadas operaciones de archivo (IOCTL_FS_RECEIVE_RESPONSE). También envía señales cuando va a comenzar (IOCTL_FS_START) o detenerse (IOCTL_FS_STOP y IOCTL_FS_FILE_CACHE_CONTROL).
si (pHeader-;NodeTypeCode == FS_MDE_TYPE_CODE){// la solicitud ha sido enviada al dispositivo de comunicación...// pruebe el valor del interruptor de códigos de control (controlCode){case IOCTL_FS_SEND_REQUEST:....caso IOCTL_FS_RECEIVE_RESPONSE:...caso IOCTL_FS_START:...caso IOCTL_FS_STOP:...caso IOCTL_FS_FILE_CACHE_CONTROL:... } estado de retorno;}
Si la petición no es para el dispositivo de comunicación, se comprueba si es para el dispositivo de control. El dispositivo de control puede procesar peticiones de gestión de discos como montar un disco (IOCTL_FS_ADD_DISK), desmontar un disco (IOCTL_FS_DELETE_DISK) u obtener una lista de las unidades existentes (IOCTL_FS_GET_DISKS).
Si no, si (pHeader->NodeTypeCode == FS_CDE_TYPE_CODE){// la solicitud ha sido enviada al dispositivo de control...// pruebe el valor del interruptor de códigos de control (controlCode){case IOCTL_FS_ADD_DISK: ...case IOCTL_FS_DELETE_DISK: ...case IOCTL_FS_GET_DISKS: ...default:...}
Por último, si la solicitud no se envía ni para el dispositivo de comunicación ni para el dispositivo de control, se remite al dispositivo redirector que se encarga del manejo de las solicitudes de almacenamiento extraíble, como la actualización de directorios, la consulta de nombres de volúmenes, etc.
// Peticiones estándar para el caso de almacenamiento extraíble IOCTL_DISK_MEDIA_REMOVAL:...caso IOCTL_STORAGE_MEDIA_REMOVAL:...caso IOCTL_DISK_EJECT_MEDIA:...caso IOCTL_STORAGE_EJECT_MEDIA:...caso IOCTL_DISK_CHECK_VERIFY:...caso IOCTL_STORAGE_CHECK_VERIFY:...caso IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:...caso IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:...caso IOCTL_DISK_IS_WRITABLE:...caso IOCTL_MF_GET_BASE_DEVICE_REF:...caso IOCTL_FILE_DIR_CHANGE_NOTIFY:...default:...
Herramienta de montaje
La herramienta de montaje es una aplicación que funciona con un dispositivo de control y permite al usuario montar o desmontar una unidad.
Ejemplo de implementación de montaje
La implementación de la herramienta de montaje más simple se ve así:
int _tmain(int argc, _TCHAR* argv[]){DWORD error = NO_ERROR;try{DiskInfo controlInfo;error = ParseArguments(argc, argv, controlInfo);...si
Deja una respuesta