diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-30 00:29:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-30 00:29:57 -0400 |
commit | 2d408b42ed0a287c64a94b48e24c6bfa95035019 (patch) | |
tree | dba39d735ce0051deadfd4d887637de33dfe842c | |
parent | fde937d826e43c9fe7fecc98b6f3da7188e76930 (diff) | |
parent | 5f0212174db33828f8bddcff501b73d2bc734f72 (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
-rw-r--r-- | drivers/net/irda/irport.c | 2 | ||||
-rw-r--r-- | net/core/netpoll.c | 30 | ||||
-rw-r--r-- | net/sctp/socket.c | 120 |
3 files changed, 101 insertions, 51 deletions
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 3098960dc2a1..3078c419cb02 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c | |||
@@ -509,7 +509,7 @@ static void irport_timeout(struct net_device *dev) | |||
509 | IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", | 509 | IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", |
510 | __FUNCTION__, iir, lsr, iobase); | 510 | __FUNCTION__, iir, lsr, iobase); |
511 | 511 | ||
512 | IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%d\n", | 512 | IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%td\n", |
513 | __FUNCTION__, self->transmitting, self->tx_buff.len, | 513 | __FUNCTION__, self->transmitting, self->tx_buff.len, |
514 | self->tx_buff.data - self->tx_buff.head); | 514 | self->tx_buff.data - self->tx_buff.head); |
515 | 515 | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 758dafe284c0..cf40ff91ac01 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -72,7 +72,8 @@ static void queue_process(struct work_struct *work) | |||
72 | netif_tx_unlock(dev); | 72 | netif_tx_unlock(dev); |
73 | local_irq_restore(flags); | 73 | local_irq_restore(flags); |
74 | 74 | ||
75 | schedule_delayed_work(&npinfo->tx_work, HZ/10); | 75 | if (atomic_read(&npinfo->refcnt)) |
76 | schedule_delayed_work(&npinfo->tx_work, HZ/10); | ||
76 | return; | 77 | return; |
77 | } | 78 | } |
78 | netif_tx_unlock(dev); | 79 | netif_tx_unlock(dev); |
@@ -250,22 +251,23 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
250 | unsigned long flags; | 251 | unsigned long flags; |
251 | 252 | ||
252 | local_irq_save(flags); | 253 | local_irq_save(flags); |
253 | if (netif_tx_trylock(dev)) { | 254 | /* try until next clock tick */ |
254 | /* try until next clock tick */ | 255 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; |
255 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; | 256 | tries > 0; --tries) { |
256 | tries > 0; --tries) { | 257 | if (netif_tx_trylock(dev)) { |
257 | if (!netif_queue_stopped(dev)) | 258 | if (!netif_queue_stopped(dev)) |
258 | status = dev->hard_start_xmit(skb, dev); | 259 | status = dev->hard_start_xmit(skb, dev); |
260 | netif_tx_unlock(dev); | ||
259 | 261 | ||
260 | if (status == NETDEV_TX_OK) | 262 | if (status == NETDEV_TX_OK) |
261 | break; | 263 | break; |
262 | 264 | ||
263 | /* tickle device maybe there is some cleanup */ | ||
264 | netpoll_poll(np); | ||
265 | |||
266 | udelay(USEC_PER_POLL); | ||
267 | } | 265 | } |
268 | netif_tx_unlock(dev); | 266 | |
267 | /* tickle device maybe there is some cleanup */ | ||
268 | netpoll_poll(np); | ||
269 | |||
270 | udelay(USEC_PER_POLL); | ||
269 | } | 271 | } |
270 | local_irq_restore(flags); | 272 | local_irq_restore(flags); |
271 | } | 273 | } |
@@ -784,9 +786,15 @@ void netpoll_cleanup(struct netpoll *np) | |||
784 | if (atomic_dec_and_test(&npinfo->refcnt)) { | 786 | if (atomic_dec_and_test(&npinfo->refcnt)) { |
785 | skb_queue_purge(&npinfo->arp_tx); | 787 | skb_queue_purge(&npinfo->arp_tx); |
786 | skb_queue_purge(&npinfo->txq); | 788 | skb_queue_purge(&npinfo->txq); |
787 | cancel_rearming_delayed_work(&npinfo->tx_work); | 789 | cancel_delayed_work(&npinfo->tx_work); |
788 | flush_scheduled_work(); | 790 | flush_scheduled_work(); |
789 | 791 | ||
792 | /* clean after last, unfinished work */ | ||
793 | if (!skb_queue_empty(&npinfo->txq)) { | ||
794 | struct sk_buff *skb; | ||
795 | skb = __skb_dequeue(&npinfo->txq); | ||
796 | kfree_skb(skb); | ||
797 | } | ||
790 | kfree(npinfo); | 798 | kfree(npinfo); |
791 | } | 799 | } |
792 | } | 800 | } |
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, | |||
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; |
@@ -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 | ||
4260 | error: | 4280 | error: |
@@ -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(¶ms, optval, len)) | 4716 | if (copy_from_user(¶ms, 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() |