forked from mirrors/linux
		
	cgroup: bpf: Add bpf_skb_in_cgroup_proto
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 c38c4597e4 ("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>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									4ed8ec521e
								
							
						
					
					
						commit
						4a482f34af
					
				
					 3 changed files with 56 additions and 1 deletions
				
			
		| 
						 | 
					@ -337,6 +337,17 @@ enum bpf_func_id {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	BPF_FUNC_skb_change_type,
 | 
						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,
 | 
						__BPF_FUNC_MAX_ID,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1036,7 +1036,9 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case BPF_MAP_TYPE_CGROUP_ARRAY:
 | 
						case BPF_MAP_TYPE_CGROUP_ARRAY:
 | 
				
			||||||
 | 
							if (func_id != BPF_FUNC_skb_in_cgroup)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1056,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)
 | 
							if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case BPF_FUNC_skb_in_cgroup:
 | 
				
			||||||
 | 
							if (map->map_type != BPF_MAP_TYPE_CGROUP_ARRAY)
 | 
				
			||||||
 | 
								goto error;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2239,6 +2239,40 @@ bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_SOCK_CGROUP_DATA
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
						struct cgroup *cgrp;
 | 
				
			||||||
 | 
						struct sock *sk;
 | 
				
			||||||
 | 
						u32 i = (u32)r3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 -EAGAIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct bpf_func_proto *
 | 
					static const struct bpf_func_proto *
 | 
				
			||||||
sk_filter_func_proto(enum bpf_func_id func_id)
 | 
					sk_filter_func_proto(enum bpf_func_id func_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -2307,6 +2341,10 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
 | 
				
			||||||
		return bpf_get_event_output_proto();
 | 
							return bpf_get_event_output_proto();
 | 
				
			||||||
	case BPF_FUNC_get_smp_processor_id:
 | 
						case BPF_FUNC_get_smp_processor_id:
 | 
				
			||||||
		return &bpf_get_smp_processor_id_proto;
 | 
							return &bpf_get_smp_processor_id_proto;
 | 
				
			||||||
 | 
					#ifdef CONFIG_SOCK_CGROUP_DATA
 | 
				
			||||||
 | 
						case BPF_FUNC_skb_in_cgroup:
 | 
				
			||||||
 | 
							return &bpf_skb_in_cgroup_proto;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return sk_filter_func_proto(func_id);
 | 
							return sk_filter_func_proto(func_id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue