[OE-core] [PATCH] cryptodev-linux: Fixes a kernel crash observed with cipher-gcm test.
He Zhe
zhe.he at windriver.com
Wed Jul 25 07:50:59 UTC 2018
Seems this needs updating. The context of cryptiodev-module_1.9.bb has changed.
Thanks,
Zhe
On 2018年07月09日 10:24, Jiping Ma wrote:
> The crypto API for AEAD ciphers changed in recent kernels so that
> associated data is now part of both source and destination scatter
> gathers. The source, destination and associated data buffers need
> to be stiched accordingly for the operations to succeed.
>
> Signed-off-by: Jiping Ma <jiping.ma2 at windriver.com>
> ---
> .../cryptodev/cryptodev-module_1.9.bb | 2 +
> ...inux-split-big-function-to-simplify-maint.patch | 249 +++++++++++++++++++++
> ...inux-Fixes-a-kernel-crash-observed-with-c.patch | 115 ++++++++++
> 3 files changed, 366 insertions(+)
> create mode 100644 meta/recipes-kernel/cryptodev/files/0001-cryptodev-linux-split-big-function-to-simplify-maint.patch
> create mode 100644 meta/recipes-kernel/cryptodev/files/0002-cryptodev-linux-Fixes-a-kernel-crash-observed-with-c.patch
>
> diff --git a/meta/recipes-kernel/cryptodev/cryptodev-module_1.9.bb b/meta/recipes-kernel/cryptodev/cryptodev-module_1.9.bb
> index 552eb6a..16ac527 100644
> --- a/meta/recipes-kernel/cryptodev/cryptodev-module_1.9.bb
> +++ b/meta/recipes-kernel/cryptodev/cryptodev-module_1.9.bb
> @@ -9,6 +9,8 @@ DEPENDS += "cryptodev-linux"
>
> SRC_URI += " \
> file://0001-Disable-installing-header-file-provided-by-another-p.patch \
> +file://0001-cryptodev-linux-split-big-function-to-simplify-maint.patch \
> +file://0002-cryptodev-linux-Fixes-a-kernel-crash-observed-with-c.patch \
> "
>
> EXTRA_OEMAKE='KERNEL_DIR="${STAGING_KERNEL_DIR}" PREFIX="${D}"'
> diff --git a/meta/recipes-kernel/cryptodev/files/0001-cryptodev-linux-split-big-function-to-simplify-maint.patch b/meta/recipes-kernel/cryptodev/files/0001-cryptodev-linux-split-big-function-to-simplify-maint.patch
> new file mode 100644
> index 0000000..56a5bb7
> --- /dev/null
> +++ b/meta/recipes-kernel/cryptodev/files/0001-cryptodev-linux-split-big-function-to-simplify-maint.patch
> @@ -0,0 +1,249 @@
> +From 1b0b6cc97ba5cc71ae1385d125256fc1b2d606b0 Mon Sep 17 00:00:00 2001
> +From: Jiping Ma <jiping.ma2 at windriver.com>
> +Date: Wed, 2 May 2018 04:59:32 +0000
> +Subject: [PATCH 1/2] cryptodev-linux: split big function to simplify
> + maintainance
> +
> +The setup of auth_buf in tls and aead is now duplicated but this
> +is temporary and allows necessary corrections for the aead case
> +with v4.2+ kernels.
> +
> +Upstream-Status: Backported
> +
> +commit 20dcf071bc3076ee7db9d603cfbe6a06e86c7d5f
> +
> +Signed-off-by: Jiping Ma <jiping.ma2 at windriver.com>
> +---
> + authenc.c | 197 ++++++++++++++++++++++++++++++++++++++++----------------------
> + 1 file changed, 126 insertions(+), 71 deletions(-)
> +
> +diff --git a/authenc.c b/authenc.c
> +index 1bd7377..28eb0f9 100644
> +--- a/authenc.c
> ++++ b/authenc.c
> +@@ -609,96 +609,151 @@ auth_n_crypt(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop,
> + return 0;
> + }
> +
> +-/* This is the main crypto function - zero-copy edition */
> +-static int
> +-__crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
> ++static int crypto_auth_zc_srtp(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
> + {
> +- struct scatterlist *dst_sg, *auth_sg, *src_sg;
> ++ struct scatterlist *dst_sg, *auth_sg;
> + struct crypt_auth_op *caop = &kcaop->caop;
> +- int ret = 0;
> ++ int ret;
> +
> +- if (caop->flags & COP_FLAG_AEAD_SRTP_TYPE) {
> +- if (unlikely(ses_ptr->cdata.init != 0 &&
> +- (ses_ptr->cdata.stream == 0 ||
> +- ses_ptr->cdata.aead != 0))) {
> +- derr(0, "Only stream modes are allowed in SRTP mode (but not AEAD)");
> +- return -EINVAL;
> +- }
> ++ if (unlikely(ses_ptr->cdata.init != 0 &&
> ++ (ses_ptr->cdata.stream == 0 || ses_ptr->cdata.aead != 0))) {
> ++ derr(0, "Only stream modes are allowed in SRTP mode (but not AEAD)");
> ++ return -EINVAL;
> ++ }
> +
> +- ret = get_userbuf_srtp(ses_ptr, kcaop, &auth_sg, &dst_sg);
> +- if (unlikely(ret)) {
> +- derr(1, "get_userbuf_srtp(): Error getting user pages.");
> +- return ret;
> +- }
> ++ ret = get_userbuf_srtp(ses_ptr, kcaop, &auth_sg, &dst_sg);
> ++ if (unlikely(ret)) {
> ++ derr(1, "get_userbuf_srtp(): Error getting user pages.");
> ++ return ret;
> ++ }
> +
> +- ret = srtp_auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> +- dst_sg, caop->len);
> ++ ret = srtp_auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> ++ dst_sg, caop->len);
> +
> +- release_user_pages(ses_ptr);
> +- } else { /* TLS and normal cases. Here auth data are usually small
> +- * so we just copy them to a free page, instead of trying
> +- * to map them.
> +- */
> +- unsigned char *auth_buf = NULL;
> +- struct scatterlist tmp;
> ++ release_user_pages(ses_ptr);
> +
> +- if (unlikely(caop->auth_len > PAGE_SIZE)) {
> +- derr(1, "auth data len is excessive.");
> +- return -EINVAL;
> +- }
> ++ return ret;
> ++}
> +
> +- auth_buf = (char *)__get_free_page(GFP_KERNEL);
> +- if (unlikely(!auth_buf)) {
> +- derr(1, "unable to get a free page.");
> +- return -ENOMEM;
> +- }
> ++static int crypto_auth_zc_tls(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
> ++{
> ++ struct crypt_auth_op *caop = &kcaop->caop;
> ++ struct scatterlist *dst_sg, *auth_sg;
> ++ unsigned char *auth_buf = NULL;
> ++ struct scatterlist tmp;
> ++ int ret;
> +
> +- if (caop->auth_src && caop->auth_len > 0) {
> +- if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
> +- derr(1, "unable to copy auth data from userspace.");
> +- ret = -EFAULT;
> +- goto free_auth_buf;
> +- }
> ++ if (unlikely(ses_ptr->cdata.aead != 0)) {
> ++ return -EINVAL;
> ++ }
> ++
> ++ if (unlikely(caop->auth_len > PAGE_SIZE)) {
> ++ derr(1, "auth data len is excessive.");
> ++ return -EINVAL;
> ++ }
> ++
> ++ auth_buf = (char *)__get_free_page(GFP_KERNEL);
> ++ if (unlikely(!auth_buf)) {
> ++ derr(1, "unable to get a free page.");
> ++ return -ENOMEM;
> ++ }
> +
> +- sg_init_one(&tmp, auth_buf, caop->auth_len);
> +- auth_sg = &tmp;
> +- } else {
> +- auth_sg = NULL;
> ++ if (caop->auth_src && caop->auth_len > 0) {
> ++ if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
> ++ derr(1, "unable to copy auth data from userspace.");
> ++ ret = -EFAULT;
> ++ goto free_auth_buf;
> + }
> +
> +- if (caop->flags & COP_FLAG_AEAD_TLS_TYPE && ses_ptr->cdata.aead == 0) {
> +- ret = get_userbuf_tls(ses_ptr, kcaop, &dst_sg);
> +- if (unlikely(ret)) {
> +- derr(1, "get_userbuf_tls(): Error getting user pages.");
> +- goto free_auth_buf;
> +- }
> ++ sg_init_one(&tmp, auth_buf, caop->auth_len);
> ++ auth_sg = &tmp;
> ++ } else {
> ++ auth_sg = NULL;
> ++ }
> +
> +- ret = tls_auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> +- dst_sg, caop->len);
> +- } else {
> +- if (unlikely(ses_ptr->cdata.init == 0 ||
> +- (ses_ptr->cdata.stream == 0 &&
> +- ses_ptr->cdata.aead == 0))) {
> +- derr(0, "Only stream and AEAD ciphers are allowed for authenc");
> +- ret = -EINVAL;
> +- goto free_auth_buf;
> +- }
> ++ ret = get_userbuf_tls(ses_ptr, kcaop, &dst_sg);
> ++ if (unlikely(ret)) {
> ++ derr(1, "get_userbuf_tls(): Error getting user pages.");
> ++ goto free_auth_buf;
> ++ }
> +
> +- ret = get_userbuf(ses_ptr, caop->src, caop->len, caop->dst, kcaop->dst_len,
> +- kcaop->task, kcaop->mm, &src_sg, &dst_sg);
> +- if (unlikely(ret)) {
> +- derr(1, "get_userbuf(): Error getting user pages.");
> +- goto free_auth_buf;
> +- }
> ++ ret = tls_auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> ++ dst_sg, caop->len);
> ++ release_user_pages(ses_ptr);
> ++
> ++free_auth_buf:
> ++ free_page((unsigned long)auth_buf);
> ++ return ret;
> ++}
> ++
> ++static int crypto_auth_zc_aead(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
> ++{
> ++ struct scatterlist *dst_sg, *auth_sg, *src_sg;
> ++ struct crypt_auth_op *caop = &kcaop->caop;
> ++ unsigned char *auth_buf = NULL;
> ++ struct scatterlist tmp;
> ++ int ret;
> +
> +- ret = auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> +- src_sg, dst_sg, caop->len);
> ++ if (unlikely(ses_ptr->cdata.init == 0 ||
> ++ (ses_ptr->cdata.stream == 0 && ses_ptr->cdata.aead == 0))) {
> ++ derr(0, "Only stream and AEAD ciphers are allowed for authenc");
> ++ return -EINVAL;
> ++ }
> ++
> ++ if (unlikely(caop->auth_len > PAGE_SIZE)) {
> ++ derr(1, "auth data len is excessive.");
> ++ return -EINVAL;
> ++ }
> ++
> ++ auth_buf = (char *)__get_free_page(GFP_KERNEL);
> ++ if (unlikely(!auth_buf)) {
> ++ derr(1, "unable to get a free page.");
> ++ return -ENOMEM;
> ++ }
> ++
> ++ if (caop->auth_src && caop->auth_len > 0) {
> ++ if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
> ++ derr(1, "unable to copy auth data from userspace.");
> ++ ret = -EFAULT;
> ++ goto free_auth_buf;
> + }
> +
> +- release_user_pages(ses_ptr);
> ++ sg_init_one(&tmp, auth_buf, caop->auth_len);
> ++ auth_sg = &tmp;
> ++ } else {
> ++ auth_sg = NULL;
> ++ }
> ++
> ++ ret = get_userbuf(ses_ptr, caop->src, caop->len, caop->dst, kcaop->dst_len,
> ++ kcaop->task, kcaop->mm, &src_sg, &dst_sg);
> ++ if (unlikely(ret)) {
> ++ derr(1, "get_userbuf(): Error getting user pages.");
> ++ goto free_auth_buf;
> ++ }
> ++
> ++ ret = auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> ++ src_sg, dst_sg, caop->len);
> ++
> ++ release_user_pages(ses_ptr);
> +
> + free_auth_buf:
> +- free_page((unsigned long)auth_buf);
> ++ free_page((unsigned long)auth_buf);
> ++
> ++ return ret;
> ++}
> ++
> ++static int
> ++__crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
> ++{
> ++ struct crypt_auth_op *caop = &kcaop->caop;
> ++ int ret;
> ++
> ++ if (caop->flags & COP_FLAG_AEAD_SRTP_TYPE) {
> ++ ret = crypto_auth_zc_srtp(ses_ptr, kcaop);
> ++ } else if (caop->flags & COP_FLAG_AEAD_TLS_TYPE) {
> ++ ret = crypto_auth_zc_tls(ses_ptr, kcaop);
> ++ } else {
> ++ ret = crypto_auth_zc_aead(ses_ptr, kcaop);
> + }
> +
> + return ret;
> +--
> +1.9.1
> +
> diff --git a/meta/recipes-kernel/cryptodev/files/0002-cryptodev-linux-Fixes-a-kernel-crash-observed-with-c.patch b/meta/recipes-kernel/cryptodev/files/0002-cryptodev-linux-Fixes-a-kernel-crash-observed-with-c.patch
> new file mode 100644
> index 0000000..cd7b592
> --- /dev/null
> +++ b/meta/recipes-kernel/cryptodev/files/0002-cryptodev-linux-Fixes-a-kernel-crash-observed-with-c.patch
> @@ -0,0 +1,115 @@
> +From d2f765e13fb193ac03679e60fe06832d400d7717 Mon Sep 17 00:00:00 2001
> +From: Jiping Ma <jiping.ma2 at windriver.com>
> +Date: Wed, 2 May 2018 05:10:58 +0000
> +Subject: [PATCH 2/2] cryptodev-linux: Fixes a kernel crash observed with
> + cipher-gcm test.
> +
> +The crypto API for AEAD ciphers changed in recent kernels so that
> +associated data is now part of both source and destination scatter
> +gathers. The source, destination and associated data buffers need
> +to be stiched accordingly for the operations to succeed.
> +
> +Upstream-Status: Backported
> +
> +commit a705360197260d28535746ae98c461ba2cfb7a9e
> +
> +Signed-off-by: Jiping Ma <jiping.ma2 at windriver.com>
> +---
> + authenc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++---------
> + 1 file changed, 46 insertions(+), 9 deletions(-)
> +
> +diff --git a/authenc.c b/authenc.c
> +index 28eb0f9..692951f 100644
> +--- a/authenc.c
> ++++ b/authenc.c
> +@@ -688,12 +688,20 @@ free_auth_buf:
> +
> + static int crypto_auth_zc_aead(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
> + {
> +- struct scatterlist *dst_sg, *auth_sg, *src_sg;
> ++ struct scatterlist *dst_sg;
> ++ struct scatterlist *src_sg;
> + struct crypt_auth_op *caop = &kcaop->caop;
> + unsigned char *auth_buf = NULL;
> +- struct scatterlist tmp;
> + int ret;
> +
> ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
> ++ struct scatterlist tmp;
> ++ struct scatterlist *auth_sg;
> ++#else
> ++ struct scatterlist auth1[2];
> ++ struct scatterlist auth2[2];
> ++#endif
> ++
> + if (unlikely(ses_ptr->cdata.init == 0 ||
> + (ses_ptr->cdata.stream == 0 && ses_ptr->cdata.aead == 0))) {
> + derr(0, "Only stream and AEAD ciphers are allowed for authenc");
> +@@ -711,11 +719,19 @@ static int crypto_auth_zc_aead(struct csession *ses_ptr, struct kernel_crypt_aut
> + return -ENOMEM;
> + }
> +
> ++ ret = get_userbuf(ses_ptr, caop->src, caop->len, caop->dst, kcaop->dst_len,
> ++ kcaop->task, kcaop->mm, &src_sg, &dst_sg);
> ++ if (unlikely(ret)) {
> ++ derr(1, "get_userbuf(): Error getting user pages.");
> ++ goto free_auth_buf;
> ++ }
> ++
> ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
> + if (caop->auth_src && caop->auth_len > 0) {
> + if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
> + derr(1, "unable to copy auth data from userspace.");
> + ret = -EFAULT;
> +- goto free_auth_buf;
> ++ goto free_pages;
> + }
> +
> + sg_init_one(&tmp, auth_buf, caop->auth_len);
> +@@ -724,16 +740,37 @@ static int crypto_auth_zc_aead(struct csession *ses_ptr, struct kernel_crypt_aut
> + auth_sg = NULL;
> + }
> +
> +- ret = get_userbuf(ses_ptr, caop->src, caop->len, caop->dst, kcaop->dst_len,
> +- kcaop->task, kcaop->mm, &src_sg, &dst_sg);
> +- if (unlikely(ret)) {
> +- derr(1, "get_userbuf(): Error getting user pages.");
> +- goto free_auth_buf;
> ++ ret = auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> ++ src_sg, dst_sg, caop->len);
> ++#else
> ++ if (caop->auth_src && caop->auth_len > 0) {
> ++ if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
> ++ derr(1, "unable to copy auth data from userspace.");
> ++ ret = -EFAULT;
> ++ goto free_pages;
> ++ }
> ++
> ++ sg_init_table(auth1, 2);
> ++ sg_set_buf(auth1, auth_buf, caop->auth_len);
> ++ sg_chain(auth1, 2, src_sg);
> ++
> ++ if (src_sg == dst_sg) {
> ++ src_sg = auth1;
> ++ dst_sg = auth1;
> ++ } else {
> ++ sg_init_table(auth2, 2);
> ++ sg_set_buf(auth2, auth_buf, caop->auth_len);
> ++ sg_chain(auth2, 2, dst_sg);
> ++ src_sg = auth1;
> ++ dst_sg = auth2;
> ++ }
> + }
> +
> +- ret = auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
> ++ ret = auth_n_crypt(ses_ptr, kcaop, NULL, caop->auth_len,
> + src_sg, dst_sg, caop->len);
> ++#endif
> +
> ++free_pages:
> + release_user_pages(ses_ptr);
> +
> + free_auth_buf:
> +--
> +1.9.1
> +
More information about the Openembedded-core
mailing list