From a9401068d7e96f8b9607486924be6890ecc1aeac Mon Sep 17 00:00:00 2001 From: nakst <> Date: Fri, 19 Nov 2021 19:02:02 +0000 Subject: [PATCH] permissions for shared regions --- desktop/api.cpp | 4 ++-- desktop/desktop.cpp | 2 +- desktop/os.header | 16 ++++++++++------ desktop/posix.cpp | 3 ++- desktop/syscall.cpp | 8 ++++---- desktop/text.cpp | 2 +- desktop/theme.cpp | 4 ++-- kernel/elf.cpp | 4 ++-- kernel/memory.cpp | 10 +++++----- kernel/objects.cpp | 2 +- kernel/scheduler.cpp | 7 ++++--- kernel/syscall.cpp | 23 +++++++++++++++++------ util/api_table.ini | 2 +- 13 files changed, 52 insertions(+), 35 deletions(-) diff --git a/desktop/api.cpp b/desktop/api.cpp index 3f74c91..649c29e 100644 --- a/desktop/api.cpp +++ b/desktop/api.cpp @@ -1512,8 +1512,8 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) { ThreadInitialise(&api.firstThreadLocalStorage); EsMessageMutexAcquire(); - api.global = (GlobalData *) EsObjectMap(api.startupInformation->globalDataRegion, - 0, sizeof(GlobalData), desktop ? ES_MAP_OBJECT_READ_WRITE : ES_MAP_OBJECT_READ_ONLY); + api.global = (GlobalData *) EsMemoryMapObject(api.startupInformation->globalDataRegion, + 0, sizeof(GlobalData), desktop ? ES_MEMORY_MAP_OBJECT_READ_WRITE : ES_MEMORY_MAP_OBJECT_READ_ONLY); } bool uiProcess = true; // TODO Determine this properly. diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index 72df698..eced823 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -1504,7 +1504,7 @@ void InstanceBlankTabCreate(EsMessage *message) { // TODO Generic icon and thumbnail cache in the API, based off the one from File Manager? size_t fileBytes; - void *file = EsFileMap(application->cExecutable, -1, &fileBytes, ES_MAP_OBJECT_READ_ONLY); + void *file = EsFileMap(application->cExecutable, -1, &fileBytes, ES_MEMORY_MAP_OBJECT_READ_ONLY); EsBundle bundle = { .base = (const BundleHeader *) file, .bytes = (ptrdiff_t) fileBytes }; if (file) { diff --git a/desktop/os.header b/desktop/os.header index a20fef2..46989d9 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -360,8 +360,6 @@ define ES_REJECTED (-2) define ES_LIST_VIEW_COLUMN_SORT_ASCENDING (1) define ES_LIST_VIEW_COLUMN_SORT_DESCENDING (2) -define ES_MAP_OBJECT_ALL (0) - define ES_TEXT_H_LEFT (1 << 0) define ES_TEXT_H_CENTER (1 << 1) define ES_TEXT_H_RIGHT (1 << 2) @@ -407,9 +405,12 @@ define _ES_NODE_NO_WRITE_BASE (0x080000) define ES_DIRECTORY_CHILDREN_UNKNOWN ((EsFileOffsetDifference) (-1)) -define ES_MAP_OBJECT_READ_WRITE (0) -define ES_MAP_OBJECT_READ_ONLY (1) -define ES_MAP_OBJECT_COPY_ON_WRITE (2) +define ES_MEMORY_MAP_OBJECT_ALL (0) // Set size to this to map the entire object. +define ES_MEMORY_MAP_OBJECT_READ_WRITE (1 << 0) +define ES_MEMORY_MAP_OBJECT_READ_ONLY (1 << 1) +define ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE (1 << 2) // Files only. + +define ES_SHARED_MEMORY_READ_WRITE (1 << 0) define ES_STRING_FORMAT_ENOUGH_SPACE (-1) @@ -740,6 +741,9 @@ define ES_SCROLL_X_DRAG (1 << 0) define ES_SCROLL_Y_DRAG (1 << 1) private define ES_SCROLL_MANUAL (1 << 2) // The parent is responsible for updating the position of the scroll bars. +define ES_SUBSYSTEM_ID_NATIVE (0) +define ES_SUBSYSTEM_ID_POSIX (1) + include desktop/icons.header enum EsFatalError { @@ -2101,7 +2105,7 @@ function uint8_t EsMemorySumBytes(uint8_t *data, size_t bytes); function void EsMemoryUnreserve(void *pointer, size_t size = 0); // Must cover the entire reserved region. Leave size 0 if you don't know the size. function void EsMemoryZero(void *destination, size_t bytes); -function void *EsObjectMap(EsHandle object, uintptr_t offset, size_t size, unsigned flags); +function void *EsMemoryMapObject(EsHandle object, uintptr_t offset, size_t size, uint32_t flags); // Standard functions. diff --git a/desktop/posix.cpp b/desktop/posix.cpp index d3ae675..f16458a 100644 --- a/desktop/posix.cpp +++ b/desktop/posix.cpp @@ -697,10 +697,11 @@ void EsPOSIXInitialise(int *argc, char ***argv) { // Get the arguments and environment. - EsHandle environmentHandle = startupInformation->data.environment; + EsHandle environmentHandle = startupInformation->data.subsystemData; char *environmentBuffer = (char *) "./application\0\0LANG=en_US.UTF-8\0PWD=/\0HOME=/\0PATH=/Applications/POSIX/bin\0TMPDIR=/Applications/POSIX/tmp\0\0"; if (environmentHandle) { + EsAssert(startupInformation->data.subsystemID == ES_SUBSYSTEM_ID_POSIX); environmentBuffer = (char *) EsHeapAllocate(ARG_MAX, false); EsConstantBufferRead((EsHandle) environmentHandle, environmentBuffer); EsHandleClose((EsHandle) environmentHandle); diff --git a/desktop/syscall.cpp b/desktop/syscall.cpp index 6dd7015..3e8f031 100644 --- a/desktop/syscall.cpp +++ b/desktop/syscall.cpp @@ -299,7 +299,7 @@ EsHandle EsMemoryShare(EsHandle sharedMemoryRegion, EsHandle targetProcess, bool return EsSyscall(ES_SYSCALL_HANDLE_SHARE, sharedMemoryRegion, targetProcess, readOnly, 0); } -void *EsObjectMap(EsHandle sharedMemoryRegion, uintptr_t offset, size_t size, unsigned flags) { +void *EsMemoryMapObject(EsHandle sharedMemoryRegion, uintptr_t offset, size_t size, unsigned flags) { intptr_t result = EsSyscall(ES_SYSCALL_MEMORY_MAP_OBJECT, sharedMemoryRegion, offset, size, flags); if (result >= 0) { @@ -425,7 +425,7 @@ void *EsFileStoreMap(EsFileStore *file, size_t *fileSize, uint32_t flags) { EsFileOffsetDifference size = EsFileStoreGetSize(file); if (size == -1) return nullptr; *fileSize = size; - return EsObjectMap(file->handle, 0, size, flags); + return EsMemoryMapObject(file->handle, 0, size, flags); } else if (file->type == FILE_STORE_PATH) { return EsFileMap(file->path, file->pathBytes, fileSize, flags); } else if (file->type == FILE_STORE_EMBEDDED_FILE) { @@ -530,13 +530,13 @@ EsError EsFileDelete(EsHandle handle) { void *EsFileMap(const char *path, ptrdiff_t pathBytes, size_t *fileSize, uint32_t flags) { EsFileInformation information = EsFileOpen(path, pathBytes, - ES_NODE_FAIL_IF_NOT_FOUND | ((flags & ES_MAP_OBJECT_READ_WRITE) ? ES_FILE_WRITE : ES_FILE_READ)); + ES_NODE_FAIL_IF_NOT_FOUND | ((flags & ES_MEMORY_MAP_OBJECT_READ_WRITE) ? ES_FILE_WRITE : ES_FILE_READ)); if (ES_CHECK_ERROR(information.error)) { return nullptr; } - void *base = EsObjectMap(information.handle, 0, information.size, flags); + void *base = EsMemoryMapObject(information.handle, 0, information.size, flags); EsHandleClose(information.handle); if (fileSize) *fileSize = information.size; return base; diff --git a/desktop/text.cpp b/desktop/text.cpp index fe3d721..99dea7f 100644 --- a/desktop/text.cpp +++ b/desktop/text.cpp @@ -758,7 +758,7 @@ Font FontGet(EsFont key) { // EsPrint("Loading font from '%z' (f%d/w%d/i%d).\n", file, key.family, key.weight, key.italic); size_t size; - void *data = EsFileStoreMap(file, &size, ES_MAP_OBJECT_READ_ONLY); + void *data = EsFileStoreMap(file, &size, ES_MEMORY_MAP_OBJECT_READ_ONLY); if (!data) { EsPrint("Could not load font (f%d/w%d/i%d).\n", key.family, key.weight, key.italic); diff --git a/desktop/theme.cpp b/desktop/theme.cpp index ec431b4..11fccce 100644 --- a/desktop/theme.cpp +++ b/desktop/theme.cpp @@ -1312,7 +1312,7 @@ bool ThemeInitialise() { size_t cursorsBitmapBytes; const void *cursorsBitmap = EsBundleFind(&bundleDesktop, EsLiteral("Cursors.png"), &cursorsBitmapBytes); theming.cursorData = EsMemoryCreateShareableRegion(ES_THEME_CURSORS_WIDTH * ES_THEME_CURSORS_HEIGHT * 4); - void *destination = EsObjectMap(theming.cursorData, 0, ES_THEME_CURSORS_WIDTH * ES_THEME_CURSORS_HEIGHT * 4, ES_MAP_OBJECT_READ_WRITE); + void *destination = EsMemoryMapObject(theming.cursorData, 0, ES_THEME_CURSORS_WIDTH * ES_THEME_CURSORS_HEIGHT * 4, ES_MEMORY_MAP_OBJECT_READ_WRITE); LoadImage(cursorsBitmap, cursorsBitmapBytes, destination, ES_THEME_CURSORS_WIDTH, ES_THEME_CURSORS_HEIGHT, true); EsObjectUnmap(destination); } @@ -1320,7 +1320,7 @@ bool ThemeInitialise() { theming.cursors.width = ES_THEME_CURSORS_WIDTH; theming.cursors.height = ES_THEME_CURSORS_HEIGHT; theming.cursors.stride = ES_THEME_CURSORS_WIDTH * 4; - theming.cursors.bits = EsObjectMap(theming.cursorData, 0, ES_MAP_OBJECT_ALL, ES_MAP_OBJECT_READ_ONLY); + theming.cursors.bits = EsMemoryMapObject(theming.cursorData, 0, ES_MEMORY_MAP_OBJECT_ALL, ES_MEMORY_MAP_OBJECT_READ_ONLY); theming.cursors.fullAlpha = true; theming.cursors.readOnly = true; diff --git a/kernel/elf.cpp b/kernel/elf.cpp index c2bd160..90c704b 100644 --- a/kernel/elf.cpp +++ b/kernel/elf.cpp @@ -154,7 +154,7 @@ EsError KLoadELF(KNode *node, KLoadedExecutable *executable) { // Map the bundle file. if (!MMMapFile(thisProcess->vmm, (FSFile *) node, - 0, fileSize, ES_MAP_OBJECT_READ_ONLY, + 0, fileSize, ES_MEMORY_MAP_OBJECT_READ_ONLY, (uint8_t *) header.mapAddress)) { return ES_ERROR_INSUFFICIENT_RESOURCES; } @@ -239,7 +239,7 @@ EsError KLoadELF(KNode *node, KLoadedExecutable *executable) { success = MMMapFile(thisProcess->vmm, (FSFile *) node, executableOffset + fileOffset, zeroStart - fileStart, - ES_MAP_OBJECT_COPY_ON_WRITE, + ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE, (uint8_t *) fileStart, end - zeroStart); if (success) { diff --git a/kernel/memory.cpp b/kernel/memory.cpp index 0764d79..3d6482d 100644 --- a/kernel/memory.cpp +++ b/kernel/memory.cpp @@ -1015,7 +1015,7 @@ void MMUnreserve(MMSpace *space, MMRegion *remove, bool unmapPages, bool guardRe } void *MMMapFile(MMSpace *space, FSFile *node, EsFileOffset offset, size_t bytes, int protection, void *baseAddress, size_t zeroedBytes, uint32_t additionalFlags) { - if (protection != ES_MAP_OBJECT_READ_ONLY && protection != ES_MAP_OBJECT_COPY_ON_WRITE) { + if (protection != ES_MEMORY_MAP_OBJECT_READ_ONLY && protection != ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE) { return nullptr; } @@ -1025,7 +1025,7 @@ void *MMMapFile(MMSpace *space, FSFile *node, EsFileOffset offset, size_t bytes, MMRegion *region = nullptr; uint64_t fileHandleFlags = ES_NODE_PREVENT_RESIZE - | (protection == ES_MAP_OBJECT_READ_WRITE ? ES_FILE_WRITE_SHARED : ES_FILE_READ_SHARED); + | (protection == ES_MEMORY_MAP_OBJECT_READ_WRITE ? ES_FILE_WRITE_SHARED : ES_FILE_READ_SHARED); bool decommit = false; // Register a handle to the node. @@ -1056,8 +1056,8 @@ void *MMMapFile(MMSpace *space, FSFile *node, EsFileOffset offset, size_t bytes, // Reserve the region. region = MMReserve(space, bytes + zeroedBytes, MM_REGION_FILE | additionalFlags - | ((protection == ES_MAP_OBJECT_READ_ONLY || protection == ES_MAP_OBJECT_COPY_ON_WRITE) ? MM_REGION_READ_ONLY : 0) - | (protection == ES_MAP_OBJECT_COPY_ON_WRITE ? MM_REGION_COPY_ON_WRITE : 0), + | ((protection == ES_MEMORY_MAP_OBJECT_READ_ONLY || protection == ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE) ? MM_REGION_READ_ONLY : 0) + | (protection == ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE ? MM_REGION_COPY_ON_WRITE : 0), baseAddress ? (uintptr_t) baseAddress - offsetIntoPage : 0); if (!region) { @@ -1066,7 +1066,7 @@ void *MMMapFile(MMSpace *space, FSFile *node, EsFileOffset offset, size_t bytes, // Commit copy on write regions. - if (protection == ES_MAP_OBJECT_COPY_ON_WRITE) { + if (protection == ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE) { if (!MMCommit(bytes + zeroedBytes, false)) { goto fail; } diff --git a/kernel/objects.cpp b/kernel/objects.cpp index 41fa53b..08344fe 100644 --- a/kernel/objects.cpp +++ b/kernel/objects.cpp @@ -373,7 +373,7 @@ uintptr_t HandleShare(Handle share, Process *process, uint32_t mode, EsHandle at // TODO Sort out flag modes. if (share.type == KERNEL_OBJECT_SHMEM) { - sharedFlags = mode; + sharedFlags &= mode; } else if (share.type == KERNEL_OBJECT_NODE) { sharedFlags = (mode & 1) && (share.flags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE)) ? ES_FILE_READ_SHARED : share.flags; if (mode & 2) sharedFlags &= ~_ES_NODE_DIRECTORY_WRITE; diff --git a/kernel/scheduler.cpp b/kernel/scheduler.cpp index b7c5952..eb240b0 100644 --- a/kernel/scheduler.cpp +++ b/kernel/scheduler.cpp @@ -762,9 +762,10 @@ void ProcessLoadExecutable() { startupInformation->tlsBytes = application.tlsBytes; startupInformation->timeStampTicksPerMs = timeStampTicksPerMs; - if (OpenHandleToObject(mmGlobalDataRegion, KERNEL_OBJECT_SHMEM, ES_FLAGS_DEFAULT)) { - // TODO Write protection. - startupInformation->globalDataRegion = thisProcess->handleTable.OpenHandle(mmGlobalDataRegion, ES_FLAGS_DEFAULT, KERNEL_OBJECT_SHMEM); + uint32_t globalDataRegionFlags = thisProcess->type == PROCESS_DESKTOP ? ES_SHARED_MEMORY_READ_WRITE : ES_FLAGS_DEFAULT; + + if (OpenHandleToObject(mmGlobalDataRegion, KERNEL_OBJECT_SHMEM, globalDataRegionFlags)) { + startupInformation->globalDataRegion = thisProcess->handleTable.OpenHandle(mmGlobalDataRegion, globalDataRegionFlags, KERNEL_OBJECT_SHMEM); } EsMemoryCopy(&startupInformation->data, &thisProcess->data, sizeof(EsProcessCreateData)); diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 7525566..e55b2f1 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -63,7 +63,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_ALLOCATE) { if (argument0 > ES_SHARED_MEMORY_MAXIMUM_SIZE) SYSCALL_RETURN(ES_FATAL_ERROR_OUT_OF_RANGE, true); MMSharedRegion *region = MMSharedCreateRegion(argument0, false, 0); if (!region) SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false); - SYSCALL_RETURN(currentProcess->handleTable.OpenHandle(region, 0, KERNEL_OBJECT_SHMEM), false); + SYSCALL_RETURN(currentProcess->handleTable.OpenHandle(region, ES_SHARED_MEMORY_READ_WRITE, KERNEL_OBJECT_SHMEM), false); } else { EsMemoryProtection protection = (EsMemoryProtection) argument2; uint32_t flags = MM_REGION_USER; @@ -546,22 +546,33 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_THREAD_CREATE) { SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_MAP_OBJECT) { SYSCALL_HANDLE_2(argument0, (KernelObjectType) (KERNEL_OBJECT_SHMEM | KERNEL_OBJECT_NODE), object); + if (((argument3 & ES_MEMORY_MAP_OBJECT_READ_WRITE) ? 1 : 0) + + ((argument3 & ES_MEMORY_MAP_OBJECT_READ_ONLY) ? 1 : 0) + + ((argument3 & ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE) ? 1 : 0) != 1) { + SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_FILE_ACCESS, true); + } + if (object.type == KERNEL_OBJECT_SHMEM) { - // TODO Access permissions and modes. MMSharedRegion *region = (MMSharedRegion *) object.object; - if (argument2 == ES_MAP_OBJECT_ALL) { + if (argument2 == ES_MEMORY_MAP_OBJECT_ALL) { argument2 = region->sizeBytes; } - uintptr_t address = (uintptr_t) MMMapShared(currentVMM, region, argument1, argument2, MM_REGION_USER); + if ((argument3 == ES_MEMORY_MAP_OBJECT_READ_WRITE && (~object.flags & ES_SHARED_MEMORY_READ_WRITE)) + || argument3 == ES_MEMORY_MAP_OBJECT_COPY_ON_WRITE) { + SYSCALL_RETURN(ES_FATAL_ERROR_INSUFFICIENT_PERMISSIONS, true); + } + + uint32_t flags = MM_REGION_USER | ((argument3 & ES_MEMORY_MAP_OBJECT_READ_ONLY) ? MM_REGION_READ_ONLY : 0); + uintptr_t address = (uintptr_t) MMMapShared(currentVMM, region, argument1 /* offset */, argument2 /* bytes */, flags); SYSCALL_RETURN(address, false); } else if (object.type == KERNEL_OBJECT_NODE) { KNode *file = (KNode *) object.object; if (file->directoryEntry->type != ES_NODE_FILE) SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_NODE_TYPE, true); - if (argument3 == ES_MAP_OBJECT_READ_WRITE) { + if (argument3 == ES_MEMORY_MAP_OBJECT_READ_WRITE) { if (!(object.flags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE))) { SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_FILE_ACCESS, true); } @@ -571,7 +582,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_MAP_OBJECT) { } } - if (argument2 == ES_MAP_OBJECT_ALL) { + if (argument2 == ES_MEMORY_MAP_OBJECT_ALL) { argument2 = file->directoryEntry->totalSize; } diff --git a/util/api_table.ini b/util/api_table.ini index 3303013..51a6db8 100644 --- a/util/api_table.ini +++ b/util/api_table.ini @@ -91,7 +91,7 @@ EsMemoryCreateShareableRegion=89 EsMemoryShare=90 EsMemorySumBytes=91 EsMemoryZero=92 -EsObjectMap=93 +EsMemoryMapObject=93 EsAssertionFailure=94 EsDrawInvert=95 EsFileControl=96