kernel: handle: init handle table duplication

This commit is contained in:
2026-04-19 20:07:51 +01:00
parent c87c29366d
commit f1dd9d8564
3 changed files with 88 additions and 0 deletions
+3
View File
@@ -44,6 +44,9 @@ struct handle_table {
extern struct handle_table *handle_table_create(void);
extern void handle_table_destroy(struct handle_table *tab);
extern kern_status_t handle_table_duplicate(
struct handle_table *src,
struct handle_table **dest);
extern kern_status_t handle_table_alloc_handle(
struct handle_table *tab,
+75
View File
@@ -77,6 +77,81 @@ void handle_table_destroy(struct handle_table *tab)
do_handle_table_destroy(tab, 0);
}
static kern_status_t do_handle_table_duplicate_leaf(
struct handle_table *src,
struct handle_table **dest)
{
struct handle_table *out
= vm_cache_alloc(&handle_table_cache, VM_NORMAL);
if (!out) {
return KERN_NO_MEMORY;
}
memcpy(out, src, sizeof *out);
for (size_t i = 0; i < HANDLES_PER_TABLE; i++) {
struct object *obj = src->t_handles.t_handle_list[i].h_object;
if (obj) {
object_ref(obj);
}
}
*dest = out;
return KERN_OK;
}
static kern_status_t do_handle_table_duplicate(
struct handle_table *src,
struct handle_table **dest,
unsigned int depth)
{
if (depth == MAX_TABLE_DEPTH - 1) {
return do_handle_table_duplicate_leaf(src, dest);
}
struct handle_table *out
= vm_cache_alloc(&handle_table_cache, VM_NORMAL);
if (!out) {
return KERN_NO_MEMORY;
}
memcpy(out->t_subtables.t_subtable_map,
src->t_subtables.t_subtable_map,
sizeof out->t_subtables.t_subtable_map);
memset(out->t_subtables.t_subtable_list,
0x0,
sizeof out->t_subtables.t_subtable_list);
for (size_t i = 0; i < REFS_PER_TABLE; i++) {
struct handle_table *child
= src->t_subtables.t_subtable_list[i];
struct handle_table *dup = NULL;
kern_status_t status = KERN_OK;
if (child) {
status = do_handle_table_duplicate(
child,
&dup,
depth + 1);
}
if (status == KERN_OK) {
out->t_subtables.t_subtable_list[i] = dup;
} else {
return status;
}
}
*dest = out;
return KERN_OK;
}
kern_status_t handle_table_duplicate(
struct handle_table *src,
struct handle_table **dest)
{
return do_handle_table_duplicate(src, dest, 0);
}
static kern_status_t decode_handle_indices(
kern_handle_t handle,
unsigned int indices[MAX_TABLE_DEPTH])
+10
View File
@@ -468,6 +468,14 @@ kern_status_t sys_task_duplicate(
unsigned long flags;
task_lock_irqsave(self, &flags);
struct handle_table *child_handle_table = NULL;
status = handle_table_duplicate(self->t_handles, &child_handle_table);
if (status != KERN_OK) {
task_unlock_irqrestore(self, flags);
put_current_task(self);
return status;
}
struct handle *child_handle_slot = NULL, *space_handle_slot = NULL;
kern_handle_t child_handle, space_handle;
status = handle_table_alloc_handle(
@@ -476,6 +484,7 @@ kern_status_t sys_task_duplicate(
&child_handle_slot,
&child_handle);
if (status != KERN_OK) {
handle_table_destroy(child_handle_table);
task_unlock_irqrestore(self, flags);
put_current_task(self);
return status;
@@ -487,6 +496,7 @@ kern_status_t sys_task_duplicate(
&space_handle_slot,
&space_handle);
if (status != KERN_OK) {
handle_table_destroy(child_handle_table);
handle_table_free_handle(self->t_handles, child_handle);
task_unlock_irqrestore(self, flags);
put_current_task(self);