lkml.org 
[lkml]   [2018]   [Feb]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 025/193] dn_getsockoptdecnet: move nf_{get/set}sockopt outside sock lock
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Paolo Abeni <pabeni@redhat.com>

    commit dfec091439bb2acf763497cfc58f2bdfc67c56b7 upstream.

    After commit 3f34cfae1238 ("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: 3f34cfae1238 ("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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    net/decnet/af_decnet.c | 62 ++++++++++++++++++++++++++-----------------------
    1 file changed, 33 insertions(+), 29 deletions(-)

    --- a/net/decnet/af_decnet.c
    +++ b/net/decnet/af_decnet.c
    @@ -1337,6 +1337,12 @@ static int dn_setsockopt(struct socket *
    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;
    }
    @@ -1444,15 +1450,6 @@ static int __dn_setsockopt(struct socket
    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;
    @@ -1500,6 +1497,12 @@ static int __dn_setsockopt(struct socket
    return -EINVAL;
    scp->info_loc = u.info;
    break;
    +
    + case DSO_LINKINFO:
    + case DSO_STREAM:
    + case DSO_SEQPACKET:
    + default:
    + return -ENOPROTOOPT;
    }

    return 0;
    @@ -1513,6 +1516,20 @@ static int dn_getsockopt(struct socket *
    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;
    }
    @@ -1578,26 +1595,6 @@ static int __dn_getsockopt(struct socket
    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);
    @@ -1629,6 +1626,13 @@ static int __dn_getsockopt(struct socket
    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) {

    \
     
     \ /
      Last update: 2018-02-23 21:41    [W:3.069 / U:0.116 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site