CreateFileMapping, MapViewOfFile, handle leaking c++

人盡茶涼 提交于 2019-12-12 16:09:19

问题


Background: I am trying to create a memory mapped file that can be accessed by multiple processes. In the below code I only put in the code that pertains to the question I currently have to make things simpler. According to msdn I should be able to create a filemap, map the view of the file and close the handle I received from CreateFileMapping and the MapViewOfFile will keep my FileMap alive. The FileMap should be still accessible until I UnmapViewOfFile.

MSDN: CreateFileMapping function

Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released. Therefore, to fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling UnmapViewOfFile and close the file mapping object handle by calling CloseHandle. These functions can be called in any order.

Problem: After successfully mapping the view of the file and then closing the handle received by CreateFileMapping the FileMap no longer exists (it should still exist) and my MemMapFileReader is able to create a new map with error of 0. (When it should be receiving error 183 'already exists')

Bad Solution: Not closing the handle allows it to be accessed by the MemMapFileReader program but causes a handle leak in the MemMapFileCreator because the handle is never closed until the process is closed.

Question: What am I missing or doing wrong?

MemMapFileCreator

#include "stdafx.h"


#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#define BUF_SIZE 256
TCHAR szName[] = TEXT("MyFileMappingObject");
TCHAR szMsg[] = TEXT("Message from first process.");

int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;

hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,    // use paging file
    NULL,                    // default security
    PAGE_READWRITE,          // read/write access
    0,                       // maximum object size (high-order DWORD)
    BUF_SIZE,                // maximum object size (low-order DWORD)
    szName);                 // name of mapping object

DWORD lastError = GetLastError();
if (hMapFile == NULL)
{
    _tprintf(TEXT("Could not create file mapping object (%d).\n"),
        GetLastError());
    std::cin.get();
    return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile,   // handle to map object
    FILE_MAP_ALL_ACCESS, // read/write permission
    0,
    0,
    BUF_SIZE);

if (pBuf == NULL)
{
    _tprintf(TEXT("Could not map view of file (%d).\n"),
        GetLastError());

    CloseHandle(hMapFile);

    std::cin.get();
    return 1;
}


CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));

CloseHandle(hMapFile);

_getch();


UnmapViewOfFile(pBuf);
return 0;
}

MemMapFileReader

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#pragma comment(lib, "user32.lib")

#define BUF_SIZE 256
TCHAR szName[] = TEXT("MyFileMappingObject");

int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;

hMapFile = CreateFileMapping(
    INVALID_HANDLE_VALUE,
    NULL,
    PAGE_READWRITE,   // read/write access
    0,
    BUF_SIZE,
    szName);               // name of mapping object
DWORD lastError = GetLastError();
if (hMapFile == NULL)
{
    _tprintf(TEXT("Could not open file mapping object (%d).\n"),
        GetLastError());
    std::cin.get();
    return 1;
}

pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
    FILE_MAP_ALL_ACCESS,  // read/write permission
    0,
    0,
    BUF_SIZE);

if (pBuf == NULL)
{
    _tprintf(TEXT("Could not map view of file (%d).\n"),
        GetLastError());

    CloseHandle(hMapFile);

    std::cin.get();
    return 1;
}

MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);

UnmapViewOfFile(pBuf);

CloseHandle(hMapFile);

std::cin.get();
return 0;
}

回答1:


From MSDN:

Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released. Therefore, to fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling UnmapViewOfFile and close the file mapping object handle by calling CloseHandle. These functions can be called in any order.

The CreateFileMapping documentation says that to fully close a file all handles must be closed and the order does not matter. This logic is not invertible: you cannot close a handle and expect to use the other handles as if the file mapping wasn't 'closed'.

In other words, it means that to clean up the file mapping you need to close all handles in any order. However, you can not close the underlying file-mapping object and still use the views that depend on it.




回答2:


The CreateFileMapping() documentation says:

Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released.

The CloseHandle() documentation says:

In general, CloseHandle invalidates the specified object handle, decrements the object's handle count, and performs object retention checks. After the last handle to an object is closed, the object is removed from the system.

The mapped views simply keep the mapping object's reference count above zero until they are unmapped, but they do not keep the underlying file/mapping itself open.




回答3:


after you close Section handle view in creator process not disappear, until unmaping bat it name - "MyFileMappingObject" in NT namespace is destroyed. as result next call to CreateFileMapping - not found named object "MyFileMappingObject" and create new (when mast by your logic open existing). again - section not destroyed, but it name is destroyed. what you name - Bad Solution - really not bad - this is absolute normal - you mast not close handle to Section. and this is not handle leak - simply will be permanent open handle in your process. this situation is absolute normal

you use is NAMED section. after close it handle - section NOT DESTROYED - because exist also view of section, which hold it. but NAME of section is DESTROYED. and new call to create section - not open existing but create new.




回答4:


exist else one solution, which show that you all wrong. it require SE_CREATE_PERMANENT_PRIVILEGE, but for demo this is normal

STATIC_OBJECT_ATTRIBUTES_EX(g_oa, "\\BaseNamedObjects\\MyFileMappingObject", OBJ_CASE_INSENSITIVE|OBJ_PERMANENT, 0, 0);

NTSTATUS CreateAndWrite()
{
    NTSTATUS status;
    HANDLE hSection;
    LARGE_INTEGER Size = { PAGE_SIZE };
    if (0 <= (status = ZwCreateSection(&hSection, SECTION_MAP_READ|SECTION_MAP_WRITE, &g_oa, &Size, PAGE_READWRITE, SEC_COMMIT, 0)))
    {
        PVOID BaseAddress = 0;
        SIZE_T ViewSize = 0;
        if (0 <= (status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READWRITE)))
        {
            STATIC_WSTRING(szMsg, "Message from first process.");
            memcpy(BaseAddress, szMsg, sizeof(szMsg));
            ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
        }
        ZwClose(hSection);
    }

    return status;
}

NTSTATUS OpenReadAndDestroy()
{
    NTSTATUS status;
    HANDLE hSection;
    if (0 <= (status = ZwOpenSection(&hSection, SECTION_MAP_READ|DELETE, &g_oa)))
    {
        PVOID BaseAddress = 0;
        SIZE_T ViewSize = 0;
        if (0 <= (status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY)))
        {
            MessageBox(0, (PCWSTR)BaseAddress, 0, 0);
            ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
        }

        ZwMakeTemporaryObject(hSection);

        ZwClose(hSection);
    }

    return status;
}

        if (0 <= GotPermanentPrivilege())
        {
      if (0 <= CreateAndWrite())
      {
        // at this point - no one handles for "MyFileMappingObject" exist
        // we close all and even unmap view
        // but 1 reference to section object exist (by OBJ_PERMANENT flag)
        // and NAME is still exist
        // as result we can open,map and read data :)
        OpenReadAndDestroy();
      }
        }

what you say for this ? section is destroyed, after all handle closed ?? cannot use views ? D)

p.s. SE_CREATE_PERMANENT_PRIVILEGE - usually have only LocalSystem, but we can got it, if have SE_DEBUG_PRIVILEGE+SE_IMPERSONATE_PRIVILEGE - open "system" thread and impersonate on it



来源:https://stackoverflow.com/questions/29542495/createfilemapping-mapviewoffile-handle-leaking-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!