1604326b4SDaniel Borkmann /* SPDX-License-Identifier: GPL-2.0 */ 2604326b4SDaniel Borkmann /* Copyright (c) 2017 - 2018 Covalent IO, Inc. http://covalent.io */ 3604326b4SDaniel Borkmann 4604326b4SDaniel Borkmann #ifndef _LINUX_SKMSG_H 5604326b4SDaniel Borkmann #define _LINUX_SKMSG_H 6604326b4SDaniel Borkmann 7604326b4SDaniel Borkmann #include <linux/bpf.h> 8604326b4SDaniel Borkmann #include <linux/filter.h> 9604326b4SDaniel Borkmann #include <linux/scatterlist.h> 10604326b4SDaniel Borkmann #include <linux/skbuff.h> 11604326b4SDaniel Borkmann 12604326b4SDaniel Borkmann #include <net/sock.h> 13604326b4SDaniel Borkmann #include <net/tcp.h> 14604326b4SDaniel Borkmann #include <net/strparser.h> 15604326b4SDaniel Borkmann 16604326b4SDaniel Borkmann #define MAX_MSG_FRAGS MAX_SKB_FRAGS 17604326b4SDaniel Borkmann 18604326b4SDaniel Borkmann enum __sk_action { 19604326b4SDaniel Borkmann __SK_DROP = 0, 20604326b4SDaniel Borkmann __SK_PASS, 21604326b4SDaniel Borkmann __SK_REDIRECT, 22604326b4SDaniel Borkmann __SK_NONE, 23604326b4SDaniel Borkmann }; 24604326b4SDaniel Borkmann 25604326b4SDaniel Borkmann struct sk_msg_sg { 26604326b4SDaniel Borkmann u32 start; 27604326b4SDaniel Borkmann u32 curr; 28604326b4SDaniel Borkmann u32 end; 29604326b4SDaniel Borkmann u32 size; 30604326b4SDaniel Borkmann u32 copybreak; 31604326b4SDaniel Borkmann bool copy[MAX_MSG_FRAGS]; 32d3b18ad3SJohn Fastabend /* The extra element is used for chaining the front and sections when 33d3b18ad3SJohn Fastabend * the list becomes partitioned (e.g. end < start). The crypto APIs 34d3b18ad3SJohn Fastabend * require the chaining. 35d3b18ad3SJohn Fastabend */ 36d3b18ad3SJohn Fastabend struct scatterlist data[MAX_MSG_FRAGS + 1]; 37604326b4SDaniel Borkmann }; 38604326b4SDaniel Borkmann 39604326b4SDaniel Borkmann struct sk_msg { 40604326b4SDaniel Borkmann struct sk_msg_sg sg; 41604326b4SDaniel Borkmann void *data; 42604326b4SDaniel Borkmann void *data_end; 43604326b4SDaniel Borkmann u32 apply_bytes; 44604326b4SDaniel Borkmann u32 cork_bytes; 45604326b4SDaniel Borkmann u32 flags; 46604326b4SDaniel Borkmann struct sk_buff *skb; 47604326b4SDaniel Borkmann struct sock *sk_redir; 48604326b4SDaniel Borkmann struct sock *sk; 49604326b4SDaniel Borkmann struct list_head list; 50604326b4SDaniel Borkmann }; 51604326b4SDaniel Borkmann 52604326b4SDaniel Borkmann struct sk_psock_progs { 53604326b4SDaniel Borkmann struct bpf_prog *msg_parser; 54604326b4SDaniel Borkmann struct bpf_prog *skb_parser; 55604326b4SDaniel Borkmann struct bpf_prog *skb_verdict; 56604326b4SDaniel Borkmann }; 57604326b4SDaniel Borkmann 58604326b4SDaniel Borkmann enum sk_psock_state_bits { 59604326b4SDaniel Borkmann SK_PSOCK_TX_ENABLED, 60604326b4SDaniel Borkmann }; 61604326b4SDaniel Borkmann 62604326b4SDaniel Borkmann struct sk_psock_link { 63604326b4SDaniel Borkmann struct list_head list; 64604326b4SDaniel Borkmann struct bpf_map *map; 65604326b4SDaniel Borkmann void *link_raw; 66604326b4SDaniel Borkmann }; 67604326b4SDaniel Borkmann 68604326b4SDaniel Borkmann struct sk_psock_parser { 69604326b4SDaniel Borkmann struct strparser strp; 70604326b4SDaniel Borkmann bool enabled; 71604326b4SDaniel Borkmann void (*saved_data_ready)(struct sock *sk); 72604326b4SDaniel Borkmann }; 73604326b4SDaniel Borkmann 74604326b4SDaniel Borkmann struct sk_psock_work_state { 75604326b4SDaniel Borkmann struct sk_buff *skb; 76604326b4SDaniel Borkmann u32 len; 77604326b4SDaniel Borkmann u32 off; 78604326b4SDaniel Borkmann }; 79604326b4SDaniel Borkmann 80604326b4SDaniel Borkmann struct sk_psock { 81604326b4SDaniel Borkmann struct sock *sk; 82604326b4SDaniel Borkmann struct sock *sk_redir; 83604326b4SDaniel Borkmann u32 apply_bytes; 84604326b4SDaniel Borkmann u32 cork_bytes; 85604326b4SDaniel Borkmann u32 eval; 86604326b4SDaniel Borkmann struct sk_msg *cork; 87604326b4SDaniel Borkmann struct sk_psock_progs progs; 88604326b4SDaniel Borkmann struct sk_psock_parser parser; 89604326b4SDaniel Borkmann struct sk_buff_head ingress_skb; 90604326b4SDaniel Borkmann struct list_head ingress_msg; 91604326b4SDaniel Borkmann unsigned long state; 92604326b4SDaniel Borkmann struct list_head link; 93604326b4SDaniel Borkmann spinlock_t link_lock; 94604326b4SDaniel Borkmann refcount_t refcnt; 95604326b4SDaniel Borkmann void (*saved_unhash)(struct sock *sk); 96604326b4SDaniel Borkmann void (*saved_close)(struct sock *sk, long timeout); 97604326b4SDaniel Borkmann void (*saved_write_space)(struct sock *sk); 98604326b4SDaniel Borkmann struct proto *sk_proto; 99604326b4SDaniel Borkmann struct sk_psock_work_state work_state; 100604326b4SDaniel Borkmann struct work_struct work; 101604326b4SDaniel Borkmann union { 102604326b4SDaniel Borkmann struct rcu_head rcu; 103604326b4SDaniel Borkmann struct work_struct gc; 104604326b4SDaniel Borkmann }; 105604326b4SDaniel Borkmann }; 106604326b4SDaniel Borkmann 107604326b4SDaniel Borkmann int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len, 108604326b4SDaniel Borkmann int elem_first_coalesce); 109d829e9c4SDaniel Borkmann int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src, 110d829e9c4SDaniel Borkmann u32 off, u32 len); 111604326b4SDaniel Borkmann void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len); 112604326b4SDaniel Borkmann int sk_msg_free(struct sock *sk, struct sk_msg *msg); 113604326b4SDaniel Borkmann int sk_msg_free_nocharge(struct sock *sk, struct sk_msg *msg); 114604326b4SDaniel Borkmann void sk_msg_free_partial(struct sock *sk, struct sk_msg *msg, u32 bytes); 115604326b4SDaniel Borkmann void sk_msg_free_partial_nocharge(struct sock *sk, struct sk_msg *msg, 116604326b4SDaniel Borkmann u32 bytes); 117604326b4SDaniel Borkmann 118604326b4SDaniel Borkmann void sk_msg_return(struct sock *sk, struct sk_msg *msg, int bytes); 119d3b18ad3SJohn Fastabend void sk_msg_return_zero(struct sock *sk, struct sk_msg *msg, int bytes); 120604326b4SDaniel Borkmann 121604326b4SDaniel Borkmann int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from, 122604326b4SDaniel Borkmann struct sk_msg *msg, u32 bytes); 123604326b4SDaniel Borkmann int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from, 124604326b4SDaniel Borkmann struct sk_msg *msg, u32 bytes); 125604326b4SDaniel Borkmann 126604326b4SDaniel Borkmann static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes) 127604326b4SDaniel Borkmann { 128604326b4SDaniel Borkmann WARN_ON(i == msg->sg.end && bytes); 129604326b4SDaniel Borkmann } 130604326b4SDaniel Borkmann 131604326b4SDaniel Borkmann static inline void sk_msg_apply_bytes(struct sk_psock *psock, u32 bytes) 132604326b4SDaniel Borkmann { 133604326b4SDaniel Borkmann if (psock->apply_bytes) { 134604326b4SDaniel Borkmann if (psock->apply_bytes < bytes) 135604326b4SDaniel Borkmann psock->apply_bytes = 0; 136604326b4SDaniel Borkmann else 137604326b4SDaniel Borkmann psock->apply_bytes -= bytes; 138604326b4SDaniel Borkmann } 139604326b4SDaniel Borkmann } 140604326b4SDaniel Borkmann 141604326b4SDaniel Borkmann #define sk_msg_iter_var_prev(var) \ 142604326b4SDaniel Borkmann do { \ 143604326b4SDaniel Borkmann if (var == 0) \ 144604326b4SDaniel Borkmann var = MAX_MSG_FRAGS - 1; \ 145604326b4SDaniel Borkmann else \ 146604326b4SDaniel Borkmann var--; \ 147604326b4SDaniel Borkmann } while (0) 148604326b4SDaniel Borkmann 149604326b4SDaniel Borkmann #define sk_msg_iter_var_next(var) \ 150604326b4SDaniel Borkmann do { \ 151604326b4SDaniel Borkmann var++; \ 152604326b4SDaniel Borkmann if (var == MAX_MSG_FRAGS) \ 153604326b4SDaniel Borkmann var = 0; \ 154604326b4SDaniel Borkmann } while (0) 155604326b4SDaniel Borkmann 156604326b4SDaniel Borkmann #define sk_msg_iter_prev(msg, which) \ 157604326b4SDaniel Borkmann sk_msg_iter_var_prev(msg->sg.which) 158604326b4SDaniel Borkmann 159604326b4SDaniel Borkmann #define sk_msg_iter_next(msg, which) \ 160604326b4SDaniel Borkmann sk_msg_iter_var_next(msg->sg.which) 161604326b4SDaniel Borkmann 162604326b4SDaniel Borkmann static inline void sk_msg_clear_meta(struct sk_msg *msg) 163604326b4SDaniel Borkmann { 164604326b4SDaniel Borkmann memset(&msg->sg, 0, offsetofend(struct sk_msg_sg, copy)); 165604326b4SDaniel Borkmann } 166604326b4SDaniel Borkmann 167604326b4SDaniel Borkmann static inline void sk_msg_init(struct sk_msg *msg) 168604326b4SDaniel Borkmann { 169d3b18ad3SJohn Fastabend BUILD_BUG_ON(ARRAY_SIZE(msg->sg.data) - 1 != MAX_MSG_FRAGS); 170604326b4SDaniel Borkmann memset(msg, 0, sizeof(*msg)); 171d3b18ad3SJohn Fastabend sg_init_marker(msg->sg.data, MAX_MSG_FRAGS); 172604326b4SDaniel Borkmann } 173604326b4SDaniel Borkmann 174604326b4SDaniel Borkmann static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src, 175604326b4SDaniel Borkmann int which, u32 size) 176604326b4SDaniel Borkmann { 177604326b4SDaniel Borkmann dst->sg.data[which] = src->sg.data[which]; 178604326b4SDaniel Borkmann dst->sg.data[which].length = size; 1793f4c3127SJohn Fastabend dst->sg.size += size; 180604326b4SDaniel Borkmann src->sg.data[which].length -= size; 181604326b4SDaniel Borkmann src->sg.data[which].offset += size; 182604326b4SDaniel Borkmann } 183604326b4SDaniel Borkmann 184d3b18ad3SJohn Fastabend static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src) 185d3b18ad3SJohn Fastabend { 186d3b18ad3SJohn Fastabend memcpy(dst, src, sizeof(*src)); 187d3b18ad3SJohn Fastabend sk_msg_init(src); 188d3b18ad3SJohn Fastabend } 189d3b18ad3SJohn Fastabend 190604326b4SDaniel Borkmann static inline bool sk_msg_full(const struct sk_msg *msg) 191604326b4SDaniel Borkmann { 192604326b4SDaniel Borkmann return (msg->sg.end == msg->sg.start) && msg->sg.size; 193604326b4SDaniel Borkmann } 194604326b4SDaniel Borkmann 1958734a162SJohn Fastabend static inline u32 sk_msg_elem_used(const struct sk_msg *msg) 1968734a162SJohn Fastabend { 1978734a162SJohn Fastabend if (sk_msg_full(msg)) 1988734a162SJohn Fastabend return MAX_MSG_FRAGS; 1998734a162SJohn Fastabend 2008734a162SJohn Fastabend return msg->sg.end >= msg->sg.start ? 2018734a162SJohn Fastabend msg->sg.end - msg->sg.start : 2028734a162SJohn Fastabend msg->sg.end + (MAX_MSG_FRAGS - msg->sg.start); 2038734a162SJohn Fastabend } 2048734a162SJohn Fastabend 205604326b4SDaniel Borkmann static inline struct scatterlist *sk_msg_elem(struct sk_msg *msg, int which) 206604326b4SDaniel Borkmann { 207604326b4SDaniel Borkmann return &msg->sg.data[which]; 208604326b4SDaniel Borkmann } 209604326b4SDaniel Borkmann 210604326b4SDaniel Borkmann static inline struct page *sk_msg_page(struct sk_msg *msg, int which) 211604326b4SDaniel Borkmann { 212604326b4SDaniel Borkmann return sg_page(sk_msg_elem(msg, which)); 213604326b4SDaniel Borkmann } 214604326b4SDaniel Borkmann 215604326b4SDaniel Borkmann static inline bool sk_msg_to_ingress(const struct sk_msg *msg) 216604326b4SDaniel Borkmann { 217604326b4SDaniel Borkmann return msg->flags & BPF_F_INGRESS; 218604326b4SDaniel Borkmann } 219604326b4SDaniel Borkmann 220604326b4SDaniel Borkmann static inline void sk_msg_compute_data_pointers(struct sk_msg *msg) 221604326b4SDaniel Borkmann { 222604326b4SDaniel Borkmann struct scatterlist *sge = sk_msg_elem(msg, msg->sg.start); 223604326b4SDaniel Borkmann 224604326b4SDaniel Borkmann if (msg->sg.copy[msg->sg.start]) { 225604326b4SDaniel Borkmann msg->data = NULL; 226604326b4SDaniel Borkmann msg->data_end = NULL; 227604326b4SDaniel Borkmann } else { 228604326b4SDaniel Borkmann msg->data = sg_virt(sge); 229604326b4SDaniel Borkmann msg->data_end = msg->data + sge->length; 230604326b4SDaniel Borkmann } 231604326b4SDaniel Borkmann } 232604326b4SDaniel Borkmann 233604326b4SDaniel Borkmann static inline void sk_msg_page_add(struct sk_msg *msg, struct page *page, 234604326b4SDaniel Borkmann u32 len, u32 offset) 235604326b4SDaniel Borkmann { 236604326b4SDaniel Borkmann struct scatterlist *sge; 237604326b4SDaniel Borkmann 238604326b4SDaniel Borkmann get_page(page); 239604326b4SDaniel Borkmann sge = sk_msg_elem(msg, msg->sg.end); 240604326b4SDaniel Borkmann sg_set_page(sge, page, len, offset); 241604326b4SDaniel Borkmann sg_unmark_end(sge); 242604326b4SDaniel Borkmann 243604326b4SDaniel Borkmann msg->sg.copy[msg->sg.end] = true; 244604326b4SDaniel Borkmann msg->sg.size += len; 245604326b4SDaniel Borkmann sk_msg_iter_next(msg, end); 246604326b4SDaniel Borkmann } 247604326b4SDaniel Borkmann 248d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state) 249d3b18ad3SJohn Fastabend { 250d3b18ad3SJohn Fastabend do { 251d3b18ad3SJohn Fastabend msg->sg.copy[i] = copy_state; 252d3b18ad3SJohn Fastabend sk_msg_iter_var_next(i); 253d3b18ad3SJohn Fastabend if (i == msg->sg.end) 254d3b18ad3SJohn Fastabend break; 255d3b18ad3SJohn Fastabend } while (1); 256d3b18ad3SJohn Fastabend } 257d3b18ad3SJohn Fastabend 258d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start) 259d3b18ad3SJohn Fastabend { 260d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, true); 261d3b18ad3SJohn Fastabend } 262d3b18ad3SJohn Fastabend 263d3b18ad3SJohn Fastabend static inline void sk_msg_sg_copy_clear(struct sk_msg *msg, u32 start) 264d3b18ad3SJohn Fastabend { 265d3b18ad3SJohn Fastabend sk_msg_sg_copy(msg, start, false); 266d3b18ad3SJohn Fastabend } 267d3b18ad3SJohn Fastabend 268604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock(const struct sock *sk) 269604326b4SDaniel Borkmann { 270604326b4SDaniel Borkmann return rcu_dereference_sk_user_data(sk); 271604326b4SDaniel Borkmann } 272604326b4SDaniel Borkmann 273604326b4SDaniel Borkmann static inline void sk_psock_queue_msg(struct sk_psock *psock, 274604326b4SDaniel Borkmann struct sk_msg *msg) 275604326b4SDaniel Borkmann { 276604326b4SDaniel Borkmann list_add_tail(&msg->list, &psock->ingress_msg); 277604326b4SDaniel Borkmann } 278604326b4SDaniel Borkmann 279d3b18ad3SJohn Fastabend static inline bool sk_psock_queue_empty(const struct sk_psock *psock) 280d3b18ad3SJohn Fastabend { 281d3b18ad3SJohn Fastabend return psock ? list_empty(&psock->ingress_msg) : true; 282d3b18ad3SJohn Fastabend } 283d3b18ad3SJohn Fastabend 284604326b4SDaniel Borkmann static inline void sk_psock_report_error(struct sk_psock *psock, int err) 285604326b4SDaniel Borkmann { 286604326b4SDaniel Borkmann struct sock *sk = psock->sk; 287604326b4SDaniel Borkmann 288604326b4SDaniel Borkmann sk->sk_err = err; 289604326b4SDaniel Borkmann sk->sk_error_report(sk); 290604326b4SDaniel Borkmann } 291604326b4SDaniel Borkmann 292604326b4SDaniel Borkmann struct sk_psock *sk_psock_init(struct sock *sk, int node); 293604326b4SDaniel Borkmann 294604326b4SDaniel Borkmann int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock); 295604326b4SDaniel Borkmann void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock); 296604326b4SDaniel Borkmann void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock); 297604326b4SDaniel Borkmann 298604326b4SDaniel Borkmann int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, 299604326b4SDaniel Borkmann struct sk_msg *msg); 300604326b4SDaniel Borkmann 301604326b4SDaniel Borkmann static inline struct sk_psock_link *sk_psock_init_link(void) 302604326b4SDaniel Borkmann { 303604326b4SDaniel Borkmann return kzalloc(sizeof(struct sk_psock_link), 304604326b4SDaniel Borkmann GFP_ATOMIC | __GFP_NOWARN); 305604326b4SDaniel Borkmann } 306604326b4SDaniel Borkmann 307604326b4SDaniel Borkmann static inline void sk_psock_free_link(struct sk_psock_link *link) 308604326b4SDaniel Borkmann { 309604326b4SDaniel Borkmann kfree(link); 310604326b4SDaniel Borkmann } 311604326b4SDaniel Borkmann 312604326b4SDaniel Borkmann struct sk_psock_link *sk_psock_link_pop(struct sk_psock *psock); 313604326b4SDaniel Borkmann #if defined(CONFIG_BPF_STREAM_PARSER) 314604326b4SDaniel Borkmann void sk_psock_unlink(struct sock *sk, struct sk_psock_link *link); 315604326b4SDaniel Borkmann #else 316604326b4SDaniel Borkmann static inline void sk_psock_unlink(struct sock *sk, 317604326b4SDaniel Borkmann struct sk_psock_link *link) 318604326b4SDaniel Borkmann { 319604326b4SDaniel Borkmann } 320604326b4SDaniel Borkmann #endif 321604326b4SDaniel Borkmann 322604326b4SDaniel Borkmann void __sk_psock_purge_ingress_msg(struct sk_psock *psock); 323604326b4SDaniel Borkmann 324604326b4SDaniel Borkmann static inline void sk_psock_cork_free(struct sk_psock *psock) 325604326b4SDaniel Borkmann { 326604326b4SDaniel Borkmann if (psock->cork) { 327604326b4SDaniel Borkmann sk_msg_free(psock->sk, psock->cork); 328604326b4SDaniel Borkmann kfree(psock->cork); 329604326b4SDaniel Borkmann psock->cork = NULL; 330604326b4SDaniel Borkmann } 331604326b4SDaniel Borkmann } 332604326b4SDaniel Borkmann 333604326b4SDaniel Borkmann static inline void sk_psock_update_proto(struct sock *sk, 334604326b4SDaniel Borkmann struct sk_psock *psock, 335604326b4SDaniel Borkmann struct proto *ops) 336604326b4SDaniel Borkmann { 337604326b4SDaniel Borkmann psock->saved_unhash = sk->sk_prot->unhash; 338604326b4SDaniel Borkmann psock->saved_close = sk->sk_prot->close; 339604326b4SDaniel Borkmann psock->saved_write_space = sk->sk_write_space; 340604326b4SDaniel Borkmann 341604326b4SDaniel Borkmann psock->sk_proto = sk->sk_prot; 342604326b4SDaniel Borkmann sk->sk_prot = ops; 343604326b4SDaniel Borkmann } 344604326b4SDaniel Borkmann 345604326b4SDaniel Borkmann static inline void sk_psock_restore_proto(struct sock *sk, 346604326b4SDaniel Borkmann struct sk_psock *psock) 347604326b4SDaniel Borkmann { 348604326b4SDaniel Borkmann if (psock->sk_proto) { 349604326b4SDaniel Borkmann sk->sk_prot = psock->sk_proto; 350604326b4SDaniel Borkmann psock->sk_proto = NULL; 351604326b4SDaniel Borkmann } 352604326b4SDaniel Borkmann } 353604326b4SDaniel Borkmann 354604326b4SDaniel Borkmann static inline void sk_psock_set_state(struct sk_psock *psock, 355604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 356604326b4SDaniel Borkmann { 357604326b4SDaniel Borkmann set_bit(bit, &psock->state); 358604326b4SDaniel Borkmann } 359604326b4SDaniel Borkmann 360604326b4SDaniel Borkmann static inline void sk_psock_clear_state(struct sk_psock *psock, 361604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 362604326b4SDaniel Borkmann { 363604326b4SDaniel Borkmann clear_bit(bit, &psock->state); 364604326b4SDaniel Borkmann } 365604326b4SDaniel Borkmann 366604326b4SDaniel Borkmann static inline bool sk_psock_test_state(const struct sk_psock *psock, 367604326b4SDaniel Borkmann enum sk_psock_state_bits bit) 368604326b4SDaniel Borkmann { 369604326b4SDaniel Borkmann return test_bit(bit, &psock->state); 370604326b4SDaniel Borkmann } 371604326b4SDaniel Borkmann 372*5032d079SJohn Fastabend static inline struct sk_psock *sk_psock_get_checked(struct sock *sk) 373*5032d079SJohn Fastabend { 374*5032d079SJohn Fastabend struct sk_psock *psock; 375*5032d079SJohn Fastabend 376*5032d079SJohn Fastabend rcu_read_lock(); 377*5032d079SJohn Fastabend psock = sk_psock(sk); 378*5032d079SJohn Fastabend if (psock) { 379*5032d079SJohn Fastabend if (sk->sk_prot->recvmsg != tcp_bpf_recvmsg) { 380*5032d079SJohn Fastabend psock = ERR_PTR(-EBUSY); 381*5032d079SJohn Fastabend goto out; 382*5032d079SJohn Fastabend } 383*5032d079SJohn Fastabend 384*5032d079SJohn Fastabend if (!refcount_inc_not_zero(&psock->refcnt)) 385*5032d079SJohn Fastabend psock = ERR_PTR(-EBUSY); 386*5032d079SJohn Fastabend } 387*5032d079SJohn Fastabend out: 388*5032d079SJohn Fastabend rcu_read_unlock(); 389*5032d079SJohn Fastabend return psock; 390*5032d079SJohn Fastabend } 391*5032d079SJohn Fastabend 392604326b4SDaniel Borkmann static inline struct sk_psock *sk_psock_get(struct sock *sk) 393604326b4SDaniel Borkmann { 394604326b4SDaniel Borkmann struct sk_psock *psock; 395604326b4SDaniel Borkmann 396604326b4SDaniel Borkmann rcu_read_lock(); 397604326b4SDaniel Borkmann psock = sk_psock(sk); 398604326b4SDaniel Borkmann if (psock && !refcount_inc_not_zero(&psock->refcnt)) 399604326b4SDaniel Borkmann psock = NULL; 400604326b4SDaniel Borkmann rcu_read_unlock(); 401604326b4SDaniel Borkmann return psock; 402604326b4SDaniel Borkmann } 403604326b4SDaniel Borkmann 404604326b4SDaniel Borkmann void sk_psock_stop(struct sock *sk, struct sk_psock *psock); 405604326b4SDaniel Borkmann void sk_psock_destroy(struct rcu_head *rcu); 406604326b4SDaniel Borkmann void sk_psock_drop(struct sock *sk, struct sk_psock *psock); 407604326b4SDaniel Borkmann 408604326b4SDaniel Borkmann static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock) 409604326b4SDaniel Borkmann { 410604326b4SDaniel Borkmann if (refcount_dec_and_test(&psock->refcnt)) 411604326b4SDaniel Borkmann sk_psock_drop(sk, psock); 412604326b4SDaniel Borkmann } 413604326b4SDaniel Borkmann 414604326b4SDaniel Borkmann static inline void psock_set_prog(struct bpf_prog **pprog, 415604326b4SDaniel Borkmann struct bpf_prog *prog) 416604326b4SDaniel Borkmann { 417604326b4SDaniel Borkmann prog = xchg(pprog, prog); 418604326b4SDaniel Borkmann if (prog) 419604326b4SDaniel Borkmann bpf_prog_put(prog); 420604326b4SDaniel Borkmann } 421604326b4SDaniel Borkmann 422604326b4SDaniel Borkmann static inline void psock_progs_drop(struct sk_psock_progs *progs) 423604326b4SDaniel Borkmann { 424604326b4SDaniel Borkmann psock_set_prog(&progs->msg_parser, NULL); 425604326b4SDaniel Borkmann psock_set_prog(&progs->skb_parser, NULL); 426604326b4SDaniel Borkmann psock_set_prog(&progs->skb_verdict, NULL); 427604326b4SDaniel Borkmann } 428604326b4SDaniel Borkmann 429604326b4SDaniel Borkmann #endif /* _LINUX_SKMSG_H */ 430