Commit fedae0f6 authored by Paolo Abeni's avatar Paolo Abeni Committed by Greg Kroah-Hartman

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

commit dfec0914 upstream.

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: 's 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: 's avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: 's avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a5a8a31d
...@@ -1337,6 +1337,12 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char __use ...@@ -1337,6 +1337,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;
} }
...@@ -1444,15 +1450,6 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us ...@@ -1444,15 +1450,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;
...@@ -1500,6 +1497,12 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us ...@@ -1500,6 +1497,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;
...@@ -1513,6 +1516,20 @@ static int dn_getsockopt(struct socket *sock, int level, int optname, char __use ...@@ -1513,6 +1516,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;
} }
...@@ -1578,26 +1595,6 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us ...@@ -1578,26 +1595,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);
...@@ -1629,6 +1626,13 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us ...@@ -1629,6 +1626,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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment