From 0aa7df6d918ec6fa9a3a345a99f353931e61c141 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 May 2020 18:09:20 +0200 Subject: [PATCH] 4.4-stable patches added patches: selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch --- ...ple-messages-in-selinux_netlink_send.patch | 110 ++++++++++++++++++ queue-4.4/series | 1 + 2 files changed, 111 insertions(+) create mode 100644 queue-4.4/selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch diff --git a/queue-4.4/selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch b/queue-4.4/selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch new file mode 100644 index 00000000000..0e58be67f09 --- /dev/null +++ b/queue-4.4/selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch @@ -0,0 +1,110 @@ +From fb73974172ffaaf57a7c42f35424d9aece1a5af6 Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Tue, 28 Apr 2020 09:59:02 -0400 +Subject: selinux: properly handle multiple messages in selinux_netlink_send() + +From: Paul Moore + +commit fb73974172ffaaf57a7c42f35424d9aece1a5af6 upstream. + +Fix the SELinux netlink_send hook to properly handle multiple netlink +messages in a single sk_buff; each message is parsed and subject to +SELinux access control. Prior to this patch, SELinux only inspected +the first message in the sk_buff. + +Cc: stable@vger.kernel.org +Reported-by: Dmitry Vyukov +Reviewed-by: Stephen Smalley +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman + +--- + security/selinux/hooks.c | 69 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 45 insertions(+), 24 deletions(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -4791,38 +4791,59 @@ static int selinux_tun_dev_open(void *se + + static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) + { +- int err = 0; +- u32 perm; ++ int rc = 0; ++ unsigned int msg_len; ++ unsigned int data_len = skb->len; ++ unsigned char *data = skb->data; + struct nlmsghdr *nlh; + struct sk_security_struct *sksec = sk->sk_security; ++ u16 sclass = sksec->sclass; ++ u32 perm; + +- if (skb->len < NLMSG_HDRLEN) { +- err = -EINVAL; +- goto out; +- } +- nlh = nlmsg_hdr(skb); ++ while (data_len >= nlmsg_total_size(0)) { ++ nlh = (struct nlmsghdr *)data; + +- err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); +- if (err) { +- if (err == -EINVAL) { +- printk(KERN_WARNING +- "SELinux: unrecognized netlink message:" +- " protocol=%hu nlmsg_type=%hu sclass=%s\n", +- sk->sk_protocol, nlh->nlmsg_type, +- secclass_map[sksec->sclass - 1].name); +- if (!selinux_enforcing || security_get_allow_unknown()) +- err = 0; ++ /* NOTE: the nlmsg_len field isn't reliably set by some netlink ++ * users which means we can't reject skb's with bogus ++ * length fields; our solution is to follow what ++ * netlink_rcv_skb() does and simply skip processing at ++ * messages with length fields that are clearly junk ++ */ ++ if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len) ++ return 0; ++ ++ rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); ++ if (rc == 0) { ++ rc = sock_has_perm(current, sk, perm); ++ if (rc) ++ return rc; ++ } else if (rc == -EINVAL) { ++ /* -EINVAL is a missing msg/perm mapping */ ++ pr_warn_ratelimited("SELinux: unrecognized netlink" ++ " message: protocol=%hu nlmsg_type=%hu sclass=%s" ++ " pid=%d comm=%s\n", ++ sk->sk_protocol, nlh->nlmsg_type, ++ secclass_map[sclass - 1].name, ++ task_pid_nr(current), current->comm); ++ if (selinux_enforcing && !security_get_allow_unknown()) ++ return rc; ++ rc = 0; ++ } else if (rc == -ENOENT) { ++ /* -ENOENT is a missing socket/class mapping, ignore */ ++ rc = 0; ++ } else { ++ return rc; + } + +- /* Ignore */ +- if (err == -ENOENT) +- err = 0; +- goto out; ++ /* move to the next message after applying netlink padding */ ++ msg_len = NLMSG_ALIGN(nlh->nlmsg_len); ++ if (msg_len >= data_len) ++ return 0; ++ data_len -= msg_len; ++ data += msg_len; + } + +- err = sock_has_perm(current, sk, perm); +-out: +- return err; ++ return rc; + } + + #ifdef CONFIG_NETFILTER diff --git a/queue-4.4/series b/queue-4.4/series index 79d9b9892ad..ba8f536fb21 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -15,3 +15,4 @@ exynos4-is-fix-a-format-string-bug.patch asoc-wm8960-fix-wm8960_sysclk_pll-mode.patch asoc-imx-spdif-fix-crash-on-suspend.patch ipv6-use-read_once-for-inet-hdrincl-as-in-ipv4.patch +selinux-properly-handle-multiple-messages-in-selinux_netlink_send.patch -- 2.47.3