From: Greg Kroah-Hartman Date: Wed, 15 Dec 2021 13:35:38 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v5.4.167~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=033af30113798493d10acb0232c72e20650392bb;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches 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 --- 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 index 00000000000..aea6ca92f7d --- /dev/null +++ b/queue-5.4/bpf-fix-integer-overflow-in-argument-calculation-for-bpf_map_area_alloc.patch @@ -0,0 +1,60 @@ +From 7dd5d437c258bbf4cc15b35229e5208b87b8b4e0 Mon Sep 17 00:00:00 2001 +From: Bui Quang Minh +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 + +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 +Signed-off-by: Alexei Starovoitov +Link: https://lore.kernel.org/bpf/20210613143440.71975-1-minhquangbui99@gmail.com +Signed-off-by: Connor O'Brien +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..425f592f71b --- /dev/null +++ b/queue-5.4/kvm-x86-ignore-sparse-banks-size-for-an-all-cpus-non-sparse-ipi-req.patch @@ -0,0 +1,61 @@ +From 3244867af8c065e51969f1bffe732d3ebfd9a7d2 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +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 + +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 +Reviewed-by: Vitaly Kuznetsov +Message-Id: <20211207220926.718794-2-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..55464b2fdaf --- /dev/null +++ b/queue-5.4/selinux-fix-race-condition-when-computing-ocontext-sids.patch @@ -0,0 +1,356 @@ +From cbfcd13be5cb2a07868afe67520ed181956579a7 Mon Sep 17 00:00:00 2001 +From: Ondrej Mosnacek +Date: Wed, 28 Jul 2021 16:03:13 +0200 +Subject: selinux: fix race condition when computing ocontext SIDs + +From: Ondrej Mosnacek + +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 +Reported-by: Sujithra Periasamy +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ondrej Mosnacek +Signed-off-by: Paul Moore +[vijayb: Backport contextual differences are due to v5.10 RCU related + changes are not in 5.4] +Signed-off-by: Vijay Balakrishna +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-5.4/series b/queue-5.4/series index d7b0a2b6650..fae14e036fd 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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