From: Greg Kroah-Hartman Date: Fri, 23 Feb 2018 09:04:51 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v3.18.96~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=eeb2c0c515b6ca3d95a13e0568d42c2f7d5d1d9a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch --- diff --git a/queue-4.4/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch b/queue-4.4/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch new file mode 100644 index 00000000000..1a327af3743 --- /dev/null +++ b/queue-4.4/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch @@ -0,0 +1,135 @@ +From dfec091439bb2acf763497cfc58f2bdfc67c56b7 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Thu, 15 Feb 2018 16:59:49 +0100 +Subject: dn_getsockoptdecnet: move nf_{get/set}sockopt outside sock lock + +From: Paolo Abeni + +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 +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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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) { diff --git a/queue-4.4/series b/queue-4.4/series index 0061231f4fc..cf13ee4f8fd 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -22,3 +22,4 @@ asoc-ux500-add-module_license-tag.patch video-fbdev-mmp-add-module_license.patch arm64-dts-add-cooling-cells-to-cpu-nodes.patch make-dst_cache-a-silent-config-option.patch +dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch