Commit b212c322 authored by Al Viro's avatar Al Viro
Browse files

handle the group_source_req options directly



Native ->setsockopt() handling of these options (MCAST_..._SOURCE_GROUP
and MCAST_{,UN}BLOCK_SOURCE) consists of copyin + call of a helper that
does the actual work.  The only change needed for ->compat_setsockopt()
is a slightly different copyin - the helpers can be reused as-is.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent fcfa0b09
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -1322,8 +1322,27 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname,
	case MCAST_LEAVE_SOURCE_GROUP:
	case MCAST_BLOCK_SOURCE:
	case MCAST_UNBLOCK_SOURCE:
		return compat_mc_setsockopt(sk, level, optname, optval, optlen,
			ip_setsockopt);
	{
		struct compat_group_source_req __user *gsr32 = (void __user *)optval;
		struct group_source_req greqs;

		if (optlen != sizeof(struct compat_group_source_req))
			return -EINVAL;

		if (get_user(greqs.gsr_interface, &gsr32->gsr_interface) ||
		    copy_from_user(&greqs.gsr_group, &gsr32->gsr_group,
				sizeof(greqs.gsr_group)) ||
		    copy_from_user(&greqs.gsr_source, &gsr32->gsr_source,
				sizeof(greqs.gsr_source)))
			return -EFAULT;

		rtnl_lock();
		lock_sock(sk);
		err = do_mcast_group_source(sk, optname, &greqs);
		release_sock(sk);
		rtnl_unlock();
		return err;
	}
	case MCAST_MSFILTER:
	{
		const int size0 = offsetof(struct compat_group_filter, gf_slist);
+21 −2
Original line number Diff line number Diff line
@@ -1015,8 +1015,27 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
	case MCAST_LEAVE_SOURCE_GROUP:
	case MCAST_BLOCK_SOURCE:
	case MCAST_UNBLOCK_SOURCE:
		return compat_mc_setsockopt(sk, level, optname, optval, optlen,
			ipv6_setsockopt);
	{
		struct compat_group_source_req __user *gsr32 = (void __user *)optval;
		struct group_source_req greqs;

		if (optlen < sizeof(struct compat_group_source_req))
			return -EINVAL;

		if (get_user(greqs.gsr_interface, &gsr32->gsr_interface) ||
		    copy_from_user(&greqs.gsr_group, &gsr32->gsr_group,
				sizeof(greqs.gsr_group)) ||
		    copy_from_user(&greqs.gsr_source, &gsr32->gsr_source,
				sizeof(greqs.gsr_source)))
			return -EFAULT;

		rtnl_lock();
		lock_sock(sk);
		err = do_ipv6_mcast_group_source(sk, optname, &greqs);
		release_sock(sk);
		rtnl_unlock();
		return err;
	}
	case MCAST_MSFILTER:
	{
		const int size0 = offsetof(struct compat_group_filter, gf_slist);