2026-02-19 19:21:50 +00:00
|
|
|
#include <kernel/handle.h>
|
|
|
|
|
#include <kernel/printk.h>
|
|
|
|
|
#include <kernel/sched.h>
|
|
|
|
|
#include <kernel/syscall.h>
|
|
|
|
|
#include <kernel/vm-object.h>
|
|
|
|
|
#include <kernel/vm-region.h>
|
2026-02-08 16:17:11 +00:00
|
|
|
|
|
|
|
|
kern_status_t sys_vm_object_create(
|
|
|
|
|
const char *name,
|
2026-02-19 19:21:50 +00:00
|
|
|
size_t name_len,
|
|
|
|
|
size_t data_len,
|
|
|
|
|
vm_prot_t prot,
|
2026-02-08 16:17:11 +00:00
|
|
|
kern_handle_t *out_handle)
|
|
|
|
|
{
|
2026-02-19 19:21:50 +00:00
|
|
|
struct task *self = current_task();
|
|
|
|
|
|
|
|
|
|
if ((name || name_len) && !validate_access_r(self, name, name_len)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!validate_access_w(self, out_handle, sizeof *out_handle)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct vm_object *obj
|
|
|
|
|
= vm_object_create(name, name_len, data_len, prot);
|
|
|
|
|
if (!obj) {
|
|
|
|
|
return KERN_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kern_status_t status
|
|
|
|
|
= task_open_handle(self, &obj->vo_base, 0, out_handle);
|
|
|
|
|
if (status != KERN_OK) {
|
|
|
|
|
object_unref(&obj->vo_base);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return KERN_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kern_status_t sys_vm_object_read(
|
|
|
|
|
kern_handle_t object,
|
|
|
|
|
void *dst,
|
|
|
|
|
off_t offset,
|
|
|
|
|
size_t count,
|
|
|
|
|
size_t *nr_read)
|
|
|
|
|
{
|
|
|
|
|
struct task *self = current_task();
|
|
|
|
|
|
|
|
|
|
if (!validate_access_w(self, dst, count)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nr_read && !validate_access_w(self, nr_read, sizeof *nr_read)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct object *obj = NULL;
|
|
|
|
|
handle_flags_t flags = 0;
|
|
|
|
|
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
|
|
|
|
|
if (status != KERN_OK) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct vm_object *vmo = vm_object_cast(obj);
|
|
|
|
|
if (!vmo) {
|
|
|
|
|
return KERN_INVALID_ARGUMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vm_object_read(vmo, dst, offset, count, nr_read);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kern_status_t sys_vm_object_write(
|
|
|
|
|
kern_handle_t object,
|
|
|
|
|
const void *src,
|
|
|
|
|
off_t offset,
|
|
|
|
|
size_t count,
|
|
|
|
|
size_t *nr_written)
|
|
|
|
|
{
|
|
|
|
|
struct task *self = current_task();
|
|
|
|
|
|
|
|
|
|
if (!validate_access_r(self, src, count)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nr_written
|
|
|
|
|
&& !validate_access_w(self, nr_written, sizeof *nr_written)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct object *obj = NULL;
|
|
|
|
|
handle_flags_t flags = 0;
|
|
|
|
|
kern_status_t status = task_resolve_handle(self, object, &obj, &flags);
|
|
|
|
|
if (status != KERN_OK) {
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct vm_object *vmo = vm_object_cast(obj);
|
|
|
|
|
if (!vmo) {
|
|
|
|
|
return KERN_INVALID_ARGUMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vm_object_write(vmo, src, offset, count, nr_written);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kern_status_t sys_vm_object_copy(
|
|
|
|
|
kern_handle_t dst,
|
|
|
|
|
off_t dst_offset,
|
|
|
|
|
kern_handle_t src,
|
|
|
|
|
off_t src_offset,
|
|
|
|
|
size_t count,
|
|
|
|
|
size_t *nr_copied)
|
|
|
|
|
{
|
|
|
|
|
struct task *self = current_task();
|
|
|
|
|
|
|
|
|
|
if (nr_copied
|
|
|
|
|
&& !validate_access_w(self, nr_copied, sizeof *nr_copied)) {
|
|
|
|
|
return KERN_MEMORY_FAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
task_lock_irqsave(self, &flags);
|
|
|
|
|
|
|
|
|
|
kern_status_t status;
|
|
|
|
|
struct object *dst_obj = NULL, *src_obj = NULL;
|
|
|
|
|
handle_flags_t dst_flags = 0, src_flags = 0;
|
|
|
|
|
|
|
|
|
|
status = task_resolve_handle(self, dst, &dst_obj, &dst_flags);
|
|
|
|
|
if (status != KERN_OK) {
|
|
|
|
|
task_unlock_irqrestore(self, flags);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = task_resolve_handle(self, src, &src_obj, &src_flags);
|
|
|
|
|
if (status != KERN_OK) {
|
|
|
|
|
task_unlock_irqrestore(self, flags);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object_ref(src_obj);
|
|
|
|
|
object_ref(dst_obj);
|
|
|
|
|
|
|
|
|
|
task_unlock_irqrestore(self, flags);
|
|
|
|
|
|
|
|
|
|
struct vm_object *dst_vmo = vm_object_cast(dst_obj);
|
|
|
|
|
struct vm_object *src_vmo = vm_object_cast(src_obj);
|
|
|
|
|
if (!dst_vmo || !src_vmo) {
|
|
|
|
|
object_unref(src_obj);
|
|
|
|
|
object_unref(dst_obj);
|
|
|
|
|
return KERN_INVALID_ARGUMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = vm_object_copy(
|
|
|
|
|
dst_vmo,
|
|
|
|
|
dst_offset,
|
|
|
|
|
src_vmo,
|
|
|
|
|
src_offset,
|
|
|
|
|
count,
|
|
|
|
|
nr_copied);
|
|
|
|
|
|
|
|
|
|
object_unref(src_obj);
|
|
|
|
|
object_unref(dst_obj);
|
|
|
|
|
|
|
|
|
|
return status;
|
2026-02-08 16:17:11 +00:00
|
|
|
}
|