From 00536515871e4fe983cec426f4d5c2629f499fb8 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Fri, 25 Feb 2022 14:20:21 +0800 Subject: [PATCH] crypto: rockchip: cryptodev_linux: added non-multithreaded protection CRYPTO V1/V2 do not support multi-threading, so it is necessary to add a hold mechanism in Cryptodev to prevent abnormal consequences caused by multi-threading calls. Signed-off-by: Lin Jinhan Change-Id: Ifd5ff6b102c81c8ac44c16f9689d5219c7fa5a56 --- .../crypto/rockchip/cryptodev_linux/ioctl.c | 36 +++++++++++++++++++ .../rockchip/cryptodev_linux/rk_cryptodev.c | 14 ++++++++ .../cryptodev_linux/rk_cryptodev_int.h | 2 ++ drivers/crypto/rockchip/rk_crypto_core.c | 6 ++-- drivers/crypto/rockchip/rk_crypto_core.h | 1 + 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/rockchip/cryptodev_linux/ioctl.c b/drivers/crypto/rockchip/cryptodev_linux/ioctl.c index 64dfb24b5764..8b2ca28eb9a1 100644 --- a/drivers/crypto/rockchip/cryptodev_linux/ioctl.c +++ b/drivers/crypto/rockchip/cryptodev_linux/ioctl.c @@ -103,6 +103,7 @@ struct crypt_priv { /* cryptodev's own workqueue, keeps crypto tasks from disturbing the force */ static struct workqueue_struct *cryptodev_wq; +static atomic_t cryptodev_sess = ATOMIC_INIT(1); /* Prepare session for future use. */ static int @@ -322,6 +323,16 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop) goto session_error; } + /* Non-multithreaded can only create one session */ + if (!rk_cryptodev_multi_thread(NULL) && + !atomic_dec_and_test(&cryptodev_sess)) { + atomic_inc(&cryptodev_sess); + ddebug(2, "Non-multithreaded can only create one session. sess = %d", + atomic_read(&cryptodev_sess)); + ret = -EBUSY; + goto session_error; + } + /* put the new session to the list */ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); mutex_init(&ses_new->sem); @@ -375,6 +386,12 @@ crypto_destroy_session(struct csession *ses_ptr) mutex_unlock(&ses_ptr->sem); mutex_destroy(&ses_ptr->sem); kfree(ses_ptr); + + /* Non-multithreaded can only create one session */ + if (!rk_cryptodev_multi_thread(NULL)) { + atomic_inc(&cryptodev_sess); + ddebug(2, "Release cryptodev_sess = %d", atomic_read(&cryptodev_sess)); + } } /* Look up a session by ID and remove. */ @@ -549,6 +566,7 @@ static void cryptask_routine(struct work_struct *work) } /* ====== /dev/crypto ====== */ +static atomic_t cryptodev_node = ATOMIC_INIT(1); static int cryptodev_open(struct inode *inode, struct file *filp) @@ -557,6 +575,18 @@ cryptodev_open(struct inode *inode, struct file *filp) struct crypt_priv *pcr; int i; + /* Non-multithreaded can only be opened once */ + if (!rk_cryptodev_multi_thread(NULL) && + !atomic_dec_and_test(&cryptodev_node)) { + atomic_inc(&cryptodev_node); + ddebug(2, "Non-multithreaded can only be opened once. node = %d", + atomic_read(&cryptodev_node)); + return -EBUSY; + } + + /* make sure sess == 1 after open */ + atomic_set(&cryptodev_sess, 1); + pcr = kzalloc(sizeof(*pcr), GFP_KERNEL); if (!pcr) return -ENOMEM; @@ -615,6 +645,12 @@ cryptodev_release(struct inode *inode, struct file *filp) if (!pcr) return 0; + /* Non-multithreaded can only be opened once */ + if (!rk_cryptodev_multi_thread(NULL)) { + atomic_inc(&cryptodev_node); + ddebug(2, "Release cryptodev_node = %d", atomic_read(&cryptodev_node)); + } + cancel_work_sync(&pcr->cryptask); list_splice_tail(&pcr->todo.list, &pcr->free.list); diff --git a/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev.c b/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev.c index 370f1f84fc0f..e2202b8af0c2 100644 --- a/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev.c +++ b/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev.c @@ -36,6 +36,7 @@ struct dma_fd_map_node { struct crypto_dev_info { struct device *dev; char name[MAX_CRYPTO_NAME_LEN]; + bool is_multi_thread; }; static struct crypto_dev_info g_dev_infos[MAX_CRYPTO_DEV]; @@ -61,6 +62,8 @@ int rk_cryptodev_register_dev(struct device *dev, const char *name) g_dev_infos[i].dev = dev; strncpy(g_dev_infos[i].name, name, sizeof(g_dev_infos[i].name)); + + g_dev_infos[i].is_multi_thread = strstr(g_dev_infos[i].name, "multi"); dev_info(dev, "register to cryptodev ok!\n"); return 0; } @@ -954,3 +957,14 @@ const char *rk_get_hash_name(uint32_t id, int *is_hmac) return NULL; } +bool rk_cryptodev_multi_thread(const char *name) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(g_dev_infos); i++) { + if (g_dev_infos[i].dev) + return g_dev_infos[i].is_multi_thread; + } + + return false; +} diff --git a/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev_int.h b/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev_int.h index 0da8e207f887..1b3b1442d8ba 100644 --- a/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev_int.h +++ b/drivers/crypto/rockchip/cryptodev_linux/rk_cryptodev_int.h @@ -85,4 +85,6 @@ const char *rk_get_cipher_name(uint32_t id, int *is_stream, int *is_aead); const char *rk_get_hash_name(uint32_t id, int *is_hmac); +bool rk_cryptodev_multi_thread(const char *name); + #endif diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index 6379028f1ac8..e914ec896838 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -25,6 +25,7 @@ #include "cryptodev_linux/rk_cryptodev_int.h" #define RK_CRYPTO_V1_SOC_DATA_INIT(names) {\ + .crypto_ver = "CRYPTO V1.0.0.0",\ .use_soft_aes192 = false,\ .valid_algs_name = (names),\ .valid_algs_num = ARRAY_SIZE(names),\ @@ -39,6 +40,7 @@ } #define RK_CRYPTO_V2_SOC_DATA_INIT(names, soft_aes_192) {\ + .crypto_ver = "CRYPTO V2.0.0.0",\ .use_soft_aes192 = soft_aes_192,\ .valid_algs_name = (names),\ .valid_algs_num = ARRAY_SIZE(names),\ @@ -835,9 +837,9 @@ static int rk_crypto_probe(struct platform_device *pdev) goto err_register_alg; } - rk_cryptodev_register_dev(rk_dev->dev, "rk_crypto"); + rk_cryptodev_register_dev(rk_dev->dev, soc_data->crypto_ver); - dev_info(dev, "Crypto Accelerator successfully registered\n"); + dev_info(dev, "%s Accelerator successfully registered\n", soc_data->crypto_ver); return 0; err_register_alg: diff --git a/drivers/crypto/rockchip/rk_crypto_core.h b/drivers/crypto/rockchip/rk_crypto_core.h index 23e0509ae8e4..24062e32610d 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.h +++ b/drivers/crypto/rockchip/rk_crypto_core.h @@ -44,6 +44,7 @@ #define sha224_state sha256_state struct rk_crypto_soc_data { + const char *crypto_ver; char **valid_algs_name; int valid_algs_num; struct rk_crypto_algt **total_algs;