--- /dev/null
+From liushixin2@huawei.com Thu Jul 7 20:03:15 2022
+From: Liu Shixin <liushixin2@huawei.com>
+Date: Thu, 7 Jul 2022 10:09:38 +0800
+Subject: mm/filemap: fix UAF in find_lock_entries
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Andrew Morton <akpm@linux-foundation.org>, Matthew Wilcox <willy@infradead.org>, Jan Kara <jack@suse.cz>, William Kucharski <william.kucharski@oracle.com>, "Christoph Hellwig" <hch@lst.de>
+Cc: <linux-kernel@vger.kernel.org>, <stable@vger.kernel.org>, Liu Shixin <liushixin2@huawei.com>
+Message-ID: <20220707020938.2122198-1-liushixin2@huawei.com>
+
+From: Liu Shixin <liushixin2@huawei.com>
+
+Release refcount after xas_set to fix UAF which may cause panic like this:
+
+ page:ffffea000491fa40 refcount:1 mapcount:0 mapping:0000000000000000 index:0x1 pfn:0x1247e9
+ head:ffffea000491fa00 order:3 compound_mapcount:0 compound_pincount:0
+ memcg:ffff888104f91091
+ flags: 0x2fffff80010200(slab|head|node=0|zone=2|lastcpupid=0x1fffff)
+...
+page dumped because: VM_BUG_ON_PAGE(PageTail(page))
+ ------------[ cut here ]------------
+ kernel BUG at include/linux/page-flags.h:632!
+ invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN
+ CPU: 1 PID: 7642 Comm: sh Not tainted 5.15.51-dirty #26
+...
+ Call Trace:
+ <TASK>
+ __invalidate_mapping_pages+0xe7/0x540
+ drop_pagecache_sb+0x159/0x320
+ iterate_supers+0x120/0x240
+ drop_caches_sysctl_handler+0xaa/0xe0
+ proc_sys_call_handler+0x2b4/0x480
+ new_sync_write+0x3d6/0x5c0
+ vfs_write+0x446/0x7a0
+ ksys_write+0x105/0x210
+ do_syscall_64+0x35/0x80
+ entry_SYSCALL_64_after_hwframe+0x44/0xae
+ RIP: 0033:0x7f52b5733130
+...
+
+This problem has been fixed on mainline by patch 6b24ca4a1a8d ("mm: Use
+multi-index entries in the page cache") since it deletes the related code.
+
+Fixes: 5c211ba29deb ("mm: add and use find_lock_entries")
+Signed-off-by: Liu Shixin <liushixin2@huawei.com>
+Acked-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/filemap.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -2090,7 +2090,11 @@ unsigned find_lock_entries(struct addres
+
+ rcu_read_lock();
+ while ((page = find_get_entry(&xas, end, XA_PRESENT))) {
++ unsigned long next_idx = xas.xa_index + 1;
++
+ if (!xa_is_value(page)) {
++ if (PageTransHuge(page))
++ next_idx = page->index + thp_nr_pages(page);
+ if (page->index < start)
+ goto put;
+ if (page->index + thp_nr_pages(page) - 1 > end)
+@@ -2111,13 +2115,11 @@ unlock:
+ put:
+ put_page(page);
+ next:
+- if (!xa_is_value(page) && PageTransHuge(page)) {
+- unsigned int nr_pages = thp_nr_pages(page);
+-
++ if (next_idx != xas.xa_index + 1) {
+ /* Final THP may cross MAX_LFS_FILESIZE on 32-bit */
+- xas_set(&xas, page->index + nr_pages);
+- if (xas.xa_index < nr_pages)
++ if (next_idx < xas.xa_index)
+ break;
++ xas_set(&xas, next_idx);
+ }
+ }
+ rcu_read_unlock();
--- /dev/null
+From eeaa345e128515135ccb864c04482180c08e3259 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Wed, 8 Jun 2022 20:22:05 +0200
+Subject: mm/slub: add missing TID updates on slab deactivation
+
+From: Jann Horn <jannh@google.com>
+
+commit eeaa345e128515135ccb864c04482180c08e3259 upstream.
+
+The fastpath in slab_alloc_node() assumes that c->slab is stable as long as
+the TID stays the same. However, two places in __slab_alloc() currently
+don't update the TID when deactivating the CPU slab.
+
+If multiple operations race the right way, this could lead to an object
+getting lost; or, in an even more unlikely situation, it could even lead to
+an object being freed onto the wrong slab's freelist, messing up the
+`inuse` counter and eventually causing a page to be freed to the page
+allocator while it still contains slab objects.
+
+(I haven't actually tested these cases though, this is just based on
+looking at the code. Writing testcases for this stuff seems like it'd be
+a pain...)
+
+The race leading to state inconsistency is (all operations on the same CPU
+and kmem_cache):
+
+ - task A: begin do_slab_free():
+ - read TID
+ - read pcpu freelist (==NULL)
+ - check `slab == c->slab` (true)
+ - [PREEMPT A->B]
+ - task B: begin slab_alloc_node():
+ - fastpath fails (`c->freelist` is NULL)
+ - enter __slab_alloc()
+ - slub_get_cpu_ptr() (disables preemption)
+ - enter ___slab_alloc()
+ - take local_lock_irqsave()
+ - read c->freelist as NULL
+ - get_freelist() returns NULL
+ - write `c->slab = NULL`
+ - drop local_unlock_irqrestore()
+ - goto new_slab
+ - slub_percpu_partial() is NULL
+ - get_partial() returns NULL
+ - slub_put_cpu_ptr() (enables preemption)
+ - [PREEMPT B->A]
+ - task A: finish do_slab_free():
+ - this_cpu_cmpxchg_double() succeeds()
+ - [CORRUPT STATE: c->slab==NULL, c->freelist!=NULL]
+
+From there, the object on c->freelist will get lost if task B is allowed to
+continue from here: It will proceed to the retry_load_slab label,
+set c->slab, then jump to load_freelist, which clobbers c->freelist.
+
+But if we instead continue as follows, we get worse corruption:
+
+ - task A: run __slab_free() on object from other struct slab:
+ - CPU_PARTIAL_FREE case (slab was on no list, is now on pcpu partial)
+ - task A: run slab_alloc_node() with NUMA node constraint:
+ - fastpath fails (c->slab is NULL)
+ - call __slab_alloc()
+ - slub_get_cpu_ptr() (disables preemption)
+ - enter ___slab_alloc()
+ - c->slab is NULL: goto new_slab
+ - slub_percpu_partial() is non-NULL
+ - set c->slab to slub_percpu_partial(c)
+ - [CORRUPT STATE: c->slab points to slab-1, c->freelist has objects
+ from slab-2]
+ - goto redo
+ - node_match() fails
+ - goto deactivate_slab
+ - existing c->freelist is passed into deactivate_slab()
+ - inuse count of slab-1 is decremented to account for object from
+ slab-2
+
+At this point, the inuse count of slab-1 is 1 lower than it should be.
+This means that if we free all allocated objects in slab-1 except for one,
+SLUB will think that slab-1 is completely unused, and may free its page,
+leading to use-after-free.
+
+Fixes: c17dda40a6a4e ("slub: Separate out kmem_cache_cpu processing from deactivate_slab")
+Fixes: 03e404af26dc2 ("slub: fast release on full slab")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jann Horn <jannh@google.com>
+Acked-by: Christoph Lameter <cl@linux.com>
+Acked-by: David Rientjes <rientjes@google.com>
+Reviewed-by: Muchun Song <songmuchun@bytedance.com>
+Tested-by: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+Link: https://lore.kernel.org/r/20220608182205.2945720-1-jannh@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/slub.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -2935,6 +2935,7 @@ redo:
+
+ if (!freelist) {
+ c->page = NULL;
++ c->tid = next_tid(c->tid);
+ local_unlock_irqrestore(&s->cpu_slab->lock, flags);
+ stat(s, DEACTIVATE_BYPASS);
+ goto new_slab;
+@@ -2967,6 +2968,7 @@ deactivate_slab:
+ freelist = c->freelist;
+ c->page = NULL;
+ c->freelist = NULL;
++ c->tid = next_tid(c->tid);
+ local_unlock_irqrestore(&s->cpu_slab->lock, flags);
+ deactivate_slab(s, page, freelist);
+
--- /dev/null
+From po-hsu.lin@canonical.com Thu Jul 7 20:04:15 2022
+From: Po-Hsu Lin <po-hsu.lin@canonical.com>
+Date: Thu, 7 Jul 2022 17:42:07 +0800
+Subject: Revert "selftests/bpf: Add test for bpf_timer overwriting crash"
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: memxor@gmail.com, linux-kernel@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, shuah@kernel.org, bpf@vger.kernel.org, po-hsu.lin@canonical.com
+Message-ID: <20220707094207.229875-2-po-hsu.lin@canonical.com>
+
+From: Po-Hsu Lin <po-hsu.lin@canonical.com>
+
+This reverts commit b0028e1cc1faf2e5d88ad4065590aca90d650182 which is
+commit a7e75016a0753c24d6c995bc02501ae35368e333 upstream.
+
+It will break the bpf self-tests build with:
+progs/timer_crash.c:8:19: error: field has incomplete type 'struct bpf_timer'
+ struct bpf_timer timer;
+ ^
+/home/ubuntu/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helper_defs.h:39:8:
+note: forward declaration of 'struct bpf_timer'
+struct bpf_timer;
+ ^
+1 error generated.
+
+This test can only be built with 5.17 and newer kernels.
+
+Signed-off-by: Po-Hsu Lin <po-hsu.lin@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/prog_tests/timer_crash.c | 32 -----------
+ tools/testing/selftests/bpf/progs/timer_crash.c | 54 -------------------
+ 2 files changed, 86 deletions(-)
+ delete mode 100644 tools/testing/selftests/bpf/prog_tests/timer_crash.c
+ delete mode 100644 tools/testing/selftests/bpf/progs/timer_crash.c
+
+--- a/tools/testing/selftests/bpf/prog_tests/timer_crash.c
++++ /dev/null
+@@ -1,32 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-#include <test_progs.h>
+-#include "timer_crash.skel.h"
+-
+-enum {
+- MODE_ARRAY,
+- MODE_HASH,
+-};
+-
+-static void test_timer_crash_mode(int mode)
+-{
+- struct timer_crash *skel;
+-
+- skel = timer_crash__open_and_load();
+- if (!ASSERT_OK_PTR(skel, "timer_crash__open_and_load"))
+- return;
+- skel->bss->pid = getpid();
+- skel->bss->crash_map = mode;
+- if (!ASSERT_OK(timer_crash__attach(skel), "timer_crash__attach"))
+- goto end;
+- usleep(1);
+-end:
+- timer_crash__destroy(skel);
+-}
+-
+-void test_timer_crash(void)
+-{
+- if (test__start_subtest("array"))
+- test_timer_crash_mode(MODE_ARRAY);
+- if (test__start_subtest("hash"))
+- test_timer_crash_mode(MODE_HASH);
+-}
+--- a/tools/testing/selftests/bpf/progs/timer_crash.c
++++ /dev/null
+@@ -1,54 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-
+-#include <vmlinux.h>
+-#include <bpf/bpf_tracing.h>
+-#include <bpf/bpf_helpers.h>
+-
+-struct map_elem {
+- struct bpf_timer timer;
+- struct bpf_spin_lock lock;
+-};
+-
+-struct {
+- __uint(type, BPF_MAP_TYPE_ARRAY);
+- __uint(max_entries, 1);
+- __type(key, int);
+- __type(value, struct map_elem);
+-} amap SEC(".maps");
+-
+-struct {
+- __uint(type, BPF_MAP_TYPE_HASH);
+- __uint(max_entries, 1);
+- __type(key, int);
+- __type(value, struct map_elem);
+-} hmap SEC(".maps");
+-
+-int pid = 0;
+-int crash_map = 0; /* 0 for amap, 1 for hmap */
+-
+-SEC("fentry/do_nanosleep")
+-int sys_enter(void *ctx)
+-{
+- struct map_elem *e, value = {};
+- void *map = crash_map ? (void *)&hmap : (void *)&amap;
+-
+- if (bpf_get_current_task_btf()->tgid != pid)
+- return 0;
+-
+- *(void **)&value = (void *)0xdeadcaf3;
+-
+- bpf_map_update_elem(map, &(int){0}, &value, 0);
+- /* For array map, doing bpf_map_update_elem will do a
+- * check_and_free_timer_in_array, which will trigger the crash if timer
+- * pointer was overwritten, for hmap we need to use bpf_timer_cancel.
+- */
+- if (crash_map == 1) {
+- e = bpf_map_lookup_elem(map, &(int){0});
+- if (!e)
+- return 0;
+- bpf_timer_cancel(&e->timer);
+- }
+- return 0;
+-}
+-
+-char _license[] SEC("license") = "GPL";
--- /dev/null
+mm-slub-add-missing-tid-updates-on-slab-deactivation.patch
+mm-filemap-fix-uaf-in-find_lock_entries.patch
+revert-selftests-bpf-add-test-for-bpf_timer-overwriting-crash.patch