lkml.org 
[lkml]   [2011]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[34-longterm 127/209] net: Limit socket I/O iovec total length to INT_MAX.
    Date
    From: David S. Miller <davem@davemloft.net>

    =====================================================================
    | This is a commit scheduled for the next v2.6.34 longterm release. |
    | If you see a problem with using this for longterm, please comment.|
    =====================================================================

    commit 8acfe468b0384e834a303f08ebc4953d72fb690a upstream.

    This helps protect us from overflow issues down in the
    individual protocol sendmsg/recvmsg handlers. Once
    we hit INT_MAX we truncate out the rest of the iovec
    by setting the iov_len members to zero.

    This works because:

    1) For SOCK_STREAM and SOCK_SEQPACKET sockets, partial
    writes are allowed and the application will just continue
    with another write to send the rest of the data.

    2) For datagram oriented sockets, where there must be a
    one-to-one correspondance between write() calls and
    packets on the wire, INT_MAX is going to be far larger
    than the packet size limit the protocol is going to
    check for and signal with -EMSGSIZE.

    Based upon a patch by Linus Torvalds.

    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
    ---
    include/linux/socket.h | 2 +-
    net/compat.c | 10 ++++++----
    net/core/iovec.c | 20 +++++++++-----------
    3 files changed, 16 insertions(+), 16 deletions(-)

    diff --git a/include/linux/socket.h b/include/linux/socket.h
    index 1b5034a..354cc56 100644
    --- a/include/linux/socket.h
    +++ b/include/linux/socket.h
    @@ -314,7 +314,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/net/compat.c b/net/compat.c
    index ec24d9e..b869534 100644
    --- a/net/compat.c
    +++ b/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/net/core/iovec.c b/net/core/iovec.c
    index b5b28f0..16ed584 100644
    --- a/net/core/iovec.c
    +++ b/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) {
    @@ -60,14 +59,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;
    --
    1.7.4.4


    \
     
     \ /
      Last update: 2011-04-14 20:23    [W:4.039 / U:0.396 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site