HANDLE CreateFileMappingA(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCSTR lpName
);
[ lpName ]
File Mapping Object의 이름으로 NULL 인 경우 이름없이 만들어진다.
이미 mapping 되어있는 object의 name과 일치한다면 flProtect가 지정하는 보호기능을 사용하여 object에 access를 요청한다.
또 한가지 ! lpName에 "Global" 접두사를 붙이는 경우 (ex: lpName = "Global\\test.mmf") global namespace를 만들수 있는데
이는 SeCreateGlobalPrivilege 권한이 필요하다고 나와있다.
[
SeCreateGlobalPrivilege
]
알아낸 바로는 Administrators 그룹, 서비스 계정의 경우 기본으로 SeCreateGlobalPrivilege 권한이 있다고 한다.
따라서 일반 응용 프로그램의 경우에 일반적으로 관리자 권한으로 실행하지 않으면 CreateFileMapping 함수에서 0x5 값이 return 되며,
이는 ERROR_ACCESS_DENIED 이다.
<Sample Source>
#include <stdio.h>
#include <windows.h>
#define THREAD_NUM 10
#define MMFNAME "Global\\test_mmf"
#define PAGE_SIZE 0x100
int main()
{
HANDLE hMapping;
char *buf;
hMapping = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
PAGE_SIZE,
MMFNAME
);
if(hMapping == NULL) {
printf("hMapping is NULL (%d)\n", GetLastError());
return 0;
}
buf = (char *)MapViewOfFile(hMapping, PAGE_READONLY, 0, 0, PAGE_SIZE);
if(buf == NULL) {
printf("buf is NULL (%d)\n", GetLastError());
CloseHandle(hMapping);
return 0;
}
strcat(buf, "test mmf code !\0");
printf("BUF: %s\n", buf);
UnmapViewOfFile(buf);
CloseHandle(hMapping);
return 0;
}
<추가>
.NET과 관리자 권한으로 실행된 daemon에서 mmf 통신을 시도하려다가 access 에러가 발생하였다.
.NET이 먼저 FileMapping을 하면 관리자권한의 daemon process가 정상적으로 접근해서 read/write가 정상적으로 진행됬는데,
daemon process가 먼저 FileMapping을 한 경우에 .NET이 access denied 가 발생하였다.
아직까지는 정확한 원인은 모르지만 관리자권한의 daemon process에서 CreateFileMapping을 통해 생성한 object에 .NET이 접근할 때 해당 권한을 상속받지 못하는것으로 추측된다.
Stack Overflow에서 찾은 내용으로 해결하였는데 모두 이해하지는 못해서 잘못된 내용일 수도 있지만 우선은 정리해 둔다.
DWORD SetSecurityInfo(
HANDLE handle,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
PSID psidOwner,
PSID psidGroup,
PACL pDacl,
PACL pSacl
);
[ ObjectType ]
typedef enum _SE_OBJECT_TYPE {
SE_UNKNOWN_OBJECT_TYPE,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY,
SE_REGISTRY_WOW64_64KEY
} SE_OBJECT_TYPE;
handle object의 유형으로 enum으로 정의되어있는 상수들 중 하나를 넣으면 된다.
[ SecurityInfo ]
설정할 보안 정보의 유형을 나타내는 bit flag.
이 부분을 아직 이해를 못하였다.
[ pDacl ]
object에 대한 DACL 포인터로 access 권한을 설정할 수 있는것으로 보인다.
NULL로 설정할 경우 object에 대한 (모든) access 권한이 모든 사용자에게 부여된다.
<sample code1>
#include <stdio.h>
#include <windows.h>
#define THREAD_NUM 10
#define MMFNAME "Global\\test_mmf"
#define PAGE_SIZE 0x100
int main()
{
HANDLE hMapping;
char *buf;
hMapping = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
PAGE_SIZE,
MMFNAME
);
if(hMapping == NULL) {
printf("hMapping is NULL (%d)\n", GetLastError());
return 0;
}
SetSecurityInfo(hMapping , SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, (PACL) NULL, NULL);
buf = (char *)MapViewOfFile(hMapping ,FILE_MAP_ALL_ACCESS, 0, 0,PAGE_SIZE);
if(buf == NULL) {
printf("buf is NULL (%d)\n", GetLastError());
CloseHandle(hMapping);
return 0;
}
strcat(buf, "test mmf code !\0");
printf("BUF: %s\n", buf);
UnmapViewOfFile(buf);
CloseHandle(hMapping);
return 0;
}
댓글 없음:
댓글 쓰기