diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-09-07 16:38:39 -0700 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-09-07 16:38:40 -0700 |
| commit | d54ba079bb4f411d89ffe54ada1634cf3f896fe2 (patch) | |
| tree | bdd20a1cb70403278a7afe59d193146ab8d698ac | |
| parent | 31f961de2f90fbf52eb2d4e15b3eeaa09f9b4fc2 (diff) | |
| parent | da630d1da2b19442c337bcbe3bb3fa66fda1f5bb (diff) | |
| download | linux-next-d54ba079bb4f411d89ffe54ada1634cf3f896fe2.tar.gz linux-next-d54ba079bb4f411d89ffe54ada1634cf3f896fe2.zip | |
Merge branch 'psp-make-tx-key-ops-optional-for-drivers'
Daniel Zahka says:
====================
psp: make tx key ops optional for drivers
This is the first of two series which together implement rekeying PSP
protected tcp connections. Here are both series together on github:
https://github.com/danieldzahka/linux/commits/psp-rekey-split/
This first series is mostly non-functional changes, except for the minor
difference that netdevsim driver implements tx key ops. Its tx key ops
were basically NOPs, and in the future PSP core can subsume the assoc
counting that it was doing.
The purpose of the refactors is to make code reusable from paths that
will be added to the code in the rekeying series.
Patch 1 exists to setup two paths for tx key deletion, one where keys
are deleted as they are now in psp_assoc_free() when the assoc refcount
drops to 0, and a different path in series two, where the keys will get
put onto a queue for deferred deletion.
Patch 2 exists to allow tx assoc state to be set either from the
connection setup path, or in series two, from a tx rekeying path.
Patch 3 makes implementing tx_key_add and tx_key_del optional for
drivers. These callbacks only make sense for devices that utilize a tx
SADB. This distinction is important once rekeying is involved, because
an SADB implies a race between in flight tx packets and key deletion,
that does not exist for non-SADB implementations.
Patch 4 removes the unnecessary tx key ops in netdevsim.
No new tests are added to this series. There is no real user visible
change of behavior.
====================
Link: https://patch.msgid.link/20260903-psp-prep-v1-0-d47e9c4c375d@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/net/netdevsim/netdevsim.h | 1 | ||||
| -rw-r--r-- | drivers/net/netdevsim/psp.c | 33 | ||||
| -rw-r--r-- | include/net/psp/functions.h | 5 | ||||
| -rw-r--r-- | include/net/psp/types.h | 4 | ||||
| -rw-r--r-- | net/psp/psp.h | 12 | ||||
| -rw-r--r-- | net/psp/psp_main.c | 13 | ||||
| -rw-r--r-- | net/psp/psp_sock.c | 115 |
7 files changed, 97 insertions, 86 deletions
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 55aec41237b9..181b6baaba7a 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -122,7 +122,6 @@ struct netdevsim { struct dentry *rereg; struct mutex rereg_lock; u32 spi; - u32 assoc_cnt; } psp; struct nsim_bus_dev *nsim_bus_dev; diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c index 6b3532b5e360..b7452c49b581 100644 --- a/drivers/net/netdevsim/psp.c +++ b/drivers/net/netdevsim/psp.c @@ -23,7 +23,6 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns, struct psp_assoc *pas; struct net *net; int psp_len; - void **ptr; rcu_read_lock(); pas = psp_skb_get_assoc_rcu(skb); @@ -37,12 +36,6 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns, goto out_unlock; } - ptr = psp_assoc_drv_data(pas); - if (*ptr != ns) { - rc = SKB_DROP_REASON_PSP_OUTPUT; - goto out_unlock; - } - net = sock_net(skb->sk); if (!psp_dev_encapsulate(net, skb, pas->tx.spi, pas->version, 0)) { rc = SKB_DROP_REASON_PSP_OUTPUT; @@ -149,19 +142,6 @@ nsim_rx_spi_alloc(struct psp_dev *psd, u32 version, return 0; } -static int nsim_assoc_add(struct psp_dev *psd, struct psp_assoc *pas, - struct netlink_ext_ack *extack) -{ - struct netdevsim *ns = psd->drv_priv; - void **ptr = psp_assoc_drv_data(pas); - - /* Copy drv_priv from psd to assoc */ - *ptr = psd->drv_priv; - ns->psp.assoc_cnt++; - - return 0; -} - static int nsim_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *extack) { struct netdevsim *ns = psd->drv_priv; @@ -177,15 +157,6 @@ static int nsim_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *extack) return 0; } -static void nsim_assoc_del(struct psp_dev *psd, struct psp_assoc *pas) -{ - struct netdevsim *ns = psd->drv_priv; - void **ptr = psp_assoc_drv_data(pas); - - *ptr = NULL; - ns->psp.assoc_cnt--; -} - static void nsim_get_stats(struct psp_dev *psd, struct psp_dev_stats *stats) { struct netdevsim *ns = psd->drv_priv; @@ -204,8 +175,6 @@ static void nsim_get_stats(struct psp_dev *psd, struct psp_dev_stats *stats) static struct psp_dev_ops nsim_psp_ops = { .set_config = nsim_psp_set_config, .rx_spi_alloc = nsim_rx_spi_alloc, - .tx_key_add = nsim_assoc_add, - .tx_key_del = nsim_assoc_del, .key_rotate = nsim_key_rotate, .get_stats = nsim_get_stats, }; @@ -215,7 +184,6 @@ static struct psp_dev_caps nsim_psp_caps = { 1 << PSP_VERSION_HDR0_AES_GMAC_128 | 1 << PSP_VERSION_HDR0_AES_GCM_256 | 1 << PSP_VERSION_HDR0_AES_GMAC_256, - .assoc_drv_spc = sizeof(void *), }; static void __nsim_psp_uninit(struct netdevsim *ns, bool teardown) @@ -230,7 +198,6 @@ static void __nsim_psp_uninit(struct netdevsim *ns, bool teardown) synchronize_rcu(); psp_dev_unregister(psd); } - WARN_ON(ns->psp.assoc_cnt); } void nsim_psp_uninit(struct netdevsim *ns) diff --git a/include/net/psp/functions.h b/include/net/psp/functions.h index c5c23a54774e..b23c30898389 100644 --- a/include/net/psp/functions.h +++ b/include/net/psp/functions.h @@ -24,11 +24,6 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv); /* Kernel-facing API */ void psp_assoc_put(struct psp_assoc *pas); -static inline void *psp_assoc_drv_data(struct psp_assoc *pas) -{ - return pas->drv_data; -} - #if IS_ENABLED(CONFIG_INET_PSP) unsigned int psp_key_size(u32 version); void psp_sk_assoc_free(struct sock *sk); diff --git a/include/net/psp/types.h b/include/net/psp/types.h index 87991a1ea02d..b8905efbd604 100644 --- a/include/net/psp/types.h +++ b/include/net/psp/types.h @@ -219,12 +219,16 @@ struct psp_dev_ops { * @tx_key_add: add a Tx key to the device * Install an association in the device. Core will allocate space * for the driver to use at drv_data. + * Can be left NULL if device does not store Tx keys and @tx_key_del + * is also NULL. */ int (*tx_key_add)(struct psp_dev *psd, struct psp_assoc *pas, struct netlink_ext_ack *extack); /** * @tx_key_del: remove a Tx key from the device * Remove an association from the device. + * Can be left NULL if device does not store Tx keys and @tx_key_add + * is also NULL. */ void (*tx_key_del)(struct psp_dev *psd, struct psp_assoc *pas); diff --git a/net/psp/psp.h b/net/psp/psp.h index 86eeba823ced..bbb39e2f5b0a 100644 --- a/net/psp/psp.h +++ b/net/psp/psp.h @@ -53,4 +53,16 @@ static inline bool psp_dev_is_registered(struct psp_dev *psd) return !!psd->ops; } +static inline bool psp_dev_has_sadb(struct psp_dev *psd) +{ + lockdep_assert_held(&psd->lock); + return !!psd->ops->tx_key_del; +} + +static inline bool psp_assoc_needs_tx_key_del(struct psp_assoc *pas) +{ + lockdep_assert_held(&pas->psd->lock); + return psp_dev_has_sadb(pas->psd) && pas->tx.spi; +} + #endif /* __PSP_PSP_H */ diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index c9c1a8826b7f..91473f96ad21 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -68,9 +68,9 @@ psp_dev_create(struct net_device *netdev, !psd_ops->set_config || !psd_ops->key_rotate || !psd_ops->rx_spi_alloc || - !psd_ops->tx_key_add || - !psd_ops->tx_key_del || - !psd_ops->get_stats)) + !psd_ops->get_stats || + (!psd_ops->tx_key_add != !psd_ops->tx_key_del) || + (psd_caps->assoc_drv_spc && !psd_ops->tx_key_add))) return ERR_PTR(-EINVAL); psd = kzalloc_obj(*psd); @@ -147,8 +147,11 @@ void psp_dev_unregister(struct psp_dev *psd) list_splice_init(&psd->active_assocs, &psd->prev_assocs); list_splice_init(&psd->prev_assocs, &psd->stale_assocs); - list_for_each_entry_safe(pas, next, &psd->stale_assocs, assocs_list) - psp_dev_tx_key_del(psd, pas); + list_for_each_entry_safe(pas, next, &psd->stale_assocs, assocs_list) { + if (psp_assoc_needs_tx_key_del(pas)) + psp_dev_tx_key_del(psd, pas); + list_del(&pas->assocs_list); + } list_for_each_entry_safe(entry, entry_tmp, &psd->assoc_dev_list, dev_list) { diff --git a/net/psp/psp_sock.c b/net/psp/psp_sock.c index 1a2a6b7516b0..6a4becc38b55 100644 --- a/net/psp/psp_sock.c +++ b/net/psp/psp_sock.c @@ -78,16 +78,33 @@ static struct psp_assoc *psp_assoc_dummy(struct psp_assoc *pas) } static int psp_dev_tx_key_add(struct psp_dev *psd, struct psp_assoc *pas, + struct psp_key_parsed *key, struct netlink_ext_ack *extack) { - return psd->ops->tx_key_add(psd, pas, extack); + struct psp_assoc *dummy; + int err; + + /* Pass a fake association to drivers to make sure they don't + * try to store pointers to it. For re-keying we'll need to + * re-allocate the assoc structures. + */ + dummy = psp_assoc_dummy(pas); + if (!dummy) + return -ENOMEM; + + memcpy(&dummy->tx, key, sizeof(*key)); + err = psd->ops->tx_key_add(psd, dummy, extack); + if (!err) + memcpy(pas->drv_data, dummy->drv_data, + psd->caps->assoc_drv_spc); + + kfree(dummy); + return err; } void psp_dev_tx_key_del(struct psp_dev *psd, struct psp_assoc *pas) { - if (pas->tx.spi) - psd->ops->tx_key_del(psd, pas); - list_del(&pas->assocs_list); + psd->ops->tx_key_del(psd, pas); } static void psp_assoc_free(struct work_struct *work) @@ -96,8 +113,11 @@ static void psp_assoc_free(struct work_struct *work) struct psp_dev *psd = pas->psd; mutex_lock(&psd->lock); - if (psp_dev_is_registered(psd)) - psp_dev_tx_key_del(psd, pas); + if (psp_dev_is_registered(psd)) { + if (psp_assoc_needs_tx_key_del(pas)) + psp_dev_tx_key_del(psd, pas); + list_del(&pas->assocs_list); + } mutex_unlock(&psd->lock); psp_dev_put(psd); kfree(pas); @@ -155,6 +175,22 @@ exit_unlock: return err; } +static int psp_assoc_set_tx(struct psp_dev *psd, struct psp_assoc *pas, + struct psp_key_parsed *key, + struct netlink_ext_ack *extack) +{ + int err; + + if (psp_dev_has_sadb(psd)) { + err = psp_dev_tx_key_add(psd, pas, key, extack); + if (err) + return err; + } + + memcpy(&pas->tx, key, sizeof(*key)); + return 0; +} + static int psp_sock_recv_queue_check(struct sock *sk, struct psp_assoc *pas) { struct psp_skb_ext *pse; @@ -174,12 +210,40 @@ static int psp_sock_recv_queue_check(struct sock *sk, struct psp_assoc *pas) return 0; } +static int +psp_sock_set_tx_key(struct sock *sk, struct psp_dev *psd, struct psp_assoc *pas, + struct psp_key_parsed *key, struct netlink_ext_ack *extack) +{ + struct inet_connection_sock *icsk; + int err; + + err = psp_sock_recv_queue_check(sk, pas); + if (err) { + NL_SET_ERR_MSG(extack, + "Socket has incompatible segments already in the recv queue"); + return err; + } + + err = psp_assoc_set_tx(psd, pas, key, extack); + if (err) + return err; + + WRITE_ONCE(sk->sk_validate_xmit_skb, psp_validate_xmit); + tcp_write_collapse_fence(sk); + pas->upgrade_seq = tcp_sk(sk)->rcv_nxt; + + icsk = inet_csk(sk); + icsk->icsk_ext_hdr_len += psp_sk_overhead(sk); + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); + + return err; +} + int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, u32 version, struct psp_key_parsed *key, struct netlink_ext_ack *extack) { - struct inet_connection_sock *icsk; - struct psp_assoc *pas, *dummy; + struct psp_assoc *pas; int err; lock_sock(sk); @@ -207,40 +271,7 @@ int psp_sock_assoc_set_tx(struct sock *sk, struct psp_dev *psd, goto exit_unlock; } - err = psp_sock_recv_queue_check(sk, pas); - if (err) { - NL_SET_ERR_MSG(extack, "Socket has incompatible segments already in the recv queue"); - goto exit_unlock; - } - - /* Pass a fake association to drivers to make sure they don't - * try to store pointers to it. For re-keying we'll need to - * re-allocate the assoc structures. - */ - dummy = psp_assoc_dummy(pas); - if (!dummy) { - err = -ENOMEM; - goto exit_unlock; - } - - memcpy(&dummy->tx, key, sizeof(*key)); - err = psp_dev_tx_key_add(psd, dummy, extack); - if (err) - goto exit_free_dummy; - - memcpy(pas->drv_data, dummy->drv_data, psd->caps->assoc_drv_spc); - memcpy(&pas->tx, key, sizeof(*key)); - - WRITE_ONCE(sk->sk_validate_xmit_skb, psp_validate_xmit); - tcp_write_collapse_fence(sk); - pas->upgrade_seq = tcp_sk(sk)->rcv_nxt; - - icsk = inet_csk(sk); - icsk->icsk_ext_hdr_len += psp_sk_overhead(sk); - icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); - -exit_free_dummy: - kfree(dummy); + err = psp_sock_set_tx_key(sk, psd, pas, key, extack); exit_unlock: release_sock(sk); return err; |
