Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19-rc6 294 lines 6.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <linux/file.h> 4#include <linux/net.h> 5#include <linux/rcupdate.h> 6#include <linux/tcp.h> 7 8#include <net/ip.h> 9#include <net/psp.h> 10#include "psp.h" 11 12struct psp_dev *psp_dev_get_for_sock(struct sock *sk) 13{ 14 struct psp_dev *psd = NULL; 15 struct dst_entry *dst; 16 17 rcu_read_lock(); 18 dst = __sk_dst_get(sk); 19 if (dst) { 20 psd = rcu_dereference(dst_dev_rcu(dst)->psp_dev); 21 if (psd && !psp_dev_tryget(psd)) 22 psd = NULL; 23 } 24 rcu_read_unlock(); 25 26 return psd; 27} 28 29static struct sk_buff * 30psp_validate_xmit(struct sock *sk, struct net_device *dev, struct sk_buff *skb) 31{ 32 struct psp_assoc *pas; 33 bool good; 34 35 rcu_read_lock(); 36 pas = psp_skb_get_assoc_rcu(skb); 37 good = !pas || rcu_access_pointer(dev->psp_dev) == pas->psd; 38 rcu_read_unlock(); 39 if (!good) { 40 sk_skb_reason_drop(sk, skb, SKB_DROP_REASON_PSP_OUTPUT); 41 return NULL; 42 } 43 44 return skb; 45} 46 47struct psp_assoc *psp_assoc_create(struct psp_dev *psd) 48{ 49 struct psp_assoc *pas; 50 51 lockdep_assert_held(&psd->lock); 52 53 pas = kzalloc(struct_size(pas, drv_data, psd->caps->assoc_drv_spc), 54 GFP_KERNEL_ACCOUNT); 55 if (!pas) 56 return NULL; 57 58 pas->psd = psd; 59 pas->dev_id = psd->id; 60 pas->generation = psd->generation; 61 psp_dev_get(psd); 62 refcount_set(&pas->refcnt, 1); 63 64 list_add_tail(&pas->assocs_list, &psd->active_assocs); 65 66 return pas; 67} 68 69static struct psp_assoc *psp_assoc_dummy(struct psp_assoc *pas) 70{ 71 struct psp_dev *psd = pas->psd; 72 size_t sz; 73 74 lockdep_assert_held(&psd->lock); 75 76 sz = struct_size(pas, drv_data, psd->caps->assoc_drv_spc); 77 return kmemdup(pas, sz, GFP_KERNEL); 78} 79 80static int psp_dev_tx_key_add(struct psp_dev *psd, struct psp_assoc *pas, 81 struct netlink_ext_ack *extack) 82{ 83 return psd->ops->tx_key_add(psd, pas, extack); 84} 85 86void psp_dev_tx_key_del(struct psp_dev *psd, struct psp_assoc *pas) 87{ 88 if (pas->tx.spi) 89 psd->ops->tx_key_del(psd, pas); 90 list_del(&pas->assocs_list); 91} 92 93static void psp_assoc_free(struct work_struct *work) 94{ 95 struct psp_assoc *pas = container_of(work, struct psp_assoc, work); 96 struct psp_dev *psd = pas->psd; 97 98 mutex_lock(&psd->lock); 99 if (psd->ops) 100 psp_dev_tx_key_del(psd, pas); 101 mutex_unlock(&psd->lock); 102 psp_dev_put(psd); 103 kfree(pas); 104} 105 106static void psp_assoc_free_queue(struct rcu_head *head) 107{ 108 struct psp_assoc *pas = container_of(head, struct psp_assoc, rcu); 109 110 INIT_WORK(&pas->work, psp_assoc_free); 111 schedule_work(&pas->work); 112} 113 114/** 115 * psp_assoc_put() - release a reference on a PSP association 116 * @pas: association to release 117 */ 118void psp_assoc_put(struct psp_assoc *pas) 119{ 120 if (pas && refcount_dec_and_test(&pas->refcnt)) 121 call_rcu(&pas->rcu, psp_assoc_free_queue); 122} 123 124void psp_sk_assoc_free(struct sock *sk) 125{ 126 struct psp_assoc *pas = rcu_dereference_protected(sk->psp_assoc, 1); 127 128 rcu_assign_pointer(sk->psp_assoc, NULL); 129 psp_assoc_put(pas); 130} 131 132int psp_sock_assoc_set_rx(struct sock *sk, struct psp_assoc *pas, 133 struct psp_key_parsed *key, 134 struct netlink_ext_ack *extack) 135{ 136 int err; 137 138 memcpy(&pas->rx, key, sizeof(*key)); 139 140 lock_sock(sk); 141 142 if (psp_sk_assoc(sk)) { 143 NL_SET_ERR_MSG(extack, "Socket already has PSP state"); 144 err = -EBUSY; 145 goto exit_unlock; 146 } 147 148 refcount_inc(&pas->refcnt); 149 rcu_assign_pointer(sk->psp_assoc, pas); 150 err = 0; 151 152exit_unlock: 153 release_sock(sk); 154 155 return err; 156} 157 158static int psp_sock_recv_queue_check(struct sock *sk, struct psp_assoc *pas) 159{ 160 struct psp_skb_ext *pse; 161 struct sk_buff *skb; 162 163 skb_rbtree_walk(skb, &tcp_sk(sk)->out_of_order_queue) { 164 pse = skb_ext_find(skb, SKB_EXT_PSP); 165 if (!psp_pse_matches_pas(pse, pas)) 166 return -EBUSY; 167 } 168 169 skb_queue_walk(&sk->sk_receive_queue, skb) { 170 pse = skb_ext_find(skb, SKB_EXT_PSP); 171 if (!psp_pse_matches_pas(pse, pas)) 172 return -EBUSY; 173 } 174 return 0; 175} 176 177int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, 178 u32 version, struct psp_key_parsed *key, 179 struct netlink_ext_ack *extack) 180{ 181 struct inet_connection_sock *icsk; 182 struct psp_assoc *pas, *dummy; 183 int err; 184 185 lock_sock(sk); 186 187 pas = psp_sk_assoc(sk); 188 if (!pas) { 189 NL_SET_ERR_MSG(extack, "Socket has no Rx key"); 190 err = -EINVAL; 191 goto exit_unlock; 192 } 193 if (pas->psd != psd) { 194 NL_SET_ERR_MSG(extack, "Rx key from different device"); 195 err = -EINVAL; 196 goto exit_unlock; 197 } 198 if (pas->version != version) { 199 NL_SET_ERR_MSG(extack, 200 "PSP version mismatch with existing state"); 201 err = -EINVAL; 202 goto exit_unlock; 203 } 204 if (pas->tx.spi) { 205 NL_SET_ERR_MSG(extack, "Tx key already set"); 206 err = -EBUSY; 207 goto exit_unlock; 208 } 209 210 err = psp_sock_recv_queue_check(sk, pas); 211 if (err) { 212 NL_SET_ERR_MSG(extack, "Socket has incompatible segments already in the recv queue"); 213 goto exit_unlock; 214 } 215 216 /* Pass a fake association to drivers to make sure they don't 217 * try to store pointers to it. For re-keying we'll need to 218 * re-allocate the assoc structures. 219 */ 220 dummy = psp_assoc_dummy(pas); 221 if (!dummy) { 222 err = -ENOMEM; 223 goto exit_unlock; 224 } 225 226 memcpy(&dummy->tx, key, sizeof(*key)); 227 err = psp_dev_tx_key_add(psd, dummy, extack); 228 if (err) 229 goto exit_free_dummy; 230 231 memcpy(pas->drv_data, dummy->drv_data, psd->caps->assoc_drv_spc); 232 memcpy(&pas->tx, key, sizeof(*key)); 233 234 WRITE_ONCE(sk->sk_validate_xmit_skb, psp_validate_xmit); 235 tcp_write_collapse_fence(sk); 236 pas->upgrade_seq = tcp_sk(sk)->rcv_nxt; 237 238 icsk = inet_csk(sk); 239 icsk->icsk_ext_hdr_len += psp_sk_overhead(sk); 240 icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); 241 242exit_free_dummy: 243 kfree(dummy); 244exit_unlock: 245 release_sock(sk); 246 return err; 247} 248 249void psp_assocs_key_rotated(struct psp_dev *psd) 250{ 251 struct psp_assoc *pas, *next; 252 253 /* Mark the stale associations as invalid, they will no longer 254 * be able to Rx any traffic. 255 */ 256 list_for_each_entry_safe(pas, next, &psd->prev_assocs, assocs_list) { 257 pas->generation |= ~PSP_GEN_VALID_MASK; 258 psd->stats.stales++; 259 } 260 list_splice_init(&psd->prev_assocs, &psd->stale_assocs); 261 list_splice_init(&psd->active_assocs, &psd->prev_assocs); 262 263 /* TODO: we should inform the sockets that got shut down */ 264} 265 266void psp_twsk_init(struct inet_timewait_sock *tw, const struct sock *sk) 267{ 268 struct psp_assoc *pas = psp_sk_assoc(sk); 269 270 if (pas) 271 refcount_inc(&pas->refcnt); 272 rcu_assign_pointer(tw->psp_assoc, pas); 273 tw->tw_validate_xmit_skb = psp_validate_xmit; 274} 275 276void psp_twsk_assoc_free(struct inet_timewait_sock *tw) 277{ 278 struct psp_assoc *pas = rcu_dereference_protected(tw->psp_assoc, 1); 279 280 rcu_assign_pointer(tw->psp_assoc, NULL); 281 psp_assoc_put(pas); 282} 283 284void psp_reply_set_decrypted(const struct sock *sk, struct sk_buff *skb) 285{ 286 struct psp_assoc *pas; 287 288 rcu_read_lock(); 289 pas = psp_sk_get_assoc_rcu(sk); 290 if (pas && pas->tx.spi) 291 skb->decrypted = 1; 292 rcu_read_unlock(); 293} 294EXPORT_IPV6_MOD_GPL(psp_reply_set_decrypted);