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*de9cbbaaSRoman Gushchin #include <linux/rbtree.h> 830070984SDaniel Mack #include <uapi/linux/bpf.h> 930070984SDaniel Mack 1030070984SDaniel Mack struct sock; 114fbac77dSAndrey Ignatov struct sockaddr; 1230070984SDaniel Mack struct cgroup; 1330070984SDaniel Mack struct sk_buff; 14*de9cbbaaSRoman Gushchin struct bpf_map; 15*de9cbbaaSRoman Gushchin struct bpf_prog; 1640304b2aSLawrence Brakmo struct bpf_sock_ops_kern; 17*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage; 1830070984SDaniel Mack 1930070984SDaniel Mack #ifdef CONFIG_CGROUP_BPF 2030070984SDaniel Mack 2130070984SDaniel Mack extern struct static_key_false cgroup_bpf_enabled_key; 2230070984SDaniel Mack #define cgroup_bpf_enabled static_branch_unlikely(&cgroup_bpf_enabled_key) 2330070984SDaniel Mack 24*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage_map; 25*de9cbbaaSRoman Gushchin 26*de9cbbaaSRoman Gushchin struct bpf_storage_buffer { 27*de9cbbaaSRoman Gushchin struct rcu_head rcu; 28*de9cbbaaSRoman Gushchin char data[0]; 29*de9cbbaaSRoman Gushchin }; 30*de9cbbaaSRoman Gushchin 31*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage { 32*de9cbbaaSRoman Gushchin struct bpf_storage_buffer *buf; 33*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage_map *map; 34*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage_key key; 35*de9cbbaaSRoman Gushchin struct list_head list; 36*de9cbbaaSRoman Gushchin struct rb_node node; 37*de9cbbaaSRoman Gushchin struct rcu_head rcu; 38*de9cbbaaSRoman Gushchin }; 39*de9cbbaaSRoman Gushchin 40324bda9eSAlexei Starovoitov struct bpf_prog_list { 41324bda9eSAlexei Starovoitov struct list_head node; 42324bda9eSAlexei Starovoitov struct bpf_prog *prog; 43324bda9eSAlexei Starovoitov }; 44324bda9eSAlexei Starovoitov 45324bda9eSAlexei Starovoitov struct bpf_prog_array; 46324bda9eSAlexei Starovoitov 4730070984SDaniel Mack struct cgroup_bpf { 48324bda9eSAlexei Starovoitov /* array of effective progs in this cgroup */ 49324bda9eSAlexei Starovoitov struct bpf_prog_array __rcu *effective[MAX_BPF_ATTACH_TYPE]; 50324bda9eSAlexei Starovoitov 51324bda9eSAlexei Starovoitov /* attached progs to this cgroup and attach flags 52324bda9eSAlexei Starovoitov * when flags == 0 or BPF_F_ALLOW_OVERRIDE the progs list will 53324bda9eSAlexei Starovoitov * have either zero or one element 54324bda9eSAlexei Starovoitov * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS 5530070984SDaniel Mack */ 56324bda9eSAlexei Starovoitov struct list_head progs[MAX_BPF_ATTACH_TYPE]; 57324bda9eSAlexei Starovoitov u32 flags[MAX_BPF_ATTACH_TYPE]; 58324bda9eSAlexei Starovoitov 59324bda9eSAlexei Starovoitov /* temp storage for effective prog array used by prog_attach/detach */ 60324bda9eSAlexei Starovoitov struct bpf_prog_array __rcu *inactive; 6130070984SDaniel Mack }; 6230070984SDaniel Mack 6330070984SDaniel Mack void cgroup_bpf_put(struct cgroup *cgrp); 64324bda9eSAlexei Starovoitov int cgroup_bpf_inherit(struct cgroup *cgrp); 6530070984SDaniel Mack 66324bda9eSAlexei Starovoitov int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, 67324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 68324bda9eSAlexei Starovoitov int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, 69324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 70468e2f64SAlexei Starovoitov int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, 71468e2f64SAlexei Starovoitov union bpf_attr __user *uattr); 7230070984SDaniel Mack 73324bda9eSAlexei Starovoitov /* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */ 74324bda9eSAlexei Starovoitov int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, 75324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 76324bda9eSAlexei Starovoitov int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, 77324bda9eSAlexei Starovoitov enum bpf_attach_type type, u32 flags); 78468e2f64SAlexei Starovoitov int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, 79468e2f64SAlexei Starovoitov union bpf_attr __user *uattr); 8030070984SDaniel Mack 81b2cd1257SDavid Ahern int __cgroup_bpf_run_filter_skb(struct sock *sk, 8230070984SDaniel Mack struct sk_buff *skb, 8330070984SDaniel Mack enum bpf_attach_type type); 8430070984SDaniel Mack 8561023658SDavid Ahern int __cgroup_bpf_run_filter_sk(struct sock *sk, 8661023658SDavid Ahern enum bpf_attach_type type); 8761023658SDavid Ahern 884fbac77dSAndrey Ignatov int __cgroup_bpf_run_filter_sock_addr(struct sock *sk, 894fbac77dSAndrey Ignatov struct sockaddr *uaddr, 901cedee13SAndrey Ignatov enum bpf_attach_type type, 911cedee13SAndrey Ignatov void *t_ctx); 924fbac77dSAndrey Ignatov 9340304b2aSLawrence Brakmo int __cgroup_bpf_run_filter_sock_ops(struct sock *sk, 9440304b2aSLawrence Brakmo struct bpf_sock_ops_kern *sock_ops, 9540304b2aSLawrence Brakmo enum bpf_attach_type type); 9640304b2aSLawrence Brakmo 97ebc614f6SRoman Gushchin int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor, 98ebc614f6SRoman Gushchin short access, enum bpf_attach_type type); 99ebc614f6SRoman Gushchin 100*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(struct bpf_prog *prog); 101*de9cbbaaSRoman Gushchin void bpf_cgroup_storage_free(struct bpf_cgroup_storage *storage); 102*de9cbbaaSRoman Gushchin void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage, 103*de9cbbaaSRoman Gushchin struct cgroup *cgroup, 104*de9cbbaaSRoman Gushchin enum bpf_attach_type type); 105*de9cbbaaSRoman Gushchin void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage); 106*de9cbbaaSRoman Gushchin int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *map); 107*de9cbbaaSRoman Gushchin void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *map); 108*de9cbbaaSRoman Gushchin 109b2cd1257SDavid Ahern /* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */ 11030070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb) \ 11130070984SDaniel Mack ({ \ 11230070984SDaniel Mack int __ret = 0; \ 11330070984SDaniel Mack if (cgroup_bpf_enabled) \ 114b2cd1257SDavid Ahern __ret = __cgroup_bpf_run_filter_skb(sk, skb, \ 11530070984SDaniel Mack BPF_CGROUP_INET_INGRESS); \ 11630070984SDaniel Mack \ 11730070984SDaniel Mack __ret; \ 11830070984SDaniel Mack }) 11930070984SDaniel Mack 12030070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb) \ 12130070984SDaniel Mack ({ \ 12230070984SDaniel Mack int __ret = 0; \ 12330070984SDaniel Mack if (cgroup_bpf_enabled && sk && sk == skb->sk) { \ 12430070984SDaniel Mack typeof(sk) __sk = sk_to_full_sk(sk); \ 12530070984SDaniel Mack if (sk_fullsock(__sk)) \ 126b2cd1257SDavid Ahern __ret = __cgroup_bpf_run_filter_skb(__sk, skb, \ 12730070984SDaniel Mack BPF_CGROUP_INET_EGRESS); \ 12830070984SDaniel Mack } \ 12930070984SDaniel Mack __ret; \ 13030070984SDaniel Mack }) 13130070984SDaniel Mack 132aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_SK_PROG(sk, type) \ 13361023658SDavid Ahern ({ \ 13461023658SDavid Ahern int __ret = 0; \ 135ee07862fSYafang Shao if (cgroup_bpf_enabled) { \ 136aac3fc32SAndrey Ignatov __ret = __cgroup_bpf_run_filter_sk(sk, type); \ 13761023658SDavid Ahern } \ 13861023658SDavid Ahern __ret; \ 13961023658SDavid Ahern }) 14061023658SDavid Ahern 141aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) \ 142aac3fc32SAndrey Ignatov BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET_SOCK_CREATE) 143aac3fc32SAndrey Ignatov 144aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) \ 145aac3fc32SAndrey Ignatov BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET4_POST_BIND) 146aac3fc32SAndrey Ignatov 147aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) \ 148aac3fc32SAndrey Ignatov BPF_CGROUP_RUN_SK_PROG(sk, BPF_CGROUP_INET6_POST_BIND) 149aac3fc32SAndrey Ignatov 1504fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, type) \ 1514fbac77dSAndrey Ignatov ({ \ 1524fbac77dSAndrey Ignatov int __ret = 0; \ 1534fbac77dSAndrey Ignatov if (cgroup_bpf_enabled) \ 1541cedee13SAndrey Ignatov __ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type, \ 1551cedee13SAndrey Ignatov NULL); \ 1564fbac77dSAndrey Ignatov __ret; \ 1574fbac77dSAndrey Ignatov }) 1584fbac77dSAndrey Ignatov 1591cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, type, t_ctx) \ 160d74bad4eSAndrey Ignatov ({ \ 161d74bad4eSAndrey Ignatov int __ret = 0; \ 162d74bad4eSAndrey Ignatov if (cgroup_bpf_enabled) { \ 163d74bad4eSAndrey Ignatov lock_sock(sk); \ 1641cedee13SAndrey Ignatov __ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, type, \ 1651cedee13SAndrey Ignatov t_ctx); \ 166d74bad4eSAndrey Ignatov release_sock(sk); \ 167d74bad4eSAndrey Ignatov } \ 168d74bad4eSAndrey Ignatov __ret; \ 169d74bad4eSAndrey Ignatov }) 170d74bad4eSAndrey Ignatov 1714fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr) \ 1724fbac77dSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_BIND) 1734fbac77dSAndrey Ignatov 1744fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr) \ 1754fbac77dSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_BIND) 1764fbac77dSAndrey Ignatov 177d74bad4eSAndrey Ignatov #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (cgroup_bpf_enabled && \ 178d74bad4eSAndrey Ignatov sk->sk_prot->pre_connect) 179d74bad4eSAndrey Ignatov 180d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) \ 181d74bad4eSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET4_CONNECT) 182d74bad4eSAndrey Ignatov 183d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) \ 184d74bad4eSAndrey Ignatov BPF_CGROUP_RUN_SA_PROG(sk, uaddr, BPF_CGROUP_INET6_CONNECT) 185d74bad4eSAndrey Ignatov 186d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) \ 1871cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET4_CONNECT, NULL) 188d74bad4eSAndrey Ignatov 189d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) \ 1901cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_INET6_CONNECT, NULL) 1911cedee13SAndrey Ignatov 1921cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) \ 1931cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_SENDMSG, t_ctx) 1941cedee13SAndrey Ignatov 1951cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \ 1961cedee13SAndrey Ignatov BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx) 197d74bad4eSAndrey Ignatov 19840304b2aSLawrence Brakmo #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) \ 19940304b2aSLawrence Brakmo ({ \ 20040304b2aSLawrence Brakmo int __ret = 0; \ 20140304b2aSLawrence Brakmo if (cgroup_bpf_enabled && (sock_ops)->sk) { \ 20240304b2aSLawrence Brakmo typeof(sk) __sk = sk_to_full_sk((sock_ops)->sk); \ 203df39a9f1SWANG Cong if (__sk && sk_fullsock(__sk)) \ 20440304b2aSLawrence Brakmo __ret = __cgroup_bpf_run_filter_sock_ops(__sk, \ 20540304b2aSLawrence Brakmo sock_ops, \ 20640304b2aSLawrence Brakmo BPF_CGROUP_SOCK_OPS); \ 20740304b2aSLawrence Brakmo } \ 20840304b2aSLawrence Brakmo __ret; \ 20940304b2aSLawrence Brakmo }) 210ebc614f6SRoman Gushchin 211ebc614f6SRoman Gushchin #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access) \ 212ebc614f6SRoman Gushchin ({ \ 213ebc614f6SRoman Gushchin int __ret = 0; \ 214ebc614f6SRoman Gushchin if (cgroup_bpf_enabled) \ 215ebc614f6SRoman Gushchin __ret = __cgroup_bpf_check_dev_permission(type, major, minor, \ 216ebc614f6SRoman Gushchin access, \ 217ebc614f6SRoman Gushchin BPF_CGROUP_DEVICE); \ 218ebc614f6SRoman Gushchin \ 219ebc614f6SRoman Gushchin __ret; \ 220ebc614f6SRoman Gushchin }) 221fdb5c453SSean Young int cgroup_bpf_prog_attach(const union bpf_attr *attr, 222fdb5c453SSean Young enum bpf_prog_type ptype, struct bpf_prog *prog); 223fdb5c453SSean Young int cgroup_bpf_prog_detach(const union bpf_attr *attr, 224fdb5c453SSean Young enum bpf_prog_type ptype); 225fdb5c453SSean Young int cgroup_bpf_prog_query(const union bpf_attr *attr, 226fdb5c453SSean Young union bpf_attr __user *uattr); 22730070984SDaniel Mack #else 22830070984SDaniel Mack 229fdb5c453SSean Young struct bpf_prog; 23030070984SDaniel Mack struct cgroup_bpf {}; 23130070984SDaniel Mack static inline void cgroup_bpf_put(struct cgroup *cgrp) {} 232324bda9eSAlexei Starovoitov static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; } 23330070984SDaniel Mack 234fdb5c453SSean Young static inline int cgroup_bpf_prog_attach(const union bpf_attr *attr, 235fdb5c453SSean Young enum bpf_prog_type ptype, 236fdb5c453SSean Young struct bpf_prog *prog) 237fdb5c453SSean Young { 238fdb5c453SSean Young return -EINVAL; 239fdb5c453SSean Young } 240fdb5c453SSean Young 241fdb5c453SSean Young static inline int cgroup_bpf_prog_detach(const union bpf_attr *attr, 242fdb5c453SSean Young enum bpf_prog_type ptype) 243fdb5c453SSean Young { 244fdb5c453SSean Young return -EINVAL; 245fdb5c453SSean Young } 246fdb5c453SSean Young 247fdb5c453SSean Young static inline int cgroup_bpf_prog_query(const union bpf_attr *attr, 248fdb5c453SSean Young union bpf_attr __user *uattr) 249fdb5c453SSean Young { 250fdb5c453SSean Young return -EINVAL; 251fdb5c453SSean Young } 252fdb5c453SSean Young 253*de9cbbaaSRoman Gushchin static inline int bpf_cgroup_storage_assign(struct bpf_prog *prog, 254*de9cbbaaSRoman Gushchin struct bpf_map *map) { return 0; } 255*de9cbbaaSRoman Gushchin static inline void bpf_cgroup_storage_release(struct bpf_prog *prog, 256*de9cbbaaSRoman Gushchin struct bpf_map *map) {} 257*de9cbbaaSRoman Gushchin static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc( 258*de9cbbaaSRoman Gushchin struct bpf_prog *prog) { return 0; } 259*de9cbbaaSRoman Gushchin static inline void bpf_cgroup_storage_free( 260*de9cbbaaSRoman Gushchin struct bpf_cgroup_storage *storage) {} 261*de9cbbaaSRoman Gushchin 26213193b0fSAndrey Ignatov #define cgroup_bpf_enabled (0) 263d74bad4eSAndrey Ignatov #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0) 26430070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) 26530070984SDaniel Mack #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; }) 26661023658SDavid Ahern #define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; }) 2674fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_BIND(sk, uaddr) ({ 0; }) 2684fbac77dSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_BIND(sk, uaddr) ({ 0; }) 269aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) ({ 0; }) 270aac3fc32SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) ({ 0; }) 271d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) ({ 0; }) 272d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) ({ 0; }) 273d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) ({ 0; }) 274d74bad4eSAndrey Ignatov #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; }) 2751cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; }) 2761cedee13SAndrey Ignatov #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; }) 27740304b2aSLawrence Brakmo #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; }) 278ebc614f6SRoman Gushchin #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; }) 27930070984SDaniel Mack 28030070984SDaniel Mack #endif /* CONFIG_CGROUP_BPF */ 28130070984SDaniel Mack 28230070984SDaniel Mack #endif /* _BPF_CGROUP_H */ 283