Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 95391
b: refs/heads/master
c: 42908c6
h: refs/heads/master
i:
  95389: fd0cde4
  95387: ecf1f28
  95383: e2a99a3
  95375: 760e9a2
  95359: b582bf7
v: v3
  • Loading branch information
David L Stevens authored and David S. Miller committed Apr 29, 2008
1 parent 5206ff6 commit 8b247b5
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: be666e0a1345ed80f29cb30c73da0ec2ea5c5863
refs/heads/master: 42908c69f61f75dd70e424263ab89ee52040382b
3 changes: 3 additions & 0 deletions trunk/include/net/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,8 @@ extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsi

extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, int,
int (*)(struct sock *, int, int, char __user *, int));
extern int compat_mc_getsockopt(struct sock *, int, int, char __user *,
int __user *, int (*)(struct sock *, int, int, char __user *,
int __user *));

#endif /* NET_COMPAT_H */
79 changes: 79 additions & 0 deletions trunk/net/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,85 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,

EXPORT_SYMBOL(compat_mc_setsockopt);

int compat_mc_getsockopt(struct sock *sock, int level, int optname,
char __user *optval, int __user *optlen,
int (*getsockopt)(struct sock *,int,int,char __user *,int __user *))
{
struct compat_group_filter __user *gf32 = (void *)optval;
struct group_filter __user *kgf;
int __user *koptlen;
u32 interface, fmode, numsrc;
int klen, ulen, err;

if (optname != MCAST_MSFILTER)
return getsockopt(sock, level, optname, optval, optlen);

koptlen = compat_alloc_user_space(sizeof(*koptlen));
if (!access_ok(VERIFY_READ, optlen, sizeof(*optlen)) ||
__get_user(ulen, optlen))
return -EFAULT;

/* adjust len for pad */
klen = ulen + sizeof(*kgf) - sizeof(*gf32);

if (klen < GROUP_FILTER_SIZE(0))
return -EINVAL;

if (!access_ok(VERIFY_WRITE, koptlen, sizeof(*koptlen)) ||
__put_user(klen, koptlen))
return -EFAULT;

/* have to allow space for previous compat_alloc_user_space, too */
kgf = compat_alloc_user_space(klen+sizeof(*optlen));

if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) ||
__get_user(interface, &gf32->gf_interface) ||
__get_user(fmode, &gf32->gf_fmode) ||
__get_user(numsrc, &gf32->gf_numsrc) ||
__put_user(interface, &kgf->gf_interface) ||
__put_user(fmode, &kgf->gf_fmode) ||
__put_user(numsrc, &kgf->gf_numsrc) ||
copy_in_user(&kgf->gf_group,&gf32->gf_group,sizeof(kgf->gf_group)))
return -EFAULT;

err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen);
if (err)
return err;

if (!access_ok(VERIFY_READ, koptlen, sizeof(*koptlen)) ||
__get_user(klen, koptlen))
return -EFAULT;

ulen = klen - (sizeof(*kgf)-sizeof(*gf32));

if (!access_ok(VERIFY_WRITE, optlen, sizeof(*optlen)) ||
__put_user(ulen, optlen))
return -EFAULT;

if (!access_ok(VERIFY_READ, kgf, klen) ||
!access_ok(VERIFY_WRITE, gf32, ulen) ||
__get_user(interface, &kgf->gf_interface) ||
__get_user(fmode, &kgf->gf_fmode) ||
__get_user(numsrc, &kgf->gf_numsrc) ||
__put_user(interface, &gf32->gf_interface) ||
__put_user(fmode, &gf32->gf_fmode) ||
__put_user(numsrc, &gf32->gf_numsrc))
return -EFAULT;
if (numsrc) {
int copylen;

klen -= GROUP_FILTER_SIZE(0);
copylen = numsrc * sizeof(gf32->gf_slist[0]);
if (copylen > klen)
copylen = klen;
if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
return -EFAULT;
}
return err;
}

EXPORT_SYMBOL(compat_mc_getsockopt);


/* Argument list sizes for compat_sys_socketcall */
#define AL(x) ((x) * sizeof(u32))
Expand Down
9 changes: 8 additions & 1 deletion trunk/net/ipv4/ip_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,14 @@ int ip_getsockopt(struct sock *sk, int level,
int compat_ip_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
int err = do_ip_getsockopt(sk, level, optname, optval, optlen);
int err;

if (optname == MCAST_MSFILTER)
return compat_mc_getsockopt(sk, level, optname, optval, optlen,
ip_getsockopt);

err = do_ip_getsockopt(sk, level, optname, optval, optlen);

#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS &&
Expand Down
4 changes: 4 additions & 0 deletions trunk/net/ipv6/ipv6_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,10 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
if(level != SOL_IPV6)
return -ENOPROTOOPT;

if (optname == MCAST_MSFILTER)
return compat_mc_getsockopt(sk, level, optname, optval, optlen,
ipv6_getsockopt);

err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible ENOPROTOOPTs except default case */
Expand Down

0 comments on commit 8b247b5

Please sign in to comment.