xref: /linux-6.15/include/linux/bpf-cgroup.h (revision d74bad4e)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
230070984SDaniel Mack #ifndef _BPF_CGROUP_H
330070984SDaniel Mack #define _BPF_CGROUP_H
430070984SDaniel Mack 
530070984SDaniel Mack #include <linux/jump_label.h>
630070984SDaniel Mack #include <uapi/linux/bpf.h>
730070984SDaniel Mack 
830070984SDaniel Mack struct sock;
94fbac77dSAndrey Ignatov struct sockaddr;
1030070984SDaniel Mack struct cgroup;
1130070984SDaniel Mack struct sk_buff;
1240304b2aSLawrence Brakmo struct bpf_sock_ops_kern;
1330070984SDaniel Mack 
1430070984SDaniel Mack #ifdef CONFIG_CGROUP_BPF
1530070984SDaniel Mack 
1630070984SDaniel Mack extern struct static_key_false cgroup_bpf_enabled_key;
1730070984SDaniel Mack #define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key)
1830070984SDaniel Mack 
19324bda9eSAlexei Starovoitov struct bpf_prog_list {
20324bda9eSAlexei Starovoitov 	struct list_head node;
21324bda9eSAlexei Starovoitov 	struct bpf_prog *prog;
22324bda9eSAlexei Starovoitov };
23324bda9eSAlexei Starovoitov 
24324bda9eSAlexei Starovoitov struct bpf_prog_array;
25324bda9eSAlexei Starovoitov 
2630070984SDaniel Mack struct cgroup_bpf {
27324bda9eSAlexei Starovoitov 	/* array of effective progs in this cgroup */
28324bda9eSAlexei Starovoitov 	struct bpf_prog_array __rcu *effective[MAX_BPF_ATTACH_TYPE];
29324bda9eSAlexei Starovoitov 
30324bda9eSAlexei Starovoitov 	/* attached progs to this cgroup and attach flags
31324bda9eSAlexei Starovoitov 	 * when flags == 0 or BPF_F_ALLOW_OVERRIDE the progs list will
32324bda9eSAlexei Starovoitov 	 * have either zero or one element
33324bda9eSAlexei Starovoitov 	 * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS
3430070984SDaniel Mack 	 */
35324bda9eSAlexei Starovoitov 	struct list_head progs[MAX_BPF_ATTACH_TYPE];
36324bda9eSAlexei Starovoitov 	u32 flags[MAX_BPF_ATTACH_TYPE];
37324bda9eSAlexei Starovoitov 
38324bda9eSAlexei Starovoitov 	/* temp storage for effective prog array used by prog_attach/detach */
39324bda9eSAlexei Starovoitov 	struct bpf_prog_array __rcu *inactive;
4030070984SDaniel Mack };
4130070984SDaniel Mack 
4230070984SDaniel Mack void cgroup_bpf_put(struct cgroup *cgrp);
43324bda9eSAlexei Starovoitov int cgroup_bpf_inherit(struct cgroup *cgrp);
4430070984SDaniel Mack 
45324bda9eSAlexei Starovoitov int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
46324bda9eSAlexei Starovoitov 			enum bpf_attach_type type, u32 flags);
47324bda9eSAlexei Starovoitov int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
48324bda9eSAlexei Starovoitov 			enum bpf_attach_type type, u32 flags);
49468e2f64SAlexei Starovoitov int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
50468e2f64SAlexei Starovoitov 		       union bpf_attr __user *uattr);
5130070984SDaniel Mack 
52324bda9eSAlexei Starovoitov /* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */
53324bda9eSAlexei Starovoitov int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
54324bda9eSAlexei Starovoitov 		      enum bpf_attach_type type, u32 flags);
55324bda9eSAlexei Starovoitov int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
56324bda9eSAlexei Starovoitov 		      enum bpf_attach_type type, u32 flags);
57468e2f64SAlexei Starovoitov int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
58468e2f64SAlexei Starovoitov 		     union bpf_attr __user *uattr);
5930070984SDaniel Mack 
60b2cd1257SDavid Ahern int __cgroup_bpf_run_filter_skb(struct sock *sk,
6130070984SDaniel Mack 				struct sk_buff *skb,
6230070984SDaniel Mack 				enum bpf_attach_type type);
6330070984SDaniel Mack 
6461023658SDavid Ahern int __cgroup_bpf_run_filter_sk(struct sock *sk,
6561023658SDavid Ahern 			       enum bpf_attach_type type);
6661023658SDavid Ahern 
674fbac77dSAndrey Ignatov int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
684fbac77dSAndrey Ignatov 				      struct sockaddr *uaddr,
694fbac77dSAndrey Ignatov 				      enum bpf_attach_type type);
704fbac77dSAndrey Ignatov 
7140304b2aSLawrence Brakmo int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
7240304b2aSLawrence Brakmo 				     struct bpf_sock_ops_kern *sock_ops,
7340304b2aSLawrence Brakmo 				     enum bpf_attach_type type);
7440304b2aSLawrence Brakmo 
75ebc614f6SRoman Gushchin int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
76ebc614f6SRoman Gushchin 				      short access, enum bpf_attach_type type);
77ebc614f6SRoman Gushchin 
78b2cd1257SDavid Ahern /* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
7930070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb)			      \
8030070984SDaniel Mack ({									      \
8130070984SDaniel Mack 	int __ret = 0;							      \
8230070984SDaniel Mack 	if (cgroup_bpf_enabled)						      \
83b2cd1257SDavid Ahern 		__ret = __cgroup_bpf_run_filter_skb(sk, skb,		      \
8430070984SDaniel Mack 						    BPF_CGROUP_INET_INGRESS); \
8530070984SDaniel Mack 									      \
8630070984SDaniel Mack 	__ret;								      \
8730070984SDaniel Mack })
8830070984SDaniel Mack 
8930070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb)			       \
9030070984SDaniel Mack ({									       \
9130070984SDaniel Mack 	int __ret = 0;							       \
9230070984SDaniel Mack 	if (cgroup_bpf_enabled && sk && sk == skb->sk) {		       \
9330070984SDaniel Mack 		typeof(sk) __sk = sk_to_full_sk(sk);			       \
9430070984SDaniel Mack 		if (sk_fullsock(__sk))					       \
95b2cd1257SDavid Ahern 			__ret = __cgroup_bpf_run_filter_skb(__sk, skb,	       \
9630070984SDaniel Mack 						      BPF_CGROUP_INET_EGRESS); \
9730070984SDaniel Mack 	}								       \
9830070984SDaniel Mack 	__ret;								       \
9930070984SDaniel Mack })
10030070984SDaniel Mack 
10161023658SDavid Ahern #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk)				       \
10261023658SDavid Ahern ({									       \
10361023658SDavid Ahern 	int __ret = 0;							       \
104ee07862fSYafang Shao 	if (cgroup_bpf_enabled) {					       \
10561023658SDavid Ahern 		__ret = __cgroup_bpf_run_filter_sk(sk,			       \
10661023658SDavid Ahern 						 BPF_CGROUP_INET_SOCK_CREATE); \
10761023658SDavid Ahern 	}								       \
10861023658SDavid Ahern 	__ret;								       \
10961023658SDavid Ahern })
11061023658SDavid Ahern 
1114fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, type)				       \
1124fbac77dSAndrey Ignatov ({									       \
1134fbac77dSAndrey Ignatov 	int __ret = 0;							       \
1144fbac77dSAndrey Ignatov 	if (cgroup_bpf_enabled)						       \
1154fbac77dSAndrey Ignatov 		__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type);    \
1164fbac77dSAndrey Ignatov 	__ret;								       \
1174fbac77dSAndrey Ignatov })
1184fbac77dSAndrey Ignatov 
119*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, type)			       \
120*d74bad4eSAndrey Ignatov ({									       \
121*d74bad4eSAndrey Ignatov 	int __ret = 0;							       \
122*d74bad4eSAndrey Ignatov 	if (cgroup_bpf_enabled)	{					       \
123*d74bad4eSAndrey Ignatov 		lock_sock(sk);						       \
124*d74bad4eSAndrey Ignatov 		__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type);    \
125*d74bad4eSAndrey Ignatov 		release_sock(sk);					       \
126*d74bad4eSAndrey Ignatov 	}								       \
127*d74bad4eSAndrey Ignatov 	__ret;								       \
128*d74bad4eSAndrey Ignatov })
129*d74bad4eSAndrey Ignatov 
1304fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr)			       \
1314fbac77dSAndrey Ignatov 	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_BIND)
1324fbac77dSAndrey Ignatov 
1334fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr)			       \
1344fbac77dSAndrey Ignatov 	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_BIND)
1354fbac77dSAndrey Ignatov 
136*d74bad4eSAndrey Ignatov #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (cgroup_bpf_enabled && \
137*d74bad4eSAndrey Ignatov 					    sk->sk_prot->pre_connect)
138*d74bad4eSAndrey Ignatov 
139*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr)			       \
140*d74bad4eSAndrey Ignatov 	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_CONNECT)
141*d74bad4eSAndrey Ignatov 
142*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr)			       \
143*d74bad4eSAndrey Ignatov 	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_CONNECT)
144*d74bad4eSAndrey Ignatov 
145*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr)		       \
146*d74bad4eSAndrey Ignatov 	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET4_CONNECT)
147*d74bad4eSAndrey Ignatov 
148*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr)		       \
149*d74bad4eSAndrey Ignatov 	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET6_CONNECT)
150*d74bad4eSAndrey Ignatov 
15140304b2aSLawrence Brakmo #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops)				       \
15240304b2aSLawrence Brakmo ({									       \
15340304b2aSLawrence Brakmo 	int __ret = 0;							       \
15440304b2aSLawrence Brakmo 	if (cgroup_bpf_enabled && (sock_ops)->sk) {	       \
15540304b2aSLawrence Brakmo 		typeof(sk) __sk = sk_to_full_sk((sock_ops)->sk);	       \
156df39a9f1SWANG Cong 		if (__sk && sk_fullsock(__sk))				       \
15740304b2aSLawrence Brakmo 			__ret = __cgroup_bpf_run_filter_sock_ops(__sk,	       \
15840304b2aSLawrence Brakmo 								 sock_ops,     \
15940304b2aSLawrence Brakmo 							 BPF_CGROUP_SOCK_OPS); \
16040304b2aSLawrence Brakmo 	}								       \
16140304b2aSLawrence Brakmo 	__ret;								       \
16240304b2aSLawrence Brakmo })
163ebc614f6SRoman Gushchin 
164ebc614f6SRoman Gushchin #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access)	      \
165ebc614f6SRoman Gushchin ({									      \
166ebc614f6SRoman Gushchin 	int __ret = 0;							      \
167ebc614f6SRoman Gushchin 	if (cgroup_bpf_enabled)						      \
168ebc614f6SRoman Gushchin 		__ret = __cgroup_bpf_check_dev_permission(type, major, minor, \
169ebc614f6SRoman Gushchin 							  access,	      \
170ebc614f6SRoman Gushchin 							  BPF_CGROUP_DEVICE); \
171ebc614f6SRoman Gushchin 									      \
172ebc614f6SRoman Gushchin 	__ret;								      \
173ebc614f6SRoman Gushchin })
17430070984SDaniel Mack #else
17530070984SDaniel Mack 
17630070984SDaniel Mack struct cgroup_bpf {};
17730070984SDaniel Mack static inline void cgroup_bpf_put(struct cgroup *cgrp) {}
178324bda9eSAlexei Starovoitov static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; }
17930070984SDaniel Mack 
180*d74bad4eSAndrey Ignatov #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0)
18130070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
18230070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
18361023658SDavid Ahern #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; })
1844fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr) ({ 0; })
1854fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr) ({ 0; })
186*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) ({ 0; })
187*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) ({ 0; })
188*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) ({ 0; })
189*d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
19040304b2aSLawrence Brakmo #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
191ebc614f6SRoman Gushchin #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
19230070984SDaniel Mack 
19330070984SDaniel Mack #endif /* CONFIG_CGROUP_BPF */
19430070984SDaniel Mack 
19530070984SDaniel Mack #endif /* _BPF_CGROUP_H */
196