Skip to content

Commit 1b751c7

Browse files
lmbgregkh
authored andcommitted
bpf: sockmap: Require attach_bpf_fd when detaching a program
commit bb0de31 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: 604326b ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Lorenz Bauer <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 121b45b commit 1b751c7

4 files changed

Lines changed: 70 additions & 8 deletions

File tree

include/linux/bpf.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,13 +1444,16 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
14441444
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
14451445

14461446
#if defined(CONFIG_BPF_STREAM_PARSER)
1447-
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, u32 which);
1447+
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
1448+
struct bpf_prog *old, u32 which);
14481449
int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
1450+
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
14491451
void sock_map_unhash(struct sock *sk);
14501452
void sock_map_close(struct sock *sk, long timeout);
14511453
#else
14521454
static inline int sock_map_prog_update(struct bpf_map *map,
1453-
struct bpf_prog *prog, u32 which)
1455+
struct bpf_prog *prog,
1456+
struct bpf_prog *old, u32 which)
14541457
{
14551458
return -EOPNOTSUPP;
14561459
}
@@ -1460,6 +1463,12 @@ static inline int sock_map_get_from_fd(const union bpf_attr *attr,
14601463
{
14611464
return -EINVAL;
14621465
}
1466+
1467+
static inline int sock_map_prog_detach(const union bpf_attr *attr,
1468+
enum bpf_prog_type ptype)
1469+
{
1470+
return -EOPNOTSUPP;
1471+
}
14631472
#endif /* CONFIG_BPF_STREAM_PARSER */
14641473

14651474
#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL)

include/linux/skmsg.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,19 @@ static inline void psock_set_prog(struct bpf_prog **pprog,
430430
bpf_prog_put(prog);
431431
}
432432

433+
static inline int psock_replace_prog(struct bpf_prog **pprog,
434+
struct bpf_prog *prog,
435+
struct bpf_prog *old)
436+
{
437+
if (cmpxchg(pprog, old, prog) != old)
438+
return -ENOENT;
439+
440+
if (old)
441+
bpf_prog_put(old);
442+
443+
return 0;
444+
}
445+
433446
static inline void psock_progs_drop(struct sk_psock_progs *progs)
434447
{
435448
psock_set_prog(&progs->msg_parser, NULL);

kernel/bpf/syscall.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2695,7 +2695,7 @@ static int bpf_prog_detach(const union bpf_attr *attr)
26952695
switch (ptype) {
26962696
case BPF_PROG_TYPE_SK_MSG:
26972697
case BPF_PROG_TYPE_SK_SKB:
2698-
return sock_map_get_from_fd(attr, NULL);
2698+
return sock_map_prog_detach(attr, ptype);
26992699
case BPF_PROG_TYPE_LIRC_MODE2:
27002700
return lirc_prog_detach(attr);
27012701
case BPF_PROG_TYPE_FLOW_DISSECTOR:

net/core/sock_map.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,42 @@ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog)
7777
map = __bpf_map_get(f);
7878
if (IS_ERR(map))
7979
return PTR_ERR(map);
80-
ret = sock_map_prog_update(map, prog, attr->attach_type);
80+
ret = sock_map_prog_update(map, prog, NULL, attr->attach_type);
81+
fdput(f);
82+
return ret;
83+
}
84+
85+
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
86+
{
87+
u32 ufd = attr->target_fd;
88+
struct bpf_prog *prog;
89+
struct bpf_map *map;
90+
struct fd f;
91+
int ret;
92+
93+
if (attr->attach_flags || attr->replace_bpf_fd)
94+
return -EINVAL;
95+
96+
f = fdget(ufd);
97+
map = __bpf_map_get(f);
98+
if (IS_ERR(map))
99+
return PTR_ERR(map);
100+
101+
prog = bpf_prog_get(attr->attach_bpf_fd);
102+
if (IS_ERR(prog)) {
103+
ret = PTR_ERR(prog);
104+
goto put_map;
105+
}
106+
107+
if (prog->type != ptype) {
108+
ret = -EINVAL;
109+
goto put_prog;
110+
}
111+
112+
ret = sock_map_prog_update(map, NULL, prog, attr->attach_type);
113+
put_prog:
114+
bpf_prog_put(prog);
115+
put_map:
81116
fdput(f);
82117
return ret;
83118
}
@@ -1192,27 +1227,32 @@ static struct sk_psock_progs *sock_map_progs(struct bpf_map *map)
11921227
}
11931228

11941229
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
1195-
u32 which)
1230+
struct bpf_prog *old, u32 which)
11961231
{
11971232
struct sk_psock_progs *progs = sock_map_progs(map);
1233+
struct bpf_prog **pprog;
11981234

11991235
if (!progs)
12001236
return -EOPNOTSUPP;
12011237

12021238
switch (which) {
12031239
case BPF_SK_MSG_VERDICT:
1204-
psock_set_prog(&progs->msg_parser, prog);
1240+
pprog = &progs->msg_parser;
12051241
break;
12061242
case BPF_SK_SKB_STREAM_PARSER:
1207-
psock_set_prog(&progs->skb_parser, prog);
1243+
pprog = &progs->skb_parser;
12081244
break;
12091245
case BPF_SK_SKB_STREAM_VERDICT:
1210-
psock_set_prog(&progs->skb_verdict, prog);
1246+
pprog = &progs->skb_verdict;
12111247
break;
12121248
default:
12131249
return -EOPNOTSUPP;
12141250
}
12151251

1252+
if (old)
1253+
return psock_replace_prog(pprog, prog, old);
1254+
1255+
psock_set_prog(pprog, prog);
12161256
return 0;
12171257
}
12181258

0 commit comments

Comments
 (0)