diff --git a/include/kernel/syscall.h b/include/kernel/syscall.h index 4c059b2..edd16b9 100644 --- a/include/kernel/syscall.h +++ b/include/kernel/syscall.h @@ -121,6 +121,9 @@ extern kern_status_t sys_address_space_release( extern kern_status_t sys_kern_log(const char *s); extern kern_status_t sys_kern_handle_close(kern_handle_t handle); +extern kern_status_t sys_kern_handle_duplicate( + kern_handle_t handle, + kern_handle_t *out); extern kern_status_t sys_kern_config_get( kern_config_key_t key, void *ptr, diff --git a/libmango/arch/x86_64/syscall.S b/libmango/arch/x86_64/syscall.S index d9fd17c..ed728fb 100644 --- a/libmango/arch/x86_64/syscall.S +++ b/libmango/arch/x86_64/syscall.S @@ -77,6 +77,7 @@ SYSCALL_GATE address_space_release SYS_ADDRESS_SPACE_RELEASE 3 SYSCALL_GATE kern_log SYS_KERN_LOG 1 SYSCALL_GATE kern_handle_close SYS_KERN_HANDLE_CLOSE 1 +SYSCALL_GATE kern_handle_duplicate SYS_KERN_HANDLE_DUPLICATE 2 SYSCALL_GATE kern_config_get SYS_KERN_CONFIG_GET 3 SYSCALL_GATE kern_config_set SYS_KERN_CONFIG_SET 3 diff --git a/libmango/include-user/mango/handle.h b/libmango/include-user/mango/handle.h index 8d8196d..f0fee10 100644 --- a/libmango/include-user/mango/handle.h +++ b/libmango/include-user/mango/handle.h @@ -5,5 +5,8 @@ #include extern kern_status_t kern_handle_close(kern_handle_t handle); +extern kern_status_t kern_handle_duplicate( + kern_handle_t handle, + kern_handle_t *out); #endif diff --git a/syscall/dispatch.c b/syscall/dispatch.c index 515c4fa..f9bca21 100644 --- a/syscall/dispatch.c +++ b/syscall/dispatch.c @@ -23,6 +23,7 @@ static const virt_addr_t syscall_table[] = { SYSCALL_TABLE_ENTRY(ADDRESS_SPACE_RELEASE, address_space_release), SYSCALL_TABLE_ENTRY(KERN_LOG, kern_log), SYSCALL_TABLE_ENTRY(KERN_HANDLE_CLOSE, kern_handle_close), + SYSCALL_TABLE_ENTRY(KERN_HANDLE_DUPLICATE, kern_handle_duplicate), SYSCALL_TABLE_ENTRY(KERN_CONFIG_GET, kern_config_get), SYSCALL_TABLE_ENTRY(KERN_CONFIG_SET, kern_config_set), SYSCALL_TABLE_ENTRY(CHANNEL_CREATE, channel_create), diff --git a/syscall/handle.c b/syscall/handle.c index cda125b..a303102 100644 --- a/syscall/handle.c +++ b/syscall/handle.c @@ -4,5 +4,36 @@ kern_status_t sys_kern_handle_close(kern_handle_t handle) { struct task *self = current_task(); + return task_close_handle(self, handle); } + +kern_status_t sys_kern_handle_duplicate( + kern_handle_t handle, + kern_handle_t *out) +{ + struct task *self = current_task(); + + if (!validate_access_w(self, out, sizeof *out)) { + return KERN_MEMORY_FAULT; + } + + unsigned long flags; + task_lock_irqsave(self, &flags); + + struct object *obj = NULL; + handle_flags_t handle_flags = 0; + kern_status_t status + = task_resolve_handle(self, handle, &obj, &handle_flags); + if (status != KERN_OK) { + task_unlock_irqrestore(self, flags); + return status; + } + + status = task_open_handle(self, obj, handle_flags, out); + object_unref(obj); + + task_unlock_irqrestore(self, flags); + + return status; +}