2009-05-22 16 views
5

Tengo un conjunto de aplicaciones Win32 que comparten información usando un segmento de memoria compartida creado con CreateFileMapping() y MapViewOfFile(). Una de las aplicaciones es un servicio del sistema; el resto lo inicia el usuario que ha iniciado sesión. En Windows XP, no hubo ningún problema. Llamamos a nuestros segmentos "Global \ Something" y todo estuvo bien.¿Cómo compartir la memoria entre servicios y procesos de usuario?

La seguridad adicional en Vista (y supuestamente en Windows 7) parece impedir que esta arquitectura funcione. Los usuarios normales no pueden crear objetos (error 5 de Win32) en el espacio de nombres global. MSDN indica que si la cuenta tiene el privilegio "crear global", entonces todo debería estar bien, pero esto no parece ser el caso en la práctica. Además, las características de "integridad" de Vista parecen impedir que los procesos de usuario de "baja integridad" accedan al objeto de memoria compartida creada por el servicio de "alta integridad". Parece que debería ser capaz de arreglar esto a través de un hechizo SetSecurityDescriptorSacl() mágico, pero estoy teniendo dificultades para aprender a hablar sacl.

Así que la pregunta es: ¿Cuál es la forma correcta de usar un segmento de memoria compartida entre servicios y procesos de usuario normales?

Para adelantarse a la sencilla respuesta de "simplemente apague el UAC", estamos en un entorno bastante bloqueado y eso no es posible.

Editar: Tanto el servicio como el proceso de usuario necesitan acceso de lectura/escritura al segmento.

Respuesta

9

La manera más simple sería hacer que su servicio cree la memoria compartida y especifique una DACL en CreateFileMapping que otorgue a los usuarios regulares acceso de lectura a la memoria compartida.

Los usuarios normales no tienen el privilegio de crear global, pero los servicios pueden tener este privilegio. Si debe hacer que sus usuarios creen la memoria compartida y luego hacer que el servicio la explore, podría tener un esquema de IPC donde su código de usuario envíe un mensaje al servicio que contiene el identificador de asignación de archivos, y el servicio llamaría a DuplicateHandle para obtener un referencia a eso Esto requeriría que su servicio se ejecute con el privilegio de depuración.

La forma más simple de crear una DACL es usar ConvertStringSecurityDescriptorToSecurityDescriptor, que toma una cadena en un formato llamado SDDL que especifica la ACL.

Writing Secure Code contiene un excelente capítulo sobre cómo crear DACL con SDDL.

// Error handling removed for brevity 
SECURITY_ATTRIBUTES security; 
ZeroMemory(&security, sizeof(security)); 
security.nLength = sizeof(security); 
ConvertStringSecurityDescriptorToSecurityDescriptor(
     L"D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)", 
     SDDL_REVISION_1, 
     &security.lpSecurityDescriptor, 
     NULL); 

CreateFileMapping(INVALID_HANDLE_VALUE, &security, 
       PAGE_READWRITE, sizeHigh, sizeLow, L"Global\\MyObject"); 

LocalFree(securityDescriptor.lpSecurityDescriptor); 

"D: P (A; OICI; GA ;;; SY) (A; OICI; GA ;;; BA) (A; OICI; GR ;;; IU)" especifica el DACL. D: P significa que se trata de una DACL (en lugar de una SACL ... raramente utilizaría las SACL) seguidas de varias cadenas de ACE que controlan quién tiene acceso. Cada uno es A (permitir) y permite objetos y contiene herencia (OICI). El primero en otorgar todos los accesos (GA - otorgar todo) a Sistema (SY) y Administradores (BA, administradores incorporados). Las últimas concesiones leen (GR) a usuarios interactivos (IU), que son usuarios que realmente iniciaron sesión en una sesión.

Una vez hecho esto, los usuarios normales deberían poder llamar OpenFileMapping para obtener un control de la asignación compartida y poder asignarla a su proceso. Como los usuarios normales tienen derechos limitados sobre el objeto, deberán asegurarse de abrirlo y asignarlo solo para lectura.

Si los usuarios necesitan acceso por escrito, reemplazará GR con GWGR. Tenga en cuenta que esto no es seguro: un usuario limitado podría modificar la memoria compartida mientras su servicio está leyendo e intentando analizar información, lo que provocaría un bloqueo de su servicio.

+1

Desafortunadamente, los usuarios normales también tienen que tener acceso de escritura – Clay

+1

Respuesta actualizada. Solo necesita modificar el descriptor de seguridad. – Michael

+0

Buena respuesta: estamos en una extraña situación de seguridad. Se confía en que los usuarios finales interactúen con el sistema (por lo tanto, pueden modificar la memoria propiedad del servicio), pero se requiere que limitemos su acceso (UAC debe estar activado, etc.). Bienvenido a la locura del mundo de la red gubernamental. – Clay

Cuestiones relacionadas