Skip to content

Commit

Permalink
sctp: fix potential panics in the SCTP-AUTH API.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vlad Yasevich authored and David S. Miller committed Aug 21, 2008
1 parent 6a55617 commit 5e739d1
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 22 deletions.
4 changes: 2 additions & 2 deletions net/sctp/endpointola.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,

/* 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
*/
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);
}
}

Expand Down
85 changes: 65 additions & 20 deletions net/sctp/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -3055,6 +3055,9 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk,
{
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))
Expand Down Expand Up @@ -3085,6 +3088,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
struct sctp_hmacalgo *hmacs;
int err;

if (!sctp_auth_enable)
return -EACCES;

if (optlen < sizeof(struct sctp_hmacalgo))
return -EINVAL;

Expand Down Expand Up @@ -3123,6 +3129,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
struct sctp_association *asoc;
int ret;

if (!sctp_auth_enable)
return -EACCES;

if (optlen <= sizeof(struct sctp_authkey))
return -EINVAL;

Expand Down Expand Up @@ -3160,6 +3169,9 @@ static int sctp_setsockopt_active_key(struct sock *sk,
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))
Expand All @@ -3185,6 +3197,9 @@ static int sctp_setsockopt_del_key(struct sock *sk,
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))
Expand Down Expand Up @@ -5197,19 +5212,29 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
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;
}

Expand All @@ -5219,6 +5244,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
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)))
Expand All @@ -5233,6 +5261,12 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
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;
}

Expand All @@ -5243,13 +5277,16 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
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;
Expand All @@ -5258,20 +5295,21 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
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;
}

Expand All @@ -5282,13 +5320,16 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
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;
Expand All @@ -5301,17 +5342,21 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
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;
}
Expand Down

0 comments on commit 5e739d1

Please sign in to comment.