uio: make import_iovec()/compat_import_iovec() return bytes on success
Currently these functions return < 0 on error, and 0 for success. Change that so that we return < 0 on error, but number of bytes for success. Some callers already treat the return value that way, others need a slight tweak. Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
61939b12dc
commit
87e5e6dab6
9
fs/aio.c
9
fs/aio.c
|
@ -1479,8 +1479,9 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aio_setup_rw(int rw, const struct iocb *iocb, struct iovec **iovec,
|
static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
|
||||||
bool vectored, bool compat, struct iov_iter *iter)
|
struct iovec **iovec, bool vectored, bool compat,
|
||||||
|
struct iov_iter *iter)
|
||||||
{
|
{
|
||||||
void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
|
void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
|
||||||
size_t len = iocb->aio_nbytes;
|
size_t len = iocb->aio_nbytes;
|
||||||
|
@ -1537,7 +1538,7 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
|
ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
|
ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -1565,7 +1566,7 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
|
ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
|
ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
|
|
@ -1003,9 +1003,9 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int io_import_iovec(struct io_ring_ctx *ctx, int rw,
|
static ssize_t io_import_iovec(struct io_ring_ctx *ctx, int rw,
|
||||||
const struct sqe_submit *s, struct iovec **iovec,
|
const struct sqe_submit *s, struct iovec **iovec,
|
||||||
struct iov_iter *iter)
|
struct iov_iter *iter)
|
||||||
{
|
{
|
||||||
const struct io_uring_sqe *sqe = s->sqe;
|
const struct io_uring_sqe *sqe = s->sqe;
|
||||||
void __user *buf = u64_to_user_ptr(READ_ONCE(sqe->addr));
|
void __user *buf = u64_to_user_ptr(READ_ONCE(sqe->addr));
|
||||||
|
@ -1023,7 +1023,7 @@ static int io_import_iovec(struct io_ring_ctx *ctx, int rw,
|
||||||
opcode = READ_ONCE(sqe->opcode);
|
opcode = READ_ONCE(sqe->opcode);
|
||||||
if (opcode == IORING_OP_READ_FIXED ||
|
if (opcode == IORING_OP_READ_FIXED ||
|
||||||
opcode == IORING_OP_WRITE_FIXED) {
|
opcode == IORING_OP_WRITE_FIXED) {
|
||||||
int ret = io_import_fixed(ctx, rw, sqe, iter);
|
ssize_t ret = io_import_fixed(ctx, rw, sqe, iter);
|
||||||
*iovec = NULL;
|
*iovec = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1089,7 +1089,7 @@ static int io_read(struct io_kiocb *req, const struct sqe_submit *s,
|
||||||
struct iov_iter iter;
|
struct iov_iter iter;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
size_t iov_count;
|
size_t iov_count;
|
||||||
int ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = io_prep_rw(req, s, force_nonblock);
|
ret = io_prep_rw(req, s, force_nonblock);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1102,7 +1102,7 @@ static int io_read(struct io_kiocb *req, const struct sqe_submit *s,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = io_import_iovec(req->ctx, READ, s, &iovec, &iter);
|
ret = io_import_iovec(req->ctx, READ, s, &iovec, &iter);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
iov_count = iov_iter_count(&iter);
|
iov_count = iov_iter_count(&iter);
|
||||||
|
@ -1136,7 +1136,7 @@ static int io_write(struct io_kiocb *req, const struct sqe_submit *s,
|
||||||
struct iov_iter iter;
|
struct iov_iter iter;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
size_t iov_count;
|
size_t iov_count;
|
||||||
int ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = io_prep_rw(req, s, force_nonblock);
|
ret = io_prep_rw(req, s, force_nonblock);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1149,7 +1149,7 @@ static int io_write(struct io_kiocb *req, const struct sqe_submit *s,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = io_import_iovec(req->ctx, WRITE, s, &iovec, &iter);
|
ret = io_import_iovec(req->ctx, WRITE, s, &iovec, &iter);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
iov_count = iov_iter_count(&iter);
|
iov_count = iov_iter_count(&iter);
|
||||||
|
|
|
@ -1356,7 +1356,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
|
||||||
struct iovec iovstack[UIO_FASTIOV];
|
struct iovec iovstack[UIO_FASTIOV];
|
||||||
struct iovec *iov = iovstack;
|
struct iovec *iov = iovstack;
|
||||||
struct iov_iter iter;
|
struct iov_iter iter;
|
||||||
long error;
|
ssize_t error;
|
||||||
struct fd f;
|
struct fd f;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
|
@ -1367,7 +1367,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
|
||||||
|
|
||||||
error = import_iovec(type, uiov, nr_segs,
|
error = import_iovec(type, uiov, nr_segs,
|
||||||
ARRAY_SIZE(iovstack), &iov, &iter);
|
ARRAY_SIZE(iovstack), &iov, &iter);
|
||||||
if (!error) {
|
if (error >= 0) {
|
||||||
error = do_vmsplice(f.file, &iter, flags);
|
error = do_vmsplice(f.file, &iter, flags);
|
||||||
kfree(iov);
|
kfree(iov);
|
||||||
}
|
}
|
||||||
|
@ -1382,7 +1382,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io
|
||||||
struct iovec iovstack[UIO_FASTIOV];
|
struct iovec iovstack[UIO_FASTIOV];
|
||||||
struct iovec *iov = iovstack;
|
struct iovec *iov = iovstack;
|
||||||
struct iov_iter iter;
|
struct iov_iter iter;
|
||||||
long error;
|
ssize_t error;
|
||||||
struct fd f;
|
struct fd f;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
|
@ -1393,7 +1393,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io
|
||||||
|
|
||||||
error = compat_import_iovec(type, iov32, nr_segs,
|
error = compat_import_iovec(type, iov32, nr_segs,
|
||||||
ARRAY_SIZE(iovstack), &iov, &iter);
|
ARRAY_SIZE(iovstack), &iov, &iter);
|
||||||
if (!error) {
|
if (error >= 0) {
|
||||||
error = do_vmsplice(f.file, &iter, flags);
|
error = do_vmsplice(f.file, &iter, flags);
|
||||||
kfree(iov);
|
kfree(iov);
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,13 +279,13 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct
|
||||||
size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,
|
size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,
|
||||||
struct iov_iter *i);
|
struct iov_iter *i);
|
||||||
|
|
||||||
int import_iovec(int type, const struct iovec __user * uvector,
|
ssize_t import_iovec(int type, const struct iovec __user * uvector,
|
||||||
unsigned nr_segs, unsigned fast_segs,
|
unsigned nr_segs, unsigned fast_segs,
|
||||||
struct iovec **iov, struct iov_iter *i);
|
struct iovec **iov, struct iov_iter *i);
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
struct compat_iovec;
|
struct compat_iovec;
|
||||||
int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
|
ssize_t compat_import_iovec(int type, const struct compat_iovec __user * uvector,
|
||||||
unsigned nr_segs, unsigned fast_segs,
|
unsigned nr_segs, unsigned fast_segs,
|
||||||
struct iovec **iov, struct iov_iter *i);
|
struct iovec **iov, struct iov_iter *i);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1634,9 +1634,9 @@ EXPORT_SYMBOL(dup_iter);
|
||||||
* on-stack array was used or not (and regardless of whether this function
|
* on-stack array was used or not (and regardless of whether this function
|
||||||
* returns an error or not).
|
* returns an error or not).
|
||||||
*
|
*
|
||||||
* Return: 0 on success or negative error code on error.
|
* Return: Negative error code on error, bytes imported on success
|
||||||
*/
|
*/
|
||||||
int import_iovec(int type, const struct iovec __user * uvector,
|
ssize_t import_iovec(int type, const struct iovec __user * uvector,
|
||||||
unsigned nr_segs, unsigned fast_segs,
|
unsigned nr_segs, unsigned fast_segs,
|
||||||
struct iovec **iov, struct iov_iter *i)
|
struct iovec **iov, struct iov_iter *i)
|
||||||
{
|
{
|
||||||
|
@ -1652,16 +1652,17 @@ int import_iovec(int type, const struct iovec __user * uvector,
|
||||||
}
|
}
|
||||||
iov_iter_init(i, type, p, nr_segs, n);
|
iov_iter_init(i, type, p, nr_segs, n);
|
||||||
*iov = p == *iov ? NULL : p;
|
*iov = p == *iov ? NULL : p;
|
||||||
return 0;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(import_iovec);
|
EXPORT_SYMBOL(import_iovec);
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
|
||||||
int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
|
ssize_t compat_import_iovec(int type,
|
||||||
unsigned nr_segs, unsigned fast_segs,
|
const struct compat_iovec __user * uvector,
|
||||||
struct iovec **iov, struct iov_iter *i)
|
unsigned nr_segs, unsigned fast_segs,
|
||||||
|
struct iovec **iov, struct iov_iter *i)
|
||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
struct iovec *p;
|
struct iovec *p;
|
||||||
|
@ -1675,7 +1676,7 @@ int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
|
||||||
}
|
}
|
||||||
iov_iter_init(i, type, p, nr_segs, n);
|
iov_iter_init(i, type, p, nr_segs, n);
|
||||||
*iov = p == *iov ? NULL : p;
|
*iov = p == *iov ? NULL : p;
|
||||||
return 0;
|
return n;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,10 @@ int get_compat_msghdr(struct msghdr *kmsg,
|
||||||
|
|
||||||
kmsg->msg_iocb = NULL;
|
kmsg->msg_iocb = NULL;
|
||||||
|
|
||||||
return compat_import_iovec(save_addr ? READ : WRITE,
|
err = compat_import_iovec(save_addr ? READ : WRITE,
|
||||||
compat_ptr(msg.msg_iov), msg.msg_iovlen,
|
compat_ptr(msg.msg_iov), msg.msg_iovlen,
|
||||||
UIO_FASTIOV, iov, &kmsg->msg_iter);
|
UIO_FASTIOV, iov, &kmsg->msg_iter);
|
||||||
|
return err < 0 ? err : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bleech... */
|
/* Bleech... */
|
||||||
|
|
|
@ -2208,9 +2208,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
|
||||||
|
|
||||||
kmsg->msg_iocb = NULL;
|
kmsg->msg_iocb = NULL;
|
||||||
|
|
||||||
return import_iovec(save_addr ? READ : WRITE,
|
err = import_iovec(save_addr ? READ : WRITE,
|
||||||
msg.msg_iov, msg.msg_iovlen,
|
msg.msg_iov, msg.msg_iovlen,
|
||||||
UIO_FASTIOV, iov, &kmsg->msg_iter);
|
UIO_FASTIOV, iov, &kmsg->msg_iter);
|
||||||
|
return err < 0 ? err : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
|
static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
|
||||||
|
|
Loading…
Reference in New Issue