From 92834d5631cd2ca2a6031f129429da9f34a54fbc Mon Sep 17 00:00:00 2001 From: Kimmo Ollila Date: Sun, 15 Jan 2017 13:12:41 +0200 Subject: Add masm allocator for INTEGRITY Change-Id: I0d351f03416ff7ff596eccc88bb49abd48590b3f Reviewed-by: Antti Kokko Reviewed-by: Lars Knoll --- src/3rdparty/masm/masm.pri | 1 + src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp | 232 +++++++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp (limited to 'src/3rdparty') diff --git a/src/3rdparty/masm/masm.pri b/src/3rdparty/masm/masm.pri index afa1438974..c63cd5da66 100644 --- a/src/3rdparty/masm/masm.pri +++ b/src/3rdparty/masm/masm.pri @@ -13,6 +13,7 @@ HEADERS += $$PWD/wtf/RawPointer.h winrt: SOURCES += $$PWD/wtf/OSAllocatorWinRT.cpp else:win32: SOURCES += $$PWD/wtf/OSAllocatorWin.cpp +else:integrity: SOURCES += $$PWD/wtf/OSAllocatorIntegrity.cpp else: SOURCES += $$PWD/wtf/OSAllocatorPosix.cpp HEADERS += $$PWD/wtf/OSAllocator.h diff --git a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp new file mode 100644 index 0000000000..451ca147d1 --- /dev/null +++ b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) Rolland Dudemaine All rights reserved. +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "OSAllocator.h" + +#include +#include +#include +#include +#include + +#define ASP_PAGESIZE 0x1000 + +namespace WTF { +struct MRPair { + mutable MemoryRegion pmr; + mutable MemoryRegion vmr; + + mutable bool mapped; + + Address start; + + MRPair(Address _start = 0) : + pmr(0), + vmr(0), + mapped(false), + start(_start) + {} + + bool operator<(const MRPair& rhs) const + { + return this->start < rhs.start; + } +}; + +class MRContainer +{ +private: + std::set mrset; + LocalMutex iteratorGuard; +public: + MRContainer() { + CheckSuccess(CreateLocalMutex(&iteratorGuard)); + } + const MRPair* getMRPair(Address start) { + WaitForLocalMutex(iteratorGuard); + auto pairIterator = mrset.find(MRPair(start)); + const MRPair* result = ((pairIterator == mrset.end()) ? NULL : &(*pairIterator)); + ReleaseLocalMutex(iteratorGuard); + return result; + } + Error deleteMRPair(const MRPair* pair) { + int erased = 0; + WaitForLocalMutex(iteratorGuard); + erased = mrset.erase(*pair); + ReleaseLocalMutex(iteratorGuard); + if(erased == 1) + return Success; + else + return ArgumentError; /* An exception could be thrown in this case */ + } + Error insertMRPair(MRPair* pair) { + WaitForLocalMutex(iteratorGuard); + auto inserted = mrset.insert(*pair); + ReleaseLocalMutex(iteratorGuard); + if(inserted.second == true) + return Success; + else + return Failure; /* An exception could be thrown in this case */ + } + ~MRContainer() { + CheckSuccess(CloseLocalMutex(iteratorGuard)); + } +}; + +static MRContainer memoryRegionsContainer; + +Error setAttributes(MemoryRegion mr, bool writable, bool executable) +{ + Value attributes = MEMORY_READ; + if(writable) + attributes |= MEMORY_WRITE; + if(executable) + attributes |= MEMORY_EXEC; + return SetMemoryRegionAttributes(mr, attributes); +} + +void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable) +{ + MemoryRegion VMR; + + Address virtualStart, length; + + CheckSuccess(AllocateAnyMemoryRegion(__ghs_VirtualMemoryRegionPool, bytes, &VMR)); + CheckSuccess(GetMemoryRegionAddresses(VMR, &virtualStart, &length)); + Address addressIterator = virtualStart; + for(int i=0; i<(bytes + ASP_PAGESIZE -1)/ASP_PAGESIZE; i++) { + MRPair pair; + CheckSuccess(SplitMemoryRegion(VMR, ASP_PAGESIZE, &pair.vmr)); + CheckSuccess(setAttributes(pair.vmr, writable, executable)); + pair.start = addressIterator; + + memoryRegionsContainer.insertMRPair(&pair); + addressIterator += ASP_PAGESIZE; + } + + CheckSuccess(CloseMemoryRegion(VMR)); + return (void*)virtualStart; +} + +void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages) +{ + MemoryRegion VMR; + + Address virtualStart, length; + + CheckSuccess(AllocateAnyMemoryRegion(__ghs_VirtualMemoryRegionPool, bytes, &VMR)); + CheckSuccess(GetMemoryRegionAddresses(VMR, &virtualStart, &length)); + + Address addressIterator = virtualStart; + for(int i=0; i<(bytes + ASP_PAGESIZE -1)/ASP_PAGESIZE; i++) { + MRPair pair; + pair.start = addressIterator; + CheckSuccess(SplitMemoryRegion(VMR, ASP_PAGESIZE, &pair.vmr)); + CheckSuccess(setAttributes(pair.vmr, writable, executable)); + /* Do not map the first and the last pages if guard pages are required */ + if(!includesGuardPages || (i!=0 && i!= (bytes + ASP_PAGESIZE -1)/ASP_PAGESIZE -1)) + { + CheckSuccess(GetPageFromAddressSpaceFreeList(GetCurrentAddressSpace(), &pair.pmr)); + CheckSuccess(MapMemoryRegion(pair.vmr, pair.pmr)); + pair.mapped = true; + } + + memoryRegionsContainer.insertMRPair(&pair); + addressIterator += ASP_PAGESIZE; + } + + CheckSuccess(CloseMemoryRegion(VMR)); + return (void*)virtualStart; +} + +void OSAllocator::commit(void* address, size_t bytes, bool writable, bool executable) +{ + for(int i=0; i<(bytes + ASP_PAGESIZE -1)/ASP_PAGESIZE; i++) + { + const MRPair* pair = memoryRegionsContainer.getMRPair((Address)address); + if(pair == NULL) + return; + CheckSuccess(setAttributes(pair->vmr, writable, executable)); + CheckSuccess(GetPageFromAddressSpaceFreeList(GetCurrentAddressSpace(), &pair->pmr)); + CheckSuccess(MapMemoryRegion(pair->vmr, pair->pmr)); + pair->mapped = true; + address = (char*)address + ASP_PAGESIZE; + } +} + +void OSAllocator::decommit(void* address, size_t bytes) +{ + for(int i=0; i<(bytes + ASP_PAGESIZE -1)/ASP_PAGESIZE; i++) + { + const MRPair* pair = memoryRegionsContainer.getMRPair((Address)address); + if(pair == NULL) + return; + if(pair->mapped == false) + continue; + + CheckSuccess(UnmapMemoryRegion(pair->vmr)); + CheckSuccess(PutPageOnAddressSpaceFreeList(GetCurrentAddressSpace(), pair->pmr)); + pair->mapped = false; + address = (char*)address + ASP_PAGESIZE; + } +} + +void OSAllocator::releaseDecommitted(void* address, size_t bytes) +{ + for(int i=0; i<(bytes + ASP_PAGESIZE -1)/ASP_PAGESIZE; i++) + { + const MRPair* pair = memoryRegionsContainer.getMRPair((Address)address); + if(pair == NULL) + return; + /* Check if the memory is still committed */ + if(pair->mapped == true) + { + CheckSuccess(UnmapMemoryRegion(pair->vmr)); + CheckSuccess(PutPageOnAddressSpaceFreeList(GetCurrentAddressSpace(), pair->pmr)); + pair->mapped = false; + } + CheckSuccess(AddToMemoryPool(__ghs_VirtualMemoryRegionPool, pair->vmr)); + address = (char*)address + ASP_PAGESIZE; + + memoryRegionsContainer.deleteMRPair(pair); + } +} +} // namespace WTF -- cgit v1.2.3