aboutsummaryrefslogtreecommitdiffstats
path: root/net/tls
diff options
context:
space:
mode:
authorVakul Garg <vakul.garg@nxp.com>2018-09-25 06:56:17 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-25 13:43:01 -0400
commitb85135b595db01353a18ccfeafa9d9ae9028745e (patch)
treee1471ac258124f6f57ab495b76ee8187138097d0 /net/tls
parenta06ee256e5d6f03fffbd088de9bf84035658cc5a (diff)
tls: Fix socket mem accounting error under async encryption
Current async encryption implementation sometimes showed up socket memory accounting error during socket close. This results in kernel warning calltrace. The root cause of the problem is that socket var sk_forward_alloc gets corrupted due to access in sk_mem_charge() and sk_mem_uncharge() being invoked from multiple concurrent contexts in multicore processor. The apis sk_mem_charge() and sk_mem_uncharge() are called from functions alloc_plaintext_sg(), free_sg() etc. It is required that memory accounting apis are called under a socket lock. The plaintext sg data sent for encryption is freed using free_sg() in tls_encryption_done(). It is wrong to call free_sg() from this function. This is because this function may run in irq context. We cannot acquire socket lock in this function. We remove calling of function free_sg() for plaintext data from tls_encryption_done() and defer freeing up of plaintext data to the time when the record is picked up from tx_list and transmitted/freed. When tls_tx_records() gets called, socket is already locked and thus there is no concurrent access problem. Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption") Signed-off-by: Vakul Garg <vakul.garg@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tls')
-rw-r--r--net/tls/tls_sw.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index bf03f32aa983..406d3bb98818 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -353,6 +353,9 @@ int tls_tx_records(struct sock *sk, int flags)
353 * Remove the head of tx_list 353 * Remove the head of tx_list
354 */ 354 */
355 list_del(&rec->list); 355 list_del(&rec->list);
356 free_sg(sk, rec->sg_plaintext_data,
357 &rec->sg_plaintext_num_elem, &rec->sg_plaintext_size);
358
356 kfree(rec); 359 kfree(rec);
357 } 360 }
358 361
@@ -371,6 +374,10 @@ int tls_tx_records(struct sock *sk, int flags)
371 goto tx_err; 374 goto tx_err;
372 375
373 list_del(&rec->list); 376 list_del(&rec->list);
377 free_sg(sk, rec->sg_plaintext_data,
378 &rec->sg_plaintext_num_elem,
379 &rec->sg_plaintext_size);
380
374 kfree(rec); 381 kfree(rec);
375 } else { 382 } else {
376 break; 383 break;
@@ -399,8 +406,6 @@ static void tls_encrypt_done(struct crypto_async_request *req, int err)
399 rec->sg_encrypted_data[0].offset -= tls_ctx->tx.prepend_size; 406 rec->sg_encrypted_data[0].offset -= tls_ctx->tx.prepend_size;
400 rec->sg_encrypted_data[0].length += tls_ctx->tx.prepend_size; 407 rec->sg_encrypted_data[0].length += tls_ctx->tx.prepend_size;
401 408
402 free_sg(sk, rec->sg_plaintext_data,
403 &rec->sg_plaintext_num_elem, &rec->sg_plaintext_size);
404 409
405 /* Free the record if error is previously set on socket */ 410 /* Free the record if error is previously set on socket */
406 if (err || sk->sk_err) { 411 if (err || sk->sk_err) {
@@ -523,9 +528,6 @@ static int tls_push_record(struct sock *sk, int flags,
523 if (rc == -EINPROGRESS) 528 if (rc == -EINPROGRESS)
524 return -EINPROGRESS; 529 return -EINPROGRESS;
525 530
526 free_sg(sk, rec->sg_plaintext_data, &rec->sg_plaintext_num_elem,
527 &rec->sg_plaintext_size);
528
529 if (rc < 0) { 531 if (rc < 0) {
530 tls_err_abort(sk, EBADMSG); 532 tls_err_abort(sk, EBADMSG);
531 return rc; 533 return rc;
@@ -1566,6 +1568,11 @@ void tls_sw_free_resources_tx(struct sock *sk)
1566 1568
1567 rec = list_first_entry(&ctx->tx_list, 1569 rec = list_first_entry(&ctx->tx_list,
1568 struct tls_rec, list); 1570 struct tls_rec, list);
1571
1572 free_sg(sk, rec->sg_plaintext_data,
1573 &rec->sg_plaintext_num_elem,
1574 &rec->sg_plaintext_size);
1575
1569 list_del(&rec->list); 1576 list_del(&rec->list);
1570 kfree(rec); 1577 kfree(rec);
1571 } 1578 }
@@ -1575,6 +1582,10 @@ void tls_sw_free_resources_tx(struct sock *sk)
1575 &rec->sg_encrypted_num_elem, 1582 &rec->sg_encrypted_num_elem,
1576 &rec->sg_encrypted_size); 1583 &rec->sg_encrypted_size);
1577 1584
1585 free_sg(sk, rec->sg_plaintext_data,
1586 &rec->sg_plaintext_num_elem,
1587 &rec->sg_plaintext_size);
1588
1578 list_del(&rec->list); 1589 list_del(&rec->list);
1579 kfree(rec); 1590 kfree(rec);
1580 } 1591 }