mirror of https://gitlab.com/nakst/essence
rewrite ES_SYSCALL_PROCESS_CREATE
This commit is contained in:
parent
243166f370
commit
f140770dac
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue