#include "../file.h" #include "../mapping.h" #include #include #include #include #include #include #include #include #include static int create_file_mapping( struct fs_context *ctx, int prot, int flags, struct fs_file *f, struct file_mapping **out) { if ((flags & MAP_SHARED) && f->f_inode->i_shared_mapping) { *out = f->f_inode->i_shared_mapping; return SUCCESS; } struct file_mapping *mapping = fs_context_alloc(ctx, sizeof *mapping); if (!mapping) { return ENOMEM; } memset(mapping, 0x0, sizeof *mapping); vm_prot_t vm_prot = VM_PROT_USER; if (prot & PROT_READ) { vm_prot |= VM_PROT_READ; } if (prot & PROT_WRITE) { vm_prot |= VM_PROT_WRITE; } if (prot & PROT_EXEC) { vm_prot |= VM_PROT_EXEC; } kern_handle_t vmo = KERN_HANDLE_INVALID; kern_status_t status = vm_controller_create_object( fs_context_get_vm_controller(ctx), f->f_dent->d_name, strlen(f->f_dent->d_name), (equeue_key_t)mapping, f->f_inode->i_size, vm_prot, &vmo); if (status != KERN_OK) { fs_context_free(ctx, mapping); return __errno_from_kern_status(status); } mapping->m_file = f; mapping->m_vmo = vmo; if (flags & MAP_SHARED) { mapping->m_type = FILE_MAPPING_SHARED; f->f_inode->i_shared_mapping = mapping; } else { mapping->m_type = FILE_MAPPING_PRIVATE; queue_push_back(&f->f_mappings, &mapping->m_entry); } *out = mapping; return SUCCESS; } extern kern_status_t fs_msg_map( xpc_context_t *xpc, const xpc_endpoint_t *sender, int prot, int flags, int *out_err, kern_handle_t *out_vmo, void *arg) { struct fs_context *ctx = arg; struct fs_file *f = fs_context_get_file(ctx, sender->e_port); if (!f) { *out_err = EBADF; return KERN_OK; } struct file_mapping *mapping = NULL; int err = create_file_mapping(ctx, prot, flags, f, &mapping); if (err != SUCCESS) { *out_err = err; return KERN_OK; } kern_tracef( "mapping file %s (%s) using vmo %zx", f->f_dent->d_name, (flags & MAP_SHARED) ? "shared" : "private", mapping->m_vmo); kern_handle_t vmo; kern_handle_duplicate(mapping->m_vmo, &vmo); *out_err = SUCCESS; *out_vmo = vmo; return KERN_OK; }