void *linux_regfile_mmap2(void *addr, size_t len, int prot, int flags, int fd, size_t off) { int subret = -E_INVAL; struct mm_struct *mm = current->mm; assert(mm != NULL); if (len == 0) { return -1; } lock_mm(mm); uintptr_t start = ROUNDDOWN(addr, PGSIZE); len = ROUNDUP(len, PGSIZE); uint32_t vm_flags = VM_READ; if (prot & PROT_WRITE) { vm_flags |= VM_WRITE; } if (prot & PROT_EXEC) { vm_flags |= VM_EXEC; } if (flags & MAP_STACK) { vm_flags |= VM_STACK; } if (flags & MAP_ANONYMOUS) { vm_flags |= VM_ANONYMOUS; } subret = -E_NO_MEM; if (start == 0 && (start = get_unmapped_area(mm, len)) == 0) { goto out_unlock; } uintptr_t end = start + len; struct vma_struct *vma = find_vma(mm, start); if (vma == NULL || vma->vm_start >= end) { vma = NULL; } else if (!(flags & MAP_FIXED)) { start = get_unmapped_area(mm, len); vma = NULL; } else if (!(vma->vm_flags & VM_ANONYMOUS)) { goto out_unlock; } else if (vma->vm_start == start && end == vma->vm_end) { vma->vm_flags = vm_flags; } else { assert(vma->vm_start <= start && end <= vma->vm_end); if ((subret = mm_unmap_keep_pages(mm, start, len)) != 0) { goto out_unlock; } vma = NULL; } if (vma == NULL && (subret = mm_map(mm, start, len, vm_flags, &vma)) != 0) { goto out_unlock; } if (!(flags & MAP_ANONYMOUS)) { vma_mapfile(vma, fd, off << 12, NULL); } subret = 0; out_unlock: unlock_mm(mm); return subret == 0 ? start : -1; }
int do_mprotect(void *addr, size_t len, int prot) { /* return 0; */ struct mm_struct *mm = current->mm; assert(mm != NULL); if (len == 0) { return -E_INVAL; } uintptr_t start = ROUNDDOWN(addr, PGSIZE); uintptr_t end = ROUNDUP(addr + len, PGSIZE); int ret = -E_INVAL; lock_mm(mm); while (1) { struct vma_struct *vma = find_vma(mm, start); uintptr_t last_end; if (vma != NULL) { last_end = vma->vm_end; } if (vma == NULL) { goto out; } else if (vma->vm_start == start && vma->vm_end == end) { if (prot & PROT_WRITE) { vma->vm_flags |= VM_WRITE; } else { vma->vm_flags &= ~VM_WRITE; } } else { uintptr_t this_end = (end <= vma->vm_end) ? end : vma->vm_end; uintptr_t this_start = (start >= vma->vm_start) ? start : vma->vm_start; struct mapped_file_struct mfile = vma->mfile; mfile.offset += this_start - vma->vm_start; uint32_t flags = vma->vm_flags; if ((ret = mm_unmap_keep_pages(mm, this_start, this_end - this_start)) != 0) { goto out; } if (prot & PROT_WRITE) { flags |= VM_WRITE; } else { flags &= ~VM_WRITE; } if ((ret = mm_map(mm, this_start, this_end - this_start, flags, &vma)) != 0) { goto out; } vma->mfile = mfile; if (vma->mfile.file != NULL) { filemap_acquire(mfile.file); } } ret = 0; if (end <= last_end) break; start = last_end; } out: unlock_mm(mm); return ret; }