From: Greg Kroah-Hartman Date: Fri, 23 Feb 2018 09:04:11 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v3.18.96~28 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=38ce9c660d2682f8df36ecdfc7041a18ae896fdb;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch --- diff --git a/queue-4.14/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch b/queue-4.14/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch new file mode 100644 index 00000000000..f5fb775d50a --- /dev/null +++ b/queue-4.14/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 +@@ -1339,6 +1339,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; + } +@@ -1446,15 +1452,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; +@@ -1502,6 +1499,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; +@@ -1515,6 +1518,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; + } +@@ -1580,26 +1597,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); +@@ -1631,6 +1628,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.14/series b/queue-4.14/series index b3c0e464404..3019e934232 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -46,3 +46,4 @@ asoc-ux500-add-module_license-tag.patch video-fbdev-mmp-add-module_license.patch arm-8743-1-bl_switcher-add-module_license-tag.patch arm64-dts-add-cooling-cells-to-cpu-nodes.patch +dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch