Loading mm/process_vm_access.c +28 −34 Original line number Diff line number Diff line Loading @@ -45,9 +45,7 @@ static int process_vm_rw_pages(struct task_struct *task, unsigned long pa, unsigned long start_offset, unsigned long len, const struct iovec **iovp, unsigned long *left, size_t *lvec_offset, struct iov_iter *iter, int vm_write, unsigned int nr_pages_to_copy, ssize_t *bytes_copied) Loading @@ -59,7 +57,7 @@ static int process_vm_rw_pages(struct task_struct *task, int ret; ssize_t bytes_to_copy; ssize_t rc = 0; const struct iovec *iov = *iovp; const struct iovec *iov = iter->iov; *bytes_copied = 0; Loading @@ -77,14 +75,14 @@ static int process_vm_rw_pages(struct task_struct *task, /* Do the copy for each page */ for (pgs_copied = 0; (pgs_copied < nr_pages_to_copy) && *left; (pgs_copied < nr_pages_to_copy) && iter->nr_segs; pgs_copied++) { /* Make sure we have a non zero length iovec */ while (*left && iov->iov_len == 0) { while (iter->nr_segs && iov->iov_len == 0) { iov++; (*left)--; iter->nr_segs--; } if (!*left) if (!iter->nr_segs) break; /* Loading @@ -96,18 +94,18 @@ static int process_vm_rw_pages(struct task_struct *task, len - *bytes_copied); bytes_to_copy = min_t(ssize_t, bytes_to_copy, iov->iov_len - *lvec_offset); - iter->iov_offset); target_kaddr = kmap(process_pages[pgs_copied]) + start_offset; if (vm_write) ret = copy_from_user(target_kaddr, iov->iov_base + *lvec_offset, + iter->iov_offset, bytes_to_copy); else ret = copy_to_user(iov->iov_base + *lvec_offset, + iter->iov_offset, target_kaddr, bytes_to_copy); kunmap(process_pages[pgs_copied]); if (ret) { Loading @@ -117,15 +115,15 @@ static int process_vm_rw_pages(struct task_struct *task, goto end; } *bytes_copied += bytes_to_copy; *lvec_offset += bytes_to_copy; if (*lvec_offset == iov->iov_len) { iter->iov_offset += bytes_to_copy; if (iter->iov_offset == iov->iov_len) { /* * Need to copy remaining part of page into the * next iovec if there are any bytes left in page */ (*left)--; iter->nr_segs--; iov++; *lvec_offset = 0; iter->iov_offset = 0; start_offset = (start_offset + bytes_to_copy) % PAGE_SIZE; if (start_offset) Loading @@ -147,7 +145,7 @@ static int process_vm_rw_pages(struct task_struct *task, put_page(process_pages[j]); } *iovp = iov; iter->iov = iov; return rc; } Loading @@ -172,9 +170,7 @@ static int process_vm_rw_pages(struct task_struct *task, */ static int process_vm_rw_single_vec(unsigned long addr, unsigned long len, const struct iovec **iovp, unsigned long *left, size_t *lvec_offset, struct iov_iter *iter, struct page **process_pages, struct mm_struct *mm, struct task_struct *task, Loading @@ -198,14 +194,12 @@ static int process_vm_rw_single_vec(unsigned long addr, return 0; nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1; while ((nr_pages_copied < nr_pages) && *left) { while ((nr_pages_copied < nr_pages) && iter->nr_segs) { nr_pages_to_copy = min(nr_pages - nr_pages_copied, max_pages_per_loop); rc = process_vm_rw_pages(task, mm, process_pages, pa, start_offset, len, iovp, left, lvec_offset, start_offset, len, iter, vm_write, nr_pages_to_copy, &bytes_copied_loop); start_offset = 0; Loading Loading @@ -240,8 +234,7 @@ static int process_vm_rw_single_vec(unsigned long addr, * return less bytes than expected if an error occurs during the copying * process. */ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, static ssize_t process_vm_rw_core(pid_t pid, struct iov_iter *iter, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags, int vm_write) Loading @@ -256,8 +249,6 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, ssize_t bytes_copied = 0; unsigned long nr_pages = 0; unsigned long nr_pages_iov; unsigned long left = liovcnt; size_t iov_l_curr_offset = 0; ssize_t iov_len; /* Loading Loading @@ -312,11 +303,11 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, goto put_task_struct; } for (i = 0; i < riovcnt && left; i++) { for (i = 0; i < riovcnt && iter->nr_segs; i++) { rc = process_vm_rw_single_vec( (unsigned long)rvec[i].iov_base, rvec[i].iov_len, &lvec, &left, &iov_l_curr_offset, process_pages, mm, task, vm_write, &bytes_copied_loop); iter, process_pages, mm, task, vm_write, &bytes_copied_loop); bytes_copied += bytes_copied_loop; if (rc != 0) { /* If we have managed to copy any data at all then Loading Loading @@ -365,6 +356,7 @@ static ssize_t process_vm_rw(pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; struct iov_iter iter; ssize_t rc; if (flags != 0) Loading @@ -380,13 +372,14 @@ static ssize_t process_vm_rw(pid_t pid, if (rc <= 0) goto free_iovecs; iov_iter_init(&iter, iov_l, liovcnt, rc, 0); rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, iovstack_r, &iov_r); if (rc <= 0) goto free_iovecs; rc = process_vm_rw_core(pid, iov_l, liovcnt, iov_r, riovcnt, flags, vm_write); rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); free_iovecs: if (iov_r != iovstack_r) Loading Loading @@ -426,6 +419,7 @@ compat_process_vm_rw(compat_pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; struct iov_iter iter; ssize_t rc = -EFAULT; if (flags != 0) Loading @@ -441,14 +435,14 @@ compat_process_vm_rw(compat_pid_t pid, &iov_l); if (rc <= 0) goto free_iovecs; iov_iter_init(&iter, iov_l, liovcnt, rc, 0); rc = compat_rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, iovstack_r, &iov_r); if (rc <= 0) goto free_iovecs; rc = process_vm_rw_core(pid, iov_l, liovcnt, iov_r, riovcnt, flags, vm_write); rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); free_iovecs: if (iov_r != iovstack_r) Loading Loading
mm/process_vm_access.c +28 −34 Original line number Diff line number Diff line Loading @@ -45,9 +45,7 @@ static int process_vm_rw_pages(struct task_struct *task, unsigned long pa, unsigned long start_offset, unsigned long len, const struct iovec **iovp, unsigned long *left, size_t *lvec_offset, struct iov_iter *iter, int vm_write, unsigned int nr_pages_to_copy, ssize_t *bytes_copied) Loading @@ -59,7 +57,7 @@ static int process_vm_rw_pages(struct task_struct *task, int ret; ssize_t bytes_to_copy; ssize_t rc = 0; const struct iovec *iov = *iovp; const struct iovec *iov = iter->iov; *bytes_copied = 0; Loading @@ -77,14 +75,14 @@ static int process_vm_rw_pages(struct task_struct *task, /* Do the copy for each page */ for (pgs_copied = 0; (pgs_copied < nr_pages_to_copy) && *left; (pgs_copied < nr_pages_to_copy) && iter->nr_segs; pgs_copied++) { /* Make sure we have a non zero length iovec */ while (*left && iov->iov_len == 0) { while (iter->nr_segs && iov->iov_len == 0) { iov++; (*left)--; iter->nr_segs--; } if (!*left) if (!iter->nr_segs) break; /* Loading @@ -96,18 +94,18 @@ static int process_vm_rw_pages(struct task_struct *task, len - *bytes_copied); bytes_to_copy = min_t(ssize_t, bytes_to_copy, iov->iov_len - *lvec_offset); - iter->iov_offset); target_kaddr = kmap(process_pages[pgs_copied]) + start_offset; if (vm_write) ret = copy_from_user(target_kaddr, iov->iov_base + *lvec_offset, + iter->iov_offset, bytes_to_copy); else ret = copy_to_user(iov->iov_base + *lvec_offset, + iter->iov_offset, target_kaddr, bytes_to_copy); kunmap(process_pages[pgs_copied]); if (ret) { Loading @@ -117,15 +115,15 @@ static int process_vm_rw_pages(struct task_struct *task, goto end; } *bytes_copied += bytes_to_copy; *lvec_offset += bytes_to_copy; if (*lvec_offset == iov->iov_len) { iter->iov_offset += bytes_to_copy; if (iter->iov_offset == iov->iov_len) { /* * Need to copy remaining part of page into the * next iovec if there are any bytes left in page */ (*left)--; iter->nr_segs--; iov++; *lvec_offset = 0; iter->iov_offset = 0; start_offset = (start_offset + bytes_to_copy) % PAGE_SIZE; if (start_offset) Loading @@ -147,7 +145,7 @@ static int process_vm_rw_pages(struct task_struct *task, put_page(process_pages[j]); } *iovp = iov; iter->iov = iov; return rc; } Loading @@ -172,9 +170,7 @@ static int process_vm_rw_pages(struct task_struct *task, */ static int process_vm_rw_single_vec(unsigned long addr, unsigned long len, const struct iovec **iovp, unsigned long *left, size_t *lvec_offset, struct iov_iter *iter, struct page **process_pages, struct mm_struct *mm, struct task_struct *task, Loading @@ -198,14 +194,12 @@ static int process_vm_rw_single_vec(unsigned long addr, return 0; nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1; while ((nr_pages_copied < nr_pages) && *left) { while ((nr_pages_copied < nr_pages) && iter->nr_segs) { nr_pages_to_copy = min(nr_pages - nr_pages_copied, max_pages_per_loop); rc = process_vm_rw_pages(task, mm, process_pages, pa, start_offset, len, iovp, left, lvec_offset, start_offset, len, iter, vm_write, nr_pages_to_copy, &bytes_copied_loop); start_offset = 0; Loading Loading @@ -240,8 +234,7 @@ static int process_vm_rw_single_vec(unsigned long addr, * return less bytes than expected if an error occurs during the copying * process. */ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, unsigned long liovcnt, static ssize_t process_vm_rw_core(pid_t pid, struct iov_iter *iter, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags, int vm_write) Loading @@ -256,8 +249,6 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, ssize_t bytes_copied = 0; unsigned long nr_pages = 0; unsigned long nr_pages_iov; unsigned long left = liovcnt; size_t iov_l_curr_offset = 0; ssize_t iov_len; /* Loading Loading @@ -312,11 +303,11 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, goto put_task_struct; } for (i = 0; i < riovcnt && left; i++) { for (i = 0; i < riovcnt && iter->nr_segs; i++) { rc = process_vm_rw_single_vec( (unsigned long)rvec[i].iov_base, rvec[i].iov_len, &lvec, &left, &iov_l_curr_offset, process_pages, mm, task, vm_write, &bytes_copied_loop); iter, process_pages, mm, task, vm_write, &bytes_copied_loop); bytes_copied += bytes_copied_loop; if (rc != 0) { /* If we have managed to copy any data at all then Loading Loading @@ -365,6 +356,7 @@ static ssize_t process_vm_rw(pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; struct iov_iter iter; ssize_t rc; if (flags != 0) Loading @@ -380,13 +372,14 @@ static ssize_t process_vm_rw(pid_t pid, if (rc <= 0) goto free_iovecs; iov_iter_init(&iter, iov_l, liovcnt, rc, 0); rc = rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, iovstack_r, &iov_r); if (rc <= 0) goto free_iovecs; rc = process_vm_rw_core(pid, iov_l, liovcnt, iov_r, riovcnt, flags, vm_write); rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); free_iovecs: if (iov_r != iovstack_r) Loading Loading @@ -426,6 +419,7 @@ compat_process_vm_rw(compat_pid_t pid, struct iovec iovstack_r[UIO_FASTIOV]; struct iovec *iov_l = iovstack_l; struct iovec *iov_r = iovstack_r; struct iov_iter iter; ssize_t rc = -EFAULT; if (flags != 0) Loading @@ -441,14 +435,14 @@ compat_process_vm_rw(compat_pid_t pid, &iov_l); if (rc <= 0) goto free_iovecs; iov_iter_init(&iter, iov_l, liovcnt, rc, 0); rc = compat_rw_copy_check_uvector(CHECK_IOVEC_ONLY, rvec, riovcnt, UIO_FASTIOV, iovstack_r, &iov_r); if (rc <= 0) goto free_iovecs; rc = process_vm_rw_core(pid, iov_l, liovcnt, iov_r, riovcnt, flags, vm_write); rc = process_vm_rw_core(pid, &iter, iov_r, riovcnt, flags, vm_write); free_iovecs: if (iov_r != iovstack_r) Loading