尝试使用 CreateFileMapping 和自定义 DACL 创建只读共享内存区域在 OpenFileMapping 中失败

Posted

技术标签:

【中文标题】尝试使用 CreateFileMapping 和自定义 DACL 创建只读共享内存区域在 OpenFileMapping 中失败【英文标题】:Attempting to create a read only shared memory area with CreateFileMapping and custom DACL fails in OpenFileMapping 【发布时间】:2020-02-14 01:15:10 【问题描述】:

我有一个客户端/服务器本地进程,我希望在一个公开的只读共享内存区域中为其提供一些内容。我能够在服务器端成功创建安全描述符和共享内存区域,但是当我尝试访问客户端的共享内存区域时,它失败并显示 ACCESS_DENIED (5) 除非安全描述符除了读取 (GR) 之外,还授予交互式用户 (GW) 写入访问权限。我试图避免向交互式用户授予写访问权限,以防止恶意进程破坏共享内存区域。

服务器端设计为作为 Windows 服务运行并使用全局部分,但我发现为了解决此问题,它以什么方式运行并不重要。

服务器端:

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

DWORD cbMemShare = 1024;
m_hShareMem = CreateFileMappingW(INVALID_HANDLE_VALUE, &attributes, PAGE_READWRITE|SEC_COMMIT, 0, cbMemShare, L"MyMemShare");

客户端(作为交互式用户):

// succeeds if SD has (A;;GRGW;;;IU), fails on (A;;GR;;;IU)
HANDLE hShareMem = OpenFileMappingW(PAGE_READONLY, 0, L"MyMemShare");
if (hShareMem == NULL)

    DWORD err = GetLastError();

底线是我想不出一种方法来使该内存可以读取而不可写入。服务器应该有读/写,客户端应该有读。我对此进行了研究,但没有找到任何确定的东西。

欣赏任何见解。

【问题讨论】:

【参考方案1】:

CreateFileMappingW()OpenFileMappingW() 使用不同的保护标志定义集。

CreateFileMappingW() 支持的标志列在CreateFileMappingW function 文档中:

fl保护

指定文件映射对象的页面保护。对象的所有映射视图都必须与此保护兼容。

此参数可以是以下值之一。

PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE PAGE_EXECUTE_WRITECOPY PAGE_READONLY PAGE_READWRITE PAGE_WRITECOPY

应用程序可以为文件映射对象指定一个或多个以下属性,方法是将它们与前面的页面保护值之一组合。

SEC_COMMIT SEC_IMAGE SEC_IMAGE_NO_EXECUTE SEC_LARGE_PAGES SEC_NOCACHE SEC_RESERVE SEC_WRITECOMBINE

OpenFileMappingW() 支持的标志列在OpenFileMappingW function 文档中:

dwDesiredAccess

对文件映射对象的访问。针对目标文件映射对象上的任何安全描述符检查此访问。有关值的列表,请参阅File Mapping Security and Access Rights。

File Mapping Security and Access Rights 文档说:

下表列出了特定于文件映射对象的访问权限。

FILE_MAP_ALL_ACCESS FILE_MAP_EXECUTE FILE_MAP_READ FILE_MAP_WRITE

调用OpenFileMappingW()时,需要使用FILE_MAP_READ而不是PAGE_READONLY。如果你看FILE_MAP_READPAGE_READONLY的数值:

winbase.h

#define FILE_MAP_READ   4
#define FILE_MAP_WRITE  2

winnt.h

#define PAGE_READONLY       0x02

如您所见,FILE_MAP_READ 是 4,但 PAGE_READONLY 是 2,这与 FILE_MAP_WRITE 的数值相同。因此,您的客户端实际上是在请求对映射的写访问权限,这就是安全描述符需要包含写访问权限的原因。

【讨论】:

谢谢你。我必须重新阅读文档 20 次,但看不到明显的内容。是的,我一直在请求写权限!

以上是关于尝试使用 CreateFileMapping 和自定义 DACL 创建只读共享内存区域在 OpenFileMapping 中失败的主要内容,如果未能解决你的问题,请参考以下文章

系统错误 0x5:CreateFileMapping()

无法释放 C++ 中 CreateFileMapping 和 MapViewOfFile 创建的共享内存

CreateFileMapping() 用于写入文件长度未知的文本

CreateFileMapping,MapViewOfFile,如何避免占用系统内存

Windows API一日一练(59)CreateFileMapping和MapViewOfFile函数

CreateFileMapping MapViewOfFile UnmapViewOfFile函数用法及示例