diff mbox

[-next,3/4] cgroup: bpf: Add bpf_skb_in_cgroup_proto

Message ID 1466555002-1316296-4-git-send-email-kafai@fb.com
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Martin KaFai Lau June 22, 2016, 12:23 a.m. UTC
Adds a bpf helper, bpf_skb_in_cgroup, to decide if a skb->sk
belongs to a descendant of a cgroup2.  It is similar to the
feature added in netfilter:
commit c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match")

The user is expected to populate a BPF_MAP_TYPE_CGROUP_ARRAY
which will be used by the bpf_skb_in_cgroup.

Modifications to the bpf verifier is to ensure BPF_MAP_TYPE_CGROUP_ARRAY
and bpf_skb_in_cgroup() are always used together.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Tejun Heo <tj@kernel.org>
---
 include/uapi/linux/bpf.h |  1 +
 kernel/bpf/verifier.c    |  8 ++++++++
 net/core/filter.c        | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+)

Comments

Alexei Starovoitov June 22, 2016, 1:15 a.m. UTC | #1
On Tue, Jun 21, 2016 at 05:23:21PM -0700, Martin KaFai Lau wrote:
> Adds a bpf helper, bpf_skb_in_cgroup, to decide if a skb->sk
> belongs to a descendant of a cgroup2.  It is similar to the
> feature added in netfilter:
> commit c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match")
> 
> The user is expected to populate a BPF_MAP_TYPE_CGROUP_ARRAY
> which will be used by the bpf_skb_in_cgroup.
> 
> Modifications to the bpf verifier is to ensure BPF_MAP_TYPE_CGROUP_ARRAY
> and bpf_skb_in_cgroup() are always used together.
> 
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> Cc: Alexei Starovoitov <ast@fb.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Tejun Heo <tj@kernel.org>
> ---
>  include/uapi/linux/bpf.h |  1 +
>  kernel/bpf/verifier.c    |  8 ++++++++
>  net/core/filter.c        | 36 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 45 insertions(+)
> 
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index ef4e386..a91714bd 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -314,6 +314,7 @@ enum bpf_func_id {
>  	 */
>  	BPF_FUNC_skb_get_tunnel_opt,
>  	BPF_FUNC_skb_set_tunnel_opt,
> +	BPF_FUNC_skb_in_cgroup,
...
> +static u64 bpf_skb_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +{
...
> +	if (unlikely(!cgrp))
> +		return -ENOENT;
> +
> +	return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);

if you'd need to respin the patch for other reasons please add kdoc
to bpf.h for this new helper similar to other helpers.
To say that 0 or 1 return values is indication of cg2 descendant relation
and < 0 in case of error.

Acked-by: Alexei Starovoitov <ast@kernel.org>
kernel test robot June 22, 2016, 1:25 a.m. UTC | #2
Hi,

[auto build test ERROR on next-20160621]

url:    https://github.com/0day-ci/linux/commits/Martin-KaFai-Lau/cgroup-bpf-cgroup2-membership-test-on-skb/20160622-082800
config: i386-randconfig-s1-201625 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   net/core/filter.c: In function 'bpf_skb_in_cgroup':
>> net/core/filter.c:2049:30: error: implicit declaration of function 'sock_cgroup_ptr' [-Werror=implicit-function-declaration]
     return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
                                 ^~~~~~~~~~~~~~~
>> net/core/filter.c:2049:30: warning: passing argument 1 of 'cgroup_is_descendant' makes pointer from integer without a cast [-Wint-conversion]
   In file included from include/net/netprio_cgroup.h:17:0,
                    from include/linux/netdevice.h:48,
                    from net/core/filter.c:31:
   include/linux/cgroup.h:492:20: note: expected 'struct cgroup *' but argument is of type 'int'
    static inline bool cgroup_is_descendant(struct cgroup *cgrp,
                       ^~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/sock_cgroup_ptr +2049 net/core/filter.c

  2043			return -E2BIG;
  2044	
  2045		cgrp = READ_ONCE(array->ptrs[i]);
  2046		if (unlikely(!cgrp))
  2047			return -ENOENT;
  2048	
> 2049		return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
  2050	}
  2051	
  2052	static const struct bpf_func_proto bpf_skb_in_cgroup_proto = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot June 22, 2016, 2:15 a.m. UTC | #3
Hi,

[auto build test ERROR on next-20160621]

url:    https://github.com/0day-ci/linux/commits/Martin-KaFai-Lau/cgroup-bpf-cgroup2-membership-test-on-skb/20160622-082800
config: sh-titan_defconfig (attached as .config)
compiler: sh4-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sh 

All errors (new ones prefixed by >>):

   net/core/filter.c: In function 'bpf_skb_in_cgroup':
>> net/core/filter.c:2049:9: error: implicit declaration of function 'cgroup_is_descendant' [-Werror=implicit-function-declaration]
     return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
            ^
   net/core/filter.c:2049:30: error: implicit declaration of function 'sock_cgroup_ptr' [-Werror=implicit-function-declaration]
     return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
                                 ^
   cc1: some warnings being treated as errors

vim +/cgroup_is_descendant +2049 net/core/filter.c

  2043			return -E2BIG;
  2044	
  2045		cgrp = READ_ONCE(array->ptrs[i]);
  2046		if (unlikely(!cgrp))
  2047			return -ENOENT;
  2048	
> 2049		return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
  2050	}
  2051	
  2052	static const struct bpf_func_proto bpf_skb_in_cgroup_proto = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Martin KaFai Lau June 22, 2016, 6:19 a.m. UTC | #4
On Tue, Jun 21, 2016 at 06:15:13PM -0700, Alexei Starovoitov wrote:
> On Tue, Jun 21, 2016 at 05:23:21PM -0700, Martin KaFai Lau wrote:
> > Adds a bpf helper, bpf_skb_in_cgroup, to decide if a skb->sk
> > belongs to a descendant of a cgroup2.  It is similar to the
> > feature added in netfilter:
> > commit c38c4597e4bf ("netfilter: implement xt_cgroup cgroup2 path match")
> >
> > The user is expected to populate a BPF_MAP_TYPE_CGROUP_ARRAY
> > which will be used by the bpf_skb_in_cgroup.
> >
> > Modifications to the bpf verifier is to ensure BPF_MAP_TYPE_CGROUP_ARRAY
> > and bpf_skb_in_cgroup() are always used together.
> >
> > Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> > Cc: Alexei Starovoitov <ast@fb.com>
> > Cc: Daniel Borkmann <daniel@iogearbox.net>
> > Cc: Tejun Heo <tj@kernel.org>
> > ---
> >  include/uapi/linux/bpf.h |  1 +
> >  kernel/bpf/verifier.c    |  8 ++++++++
> >  net/core/filter.c        | 36 ++++++++++++++++++++++++++++++++++++
> >  3 files changed, 45 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index ef4e386..a91714bd 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -314,6 +314,7 @@ enum bpf_func_id {
> >  	 */
> >  	BPF_FUNC_skb_get_tunnel_opt,
> >  	BPF_FUNC_skb_set_tunnel_opt,
> > +	BPF_FUNC_skb_in_cgroup,
> ...
> > +static u64 bpf_skb_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> > +{
> ...
> > +	if (unlikely(!cgrp))
> > +		return -ENOENT;
> > +
> > +	return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
>
> if you'd need to respin the patch for other reasons please add kdoc
> to bpf.h for this new helper similar to other helpers.
> To say that 0 or 1 return values is indication of cg2 descendant relation
> and < 0 in case of error.
Will do.

I will also address the '#ifndef CONFIG_CGROUPS' case in v2, as reported
by the kbuild test.
diff mbox

Patch

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index ef4e386..a91714bd 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -314,6 +314,7 @@  enum bpf_func_id {
 	 */
 	BPF_FUNC_skb_get_tunnel_opt,
 	BPF_FUNC_skb_set_tunnel_opt,
+	BPF_FUNC_skb_in_cgroup,
 	__BPF_FUNC_MAX_ID,
 };
 
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 668e079..68753e0 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1062,6 +1062,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;
 	}
@@ -1081,6 +1085,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;
 	}
diff --git a/net/core/filter.c b/net/core/filter.c
index df6860c..410da89 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2024,6 +2024,40 @@  bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
 	}
 }
 
+static u64 bpf_skb_in_cgroup(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
+{
+	struct sk_buff *skb = (struct sk_buff *)(long)r1;
+	struct bpf_map *map = (struct bpf_map *)(long)r2;
+	struct bpf_array *array = container_of(map, struct bpf_array, map);
+	u32 i = (u32)r3;
+	struct cgroup *cgrp;
+	struct sock *sk;
+
+	WARN_ON_ONCE(!rcu_read_lock_held());
+
+	sk = skb->sk;
+	if (!sk || !sk_fullsock(sk))
+		return -ENOENT;
+
+	if (unlikely(i >= array->map.max_entries))
+		return -E2BIG;
+
+	cgrp = READ_ONCE(array->ptrs[i]);
+	if (unlikely(!cgrp))
+		return -ENOENT;
+
+	return cgroup_is_descendant(sock_cgroup_ptr(&sk->sk_cgrp_data), cgrp);
+}
+
+static const struct bpf_func_proto bpf_skb_in_cgroup_proto = {
+	.func		= bpf_skb_in_cgroup,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_CTX,
+	.arg2_type	= ARG_CONST_MAP_PTR,
+	.arg3_type	= ARG_ANYTHING,
+};
+
 static const struct bpf_func_proto *
 sk_filter_func_proto(enum bpf_func_id func_id)
 {
@@ -2086,6 +2120,8 @@  tc_cls_act_func_proto(enum bpf_func_id func_id)
 		return &bpf_get_route_realm_proto;
 	case BPF_FUNC_perf_event_output:
 		return bpf_get_event_output_proto();
+	case BPF_FUNC_skb_in_cgroup:
+		return &bpf_skb_in_cgroup_proto;
 	default:
 		return sk_filter_func_proto(func_id);
 	}