Skip to content

Commit 2897041

Browse files
committed
Merge branch 'tls-fixes'
Jakub Kicinski says: ==================== tls: rx: strp: fix inline crypto offload The local strparser version I added to TLS does not preserve decryption status, which breaks inline crypto (NIC offload). ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 7e01c7f + 74836ec commit 2897041

File tree

6 files changed

+177
-50
lines changed

6 files changed

+177
-50
lines changed

include/linux/skbuff.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,16 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
15871587
to->l4_hash = from->l4_hash;
15881588
};
15891589

1590+
static inline int skb_cmp_decrypted(const struct sk_buff *skb1,
1591+
const struct sk_buff *skb2)
1592+
{
1593+
#ifdef CONFIG_TLS_DEVICE
1594+
return skb2->decrypted - skb1->decrypted;
1595+
#else
1596+
return 0;
1597+
#endif
1598+
}
1599+
15901600
static inline void skb_copy_decrypted(struct sk_buff *to,
15911601
const struct sk_buff *from)
15921602
{

include/net/tls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ struct tls_strparser {
126126
u32 mark : 8;
127127
u32 stopped : 1;
128128
u32 copy_mode : 1;
129+
u32 mixed_decrypted : 1;
129130
u32 msg_ready : 1;
130131

131132
struct strp_msg stm;

net/tls/tls.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
167167
return ctx->strp.msg_ready;
168168
}
169169

170+
static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
171+
{
172+
return ctx->strp.mixed_decrypted;
173+
}
174+
170175
#ifdef CONFIG_TLS_DEVICE
171176
int tls_device_init(void);
172177
void tls_device_cleanup(void);

net/tls/tls_device.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,20 +1007,14 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx)
10071007
struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(tls_ctx);
10081008
struct sk_buff *skb = tls_strp_msg(sw_ctx);
10091009
struct strp_msg *rxm = strp_msg(skb);
1010-
int is_decrypted = skb->decrypted;
1011-
int is_encrypted = !is_decrypted;
1012-
struct sk_buff *skb_iter;
1013-
int left;
1014-
1015-
left = rxm->full_len - skb->len;
1016-
/* Check if all the data is decrypted already */
1017-
skb_iter = skb_shinfo(skb)->frag_list;
1018-
while (skb_iter && left > 0) {
1019-
is_decrypted &= skb_iter->decrypted;
1020-
is_encrypted &= !skb_iter->decrypted;
1021-
1022-
left -= skb_iter->len;
1023-
skb_iter = skb_iter->next;
1010+
int is_decrypted, is_encrypted;
1011+
1012+
if (!tls_strp_msg_mixed_decrypted(sw_ctx)) {
1013+
is_decrypted = skb->decrypted;
1014+
is_encrypted = !is_decrypted;
1015+
} else {
1016+
is_decrypted = 0;
1017+
is_encrypted = 0;
10241018
}
10251019

10261020
trace_tls_device_decrypted(sk, tcp_sk(sk)->copied_seq - rxm->full_len,

net/tls/tls_strp.c

Lines changed: 149 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,50 @@ static void tls_strp_anchor_free(struct tls_strparser *strp)
2929
struct skb_shared_info *shinfo = skb_shinfo(strp->anchor);
3030

3131
DEBUG_NET_WARN_ON_ONCE(atomic_read(&shinfo->dataref) != 1);
32-
shinfo->frag_list = NULL;
32+
if (!strp->copy_mode)
33+
shinfo->frag_list = NULL;
3334
consume_skb(strp->anchor);
3435
strp->anchor = NULL;
3536
}
3637

37-
/* Create a new skb with the contents of input copied to its page frags */
38-
static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
38+
static struct sk_buff *
39+
tls_strp_skb_copy(struct tls_strparser *strp, struct sk_buff *in_skb,
40+
int offset, int len)
3941
{
40-
struct strp_msg *rxm;
4142
struct sk_buff *skb;
42-
int i, err, offset;
43+
int i, err;
4344

44-
skb = alloc_skb_with_frags(0, strp->stm.full_len, TLS_PAGE_ORDER,
45+
skb = alloc_skb_with_frags(0, len, TLS_PAGE_ORDER,
4546
&err, strp->sk->sk_allocation);
4647
if (!skb)
4748
return NULL;
4849

49-
offset = strp->stm.offset;
5050
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5151
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
5252

53-
WARN_ON_ONCE(skb_copy_bits(strp->anchor, offset,
53+
WARN_ON_ONCE(skb_copy_bits(in_skb, offset,
5454
skb_frag_address(frag),
5555
skb_frag_size(frag)));
5656
offset += skb_frag_size(frag);
5757
}
5858

59-
skb_copy_header(skb, strp->anchor);
59+
skb->len = len;
60+
skb->data_len = len;
61+
skb_copy_header(skb, in_skb);
62+
return skb;
63+
}
64+
65+
/* Create a new skb with the contents of input copied to its page frags */
66+
static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
67+
{
68+
struct strp_msg *rxm;
69+
struct sk_buff *skb;
70+
71+
skb = tls_strp_skb_copy(strp, strp->anchor, strp->stm.offset,
72+
strp->stm.full_len);
73+
if (!skb)
74+
return NULL;
75+
6076
rxm = strp_msg(skb);
6177
rxm->offset = 0;
6278
return skb;
@@ -180,22 +196,22 @@ static void tls_strp_flush_anchor_copy(struct tls_strparser *strp)
180196
for (i = 0; i < shinfo->nr_frags; i++)
181197
__skb_frag_unref(&shinfo->frags[i], false);
182198
shinfo->nr_frags = 0;
199+
if (strp->copy_mode) {
200+
kfree_skb_list(shinfo->frag_list);
201+
shinfo->frag_list = NULL;
202+
}
183203
strp->copy_mode = 0;
204+
strp->mixed_decrypted = 0;
184205
}
185206

186-
static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
187-
unsigned int offset, size_t in_len)
207+
static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff *skb,
208+
struct sk_buff *in_skb, unsigned int offset,
209+
size_t in_len)
188210
{
189-
struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
190-
struct sk_buff *skb;
191-
skb_frag_t *frag;
192211
size_t len, chunk;
212+
skb_frag_t *frag;
193213
int sz;
194214

195-
if (strp->msg_ready)
196-
return 0;
197-
198-
skb = strp->anchor;
199215
frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE];
200216

201217
len = in_len;
@@ -208,19 +224,26 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
208224
skb_frag_size(frag),
209225
chunk));
210226

211-
sz = tls_rx_msg_size(strp, strp->anchor);
212-
if (sz < 0) {
213-
desc->error = sz;
214-
return 0;
215-
}
216-
217-
/* We may have over-read, sz == 0 is guaranteed under-read */
218-
if (sz > 0)
219-
chunk = min_t(size_t, chunk, sz - skb->len);
220-
221227
skb->len += chunk;
222228
skb->data_len += chunk;
223229
skb_frag_size_add(frag, chunk);
230+
231+
sz = tls_rx_msg_size(strp, skb);
232+
if (sz < 0)
233+
return sz;
234+
235+
/* We may have over-read, sz == 0 is guaranteed under-read */
236+
if (unlikely(sz && sz < skb->len)) {
237+
int over = skb->len - sz;
238+
239+
WARN_ON_ONCE(over > chunk);
240+
skb->len -= over;
241+
skb->data_len -= over;
242+
skb_frag_size_add(frag, -over);
243+
244+
chunk -= over;
245+
}
246+
224247
frag++;
225248
len -= chunk;
226249
offset += chunk;
@@ -247,15 +270,99 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
247270
offset += chunk;
248271
}
249272

250-
if (strp->stm.full_len == skb->len) {
273+
read_done:
274+
return in_len - len;
275+
}
276+
277+
static int tls_strp_copyin_skb(struct tls_strparser *strp, struct sk_buff *skb,
278+
struct sk_buff *in_skb, unsigned int offset,
279+
size_t in_len)
280+
{
281+
struct sk_buff *nskb, *first, *last;
282+
struct skb_shared_info *shinfo;
283+
size_t chunk;
284+
int sz;
285+
286+
if (strp->stm.full_len)
287+
chunk = strp->stm.full_len - skb->len;
288+
else
289+
chunk = TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE;
290+
chunk = min(chunk, in_len);
291+
292+
nskb = tls_strp_skb_copy(strp, in_skb, offset, chunk);
293+
if (!nskb)
294+
return -ENOMEM;
295+
296+
shinfo = skb_shinfo(skb);
297+
if (!shinfo->frag_list) {
298+
shinfo->frag_list = nskb;
299+
nskb->prev = nskb;
300+
} else {
301+
first = shinfo->frag_list;
302+
last = first->prev;
303+
last->next = nskb;
304+
first->prev = nskb;
305+
}
306+
307+
skb->len += chunk;
308+
skb->data_len += chunk;
309+
310+
if (!strp->stm.full_len) {
311+
sz = tls_rx_msg_size(strp, skb);
312+
if (sz < 0)
313+
return sz;
314+
315+
/* We may have over-read, sz == 0 is guaranteed under-read */
316+
if (unlikely(sz && sz < skb->len)) {
317+
int over = skb->len - sz;
318+
319+
WARN_ON_ONCE(over > chunk);
320+
skb->len -= over;
321+
skb->data_len -= over;
322+
__pskb_trim(nskb, nskb->len - over);
323+
324+
chunk -= over;
325+
}
326+
327+
strp->stm.full_len = sz;
328+
}
329+
330+
return chunk;
331+
}
332+
333+
static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
334+
unsigned int offset, size_t in_len)
335+
{
336+
struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
337+
struct sk_buff *skb;
338+
int ret;
339+
340+
if (strp->msg_ready)
341+
return 0;
342+
343+
skb = strp->anchor;
344+
if (!skb->len)
345+
skb_copy_decrypted(skb, in_skb);
346+
else
347+
strp->mixed_decrypted |= !!skb_cmp_decrypted(skb, in_skb);
348+
349+
if (IS_ENABLED(CONFIG_TLS_DEVICE) && strp->mixed_decrypted)
350+
ret = tls_strp_copyin_skb(strp, skb, in_skb, offset, in_len);
351+
else
352+
ret = tls_strp_copyin_frag(strp, skb, in_skb, offset, in_len);
353+
if (ret < 0) {
354+
desc->error = ret;
355+
ret = 0;
356+
}
357+
358+
if (strp->stm.full_len && strp->stm.full_len == skb->len) {
251359
desc->count = 0;
252360

253361
strp->msg_ready = 1;
254362
tls_rx_msg_ready(strp);
255363
}
256364

257-
read_done:
258-
return in_len - len;
365+
return ret;
259366
}
260367

261368
static int tls_strp_read_copyin(struct tls_strparser *strp)
@@ -315,22 +422,28 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
315422
return 0;
316423
}
317424

318-
static bool tls_strp_check_no_dup(struct tls_strparser *strp)
425+
static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
319426
{
320427
unsigned int len = strp->stm.offset + strp->stm.full_len;
321-
struct sk_buff *skb;
428+
struct sk_buff *first, *skb;
322429
u32 seq;
323430

324-
skb = skb_shinfo(strp->anchor)->frag_list;
325-
seq = TCP_SKB_CB(skb)->seq;
431+
first = skb_shinfo(strp->anchor)->frag_list;
432+
skb = first;
433+
seq = TCP_SKB_CB(first)->seq;
326434

435+
/* Make sure there's no duplicate data in the queue,
436+
* and the decrypted status matches.
437+
*/
327438
while (skb->len < len) {
328439
seq += skb->len;
329440
len -= skb->len;
330441
skb = skb->next;
331442

332443
if (TCP_SKB_CB(skb)->seq != seq)
333444
return false;
445+
if (skb_cmp_decrypted(first, skb))
446+
return false;
334447
}
335448

336449
return true;
@@ -411,7 +524,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
411524
return tls_strp_read_copy(strp, true);
412525
}
413526

414-
if (!tls_strp_check_no_dup(strp))
527+
if (!tls_strp_check_queue_ok(strp))
415528
return tls_strp_read_copy(strp, false);
416529

417530
strp->msg_ready = 1;

net/tls/tls_sw.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,10 +2304,14 @@ static void tls_data_ready(struct sock *sk)
23042304
struct tls_context *tls_ctx = tls_get_ctx(sk);
23052305
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
23062306
struct sk_psock *psock;
2307+
gfp_t alloc_save;
23072308

23082309
trace_sk_data_ready(sk);
23092310

2311+
alloc_save = sk->sk_allocation;
2312+
sk->sk_allocation = GFP_ATOMIC;
23102313
tls_strp_data_ready(&ctx->strp);
2314+
sk->sk_allocation = alloc_save;
23112315

23122316
psock = sk_psock_get(sk);
23132317
if (psock) {

0 commit comments

Comments
 (0)