Skip to content

Commit 748cd57

Browse files
Di ZhuAlexei Starovoitov
authored andcommitted
bpf: support BPF_PROG_QUERY for progs attached to sockmap
Right now there is no way to query whether BPF programs are attached to a sockmap or not. we can use the standard interface in libbpf to query, such as: bpf_prog_query(mapFd, BPF_SK_SKB_STREAM_PARSER, 0, NULL, ...); the mapFd is the fd of sockmap. Signed-off-by: Di Zhu <zhudi2@huawei.com> Acked-by: Yonghong Song <yhs@fb.com> Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com> Link: https://lore.kernel.org/r/20220119014005.1209-1-zhudi2@huawei.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 3f712d4 commit 748cd57

File tree

3 files changed

+84
-7
lines changed

3 files changed

+84
-7
lines changed

include/linux/bpf.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,9 @@ int bpf_prog_test_run_syscall(struct bpf_prog *prog,
20692069
int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog);
20702070
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);
20712071
int sock_map_update_elem_sys(struct bpf_map *map, void *key, void *value, u64 flags);
2072+
int sock_map_bpf_prog_query(const union bpf_attr *attr,
2073+
union bpf_attr __user *uattr);
2074+
20722075
void sock_map_unhash(struct sock *sk);
20732076
void sock_map_close(struct sock *sk, long timeout);
20742077
#else
@@ -2122,6 +2125,12 @@ static inline int sock_map_update_elem_sys(struct bpf_map *map, void *key, void
21222125
{
21232126
return -EOPNOTSUPP;
21242127
}
2128+
2129+
static inline int sock_map_bpf_prog_query(const union bpf_attr *attr,
2130+
union bpf_attr __user *uattr)
2131+
{
2132+
return -EINVAL;
2133+
}
21252134
#endif /* CONFIG_BPF_SYSCALL */
21262135
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */
21272136

kernel/bpf/syscall.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3318,6 +3318,11 @@ static int bpf_prog_query(const union bpf_attr *attr,
33183318
case BPF_FLOW_DISSECTOR:
33193319
case BPF_SK_LOOKUP:
33203320
return netns_bpf_prog_query(attr, uattr);
3321+
case BPF_SK_SKB_STREAM_PARSER:
3322+
case BPF_SK_SKB_STREAM_VERDICT:
3323+
case BPF_SK_MSG_VERDICT:
3324+
case BPF_SK_SKB_VERDICT:
3325+
return sock_map_bpf_prog_query(attr, uattr);
33213326
default:
33223327
return -EINVAL;
33233328
}

net/core/sock_map.c

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,45 +1416,108 @@ static struct sk_psock_progs *sock_map_progs(struct bpf_map *map)
14161416
return NULL;
14171417
}
14181418

1419-
static int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
1420-
struct bpf_prog *old, u32 which)
1419+
static int sock_map_prog_lookup(struct bpf_map *map, struct bpf_prog ***pprog,
1420+
u32 which)
14211421
{
14221422
struct sk_psock_progs *progs = sock_map_progs(map);
1423-
struct bpf_prog **pprog;
14241423

14251424
if (!progs)
14261425
return -EOPNOTSUPP;
14271426

14281427
switch (which) {
14291428
case BPF_SK_MSG_VERDICT:
1430-
pprog = &progs->msg_parser;
1429+
*pprog = &progs->msg_parser;
14311430
break;
14321431
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
14331432
case BPF_SK_SKB_STREAM_PARSER:
1434-
pprog = &progs->stream_parser;
1433+
*pprog = &progs->stream_parser;
14351434
break;
14361435
#endif
14371436
case BPF_SK_SKB_STREAM_VERDICT:
14381437
if (progs->skb_verdict)
14391438
return -EBUSY;
1440-
pprog = &progs->stream_verdict;
1439+
*pprog = &progs->stream_verdict;
14411440
break;
14421441
case BPF_SK_SKB_VERDICT:
14431442
if (progs->stream_verdict)
14441443
return -EBUSY;
1445-
pprog = &progs->skb_verdict;
1444+
*pprog = &progs->skb_verdict;
14461445
break;
14471446
default:
14481447
return -EOPNOTSUPP;
14491448
}
14501449

1450+
return 0;
1451+
}
1452+
1453+
static int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
1454+
struct bpf_prog *old, u32 which)
1455+
{
1456+
struct bpf_prog **pprog;
1457+
int ret;
1458+
1459+
ret = sock_map_prog_lookup(map, &pprog, which);
1460+
if (ret)
1461+
return ret;
1462+
14511463
if (old)
14521464
return psock_replace_prog(pprog, prog, old);
14531465

14541466
psock_set_prog(pprog, prog);
14551467
return 0;
14561468
}
14571469

1470+
int sock_map_bpf_prog_query(const union bpf_attr *attr,
1471+
union bpf_attr __user *uattr)
1472+
{
1473+
__u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
1474+
u32 prog_cnt = 0, flags = 0, ufd = attr->target_fd;
1475+
struct bpf_prog **pprog;
1476+
struct bpf_prog *prog;
1477+
struct bpf_map *map;
1478+
struct fd f;
1479+
u32 id = 0;
1480+
int ret;
1481+
1482+
if (attr->query.query_flags)
1483+
return -EINVAL;
1484+
1485+
f = fdget(ufd);
1486+
map = __bpf_map_get(f);
1487+
if (IS_ERR(map))
1488+
return PTR_ERR(map);
1489+
1490+
rcu_read_lock();
1491+
1492+
ret = sock_map_prog_lookup(map, &pprog, attr->query.attach_type);
1493+
if (ret)
1494+
goto end;
1495+
1496+
prog = *pprog;
1497+
prog_cnt = !prog ? 0 : 1;
1498+
1499+
if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
1500+
goto end;
1501+
1502+
/* we do not hold the refcnt, the bpf prog may be released
1503+
* asynchronously and the id would be set to 0.
1504+
*/
1505+
id = data_race(prog->aux->id);
1506+
if (id == 0)
1507+
prog_cnt = 0;
1508+
1509+
end:
1510+
rcu_read_unlock();
1511+
1512+
if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)) ||
1513+
(id != 0 && copy_to_user(prog_ids, &id, sizeof(u32))) ||
1514+
copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
1515+
ret = -EFAULT;
1516+
1517+
fdput(f);
1518+
return ret;
1519+
}
1520+
14581521
static void sock_map_unlink(struct sock *sk, struct sk_psock_link *link)
14591522
{
14601523
switch (link->map->map_type) {

0 commit comments

Comments
 (0)