From 2dbbe35c1331630f17747250d2a1342eb0c36710 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Oct 2010 11:41:55 -0700 Subject: [PATCH] --- yaml --- r: 220950 b: refs/heads/master c: 8acfe468b0384e834a303f08ebc4953d72fb690a h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/socket.h | 2 +- trunk/net/compat.c | 10 ++++++---- trunk/net/core/iovec.c | 20 +++++++++----------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/[refs] b/[refs] index cb0e3e09f7ee..5bdd4aeff9bc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 349f6c5c5d827db909a69e5b9e844e8623c8e881 +refs/heads/master: 8acfe468b0384e834a303f08ebc4953d72fb690a diff --git a/trunk/include/linux/socket.h b/trunk/include/linux/socket.h index 5146b50202ce..86b652fabf6e 100644 --- a/trunk/include/linux/socket.h +++ b/trunk/include/linux/socket.h @@ -322,7 +322,7 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata, int offset, unsigned int len, __wsum *csump); -extern long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode); +extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode); extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, int offset, int len); diff --git a/trunk/net/compat.c b/trunk/net/compat.c index 63d260e81472..3649d5895361 100644 --- a/trunk/net/compat.c +++ b/trunk/net/compat.c @@ -41,10 +41,12 @@ static inline int iov_from_user_compat_to_kern(struct iovec *kiov, compat_size_t len; if (get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } + get_user(buf, &uiov32->iov_base)) + return -EFAULT; + + if (len > INT_MAX - tot_len) + len = INT_MAX - tot_len; + tot_len += len; kiov->iov_base = compat_ptr(buf); kiov->iov_len = (__kernel_size_t) len; diff --git a/trunk/net/core/iovec.c b/trunk/net/core/iovec.c index 72aceb1fe4fa..c40f27e7d208 100644 --- a/trunk/net/core/iovec.c +++ b/trunk/net/core/iovec.c @@ -35,10 +35,9 @@ * in any case. */ -long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode) +int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode) { - int size, ct; - long err; + int size, ct, err; if (m->msg_namelen) { if (mode == VERIFY_READ) { @@ -62,14 +61,13 @@ long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, err = 0; for (ct = 0; ct < m->msg_iovlen; ct++) { - err += iov[ct].iov_len; - /* - * Goal is not to verify user data, but to prevent returning - * negative value, which is interpreted as errno. - * Overflow is still possible, but it is harmless. - */ - if (err < 0) - return -EMSGSIZE; + size_t len = iov[ct].iov_len; + + if (len > INT_MAX - err) { + len = INT_MAX - err; + iov[ct].iov_len = len; + } + err += len; } return err;