rewrite ES_SYSCALL_PROCESS_CREATE

This commit is contained in:
nakst 2021-09-11 18:14:47 +01:00
parent 243166f370
commit f140770dac
5 changed files with 126 additions and 80 deletions

View File

@ -1233,6 +1233,8 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
arguments.permissions = ES_PERMISSION_WINDOW_MANAGER;
Array<EsMountPoint> initialMountPoints = {};
Array<EsHandle> handleDuplicateList = {};
Array<uint32_t> handleModeDuplicateList = {};
_EsNodeInformation settingsNode = {};
if (application->permissions & APPLICATION_PERMISSION_MANAGE_PROCESSES) {
@ -1246,20 +1248,26 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
arguments.permissions |= ES_PERMISSION_POSIX_SUBSYSTEM;
MountPoint root = *NodeFindMountPoint(EsLiteral("0:"));
root.write = true;
root.prefixBytes = EsStringFormat(root.prefix, sizeof(root.prefix), "|POSIX:");
initialMountPoints.Add(root);
handleDuplicateList.Add(root.base);
handleModeDuplicateList.Add(0);
}
if (application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
initialMountPoints.Add(api.mountPoints[i]);
initialMountPoints[i].write = true;
handleDuplicateList.Add(api.mountPoints[i].base);
handleModeDuplicateList.Add(0);
}
arguments.permissions |= ES_PERMISSION_GET_VOLUME_INFORMATION;
} else {
initialMountPoints.Add(*NodeFindMountPoint(EsLiteral("|Fonts:")));
MountPoint fonts = *NodeFindMountPoint(EsLiteral("|Fonts:"));
initialMountPoints.Add(fonts);
handleDuplicateList.Add(fonts.base);
handleModeDuplicateList.Add(2 /* prevent write */);
}
{
@ -1270,25 +1278,34 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
EsMountPoint settings = {};
settings.prefixBytes = EsStringFormat(settings.prefix, sizeof(settings.prefix), "|Settings:");
settings.base = settingsNode.handle;
settings.write = true;
initialMountPoints.Add(settings);
handleDuplicateList.Add(settings.base);
handleModeDuplicateList.Add(0);
} else {
settingsNode.handle = ES_INVALID_HANDLE;
}
}
#if 0
arguments.initialMountPoints = initialMountPoints.array;
arguments.initialMountPointCount = initialMountPoints.Length();
#endif
arguments.data.initialMountPoints = EsConstantBufferCreate(initialMountPoints.array, initialMountPoints.Length() * sizeof(EsMountPoint), ES_CURRENT_PROCESS);
handleDuplicateList.Add(arguments.data.initialMountPoints);
handleModeDuplicateList.Add(0);
// TODO Update this.
arguments.handles = handleDuplicateList.array;
arguments.handleModes = handleModeDuplicateList.array;
arguments.handleCount = handleDuplicateList.Length();
EsAssert(handleDuplicateList.Length() == handleModeDuplicateList.Length());
error = EsProcessCreate(&arguments, &information);
EsHandleClose(arguments.executable);
initialMountPoints.Free();
if (settingsNode.handle) EsHandleClose(settingsNode.handle);
handleDuplicateList.Free();
handleModeDuplicateList.Free();
if (settingsNode.handle) {
EsHandleClose(settingsNode.handle);
}
if (!ES_CHECK_ERROR(error)) {
process = information.handle;

View File

@ -1248,7 +1248,6 @@ struct EsMountPoint {
char prefix[16];
size_t prefixBytes;
EsHandle base;
bool write;
};
struct EsProcessCreateData {
@ -1269,6 +1268,7 @@ struct EsProcessStartupInformation {
struct EsProcessCreationArguments {
EsHandle executable;
EsHandle *handles; // Duplicated.
uint32_t *handleModes; // The share arguments.
size_t handleCount;
EsProcessCreateData data;
uint32_t flags;

View File

@ -386,6 +386,33 @@ void CloseHandleToObject(void *object, KernelObjectType type, uint32_t flags) {
}
}
uintptr_t HandleShare(Handle share, Process *process, uint32_t mode, EsHandle at = ES_INVALID_HANDLE) {
#define HANDLE_SHARE_TYPE_MASK (KERNEL_OBJECT_SHMEM | KERNEL_OBJECT_CONSTANT_BUFFER | KERNEL_OBJECT_PROCESS \
| KERNEL_OBJECT_DEVICE | KERNEL_OBJECT_NODE | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_PIPE)
if ((share.type & HANDLE_SHARE_TYPE_MASK) == 0) {
KernelPanic("HandleShare - Invalid object type %x; allowed types are %x.\n", share.type, HANDLE_SHARE_TYPE_MASK);
}
uint32_t sharedFlags = share.flags;
// TODO Sort out flag modes.
if (share.type == KERNEL_OBJECT_SHMEM) {
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;
} else if (share.type == KERNEL_OBJECT_PIPE) {
}
if (!OpenHandleToObject(share.object, share.type, sharedFlags)) {
return ES_ERROR_PERMISSION_NOT_GRANTED;
} else {
return process->handleTable.OpenHandle(share.object, sharedFlags, share.type, at);
}
}
bool HandleTable::CloseHandle(EsHandle handle) {
if (handle > HANDLE_TABLE_L1_ENTRIES * HANDLE_TABLE_L2_ENTRIES) {
return false;

View File

@ -128,7 +128,7 @@ struct Process {
char cExecutableName[ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH + 1];
EsProcessCreateData data;
uint64_t permissions;
uint64_t creationFlags;
uint32_t creationFlags;
ProcessType type;
// Object management:
@ -144,7 +144,7 @@ struct Process {
// Termination:
bool allThreadsTerminated;
bool terminating;
int exitStatus;
int exitStatus; // TODO Remove this.
KEvent killedEvent;
// Executable state:
@ -156,6 +156,7 @@ struct Process {
// Statistics:
uintptr_t cpuTimeSlices, idleTimeSlices;
// POSIX:
#ifdef ENABLE_POSIX_SUBSYSTEM
bool posixForking;
int pgid;

View File

@ -229,13 +229,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
EsProcessCreationArguments arguments;
SYSCALL_READ(&arguments, argument0, sizeof(EsProcessCreationArguments));
EsProcessInformation processInformation;
EsMemoryZero(&processInformation, sizeof(EsProcessInformation));
if (arguments.handleCount > 65536) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
}
// Check the permissions.
SYSCALL_PERMISSION(ES_PERMISSION_PROCESS_CREATE);
@ -256,63 +249,86 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_NODE_TYPE, true);
}
// TODO.
#if 0
Process *process = scheduler.SpawnProcess();
// Check the handle list.
if (!process) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
if (arguments.handleCount > SYSCALL_BUFFER_LIMIT / sizeof(Handle)) {
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
}
process->creationFlags = arguments.flags;
process->creationArguments[CREATION_ARGUMENT_MAIN] = arguments.creationArgument.u;
process->permissions = arguments.permissions;
EsHandle *inHandles;
SYSCALL_READ_HEAP(inHandles, (uintptr_t) arguments.handles, arguments.handleCount * sizeof(EsHandle));
uint32_t *inHandleModes;
SYSCALL_READ_HEAP(inHandleModes, (uintptr_t) arguments.handleModes, arguments.handleCount * sizeof(uint32_t));
// TODO Free the process object if something fails here.
Handle *handles = (Handle *) EsHeapAllocate(sizeof(Handle) * arguments.handleCount, false, K_PAGED);
if (arguments.environmentBlockBytes) {
if (arguments.environmentBlockBytes > SYSCALL_BUFFER_LIMIT) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
SYSCALL_BUFFER((uintptr_t) arguments.environmentBlock, arguments.environmentBlockBytes, 1, false);
process->creationArguments[CREATION_ARGUMENT_ENVIRONMENT] = MakeConstantBuffer(arguments.environmentBlock, arguments.environmentBlockBytes, process);
}
if (arguments.initialMountPointCount) {
if (arguments.initialMountPointCount > ES_MOUNT_POINT_MAX_COUNT) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
if (!handles && arguments.handleCount) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, K_PAGED);
}
EsMountPoint *mountPoints = (EsMountPoint *) EsHeapAllocate(arguments.initialMountPointCount * sizeof(EsMountPoint), false, K_FIXED);
EsDefer(EsHeapFree(mountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint), K_FIXED));
SYSCALL_READ(mountPoints, (uintptr_t) arguments.initialMountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint));
EsDefer(EsHeapFree(handles, sizeof(Handle) * arguments.handleCount, K_PAGED));
for (uintptr_t i = 0; i < arguments.initialMountPointCount; i++) {
// Open handles to the mount points for the new process.
// TODO Handling errors when opening handles.
KObject object(currentProcess, mountPoints[i].base, KERNEL_OBJECT_NODE);
CHECK_OBJECT(object);
if (!mountPoints[i].write) object.flags &= ~_ES_NODE_DIRECTORY_WRITE;
OpenHandleToObject(object.object, object.type, object.flags);
mountPoints[i].base = process->handleTable.OpenHandle(object.object, object.flags, object.type);
EsError error = ES_SUCCESS;
for (uintptr_t i = 0; i < arguments.handleCount; i++) {
if (RESOLVE_HANDLE_NORMAL != currentProcess->handleTable.ResolveHandle(&handles[i], inHandles[i], HANDLE_SHARE_TYPE_MASK)) {
handles[i].object = nullptr;
error = ES_FATAL_ERROR_INVALID_HANDLE;
}
process->creationArguments[CREATION_ARGUMENT_INITIAL_MOUNT_POINTS]
= MakeConstantBuffer(mountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint), process);
}
if (!process->StartWithNode((KNode *) executableObject.object)) {
CloseHandleToObject(process, KERNEL_OBJECT_PROCESS);
SYSCALL_RETURN(ES_ERROR_UNKNOWN, false);
// Create the process.
if (error == ES_SUCCESS) {
Process *process = scheduler.SpawnProcess();
if (!process) {
error = ES_ERROR_INSUFFICIENT_RESOURCES;
} else {
process->creationFlags = arguments.flags;
process->data = arguments.data;
process->permissions = arguments.permissions;
// Duplicate handles.
for (uintptr_t i = 0; i < arguments.handleCount; i++) {
EsError error2 = HandleShare(handles[i], process, inHandleModes[i], inHandles[i]);
if (ES_CHECK_ERROR(error2)) {
error = error2;
break;
}
}
// Start the process.
if (error != ES_SUCCESS || !process->StartWithNode(executableObject)) {
// TODO Confirm that this frees the handle table.
error = ES_ERROR_UNKNOWN; // TODO.
CloseHandleToObject(process, KERNEL_OBJECT_PROCESS);
} else {
// Write the process information out.
EsProcessInformation processInformation;
EsMemoryZero(&processInformation, sizeof(EsProcessInformation));
processInformation.pid = process->id;
processInformation.mainThread.tid = process->executableMainThread->id;
processInformation.mainThread.handle = currentProcess->handleTable.OpenHandle(process->executableMainThread, 0, KERNEL_OBJECT_THREAD);
processInformation.handle = currentProcess->handleTable.OpenHandle(process, 0, KERNEL_OBJECT_PROCESS);
SYSCALL_WRITE(argument2, &processInformation, sizeof(EsProcessInformation));
}
}
}
processInformation.pid = process->id;
processInformation.mainThread.tid = process->executableMainThread->id;
// Close handles.
processInformation.mainThread.handle = currentProcess->handleTable.OpenHandle(process->executableMainThread, 0, KERNEL_OBJECT_THREAD);
processInformation.handle = currentProcess->handleTable.OpenHandle(process, 0, KERNEL_OBJECT_PROCESS);
for (uintptr_t i = 0; i < arguments.handleCount; i++) {
if (handles[i].object) {
CloseHandleToObject(handles[i].object, handles[i].type, handles[i].flags);
}
}
SYSCALL_WRITE(argument2, &processInformation, sizeof(EsProcessInformation));
SYSCALL_RETURN(ES_SUCCESS, false);
#endif
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
SYSCALL_RETURN(error, error >= 0);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_SCREEN_FORCE_UPDATE) {
@ -716,24 +732,9 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_CONSTANT_BUFFER_CREATE) {
}
SYSCALL_IMPLEMENT(ES_SYSCALL_HANDLE_SHARE) {
SYSCALL_HANDLE_2(argument0, KERNEL_OBJECT_SHMEM | KERNEL_OBJECT_CONSTANT_BUFFER | KERNEL_OBJECT_PROCESS
| KERNEL_OBJECT_DEVICE | KERNEL_OBJECT_NODE | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_PIPE, share);
SYSCALL_HANDLE_2(argument0, HANDLE_SHARE_TYPE_MASK, share);
SYSCALL_HANDLE(argument1, KERNEL_OBJECT_PROCESS, process, Process);
uint32_t sharedFlags = share.flags;
if (share.type == KERNEL_OBJECT_SHMEM) {
sharedFlags = argument2; // TODO Sort out flags.
} else if (share.type == KERNEL_OBJECT_NODE) {
sharedFlags = (argument2 & 1) && (share.flags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE)) ? ES_FILE_READ_SHARED : share.flags;
} else if (share.type == KERNEL_OBJECT_PIPE) {
// TODO Sort out flags.
}
if (!OpenHandleToObject(share.object, share.type, sharedFlags)) {
SYSCALL_RETURN(ES_ERROR_PERMISSION_NOT_GRANTED, false);
} else {
SYSCALL_RETURN(process->handleTable.OpenHandle(share.object, sharedFlags, share.type), false);
}
SYSCALL_RETURN(HandleShare(share, process, argument2), false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_VOLUME_GET_INFORMATION) {