crypto: ccree - fix backlog notifications
authorGilad Ben-Yossef <gilad@benyossef.com>
Thu, 18 Apr 2019 13:38:46 +0000 (16:38 +0300)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 25 Apr 2019 07:38:14 +0000 (15:38 +0800)
We were doing backlog notification callbacks via a cipher/hash/aead
request structure cast to the base structure, which may or may not
work based on how the structure is laid in memory and is not safe.

Fix it by delegating the backlog notification to the appropriate
internal callbacks which are type aware.

Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
Cc: stable@vger.kernel.org # v4.19+
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/ccree/cc_aead.c
drivers/crypto/ccree/cc_cipher.c
drivers/crypto/ccree/cc_hash.c
drivers/crypto/ccree/cc_request_mgr.c

index c5cde327cf1fc45db03a45ca94bf881c6d08cb39..1fa3c7fef8513d8f6f53bb977416f4ba89a55624 100644 (file)
@@ -220,6 +220,10 @@ static void cc_aead_complete(struct device *dev, void *cc_req, int err)
        struct crypto_aead *tfm = crypto_aead_reqtfm(cc_req);
        struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
 
+       /* BACKLOG notification */
+       if (err == -EINPROGRESS)
+               goto done;
+
        cc_unmap_aead_request(dev, areq);
 
        /* Restore ordinary iv pointer */
index 15da3a35a6a15c3fa1f94dc93b3db1f22bc8ac5b..1ba7c8a7bd52350da72f821ec1e61cd487a409d3 100644 (file)
@@ -818,9 +818,13 @@ static void cc_cipher_complete(struct device *dev, void *cc_req, int err)
        struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req);
        unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm);
 
-       cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst);
-       memcpy(req->iv, req_ctx->iv, ivsize);
-       kzfree(req_ctx->iv);
+       if (err != -EINPROGRESS) {
+               /* Not a BACKLOG notification */
+               cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst);
+               memcpy(req->iv, req_ctx->iv, ivsize);
+               kzfree(req_ctx->iv);
+       }
+
        skcipher_request_complete(req, err);
 }
 
index 2c4ddc8fb76b24829e9e2c34053b7c0e39f2eee0..e824ab60b59cf06cebcd2c82364616d02c271849 100644 (file)
@@ -280,8 +280,12 @@ static void cc_update_complete(struct device *dev, void *cc_req, int err)
 
        dev_dbg(dev, "req=%pK\n", req);
 
-       cc_unmap_hash_request(dev, state, req->src, false);
-       cc_unmap_req(dev, state, ctx);
+       if (err != -EINPROGRESS) {
+               /* Not a BACKLOG notification */
+               cc_unmap_hash_request(dev, state, req->src, false);
+               cc_unmap_req(dev, state, ctx);
+       }
+
        req->base.complete(&req->base, err);
 }
 
@@ -295,9 +299,13 @@ static void cc_digest_complete(struct device *dev, void *cc_req, int err)
 
        dev_dbg(dev, "req=%pK\n", req);
 
-       cc_unmap_hash_request(dev, state, req->src, false);
-       cc_unmap_result(dev, state, digestsize, req->result);
-       cc_unmap_req(dev, state, ctx);
+       if (err != -EINPROGRESS) {
+               /* Not a BACKLOG notification */
+               cc_unmap_hash_request(dev, state, req->src, false);
+               cc_unmap_result(dev, state, digestsize, req->result);
+               cc_unmap_req(dev, state, ctx);
+       }
+
        req->base.complete(&req->base, err);
 }
 
@@ -311,9 +319,13 @@ static void cc_hash_complete(struct device *dev, void *cc_req, int err)
 
        dev_dbg(dev, "req=%pK\n", req);
 
-       cc_unmap_hash_request(dev, state, req->src, false);
-       cc_unmap_result(dev, state, digestsize, req->result);
-       cc_unmap_req(dev, state, ctx);
+       if (err != -EINPROGRESS) {
+               /* Not a BACKLOG notification */
+               cc_unmap_hash_request(dev, state, req->src, false);
+               cc_unmap_result(dev, state, digestsize, req->result);
+               cc_unmap_req(dev, state, ctx);
+       }
+
        req->base.complete(&req->base, err);
 }
 
index 88c97a580dd860f901fbc8551c919e9cb8e64e6a..c2e8190bb0677be8434c9f6dbb76905db94ec8f4 100644 (file)
@@ -364,10 +364,12 @@ static void cc_enqueue_backlog(struct cc_drvdata *drvdata,
                               struct cc_bl_item *bli)
 {
        struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
+       struct device *dev = drvdata_to_dev(drvdata);
 
        spin_lock_bh(&mgr->bl_lock);
        list_add_tail(&bli->list, &mgr->backlog);
        ++mgr->bl_len;
+       dev_dbg(dev, "+++bl len: %d\n", mgr->bl_len);
        spin_unlock_bh(&mgr->bl_lock);
        tasklet_schedule(&mgr->comptask);
 }
@@ -377,7 +379,7 @@ static void cc_proc_backlog(struct cc_drvdata *drvdata)
        struct cc_req_mgr_handle *mgr = drvdata->request_mgr_handle;
        struct cc_bl_item *bli;
        struct cc_crypto_req *creq;
-       struct crypto_async_request *req;
+       void *req;
        bool ivgen;
        unsigned int total_len;
        struct device *dev = drvdata_to_dev(drvdata);
@@ -387,17 +389,20 @@ static void cc_proc_backlog(struct cc_drvdata *drvdata)
 
        while (mgr->bl_len) {
                bli = list_first_entry(&mgr->backlog, struct cc_bl_item, list);
+               dev_dbg(dev, "---bl len: %d\n", mgr->bl_len);
+
                spin_unlock(&mgr->bl_lock);
 
+
                creq = &bli->creq;
-               req = (struct crypto_async_request *)creq->user_arg;
+               req = creq->user_arg;
 
                /*
                 * Notify the request we're moving out of the backlog
                 * but only if we haven't done so already.
                 */
                if (!bli->notif) {
-                       req->complete(req, -EINPROGRESS);
+                       creq->user_cb(dev, req, -EINPROGRESS);
                        bli->notif = true;
                }