Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfec0914 authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller
Browse files

dn_getsockoptdecnet: move nf_{get/set}sockopt outside sock lock



After commit 3f34cfae ("netfilter: on sockopt() acquire sock lock
only in the required scope"), the caller of nf_{get/set}sockopt() must
not hold any lock, but, in such changeset, I forgot to cope with DECnet.

This commit addresses the issue moving the nf call outside the lock,
in the dn_{get,set}sockopt() with the same schema currently used by
ipv4 and ipv6. Also moves the unhandled sockopts of the end of the main
switch statements, to improve code readability.

Reported-by: default avatarPetr Vandrovec <petr@vandrovec.name>
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=198791#c2


Fixes: 3f34cfae ("netfilter: on sockopt() acquire sock lock only in the required scope")
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7dcf688d
Loading
Loading
Loading
Loading
+33 −29
Original line number Original line Diff line number Diff line
@@ -1338,6 +1338,12 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char __use
	lock_sock(sk);
	lock_sock(sk);
	err = __dn_setsockopt(sock, level, optname, optval, optlen, 0);
	err = __dn_setsockopt(sock, level, optname, optval, optlen, 0);
	release_sock(sk);
	release_sock(sk);
#ifdef CONFIG_NETFILTER
	/* we need to exclude all possible ENOPROTOOPTs except default case */
	if (err == -ENOPROTOOPT && optname != DSO_LINKINFO &&
	    optname != DSO_STREAM && optname != DSO_SEQPACKET)
		err = nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
#endif


	return err;
	return err;
}
}
@@ -1445,15 +1451,6 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
		dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
		dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
		break;
		break;


	default:
#ifdef CONFIG_NETFILTER
		return nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
#endif
	case DSO_LINKINFO:
	case DSO_STREAM:
	case DSO_SEQPACKET:
		return -ENOPROTOOPT;

	case DSO_MAXWINDOW:
	case DSO_MAXWINDOW:
		if (optlen != sizeof(unsigned long))
		if (optlen != sizeof(unsigned long))
			return -EINVAL;
			return -EINVAL;
@@ -1501,6 +1498,12 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
			return -EINVAL;
			return -EINVAL;
		scp->info_loc = u.info;
		scp->info_loc = u.info;
		break;
		break;

	case DSO_LINKINFO:
	case DSO_STREAM:
	case DSO_SEQPACKET:
	default:
		return -ENOPROTOOPT;
	}
	}


	return 0;
	return 0;
@@ -1514,6 +1517,20 @@ static int dn_getsockopt(struct socket *sock, int level, int optname, char __use
	lock_sock(sk);
	lock_sock(sk);
	err = __dn_getsockopt(sock, level, optname, optval, optlen, 0);
	err = __dn_getsockopt(sock, level, optname, optval, optlen, 0);
	release_sock(sk);
	release_sock(sk);
#ifdef CONFIG_NETFILTER
	if (err == -ENOPROTOOPT && optname != DSO_STREAM &&
	    optname != DSO_SEQPACKET && optname != DSO_CONACCEPT &&
	    optname != DSO_CONREJECT) {
		int len;

		if (get_user(len, optlen))
			return -EFAULT;

		err = nf_getsockopt(sk, PF_DECnet, optname, optval, &len);
		if (err >= 0)
			err = put_user(len, optlen);
	}
#endif


	return err;
	return err;
}
}
@@ -1579,26 +1596,6 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
		r_data = &link;
		r_data = &link;
		break;
		break;


	default:
#ifdef CONFIG_NETFILTER
	{
		int ret, len;

		if (get_user(len, optlen))
			return -EFAULT;

		ret = nf_getsockopt(sk, PF_DECnet, optname, optval, &len);
		if (ret >= 0)
			ret = put_user(len, optlen);
		return ret;
	}
#endif
	case DSO_STREAM:
	case DSO_SEQPACKET:
	case DSO_CONACCEPT:
	case DSO_CONREJECT:
		return -ENOPROTOOPT;

	case DSO_MAXWINDOW:
	case DSO_MAXWINDOW:
		if (r_len > sizeof(unsigned long))
		if (r_len > sizeof(unsigned long))
			r_len = sizeof(unsigned long);
			r_len = sizeof(unsigned long);
@@ -1630,6 +1627,13 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
			r_len = sizeof(unsigned char);
			r_len = sizeof(unsigned char);
		r_data = &scp->info_rem;
		r_data = &scp->info_rem;
		break;
		break;

	case DSO_STREAM:
	case DSO_SEQPACKET:
	case DSO_CONACCEPT:
	case DSO_CONREJECT:
	default:
		return -ENOPROTOOPT;
	}
	}


	if (r_data) {
	if (r_data) {