1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 230070984SDaniel Mack #ifndef _BPF_CGROUP_H 330070984SDaniel Mack #define _BPF_CGROUP_H 430070984SDaniel Mack 5f292b87dSRoman Gushchin #include <linux/errno.h> 630070984SDaniel Mack #include <linux/jump_label.h> 7*aa0ad5b0SRoman Gushchin #include <linux/percpu.h> 8de9cbbaaSRoman Gushchin #include <linux/rbtree.h> 930070984SDaniel Mack #include <uapi/linux/bpf.h> 1030070984SDaniel Mack 1130070984SDaniel Mack struct sock; 124fbac77dSAndrey Ignatov struct sockaddr; 1330070984SDaniel Mack struct cgroup; 1430070984SDaniel Mack struct sk_buff; 15de9cbbaaSRoman Gushchin struct bpf_map; 16de9cbbaaSRoman Gushchin struct bpf_prog; 1740304b2aSLawrence Brakmo struct bpf_sock_ops_kern; 18de9cbbaaSRoman Gushchin struct bpf_cgroup_storage; 1930070984SDaniel Mack 2030070984SDaniel Mack #ifdef CONFIG_CGROUP_BPF 2130070984SDaniel Mack 2230070984SDaniel Mack extern struct static_key_false cgroup_bpf_enabled_key; 2330070984SDaniel Mack #define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key) 2430070984SDaniel Mack 25*aa0ad5b0SRoman Gushchin DECLARE_PER_CPU(void*, bpf_cgroup_storage); 26*aa0ad5b0SRoman Gushchin 27de9cbbaaSRoman Gushchin struct bpf_cgroup_storage_map; 28de9cbbaaSRoman Gushchin 29de9cbbaaSRoman Gushchin struct bpf_storage_buffer { 30de9cbbaaSRoman Gushchin struct rcu_head rcu; 31de9cbbaaSRoman Gushchin char data[0]; 32de9cbbaaSRoman Gushchin }; 33de9cbbaaSRoman Gushchin 34de9cbbaaSRoman Gushchin struct bpf_cgroup_storage { 35de9cbbaaSRoman Gushchin struct bpf_storage_buffer *buf; 36de9cbbaaSRoman Gushchin struct bpf_cgroup_storage_map *map; 37de9cbbaaSRoman Gushchin struct bpf_cgroup_storage_key key; 38de9cbbaaSRoman Gushchin struct list_head list; 39de9cbbaaSRoman Gushchin struct rb_node node; 40de9cbbaaSRoman Gushchin struct rcu_head rcu; 41de9cbbaaSRoman Gushchin }; 42de9cbbaaSRoman Gushchin 43324bda9eSAlexei Starovoitov struct bpf_prog_list { 44324bda9eSAlexei Starovoitov struct list_head node; 45324bda9eSAlexei Starovoitov struct bpf_prog *prog; 46324bda9eSAlexei Starovoitov }; 47324bda9eSAlexei Starovoitov 48324bda9eSAlexei Starovoitov struct bpf_prog_array; 49324bda9eSAlexei Starovoitov 5030070984SDaniel Mack struct cgroup_bpf { 51324bda9eSAlexei Starovoitov /* array of effective progs in this cgroup */ 52324bda9eSAlexei Starovoitov struct bpf_prog_array __rcu *effective[MAX_BPF_ATTACH_TYPE]; 53324bda9eSAlexei Starovoitov 54324bda9eSAlexei Starovoitov /* attached progs to this cgroup and attach flags 55324bda9eSAlexei Starovoitov * when flags == 0 or BPF_F_ALLOW_OVERRIDE the progs list will 56324bda9eSAlexei Starovoitov * have either zero or one element 57324bda9eSAlexei Starovoitov * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS 5830070984SDaniel Mack */ 59324bda9eSAlexei Starovoitov struct list_head progs[MAX_BPF_ATTACH_TYPE]; 60324bda9eSAlexei Starovoitov u32 flags[MAX_BPF_ATTACH_TYPE]; 61324bda9eSAlexei Starovoitov 62324bda9eSAlexei Starovoitov /* temp storage for effective prog array used by prog_attach/detach */ 63324bda9eSAlexei Starovoitov struct bpf_prog_array __rcu *inactive; 6430070984SDaniel Mack }; 6530070984SDaniel Mack 6630070984SDaniel Mack void cgroup_bpf_put(struct cgroup *cgrp); 67324bda9eSAlexei Starovoitov int cgroup_bpf_inherit(struct cgroup *cgrp); 6830070984SDaniel Mack 69324bda9eSAlexei Starovoitov int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, 70324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 71324bda9eSAlexei Starovoitov int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, 72324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 73468e2f64SAlexei Starovoitov int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, 74468e2f64SAlexei Starovoitov union bpf_attr __user *uattr); 7530070984SDaniel Mack 76324bda9eSAlexei Starovoitov /* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */ 77324bda9eSAlexei Starovoitov int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, 78324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 79324bda9eSAlexei Starovoitov int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, 80324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 81468e2f64SAlexei Starovoitov int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, 82468e2f64SAlexei Starovoitov union bpf_attr __user *uattr); 8330070984SDaniel Mack 84b2cd1257SDavid Ahern int __cgroup_bpf_run_filter_skb(struct sock *sk, 8530070984SDaniel Mack struct sk_buff *skb, 8630070984SDaniel Mack enum bpf_attach_type type); 8730070984SDaniel Mack 8861023658SDavid Ahern int __cgroup_bpf_run_filter_sk(struct sock *sk, 8961023658SDavid Ahern enum bpf_attach_type type); 9061023658SDavid Ahern 914fbac77dSAndrey Ignatov int __cgroup_bpf_run_filter_sock_addr(struct sock *sk, 924fbac77dSAndrey Ignatov struct sockaddr *uaddr, 931cedee13SAndrey Ignatov enum bpf_attach_type type, 941cedee13SAndrey Ignatov void *t_ctx); 954fbac77dSAndrey Ignatov 9640304b2aSLawrence Brakmo int __cgroup_bpf_run_filter_sock_ops(struct sock *sk, 9740304b2aSLawrence Brakmo struct bpf_sock_ops_kern *sock_ops, 9840304b2aSLawrence Brakmo enum bpf_attach_type type); 9940304b2aSLawrence Brakmo 100ebc614f6SRoman Gushchin int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor, 101ebc614f6SRoman Gushchin short access, enum bpf_attach_type type); 102ebc614f6SRoman Gushchin 103*aa0ad5b0SRoman Gushchin static inline void bpf_cgroup_storage_set(struct bpf_cgroup_storage *storage) 104*aa0ad5b0SRoman Gushchin { 105*aa0ad5b0SRoman Gushchin struct bpf_storage_buffer *buf; 106*aa0ad5b0SRoman Gushchin 107*aa0ad5b0SRoman Gushchin if (!storage) 108*aa0ad5b0SRoman Gushchin return; 109*aa0ad5b0SRoman Gushchin 110*aa0ad5b0SRoman Gushchin buf = READ_ONCE(storage->buf); 111*aa0ad5b0SRoman Gushchin this_cpu_write(bpf_cgroup_storage, &buf->data[0]); 112*aa0ad5b0SRoman Gushchin } 113*aa0ad5b0SRoman Gushchin 114de9cbbaaSRoman Gushchin struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(struct bpf_prog *prog); 115de9cbbaaSRoman Gushchin void bpf_cgroup_storage_free(struct bpf_cgroup_storage *storage); 116de9cbbaaSRoman Gushchin void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage, 117de9cbbaaSRoman Gushchin struct cgroup *cgroup, 118de9cbbaaSRoman Gushchin enum bpf_attach_type type); 119de9cbbaaSRoman Gushchin void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage); 120de9cbbaaSRoman Gushchin int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *map); 121de9cbbaaSRoman Gushchin void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *map); 122de9cbbaaSRoman Gushchin 123b2cd1257SDavid Ahern /* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */ 12430070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb) \ 12530070984SDaniel Mack ({ \ 12630070984SDaniel Mack int __ret = 0; \ 12730070984SDaniel Mack if (cgroup_bpf_enabled) \ 128b2cd1257SDavid Ahern __ret = __cgroup_bpf_run_filter_skb(sk, skb, \ 12930070984SDaniel Mack BPF_CGROUP_INET_INGRESS); \ 13030070984SDaniel Mack \ 13130070984SDaniel Mack __ret; \ 13230070984SDaniel Mack }) 13330070984SDaniel Mack 13430070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb) \ 13530070984SDaniel Mack ({ \ 13630070984SDaniel Mack int __ret = 0; \ 13730070984SDaniel Mack if (cgroup_bpf_enabled && sk && sk == skb->sk) { \ 13830070984SDaniel Mack typeof(sk) __sk = sk_to_full_sk(sk); \ 13930070984SDaniel Mack if (sk_fullsock(__sk)) \ 140b2cd1257SDavid Ahern __ret = __cgroup_bpf_run_filter_skb(__sk, skb, \ 14130070984SDaniel Mack BPF_CGROUP_INET_EGRESS); \ 14230070984SDaniel Mack } \ 14330070984SDaniel Mack __ret; \ 14430070984SDaniel Mack }) 14530070984SDaniel Mack 146aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_SK_PROG(sk, type) \ 14761023658SDavid Ahern ({ \ 14861023658SDavid Ahern int __ret = 0; \ 149ee07862fSYafang Shao if (cgroup_bpf_enabled) { \ 150aac3fc32SAndrey Ignatov __ret = __cgroup_bpf_run_filter_sk(sk, type); \ 15161023658SDavid Ahern } \ 15261023658SDavid Ahern __ret; \ 15361023658SDavid Ahern }) 15461023658SDavid Ahern 155aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) \ 156aac3fc32SAndrey Ignatov BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET_SOCK_CREATE) 157aac3fc32SAndrey Ignatov 158aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) \ 159aac3fc32SAndrey Ignatov BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET4_POST_BIND) 160aac3fc32SAndrey Ignatov 161aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) \ 162aac3fc32SAndrey Ignatov BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET6_POST_BIND) 163aac3fc32SAndrey Ignatov 1644fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, type) \ 1654fbac77dSAndrey Ignatov ({ \ 1664fbac77dSAndrey Ignatov int __ret = 0; \ 1674fbac77dSAndrey Ignatov if (cgroup_bpf_enabled) \ 1681cedee13SAndrey Ignatov __ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type, \ 1691cedee13SAndrey Ignatov NULL); \ 1704fbac77dSAndrey Ignatov __ret; \ 1714fbac77dSAndrey Ignatov }) 1724fbac77dSAndrey Ignatov 1731cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, type, t_ctx) \ 174d74bad4eSAndrey Ignatov ({ \ 175d74bad4eSAndrey Ignatov int __ret = 0; \ 176d74bad4eSAndrey Ignatov if (cgroup_bpf_enabled) { \ 177d74bad4eSAndrey Ignatov lock_sock(sk); \ 1781cedee13SAndrey Ignatov __ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type, \ 1791cedee13SAndrey Ignatov t_ctx); \ 180d74bad4eSAndrey Ignatov release_sock(sk); \ 181d74bad4eSAndrey Ignatov } \ 182d74bad4eSAndrey Ignatov __ret; \ 183d74bad4eSAndrey Ignatov }) 184d74bad4eSAndrey Ignatov 1854fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr) \ 1864fbac77dSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_BIND) 1874fbac77dSAndrey Ignatov 1884fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr) \ 1894fbac77dSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_BIND) 1904fbac77dSAndrey Ignatov 191d74bad4eSAndrey Ignatov #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (cgroup_bpf_enabled && \ 192d74bad4eSAndrey Ignatov sk->sk_prot->pre_connect) 193d74bad4eSAndrey Ignatov 194d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) \ 195d74bad4eSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_CONNECT) 196d74bad4eSAndrey Ignatov 197d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) \ 198d74bad4eSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_CONNECT) 199d74bad4eSAndrey Ignatov 200d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) \ 2011cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET4_CONNECT, NULL) 202d74bad4eSAndrey Ignatov 203d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) \ 2041cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET6_CONNECT, NULL) 2051cedee13SAndrey Ignatov 2061cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) \ 2071cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_SENDMSG, t_ctx) 2081cedee13SAndrey Ignatov 2091cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \ 2101cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx) 211d74bad4eSAndrey Ignatov 21240304b2aSLawrence Brakmo #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) \ 21340304b2aSLawrence Brakmo ({ \ 21440304b2aSLawrence Brakmo int __ret = 0; \ 21540304b2aSLawrence Brakmo if (cgroup_bpf_enabled && (sock_ops)->sk) { \ 21640304b2aSLawrence Brakmo typeof(sk) __sk = sk_to_full_sk((sock_ops)->sk); \ 217df39a9f1SWANG Cong if (__sk && sk_fullsock(__sk)) \ 21840304b2aSLawrence Brakmo __ret = __cgroup_bpf_run_filter_sock_ops(__sk, \ 21940304b2aSLawrence Brakmo sock_ops, \ 22040304b2aSLawrence Brakmo BPF_CGROUP_SOCK_OPS); \ 22140304b2aSLawrence Brakmo } \ 22240304b2aSLawrence Brakmo __ret; \ 22340304b2aSLawrence Brakmo }) 224ebc614f6SRoman Gushchin 225ebc614f6SRoman Gushchin #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access) \ 226ebc614f6SRoman Gushchin ({ \ 227ebc614f6SRoman Gushchin int __ret = 0; \ 228ebc614f6SRoman Gushchin if (cgroup_bpf_enabled) \ 229ebc614f6SRoman Gushchin __ret = __cgroup_bpf_check_dev_permission(type, major, minor, \ 230ebc614f6SRoman Gushchin access, \ 231ebc614f6SRoman Gushchin BPF_CGROUP_DEVICE); \ 232ebc614f6SRoman Gushchin \ 233ebc614f6SRoman Gushchin __ret; \ 234ebc614f6SRoman Gushchin }) 235fdb5c453SSean Young int cgroup_bpf_prog_attach(const union bpf_attr *attr, 236fdb5c453SSean Young enum bpf_prog_type ptype, struct bpf_prog *prog); 237fdb5c453SSean Young int cgroup_bpf_prog_detach(const union bpf_attr *attr, 238fdb5c453SSean Young enum bpf_prog_type ptype); 239fdb5c453SSean Young int cgroup_bpf_prog_query(const union bpf_attr *attr, 240fdb5c453SSean Young union bpf_attr __user *uattr); 24130070984SDaniel Mack #else 24230070984SDaniel Mack 243fdb5c453SSean Young struct bpf_prog; 24430070984SDaniel Mack struct cgroup_bpf {}; 24530070984SDaniel Mack static inline void cgroup_bpf_put(struct cgroup *cgrp) {} 246324bda9eSAlexei Starovoitov static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; } 24730070984SDaniel Mack 248fdb5c453SSean Young static inline int cgroup_bpf_prog_attach(const union bpf_attr *attr, 249fdb5c453SSean Young enum bpf_prog_type ptype, 250fdb5c453SSean Young struct bpf_prog *prog) 251fdb5c453SSean Young { 252fdb5c453SSean Young return -EINVAL; 253fdb5c453SSean Young } 254fdb5c453SSean Young 255fdb5c453SSean Young static inline int cgroup_bpf_prog_detach(const union bpf_attr *attr, 256fdb5c453SSean Young enum bpf_prog_type ptype) 257fdb5c453SSean Young { 258fdb5c453SSean Young return -EINVAL; 259fdb5c453SSean Young } 260fdb5c453SSean Young 261fdb5c453SSean Young static inline int cgroup_bpf_prog_query(const union bpf_attr *attr, 262fdb5c453SSean Young union bpf_attr __user *uattr) 263fdb5c453SSean Young { 264fdb5c453SSean Young return -EINVAL; 265fdb5c453SSean Young } 266fdb5c453SSean Young 267*aa0ad5b0SRoman Gushchin static inline void bpf_cgroup_storage_set(struct bpf_cgroup_storage *storage) {} 268de9cbbaaSRoman Gushchin static inline int bpf_cgroup_storage_assign(struct bpf_prog *prog, 269de9cbbaaSRoman Gushchin struct bpf_map *map) { return 0; } 270de9cbbaaSRoman Gushchin static inline void bpf_cgroup_storage_release(struct bpf_prog *prog, 271de9cbbaaSRoman Gushchin struct bpf_map *map) {} 272de9cbbaaSRoman Gushchin static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc( 273de9cbbaaSRoman Gushchin struct bpf_prog *prog) { return 0; } 274de9cbbaaSRoman Gushchin static inline void bpf_cgroup_storage_free( 275de9cbbaaSRoman Gushchin struct bpf_cgroup_storage *storage) {} 276de9cbbaaSRoman Gushchin 27713193b0fSAndrey Ignatov #define cgroup_bpf_enabled (0) 278d74bad4eSAndrey Ignatov #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0) 27930070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) 28030070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; }) 28161023658SDavid Ahern #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; }) 2824fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr) ({ 0; }) 2834fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr) ({ 0; }) 284aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) ({ 0; }) 285aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) ({ 0; }) 286d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) ({ 0; }) 287d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) ({ 0; }) 288d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) ({ 0; }) 289d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; }) 2901cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; }) 2911cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; }) 29240304b2aSLawrence Brakmo #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; }) 293ebc614f6SRoman Gushchin #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; }) 29430070984SDaniel Mack 29530070984SDaniel Mack #endif /* CONFIG_CGROUP_BPF */ 29630070984SDaniel Mack 29730070984SDaniel Mack #endif /* _BPF_CGROUP_H */ 298