--- /dev/null
+From 978c4486cca5c7b9253d3ab98a88c8e769cb9bbd Mon Sep 17 00:00:00 2001
+From: Jiri Olsa <jolsa@kernel.org>
+Date: Sun, 8 Dec 2024 15:25:07 +0100
+Subject: bpf,perf: Fix invalid prog_array access in perf_event_detach_bpf_prog
+
+From: Jiri Olsa <jolsa@kernel.org>
+
+commit 978c4486cca5c7b9253d3ab98a88c8e769cb9bbd upstream.
+
+Syzbot reported [1] crash that happens for following tracing scenario:
+
+ - create tracepoint perf event with attr.inherit=1, attach it to the
+ process and set bpf program to it
+ - attached process forks -> chid creates inherited event
+
+ the new child event shares the parent's bpf program and tp_event
+ (hence prog_array) which is global for tracepoint
+
+ - exit both process and its child -> release both events
+ - first perf_event_detach_bpf_prog call will release tp_event->prog_array
+ and second perf_event_detach_bpf_prog will crash, because
+ tp_event->prog_array is NULL
+
+The fix makes sure the perf_event_detach_bpf_prog checks prog_array
+is valid before it tries to remove the bpf program from it.
+
+[1] https://lore.kernel.org/bpf/Z1MR6dCIKajNS6nU@krava/T/#m91dbf0688221ec7a7fc95e896a7ef9ff93b0b8ad
+
+Fixes: 0ee288e69d03 ("bpf,perf: Fix perf_event_detach_bpf_prog error handling")
+Reported-by: syzbot+2e0d2840414ce817aaac@syzkaller.appspotmail.com
+Signed-off-by: Jiri Olsa <jolsa@kernel.org>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20241208142507.1207698-1-jolsa@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/bpf_trace.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2180,6 +2180,9 @@ void perf_event_detach_bpf_prog(struct p
+ goto unlock;
+
+ old_array = bpf_event_rcu_dereference(event->tp_event->prog_array);
++ if (!old_array)
++ goto put;
++
+ ret = bpf_prog_array_copy(old_array, event->prog, NULL, 0, &new_array);
+ if (ret < 0) {
+ bpf_prog_array_delete_safe(old_array, event->prog);
+@@ -2188,6 +2191,7 @@ void perf_event_detach_bpf_prog(struct p
+ bpf_prog_array_free_sleepable(old_array);
+ }
+
++put:
+ /*
+ * It could be that the bpf_prog is not sleepable (and will be freed
+ * via normal RCU), but is called from a point that supports sleepable
--- /dev/null
+From 75e072a390da9a22e7ae4a4e8434dfca5da499fb Mon Sep 17 00:00:00 2001
+From: Michal Luczaj <mhal@rbox.co>
+Date: Mon, 2 Dec 2024 12:29:23 +0100
+Subject: bpf, sockmap: Fix update element with same
+
+From: Michal Luczaj <mhal@rbox.co>
+
+commit 75e072a390da9a22e7ae4a4e8434dfca5da499fb upstream.
+
+Consider a sockmap entry being updated with the same socket:
+
+ osk = stab->sks[idx];
+ sock_map_add_link(psock, link, map, &stab->sks[idx]);
+ stab->sks[idx] = sk;
+ if (osk)
+ sock_map_unref(osk, &stab->sks[idx]);
+
+Due to sock_map_unref(), which invokes sock_map_del_link(), all the
+psock's links for stab->sks[idx] are torn:
+
+ list_for_each_entry_safe(link, tmp, &psock->link, list) {
+ if (link->link_raw == link_raw) {
+ ...
+ list_del(&link->list);
+ sk_psock_free_link(link);
+ }
+ }
+
+And that includes the new link sock_map_add_link() added just before
+the unref.
+
+This results in a sockmap holding a socket, but without the respective
+link. This in turn means that close(sock) won't trigger the cleanup,
+i.e. a closed socket will not be automatically removed from the sockmap.
+
+Stop tearing the links when a matching link_raw is found.
+
+Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: John Fastabend <john.fastabend@gmail.com>
+Link: https://lore.kernel.org/bpf/20241202-sockmap-replace-v1-1-1e88579e7bd5@rbox.co
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/sock_map.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -158,6 +158,7 @@ static void sock_map_del_link(struct soc
+ verdict_stop = true;
+ list_del(&link->list);
+ sk_psock_free_link(link);
++ break;
+ }
+ }
+ spin_unlock_bh(&psock->link_lock);