diff options
-rw-r--r-- | net/sctp/socket.c | 108 |
1 files changed, 74 insertions, 34 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6edaaa009d62..c1f239ac12b9 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3375,12 +3375,13 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
3375 | sctp_assoc_t associd; | 3375 | sctp_assoc_t associd; |
3376 | int retval = 0; | 3376 | int retval = 0; |
3377 | 3377 | ||
3378 | if (len != sizeof(status)) { | 3378 | if (len < sizeof(status)) { |
3379 | retval = -EINVAL; | 3379 | retval = -EINVAL; |
3380 | goto out; | 3380 | goto out; |
3381 | } | 3381 | } |
3382 | 3382 | ||
3383 | if (copy_from_user(&status, optval, sizeof(status))) { | 3383 | len = sizeof(status); |
3384 | if (copy_from_user(&status, optval, len)) { | ||
3384 | retval = -EFAULT; | 3385 | retval = -EFAULT; |
3385 | goto out; | 3386 | goto out; |
3386 | } | 3387 | } |
@@ -3452,12 +3453,13 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
3452 | struct sctp_transport *transport; | 3453 | struct sctp_transport *transport; |
3453 | int retval = 0; | 3454 | int retval = 0; |
3454 | 3455 | ||
3455 | if (len != sizeof(pinfo)) { | 3456 | if (len < sizeof(pinfo)) { |
3456 | retval = -EINVAL; | 3457 | retval = -EINVAL; |
3457 | goto out; | 3458 | goto out; |
3458 | } | 3459 | } |
3459 | 3460 | ||
3460 | if (copy_from_user(&pinfo, optval, sizeof(pinfo))) { | 3461 | len = sizeof(pinfo); |
3462 | if (copy_from_user(&pinfo, optval, len)) { | ||
3461 | retval = -EFAULT; | 3463 | retval = -EFAULT; |
3462 | goto out; | 3464 | goto out; |
3463 | } | 3465 | } |
@@ -3523,8 +3525,11 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, | |||
3523 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, | 3525 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, |
3524 | int __user *optlen) | 3526 | int __user *optlen) |
3525 | { | 3527 | { |
3526 | if (len != sizeof(struct sctp_event_subscribe)) | 3528 | if (len < sizeof(struct sctp_event_subscribe)) |
3527 | return -EINVAL; | 3529 | return -EINVAL; |
3530 | len = sizeof(struct sctp_event_subscribe); | ||
3531 | if (put_user(len, optlen)) | ||
3532 | return -EFAULT; | ||
3528 | if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) | 3533 | if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) |
3529 | return -EFAULT; | 3534 | return -EFAULT; |
3530 | return 0; | 3535 | return 0; |
@@ -3546,9 +3551,12 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv | |||
3546 | /* Applicable to UDP-style socket only */ | 3551 | /* Applicable to UDP-style socket only */ |
3547 | if (sctp_style(sk, TCP)) | 3552 | if (sctp_style(sk, TCP)) |
3548 | return -EOPNOTSUPP; | 3553 | return -EOPNOTSUPP; |
3549 | if (len != sizeof(int)) | 3554 | if (len < sizeof(int)) |
3550 | return -EINVAL; | 3555 | return -EINVAL; |
3551 | if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len)) | 3556 | len = sizeof(int); |
3557 | if (put_user(len, optlen)) | ||
3558 | return -EFAULT; | ||
3559 | if (copy_to_user(optval, &sctp_sk(sk)->autoclose, sizeof(int))) | ||
3552 | return -EFAULT; | 3560 | return -EFAULT; |
3553 | return 0; | 3561 | return 0; |
3554 | } | 3562 | } |
@@ -3599,8 +3607,9 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval | |||
3599 | int retval = 0; | 3607 | int retval = 0; |
3600 | struct sctp_association *asoc; | 3608 | struct sctp_association *asoc; |
3601 | 3609 | ||
3602 | if (len != sizeof(sctp_peeloff_arg_t)) | 3610 | if (len < sizeof(sctp_peeloff_arg_t)) |
3603 | return -EINVAL; | 3611 | return -EINVAL; |
3612 | len = sizeof(sctp_peeloff_arg_t); | ||
3604 | if (copy_from_user(&peeloff, optval, len)) | 3613 | if (copy_from_user(&peeloff, optval, len)) |
3605 | return -EFAULT; | 3614 | return -EFAULT; |
3606 | 3615 | ||
@@ -3628,6 +3637,8 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval | |||
3628 | 3637 | ||
3629 | /* Return the fd mapped to the new socket. */ | 3638 | /* Return the fd mapped to the new socket. */ |
3630 | peeloff.sd = retval; | 3639 | peeloff.sd = retval; |
3640 | if (put_user(len, optlen)) | ||
3641 | return -EFAULT; | ||
3631 | if (copy_to_user(optval, &peeloff, len)) | 3642 | if (copy_to_user(optval, &peeloff, len)) |
3632 | retval = -EFAULT; | 3643 | retval = -EFAULT; |
3633 | 3644 | ||
@@ -3736,9 +3747,9 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3736 | struct sctp_association *asoc = NULL; | 3747 | struct sctp_association *asoc = NULL; |
3737 | struct sctp_sock *sp = sctp_sk(sk); | 3748 | struct sctp_sock *sp = sctp_sk(sk); |
3738 | 3749 | ||
3739 | if (len != sizeof(struct sctp_paddrparams)) | 3750 | if (len < sizeof(struct sctp_paddrparams)) |
3740 | return -EINVAL; | 3751 | return -EINVAL; |
3741 | 3752 | len = sizeof(struct sctp_paddrparams); | |
3742 | if (copy_from_user(¶ms, optval, len)) | 3753 | if (copy_from_user(¶ms, optval, len)) |
3743 | return -EFAULT; | 3754 | return -EFAULT; |
3744 | 3755 | ||
@@ -3837,9 +3848,11 @@ static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | |||
3837 | struct sctp_association *asoc = NULL; | 3848 | struct sctp_association *asoc = NULL; |
3838 | struct sctp_sock *sp = sctp_sk(sk); | 3849 | struct sctp_sock *sp = sctp_sk(sk); |
3839 | 3850 | ||
3840 | if (len != sizeof(struct sctp_assoc_value)) | 3851 | if (len < sizeof(struct sctp_assoc_value)) |
3841 | return - EINVAL; | 3852 | return - EINVAL; |
3842 | 3853 | ||
3854 | len = sizeof(struct sctp_assoc_value); | ||
3855 | |||
3843 | if (copy_from_user(¶ms, optval, len)) | 3856 | if (copy_from_user(¶ms, optval, len)) |
3844 | return -EFAULT; | 3857 | return -EFAULT; |
3845 | 3858 | ||
@@ -3888,8 +3901,11 @@ static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | |||
3888 | */ | 3901 | */ |
3889 | static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen) | 3902 | static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen) |
3890 | { | 3903 | { |
3891 | if (len != sizeof(struct sctp_initmsg)) | 3904 | if (len < sizeof(struct sctp_initmsg)) |
3892 | return -EINVAL; | 3905 | return -EINVAL; |
3906 | len = sizeof(struct sctp_initmsg); | ||
3907 | if (put_user(len, optlen)) | ||
3908 | return -EFAULT; | ||
3893 | if (copy_to_user(optval, &sctp_sk(sk)->initmsg, len)) | 3909 | if (copy_to_user(optval, &sctp_sk(sk)->initmsg, len)) |
3894 | return -EFAULT; | 3910 | return -EFAULT; |
3895 | return 0; | 3911 | return 0; |
@@ -3904,7 +3920,7 @@ static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, | |||
3904 | struct list_head *pos; | 3920 | struct list_head *pos; |
3905 | int cnt = 0; | 3921 | int cnt = 0; |
3906 | 3922 | ||
3907 | if (len != sizeof(sctp_assoc_t)) | 3923 | if (len < sizeof(sctp_assoc_t)) |
3908 | return -EINVAL; | 3924 | return -EINVAL; |
3909 | 3925 | ||
3910 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) | 3926 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) |
@@ -3940,10 +3956,12 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, | |||
3940 | struct sctp_sock *sp = sctp_sk(sk); | 3956 | struct sctp_sock *sp = sctp_sk(sk); |
3941 | int addrlen; | 3957 | int addrlen; |
3942 | 3958 | ||
3943 | if (len != sizeof(struct sctp_getaddrs_old)) | 3959 | if (len < sizeof(struct sctp_getaddrs_old)) |
3944 | return -EINVAL; | 3960 | return -EINVAL; |
3945 | 3961 | ||
3946 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) | 3962 | len = sizeof(struct sctp_getaddrs_old); |
3963 | |||
3964 | if (copy_from_user(&getaddrs, optval, len)) | ||
3947 | return -EFAULT; | 3965 | return -EFAULT; |
3948 | 3966 | ||
3949 | if (getaddrs.addr_num <= 0) return -EINVAL; | 3967 | if (getaddrs.addr_num <= 0) return -EINVAL; |
@@ -3966,7 +3984,9 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, | |||
3966 | if (cnt >= getaddrs.addr_num) break; | 3984 | if (cnt >= getaddrs.addr_num) break; |
3967 | } | 3985 | } |
3968 | getaddrs.addr_num = cnt; | 3986 | getaddrs.addr_num = cnt; |
3969 | if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) | 3987 | if (put_user(len, optlen)) |
3988 | return -EFAULT; | ||
3989 | if (copy_to_user(optval, &getaddrs, len)) | ||
3970 | return -EFAULT; | 3990 | return -EFAULT; |
3971 | 3991 | ||
3972 | return 0; | 3992 | return 0; |
@@ -4037,7 +4057,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, | |||
4037 | rwlock_t *addr_lock; | 4057 | rwlock_t *addr_lock; |
4038 | int cnt = 0; | 4058 | int cnt = 0; |
4039 | 4059 | ||
4040 | if (len != sizeof(sctp_assoc_t)) | 4060 | if (len < sizeof(sctp_assoc_t)) |
4041 | return -EINVAL; | 4061 | return -EINVAL; |
4042 | 4062 | ||
4043 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) | 4063 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) |
@@ -4179,10 +4199,11 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, | |||
4179 | void *buf; | 4199 | void *buf; |
4180 | int bytes_copied = 0; | 4200 | int bytes_copied = 0; |
4181 | 4201 | ||
4182 | if (len != sizeof(struct sctp_getaddrs_old)) | 4202 | if (len < sizeof(struct sctp_getaddrs_old)) |
4183 | return -EINVAL; | 4203 | return -EINVAL; |
4184 | 4204 | ||
4185 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) | 4205 | len = sizeof(struct sctp_getaddrs_old); |
4206 | if (copy_from_user(&getaddrs, optval, len)) | ||
4186 | return -EFAULT; | 4207 | return -EFAULT; |
4187 | 4208 | ||
4188 | if (getaddrs.addr_num <= 0) return -EINVAL; | 4209 | if (getaddrs.addr_num <= 0) return -EINVAL; |
@@ -4254,7 +4275,7 @@ copy_getaddrs: | |||
4254 | 4275 | ||
4255 | /* copy the leading structure back to user */ | 4276 | /* copy the leading structure back to user */ |
4256 | getaddrs.addr_num = cnt; | 4277 | getaddrs.addr_num = cnt; |
4257 | if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) | 4278 | if (copy_to_user(optval, &getaddrs, len)) |
4258 | err = -EFAULT; | 4279 | err = -EFAULT; |
4259 | 4280 | ||
4260 | error: | 4281 | error: |
@@ -4282,7 +4303,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
4282 | void *addrs; | 4303 | void *addrs; |
4283 | void *buf; | 4304 | void *buf; |
4284 | 4305 | ||
4285 | if (len <= sizeof(struct sctp_getaddrs)) | 4306 | if (len < sizeof(struct sctp_getaddrs)) |
4286 | return -EINVAL; | 4307 | return -EINVAL; |
4287 | 4308 | ||
4288 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) | 4309 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) |
@@ -4379,10 +4400,12 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, | |||
4379 | struct sctp_association *asoc; | 4400 | struct sctp_association *asoc; |
4380 | struct sctp_sock *sp = sctp_sk(sk); | 4401 | struct sctp_sock *sp = sctp_sk(sk); |
4381 | 4402 | ||
4382 | if (len != sizeof(struct sctp_prim)) | 4403 | if (len < sizeof(struct sctp_prim)) |
4383 | return -EINVAL; | 4404 | return -EINVAL; |
4384 | 4405 | ||
4385 | if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) | 4406 | len = sizeof(struct sctp_prim); |
4407 | |||
4408 | if (copy_from_user(&prim, optval, len)) | ||
4386 | return -EFAULT; | 4409 | return -EFAULT; |
4387 | 4410 | ||
4388 | asoc = sctp_id2assoc(sk, prim.ssp_assoc_id); | 4411 | asoc = sctp_id2assoc(sk, prim.ssp_assoc_id); |
@@ -4398,7 +4421,9 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, | |||
4398 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, | 4421 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, |
4399 | (union sctp_addr *)&prim.ssp_addr); | 4422 | (union sctp_addr *)&prim.ssp_addr); |
4400 | 4423 | ||
4401 | if (copy_to_user(optval, &prim, sizeof(struct sctp_prim))) | 4424 | if (put_user(len, optlen)) |
4425 | return -EFAULT; | ||
4426 | if (copy_to_user(optval, &prim, len)) | ||
4402 | return -EFAULT; | 4427 | return -EFAULT; |
4403 | 4428 | ||
4404 | return 0; | 4429 | return 0; |
@@ -4415,10 +4440,15 @@ static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len, | |||
4415 | { | 4440 | { |
4416 | struct sctp_setadaptation adaptation; | 4441 | struct sctp_setadaptation adaptation; |
4417 | 4442 | ||
4418 | if (len != sizeof(struct sctp_setadaptation)) | 4443 | if (len < sizeof(struct sctp_setadaptation)) |
4419 | return -EINVAL; | 4444 | return -EINVAL; |
4420 | 4445 | ||
4446 | len = sizeof(struct sctp_setadaptation); | ||
4447 | |||
4421 | adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind; | 4448 | adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind; |
4449 | |||
4450 | if (put_user(len, optlen)) | ||
4451 | return -EFAULT; | ||
4422 | if (copy_to_user(optval, &adaptation, len)) | 4452 | if (copy_to_user(optval, &adaptation, len)) |
4423 | return -EFAULT; | 4453 | return -EFAULT; |
4424 | 4454 | ||
@@ -4452,9 +4482,12 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, | |||
4452 | struct sctp_association *asoc; | 4482 | struct sctp_association *asoc; |
4453 | struct sctp_sock *sp = sctp_sk(sk); | 4483 | struct sctp_sock *sp = sctp_sk(sk); |
4454 | 4484 | ||
4455 | if (len != sizeof(struct sctp_sndrcvinfo)) | 4485 | if (len < sizeof(struct sctp_sndrcvinfo)) |
4456 | return -EINVAL; | 4486 | return -EINVAL; |
4457 | if (copy_from_user(&info, optval, sizeof(struct sctp_sndrcvinfo))) | 4487 | |
4488 | len = sizeof(struct sctp_sndrcvinfo); | ||
4489 | |||
4490 | if (copy_from_user(&info, optval, len)) | ||
4458 | return -EFAULT; | 4491 | return -EFAULT; |
4459 | 4492 | ||
4460 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); | 4493 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); |
@@ -4475,7 +4508,9 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, | |||
4475 | info.sinfo_timetolive = sp->default_timetolive; | 4508 | info.sinfo_timetolive = sp->default_timetolive; |
4476 | } | 4509 | } |
4477 | 4510 | ||
4478 | if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo))) | 4511 | if (put_user(len, optlen)) |
4512 | return -EFAULT; | ||
4513 | if (copy_to_user(optval, &info, len)) | ||
4479 | return -EFAULT; | 4514 | return -EFAULT; |
4480 | 4515 | ||
4481 | return 0; | 4516 | return 0; |
@@ -4526,10 +4561,12 @@ static int sctp_getsockopt_rtoinfo(struct sock *sk, int len, | |||
4526 | struct sctp_rtoinfo rtoinfo; | 4561 | struct sctp_rtoinfo rtoinfo; |
4527 | struct sctp_association *asoc; | 4562 | struct sctp_association *asoc; |
4528 | 4563 | ||
4529 | if (len != sizeof (struct sctp_rtoinfo)) | 4564 | if (len < sizeof (struct sctp_rtoinfo)) |
4530 | return -EINVAL; | 4565 | return -EINVAL; |
4531 | 4566 | ||
4532 | if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo))) | 4567 | len = sizeof(struct sctp_rtoinfo); |
4568 | |||
4569 | if (copy_from_user(&rtoinfo, optval, len)) | ||
4533 | return -EFAULT; | 4570 | return -EFAULT; |
4534 | 4571 | ||
4535 | asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); | 4572 | asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); |
@@ -4581,11 +4618,12 @@ static int sctp_getsockopt_associnfo(struct sock *sk, int len, | |||
4581 | struct list_head *pos; | 4618 | struct list_head *pos; |
4582 | int cnt = 0; | 4619 | int cnt = 0; |
4583 | 4620 | ||
4584 | if (len != sizeof (struct sctp_assocparams)) | 4621 | if (len < sizeof (struct sctp_assocparams)) |
4585 | return -EINVAL; | 4622 | return -EINVAL; |
4586 | 4623 | ||
4587 | if (copy_from_user(&assocparams, optval, | 4624 | len = sizeof(struct sctp_assocparams); |
4588 | sizeof (struct sctp_assocparams))) | 4625 | |
4626 | if (copy_from_user(&assocparams, optval, len)) | ||
4589 | return -EFAULT; | 4627 | return -EFAULT; |
4590 | 4628 | ||
4591 | asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); | 4629 | asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); |
@@ -4671,9 +4709,11 @@ static int sctp_getsockopt_context(struct sock *sk, int len, | |||
4671 | struct sctp_sock *sp; | 4709 | struct sctp_sock *sp; |
4672 | struct sctp_association *asoc; | 4710 | struct sctp_association *asoc; |
4673 | 4711 | ||
4674 | if (len != sizeof(struct sctp_assoc_value)) | 4712 | if (len < sizeof(struct sctp_assoc_value)) |
4675 | return -EINVAL; | 4713 | return -EINVAL; |
4676 | 4714 | ||
4715 | len = sizeof(struct sctp_assoc_value); | ||
4716 | |||
4677 | if (copy_from_user(¶ms, optval, len)) | 4717 | if (copy_from_user(¶ms, optval, len)) |
4678 | return -EFAULT; | 4718 | return -EFAULT; |
4679 | 4719 | ||