bpf-cgroup.h 14.4 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3 4
#ifndef _BPF_CGROUP_H
#define _BPF_CGROUP_H

5
#include <linux/bpf.h>
6
#include <linux/errno.h>
7
#include <linux/jump_label.h>
8
#include <linux/percpu.h>
9
#include <linux/percpu-refcount.h>
10
#include <linux/rbtree.h>
11 12 13
#include <uapi/linux/bpf.h>

struct sock;
A
Andrey Ignatov 已提交
14
struct sockaddr;
15 16
struct cgroup;
struct sk_buff;
17 18
struct bpf_map;
struct bpf_prog;
L
Lawrence Brakmo 已提交
19
struct bpf_sock_ops_kern;
20
struct bpf_cgroup_storage;
A
Andrey Ignatov 已提交
21 22
struct ctl_table;
struct ctl_table_header;
23 24 25 26 27 28

#ifdef CONFIG_CGROUP_BPF

extern struct static_key_false cgroup_bpf_enabled_key;
#define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key)

29 30
DECLARE_PER_CPU(struct bpf_cgroup_storage*,
		bpf_cgroup_storage[MAX_BPF_CGROUP_STORAGE_TYPE]);
31 32 33

#define for_each_cgroup_storage_type(stype) \
	for (stype = 0; stype < MAX_BPF_CGROUP_STORAGE_TYPE; stype++)
34

35 36 37 38
struct bpf_cgroup_storage_map;

struct bpf_storage_buffer {
	struct rcu_head rcu;
39
	char data[];
40 41 42
};

struct bpf_cgroup_storage {
43 44 45 46
	union {
		struct bpf_storage_buffer *buf;
		void __percpu *percpu_buf;
	};
47 48 49 50 51 52 53
	struct bpf_cgroup_storage_map *map;
	struct bpf_cgroup_storage_key key;
	struct list_head list;
	struct rb_node node;
	struct rcu_head rcu;
};

54 55 56 57 58 59 60 61
struct bpf_cgroup_link {
	struct bpf_link link;
	struct cgroup *cgroup;
	enum bpf_attach_type type;
};

extern const struct bpf_link_ops bpf_cgroup_link_lops;

62 63 64
struct bpf_prog_list {
	struct list_head node;
	struct bpf_prog *prog;
65
	struct bpf_cgroup_link *link;
66
	struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE];
67 68 69 70
};

struct bpf_prog_array;

71
struct cgroup_bpf {
72 73 74 75 76 77 78
	/* array of effective progs in this cgroup */
	struct bpf_prog_array __rcu *effective[MAX_BPF_ATTACH_TYPE];

	/* attached progs to this cgroup and attach flags
	 * when flags == 0 or BPF_F_ALLOW_OVERRIDE the progs list will
	 * have either zero or one element
	 * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS
79
	 */
80 81 82 83
	struct list_head progs[MAX_BPF_ATTACH_TYPE];
	u32 flags[MAX_BPF_ATTACH_TYPE];

	/* temp storage for effective prog array used by prog_attach/detach */
84
	struct bpf_prog_array *inactive;
85 86 87 88 89 90

	/* reference counter used to detach bpf programs after cgroup removal */
	struct percpu_ref refcnt;

	/* cgroup_bpf is released using a work queue */
	struct work_struct release_work;
91 92
};

93
int cgroup_bpf_inherit(struct cgroup *cgrp);
94
void cgroup_bpf_offline(struct cgroup *cgrp);
95

96 97 98
int __cgroup_bpf_attach(struct cgroup *cgrp,
			struct bpf_prog *prog, struct bpf_prog *replace_prog,
			struct bpf_cgroup_link *link,
99 100
			enum bpf_attach_type type, u32 flags);
int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
101
			struct bpf_cgroup_link *link,
102
			enum bpf_attach_type type);
103 104
int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
		       union bpf_attr __user *uattr);
105

106
/* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */
107 108 109
int cgroup_bpf_attach(struct cgroup *cgrp,
		      struct bpf_prog *prog, struct bpf_prog *replace_prog,
		      struct bpf_cgroup_link *link, enum bpf_attach_type type,
110
		      u32 flags);
111
int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
112
		      enum bpf_attach_type type);
113 114
int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
		     union bpf_attr __user *uattr);
115

116 117 118 119
int __cgroup_bpf_run_filter_skb(struct sock *sk,
				struct sk_buff *skb,
				enum bpf_attach_type type);

120 121 122
int __cgroup_bpf_run_filter_sk(struct sock *sk,
			       enum bpf_attach_type type);

A
Andrey Ignatov 已提交
123 124
int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
				      struct sockaddr *uaddr,
A
Andrey Ignatov 已提交
125 126
				      enum bpf_attach_type type,
				      void *t_ctx);
A
Andrey Ignatov 已提交
127

L
Lawrence Brakmo 已提交
128 129 130 131
int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
				     struct bpf_sock_ops_kern *sock_ops,
				     enum bpf_attach_type type);

132 133 134
int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
				      short access, enum bpf_attach_type type);

A
Andrey Ignatov 已提交
135 136
int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
				   struct ctl_table *table, int write,
137
				   void __user *buf, size_t *pcount,
138 139
				   loff_t *ppos, void **new_buf,
				   enum bpf_attach_type type);
A
Andrey Ignatov 已提交
140

141 142 143 144 145 146 147 148
int __cgroup_bpf_run_filter_setsockopt(struct sock *sock, int *level,
				       int *optname, char __user *optval,
				       int *optlen, char **kernel_optval);
int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
				       int optname, char __user *optval,
				       int __user *optlen, int max_optlen,
				       int retval);

149 150
static inline enum bpf_cgroup_storage_type cgroup_storage_type(
	struct bpf_map *map)
151
{
152 153 154
	if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
		return BPF_CGROUP_STORAGE_PERCPU;

155 156 157 158 159 160 161
	return BPF_CGROUP_STORAGE_SHARED;
}

static inline void bpf_cgroup_storage_set(struct bpf_cgroup_storage
					  *storage[MAX_BPF_CGROUP_STORAGE_TYPE])
{
	enum bpf_cgroup_storage_type stype;
162

163 164
	for_each_cgroup_storage_type(stype)
		this_cpu_write(bpf_cgroup_storage[stype], storage[stype]);
165 166
}

167 168
struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(struct bpf_prog *prog,
					enum bpf_cgroup_storage_type stype);
169 170 171 172 173
void bpf_cgroup_storage_free(struct bpf_cgroup_storage *storage);
void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage,
			     struct cgroup *cgroup,
			     enum bpf_attach_type type);
void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage);
174 175
int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *map);
void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *map);
176

177 178 179 180
int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value);
int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
				     void *value, u64 flags);

181 182 183 184 185 186 187 188 189
/* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb)			      \
({									      \
	int __ret = 0;							      \
	if (cgroup_bpf_enabled)						      \
		__ret = __cgroup_bpf_run_filter_skb(sk, skb,		      \
						    BPF_CGROUP_INET_INGRESS); \
									      \
	__ret;								      \
190 191
})

192 193 194 195 196 197 198 199 200 201
#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb)			       \
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled && sk && sk == skb->sk) {		       \
		typeof(sk) __sk = sk_to_full_sk(sk);			       \
		if (sk_fullsock(__sk))					       \
			__ret = __cgroup_bpf_run_filter_skb(__sk, skb,	       \
						      BPF_CGROUP_INET_EGRESS); \
	}								       \
	__ret;								       \
202 203
})

A
Andrey Ignatov 已提交
204
#define BPF_CGROUP_RUN_SK_PROG(sk, type)				       \
205 206
({									       \
	int __ret = 0;							       \
207
	if (cgroup_bpf_enabled) {					       \
A
Andrey Ignatov 已提交
208
		__ret = __cgroup_bpf_run_filter_sk(sk, type);		       \
209 210 211 212
	}								       \
	__ret;								       \
})

A
Andrey Ignatov 已提交
213 214 215 216 217 218 219 220 221
#define BPF_CGROUP_RUN_PROG_INET_SOCK(sk)				       \
	BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET_SOCK_CREATE)

#define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk)				       \
	BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET4_POST_BIND)

#define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk)				       \
	BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET6_POST_BIND)

A
Andrey Ignatov 已提交
222 223 224 225
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, type)				       \
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled)						       \
A
Andrey Ignatov 已提交
226 227
		__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type,     \
							  NULL);	       \
A
Andrey Ignatov 已提交
228 229 230
	__ret;								       \
})

A
Andrey Ignatov 已提交
231
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, type, t_ctx)		       \
A
Andrey Ignatov 已提交
232 233 234 235
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled)	{					       \
		lock_sock(sk);						       \
A
Andrey Ignatov 已提交
236 237
		__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type,     \
							  t_ctx);	       \
A
Andrey Ignatov 已提交
238 239 240 241 242
		release_sock(sk);					       \
	}								       \
	__ret;								       \
})

A
Andrey Ignatov 已提交
243 244 245 246 247 248
#define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr)			       \
	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_BIND)

#define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr)			       \
	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_BIND)

A
Andrey Ignatov 已提交
249 250 251 252 253 254 255 256 257 258
#define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (cgroup_bpf_enabled && \
					    sk->sk_prot->pre_connect)

#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr)			       \
	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_CONNECT)

#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr)			       \
	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_CONNECT)

#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr)		       \
A
Andrey Ignatov 已提交
259
	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET4_CONNECT, NULL)
A
Andrey Ignatov 已提交
260 261

#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr)		       \
A
Andrey Ignatov 已提交
262 263 264 265 266 267 268
	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET6_CONNECT, NULL)

#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx)		       \
	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_SENDMSG, t_ctx)

#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx)		       \
	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx)
A
Andrey Ignatov 已提交
269

D
Daniel Borkmann 已提交
270 271 272 273 274 275
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr)			\
	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_RECVMSG, NULL)

#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr)			\
	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_RECVMSG, NULL)

L
Lawrence Brakmo 已提交
276 277 278 279 280
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops)				       \
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled && (sock_ops)->sk) {	       \
		typeof(sk) __sk = sk_to_full_sk((sock_ops)->sk);	       \
281
		if (__sk && sk_fullsock(__sk))				       \
L
Lawrence Brakmo 已提交
282 283 284 285 286 287
			__ret = __cgroup_bpf_run_filter_sock_ops(__sk,	       \
								 sock_ops,     \
							 BPF_CGROUP_SOCK_OPS); \
	}								       \
	__ret;								       \
})
288 289 290 291 292 293 294 295 296 297 298

#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access)	      \
({									      \
	int __ret = 0;							      \
	if (cgroup_bpf_enabled)						      \
		__ret = __cgroup_bpf_check_dev_permission(type, major, minor, \
							  access,	      \
							  BPF_CGROUP_DEVICE); \
									      \
	__ret;								      \
})
A
Andrey Ignatov 已提交
299 300


301
#define BPF_CGROUP_RUN_PROG_SYSCTL(head, table, write, buf, count, pos, nbuf)  \
A
Andrey Ignatov 已提交
302 303 304 305
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled)						       \
		__ret = __cgroup_bpf_run_filter_sysctl(head, table, write,     \
306
						       buf, count, pos, nbuf,  \
A
Andrey Ignatov 已提交
307 308 309 310
						       BPF_CGROUP_SYSCTL);     \
	__ret;								       \
})

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
#define BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock, level, optname, optval, optlen,   \
				       kernel_optval)			       \
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled)						       \
		__ret = __cgroup_bpf_run_filter_setsockopt(sock, level,	       \
							   optname, optval,    \
							   optlen,	       \
							   kernel_optval);     \
	__ret;								       \
})

#define BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen)			       \
({									       \
	int __ret = 0;							       \
	if (cgroup_bpf_enabled)						       \
		get_user(__ret, optlen);				       \
	__ret;								       \
})

#define BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock, level, optname, optval, optlen,   \
				       max_optlen, retval)		       \
({									       \
	int __ret = retval;						       \
	if (cgroup_bpf_enabled)						       \
		__ret = __cgroup_bpf_run_filter_getsockopt(sock, level,	       \
							   optname, optval,    \
							   optlen, max_optlen, \
							   retval);	       \
	__ret;								       \
})

343 344 345 346
int cgroup_bpf_prog_attach(const union bpf_attr *attr,
			   enum bpf_prog_type ptype, struct bpf_prog *prog);
int cgroup_bpf_prog_detach(const union bpf_attr *attr,
			   enum bpf_prog_type ptype);
347
int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
348 349
int cgroup_bpf_prog_query(const union bpf_attr *attr,
			  union bpf_attr __user *uattr);
350 351
#else

352
struct bpf_prog;
353
struct cgroup_bpf {};
354
static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; }
355
static inline void cgroup_bpf_offline(struct cgroup *cgrp) {}
356

357 358 359 360 361 362 363 364 365 366 367 368 369
static inline int cgroup_bpf_prog_attach(const union bpf_attr *attr,
					 enum bpf_prog_type ptype,
					 struct bpf_prog *prog)
{
	return -EINVAL;
}

static inline int cgroup_bpf_prog_detach(const union bpf_attr *attr,
					 enum bpf_prog_type ptype)
{
	return -EINVAL;
}

370 371 372 373 374 375
static inline int cgroup_bpf_link_attach(const union bpf_attr *attr,
					 struct bpf_prog *prog)
{
	return -EINVAL;
}

376 377 378 379 380 381
static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
					union bpf_attr __user *uattr)
{
	return -EINVAL;
}

382 383
static inline void bpf_cgroup_storage_set(
	struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]) {}
384
static inline int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux,
385
					    struct bpf_map *map) { return 0; }
386
static inline void bpf_cgroup_storage_release(struct bpf_prog_aux *aux,
387 388
					      struct bpf_map *map) {}
static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(
389
	struct bpf_prog *prog, enum bpf_cgroup_storage_type stype) { return NULL; }
390 391
static inline void bpf_cgroup_storage_free(
	struct bpf_cgroup_storage *storage) {}
392 393 394 395 396 397 398 399
static inline int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key,
						 void *value) {
	return 0;
}
static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
					void *key, void *value, u64 flags) {
	return 0;
}
400

401
#define cgroup_bpf_enabled (0)
A
Andrey Ignatov 已提交
402
#define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0)
403 404
#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
405
#define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; })
A
Andrey Ignatov 已提交
406 407
#define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr) ({ 0; })
A
Andrey Ignatov 已提交
408 409
#define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) ({ 0; })
A
Andrey Ignatov 已提交
410 411 412 413
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
A
Andrey Ignatov 已提交
414 415
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
D
Daniel Borkmann 已提交
416 417
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
L
Lawrence Brakmo 已提交
418
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
419
#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
420
#define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; })
421 422 423 424 425
#define BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen) ({ 0; })
#define BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock, level, optname, optval, \
				       optlen, max_optlen, retval) ({ retval; })
#define BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock, level, optname, optval, optlen, \
				       kernel_optval) ({ 0; })
426

427 428
#define for_each_cgroup_storage_type(stype) for (; false; )

429 430 431
#endif /* CONFIG_CGROUP_BPF */

#endif /* _BPF_CGROUP_H */