summaryrefslogtreecommitdiff
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@google.com>2020-05-05 19:29:21 +0200
committerGreg Kroah-Hartman <gregkh@google.com>2020-05-05 19:29:21 +0200
commitb7e5163e48fbcc262d65782d3fabd1cc08a2d757 (patch)
tree74be41e9042e434b9e4a36620d93b29ac4313a16 /security/selinux/hooks.c
parent82cb57eb0b7280471835e36813b94cd4f2a37372 (diff)
parentb63f449e18b130fdc372b9717e72c19b83fc4876 (diff)
Merge 4.4.222 into android-4.4-p
Changes in 4.4.222 ext4: fix special inode number checks in __ext4_iget() drm/qxl: qxl_release leak in qxl_hw_surface_alloc() ALSA: pcm: oss: Place the plugin buffer overflow checks correctly PM: ACPI: Output correct message on target power state RDMA/mlx4: Initialize ib_spec on the stack vfio/type1: Fix VA->PA translation for PFNMAP VMAs in vaddr_get_pfn() ALSA: opti9xx: shut up gcc-10 range warning nfs: Fix potential posix_acl refcnt leak in nfs3_set_acl dmaengine: dmatest: Fix iteration non-stop logic i2c: designware-pci: use IRQF_COND_SUSPEND flag perf hists: Fix HISTC_MEM_DCACHELINE width setting powerpc/perf: Remove PPMU_HAS_SSLOT flag for Power8 perf/x86: Fix uninitialized value usage exynos4-is: fix a format string bug ASoC: wm8960: Fix WM8960_SYSCLK_PLL mode ASoC: imx-spdif: Fix crash on suspend ipv6: use READ_ONCE() for inet->hdrincl as in ipv4 selinux: properly handle multiple messages in selinux_netlink_send() Linux 4.4.222 Change-Id: I510144039d424ae2e57ae23c188f2ed4d020ed11 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d6278891c160..3bc8c5e92c98 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4825,38 +4825,59 @@ 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;
- 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