diff options
author | David L Stevens <dlstevens@us.ibm.com> | 2008-04-29 06:23:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-29 06:23:00 -0400 |
commit | be666e0a1345ed80f29cb30c73da0ec2ea5c5863 (patch) | |
tree | 46a29aa49e2357a3c1c69a39d9789a16c568fe9d /net | |
parent | 2ad17defd596ca7e8ba782d5fc6950ee0e99513c (diff) |
net: Several cleanups for the setsockopt compat support.
1) added missing "__user" for kgsr and kgf pointers
2) verify read for only GROUP_FILTER_SIZE(0). The group_filter
structure definition (via RFC) includes space for one source
in the source list array, but that source need not be present.
So, sizeof(group_filter) > GROUP_FILTER_SIZE(0). Fixed
the user read-check for minimum length to use the smaller size.
3) remove unneeded "&" for gf_slist addresses
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/compat.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/net/compat.c b/net/compat.c index 01bf95d0832e..8146f654391c 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -548,6 +548,9 @@ struct compat_group_filter { | |||
548 | __attribute__ ((aligned(4))); | 548 | __attribute__ ((aligned(4))); |
549 | } __attribute__ ((packed)); | 549 | } __attribute__ ((packed)); |
550 | 550 | ||
551 | #define __COMPAT_GF0_SIZE (sizeof(struct compat_group_filter) - \ | ||
552 | sizeof(struct __kernel_sockaddr_storage)) | ||
553 | |||
551 | 554 | ||
552 | int compat_mc_setsockopt(struct sock *sock, int level, int optname, | 555 | int compat_mc_setsockopt(struct sock *sock, int level, int optname, |
553 | char __user *optval, int optlen, | 556 | char __user *optval, int optlen, |
@@ -582,7 +585,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname, | |||
582 | case MCAST_UNBLOCK_SOURCE: | 585 | case MCAST_UNBLOCK_SOURCE: |
583 | { | 586 | { |
584 | struct compat_group_source_req __user *gsr32 = (void *)optval; | 587 | struct compat_group_source_req __user *gsr32 = (void *)optval; |
585 | struct group_source_req *kgsr = compat_alloc_user_space( | 588 | struct group_source_req __user *kgsr = compat_alloc_user_space( |
586 | sizeof(struct group_source_req)); | 589 | sizeof(struct group_source_req)); |
587 | u32 interface; | 590 | u32 interface; |
588 | 591 | ||
@@ -603,10 +606,10 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname, | |||
603 | case MCAST_MSFILTER: | 606 | case MCAST_MSFILTER: |
604 | { | 607 | { |
605 | struct compat_group_filter __user *gf32 = (void *)optval; | 608 | struct compat_group_filter __user *gf32 = (void *)optval; |
606 | struct group_filter *kgf; | 609 | struct group_filter __user *kgf; |
607 | u32 interface, fmode, numsrc; | 610 | u32 interface, fmode, numsrc; |
608 | 611 | ||
609 | if (!access_ok(VERIFY_READ, gf32, sizeof(*gf32)) || | 612 | if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) || |
610 | __get_user(interface, &gf32->gf_interface) || | 613 | __get_user(interface, &gf32->gf_interface) || |
611 | __get_user(fmode, &gf32->gf_fmode) || | 614 | __get_user(fmode, &gf32->gf_fmode) || |
612 | __get_user(numsrc, &gf32->gf_numsrc)) | 615 | __get_user(numsrc, &gf32->gf_numsrc)) |
@@ -622,7 +625,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname, | |||
622 | __put_user(numsrc, &kgf->gf_numsrc) || | 625 | __put_user(numsrc, &kgf->gf_numsrc) || |
623 | copy_in_user(&kgf->gf_group, &gf32->gf_group, | 626 | copy_in_user(&kgf->gf_group, &gf32->gf_group, |
624 | sizeof(kgf->gf_group)) || | 627 | sizeof(kgf->gf_group)) || |
625 | (numsrc && copy_in_user(&kgf->gf_slist, &gf32->gf_slist, | 628 | (numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist, |
626 | numsrc * sizeof(kgf->gf_slist[0])))) | 629 | numsrc * sizeof(kgf->gf_slist[0])))) |
627 | return -EFAULT; | 630 | return -EFAULT; |
628 | koptval = (char __user *)kgf; | 631 | koptval = (char __user *)kgf; |