]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.0/net-mlx5-fpga-tls-idr-remove-on-flow-delete.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / queue-5.0 / net-mlx5-fpga-tls-idr-remove-on-flow-delete.patch
1 From foo@baz Sat Apr 20 16:43:09 CEST 2019
2 From: Saeed Mahameed <saeedm@mellanox.com>
3 Date: Tue, 19 Mar 2019 01:05:41 -0700
4 Subject: net/mlx5: FPGA, tls, idr remove on flow delete
5
6 From: Saeed Mahameed <saeedm@mellanox.com>
7
8 [ Upstream commit df3a8344d404a810b4aadbf19b08c8232fbaa715 ]
9
10 Flow is kfreed on mlx5_fpga_tls_del_flow but kept in the idr data
11 structure, this is risky and can cause use-after-free, since the
12 idr_remove is delayed until tls_send_teardown_cmd completion.
13
14 Instead of delaying idr_remove, in this patch we do it on
15 mlx5_fpga_tls_del_flow, before actually kfree(flow).
16
17 Added synchronize_rcu before kfree(flow)
18
19 Fixes: ab412e1dd7db ("net/mlx5: Accel, add TLS rx offload routines")
20 Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22 ---
23 drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c | 43 +++++++--------------
24 1 file changed, 15 insertions(+), 28 deletions(-)
25
26 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c
27 +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c
28 @@ -148,14 +148,16 @@ static int mlx5_fpga_tls_alloc_swid(stru
29 return ret;
30 }
31
32 -static void mlx5_fpga_tls_release_swid(struct idr *idr,
33 - spinlock_t *idr_spinlock, u32 swid)
34 +static void *mlx5_fpga_tls_release_swid(struct idr *idr,
35 + spinlock_t *idr_spinlock, u32 swid)
36 {
37 unsigned long flags;
38 + void *ptr;
39
40 spin_lock_irqsave(idr_spinlock, flags);
41 - idr_remove(idr, swid);
42 + ptr = idr_remove(idr, swid);
43 spin_unlock_irqrestore(idr_spinlock, flags);
44 + return ptr;
45 }
46
47 static void mlx_tls_kfree_complete(struct mlx5_fpga_conn *conn,
48 @@ -165,20 +167,12 @@ static void mlx_tls_kfree_complete(struc
49 kfree(buf);
50 }
51
52 -struct mlx5_teardown_stream_context {
53 - struct mlx5_fpga_tls_command_context cmd;
54 - u32 swid;
55 -};
56 -
57 static void
58 mlx5_fpga_tls_teardown_completion(struct mlx5_fpga_conn *conn,
59 struct mlx5_fpga_device *fdev,
60 struct mlx5_fpga_tls_command_context *cmd,
61 struct mlx5_fpga_dma_buf *resp)
62 {
63 - struct mlx5_teardown_stream_context *ctx =
64 - container_of(cmd, struct mlx5_teardown_stream_context, cmd);
65 -
66 if (resp) {
67 u32 syndrome = MLX5_GET(tls_resp, resp->sg[0].data, syndrome);
68
69 @@ -186,14 +180,6 @@ mlx5_fpga_tls_teardown_completion(struct
70 mlx5_fpga_err(fdev,
71 "Teardown stream failed with syndrome = %d",
72 syndrome);
73 - else if (MLX5_GET(tls_cmd, cmd->buf.sg[0].data, direction_sx))
74 - mlx5_fpga_tls_release_swid(&fdev->tls->tx_idr,
75 - &fdev->tls->tx_idr_spinlock,
76 - ctx->swid);
77 - else
78 - mlx5_fpga_tls_release_swid(&fdev->tls->rx_idr,
79 - &fdev->tls->rx_idr_spinlock,
80 - ctx->swid);
81 }
82 mlx5_fpga_tls_put_command_ctx(cmd);
83 }
84 @@ -253,7 +239,7 @@ int mlx5_fpga_tls_resync_rx(struct mlx5_
85 static void mlx5_fpga_tls_send_teardown_cmd(struct mlx5_core_dev *mdev,
86 void *flow, u32 swid, gfp_t flags)
87 {
88 - struct mlx5_teardown_stream_context *ctx;
89 + struct mlx5_fpga_tls_command_context *ctx;
90 struct mlx5_fpga_dma_buf *buf;
91 void *cmd;
92
93 @@ -261,7 +247,7 @@ static void mlx5_fpga_tls_send_teardown_
94 if (!ctx)
95 return;
96
97 - buf = &ctx->cmd.buf;
98 + buf = &ctx->buf;
99 cmd = (ctx + 1);
100 MLX5_SET(tls_cmd, cmd, command_type, CMD_TEARDOWN_STREAM);
101 MLX5_SET(tls_cmd, cmd, swid, swid);
102 @@ -272,8 +258,7 @@ static void mlx5_fpga_tls_send_teardown_
103 buf->sg[0].data = cmd;
104 buf->sg[0].size = MLX5_TLS_COMMAND_SIZE;
105
106 - ctx->swid = swid;
107 - mlx5_fpga_tls_cmd_send(mdev->fpga, &ctx->cmd,
108 + mlx5_fpga_tls_cmd_send(mdev->fpga, ctx,
109 mlx5_fpga_tls_teardown_completion);
110 }
111
112 @@ -283,13 +268,14 @@ void mlx5_fpga_tls_del_flow(struct mlx5_
113 struct mlx5_fpga_tls *tls = mdev->fpga->tls;
114 void *flow;
115
116 - rcu_read_lock();
117 if (direction_sx)
118 - flow = idr_find(&tls->tx_idr, swid);
119 + flow = mlx5_fpga_tls_release_swid(&tls->tx_idr,
120 + &tls->tx_idr_spinlock,
121 + swid);
122 else
123 - flow = idr_find(&tls->rx_idr, swid);
124 -
125 - rcu_read_unlock();
126 + flow = mlx5_fpga_tls_release_swid(&tls->rx_idr,
127 + &tls->rx_idr_spinlock,
128 + swid);
129
130 if (!flow) {
131 mlx5_fpga_err(mdev->fpga, "No flow information for swid %u\n",
132 @@ -297,6 +283,7 @@ void mlx5_fpga_tls_del_flow(struct mlx5_
133 return;
134 }
135
136 + synchronize_rcu(); /* before kfree(flow) */
137 mlx5_fpga_tls_send_teardown_cmd(mdev, flow, swid, flags);
138 }
139