Skip to content

Commit 53b25cd

Browse files
4astSomasundaram Krishnasamy
authored andcommitted
bpf: introduce BPF_PROG_QUERY command
introduce BPF_PROG_QUERY command to retrieve a set of either attached programs to given cgroup or a set of effective programs that will execute for events within a cgroup Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> for cgroup bits Acked-by: Tejun Heo <[email protected]> Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit 468e2f6) Orabug: 31667601 Signed-off-by: Alan Maguire <[email protected]> Reviewed-by: Mark Haywood <[email protected]> Conflicts: include/uapi/linux/bpf.h context issues in bpf.h, and needed KABI wrapping for anonymous struct used for queries. Signed-off-by: Somasundaram Krishnasamy <[email protected]>
1 parent 7ecc66b commit 53b25cd

File tree

7 files changed

+152
-0
lines changed

7 files changed

+152
-0
lines changed

include/linux/bpf-cgroup.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
4646
enum bpf_attach_type type, u32 flags);
4747
int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
4848
enum bpf_attach_type type, u32 flags);
49+
int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
50+
union bpf_attr __user *uattr);
4951

5052
/* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */
5153
int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
5254
enum bpf_attach_type type, u32 flags);
5355
int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
5456
enum bpf_attach_type type, u32 flags);
57+
int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
58+
union bpf_attr __user *uattr);
5559

5660
int __cgroup_bpf_run_filter_skb(struct sock *sk,
5761
struct sk_buff *skb,

include/linux/bpf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ struct bpf_prog_array {
269269

270270
struct bpf_prog_array __rcu *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags);
271271
void bpf_prog_array_free(struct bpf_prog_array __rcu *progs);
272+
int bpf_prog_array_length(struct bpf_prog_array __rcu *progs);
273+
int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
274+
__u32 __user *prog_ids, u32 cnt);
272275

273276
#define BPF_PROG_RUN_ARRAY(array, ctx, func) \
274277
({ \

include/uapi/linux/bpf.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ enum bpf_cmd {
9393
BPF_PROG_GET_FD_BY_ID,
9494
BPF_MAP_GET_FD_BY_ID,
9595
BPF_OBJ_GET_INFO_BY_FD,
96+
BPF_PROG_QUERY,
9697
};
9798

9899
enum bpf_map_type {
@@ -212,6 +213,11 @@ enum bpf_attach_type {
212213
/* Specify numa node during map creation */
213214
#define BPF_F_NUMA_NODE (1U << 2)
214215

216+
/* flags for BPF_PROG_QUERY */
217+
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
218+
219+
#define BPF_OBJ_NAME_LEN 16U
220+
215221
union bpf_attr {
216222
struct { /* anonymous struct used by BPF_MAP_CREATE command */
217223
__u32 map_type; /* one of enum bpf_map_type */
@@ -289,6 +295,17 @@ union bpf_attr {
289295
__u32 info_len;
290296
__aligned_u64 info;
291297
} info;
298+
299+
#ifndef __GENKSYMS__
300+
struct { /* anonymous struct used by BPF_PROG_QUERY command */
301+
__u32 target_fd; /* container object to query */
302+
__u32 attach_type;
303+
__u32 query_flags;
304+
__u32 attach_flags;
305+
__aligned_u64 prog_ids;
306+
__u32 prog_cnt;
307+
} query;
308+
#endif
292309
} __attribute__((aligned(8)));
293310

294311
/* BPF helper function descriptions:

kernel/bpf/cgroup.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,52 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
384384
return err;
385385
}
386386

387+
/* Must be called with cgroup_mutex held to avoid races. */
388+
int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
389+
union bpf_attr __user *uattr)
390+
{
391+
__u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
392+
enum bpf_attach_type type = attr->query.attach_type;
393+
struct list_head *progs = &cgrp->bpf.progs[type];
394+
u32 flags = cgrp->bpf.flags[type];
395+
int cnt, ret = 0, i;
396+
397+
if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE)
398+
cnt = bpf_prog_array_length(cgrp->bpf.effective[type]);
399+
else
400+
cnt = prog_list_length(progs);
401+
402+
if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
403+
return -EFAULT;
404+
if (copy_to_user(&uattr->query.prog_cnt, &cnt, sizeof(cnt)))
405+
return -EFAULT;
406+
if (attr->query.prog_cnt == 0 || !prog_ids || !cnt)
407+
/* return early if user requested only program count + flags */
408+
return 0;
409+
if (attr->query.prog_cnt < cnt) {
410+
cnt = attr->query.prog_cnt;
411+
ret = -ENOSPC;
412+
}
413+
414+
if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE) {
415+
return bpf_prog_array_copy_to_user(cgrp->bpf.effective[type],
416+
prog_ids, cnt);
417+
} else {
418+
struct bpf_prog_list *pl;
419+
u32 id;
420+
421+
i = 0;
422+
list_for_each_entry(pl, progs, node) {
423+
id = pl->prog->aux->id;
424+
if (copy_to_user(prog_ids + i, &id, sizeof(id)))
425+
return -EFAULT;
426+
if (++i == cnt)
427+
break;
428+
}
429+
}
430+
return ret;
431+
}
432+
387433
/**
388434
* __cgroup_bpf_run_filter_skb() - Run a program for packet filtering
389435
* @sk: The socket sending or receiving traffic

kernel/bpf/core.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,44 @@ void bpf_prog_array_free(struct bpf_prog_array __rcu *progs)
15031503
kfree_rcu(progs, rcu);
15041504
}
15051505

1506+
int bpf_prog_array_length(struct bpf_prog_array __rcu *progs)
1507+
{
1508+
struct bpf_prog **prog;
1509+
u32 cnt = 0;
1510+
1511+
rcu_read_lock();
1512+
prog = rcu_dereference(progs)->progs;
1513+
for (; *prog; prog++)
1514+
cnt++;
1515+
rcu_read_unlock();
1516+
return cnt;
1517+
}
1518+
1519+
int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
1520+
__u32 __user *prog_ids, u32 cnt)
1521+
{
1522+
struct bpf_prog **prog;
1523+
u32 i = 0, id;
1524+
1525+
rcu_read_lock();
1526+
prog = rcu_dereference(progs)->progs;
1527+
for (; *prog; prog++) {
1528+
id = (*prog)->aux->id;
1529+
if (copy_to_user(prog_ids + i, &id, sizeof(id))) {
1530+
rcu_read_unlock();
1531+
return -EFAULT;
1532+
}
1533+
if (++i == cnt) {
1534+
prog++;
1535+
break;
1536+
}
1537+
}
1538+
rcu_read_unlock();
1539+
if (*prog)
1540+
return -ENOSPC;
1541+
return 0;
1542+
}
1543+
15061544
static void bpf_prog_free_deferred(struct work_struct *work)
15071545
{
15081546
struct bpf_prog_aux *aux;

kernel/bpf/syscall.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,37 @@ static int bpf_prog_detach(const union bpf_attr *attr)
12551255
return ret;
12561256
}
12571257

1258+
#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
1259+
1260+
static int bpf_prog_query(const union bpf_attr *attr,
1261+
union bpf_attr __user *uattr)
1262+
{
1263+
struct cgroup *cgrp;
1264+
int ret;
1265+
1266+
if (!capable(CAP_NET_ADMIN))
1267+
return -EPERM;
1268+
if (CHECK_ATTR(BPF_PROG_QUERY))
1269+
return -EINVAL;
1270+
if (attr->query.query_flags & ~BPF_F_QUERY_EFFECTIVE)
1271+
return -EINVAL;
1272+
1273+
switch (attr->query.attach_type) {
1274+
case BPF_CGROUP_INET_INGRESS:
1275+
case BPF_CGROUP_INET_EGRESS:
1276+
case BPF_CGROUP_INET_SOCK_CREATE:
1277+
case BPF_CGROUP_SOCK_OPS:
1278+
break;
1279+
default:
1280+
return -EINVAL;
1281+
}
1282+
cgrp = cgroup_get_from_fd(attr->query.target_fd);
1283+
if (IS_ERR(cgrp))
1284+
return PTR_ERR(cgrp);
1285+
ret = cgroup_bpf_query(cgrp, attr, uattr);
1286+
cgroup_put(cgrp);
1287+
return ret;
1288+
}
12581289
#endif /* CONFIG_CGROUP_BPF */
12591290

12601291
#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration
@@ -1539,6 +1570,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
15391570
case BPF_PROG_DETACH:
15401571
err = bpf_prog_detach(&attr);
15411572
break;
1573+
case BPF_PROG_QUERY:
1574+
err = bpf_prog_query(&attr, uattr);
1575+
break;
15421576
#endif
15431577
case BPF_PROG_TEST_RUN:
15441578
err = bpf_prog_test_run(&attr, uattr);

kernel/cgroup/cgroup.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6009,6 +6009,16 @@ int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
60096009
mutex_unlock(&cgroup_mutex);
60106010
return ret;
60116011
}
6012+
int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
6013+
union bpf_attr __user *uattr)
6014+
{
6015+
int ret;
6016+
6017+
mutex_lock(&cgroup_mutex);
6018+
ret = __cgroup_bpf_query(cgrp, attr, uattr);
6019+
mutex_unlock(&cgroup_mutex);
6020+
return ret;
6021+
}
60126022
#endif /* CONFIG_CGROUP_BPF */
60136023

60146024
#ifdef CONFIG_SYSFS

0 commit comments

Comments
 (0)