]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'net-tls-fix-device-surprise-removal-with-offload'
authorDavid S. Miller <davem@davemloft.net>
Wed, 22 May 2019 19:21:44 +0000 (12:21 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 22 May 2019 19:21:44 +0000 (12:21 -0700)
Jakub Kicinski says:

====================
net/tls: fix device surprise removal with offload

This series fixes two issues with device surprise removal.
First we need to take a read lock around resync, otherwise
netdev notifier handler may clear the structures from under
our feet.

Secondly we need to be careful about the interpretation
of device features.  Offload has to be properly cleaned
up even if the TLS device features got cleared after
connection state was installed.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
net/tls/tls_device.c

index ca54a7c7ec81a44529b157b294464744ea116b75..b95c408fd771452a4ae2f026eb3f6785cf8c89bf 100644 (file)
@@ -553,8 +553,8 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
 void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
-       struct net_device *netdev = tls_ctx->netdev;
        struct tls_offload_context_rx *rx_ctx;
+       struct net_device *netdev;
        u32 is_req_pending;
        s64 resync_req;
        u32 req_seq;
@@ -568,10 +568,15 @@ void handle_device_resync(struct sock *sk, u32 seq, u64 rcd_sn)
        is_req_pending = resync_req;
 
        if (unlikely(is_req_pending) && req_seq == seq &&
-           atomic64_try_cmpxchg(&rx_ctx->resync_req, &resync_req, 0))
-               netdev->tlsdev_ops->tls_dev_resync_rx(netdev, sk,
-                                                     seq + TLS_HEADER_SIZE - 1,
-                                                     rcd_sn);
+           atomic64_try_cmpxchg(&rx_ctx->resync_req, &resync_req, 0)) {
+               seq += TLS_HEADER_SIZE - 1;
+               down_read(&device_offload_lock);
+               netdev = tls_ctx->netdev;
+               if (netdev)
+                       netdev->tlsdev_ops->tls_dev_resync_rx(netdev, sk, seq,
+                                                             rcd_sn);
+               up_read(&device_offload_lock);
+       }
 }
 
 static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
@@ -934,12 +939,6 @@ void tls_device_offload_cleanup_rx(struct sock *sk)
        if (!netdev)
                goto out;
 
-       if (!(netdev->features & NETIF_F_HW_TLS_RX)) {
-               pr_err_ratelimited("%s: device is missing NETIF_F_HW_TLS_RX cap\n",
-                                  __func__);
-               goto out;
-       }
-
        netdev->tlsdev_ops->tls_dev_del(netdev, tls_ctx,
                                        TLS_OFFLOAD_CTX_DIR_RX);
 
@@ -998,7 +997,8 @@ static int tls_dev_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-       if (!(dev->features & (NETIF_F_HW_TLS_RX | NETIF_F_HW_TLS_TX)))
+       if (!dev->tlsdev_ops &&
+           !(dev->features & (NETIF_F_HW_TLS_RX | NETIF_F_HW_TLS_TX)))
                return NOTIFY_DONE;
 
        switch (event) {