Commit cd075fde authored by Holger Dengler's avatar Holger Dengler Committed by Hongbo Li
Browse files

s390/pkey: Wipe copies of protected- and secure-keys

mainline inclusion
from mainline-v6.10-rc1
commit f2ebdadd85af4f4d0cae1e5d009c70eccc78c207
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAGTIZ
CVE: CVE-2024-42155

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f2ebdadd85af4f4d0cae1e5d009c70eccc78c207



--------------------------------

Although the clear-key of neither protected- nor secure-keys is
accessible, this key material should only be visible to the calling
process. So wipe all copies of protected- or secure-keys from stack,
even in case of an error.

Reviewed-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarIngo Franzki <ifranzki@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Conflicts:
	drivers/s390/crypto/pkey_api.c
[lhb: adjust context]
Signed-off-by: default avatarHongbo Li <lihongbo22@huawei.com>
parent fe266c4b
Loading
Loading
Loading
Loading
+37 −43
Original line number Diff line number Diff line
@@ -1137,10 +1137,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		rc = cca_genseckey(kgs.cardnr, kgs.domain,
				   kgs.keytype, kgs.seckey.seckey);
		DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc);
		if (rc)
			break;
		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
			return -EFAULT;
		if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))
			rc = -EFAULT;
		memzero_explicit(&kgs, sizeof(kgs));
		break;
	}
	case PKEY_CLR2SECK: {
@@ -1169,10 +1168,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
				     ksp.seckey.seckey, ksp.protkey.protkey,
				     &ksp.protkey.len, &ksp.protkey.type);
		DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc);
		if (rc)
			break;
		if (copy_to_user(usp, &ksp, sizeof(ksp)))
			return -EFAULT;
		if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
			rc = -EFAULT;
		memzero_explicit(&ksp, sizeof(ksp));
		break;
	}
	case PKEY_CLR2PROTK: {
@@ -1214,10 +1212,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
			return -EFAULT;
		rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey);
		DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc);
		if (rc)
			break;
		if (copy_to_user(usp, &ksp, sizeof(ksp)))
			return -EFAULT;
		if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
			rc = -EFAULT;
		memzero_explicit(&ksp, sizeof(ksp));
		break;
	}
	case PKEY_VERIFYKEY: {
@@ -1229,10 +1226,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
				    &kvk.keysize, &kvk.attributes);
		DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc);
		if (rc)
			break;
		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
			return -EFAULT;
		if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))
			rc = -EFAULT;
		memzero_explicit(&kvk, sizeof(kvk));
		break;
	}
	case PKEY_GENPROTK: {
@@ -1243,10 +1239,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
			return -EFAULT;
		rc = pkey_genprotkey(kgp.keytype, &kgp.protkey);
		DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc);
		if (rc)
			break;
		if (copy_to_user(ugp, &kgp, sizeof(kgp)))
			return -EFAULT;
		if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp)))
			rc = -EFAULT;
		memzero_explicit(&kgp, sizeof(kgp));
		break;
	}
	case PKEY_VERIFYPROTK: {
@@ -1257,6 +1252,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
			return -EFAULT;
		rc = pkey_verifyprotkey(&kvp.protkey);
		DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc);
		memzero_explicit(&kvp, sizeof(kvp));
		break;
	}
	case PKEY_KBLOB2PROTK: {
@@ -1273,10 +1269,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
		memzero_explicit(kkey, ktp.keylen);
		kfree(kkey);
		if (rc)
			break;
		if (copy_to_user(utp, &ktp, sizeof(ktp)))
			return -EFAULT;
		if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
			rc = -EFAULT;
		memzero_explicit(&ktp, sizeof(ktp));
		break;
	}
	case PKEY_GENSECK2: {
@@ -1302,23 +1297,23 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc);
		kfree(apqns);
		if (rc) {
			kfree(kkey);
			kfree_sensitive(kkey);
			break;
		}
		if (kgs.key) {
			if (kgs.keylen < klen) {
				kfree(kkey);
				kfree_sensitive(kkey);
				return -EINVAL;
			}
			if (copy_to_user(kgs.key, kkey, klen)) {
				kfree(kkey);
				kfree_sensitive(kkey);
				return -EFAULT;
			}
		}
		kgs.keylen = klen;
		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
			rc = -EFAULT;
		kfree(kkey);
		kfree_sensitive(kkey);
		break;
	}
	case PKEY_CLR2SECK2: {
@@ -1344,16 +1339,16 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc);
		kfree(apqns);
		if (rc) {
			kfree(kkey);
			kfree_sensitive(kkey);
			break;
		}
		if (kcs.key) {
			if (kcs.keylen < klen) {
				kfree(kkey);
				kfree_sensitive(kkey);
				return -EINVAL;
			}
			if (copy_to_user(kcs.key, kkey, klen)) {
				kfree(kkey);
				kfree_sensitive(kkey);
				return -EFAULT;
			}
		}
@@ -1361,7 +1356,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
			rc = -EFAULT;
		memzero_explicit(&kcs, sizeof(kcs));
		kfree(kkey);
		kfree_sensitive(kkey);
		break;
	}
	case PKEY_VERIFYKEY2: {
@@ -1378,7 +1373,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
				     &kvk.cardnr, &kvk.domain,
				     &kvk.type, &kvk.size, &kvk.flags);
		DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc);
		kfree(kkey);
		kfree_sensitive(kkey);
		if (rc)
			break;
		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
@@ -1407,10 +1402,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		kfree(apqns);
		memzero_explicit(kkey, ktp.keylen);
		kfree(kkey);
		if (rc)
			break;
		if (copy_to_user(utp, &ktp, sizeof(ktp)))
			return -EFAULT;
		if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
			rc = -EFAULT;
		memzero_explicit(&ktp, sizeof(ktp));
		break;
	}
	case PKEY_APQNS4K: {
@@ -1438,7 +1432,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		rc = pkey_apqns4key(kkey, kak.keylen, kak.flags,
				    apqns, &nr_apqns);
		DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc);
		kfree(kkey);
		kfree_sensitive(kkey);
		if (rc && rc != -ENOSPC) {
			kfree(apqns);
			break;
@@ -1524,7 +1518,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		protkey = kmalloc(protkeylen, GFP_KERNEL);
		if (!protkey) {
			kfree(apqns);
			kfree(kkey);
			kfree_sensitive(kkey);
			return -ENOMEM;
		}
		rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey,
@@ -1535,20 +1529,20 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
		memzero_explicit(kkey, ktp.keylen);
		kfree(kkey);
		if (rc) {
			kfree(protkey);
			kfree_sensitive(protkey);
			break;
		}
		if (ktp.pkey && ktp.pkeylen) {
			if (protkeylen > ktp.pkeylen) {
				kfree(protkey);
				kfree_sensitive(protkey);
				return -EINVAL;
			}
			if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
				kfree(protkey);
				kfree_sensitive(protkey);
				return -EFAULT;
			}
		}
		kfree(protkey);
		kfree_sensitive(protkey);
		ktp.pkeylen = protkeylen;
		if (copy_to_user(utp, &ktp, sizeof(ktp)))
			return -EFAULT;