问题描述
我有一组共享使用带有的CreateFileMapping()创建共享内存段信息的Win32应用程序
和 MapViewOfFile()
。一项所述的应用是一个系统的服务;其余的是由登录用户启动。在Windows XP中,没有任何问题。我们命名我们的部分全球\\东西,一切都很好。
I have a set of Win32 applications that share information using a shared memory segment created with CreateFileMapping()
and MapViewOfFile()
. One of the applications is a system service; the remainder are started by the logged-in user. On Windows XP, there was no problem. We named our segments "Global\Something" and all was well.
在Vista中(和assumedly的Windows 7)的额外的安全性显得prevent这种架构无法正常工作。普通用户不允许在全局命名空间创建(Win32错误5)对象。在MSDN表明,如果帐户有创建全局特权,那么所有应该很好,但是这似乎并没有在实践中的情况。
此外,Vista的诚信的特点似乎prevent访问高诚信的服务创建共享内存对象的低诚信的用户进程。它看起来像我应该能够通过某种神奇的 SetSecurityDescriptorSacl()
咒语来解决这个问题,但我有困难学习说话SACL。
The additional security in Vista (and assumedly Windows 7) appears to prevent this architecture from working. Normal users are not allowed to create (Win32 error 5) objects in the global namespace. The MSDN indicates that if the account has the "create global" privilege then all should be well, but this does not seem to be the case in practice.Also, Vista’s "integrity" features appear to prevent the "low integrity" user processes from accessing the "high integrity" service-created shared memory object. It looks like I should be able to fix this via some magical SetSecurityDescriptorSacl()
incantation, but I’m having difficulty learning to speak sacl.
所以,问题是:什么是使用服务和普通用户进程之间共享内存段的正确方法
要preempt的刚关掉UAC简单的答案,我们正处在一个相当锁定的环境,这是不是一种可能性。
To preempt the easy answer of "just turn off UAC", we’re in a fairly locked-down environment and that is not a possibility.
编辑:两个服务和用户进程需要读的段/写访问
Both the service and the user process need read/write access to the segment.
推荐答案
最简单的方法就是让你的服务创建共享内存和的CreateFileMapping授予普通用户读取访问共享内存指定DACL。
The simplest way would be to have your service create the shared memory and specify a DACL in CreateFileMapping that grants regular users read access to the shared memory.
普通用户不具备创建全局特权,但服务可以有这个特权。如果你必须有你的用户创建共享内存,然后让服务探测器它,你可以有您的用户code将消息发送到包含文件映射句柄服务的IPC方案,那么该服务会叫DuplicateHandle得到它的参考。这需要你的服务与调试权限运行。
Normal users don't have the create global privilege, but services can have this privilege. If you must have your users create the shared memory and then have the service probe it, you could have an IPC scheme where your user code sends a message to the service containing the file mapping handle, and the service would then call DuplicateHandle to get a reference to it. This would require your service to run with the debug privilege.
创建DACL的最简单的方法是使用ConvertStringSecurityDescriptorToSecurityDescriptor,这需要一个串在一个称为SDDL指定访问控制列表格式
The simplest way to create a DACL is to use ConvertStringSecurityDescriptorToSecurityDescriptor, which takes a string in a format called SDDL specifying the ACL.
包含有关创建DACL与SDDL一个优秀的篇章。
Writing Secure Code contains an excellent chapter on creating DACL's with 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)指定DACL。 D:P表示这是一个DACL(而不是一个SACL你很少使用SACL的。),其次是几个ACE字符串用来控制谁可以访问。每个人都是(允许),并允许对象包含继承(OICI)。第一次授予的所有访问(GA - 授予所有)至系统(SY)和管理员(BA,内置administratos)。最后授予读取(GR)互动用户(IU),这是用户实际登录到会话。
"D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GR;;;IU)" specifies the DACL. D:P means this is a DACL (instead of a SACL . . . you'd rarely use SACL's) followed by several ACE strings which control who gets access. Each one is A (allow) and allows for object and contains inheritance (OICI). The first to grant all access (GA - grant all) to System (SY) and Administrators (BA, built-in administratos). The last grants read (GR) to interactive users (IU), which are users actually logged on to a session.
一旦做到这一点,正常用户应该能够调用OpenFileMapping得到的句柄共享映射,并且能够将其映射到它们的过程。由于普通用户已经限制了对象的权利,他们就必须一定要打开它,它映射为只读访问。
Once this is done, normal users should be able to call OpenFileMapping to get a handle to the shared mapping, and be able to map it into their process. Since normal users have limited rights on the object, they'll have to be sure to open it and map it for read-access only.
如果用户需要写acccess,你会用GWGR替代GR。请注意,这是不安全的 - 那有限的用户将能够修改共享内存,而您的服务已阅读和试图解析信息,从而导致你的服务崩溃
If users need write-acccess, you'd replace GR with GWGR. Note that this isn't secure - a limited user would then be able to modify the shared memory while your service is reading and trying to parse information, resulting in a crash of your service.
这篇关于如何共享服务和用户进程之间的内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!