[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