lkml.org 
[lkml]   [2008]   [Sep]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 26/42] sctp: fix potential panics in the SCTP-AUTH API.
    2.6.26-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Vlad Yasevich <vladislav.yasevich@hp.com>

    [ Upstream commit 5e739d1752aca4e8f3e794d431503bfca3162df4 ]

    All of the SCTP-AUTH socket options could cause a panic
    if the extension is disabled and the API is envoked.

    Additionally, there were some additional assumptions that
    certain pointers would always be valid which may not
    always be the case.

    This patch hardens the API and address all of the crash
    scenarios.

    Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    net/sctp/endpointola.c | 4 +-
    net/sctp/socket.c | 85 +++++++++++++++++++++++++++++++++++++------------
    2 files changed, 67 insertions(+), 22 deletions(-)

    --- a/net/sctp/endpointola.c
    +++ b/net/sctp/endpointola.c
    @@ -103,6 +103,7 @@ static struct sctp_endpoint *sctp_endpoi

    /* Initialize the CHUNKS parameter */
    auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS;
    + auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t));

    /* If the Add-IP functionality is enabled, we must
    * authenticate, ASCONF and ASCONF-ACK chunks
    @@ -110,8 +111,7 @@ static struct sctp_endpoint *sctp_endpoi
    if (sctp_addip_enable) {
    auth_chunks->chunks[0] = SCTP_CID_ASCONF;
    auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK;
    - auth_chunks->param_hdr.length =
    - htons(sizeof(sctp_paramhdr_t) + 2);
    + auth_chunks->param_hdr.length += htons(2);
    }
    }

    --- a/net/sctp/socket.c
    +++ b/net/sctp/socket.c
    @@ -2965,6 +2965,9 @@ static int sctp_setsockopt_auth_chunk(st
    {
    struct sctp_authchunk val;

    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    if (optlen != sizeof(struct sctp_authchunk))
    return -EINVAL;
    if (copy_from_user(&val, optval, optlen))
    @@ -2995,6 +2998,9 @@ static int sctp_setsockopt_hmac_ident(st
    struct sctp_hmacalgo *hmacs;
    int err;

    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    if (optlen < sizeof(struct sctp_hmacalgo))
    return -EINVAL;

    @@ -3033,6 +3039,9 @@ static int sctp_setsockopt_auth_key(stru
    struct sctp_association *asoc;
    int ret;

    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    if (optlen <= sizeof(struct sctp_authkey))
    return -EINVAL;

    @@ -3070,6 +3079,9 @@ static int sctp_setsockopt_active_key(st
    struct sctp_authkeyid val;
    struct sctp_association *asoc;

    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    if (optlen != sizeof(struct sctp_authkeyid))
    return -EINVAL;
    if (copy_from_user(&val, optval, optlen))
    @@ -3095,6 +3107,9 @@ static int sctp_setsockopt_del_key(struc
    struct sctp_authkeyid val;
    struct sctp_association *asoc;

    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    if (optlen != sizeof(struct sctp_authkeyid))
    return -EINVAL;
    if (copy_from_user(&val, optval, optlen))
    @@ -5053,19 +5068,29 @@ static int sctp_getsockopt_maxburst(stru
    static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
    char __user *optval, int __user *optlen)
    {
    + struct sctp_hmacalgo __user *p = (void __user *)optval;
    struct sctp_hmac_algo_param *hmacs;
    - __u16 param_len;
    + __u16 data_len = 0;
    + u32 num_idents;
    +
    + if (!sctp_auth_enable)
    + return -EACCES;

    hmacs = sctp_sk(sk)->ep->auth_hmacs_list;
    - param_len = ntohs(hmacs->param_hdr.length);
    + data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t);

    - if (len < param_len)
    + if (len < sizeof(struct sctp_hmacalgo) + data_len)
    return -EINVAL;
    +
    + len = sizeof(struct sctp_hmacalgo) + data_len;
    + num_idents = data_len / sizeof(u16);
    +
    if (put_user(len, optlen))
    return -EFAULT;
    - if (copy_to_user(optval, hmacs->hmac_ids, len))
    + if (put_user(num_idents, &p->shmac_num_idents))
    + return -EFAULT;
    + if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
    return -EFAULT;
    -
    return 0;
    }

    @@ -5075,6 +5100,9 @@ static int sctp_getsockopt_active_key(st
    struct sctp_authkeyid val;
    struct sctp_association *asoc;

    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    if (len < sizeof(struct sctp_authkeyid))
    return -EINVAL;
    if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid)))
    @@ -5089,6 +5117,12 @@ static int sctp_getsockopt_active_key(st
    else
    val.scact_keynumber = sctp_sk(sk)->ep->active_key_id;

    + len = sizeof(struct sctp_authkeyid);
    + if (put_user(len, optlen))
    + return -EFAULT;
    + if (copy_to_user(optval, &val, len))
    + return -EFAULT;
    +
    return 0;
    }

    @@ -5099,13 +5133,16 @@ static int sctp_getsockopt_peer_auth_chu
    struct sctp_authchunks val;
    struct sctp_association *asoc;
    struct sctp_chunks_param *ch;
    - u32 num_chunks;
    + u32 num_chunks = 0;
    char __user *to;

    - if (len <= sizeof(struct sctp_authchunks))
    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    + if (len < sizeof(struct sctp_authchunks))
    return -EINVAL;

    - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks)))
    + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
    return -EFAULT;

    to = p->gauth_chunks;
    @@ -5114,20 +5151,21 @@ static int sctp_getsockopt_peer_auth_chu
    return -EINVAL;

    ch = asoc->peer.peer_chunks;
    + if (!ch)
    + goto num;

    /* See if the user provided enough room for all the data */
    num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
    if (len < num_chunks)
    return -EINVAL;

    - len = num_chunks;
    - if (put_user(len, optlen))
    + if (copy_to_user(to, ch->chunks, num_chunks))
    return -EFAULT;
    +num:
    + len = sizeof(struct sctp_authchunks) + num_chunks;
    + if (put_user(len, optlen)) return -EFAULT;
    if (put_user(num_chunks, &p->gauth_number_of_chunks))
    return -EFAULT;
    - if (copy_to_user(to, ch->chunks, len))
    - return -EFAULT;
    -
    return 0;
    }

    @@ -5138,13 +5176,16 @@ static int sctp_getsockopt_local_auth_ch
    struct sctp_authchunks val;
    struct sctp_association *asoc;
    struct sctp_chunks_param *ch;
    - u32 num_chunks;
    + u32 num_chunks = 0;
    char __user *to;

    - if (len <= sizeof(struct sctp_authchunks))
    + if (!sctp_auth_enable)
    + return -EACCES;
    +
    + if (len < sizeof(struct sctp_authchunks))
    return -EINVAL;

    - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks)))
    + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
    return -EFAULT;

    to = p->gauth_chunks;
    @@ -5157,17 +5198,21 @@ static int sctp_getsockopt_local_auth_ch
    else
    ch = sctp_sk(sk)->ep->auth_chunk_list;

    + if (!ch)
    + goto num;
    +
    num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t);
    - if (len < num_chunks)
    + if (len < sizeof(struct sctp_authchunks) + num_chunks)
    return -EINVAL;

    - len = num_chunks;
    + if (copy_to_user(to, ch->chunks, num_chunks))
    + return -EFAULT;
    +num:
    + len = sizeof(struct sctp_authchunks) + num_chunks;
    if (put_user(len, optlen))
    return -EFAULT;
    if (put_user(num_chunks, &p->gauth_number_of_chunks))
    return -EFAULT;
    - if (copy_to_user(to, ch->chunks, len))
    - return -EFAULT;

    return 0;
    }
    --


    \
     
     \ /
      Last update: 2008-09-03 19:45    [W:0.031 / U:62.276 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site