#include #include #include #include #include #include kern_status_t sys_vm_object_create( const char *name, size_t name_len, size_t data_len, vm_prot_t prot, kern_handle_t *out_handle) { 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; }