This series addresses several s390 driver vulnerabilities related to improper handling of sensitive keys-related material and its lack of proper disposal in stable kernel branches. These issues have been announced as CVE-2024-42155 [1], CVE-2024-42156 [2] and CVE-2024-42158 [4] and fixed in upstream. Another problem named as CVE-2024-42157 [3] has already been successfully backported.
All patches have been cherry-picked and are ready to be cleanly applied to 6.1 stable branch. Same series adapted for 6.6 version will follow separately. Backports for 5.10/5.15 have already been sent, see [5].
[PATCH 6.1 1/3] s390/pkey: Use kfree_sensitive() to fix Coccinelle warnings Use kfree_sensitive() instead of kfree() and memzero_explicit(). Fixes CVE-2024-42158.
[PATCH 6.1 2/3] s390/pkey: Wipe copies of clear-key structures on failure Properly wipe sensitive key material from stack for IOCTLs that deal with clear-key conversion. Fixes CVE-2024-42156.
[PATCH 6.1 3/3] s390/pkey: Wipe copies of protected- and secure-keys Properly wipe key copies from stack for affected IOCTLs. Fixes CVE-2024-42155.
[1] https://nvd.nist.gov/vuln/detail/CVE-2024-42155 [2] https://nvd.nist.gov/vuln/detail/CVE-2024-42156 [3] https://nvd.nist.gov/vuln/detail/CVE-2024-42157 [4] https://nvd.nist.gov/vuln/detail/CVE-2024-42158 [5] https://lore.kernel.org/all/20241128142245.18136-1-n.zhandarovich@fintech.ru...
From: Jules Irenge jbi.octave@gmail.com
commit 22e6824622e8a8889df0f8fc4ed5aea0e702a694 upstream.
Replace memzero_explicit() and kfree() with kfree_sensitive() to fix warnings reported by Coccinelle:
WARNING opportunity for kfree_sensitive/kvfree_sensitive (line 1506) WARNING opportunity for kfree_sensitive/kvfree_sensitive (line 1643) WARNING opportunity for kfree_sensitive/kvfree_sensitive (line 1770)
Signed-off-by: Jules Irenge jbi.octave@gmail.com Reviewed-by: Holger Dengler dengler@linux.ibm.com Link: https://lore.kernel.org/r/ZjqZkNi_JUJu73Rg@octinomon.home Signed-off-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com [Nikita: small changes were made during cherry-picking due to different debug macro use and similar discrepancies between branches] Signed-off-by: Nikita Zhandarovich n.zhandarovich@fintech.ru --- P.S. As no Fixes: tag was present, I decided against adding it myself and leaving commit body intact.
drivers/s390/crypto/pkey_api.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 17885c9f55cb..d1429622036f 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -1307,8 +1307,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, return PTR_ERR(kkey); rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); - memzero_explicit(kkey, ktp.keylen); - kfree(kkey); + kfree_sensitive(kkey); if (rc) break; if (copy_to_user(utp, &ktp, sizeof(ktp))) @@ -1441,8 +1440,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); kfree(apqns); - memzero_explicit(kkey, ktp.keylen); - kfree(kkey); + kfree_sensitive(kkey); if (rc) break; if (copy_to_user(utp, &ktp, sizeof(ktp))) @@ -1568,8 +1566,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, protkey, &protkeylen); DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); kfree(apqns); - memzero_explicit(kkey, ktp.keylen); - kfree(kkey); + kfree_sensitive(kkey); if (rc) { kfree(protkey); break;
From: Holger Dengler dengler@linux.ibm.com
commit d65d76a44ffe74c73298ada25b0f578680576073 upstream.
Wipe all sensitive data from stack for all IOCTLs, which convert a clear-key into a protected- or secure-key.
Reviewed-by: Harald Freudenberger freude@linux.ibm.com Reviewed-by: Ingo Franzki ifranzki@linux.ibm.com Acked-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Holger Dengler dengler@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com [Nikita: small changes were made during cherry-picking due to different debug macro use and similar discrepancies between branches] Signed-off-by: Nikita Zhandarovich n.zhandarovich@fintech.ru --- P.S. As no Fixes: tag was present, I decided against adding it myself and leaving commit body intact.
drivers/s390/crypto/pkey_api.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index d1429622036f..0aaa8686a0b2 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -1188,9 +1188,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, kcs.clrkey.clrkey, kcs.seckey.seckey); DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); - if (rc) - break; - if (copy_to_user(ucs, &kcs, sizeof(kcs))) + if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs))) rc = -EFAULT; memzero_explicit(&kcs, sizeof(kcs)); break; @@ -1220,9 +1218,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, rc = pkey_clr2protkey(kcp.keytype, &kcp.clrkey, &kcp.protkey); DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); - if (rc) - break; - if (copy_to_user(ucp, &kcp, sizeof(kcp))) + if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp))) rc = -EFAULT; memzero_explicit(&kcp, sizeof(kcp)); break; @@ -1366,11 +1362,14 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kcs, ucs, sizeof(kcs))) return -EFAULT; apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); - if (IS_ERR(apqns)) + if (IS_ERR(apqns)) { + memzero_explicit(&kcs, sizeof(kcs)); return PTR_ERR(apqns); + } kkey = kzalloc(klen, GFP_KERNEL); if (!kkey) { kfree(apqns); + memzero_explicit(&kcs, sizeof(kcs)); return -ENOMEM; } rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, @@ -1380,15 +1379,18 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(apqns); if (rc) { kfree(kkey); + memzero_explicit(&kcs, sizeof(kcs)); break; } if (kcs.key) { if (kcs.keylen < klen) { kfree(kkey); + memzero_explicit(&kcs, sizeof(kcs)); return -EINVAL; } if (copy_to_user(kcs.key, kkey, klen)) { kfree(kkey); + memzero_explicit(&kcs, sizeof(kcs)); return -EFAULT; } }
From: Holger Dengler dengler@linux.ibm.com
commit f2ebdadd85af4f4d0cae1e5d009c70eccc78c207 upstream.
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: Harald Freudenberger freude@linux.ibm.com Reviewed-by: Ingo Franzki ifranzki@linux.ibm.com Acked-by: Heiko Carstens hca@linux.ibm.com Signed-off-by: Holger Dengler dengler@linux.ibm.com Signed-off-by: Alexander Gordeev agordeev@linux.ibm.com [Nikita: small changes were made during cherry-picking due to different debug macro use and similar discrepancies between branches] Signed-off-by: Nikita Zhandarovich n.zhandarovich@fintech.ru --- P.S. As no Fixes: tag was present, I decided against adding it myself and leaving commit body intact.
drivers/s390/crypto/pkey_api.c | 80 ++++++++++++++++------------------ 1 file changed, 37 insertions(+), 43 deletions(-)
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 0aaa8686a0b2..4b7ca7473123 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -1173,10 +1173,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: { @@ -1203,10 +1202,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: { @@ -1246,10 +1244,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: { @@ -1261,10 +1258,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: { @@ -1275,10 +1271,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: { @@ -1289,6 +1284,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: { @@ -1304,10 +1300,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); kfree_sensitive(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: { @@ -1333,23 +1328,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: { @@ -1378,18 +1373,18 @@ 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); memzero_explicit(&kcs, sizeof(kcs)); break; } if (kcs.key) { if (kcs.keylen < klen) { - kfree(kkey); + kfree_sensitive(kkey); memzero_explicit(&kcs, sizeof(kcs)); return -EINVAL; } if (copy_to_user(kcs.key, kkey, klen)) { - kfree(kkey); + kfree_sensitive(kkey); memzero_explicit(&kcs, sizeof(kcs)); return -EFAULT; } @@ -1398,7 +1393,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: { @@ -1415,7 +1410,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))) @@ -1443,10 +1438,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); kfree(apqns); kfree_sensitive(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: { @@ -1474,7 +1468,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; @@ -1560,7 +1554,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, @@ -1570,20 +1564,20 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(apqns); kfree_sensitive(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;
linux-stable-mirror@lists.linaro.org