]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Dec 2021 13:35:38 +0000 (14:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Dec 2021 13:35:38 +0000 (14:35 +0100)
added patches:
bpf-fix-integer-overflow-in-argument-calculation-for-bpf_map_area_alloc.patch
kvm-x86-ignore-sparse-banks-size-for-an-all-cpus-non-sparse-ipi-req.patch
selinux-fix-race-condition-when-computing-ocontext-sids.patch

queue-5.4/bpf-fix-integer-overflow-in-argument-calculation-for-bpf_map_area_alloc.patch [new file with mode: 0644]
queue-5.4/kvm-x86-ignore-sparse-banks-size-for-an-all-cpus-non-sparse-ipi-req.patch [new file with mode: 0644]
queue-5.4/selinux-fix-race-condition-when-computing-ocontext-sids.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/bpf-fix-integer-overflow-in-argument-calculation-for-bpf_map_area_alloc.patch b/queue-5.4/bpf-fix-integer-overflow-in-argument-calculation-for-bpf_map_area_alloc.patch
new file mode 100644 (file)
index 0000000..aea6ca9
--- /dev/null
@@ -0,0 +1,60 @@
+From 7dd5d437c258bbf4cc15b35229e5208b87b8b4e0 Mon Sep 17 00:00:00 2001
+From: Bui Quang Minh <minhquangbui99@gmail.com>
+Date: Sun, 13 Jun 2021 21:34:39 +0700
+Subject: bpf: Fix integer overflow in argument calculation for bpf_map_area_alloc
+
+From: Bui Quang Minh <minhquangbui99@gmail.com>
+
+commit 7dd5d437c258bbf4cc15b35229e5208b87b8b4e0 upstream.
+
+In 32-bit architecture, the result of sizeof() is a 32-bit integer so
+the expression becomes the multiplication between 2 32-bit integer which
+can potentially leads to integer overflow. As a result,
+bpf_map_area_alloc() allocates less memory than needed.
+
+Fix this by casting 1 operand to u64.
+
+Fixes: 0d2c4f964050 ("bpf: Eliminate rlimit-based memory accounting for sockmap and sockhash maps")
+Fixes: 99c51064fb06 ("devmap: Use bpf_map_area_alloc() for allocating hash buckets")
+Fixes: 546ac1ffb70d ("bpf: add devmap, a map for storing net device references")
+Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Link: https://lore.kernel.org/bpf/20210613143440.71975-1-minhquangbui99@gmail.com
+Signed-off-by: Connor O'Brien <connoro@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/devmap.c |    4 ++--
+ net/core/sock_map.c |    2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/kernel/bpf/devmap.c
++++ b/kernel/bpf/devmap.c
+@@ -94,7 +94,7 @@ static struct hlist_head *dev_map_create
+       int i;
+       struct hlist_head *hash;
+-      hash = bpf_map_area_alloc(entries * sizeof(*hash), numa_node);
++      hash = bpf_map_area_alloc((u64) entries * sizeof(*hash), numa_node);
+       if (hash != NULL)
+               for (i = 0; i < entries; i++)
+                       INIT_HLIST_HEAD(&hash[i]);
+@@ -159,7 +159,7 @@ static int dev_map_init_map(struct bpf_d
+               spin_lock_init(&dtab->index_lock);
+       } else {
+-              dtab->netdev_map = bpf_map_area_alloc(dtab->map.max_entries *
++              dtab->netdev_map = bpf_map_area_alloc((u64) dtab->map.max_entries *
+                                                     sizeof(struct bpf_dtab_netdev *),
+                                                     dtab->map.numa_node);
+               if (!dtab->netdev_map)
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -48,7 +48,7 @@ static struct bpf_map *sock_map_alloc(un
+       if (err)
+               goto free_stab;
+-      stab->sks = bpf_map_area_alloc(stab->map.max_entries *
++      stab->sks = bpf_map_area_alloc((u64) stab->map.max_entries *
+                                      sizeof(struct sock *),
+                                      stab->map.numa_node);
+       if (stab->sks)
diff --git a/queue-5.4/kvm-x86-ignore-sparse-banks-size-for-an-all-cpus-non-sparse-ipi-req.patch b/queue-5.4/kvm-x86-ignore-sparse-banks-size-for-an-all-cpus-non-sparse-ipi-req.patch
new file mode 100644 (file)
index 0000000..425f592
--- /dev/null
@@ -0,0 +1,61 @@
+From 3244867af8c065e51969f1bffe732d3ebfd9a7d2 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Tue, 7 Dec 2021 22:09:19 +0000
+Subject: KVM: x86: Ignore sparse banks size for an "all CPUs", non-sparse IPI req
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 3244867af8c065e51969f1bffe732d3ebfd9a7d2 upstream.
+
+Do not bail early if there are no bits set in the sparse banks for a
+non-sparse, a.k.a. "all CPUs", IPI request.  Per the Hyper-V spec, it is
+legal to have a variable length of '0', e.g. VP_SET's BankContents in
+this case, if the request can be serviced without the extra info.
+
+  It is possible that for a given invocation of a hypercall that does
+  accept variable sized input headers that all the header input fits
+  entirely within the fixed size header. In such cases the variable sized
+  input header is zero-sized and the corresponding bits in the hypercall
+  input should be set to zero.
+
+Bailing early results in KVM failing to send IPIs to all CPUs as expected
+by the guest.
+
+Fixes: 214ff83d4473 ("KVM: x86: hyperv: implement PV IPI send hypercalls")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Message-Id: <20211207220926.718794-2-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/hyperv.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/hyperv.c
++++ b/arch/x86/kvm/hyperv.c
+@@ -1501,11 +1501,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vc
+               all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL;
++              if (all_cpus)
++                      goto check_and_send_ipi;
++
+               if (!sparse_banks_len)
+                       goto ret_success;
+-              if (!all_cpus &&
+-                  kvm_read_guest(kvm,
++              if (kvm_read_guest(kvm,
+                                  ingpa + offsetof(struct hv_send_ipi_ex,
+                                                   vp_set.bank_contents),
+                                  sparse_banks,
+@@ -1513,6 +1515,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vc
+                       return HV_STATUS_INVALID_HYPERCALL_INPUT;
+       }
++check_and_send_ipi:
+       if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
+               return HV_STATUS_INVALID_HYPERCALL_INPUT;
diff --git a/queue-5.4/selinux-fix-race-condition-when-computing-ocontext-sids.patch b/queue-5.4/selinux-fix-race-condition-when-computing-ocontext-sids.patch
new file mode 100644 (file)
index 0000000..55464b2
--- /dev/null
@@ -0,0 +1,356 @@
+From cbfcd13be5cb2a07868afe67520ed181956579a7 Mon Sep 17 00:00:00 2001
+From: Ondrej Mosnacek <omosnace@redhat.com>
+Date: Wed, 28 Jul 2021 16:03:13 +0200
+Subject: selinux: fix race condition when computing ocontext SIDs
+
+From: Ondrej Mosnacek <omosnace@redhat.com>
+
+commit cbfcd13be5cb2a07868afe67520ed181956579a7 upstream.
+
+Current code contains a lot of racy patterns when converting an
+ocontext's context structure to an SID. This is being done in a "lazy"
+fashion, such that the SID is looked up in the SID table only when it's
+first needed and then cached in the "sid" field of the ocontext
+structure. However, this is done without any locking or memory barriers
+and is thus unsafe.
+
+Between commits 24ed7fdae669 ("selinux: use separate table for initial
+SID lookup") and 66f8e2f03c02 ("selinux: sidtab reverse lookup hash
+table"), this race condition lead to an actual observable bug, because a
+pointer to the shared sid field was passed directly to
+sidtab_context_to_sid(), which was using this location to also store an
+intermediate value, which could have been read by other threads and
+interpreted as an SID. In practice this caused e.g. new mounts to get a
+wrong (seemingly random) filesystem context, leading to strange denials.
+This bug has been spotted in the wild at least twice, see [1] and [2].
+
+Fix the race condition by making all the racy functions use a common
+helper that ensures the ocontext::sid accesses are made safely using the
+appropriate SMP constructs.
+
+Note that security_netif_sid() was populating the sid field of both
+contexts stored in the ocontext, but only the first one was actually
+used. The SELinux wiki's documentation on the "netifcon" policy
+statement [3] suggests that using only the first context is intentional.
+I kept only the handling of the first context here, as there is really
+no point in doing the SID lookup for the unused one.
+
+I wasn't able to reproduce the bug mentioned above on any kernel that
+includes commit 66f8e2f03c02, even though it has been reported that the
+issue occurs with that commit, too, just less frequently. Thus, I wasn't
+able to verify that this patch fixes the issue, but it makes sense to
+avoid the race condition regardless.
+
+[1] https://github.com/containers/container-selinux/issues/89
+[2] https://lists.fedoraproject.org/archives/list/selinux@lists.fedoraproject.org/thread/6DMTAMHIOAOEMUAVTULJD45JZU7IBAFM/
+[3] https://selinuxproject.org/page/NetworkStatements#netifcon
+
+Cc: stable@vger.kernel.org
+Cc: Xinjie Zheng <xinjie@google.com>
+Reported-by: Sujithra Periasamy <sujithra@google.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+[vijayb: Backport contextual differences are due to v5.10 RCU related
+ changes are not in 5.4]
+Signed-off-by: Vijay Balakrishna <vijayb@linux.microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/ss/services.c |  159 ++++++++++++++++++++++-------------------
+ 1 file changed, 87 insertions(+), 72 deletions(-)
+
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -2251,6 +2251,43 @@ size_t security_policydb_len(struct seli
+ }
+ /**
++ * ocontext_to_sid - Helper to safely get sid for an ocontext
++ * @sidtab: SID table
++ * @c: ocontext structure
++ * @index: index of the context entry (0 or 1)
++ * @out_sid: pointer to the resulting SID value
++ *
++ * For all ocontexts except OCON_ISID the SID fields are populated
++ * on-demand when needed. Since updating the SID value is an SMP-sensitive
++ * operation, this helper must be used to do that safely.
++ *
++ * WARNING: This function may return -ESTALE, indicating that the caller
++ * must retry the operation after re-acquiring the policy pointer!
++ */
++static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c,
++                         size_t index, u32 *out_sid)
++{
++      int rc;
++      u32 sid;
++
++      /* Ensure the associated sidtab entry is visible to this thread. */
++      sid = smp_load_acquire(&c->sid[index]);
++      if (!sid) {
++              rc = sidtab_context_to_sid(sidtab, &c->context[index], &sid);
++              if (rc)
++                      return rc;
++
++              /*
++               * Ensure the new sidtab entry is visible to other threads
++               * when they see the SID.
++               */
++              smp_store_release(&c->sid[index], sid);
++      }
++      *out_sid = sid;
++      return 0;
++}
++
++/**
+  * security_port_sid - Obtain the SID for a port.
+  * @protocol: protocol number
+  * @port: port number
+@@ -2262,10 +2299,12 @@ int security_port_sid(struct selinux_sta
+       struct policydb *policydb;
+       struct sidtab *sidtab;
+       struct ocontext *c;
+-      int rc = 0;
++      int rc;
+       read_lock(&state->ss->policy_rwlock);
++retry:
++      rc = 0;
+       policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
+@@ -2279,14 +2318,11 @@ int security_port_sid(struct selinux_sta
+       }
+       if (c) {
+-              if (!c->sid[0]) {
+-                      rc = sidtab_context_to_sid(sidtab,
+-                                                 &c->context[0],
+-                                                 &c->sid[0]);
+-                      if (rc)
+-                              goto out;
+-              }
+-              *out_sid = c->sid[0];
++              rc = ocontext_to_sid(sidtab, c, 0, out_sid);
++              if (rc == -ESTALE)
++                      goto retry;
++              if (rc)
++                      goto out;
+       } else {
+               *out_sid = SECINITSID_PORT;
+       }
+@@ -2308,10 +2344,12 @@ int security_ib_pkey_sid(struct selinux_
+       struct policydb *policydb;
+       struct sidtab *sidtab;
+       struct ocontext *c;
+-      int rc = 0;
++      int rc;
+       read_lock(&state->ss->policy_rwlock);
++retry:
++      rc = 0;
+       policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
+@@ -2326,14 +2364,11 @@ int security_ib_pkey_sid(struct selinux_
+       }
+       if (c) {
+-              if (!c->sid[0]) {
+-                      rc = sidtab_context_to_sid(sidtab,
+-                                                 &c->context[0],
+-                                                 &c->sid[0]);
+-                      if (rc)
+-                              goto out;
+-              }
+-              *out_sid = c->sid[0];
++              rc = ocontext_to_sid(sidtab, c, 0, out_sid);
++              if (rc == -ESTALE)
++                      goto retry;
++              if (rc)
++                      goto out;
+       } else
+               *out_sid = SECINITSID_UNLABELED;
+@@ -2354,10 +2389,12 @@ int security_ib_endport_sid(struct selin
+       struct policydb *policydb;
+       struct sidtab *sidtab;
+       struct ocontext *c;
+-      int rc = 0;
++      int rc;
+       read_lock(&state->ss->policy_rwlock);
++retry:
++      rc = 0;
+       policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
+@@ -2373,14 +2410,11 @@ int security_ib_endport_sid(struct selin
+       }
+       if (c) {
+-              if (!c->sid[0]) {
+-                      rc = sidtab_context_to_sid(sidtab,
+-                                                 &c->context[0],
+-                                                 &c->sid[0]);
+-                      if (rc)
+-                              goto out;
+-              }
+-              *out_sid = c->sid[0];
++              rc = ocontext_to_sid(sidtab, c, 0, out_sid);
++              if (rc == -ESTALE)
++                      goto retry;
++              if (rc)
++                      goto out;
+       } else
+               *out_sid = SECINITSID_UNLABELED;
+@@ -2399,11 +2433,13 @@ int security_netif_sid(struct selinux_st
+ {
+       struct policydb *policydb;
+       struct sidtab *sidtab;
+-      int rc = 0;
++      int rc;
+       struct ocontext *c;
+       read_lock(&state->ss->policy_rwlock);
++retry:
++      rc = 0;
+       policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
+@@ -2415,19 +2451,11 @@ int security_netif_sid(struct selinux_st
+       }
+       if (c) {
+-              if (!c->sid[0] || !c->sid[1]) {
+-                      rc = sidtab_context_to_sid(sidtab,
+-                                                &c->context[0],
+-                                                &c->sid[0]);
+-                      if (rc)
+-                              goto out;
+-                      rc = sidtab_context_to_sid(sidtab,
+-                                                 &c->context[1],
+-                                                 &c->sid[1]);
+-                      if (rc)
+-                              goto out;
+-              }
+-              *if_sid = c->sid[0];
++              rc = ocontext_to_sid(sidtab, c, 0, if_sid);
++              if (rc == -ESTALE)
++                      goto retry;
++              if (rc)
++                      goto out;
+       } else
+               *if_sid = SECINITSID_NETIF;
+@@ -2469,6 +2497,7 @@ int security_node_sid(struct selinux_sta
+       read_lock(&state->ss->policy_rwlock);
++retry:
+       policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
+@@ -2511,14 +2540,11 @@ int security_node_sid(struct selinux_sta
+       }
+       if (c) {
+-              if (!c->sid[0]) {
+-                      rc = sidtab_context_to_sid(sidtab,
+-                                                 &c->context[0],
+-                                                 &c->sid[0]);
+-                      if (rc)
+-                              goto out;
+-              }
+-              *out_sid = c->sid[0];
++              rc = ocontext_to_sid(sidtab, c, 0, out_sid);
++              if (rc == -ESTALE)
++                      goto retry;
++              if (rc)
++                      goto out;
+       } else {
+               *out_sid = SECINITSID_NODE;
+       }
+@@ -2677,7 +2703,7 @@ static inline int __security_genfs_sid(s
+       u16 sclass;
+       struct genfs *genfs;
+       struct ocontext *c;
+-      int rc, cmp = 0;
++      int cmp = 0;
+       while (path[0] == '/' && path[1] == '/')
+               path++;
+@@ -2691,9 +2717,8 @@ static inline int __security_genfs_sid(s
+                       break;
+       }
+-      rc = -ENOENT;
+       if (!genfs || cmp)
+-              goto out;
++              return -ENOENT;
+       for (c = genfs->head; c; c = c->next) {
+               len = strlen(c->u.name);
+@@ -2702,20 +2727,10 @@ static inline int __security_genfs_sid(s
+                       break;
+       }
+-      rc = -ENOENT;
+       if (!c)
+-              goto out;
++              return -ENOENT;
+-      if (!c->sid[0]) {
+-              rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]);
+-              if (rc)
+-                      goto out;
+-      }
+-
+-      *sid = c->sid[0];
+-      rc = 0;
+-out:
+-      return rc;
++      return ocontext_to_sid(sidtab, c, 0, sid);
+ }
+ /**
+@@ -2750,13 +2765,15 @@ int security_fs_use(struct selinux_state
+ {
+       struct policydb *policydb;
+       struct sidtab *sidtab;
+-      int rc = 0;
++      int rc;
+       struct ocontext *c;
+       struct superblock_security_struct *sbsec = sb->s_security;
+       const char *fstype = sb->s_type->name;
+       read_lock(&state->ss->policy_rwlock);
++retry:
++      rc = 0;
+       policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
+@@ -2769,13 +2786,11 @@ int security_fs_use(struct selinux_state
+       if (c) {
+               sbsec->behavior = c->v.behavior;
+-              if (!c->sid[0]) {
+-                      rc = sidtab_context_to_sid(sidtab, &c->context[0],
+-                                                 &c->sid[0]);
+-                      if (rc)
+-                              goto out;
+-              }
+-              sbsec->sid = c->sid[0];
++              rc = ocontext_to_sid(sidtab, c, 0, &sbsec->sid);
++              if (rc == -ESTALE)
++                      goto retry;
++              if (rc)
++                      goto out;
+       } else {
+               rc = __security_genfs_sid(state, fstype, "/", SECCLASS_DIR,
+                                         &sbsec->sid);
index d7b0a2b6650e75094a0b3445f206d6f04ac6536b..fae14e036fd0be2c3a0e6ba4691dd3a3dcc11ffa 100644 (file)
@@ -7,3 +7,6 @@ net-netlink-af_netlink-prevent-empty-skb-by-adding-a.patch
 drm-amd-display-fix-for-the-no-audio-bug-with-tiled-.patch
 drm-amd-display-add-connector-type-check-for-crc-sou.patch
 tracing-fix-a-kmemleak-false-positive-in-tracing_map.patch
+kvm-x86-ignore-sparse-banks-size-for-an-all-cpus-non-sparse-ipi-req.patch
+selinux-fix-race-condition-when-computing-ocontext-sids.patch
+bpf-fix-integer-overflow-in-argument-calculation-for-bpf_map_area_alloc.patch