aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-30 00:29:57 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-30 00:29:57 -0400
commit2d408b42ed0a287c64a94b48e24c6bfa95035019 (patch)
treedba39d735ce0051deadfd4d887637de33dfe842c /net/sctp/socket.c
parentfde937d826e43c9fe7fecc98b6f3da7188e76930 (diff)
parent5f0212174db33828f8bddcff501b73d2bc734f72 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: [IRDA]: fix printk format [NETPOLL] netconsole: fix soft lockup when removing module [NETPOLL]: tx lock deadlock fix SCTP: lock_sock_nested in sctp_sock_migrate SCTP: Fix sctp_getsockopt_get_peer_addrs SCTP: update sctp_getsockopt helpers to allow oversized buffers
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c120
1 files changed, 81 insertions, 39 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6edaaa009d62..67861a8f00cb 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,
3523static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, 3525static 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(&params, optval, len)) 3753 if (copy_from_user(&params, 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(&params, optval, len)) 3856 if (copy_from_user(&params, 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 */
3889static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen) 3902static 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;
@@ -3999,8 +4019,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
3999 return -EINVAL; 4019 return -EINVAL;
4000 4020
4001 to = optval + offsetof(struct sctp_getaddrs,addrs); 4021 to = optval + offsetof(struct sctp_getaddrs,addrs);
4002 space_left = len - sizeof(struct sctp_getaddrs) - 4022 space_left = len - offsetof(struct sctp_getaddrs,addrs);
4003 offsetof(struct sctp_getaddrs,addrs);
4004 4023
4005 list_for_each(pos, &asoc->peer.transport_addr_list) { 4024 list_for_each(pos, &asoc->peer.transport_addr_list) {
4006 from = list_entry(pos, struct sctp_transport, transports); 4025 from = list_entry(pos, struct sctp_transport, transports);
@@ -4037,7 +4056,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
4037 rwlock_t *addr_lock; 4056 rwlock_t *addr_lock;
4038 int cnt = 0; 4057 int cnt = 0;
4039 4058
4040 if (len != sizeof(sctp_assoc_t)) 4059 if (len < sizeof(sctp_assoc_t))
4041 return -EINVAL; 4060 return -EINVAL;
4042 4061
4043 if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) 4062 if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
@@ -4179,10 +4198,11 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4179 void *buf; 4198 void *buf;
4180 int bytes_copied = 0; 4199 int bytes_copied = 0;
4181 4200
4182 if (len != sizeof(struct sctp_getaddrs_old)) 4201 if (len < sizeof(struct sctp_getaddrs_old))
4183 return -EINVAL; 4202 return -EINVAL;
4184 4203
4185 if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) 4204 len = sizeof(struct sctp_getaddrs_old);
4205 if (copy_from_user(&getaddrs, optval, len))
4186 return -EFAULT; 4206 return -EFAULT;
4187 4207
4188 if (getaddrs.addr_num <= 0) return -EINVAL; 4208 if (getaddrs.addr_num <= 0) return -EINVAL;
@@ -4254,7 +4274,7 @@ copy_getaddrs:
4254 4274
4255 /* copy the leading structure back to user */ 4275 /* copy the leading structure back to user */
4256 getaddrs.addr_num = cnt; 4276 getaddrs.addr_num = cnt;
4257 if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) 4277 if (copy_to_user(optval, &getaddrs, len))
4258 err = -EFAULT; 4278 err = -EFAULT;
4259 4279
4260error: 4280error:
@@ -4282,7 +4302,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4282 void *addrs; 4302 void *addrs;
4283 void *buf; 4303 void *buf;
4284 4304
4285 if (len <= sizeof(struct sctp_getaddrs)) 4305 if (len < sizeof(struct sctp_getaddrs))
4286 return -EINVAL; 4306 return -EINVAL;
4287 4307
4288 if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) 4308 if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs)))
@@ -4306,8 +4326,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4306 } 4326 }
4307 4327
4308 to = optval + offsetof(struct sctp_getaddrs,addrs); 4328 to = optval + offsetof(struct sctp_getaddrs,addrs);
4309 space_left = len - sizeof(struct sctp_getaddrs) - 4329 space_left = len - offsetof(struct sctp_getaddrs,addrs);
4310 offsetof(struct sctp_getaddrs,addrs); 4330
4311 addrs = kmalloc(space_left, GFP_KERNEL); 4331 addrs = kmalloc(space_left, GFP_KERNEL);
4312 if (!addrs) 4332 if (!addrs)
4313 return -ENOMEM; 4333 return -ENOMEM;
@@ -4379,10 +4399,12 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
4379 struct sctp_association *asoc; 4399 struct sctp_association *asoc;
4380 struct sctp_sock *sp = sctp_sk(sk); 4400 struct sctp_sock *sp = sctp_sk(sk);
4381 4401
4382 if (len != sizeof(struct sctp_prim)) 4402 if (len < sizeof(struct sctp_prim))
4383 return -EINVAL; 4403 return -EINVAL;
4384 4404
4385 if (copy_from_user(&prim, optval, sizeof(struct sctp_prim))) 4405 len = sizeof(struct sctp_prim);
4406
4407 if (copy_from_user(&prim, optval, len))
4386 return -EFAULT; 4408 return -EFAULT;
4387 4409
4388 asoc = sctp_id2assoc(sk, prim.ssp_assoc_id); 4410 asoc = sctp_id2assoc(sk, prim.ssp_assoc_id);
@@ -4398,7 +4420,9 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
4398 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, 4420 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
4399 (union sctp_addr *)&prim.ssp_addr); 4421 (union sctp_addr *)&prim.ssp_addr);
4400 4422
4401 if (copy_to_user(optval, &prim, sizeof(struct sctp_prim))) 4423 if (put_user(len, optlen))
4424 return -EFAULT;
4425 if (copy_to_user(optval, &prim, len))
4402 return -EFAULT; 4426 return -EFAULT;
4403 4427
4404 return 0; 4428 return 0;
@@ -4415,10 +4439,15 @@ static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len,
4415{ 4439{
4416 struct sctp_setadaptation adaptation; 4440 struct sctp_setadaptation adaptation;
4417 4441
4418 if (len != sizeof(struct sctp_setadaptation)) 4442 if (len < sizeof(struct sctp_setadaptation))
4419 return -EINVAL; 4443 return -EINVAL;
4420 4444
4445 len = sizeof(struct sctp_setadaptation);
4446
4421 adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind; 4447 adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind;
4448
4449 if (put_user(len, optlen))
4450 return -EFAULT;
4422 if (copy_to_user(optval, &adaptation, len)) 4451 if (copy_to_user(optval, &adaptation, len))
4423 return -EFAULT; 4452 return -EFAULT;
4424 4453
@@ -4452,9 +4481,12 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
4452 struct sctp_association *asoc; 4481 struct sctp_association *asoc;
4453 struct sctp_sock *sp = sctp_sk(sk); 4482 struct sctp_sock *sp = sctp_sk(sk);
4454 4483
4455 if (len != sizeof(struct sctp_sndrcvinfo)) 4484 if (len < sizeof(struct sctp_sndrcvinfo))
4456 return -EINVAL; 4485 return -EINVAL;
4457 if (copy_from_user(&info, optval, sizeof(struct sctp_sndrcvinfo))) 4486
4487 len = sizeof(struct sctp_sndrcvinfo);
4488
4489 if (copy_from_user(&info, optval, len))
4458 return -EFAULT; 4490 return -EFAULT;
4459 4491
4460 asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); 4492 asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
@@ -4475,7 +4507,9 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
4475 info.sinfo_timetolive = sp->default_timetolive; 4507 info.sinfo_timetolive = sp->default_timetolive;
4476 } 4508 }
4477 4509
4478 if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo))) 4510 if (put_user(len, optlen))
4511 return -EFAULT;
4512 if (copy_to_user(optval, &info, len))
4479 return -EFAULT; 4513 return -EFAULT;
4480 4514
4481 return 0; 4515 return 0;
@@ -4526,10 +4560,12 @@ static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
4526 struct sctp_rtoinfo rtoinfo; 4560 struct sctp_rtoinfo rtoinfo;
4527 struct sctp_association *asoc; 4561 struct sctp_association *asoc;
4528 4562
4529 if (len != sizeof (struct sctp_rtoinfo)) 4563 if (len < sizeof (struct sctp_rtoinfo))
4530 return -EINVAL; 4564 return -EINVAL;
4531 4565
4532 if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo))) 4566 len = sizeof(struct sctp_rtoinfo);
4567
4568 if (copy_from_user(&rtoinfo, optval, len))
4533 return -EFAULT; 4569 return -EFAULT;
4534 4570
4535 asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id); 4571 asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
@@ -4581,11 +4617,12 @@ static int sctp_getsockopt_associnfo(struct sock *sk, int len,
4581 struct list_head *pos; 4617 struct list_head *pos;
4582 int cnt = 0; 4618 int cnt = 0;
4583 4619
4584 if (len != sizeof (struct sctp_assocparams)) 4620 if (len < sizeof (struct sctp_assocparams))
4585 return -EINVAL; 4621 return -EINVAL;
4586 4622
4587 if (copy_from_user(&assocparams, optval, 4623 len = sizeof(struct sctp_assocparams);
4588 sizeof (struct sctp_assocparams))) 4624
4625 if (copy_from_user(&assocparams, optval, len))
4589 return -EFAULT; 4626 return -EFAULT;
4590 4627
4591 asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id); 4628 asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
@@ -4671,9 +4708,11 @@ static int sctp_getsockopt_context(struct sock *sk, int len,
4671 struct sctp_sock *sp; 4708 struct sctp_sock *sp;
4672 struct sctp_association *asoc; 4709 struct sctp_association *asoc;
4673 4710
4674 if (len != sizeof(struct sctp_assoc_value)) 4711 if (len < sizeof(struct sctp_assoc_value))
4675 return -EINVAL; 4712 return -EINVAL;
4676 4713
4714 len = sizeof(struct sctp_assoc_value);
4715
4677 if (copy_from_user(&params, optval, len)) 4716 if (copy_from_user(&params, optval, len))
4678 return -EFAULT; 4717 return -EFAULT;
4679 4718
@@ -6084,8 +6123,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
6084 * queued to the backlog. This prevents a potential race between 6123 * queued to the backlog. This prevents a potential race between
6085 * backlog processing on the old socket and new-packet processing 6124 * backlog processing on the old socket and new-packet processing
6086 * on the new socket. 6125 * on the new socket.
6126 *
6127 * The caller has just allocated newsk so we can guarantee that other
6128 * paths won't try to lock it and then oldsk.
6087 */ 6129 */
6088 sctp_lock_sock(newsk); 6130 lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
6089 sctp_assoc_migrate(assoc, newsk); 6131 sctp_assoc_migrate(assoc, newsk);
6090 6132
6091 /* If the association on the newsk is already closed before accept() 6133 /* If the association on the newsk is already closed before accept()