Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc9a2002 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bpf-cgroup2'



Martin KaFai Lau says:

====================
cgroup: bpf: cgroup2 membership test on skb

This series is to implement a bpf-way to
check the cgroup2 membership of a skb (sk_buff).

It is similar to the feature added in netfilter:
c38c4597 ("netfilter: implement xt_cgroup cgroup2 path match")

The current target is the tc-like usage.

v3:
- Remove WARN_ON_ONCE(!rcu_read_lock_held())
- Stop BPF_MAP_TYPE_CGROUP_ARRAY usage in patch 2/4
- Avoid mounting bpf fs manually in patch 4/4

- Thanks for Daniel's review and the above suggestions

- Check CONFIG_SOCK_CGROUP_DATA instead of CONFIG_CGROUPS.  Thanks to
  the kbuild bot's report.
  Patch 2/4 only needs CONFIG_CGROUPS while patch 3/4 needs
  CONFIG_SOCK_CGROUP_DATA.  Since a single bpf cgrp2 array alone is
  not useful for now, CONFIG_SOCK_CGROUP_DATA is also used in
  patch 2/4.  We can fine tune it later if we find other use cases
  for the cgrp2 array.
- Return EAGAIN instead of ENOENT if the cgrp2 array entry is
  NULL.  It is to distinguish these two cases: 1) the userland has
  not populated this array entry yet. or 2) not finding cgrp2 from the skb.

- Be-lated thanks to Alexei and Tejun on reviewing v1 and giving advice on
  this work.

v2:
- Fix two return cases in cgroup_get_from_fd()
- Fix compilation errors when CONFIG_CGROUPS is not used:
  - arraymap.c: avoid registering BPF_MAP_TYPE_CGROUP_ARRAY
  - filter.c: tc_cls_act_func_proto() returns NULL on BPF_FUNC_skb_in_cgroup
- Add comments to BPF_FUNC_skb_in_cgroup and cgroup_get_from_fd()
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6bd3847b a3f74617
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
						       struct cgroup_subsys *ss);

struct cgroup *cgroup_get_from_path(const char *path);
struct cgroup *cgroup_get_from_fd(int fd);

int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
+12 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ enum bpf_map_type {
	BPF_MAP_TYPE_PERCPU_HASH,
	BPF_MAP_TYPE_PERCPU_ARRAY,
	BPF_MAP_TYPE_STACK_TRACE,
	BPF_MAP_TYPE_CGROUP_ARRAY,
};

enum bpf_prog_type {
@@ -336,6 +337,17 @@ enum bpf_func_id {
	 */
	BPF_FUNC_skb_change_type,

	/**
	 * bpf_skb_in_cgroup(skb, map, index) - Check cgroup2 membership of skb
	 * @skb: pointer to skb
	 * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
	 * @index: index of the cgroup in the bpf_map
	 * Return:
	 *   == 0 skb failed the cgroup2 descendant test
	 *   == 1 skb succeeded the cgroup2 descendant test
	 *    < 0 error
	 */
	BPF_FUNC_skb_in_cgroup,
	__BPF_FUNC_MAX_ID,
};

+43 −0
Original line number Diff line number Diff line
@@ -537,3 +537,46 @@ static int __init register_perf_event_array_map(void)
	return 0;
}
late_initcall(register_perf_event_array_map);

#ifdef CONFIG_SOCK_CGROUP_DATA
static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
				     struct file *map_file /* not used */,
				     int fd)
{
	return cgroup_get_from_fd(fd);
}

static void cgroup_fd_array_put_ptr(void *ptr)
{
	/* cgroup_put free cgrp after a rcu grace period */
	cgroup_put(ptr);
}

static void cgroup_fd_array_free(struct bpf_map *map)
{
	bpf_fd_array_map_clear(map);
	fd_array_map_free(map);
}

static const struct bpf_map_ops cgroup_array_ops = {
	.map_alloc = fd_array_map_alloc,
	.map_free = cgroup_fd_array_free,
	.map_get_next_key = array_map_get_next_key,
	.map_lookup_elem = fd_array_map_lookup_elem,
	.map_delete_elem = fd_array_map_delete_elem,
	.map_fd_get_ptr = cgroup_fd_array_get_ptr,
	.map_fd_put_ptr = cgroup_fd_array_put_ptr,
};

static struct bpf_map_type_list cgroup_array_type __read_mostly = {
	.ops = &cgroup_array_ops,
	.type = BPF_MAP_TYPE_CGROUP_ARRAY,
};

static int __init register_cgroup_array_map(void)
{
	bpf_register_map_type(&cgroup_array_type);
	return 0;
}
late_initcall(register_cgroup_array_map);
#endif
+2 −1
Original line number Diff line number Diff line
@@ -393,7 +393,8 @@ static int map_update_elem(union bpf_attr *attr)
	} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
		err = bpf_percpu_array_update(map, key, value, attr->flags);
	} else if (map->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
		   map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
		   map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||
		   map->map_type == BPF_MAP_TYPE_CGROUP_ARRAY) {
		rcu_read_lock();
		err = bpf_fd_array_map_update_elem(map, f.file, key, value,
						   attr->flags);
+8 −0
Original line number Diff line number Diff line
@@ -1035,6 +1035,10 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
		if (func_id != BPF_FUNC_get_stackid)
			goto error;
		break;
	case BPF_MAP_TYPE_CGROUP_ARRAY:
		if (func_id != BPF_FUNC_skb_in_cgroup)
			goto error;
		break;
	default:
		break;
	}
@@ -1054,6 +1058,10 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
		if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
			goto error;
		break;
	case BPF_FUNC_skb_in_cgroup:
		if (map->map_type != BPF_MAP_TYPE_CGROUP_ARRAY)
			goto error;
		break;
	default:
		break;
	}
Loading