From 3f7aa783b37ebf29c2387cdd2f16d1d2cf21bad7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 23 Feb 2018 10:05:11 +0100 Subject: [PATCH] 4.9-stable patches added patches: dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch --- ...f_-get-set-sockopt-outside-sock-lock.patch | 135 ++++++++++++++++++ queue-4.9/series | 1 + 2 files changed, 136 insertions(+) create mode 100644 queue-4.9/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch diff --git a/queue-4.9/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch b/queue-4.9/dn_getsockoptdecnet-move-nf_-get-set-sockopt-outside-sock-lock.patch new file mode 100644 index 00000000000..1a327af3743 --- /dev/null +++ b/queue-4.9/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.9/series b/queue-4.9/series index e423bc634ba..d98af37ed0c 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -33,3 +33,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 -- 2.47.3