Loading fs/compat.c +0 −76 Original line number Diff line number Diff line Loading @@ -54,82 +54,6 @@ #include <asm/ioctls.h> #include "internal.h" /* A write operation does a read from user space and vice versa */ #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ) ssize_t compat_rw_copy_check_uvector(int type, const struct compat_iovec __user *uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer) { compat_ssize_t tot_len; struct iovec *iov = *ret_pointer = fast_pointer; ssize_t ret = 0; int seg; /* * SuS says "The readv() function *may* fail if the iovcnt argument * was less than or equal to 0, or greater than {IOV_MAX}. Linux has * traditionally returned zero for zero segments, so... */ if (nr_segs == 0) goto out; ret = -EINVAL; if (nr_segs > UIO_MAXIOV) goto out; if (nr_segs > fast_segs) { ret = -ENOMEM; iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) goto out; } *ret_pointer = iov; ret = -EFAULT; if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) goto out; /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an * ssize_t. * * In Linux, the total length is limited to MAX_RW_COUNT, there is * no overflow possibility. */ tot_len = 0; ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { compat_uptr_t buf; compat_ssize_t len; if (__get_user(len, &uvector->iov_len) || __get_user(buf, &uvector->iov_base)) { ret = -EFAULT; goto out; } if (len < 0) /* size_t not fitting in compat_ssize_t .. */ goto out; if (type >= 0 && !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { ret = -EFAULT; goto out; } if (len > MAX_RW_COUNT - tot_len) len = MAX_RW_COUNT - tot_len; tot_len += len; iov->iov_base = compat_ptr(buf); iov->iov_len = (compat_size_t) len; uvector++; iov++; } ret = tot_len; out: return ret; } struct compat_ncp_mount_data { compat_int_t version; compat_uint_t ncp_fd; Loading fs/read_write.c +75 −0 Original line number Diff line number Diff line Loading @@ -841,6 +841,81 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, return ret; } #ifdef CONFIG_COMPAT ssize_t compat_rw_copy_check_uvector(int type, const struct compat_iovec __user *uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer) { compat_ssize_t tot_len; struct iovec *iov = *ret_pointer = fast_pointer; ssize_t ret = 0; int seg; /* * SuS says "The readv() function *may* fail if the iovcnt argument * was less than or equal to 0, or greater than {IOV_MAX}. Linux has * traditionally returned zero for zero segments, so... */ if (nr_segs == 0) goto out; ret = -EINVAL; if (nr_segs > UIO_MAXIOV) goto out; if (nr_segs > fast_segs) { ret = -ENOMEM; iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) goto out; } *ret_pointer = iov; ret = -EFAULT; if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) goto out; /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an * ssize_t. * * In Linux, the total length is limited to MAX_RW_COUNT, there is * no overflow possibility. */ tot_len = 0; ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { compat_uptr_t buf; compat_ssize_t len; if (__get_user(len, &uvector->iov_len) || __get_user(buf, &uvector->iov_base)) { ret = -EFAULT; goto out; } if (len < 0) /* size_t not fitting in compat_ssize_t .. */ goto out; if (type >= 0 && !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { ret = -EFAULT; goto out; } if (len > MAX_RW_COUNT - tot_len) len = MAX_RW_COUNT - tot_len; tot_len += len; iov->iov_base = compat_ptr(buf); iov->iov_len = (compat_size_t) len; uvector++; iov++; } ret = tot_len; out: return ret; } #endif static ssize_t __do_readv_writev(int type, struct file *file, struct iov_iter *iter, loff_t *pos, int flags) { Loading Loading
fs/compat.c +0 −76 Original line number Diff line number Diff line Loading @@ -54,82 +54,6 @@ #include <asm/ioctls.h> #include "internal.h" /* A write operation does a read from user space and vice versa */ #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ) ssize_t compat_rw_copy_check_uvector(int type, const struct compat_iovec __user *uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer) { compat_ssize_t tot_len; struct iovec *iov = *ret_pointer = fast_pointer; ssize_t ret = 0; int seg; /* * SuS says "The readv() function *may* fail if the iovcnt argument * was less than or equal to 0, or greater than {IOV_MAX}. Linux has * traditionally returned zero for zero segments, so... */ if (nr_segs == 0) goto out; ret = -EINVAL; if (nr_segs > UIO_MAXIOV) goto out; if (nr_segs > fast_segs) { ret = -ENOMEM; iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) goto out; } *ret_pointer = iov; ret = -EFAULT; if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) goto out; /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an * ssize_t. * * In Linux, the total length is limited to MAX_RW_COUNT, there is * no overflow possibility. */ tot_len = 0; ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { compat_uptr_t buf; compat_ssize_t len; if (__get_user(len, &uvector->iov_len) || __get_user(buf, &uvector->iov_base)) { ret = -EFAULT; goto out; } if (len < 0) /* size_t not fitting in compat_ssize_t .. */ goto out; if (type >= 0 && !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { ret = -EFAULT; goto out; } if (len > MAX_RW_COUNT - tot_len) len = MAX_RW_COUNT - tot_len; tot_len += len; iov->iov_base = compat_ptr(buf); iov->iov_len = (compat_size_t) len; uvector++; iov++; } ret = tot_len; out: return ret; } struct compat_ncp_mount_data { compat_int_t version; compat_uint_t ncp_fd; Loading
fs/read_write.c +75 −0 Original line number Diff line number Diff line Loading @@ -841,6 +841,81 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, return ret; } #ifdef CONFIG_COMPAT ssize_t compat_rw_copy_check_uvector(int type, const struct compat_iovec __user *uvector, unsigned long nr_segs, unsigned long fast_segs, struct iovec *fast_pointer, struct iovec **ret_pointer) { compat_ssize_t tot_len; struct iovec *iov = *ret_pointer = fast_pointer; ssize_t ret = 0; int seg; /* * SuS says "The readv() function *may* fail if the iovcnt argument * was less than or equal to 0, or greater than {IOV_MAX}. Linux has * traditionally returned zero for zero segments, so... */ if (nr_segs == 0) goto out; ret = -EINVAL; if (nr_segs > UIO_MAXIOV) goto out; if (nr_segs > fast_segs) { ret = -ENOMEM; iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); if (iov == NULL) goto out; } *ret_pointer = iov; ret = -EFAULT; if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) goto out; /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an * ssize_t. * * In Linux, the total length is limited to MAX_RW_COUNT, there is * no overflow possibility. */ tot_len = 0; ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { compat_uptr_t buf; compat_ssize_t len; if (__get_user(len, &uvector->iov_len) || __get_user(buf, &uvector->iov_base)) { ret = -EFAULT; goto out; } if (len < 0) /* size_t not fitting in compat_ssize_t .. */ goto out; if (type >= 0 && !access_ok(vrfy_dir(type), compat_ptr(buf), len)) { ret = -EFAULT; goto out; } if (len > MAX_RW_COUNT - tot_len) len = MAX_RW_COUNT - tot_len; tot_len += len; iov->iov_base = compat_ptr(buf); iov->iov_len = (compat_size_t) len; uvector++; iov++; } ret = tot_len; out: return ret; } #endif static ssize_t __do_readv_writev(int type, struct file *file, struct iov_iter *iter, loff_t *pos, int flags) { Loading