diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3204a9b29407..9b01e994f661 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -188,13 +188,13 @@ static void sctp_for_each_tx_datachunk(struct sctp_association *asoc, | |||
188 | list_for_each_entry(chunk, &t->transmitted, transmitted_list) | 188 | list_for_each_entry(chunk, &t->transmitted, transmitted_list) |
189 | cb(chunk); | 189 | cb(chunk); |
190 | 190 | ||
191 | list_for_each_entry(chunk, &q->retransmit, list) | 191 | list_for_each_entry(chunk, &q->retransmit, transmitted_list) |
192 | cb(chunk); | 192 | cb(chunk); |
193 | 193 | ||
194 | list_for_each_entry(chunk, &q->sacked, list) | 194 | list_for_each_entry(chunk, &q->sacked, transmitted_list) |
195 | cb(chunk); | 195 | cb(chunk); |
196 | 196 | ||
197 | list_for_each_entry(chunk, &q->abandoned, list) | 197 | list_for_each_entry(chunk, &q->abandoned, transmitted_list) |
198 | cb(chunk); | 198 | cb(chunk); |
199 | 199 | ||
200 | list_for_each_entry(chunk, &q->out_chunk_list, list) | 200 | list_for_each_entry(chunk, &q->out_chunk_list, list) |
@@ -2277,7 +2277,7 @@ static int sctp_setsockopt_events(struct sock *sk, char __user *optval, | |||
2277 | 2277 | ||
2278 | if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { | 2278 | if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { |
2279 | event = sctp_ulpevent_make_sender_dry_event(asoc, | 2279 | event = sctp_ulpevent_make_sender_dry_event(asoc, |
2280 | GFP_ATOMIC); | 2280 | GFP_USER | __GFP_NOWARN); |
2281 | if (!event) | 2281 | if (!event) |
2282 | return -ENOMEM; | 2282 | return -ENOMEM; |
2283 | 2283 | ||
@@ -3498,6 +3498,8 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
3498 | 3498 | ||
3499 | if (optlen < sizeof(struct sctp_hmacalgo)) | 3499 | if (optlen < sizeof(struct sctp_hmacalgo)) |
3500 | return -EINVAL; | 3500 | return -EINVAL; |
3501 | optlen = min_t(unsigned int, optlen, sizeof(struct sctp_hmacalgo) + | ||
3502 | SCTP_AUTH_NUM_HMACS * sizeof(u16)); | ||
3501 | 3503 | ||
3502 | hmacs = memdup_user(optval, optlen); | 3504 | hmacs = memdup_user(optval, optlen); |
3503 | if (IS_ERR(hmacs)) | 3505 | if (IS_ERR(hmacs)) |
@@ -3536,6 +3538,11 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
3536 | 3538 | ||
3537 | if (optlen <= sizeof(struct sctp_authkey)) | 3539 | if (optlen <= sizeof(struct sctp_authkey)) |
3538 | return -EINVAL; | 3540 | return -EINVAL; |
3541 | /* authkey->sca_keylength is u16, so optlen can't be bigger than | ||
3542 | * this. | ||
3543 | */ | ||
3544 | optlen = min_t(unsigned int, optlen, USHRT_MAX + | ||
3545 | sizeof(struct sctp_authkey)); | ||
3539 | 3546 | ||
3540 | authkey = memdup_user(optval, optlen); | 3547 | authkey = memdup_user(optval, optlen); |
3541 | if (IS_ERR(authkey)) | 3548 | if (IS_ERR(authkey)) |
@@ -3891,13 +3898,20 @@ static int sctp_setsockopt_reset_streams(struct sock *sk, | |||
3891 | struct sctp_association *asoc; | 3898 | struct sctp_association *asoc; |
3892 | int retval = -EINVAL; | 3899 | int retval = -EINVAL; |
3893 | 3900 | ||
3894 | if (optlen < sizeof(struct sctp_reset_streams)) | 3901 | if (optlen < sizeof(*params)) |
3895 | return -EINVAL; | 3902 | return -EINVAL; |
3903 | /* srs_number_streams is u16, so optlen can't be bigger than this. */ | ||
3904 | optlen = min_t(unsigned int, optlen, USHRT_MAX + | ||
3905 | sizeof(__u16) * sizeof(*params)); | ||
3896 | 3906 | ||
3897 | params = memdup_user(optval, optlen); | 3907 | params = memdup_user(optval, optlen); |
3898 | if (IS_ERR(params)) | 3908 | if (IS_ERR(params)) |
3899 | return PTR_ERR(params); | 3909 | return PTR_ERR(params); |
3900 | 3910 | ||
3911 | if (params->srs_number_streams * sizeof(__u16) > | ||
3912 | optlen - sizeof(*params)) | ||
3913 | goto out; | ||
3914 | |||
3901 | asoc = sctp_id2assoc(sk, params->srs_assoc_id); | 3915 | asoc = sctp_id2assoc(sk, params->srs_assoc_id); |
3902 | if (!asoc) | 3916 | if (!asoc) |
3903 | goto out; | 3917 | goto out; |
@@ -4494,7 +4508,7 @@ static int sctp_init_sock(struct sock *sk) | |||
4494 | SCTP_DBG_OBJCNT_INC(sock); | 4508 | SCTP_DBG_OBJCNT_INC(sock); |
4495 | 4509 | ||
4496 | local_bh_disable(); | 4510 | local_bh_disable(); |
4497 | percpu_counter_inc(&sctp_sockets_allocated); | 4511 | sk_sockets_allocated_inc(sk); |
4498 | sock_prot_inuse_add(net, sk->sk_prot, 1); | 4512 | sock_prot_inuse_add(net, sk->sk_prot, 1); |
4499 | 4513 | ||
4500 | /* Nothing can fail after this block, otherwise | 4514 | /* Nothing can fail after this block, otherwise |
@@ -4538,7 +4552,7 @@ static void sctp_destroy_sock(struct sock *sk) | |||
4538 | } | 4552 | } |
4539 | sctp_endpoint_free(sp->ep); | 4553 | sctp_endpoint_free(sp->ep); |
4540 | local_bh_disable(); | 4554 | local_bh_disable(); |
4541 | percpu_counter_dec(&sctp_sockets_allocated); | 4555 | sk_sockets_allocated_dec(sk); |
4542 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | 4556 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
4543 | local_bh_enable(); | 4557 | local_bh_enable(); |
4544 | } | 4558 | } |
@@ -5011,7 +5025,7 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv | |||
5011 | len = sizeof(int); | 5025 | len = sizeof(int); |
5012 | if (put_user(len, optlen)) | 5026 | if (put_user(len, optlen)) |
5013 | return -EFAULT; | 5027 | return -EFAULT; |
5014 | if (copy_to_user(optval, &sctp_sk(sk)->autoclose, sizeof(int))) | 5028 | if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len)) |
5015 | return -EFAULT; | 5029 | return -EFAULT; |
5016 | return 0; | 5030 | return 0; |
5017 | } | 5031 | } |
@@ -5080,7 +5094,6 @@ static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *p | |||
5080 | *newfile = sock_alloc_file(newsock, 0, NULL); | 5094 | *newfile = sock_alloc_file(newsock, 0, NULL); |
5081 | if (IS_ERR(*newfile)) { | 5095 | if (IS_ERR(*newfile)) { |
5082 | put_unused_fd(retval); | 5096 | put_unused_fd(retval); |
5083 | sock_release(newsock); | ||
5084 | retval = PTR_ERR(*newfile); | 5097 | retval = PTR_ERR(*newfile); |
5085 | *newfile = NULL; | 5098 | *newfile = NULL; |
5086 | return retval; | 5099 | return retval; |
@@ -5642,6 +5655,9 @@ copy_getaddrs: | |||
5642 | err = -EFAULT; | 5655 | err = -EFAULT; |
5643 | goto out; | 5656 | goto out; |
5644 | } | 5657 | } |
5658 | /* XXX: We should have accounted for sizeof(struct sctp_getaddrs) too, | ||
5659 | * but we can't change it anymore. | ||
5660 | */ | ||
5645 | if (put_user(bytes_copied, optlen)) | 5661 | if (put_user(bytes_copied, optlen)) |
5646 | err = -EFAULT; | 5662 | err = -EFAULT; |
5647 | out: | 5663 | out: |
@@ -6078,7 +6094,7 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len, | |||
6078 | params.assoc_id = 0; | 6094 | params.assoc_id = 0; |
6079 | } else if (len >= sizeof(struct sctp_assoc_value)) { | 6095 | } else if (len >= sizeof(struct sctp_assoc_value)) { |
6080 | len = sizeof(struct sctp_assoc_value); | 6096 | len = sizeof(struct sctp_assoc_value); |
6081 | if (copy_from_user(¶ms, optval, sizeof(params))) | 6097 | if (copy_from_user(¶ms, optval, len)) |
6082 | return -EFAULT; | 6098 | return -EFAULT; |
6083 | } else | 6099 | } else |
6084 | return -EINVAL; | 6100 | return -EINVAL; |
@@ -6248,7 +6264,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
6248 | 6264 | ||
6249 | if (len < sizeof(struct sctp_authkeyid)) | 6265 | if (len < sizeof(struct sctp_authkeyid)) |
6250 | return -EINVAL; | 6266 | return -EINVAL; |
6251 | if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) | 6267 | |
6268 | len = sizeof(struct sctp_authkeyid); | ||
6269 | if (copy_from_user(&val, optval, len)) | ||
6252 | return -EFAULT; | 6270 | return -EFAULT; |
6253 | 6271 | ||
6254 | asoc = sctp_id2assoc(sk, val.scact_assoc_id); | 6272 | asoc = sctp_id2assoc(sk, val.scact_assoc_id); |
@@ -6260,7 +6278,6 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
6260 | else | 6278 | else |
6261 | val.scact_keynumber = ep->active_key_id; | 6279 | val.scact_keynumber = ep->active_key_id; |
6262 | 6280 | ||
6263 | len = sizeof(struct sctp_authkeyid); | ||
6264 | if (put_user(len, optlen)) | 6281 | if (put_user(len, optlen)) |
6265 | return -EFAULT; | 6282 | return -EFAULT; |
6266 | if (copy_to_user(optval, &val, len)) | 6283 | if (copy_to_user(optval, &val, len)) |
@@ -6286,7 +6303,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | |||
6286 | if (len < sizeof(struct sctp_authchunks)) | 6303 | if (len < sizeof(struct sctp_authchunks)) |
6287 | return -EINVAL; | 6304 | return -EINVAL; |
6288 | 6305 | ||
6289 | if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) | 6306 | if (copy_from_user(&val, optval, sizeof(val))) |
6290 | return -EFAULT; | 6307 | return -EFAULT; |
6291 | 6308 | ||
6292 | to = p->gauth_chunks; | 6309 | to = p->gauth_chunks; |
@@ -6331,7 +6348,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | |||
6331 | if (len < sizeof(struct sctp_authchunks)) | 6348 | if (len < sizeof(struct sctp_authchunks)) |
6332 | return -EINVAL; | 6349 | return -EINVAL; |
6333 | 6350 | ||
6334 | if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) | 6351 | if (copy_from_user(&val, optval, sizeof(val))) |
6335 | return -EFAULT; | 6352 | return -EFAULT; |
6336 | 6353 | ||
6337 | to = p->gauth_chunks; | 6354 | to = p->gauth_chunks; |