Re: [PATCH net] rxrpc: Don't put crypto buffers on the stack

2018-02-08 Thread David Miller
From: David Howells 
Date: Thu, 08 Feb 2018 15:59:07 +

> Don't put buffers of data to be handed to crypto on the stack as this may
> cause an assertion failure in the kernel (see below).  Fix this by using an
> kmalloc'd buffer instead.
 ...
> Reported-by: Jonathan Billings 
> Reported-by: Marc Dionne 
> Signed-off-by: David Howells 
> Tested-by: Jonathan Billings 

Applied, thanks David.


[PATCH net] rxrpc: Don't put crypto buffers on the stack

2018-02-08 Thread David Howells
Don't put buffers of data to be handed to crypto on the stack as this may
cause an assertion failure in the kernel (see below).  Fix this by using an
kmalloc'd buffer instead.

kernel BUG at ./include/linux/scatterlist.h:147!
...
RIP: 0010:rxkad_encrypt_response.isra.6+0x191/0x1b0 [rxrpc]
RSP: 0018:be2fc06cfca8 EFLAGS: 00010246
RAX:  RBX: 989277d59900 RCX: 0028
RDX: 259dc06cfd88 RSI: 0025 RDI: be30406cfd88
RBP: be2fc06cfd60 R08: be2fc06cfd08 R09: be2fc06cfd08
R10:  R11:  R12: 17c5f80d9f95
R13: be2fc06cfd88 R14: 98927a3f7aa0 R15: be2fc06cfd08
FS:  () GS:98927fc0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: 55b1ff28f0f8 CR3: 1b412003 CR4: 003606f0
DR0:  DR1:  DR2: 
DR3:  DR6: fffe0ff0 DR7: 0400
Call Trace:
 rxkad_respond_to_challenge+0x297/0x330 [rxrpc]
 rxrpc_process_connection+0xd1/0x690 [rxrpc]
 ? process_one_work+0x1c3/0x680
 ? __lock_is_held+0x59/0xa0
 process_one_work+0x249/0x680
 worker_thread+0x3a/0x390
 ? process_one_work+0x680/0x680
 kthread+0x121/0x140
 ? kthread_create_worker_on_cpu+0x70/0x70
 ret_from_fork+0x3a/0x50

Reported-by: Jonathan Billings 
Reported-by: Marc Dionne 
Signed-off-by: David Howells 
Tested-by: Jonathan Billings 
---

 net/rxrpc/conn_event.c |1 +
 net/rxrpc/rxkad.c  |   92 +++-
 2 files changed, 52 insertions(+), 41 deletions(-)

diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 4ca11be6be3c..b1dfae107431 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -460,6 +460,7 @@ void rxrpc_process_connection(struct work_struct *work)
case -EKEYEXPIRED:
case -EKEYREJECTED:
goto protocol_error;
+   case -ENOMEM:
case -EAGAIN:
goto requeue_and_leave;
case -ECONNABORTED:
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index c38b3a1de56c..77cb23c7bd0a 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -773,8 +773,7 @@ static int rxkad_respond_to_challenge(struct 
rxrpc_connection *conn,
 {
const struct rxrpc_key_token *token;
struct rxkad_challenge challenge;
-   struct rxkad_response resp
-   __attribute__((aligned(8))); /* must be aligned for crypto */
+   struct rxkad_response *resp;
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
const char *eproto;
u32 version, nonce, min_level, abort_code;
@@ -818,26 +817,29 @@ static int rxkad_respond_to_challenge(struct 
rxrpc_connection *conn,
token = conn->params.key->payload.data[0];
 
/* build the response packet */
-   memset(, 0, sizeof(resp));
-
-   resp.version= htonl(RXKAD_VERSION);
-   resp.encrypted.epoch= htonl(conn->proto.epoch);
-   resp.encrypted.cid  = htonl(conn->proto.cid);
-   resp.encrypted.securityIndex= htonl(conn->security_ix);
-   resp.encrypted.inc_nonce= htonl(nonce + 1);
-   resp.encrypted.level= htonl(conn->params.security_level);
-   resp.kvno   = htonl(token->kad->kvno);
-   resp.ticket_len = htonl(token->kad->ticket_len);
-
-   resp.encrypted.call_id[0] = htonl(conn->channels[0].call_counter);
-   resp.encrypted.call_id[1] = htonl(conn->channels[1].call_counter);
-   resp.encrypted.call_id[2] = htonl(conn->channels[2].call_counter);
-   resp.encrypted.call_id[3] = htonl(conn->channels[3].call_counter);
+   resp = kzalloc(sizeof(struct rxkad_response), GFP_NOFS);
+   if (!resp)
+   return -ENOMEM;
+
+   resp->version   = htonl(RXKAD_VERSION);
+   resp->encrypted.epoch   = htonl(conn->proto.epoch);
+   resp->encrypted.cid = htonl(conn->proto.cid);
+   resp->encrypted.securityIndex   = htonl(conn->security_ix);
+   resp->encrypted.inc_nonce   = htonl(nonce + 1);
+   resp->encrypted.level   = htonl(conn->params.security_level);
+   resp->kvno  = htonl(token->kad->kvno);
+   resp->ticket_len= htonl(token->kad->ticket_len);
+   resp->encrypted.call_id[0]  = htonl(conn->channels[0].call_counter);
+   resp->encrypted.call_id[1]  = htonl(conn->channels[1].call_counter);
+   resp->encrypted.call_id[2]  = htonl(conn->channels[2].call_counter);
+   resp->encrypted.call_id[3]  = htonl(conn->channels[3].call_counter);
 
/* calculate the response checksum and then do the encryption */
-   rxkad_calc_response_checksum();
-