From: Harald Freudenberger <freude@linux.ibm.com>
Subject: s390/pkey: move pckmo subfunction available checks away from module init
Patch-mainline: v4.20-rc1
Git-commit: f822ad2c2c03af85a531c5174136b6d5b1abc566
References: LTC#176021 bsc#1128544

Description:   kernel: fix pkey module failure on LPARs with PCKMO disabled
Symptom:       The pkey module does not load on LPARs where the PCKMO functions
               are disabled.
Problem:       The init of the pkey module currently fails if the pckmo
               instruction or the subfunctions are not available.  However,
               customers may restrict their LPAR to switch off exactly
               these functions and work with secure key only. So it is a
               valid case to have the pkey module active and use it for
               secure key to protected key transfer only.
Solution:      This fix moves the pckmo subfunction check from the pkey
               module init function into the internal function where the
               pckmo instruction is called. So now only on invocation of
               the pckmo instruction the check for the required subfunction
               is done. If not available EOPNOTSUPP is returned to the caller.

               Effectively this allows a customer to use the pkey module
               with secure keys only. An attempt to create protected keys from
               clear key material will still fail as this import is disabled
               by the LPAR profile.

               The check for having the pckmo instruction available is still
               done during module init. This instruction came in with MSA 3
               together with the basic set of kmc instructions needed to work
               with protected keys. So this MSA 3 check is still a requirement
               for the pkey module to work. MSA 3 was introduced with z196.
Reproduction:  Disable "Permit AES key import functions" at the security tab of
               the LPAR Profile. (Re-) Activate the LPAR and modprobe pkey,
               should work with the fix.

Upstream-Description:

              s390/pkey: move pckmo subfunction available checks away from module init

              The init of the pkey module currently fails if the pckmo instruction
              or the subfunctions are not available.  However, customers may
              restrict their LPAR to switch off exactly these functions and work
              with secure key only. So it is a valid case to have the pkey module
              active and use it for secure key to protected key transfer only.

              This patch moves the pckmo subfunction check from the pkey module init
              function into the internal function where the pckmo instruction is
              called. So now only on invocation of the pckmo instruction the check
              for the required subfunction is done. If not available EOPNOTSUPP is
              returned to the caller.

              The check for having the pckmo instruction available is still done
              during module init. This instruction came in with MSA 3 together with
              the basic set of kmc instructions needed to work with protected keys.

              Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
              Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
              Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>


Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Oscar Salvador <osalvador@suse.de>
---
 drivers/s390/crypto/pkey_api.c |   26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -39,6 +39,9 @@ MODULE_DESCRIPTION("s390 protected key i
 /* Size of vardata block used for some of the cca requests/replies */
 #define VARDATASIZE 4096
 
+/* mask of available pckmo subfunctions, fetched once at module init */
+static cpacf_mask_t pckmo_functions;
+
 /*
  * debug feature data and functions
  */
@@ -684,6 +687,16 @@ int pkey_clr2protkey(u32 keytype,
 		return -EINVAL;
 	}
 
+	/*
+	 * Check if the needed pckmo subfunction is available.
+	 * These subfunctions can be enabled/disabled by customers
+	 * in the LPAR profile or may even change on the fly.
+	 */
+	if (!cpacf_test_func(&pckmo_functions, fc)) {
+		DEBUG_ERR("%s pckmo functions not available\n", __func__);
+		return -EOPNOTSUPP;
+	}
+
 	/* prepare param block */
 	memset(paramblock, 0, sizeof(paramblock));
 	memcpy(paramblock, clrkey->clrkey, keysize);
@@ -1677,15 +1690,16 @@ static struct miscdevice pkey_dev = {
  */
 int __init pkey_init(void)
 {
-	cpacf_mask_t pckmo_functions, kmc_functions;
+	cpacf_mask_t kmc_functions;
 
-	/* check for pckmo instructions available */
+	/*
+	 * The pckmo instruction should be available - even if we don't
+	 * actually invoke it. This instruction comes with MSA 3 which
+	 * is also the minimum level for the kmc instructions which
+	 * are able to work with protected keys.
+	 */
 	if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
 		return -EOPNOTSUPP;
-	if (!cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_128_KEY) ||
-	    !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_192_KEY) ||
-	    !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY))
-		return -EOPNOTSUPP;
 
 	/* check for kmc instructions available */
 	if (!cpacf_query(CPACF_KMC, &kmc_functions))
