Skip to content

Commit

Permalink
dn_getsockoptdecnet: move nf_{get/set}sockopt outside sock lock
Browse files Browse the repository at this point in the history
After commit 3f34cfa ("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: Petr Vandrovec <petr@vandrovec.name>
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=198791#c2
Fixes: 3f34cfa ("netfilter: on sockopt() acquire sock lock only in the required scope")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Paolo Abeni authored and David S. Miller committed Feb 16, 2018
1 parent 7dcf688 commit dfec091
Showing 1 changed file with 33 additions and 29 deletions.
62 changes: 33 additions & 29 deletions net/decnet/af_decnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,12 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char __use
lock_sock(sk);
err = __dn_setsockopt(sock, level, optname, optval, optlen, 0);
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;
}
Expand Down Expand Up @@ -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);
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:
if (optlen != sizeof(unsigned long))
return -EINVAL;
Expand Down Expand Up @@ -1501,6 +1498,12 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
return -EINVAL;
scp->info_loc = u.info;
break;

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

return 0;
Expand All @@ -1514,6 +1517,20 @@ static int dn_getsockopt(struct socket *sock, int level, int optname, char __use
lock_sock(sk);
err = __dn_getsockopt(sock, level, optname, optval, optlen, 0);
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;
}
Expand Down Expand Up @@ -1579,26 +1596,6 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
r_data = &link;
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:
if (r_len > sizeof(unsigned long))
r_len = sizeof(unsigned long);
Expand Down Expand Up @@ -1630,6 +1627,13 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
r_len = sizeof(unsigned char);
r_data = &scp->info_rem;
break;

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

if (r_data) {
Expand Down

0 comments on commit dfec091

Please sign in to comment.