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;
|
arguments.permissions = ES_PERMISSION_WINDOW_MANAGER;
|
||||||
|
|
||||||
Array<EsMountPoint> initialMountPoints = {};
|
Array<EsMountPoint> initialMountPoints = {};
|
||||||
|
Array<EsHandle> handleDuplicateList = {};
|
||||||
|
Array<uint32_t> handleModeDuplicateList = {};
|
||||||
_EsNodeInformation settingsNode = {};
|
_EsNodeInformation settingsNode = {};
|
||||||
|
|
||||||
if (application->permissions & APPLICATION_PERMISSION_MANAGE_PROCESSES) {
|
if (application->permissions & APPLICATION_PERMISSION_MANAGE_PROCESSES) {
|
||||||
|
@ -1246,20 +1248,26 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
|
||||||
arguments.permissions |= ES_PERMISSION_POSIX_SUBSYSTEM;
|
arguments.permissions |= ES_PERMISSION_POSIX_SUBSYSTEM;
|
||||||
|
|
||||||
MountPoint root = *NodeFindMountPoint(EsLiteral("0:"));
|
MountPoint root = *NodeFindMountPoint(EsLiteral("0:"));
|
||||||
root.write = true;
|
|
||||||
root.prefixBytes = EsStringFormat(root.prefix, sizeof(root.prefix), "|POSIX:");
|
root.prefixBytes = EsStringFormat(root.prefix, sizeof(root.prefix), "|POSIX:");
|
||||||
initialMountPoints.Add(root);
|
initialMountPoints.Add(root);
|
||||||
|
|
||||||
|
handleDuplicateList.Add(root.base);
|
||||||
|
handleModeDuplicateList.Add(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
|
if (application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
|
||||||
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
|
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
|
||||||
initialMountPoints.Add(api.mountPoints[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;
|
arguments.permissions |= ES_PERMISSION_GET_VOLUME_INFORMATION;
|
||||||
} else {
|
} 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 = {};
|
EsMountPoint settings = {};
|
||||||
settings.prefixBytes = EsStringFormat(settings.prefix, sizeof(settings.prefix), "|Settings:");
|
settings.prefixBytes = EsStringFormat(settings.prefix, sizeof(settings.prefix), "|Settings:");
|
||||||
settings.base = settingsNode.handle;
|
settings.base = settingsNode.handle;
|
||||||
settings.write = true;
|
|
||||||
initialMountPoints.Add(settings);
|
initialMountPoints.Add(settings);
|
||||||
|
|
||||||
|
handleDuplicateList.Add(settings.base);
|
||||||
|
handleModeDuplicateList.Add(0);
|
||||||
} else {
|
} else {
|
||||||
settingsNode.handle = ES_INVALID_HANDLE;
|
settingsNode.handle = ES_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
arguments.data.initialMountPoints = EsConstantBufferCreate(initialMountPoints.array, initialMountPoints.Length() * sizeof(EsMountPoint), ES_CURRENT_PROCESS);
|
||||||
arguments.initialMountPoints = initialMountPoints.array;
|
handleDuplicateList.Add(arguments.data.initialMountPoints);
|
||||||
arguments.initialMountPointCount = initialMountPoints.Length();
|
handleModeDuplicateList.Add(0);
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO Update this.
|
arguments.handles = handleDuplicateList.array;
|
||||||
|
arguments.handleModes = handleModeDuplicateList.array;
|
||||||
|
arguments.handleCount = handleDuplicateList.Length();
|
||||||
|
EsAssert(handleDuplicateList.Length() == handleModeDuplicateList.Length());
|
||||||
|
|
||||||
error = EsProcessCreate(&arguments, &information);
|
error = EsProcessCreate(&arguments, &information);
|
||||||
EsHandleClose(arguments.executable);
|
EsHandleClose(arguments.executable);
|
||||||
|
|
||||||
initialMountPoints.Free();
|
initialMountPoints.Free();
|
||||||
if (settingsNode.handle) EsHandleClose(settingsNode.handle);
|
handleDuplicateList.Free();
|
||||||
|
handleModeDuplicateList.Free();
|
||||||
|
|
||||||
|
if (settingsNode.handle) {
|
||||||
|
EsHandleClose(settingsNode.handle);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ES_CHECK_ERROR(error)) {
|
if (!ES_CHECK_ERROR(error)) {
|
||||||
process = information.handle;
|
process = information.handle;
|
||||||
|
|
|
@ -1248,7 +1248,6 @@ struct EsMountPoint {
|
||||||
char prefix[16];
|
char prefix[16];
|
||||||
size_t prefixBytes;
|
size_t prefixBytes;
|
||||||
EsHandle base;
|
EsHandle base;
|
||||||
bool write;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EsProcessCreateData {
|
struct EsProcessCreateData {
|
||||||
|
@ -1269,6 +1268,7 @@ struct EsProcessStartupInformation {
|
||||||
struct EsProcessCreationArguments {
|
struct EsProcessCreationArguments {
|
||||||
EsHandle executable;
|
EsHandle executable;
|
||||||
EsHandle *handles; // Duplicated.
|
EsHandle *handles; // Duplicated.
|
||||||
|
uint32_t *handleModes; // The share arguments.
|
||||||
size_t handleCount;
|
size_t handleCount;
|
||||||
EsProcessCreateData data;
|
EsProcessCreateData data;
|
||||||
uint32_t flags;
|
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) {
|
bool HandleTable::CloseHandle(EsHandle handle) {
|
||||||
if (handle > HANDLE_TABLE_L1_ENTRIES * HANDLE_TABLE_L2_ENTRIES) {
|
if (handle > HANDLE_TABLE_L1_ENTRIES * HANDLE_TABLE_L2_ENTRIES) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -128,7 +128,7 @@ struct Process {
|
||||||
char cExecutableName[ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH + 1];
|
char cExecutableName[ES_SNAPSHOT_MAX_PROCESS_NAME_LENGTH + 1];
|
||||||
EsProcessCreateData data;
|
EsProcessCreateData data;
|
||||||
uint64_t permissions;
|
uint64_t permissions;
|
||||||
uint64_t creationFlags;
|
uint32_t creationFlags;
|
||||||
ProcessType type;
|
ProcessType type;
|
||||||
|
|
||||||
// Object management:
|
// Object management:
|
||||||
|
@ -144,7 +144,7 @@ struct Process {
|
||||||
// Termination:
|
// Termination:
|
||||||
bool allThreadsTerminated;
|
bool allThreadsTerminated;
|
||||||
bool terminating;
|
bool terminating;
|
||||||
int exitStatus;
|
int exitStatus; // TODO Remove this.
|
||||||
KEvent killedEvent;
|
KEvent killedEvent;
|
||||||
|
|
||||||
// Executable state:
|
// Executable state:
|
||||||
|
@ -156,6 +156,7 @@ struct Process {
|
||||||
// Statistics:
|
// Statistics:
|
||||||
uintptr_t cpuTimeSlices, idleTimeSlices;
|
uintptr_t cpuTimeSlices, idleTimeSlices;
|
||||||
|
|
||||||
|
// POSIX:
|
||||||
#ifdef ENABLE_POSIX_SUBSYSTEM
|
#ifdef ENABLE_POSIX_SUBSYSTEM
|
||||||
bool posixForking;
|
bool posixForking;
|
||||||
int pgid;
|
int pgid;
|
||||||
|
|
|
@ -229,13 +229,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
|
||||||
EsProcessCreationArguments arguments;
|
EsProcessCreationArguments arguments;
|
||||||
SYSCALL_READ(&arguments, argument0, sizeof(EsProcessCreationArguments));
|
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.
|
// Check the permissions.
|
||||||
|
|
||||||
SYSCALL_PERMISSION(ES_PERMISSION_PROCESS_CREATE);
|
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);
|
SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_NODE_TYPE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO.
|
// Check the handle list.
|
||||||
#if 0
|
|
||||||
Process *process = scheduler.SpawnProcess();
|
|
||||||
|
|
||||||
if (!process) {
|
if (arguments.handleCount > SYSCALL_BUFFER_LIMIT / sizeof(Handle)) {
|
||||||
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
|
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
process->creationFlags = arguments.flags;
|
EsHandle *inHandles;
|
||||||
process->creationArguments[CREATION_ARGUMENT_MAIN] = arguments.creationArgument.u;
|
SYSCALL_READ_HEAP(inHandles, (uintptr_t) arguments.handles, arguments.handleCount * sizeof(EsHandle));
|
||||||
process->permissions = arguments.permissions;
|
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 (!handles && arguments.handleCount) {
|
||||||
if (arguments.environmentBlockBytes > SYSCALL_BUFFER_LIMIT) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, K_PAGED);
|
||||||
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);
|
|
||||||
|
|
||||||
EsMountPoint *mountPoints = (EsMountPoint *) EsHeapAllocate(arguments.initialMountPointCount * sizeof(EsMountPoint), false, K_FIXED);
|
EsDefer(EsHeapFree(handles, sizeof(Handle) * arguments.handleCount, K_PAGED));
|
||||||
EsDefer(EsHeapFree(mountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint), K_FIXED));
|
|
||||||
SYSCALL_READ(mountPoints, (uintptr_t) arguments.initialMountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint));
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < arguments.initialMountPointCount; i++) {
|
EsError error = ES_SUCCESS;
|
||||||
// Open handles to the mount points for the new process.
|
|
||||||
// TODO Handling errors when opening handles.
|
for (uintptr_t i = 0; i < arguments.handleCount; i++) {
|
||||||
KObject object(currentProcess, mountPoints[i].base, KERNEL_OBJECT_NODE);
|
if (RESOLVE_HANDLE_NORMAL != currentProcess->handleTable.ResolveHandle(&handles[i], inHandles[i], HANDLE_SHARE_TYPE_MASK)) {
|
||||||
CHECK_OBJECT(object);
|
handles[i].object = nullptr;
|
||||||
if (!mountPoints[i].write) object.flags &= ~_ES_NODE_DIRECTORY_WRITE;
|
error = ES_FATAL_ERROR_INVALID_HANDLE;
|
||||||
OpenHandleToObject(object.object, object.type, object.flags);
|
|
||||||
mountPoints[i].base = process->handleTable.OpenHandle(object.object, object.flags, object.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
process->creationArguments[CREATION_ARGUMENT_INITIAL_MOUNT_POINTS]
|
|
||||||
= MakeConstantBuffer(mountPoints, arguments.initialMountPointCount * sizeof(EsMountPoint), process);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process->StartWithNode((KNode *) executableObject.object)) {
|
// Create the process.
|
||||||
CloseHandleToObject(process, KERNEL_OBJECT_PROCESS);
|
|
||||||
SYSCALL_RETURN(ES_ERROR_UNKNOWN, false);
|
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;
|
// Close handles.
|
||||||
processInformation.mainThread.tid = process->executableMainThread->id;
|
|
||||||
|
|
||||||
processInformation.mainThread.handle = currentProcess->handleTable.OpenHandle(process->executableMainThread, 0, KERNEL_OBJECT_THREAD);
|
for (uintptr_t i = 0; i < arguments.handleCount; i++) {
|
||||||
processInformation.handle = currentProcess->handleTable.OpenHandle(process, 0, KERNEL_OBJECT_PROCESS);
|
if (handles[i].object) {
|
||||||
|
CloseHandleToObject(handles[i].object, handles[i].type, handles[i].flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SYSCALL_WRITE(argument2, &processInformation, sizeof(EsProcessInformation));
|
SYSCALL_RETURN(error, error >= 0);
|
||||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_IMPLEMENT(ES_SYSCALL_SCREEN_FORCE_UPDATE) {
|
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_IMPLEMENT(ES_SYSCALL_HANDLE_SHARE) {
|
||||||
SYSCALL_HANDLE_2(argument0, KERNEL_OBJECT_SHMEM | KERNEL_OBJECT_CONSTANT_BUFFER | KERNEL_OBJECT_PROCESS
|
SYSCALL_HANDLE_2(argument0, HANDLE_SHARE_TYPE_MASK, share);
|
||||||
| KERNEL_OBJECT_DEVICE | KERNEL_OBJECT_NODE | KERNEL_OBJECT_EVENT | KERNEL_OBJECT_PIPE, share);
|
|
||||||
SYSCALL_HANDLE(argument1, KERNEL_OBJECT_PROCESS, process, Process);
|
SYSCALL_HANDLE(argument1, KERNEL_OBJECT_PROCESS, process, Process);
|
||||||
uint32_t sharedFlags = share.flags;
|
SYSCALL_RETURN(HandleShare(share, process, argument2), false);
|
||||||
|
|
||||||
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_IMPLEMENT(ES_SYSCALL_VOLUME_GET_INFORMATION) {
|
SYSCALL_IMPLEMENT(ES_SYSCALL_VOLUME_GET_INFORMATION) {
|
||||||
|
|
Loading…
Reference in New Issue