From ba16486d79d44e3d07c713ff566be156292ed744 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 4 Jun 2026 10:21:17 +0800 Subject: rhashtable: Add workqueue/irq_work header inclusions Add inclusions for irq_work.h and workqueue.h to rhashtable.c rather than relying on indirect inclusions from elsewhere. Remove workqueue.h from rhashtable.h now that it uses IRQ work only. Signed-off-by: Herbert Xu --- include/linux/rhashtable.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 79f83b6eec27..57a2a29bef0e 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 2fdf279ccf1bdea919b7dfa56081047c7a8d5015 Mon Sep 17 00:00:00 2001 From: "Pratik R. Sampat" Date: Mon, 15 Jun 2026 15:23:15 +0000 Subject: crypto: ccp - Introduce SNP_VERIFY_MITIGATION command The SEV-SNP firmware provides the SNP_VERIFY_MITIGATION command, which can be used to query the status of currently supported vulnerability mitigations and to initiate mitigations within the firmware. This command is an explicit mechanism to ascertain if a firmware mitigation is applied without needing a full RMP re-build, which is most useful in a live firmware update scenario. The firmware supports two subcommands: STATUS and VERIFY. The STATUS subcommand is used to query the supported and verified mitigation bits. The VERIFY subcommand initiates the mitigation process within the FW for the specified vulnerability. Expose a userspace interface under: /sys/firmware/sev/vulnerabilities/ - supported_mitigations (read-only): supported mitigation vector mask - verified_mitigations (read/write): current verified mask; write a vector to request VERIFY for that bit The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using it are bug-specific. Information about supported mitigations and its corresponding vector is to be published as part of the AMD Security Bulletin. See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for more details. Reviewed-by: Tycho Andersen (AMD) Reviewed-by: Tom Lendacky Signed-off-by: Pratik R. Sampat Signed-off-by: Herbert Xu --- .../ABI/testing/sysfs-firmware-sev-vulnerabilities | 19 +++ drivers/crypto/ccp/sev-dev.c | 177 +++++++++++++++++++++ drivers/crypto/ccp/sev-dev.h | 3 + include/linux/psp-sev.h | 51 ++++++ 4 files changed, 250 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities (limited to 'include') diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities new file mode 100644 index 000000000000..964362558bb2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities @@ -0,0 +1,19 @@ +What: /sys/firmware/sev/vulnerabilities/supported_mitigations +Date: June 2026 +Contact: linux-crypto@vger.kernel.org +Description: + Read-only interface that reports the vector of SEV-SNP + firmware vulnerability mitigations supported by the firmware. + +What: /sys/firmware/sev/vulnerabilities/verified_mitigations +Date: June 2026 +Contact: linux-crypto@vger.kernel.org +Description: + Read/write interface that reports the vector of SEV-SNP + firmware vulnerability mitigations already verified by the + firmware. Writing a vector value requests the firmware to + VERIFY the corresponding mitigation bit(s). + + The list of supported mitigations and the meaning of each + vector bit are both platform- and bug-specific and are + published as part of the AMD Security Bulletin. diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index ca473ca198b8..8be4dab05cbb 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -245,6 +245,7 @@ static int sev_cmd_buffer_len(int cmd) case SEV_CMD_SNP_LAUNCH_FINISH: return sizeof(struct sev_data_snp_launch_finish); case SEV_CMD_SNP_DBG_DECRYPT: return sizeof(struct sev_data_snp_dbg); case SEV_CMD_SNP_DBG_ENCRYPT: return sizeof(struct sev_data_snp_dbg); + case SEV_CMD_SNP_VERIFY_MITIGATION: return sizeof(struct sev_data_snp_verify_mitigation); case SEV_CMD_SNP_PAGE_UNSMASH: return sizeof(struct sev_data_snp_page_unsmash); case SEV_CMD_SNP_PLATFORM_STATUS: return sizeof(struct sev_data_snp_addr); case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request); @@ -1352,6 +1353,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg) return 0; } +#ifdef CONFIG_SYSFS +static int snp_verify_mitigation(u16 command, u64 vector, + struct sev_data_snp_verify_mitigation_dst *dst) +{ + struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL; + struct sev_data_snp_verify_mitigation data = {0}; + struct sev_device *sev = psp_master->sev_data; + int ret, error = 0; + + mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO); + if (!mit_dst) + return -ENOMEM; + + data.length = sizeof(data); + data.subcommand = command; + data.vector = vector; + data.dst_paddr = __psp_pa(mit_dst); + data.dst_paddr_en = true; + + ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error); + if (!ret) + memcpy(dst, mit_dst, sizeof(*mit_dst)); + else + dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n", + ret, error); + + snp_free_firmware_page(mit_dst); + + return ret; +} + +static ssize_t supported_mitigations_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct sev_data_snp_verify_mitigation_dst dst; + int ret; + + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector); +} + +static struct kobj_attribute supported_attr = + __ATTR_RO_MODE(supported_mitigations, 0400); + +static ssize_t verified_mitigations_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct sev_data_snp_verify_mitigation_dst dst; + int ret; + + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst); + if (ret) + return ret; + + return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector); +} + +static ssize_t verified_mitigations_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct sev_data_snp_verify_mitigation_dst dst; + struct sev_device *sev = psp_master->sev_data; + u64 vector; + int ret; + + ret = kstrtoull(buf, 0, &vector); + if (ret) + return ret; + + /* + * The firmware verifies a single mitigation per call. Reject vectors + * with more than one bit set early to avoid a guaranteed-to-fail call + */ + if (hweight64(vector) != 1) + return -EINVAL; + + ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst); + if (ret) + return ret; + + if (dst.mit_failure_status) { + dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n", + dst.mit_failure_status); + return -EINVAL; + } + + return count; +} + +static struct kobj_attribute verified_attr = + __ATTR_RW_MODE(verified_mitigations, 0600); + +static struct attribute *mitigation_attrs[] = { + &supported_attr.attr, + &verified_attr.attr, + NULL +}; + +static const struct attribute_group mit_attr_group = { + .attrs = mitigation_attrs, +}; + +static void sev_snp_register_verify_mitigation(struct sev_device *sev) +{ + int rc; + + if (!(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED) || + sev->verify_mit) + return; + + if (!sev->sev_kobj) { + sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj); + if (!sev->sev_kobj) + return; + } + + sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj); + if (!sev->verify_mit) + goto err_sev_kobj; + + rc = sysfs_create_group(sev->verify_mit, &mit_attr_group); + if (rc) + goto err_verify_mit; + + return; + +err_verify_mit: + kobject_put(sev->verify_mit); + sev->verify_mit = NULL; +err_sev_kobj: + kobject_put(sev->sev_kobj); + sev->sev_kobj = NULL; +} + +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) +{ + if (sev->verify_mit) { + sysfs_remove_group(sev->verify_mit, &mit_attr_group); + kobject_put(sev->verify_mit); + sev->verify_mit = NULL; + } + + if (sev->sev_kobj) { + kobject_put(sev->sev_kobj); + sev->sev_kobj = NULL; + } +} +#else // CONFIG_SYSFS +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { } +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { } +#endif // CONFIG_SYSFS + static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) { struct sev_data_range_list *snp_range_list __free(kfree) = NULL; @@ -1675,6 +1832,17 @@ int sev_platform_init(struct sev_platform_init_args *args) rc = _sev_platform_init_locked(args); mutex_unlock(&sev_cmd_mutex); + /* + * Register the sysfs interface outside the sev_cmd_mutex. The + * _show()/_store() handlers issue SEV commands that acquire the + * sev_cmd_mutex, so creating (and on the shutdown path, removing) the + * sysfs group must stay outside that lock. sysfs provides its own + * synchronization between group creation/removal and concurrent + * attribute access. + */ + if (!rc) + sev_snp_register_verify_mitigation(psp_master->sev_data); + return rc; } EXPORT_SYMBOL_GPL(sev_platform_init); @@ -2769,6 +2937,15 @@ static void sev_firmware_shutdown(struct sev_device *sev) if (sev->tio_status) sev_tsm_uninit(sev); + /* + * Remove the sysfs interface before taking the sev_cmd_mutex. + * sysfs_remove_group() waits for in-flight _show()/_store() handlers + * to drain, and those handlers issue SNP_VERIFY_MITIGATION via + * sev_do_cmd() which acquires the sev_cmd_mutex. Removing the group + * while holding the mutex could therefore deadlock. + */ + sev_snp_unregister_verify_mitigation(sev); + mutex_lock(&sev_cmd_mutex); __sev_firmware_shutdown(sev, false); diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h index b1cd556bbbf6..d5e596606def 100644 --- a/drivers/crypto/ccp/sev-dev.h +++ b/drivers/crypto/ccp/sev-dev.h @@ -59,6 +59,9 @@ struct sev_device { bool snp_initialized; + struct kobject *sev_kobj; + struct kobject *verify_mit; + struct sev_user_data_status sev_plat_status; struct sev_user_data_snp_status snp_plat_status; diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index ce16bbc0b308..03a79786df1d 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -129,6 +129,7 @@ enum sev_cmd { SEV_CMD_SNP_LAUNCH_FINISH = 0x0A2, SEV_CMD_SNP_DBG_DECRYPT = 0x0B0, SEV_CMD_SNP_DBG_ENCRYPT = 0x0B1, + SEV_CMD_SNP_VERIFY_MITIGATION = 0x0B2, SEV_CMD_SNP_PAGE_SWAP_OUT = 0x0C0, SEV_CMD_SNP_PAGE_SWAP_IN = 0x0C1, SEV_CMD_SNP_PAGE_MOVE = 0x0C2, @@ -898,10 +899,60 @@ struct snp_feature_info { #define SNP_CIPHER_TEXT_HIDING_SUPPORTED BIT(3) #define SNP_AES_256_XTS_POLICY_SUPPORTED BIT(4) #define SNP_CXL_ALLOW_POLICY_SUPPORTED BIT(5) +#define SNP_VERIFY_MITIGATION_SUPPORTED BIT(13) /* Feature bits in EBX */ #define SNP_SEV_TIO_SUPPORTED BIT(1) +#define SNP_MIT_SUBCMD_REQ_STATUS 0x0 +#define SNP_MIT_SUBCMD_REQ_VERIFY 0x1 + +/** + * struct sev_data_snp_verify_mitigation - SNP_VERIFY_MITIGATION command params + * + * @length: Length of the command buffer read by the PSP + * @subcommand: Mitigation sub-command for the firmware to execute. + * REQ_STATUS: 0x0 - Request status about currently supported and + * verified mitigations + * REQ_VERIFY: 0x1 - Request to initiate verification mitigation + * operation on a specific mitigation + * @rsvd: Reserved + * @vector: Bit specifying the vulnerability mitigation to process + * @dst_paddr_en: Destination paddr enabled + * @src_paddr_en: Source paddr enabled + * @rsvd1: Reserved + * @rsvd2: Reserved + * @src_paddr: Source address for optional input data + * @dst_paddr: Destination address to write the result + * @rsvd3: Reserved + */ +struct sev_data_snp_verify_mitigation { + u32 length; + u16 subcommand; + u16 rsvd; + u64 vector; + u32 dst_paddr_en : 1, + src_paddr_en : 1, + rsvd1 : 30; + u8 rsvd2[4]; + u64 src_paddr; + u64 dst_paddr; + u8 rsvd3[24]; +} __packed; + +/** + * struct sev_data_snp_verify_mitigation_dst - mitigation result vectors + * + * @mit_verified_vector: Bit vector of vulnerability mitigations verified + * @mit_supported_vector: Bit vector of vulnerability mitigations supported + * @mit_failure_status: Status of the verification operation + */ +struct sev_data_snp_verify_mitigation_dst { + u64 mit_verified_vector; /* OUT */ + u64 mit_supported_vector; /* OUT */ + u32 mit_failure_status; /* OUT */ +} __packed; + /** * struct sev_snp_tcb_version_genoa_milan * -- cgit v1.2.3 From 2f204fe718f5bf519013cc2536ad7bb2cbb51661 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 22 Jun 2026 16:48:03 -0700 Subject: crypto: af_alg - Add af_alg_restrict sysctl, defaulting to 1 AF_ALG is a frequent source of vulnerabilities and a maintenance nightmare. It exposes far more functionality to userspace than ever should have been exposed, especially to unprivileged processes. Recent exploits have targeted kernel internal implementation details like "authencesn" that have zero use case for userspace access. Fortunately, AF_ALG is rarely used in practice, as userspace crypto libraries exist. And when it is used, only some functionality is known to be used, and many users are known to hold capabilities already. iwd for example requires CAP_NET_ADMIN and has a known algorithm list (https://lore.kernel.org/linux-crypto/bcbbef00-5881-421b-8892-7be6c04b832d@gmail.com/). Thus, let's restrict the set of allowed algorithms by default, depending on the capabilities held. Add a sysctl /proc/sys/crypto/af_alg_restrict with meaning: 0: unrestricted 1: limited functionality 2: completely disabled Set the default value to 1, which enables an algorithm allowlist for unprivileged processes and a slightly longer allowlist for privileged processes. Note that the list may be tweaked in the future. However, the common use cases such as iwd and bluez are taken into account already. I've tested that iwd still works with the default value of 1. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- Documentation/admin-guide/sysctl/crypto.rst | 36 +++++++++++++++ Documentation/crypto/userspace-if.rst | 13 ++++-- crypto/af_alg.c | 72 ++++++++++++++++++++++++++--- crypto/algif_aead.c | 11 +++++ crypto/algif_hash.c | 24 ++++++++++ crypto/algif_rng.c | 9 ++++ crypto/algif_skcipher.c | 20 ++++++++ include/crypto/if_alg.h | 8 ++++ 8 files changed, 184 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/Documentation/admin-guide/sysctl/crypto.rst b/Documentation/admin-guide/sysctl/crypto.rst index b707bd314a64..9a1bd53287f4 100644 --- a/Documentation/admin-guide/sysctl/crypto.rst +++ b/Documentation/admin-guide/sysctl/crypto.rst @@ -7,6 +7,42 @@ kernel configuration: .. contents:: :local: +.. _af_alg_restrict: + +af_alg_restrict +=============== + +Controls the level of restriction of AF_ALG. + +AF_ALG is a deprecated and rarely-used userspace interface that is a +frequent source of vulnerabilities. It also unnecessarily exposes a +large number of kernel implementation details. For more information +about AF_ALG, see :ref:`Documentation/crypto/userspace-if.rst +`. + +Starting in Linux v7.3, AF_ALG supports only a limited set of +algorithms by default. This sysctl allows the system administrator to +remove this restriction when needed for compatibility reasons, or to +go further and disable AF_ALG entirely. The default value is 1. + +=== ================================================================== +0 AF_ALG is unrestricted. + +1 AF_ALG is supported with a limited list of algorithms. The list + is designed for compatibility with known users such as iwd and + bluez that haven't yet been fixed to use userspace crypto code. + + Specifically, there is an allowlist for unprivileged processes + and a somewhat longer allowlist for processes that hold + CAP_SYS_ADMIN or CAP_NET_ADMIN in the initial user namespace. + + Attempts to bind() an AF_ALG socket with a disallowed algorithm + fail with ENOENT. + +2 AF_ALG is completely disabled. Attempts to create an AF_ALG + socket fail with EAFNOSUPPORT. +=== ================================================================== + fips_enabled ============ diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst index ab93300c8e04..d6194346e366 100644 --- a/Documentation/crypto/userspace-if.rst +++ b/Documentation/crypto/userspace-if.rst @@ -1,3 +1,5 @@ +.. _crypto_userspace_interface: + User Space Interface ==================== @@ -12,9 +14,14 @@ AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010, most kernel developers now consider it to be a mistake. Support for hardware accelerators, which was the original purpose of AF_ALG, has been removed. -AF_ALG continues to be supported only for backwards compatibility. On systems -where no programs using AF_ALG remain, the support for it should be disabled by -disabling ``CONFIG_CRYPTO_USER_API_*``. +AF_ALG continues to be supported only for backwards compatibility. + +Starting in Linux v7.3, the set of algorithms supported by AF_ALG is limited by +default. See :ref:`/proc/sys/crypto/af_alg_restrict `. + +On systems where no programs using AF_ALG remain, the support for it should be +disabled entirely by setting ``/proc/sys/crypto/af_alg_restrict`` to 2 or by +disabling ``CONFIG_CRYPTO_USER_API_*`` in the kernel configuration. Deprecation ----------- diff --git a/crypto/af_alg.c b/crypto/af_alg.c index cce000e8590e..34b801568fba 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -22,10 +23,28 @@ #include #include #include +#include +#include #include #include #include +static int af_alg_restrict = 1; + +static const struct ctl_table af_alg_table[] = { + { + .procname = "af_alg_restrict", + .data = &af_alg_restrict, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_TWO, + }, +}; + +static struct ctl_table_header *af_alg_header; + struct alg_type_list { const struct af_alg_type *type; struct list_head list; @@ -110,6 +129,39 @@ int af_alg_unregister_type(const struct af_alg_type *type) } EXPORT_SYMBOL_GPL(af_alg_unregister_type); +static bool af_alg_capable(void) +{ + return ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN) || + capable(CAP_SYS_ADMIN); +} + +int af_alg_check_restriction(const char *name, + const struct af_alg_allowlist_entry allowlist[]) +{ + int level = READ_ONCE(af_alg_restrict); + + if (level == 0) + return 0; + if (level == 1) { + for (const struct af_alg_allowlist_entry *ent = allowlist; + ent->name; ent++) { + if (strcmp(name, ent->name) == 0 && + (!ent->privileged || af_alg_capable())) + return 0; + } + } + /* + * Use -ENOENT (the error code for "algorithm not found") instead of + * -EACCES or -EPERM, for the highest chance of correctly triggering + * fallback code paths in userspace programs. + * + * Don't log a warning, since it would be noisy. iwd tries to bind a + * bunch of algorithms that it never uses. + */ + return -ENOENT; +} +EXPORT_SYMBOL_GPL(af_alg_check_restriction); + static void alg_do_release(const struct af_alg_type *type, void *private) { if (!type) @@ -506,6 +558,9 @@ static int alg_create(struct net *net, struct socket *sock, int protocol, struct sock *sk; int err; + if (READ_ONCE(af_alg_restrict) == 2) + return -EAFNOSUPPORT; + if (sock->type != SOCK_SEQPACKET) return -ESOCKTNOSUPPORT; if (protocol != 0) @@ -1222,27 +1277,32 @@ EXPORT_SYMBOL_GPL(af_alg_get_rsgl); static int __init af_alg_init(void) { - int err = proto_register(&alg_proto, 0); + int err; + + af_alg_header = register_sysctl("crypto", af_alg_table); + err = proto_register(&alg_proto, 0); if (err) - goto out; + goto out_unregister_sysctl; err = sock_register(&alg_family); - if (err != 0) + if (err) goto out_unregister_proto; -out: - return err; + return 0; out_unregister_proto: proto_unregister(&alg_proto); - goto out; +out_unregister_sysctl: + unregister_sysctl_table(af_alg_header); + return err; } static void __exit af_alg_exit(void) { sock_unregister(PF_ALG); proto_unregister(&alg_proto); + unregister_sysctl_table(af_alg_header); } module_init(af_alg_init); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 787aac8aeb24..b9217f9086aa 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -34,6 +34,11 @@ #include #include +static const struct af_alg_allowlist_entry aead_allowlist[] = { + { "ccm(aes)", true }, /* bluez */ + {}, +}; + static inline bool aead_sufficient_data(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); @@ -344,6 +349,12 @@ static struct proto_ops algif_aead_ops_nokey = { static void *aead_bind(const char *name) { + int err; + + err = af_alg_check_restriction(name, aead_allowlist); + if (err) + return ERR_PTR(err); + return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK); } diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 5452ad6c1506..a8d958d51ece 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -16,6 +16,24 @@ #include #include +static const struct af_alg_allowlist_entry hash_allowlist[] = { + { "cmac(aes)", true }, /* iwd, bluez */ + { "hmac(md5)", true }, /* iwd */ + { "hmac(sha1)", true }, /* iwd */ + { "hmac(sha224)", true }, /* iwd */ + { "hmac(sha256)", true }, /* iwd */ + { "hmac(sha384)", true }, /* iwd */ + { "hmac(sha512)", true }, /* iwd, sha512hmac */ + { "md4", true }, /* iwd */ + { "md5", true }, /* iwd */ + { "sha1", false }, /* iwd, iproute2 < 7.0 */ + { "sha224", true }, /* iwd */ + { "sha256", true }, /* iwd */ + { "sha384", true }, /* iwd */ + { "sha512", true }, /* iwd */ + {}, +}; + struct hash_ctx { struct af_alg_sgl sgl; @@ -382,6 +400,12 @@ static struct proto_ops algif_hash_ops_nokey = { static void *hash_bind(const char *name) { + int err; + + err = af_alg_check_restriction(name, hash_allowlist); + if (err) + return ERR_PTR(err); + return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK); } diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c index 4dfe7899f8fa..bd522915d56d 100644 --- a/crypto/algif_rng.c +++ b/crypto/algif_rng.c @@ -50,6 +50,10 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stephan Mueller "); MODULE_DESCRIPTION("User-space interface for random number generators"); +static const struct af_alg_allowlist_entry rng_allowlist[] = { + {}, +}; + struct rng_ctx { #define MAXSIZE 128 unsigned int len; @@ -201,6 +205,11 @@ static void *rng_bind(const char *name) { struct rng_parent_ctx *pctx; struct crypto_rng *rng; + int err; + + err = af_alg_check_restriction(name, rng_allowlist); + if (err) + return ERR_PTR(err); pctx = kzalloc_obj(*pctx); if (!pctx) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index df20bdfe1f1f..2b8069667974 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -34,6 +34,20 @@ #include #include +static const struct af_alg_allowlist_entry skcipher_allowlist[] = { + { "adiantum(xchacha12,aes)", false }, /* cryptsetup */ + { "adiantum(xchacha20,aes)", false }, /* cryptsetup */ + { "cbc(aes)", true }, /* iwd */ + { "cbc(des)", true }, /* iwd */ + { "cbc(des3_ede)", true }, /* iwd */ + { "ctr(aes)", true }, /* iwd */ + { "ecb(aes)", true }, /* iwd, bluez */ + { "ecb(des)", true }, /* iwd */ + { "hctr2(aes)", false }, /* cryptsetup */ + { "xts(aes)", false }, /* cryptsetup benchmark */ + {}, +}; + static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { @@ -309,6 +323,12 @@ static struct proto_ops algif_skcipher_ops_nokey = { static void *skcipher_bind(const char *name) { + int err; + + err = af_alg_check_restriction(name, skcipher_allowlist); + if (err) + return ERR_PTR(err); + return crypto_alloc_skcipher(name, 0, AF_ALG_CRYPTOAPI_MASK); } diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 7643ba954125..4e9ed8e73403 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -161,9 +161,17 @@ struct af_alg_ctx { unsigned int inflight; }; +struct af_alg_allowlist_entry { + const char *name; + bool privileged; +}; + int af_alg_register_type(const struct af_alg_type *type); int af_alg_unregister_type(const struct af_alg_type *type); +int af_alg_check_restriction(const char *name, + const struct af_alg_allowlist_entry allowlist[]); + int af_alg_release(struct socket *sock); void af_alg_release_parent(struct sock *sk); int af_alg_accept(struct sock *sk, struct socket *newsock, -- cgit v1.2.3 From d4e273a5065f81ca86eca48cb3fed55867cc0115 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 11 Jul 2026 16:52:17 +0200 Subject: crypto: powerpc/aes - use bool for encryption/decryption flag Use bool for the CBC encryption/decryption flag passed through p8_aes_cbc_crypt() to aes_p8_cbc_encrypt(). Signed-off-by: Thorsten Blum Reviewed-by: Breno Leitao Signed-off-by: Herbert Xu --- arch/powerpc/crypto/aes_cbc.c | 6 +++--- include/crypto/aes.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/powerpc/crypto/aes_cbc.c b/arch/powerpc/crypto/aes_cbc.c index 4a9f285f0970..9c271b4642c8 100644 --- a/arch/powerpc/crypto/aes_cbc.c +++ b/arch/powerpc/crypto/aes_cbc.c @@ -72,7 +72,7 @@ static int p8_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key, return ret ? -EINVAL : 0; } -static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc) +static int p8_aes_cbc_crypt(struct skcipher_request *req, bool enc) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); const struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); @@ -110,12 +110,12 @@ static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc) static int p8_aes_cbc_encrypt(struct skcipher_request *req) { - return p8_aes_cbc_crypt(req, 1); + return p8_aes_cbc_crypt(req, true); } static int p8_aes_cbc_decrypt(struct skcipher_request *req) { - return p8_aes_cbc_crypt(req, 0); + return p8_aes_cbc_crypt(req, false); } struct skcipher_alg p8_aes_cbc_alg = { diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 16fbfd93e2bd..3279cfa54608 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -259,7 +259,7 @@ int aes_p8_set_decrypt_key(const u8 *userKey, const int bits, void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key); void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len, - const struct p8_aes_key *key, u8 *iv, const int enc); + const struct p8_aes_key *key, u8 *iv, bool enc); void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len, const struct p8_aes_key *key, const u8 *iv); void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len, -- cgit v1.2.3 From a264cb967dbdbf9544c4de80e2f7188214b93f77 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 24 Jul 2026 18:42:53 -0700 Subject: crypto: af_alg - clean up kernel-doc warnings - add missing struct member @wait, drop @completion - convert function comments to kernel-doc format - for af_alg_readable(), change comments from "writable" to "readable" Warning: include/crypto/if_alg.h:161 struct member 'wait' not described in 'af_alg_ctx' Warning: include/crypto/if_alg.h:161 Excess struct member 'completion' description in 'af_alg_ctx' Warning: include/crypto/if_alg.h:187 This comment starts with '/**', but isn't a kernel-doc comment. * Size of available buffer for sending data from user space to kernel. Warning: include/crypto/if_alg.h:202 This comment starts with '/**', but isn't a kernel-doc comment. * Can the send buffer still be written to? Warning: include/crypto/if_alg.h:213 This comment starts with '/**', but isn't a kernel-doc comment. * Size of available buffer used by kernel for the RX user space operation. Warning: include/crypto/if_alg.h:228 This comment starts with '/**', but isn't a kernel-doc comment. * Can the RX buffer still be written to? Signed-off-by: Randy Dunlap Signed-off-by: Herbert Xu --- include/crypto/if_alg.h | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index 4e9ed8e73403..dbf6a97c72a2 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -121,7 +121,7 @@ struct af_alg_async_req { * @iv: IV for cipher operation * @state: Existing state for continuing operation * @aead_assoclen: Length of AAD for AEAD cipher operations - * @completion: Work queue for synchronous operation + * @wait: For waiting for completion of async crypto ops * @used: TX bytes sent to kernel. This variable is used to * ensure that user space cannot cause the kernel * to allocate too much memory in sendmsg operation. @@ -185,10 +185,11 @@ static inline struct alg_sock *alg_sk(struct sock *sk) } /** - * Size of available buffer for sending data from user space to kernel. + * af_alg_sndbuf - Size of available buffer for sending data from user space to kernel. * - * @sk socket of connection to user space - * @return number of bytes still available + * @sk: socket of connection to user space + * + * Returns: number of bytes still available */ static inline int af_alg_sndbuf(struct sock *sk) { @@ -200,10 +201,11 @@ static inline int af_alg_sndbuf(struct sock *sk) } /** - * Can the send buffer still be written to? + * af_alg_writable - Can the send buffer still be written to? + * + * @sk: socket of connection to user space * - * @sk socket of connection to user space - * @return true => writable, false => not writable + * Returns: true => writable, false => not writable */ static inline bool af_alg_writable(struct sock *sk) { @@ -211,10 +213,11 @@ static inline bool af_alg_writable(struct sock *sk) } /** - * Size of available buffer used by kernel for the RX user space operation. + * af_alg_rcvbuf - Size of available buffer used by kernel for the RX user space operation. * - * @sk socket of connection to user space - * @return number of bytes still available + * @sk: socket of connection to user space + * + * Returns: number of bytes still available */ static inline int af_alg_rcvbuf(struct sock *sk) { @@ -226,10 +229,11 @@ static inline int af_alg_rcvbuf(struct sock *sk) } /** - * Can the RX buffer still be written to? + * af_alg_readable - Can the RX buffer still be read from? + * + * @sk: socket of connection to user space * - * @sk socket of connection to user space - * @return true => writable, false => not writable + * Returns: true => readable, false => not readable */ static inline bool af_alg_readable(struct sock *sk) { -- cgit v1.2.3 From 389a3c294ae914efd1681f5355b07ed8b439678d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Jul 2026 22:17:10 -0700 Subject: crypto: ccp - don't abuse kernel-doc comment format Use plain C "/*" notation for comments that are not in kernel-doc format to avoid kernel-doc warnings: Warning: include/uapi/linux/psp-sfs.h:18 expecting prototype for SFS(). Prototype was for PAYLOAD_NAME_SIZE() instead Warning: include/uapi/linux/psp-sfs.h:46 This comment starts with '/**', but isn't a kernel-doc comment. * Seamless Firmware Support (SFS) IOC Fixes: 648dbccc03a0 ("crypto: ccp - Add AMD Seamless Firmware Servicing (SFS) driver") Signed-off-by: Randy Dunlap Acked-by: Tom Lendacky Signed-off-by: Herbert Xu --- include/uapi/linux/psp-sfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/psp-sfs.h b/include/uapi/linux/psp-sfs.h index 94e51670383c..fe9402c8a575 100644 --- a/include/uapi/linux/psp-sfs.h +++ b/include/uapi/linux/psp-sfs.h @@ -12,7 +12,7 @@ #include -/** +/* * SFS: AMD Seamless Firmware Support (SFS) interface */ @@ -43,7 +43,7 @@ struct sfs_user_update_package { __u32 sfs_extended_status; } __packed; -/** +/* * Seamless Firmware Support (SFS) IOC * * possible return codes for all SFS IOCTLs: -- cgit v1.2.3 From 967cfc046d7403de9c423a06ec1b0caecdb74463 Mon Sep 17 00:00:00 2001 From: Paul Louvel Date: Thu, 30 Jul 2026 17:48:41 +0200 Subject: crypto: ecdsa - Fix typo in function documentation Fix the misspelling of 'validate' in crypto_ecdh_shared_secret() and ecc_is_pubkey_valid_partial() documentation. Signed-off-by: Paul Louvel Signed-off-by: Herbert Xu --- include/crypto/internal/ecc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h index a4b48d76f53a..d67fe13a543a 100644 --- a/include/crypto/internal/ecc.h +++ b/include/crypto/internal/ecc.h @@ -149,7 +149,7 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, * @curve: elliptic curve domain parameters * @pk: public key as a point * - * Valdiate public key according to SP800-56A section 5.6.2.3.4 ECC Partial + * Validate public key according to SP800-56A section 5.6.2.3.4 ECC Partial * Public-Key Validation Routine. * * Note: There is no check that the public key is in the correct elliptic curve @@ -166,7 +166,7 @@ int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve, * @curve: elliptic curve domain parameters * @pk: public key as a point * - * Valdiate public key according to SP800-56A section 5.6.2.3.3 ECC Full + * Validate public key according to SP800-56A section 5.6.2.3.3 ECC Full * Public-Key Validation Routine. * * Return: 0 if validation is successful, -EINVAL if validation is failed. -- cgit v1.2.3 From 185c67edbb7cb7233de57168b612c08cdec8f1ac Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 2 Aug 2026 16:00:54 -0700 Subject: crypto: af_alg - Replace 'bool privileged' with flags It isn't obvious what false/true mean at the definition sites, so let's replace it with flags instead. Also flip the polarity to make the default zero-initialized value be the secure (privileged-only) value. Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/af_alg.c | 3 ++- crypto/algif_aead.c | 2 +- crypto/algif_hash.c | 28 ++++++++++++++-------------- crypto/algif_skcipher.c | 28 ++++++++++++++-------------- include/crypto/if_alg.h | 6 +++++- 5 files changed, 36 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 34b801568fba..1e5da61b315c 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -146,7 +146,8 @@ int af_alg_check_restriction(const char *name, for (const struct af_alg_allowlist_entry *ent = allowlist; ent->name; ent++) { if (strcmp(name, ent->name) == 0 && - (!ent->privileged || af_alg_capable())) + ((ent->flags & AF_ALG_UNPRIVILEGED) || + af_alg_capable())) return 0; } } diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index b9217f9086aa..5574e2d70539 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -35,7 +35,7 @@ #include static const struct af_alg_allowlist_entry aead_allowlist[] = { - { "ccm(aes)", true }, /* bluez */ + { "ccm(aes)" }, /* bluez */ {}, }; diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index a8d958d51ece..6e8b5fb82a7f 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -17,20 +17,20 @@ #include static const struct af_alg_allowlist_entry hash_allowlist[] = { - { "cmac(aes)", true }, /* iwd, bluez */ - { "hmac(md5)", true }, /* iwd */ - { "hmac(sha1)", true }, /* iwd */ - { "hmac(sha224)", true }, /* iwd */ - { "hmac(sha256)", true }, /* iwd */ - { "hmac(sha384)", true }, /* iwd */ - { "hmac(sha512)", true }, /* iwd, sha512hmac */ - { "md4", true }, /* iwd */ - { "md5", true }, /* iwd */ - { "sha1", false }, /* iwd, iproute2 < 7.0 */ - { "sha224", true }, /* iwd */ - { "sha256", true }, /* iwd */ - { "sha384", true }, /* iwd */ - { "sha512", true }, /* iwd */ + { "cmac(aes)" }, /* iwd, bluez */ + { "hmac(md5)" }, /* iwd */ + { "hmac(sha1)" }, /* iwd */ + { "hmac(sha224)" }, /* iwd */ + { "hmac(sha256)" }, /* iwd */ + { "hmac(sha384)" }, /* iwd */ + { "hmac(sha512)" }, /* iwd, sha512hmac */ + { "md4" }, /* iwd */ + { "md5" }, /* iwd */ + { "sha1", AF_ALG_UNPRIVILEGED }, /* iwd, iproute2 < 7.0 */ + { "sha224" }, /* iwd */ + { "sha256" }, /* iwd */ + { "sha384" }, /* iwd */ + { "sha512" }, /* iwd */ {}, }; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 68b48d805e92..1e61fe6e24b9 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -36,20 +36,20 @@ #include static const struct af_alg_allowlist_entry skcipher_allowlist[] = { - { "adiantum(xchacha12,aes)", false }, /* cryptsetup */ - { "adiantum(xchacha20,aes)", false }, /* cryptsetup */ - { "cbc(aes)", true }, /* iwd */ - { "cbc(des)", true }, /* iwd */ - { "cbc(des3_ede)", true }, /* iwd */ - { "cbc(paes)", true }, /* caam and others */ - { "ctr(aes)", true }, /* iwd */ - { "ecb(aes)", true }, /* iwd, bluez */ - { "ecb(des)", true }, /* iwd */ - { "hctr2(aes)", false }, /* cryptsetup */ - { "xts(aes)", false }, /* cryptsetup benchmark */ - { "xts(camellia)", false }, /* cryptsetup */ - { "xts(serpent)", false }, /* cryptsetup */ - { "xts(twofish)", false }, /* cryptsetup */ + { "adiantum(xchacha12,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "adiantum(xchacha20,aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "cbc(aes)" }, /* iwd */ + { "cbc(des)" }, /* iwd */ + { "cbc(des3_ede)" }, /* iwd */ + { "cbc(paes)" }, /* caam and others */ + { "ctr(aes)" }, /* iwd */ + { "ecb(aes)" }, /* iwd, bluez */ + { "ecb(des)" }, /* iwd */ + { "hctr2(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "xts(aes)", AF_ALG_UNPRIVILEGED }, /* cryptsetup benchmark */ + { "xts(camellia)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "xts(serpent)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ + { "xts(twofish)", AF_ALG_UNPRIVILEGED }, /* cryptsetup */ {}, }; diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index dbf6a97c72a2..0d51428c1da4 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -8,6 +8,7 @@ #ifndef _CRYPTO_IF_ALG_H #define _CRYPTO_IF_ALG_H +#include #include #include #include @@ -161,9 +162,12 @@ struct af_alg_ctx { unsigned int inflight; }; +/* Flags for af_alg_allowlist_entry::flags: */ +#define AF_ALG_UNPRIVILEGED BIT(0) /* Unprivileged use is allowed */ + struct af_alg_allowlist_entry { const char *name; - bool privileged; + u32 flags; }; int af_alg_register_type(const struct af_alg_type *type); -- cgit v1.2.3