int ckpt_map_attach(char *node, pid_t gpid, unsigned long area, size_t size, int prot, int flags) { struct file *file; unsigned long ret; unsigned long populate; char path[MAP_PATH_MAX]; ret = ckpt_map_get_path(node, gpid, area, path); if (ret) { log_err("failed to get path"); return ret; } file = filp_open(path, MAP_FLAG, MAP_MODE); if (IS_ERR(file)) { log_err("failed to open, path=%s", path); return PTR_ERR(file); } ret = do_mmap_pgoff(file, area, size, prot, flags, 0, &populate); if (populate) mm_populate(ret, populate); if (ret != area) { log_err("failed to attach, ret=%d", (int)ret); return -EINVAL; } log_map_attach(path); return 0; }
/* * This is really a simplified "vm_mmap". it only handles MPX * bounds tables (the bounds directory is user-allocated). * * Later on, we use the vma->vm_ops to uniquely identify these * VMAs. */ static unsigned long mpx_mmap(unsigned long len) { unsigned long ret; unsigned long addr, pgoff; struct mm_struct *mm = current->mm; vm_flags_t vm_flags; struct vm_area_struct *vma; /* Only bounds table and bounds directory can be allocated here */ if (len != MPX_BD_SIZE_BYTES && len != MPX_BT_SIZE_BYTES) return -EINVAL; down_write(&mm->mmap_sem); /* Too many mappings? */ if (mm->map_count > sysctl_max_map_count) { ret = -ENOMEM; goto out; } /* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */ addr = get_unmapped_area(NULL, 0, len, 0, MAP_ANONYMOUS | MAP_PRIVATE); if (addr & ~PAGE_MASK) { ret = addr; goto out; } vm_flags = VM_READ | VM_WRITE | VM_MPX | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; /* Set pgoff according to addr for anon_vma */ pgoff = addr >> PAGE_SHIFT; ret = mmap_region(NULL, addr, len, vm_flags, pgoff); if (IS_ERR_VALUE(ret)) goto out; vma = find_vma(mm, ret); if (!vma) { ret = -ENOMEM; goto out; } vma->vm_ops = &mpx_vma_ops; if (vm_flags & VM_LOCKED) { up_write(&mm->mmap_sem); mm_populate(ret, len); return ret; } out: up_write(&mm->mmap_sem); return ret; }
/* * This is really a simplified "vm_mmap". it only handles MPX * bounds tables (the bounds directory is user-allocated). */ static unsigned long mpx_mmap(unsigned long len) { struct mm_struct *mm = current->mm; unsigned long addr, populate; /* Only bounds table can be allocated here */ if (len != mpx_bt_size_bytes(mm)) return -EINVAL; down_write(&mm->mmap_sem); addr = do_mmap(NULL, 0, len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, VM_MPX, 0, &populate, NULL); up_write(&mm->mmap_sem); if (populate) mm_populate(addr, populate); return addr; }