selinux: properly handle multiple messages in selinux_netlink_send() (CVE-2020-10751)
This commit is contained in:
parent
136062cf83
commit
b3b40efebd
|
@ -1,3 +1,10 @@
|
|||
linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium
|
||||
|
||||
* selinux: properly handle multiple messages in selinux_netlink_send()
|
||||
(CVE-2020-10751)
|
||||
|
||||
-- Salvatore Bonaccorso <carnil@debian.org> Thu, 28 May 2020 23:02:30 +0200
|
||||
|
||||
linux (4.19.118-2) buster; urgency=medium
|
||||
|
||||
* Merge changes from 4.19.67-2+deb10u2 to include all security fixes from
|
||||
|
|
112
debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch
vendored
Normal file
112
debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
From: Paul Moore <paul@paul-moore.com>
|
||||
Date: Tue, 28 Apr 2020 09:59:02 -0400
|
||||
Subject: selinux: properly handle multiple messages in selinux_netlink_send()
|
||||
Origin: https://git.kernel.org/linus/fb73974172ffaaf57a7c42f35424d9aece1a5af6
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-10751
|
||||
|
||||
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 <dvyukov@google.com>
|
||||
Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
|
||||
Signed-off-by: Paul Moore <paul@paul-moore.com>
|
||||
---
|
||||
security/selinux/hooks.c | 70 ++++++++++++++++++++++++++--------------
|
||||
1 file changed, 45 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
|
||||
index c574285966f9..452254fd89f8 100644
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -5595,40 +5595,60 @@ static int selinux_tun_dev_open(void *security)
|
||||
|
||||
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;
|
||||
+
|
||||
+ /* 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;
|
||||
|
||||
- err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
|
||||
- if (err) {
|
||||
- if (err == -EINVAL) {
|
||||
+ rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm);
|
||||
+ if (rc == 0) {
|
||||
+ rc = sock_has_perm(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"
|
||||
- " pig=%d comm=%s\n",
|
||||
- sk->sk_protocol, nlh->nlmsg_type,
|
||||
- secclass_map[sksec->sclass - 1].name,
|
||||
- task_pid_nr(current), current->comm);
|
||||
- if (!enforcing_enabled(&selinux_state) ||
|
||||
- security_get_allow_unknown(&selinux_state))
|
||||
- err = 0;
|
||||
+ " 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 (enforcing_enabled(&selinux_state) &&
|
||||
+ !security_get_allow_unknown(&selinux_state))
|
||||
+ 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(sk, perm);
|
||||
-out:
|
||||
- return err;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETFILTER
|
||||
--
|
||||
2.27.0.rc0
|
||||
|
|
@ -300,5 +300,6 @@ bugfix/all/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6.patch
|
|||
bugfix/all/blktrace-protect-q-blk_trace-with-rcu.patch
|
||||
bugfix/all/blktrace-fix-dereference-after-null-check.patch
|
||||
bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch
|
||||
bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch
|
||||
|
||||
# ABI maintenance
|
||||
|
|
Loading…
Reference in New Issue