diff --git a/debian/changelog b/debian/changelog index 6cac52587..c98562377 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 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 diff --git a/debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch b/debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch new file mode 100644 index 000000000..7857d0db8 --- /dev/null +++ b/debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch @@ -0,0 +1,112 @@ +From: Paul Moore +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 +Reviewed-by: Stephen Smalley +Signed-off-by: Paul Moore +--- + 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 + diff --git a/debian/patches/series b/debian/patches/series index c4eedde94..ee50e4c72 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -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