aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c45
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;
5647out: 5663out:
@@ -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(&params, optval, sizeof(params))) 6097 if (copy_from_user(&params, 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;