--- /dev/null
+From bb0de3131f4c60a9bf976681e0fe4d1e55c7a821 Mon Sep 17 00:00:00 2001
+From: Lorenz Bauer <lmb@cloudflare.com>
+Date: Mon, 29 Jun 2020 10:56:28 +0100
+Subject: bpf: sockmap: Require attach_bpf_fd when detaching a program
+
+From: Lorenz Bauer <lmb@cloudflare.com>
+
+commit bb0de3131f4c60a9bf976681e0fe4d1e55c7a821 upstream.
+
+The sockmap code currently ignores the value of attach_bpf_fd when
+detaching a program. This is contrary to the usual behaviour of
+checking that attach_bpf_fd represents the currently attached
+program.
+
+Ensure that attach_bpf_fd is indeed the currently attached
+program. It turns out that all sockmap selftests already do this,
+which indicates that this is unlikely to cause breakage.
+
+Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
+Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Link: https://lore.kernel.org/bpf/20200629095630.7933-5-lmb@cloudflare.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/bpf.h | 13 +++++++++++--
+ include/linux/skmsg.h | 13 +++++++++++++
+ kernel/bpf/syscall.c | 4 ++--
+ net/core/sock_map.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
+ 4 files changed, 71 insertions(+), 9 deletions(-)
+
+--- a/include/linux/bpf.h
++++ b/include/linux/bpf.h
+@@ -956,11 +956,14 @@ static inline void bpf_map_offload_map_f
+ #endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
+
+ #if defined(CONFIG_BPF_STREAM_PARSER)
+-int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which);
++int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
++ struct bpf_prog *old, u32 which);
+ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
++int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
+ #else
+ static inline int sock_map_prog_update(struct bpf_map *map,
+- struct bpf_prog *prog, u32 which)
++ struct bpf_prog *prog,
++ struct bpf_prog *old, u32 which)
+ {
+ return -EOPNOTSUPP;
+ }
+@@ -970,6 +973,12 @@ static inline int sock_map_get_from_fd(c
+ {
+ return -EINVAL;
+ }
++
++static inline int sock_map_prog_detach(const union bpf_attr *attr,
++ enum bpf_prog_type ptype)
++{
++ return -EOPNOTSUPP;
++}
+ #endif
+
+ #if defined(CONFIG_XDP_SOCKETS)
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -450,6 +450,19 @@ static inline void psock_set_prog(struct
+ bpf_prog_put(prog);
+ }
+
++static inline int psock_replace_prog(struct bpf_prog **pprog,
++ struct bpf_prog *prog,
++ struct bpf_prog *old)
++{
++ if (cmpxchg(pprog, old, prog) != old)
++ return -ENOENT;
++
++ if (old)
++ bpf_prog_put(old);
++
++ return 0;
++}
++
+ static inline void psock_progs_drop(struct sk_psock_progs *progs)
+ {
+ psock_set_prog(&progs->msg_parser, NULL);
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -2029,10 +2029,10 @@ static int bpf_prog_detach(const union b
+ ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
+ break;
+ case BPF_SK_MSG_VERDICT:
+- return sock_map_get_from_fd(attr, NULL);
++ return sock_map_prog_detach(attr, BPF_PROG_TYPE_SK_MSG);
+ case BPF_SK_SKB_STREAM_PARSER:
+ case BPF_SK_SKB_STREAM_VERDICT:
+- return sock_map_get_from_fd(attr, NULL);
++ return sock_map_prog_detach(attr, BPF_PROG_TYPE_SK_SKB);
+ case BPF_LIRC_MODE2:
+ return lirc_prog_detach(attr);
+ case BPF_FLOW_DISSECTOR:
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -71,7 +71,42 @@ int sock_map_get_from_fd(const union bpf
+ map = __bpf_map_get(f);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+- ret = sock_map_prog_update(map, prog, attr->attach_type);
++ ret = sock_map_prog_update(map, prog, NULL, attr->attach_type);
++ fdput(f);
++ return ret;
++}
++
++int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
++{
++ u32 ufd = attr->target_fd;
++ struct bpf_prog *prog;
++ struct bpf_map *map;
++ struct fd f;
++ int ret;
++
++ if (attr->attach_flags)
++ return -EINVAL;
++
++ f = fdget(ufd);
++ map = __bpf_map_get(f);
++ if (IS_ERR(map))
++ return PTR_ERR(map);
++
++ prog = bpf_prog_get(attr->attach_bpf_fd);
++ if (IS_ERR(prog)) {
++ ret = PTR_ERR(prog);
++ goto put_map;
++ }
++
++ if (prog->type != ptype) {
++ ret = -EINVAL;
++ goto put_prog;
++ }
++
++ ret = sock_map_prog_update(map, NULL, prog, attr->attach_type);
++put_prog:
++ bpf_prog_put(prog);
++put_map:
+ fdput(f);
+ return ret;
+ }
+@@ -1015,27 +1050,32 @@ static struct sk_psock_progs *sock_map_p
+ }
+
+ int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
+- u32 which)
++ struct bpf_prog *old, u32 which)
+ {
+ struct sk_psock_progs *progs = sock_map_progs(map);
++ struct bpf_prog **pprog;
+
+ if (!progs)
+ return -EOPNOTSUPP;
+
+ switch (which) {
+ case BPF_SK_MSG_VERDICT:
+- psock_set_prog(&progs->msg_parser, prog);
++ pprog = &progs->msg_parser;
+ break;
+ case BPF_SK_SKB_STREAM_PARSER:
+- psock_set_prog(&progs->skb_parser, prog);
++ pprog = &progs->skb_parser;
+ break;
+ case BPF_SK_SKB_STREAM_VERDICT:
+- psock_set_prog(&progs->skb_verdict, prog);
++ pprog = &progs->skb_verdict;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
++ if (old)
++ return psock_replace_prog(pprog, prog, old);
++
++ psock_set_prog(pprog, prog);
+ return 0;
+ }
+
--- /dev/null
+From f43cb0d672aa8eb09bfdb779de5900c040487d1d Mon Sep 17 00:00:00 2001
+From: Lorenz Bauer <lmb@cloudflare.com>
+Date: Thu, 9 Jul 2020 12:51:51 +0100
+Subject: selftests: bpf: Fix detach from sockmap tests
+
+From: Lorenz Bauer <lmb@cloudflare.com>
+
+commit f43cb0d672aa8eb09bfdb779de5900c040487d1d upstream.
+
+Fix sockmap tests which rely on old bpf_prog_dispatch behaviour.
+In the first case, the tests check that detaching without giving
+a program succeeds. Since these are not the desired semantics,
+invert the condition. In the second case, the clean up code doesn't
+supply the necessary program fds.
+
+Fixes: bb0de3131f4c ("bpf: sockmap: Require attach_bpf_fd when detaching a program")
+Reported-by: Martin KaFai Lau <kafai@fb.com>
+Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
+Link: https://lore.kernel.org/bpf/20200709115151.75829-1-lmb@cloudflare.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/testing/selftests/bpf/test_maps.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/tools/testing/selftests/bpf/test_maps.c
++++ b/tools/testing/selftests/bpf/test_maps.c
+@@ -793,19 +793,19 @@ static void test_sockmap(unsigned int ta
+ }
+
+ err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
+- if (err) {
++ if (!err) {
+ printf("Failed empty parser prog detach\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
+- if (err) {
++ if (!err) {
+ printf("Failed empty verdict prog detach\n");
+ goto out_sockmap;
+ }
+
+ err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
+- if (err) {
++ if (!err) {
+ printf("Failed empty msg verdict prog detach\n");
+ goto out_sockmap;
+ }
+@@ -1094,19 +1094,19 @@ static void test_sockmap(unsigned int ta
+ assert(status == 0);
+ }
+
+- err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
++ err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
+ if (!err) {
+ printf("Detached an invalid prog type.\n");
+ goto out_sockmap;
+ }
+
+- err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
++ err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
+ if (err) {
+ printf("Failed parser prog detach\n");
+ goto out_sockmap;
+ }
+
+- err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
++ err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
+ if (err) {
+ printf("Failed parser prog detach\n");
+ goto out_sockmap;