--- /dev/null
+From 60c2837711ad6d3be46b410456ba365861aa29a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jun 2026 22:25:11 -0400
+Subject: crypto: qat - remove unused character device and IOCTLs
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit d237230728c567297f2f98b425d63156ab2ed17f ]
+
+The QAT driver exposes a character device (qat_adf_ctl) with IOCTLs
+for device configuration, start, stop, status query and enumeration.
+These IOCTLs are not part of any public uAPI header and have no known
+in-tree or out-of-tree users. Device lifecycle is already managed via
+sysfs.
+
+The ioctl interface also increases the attack surface and is the
+subject of a number of bug reports.
+
+Remove the character device, the IOCTL definitions, and the related
+data structures (adf_dev_status_info, adf_user_cfg_key_val,
+adf_user_cfg_section, adf_user_cfg_ctl_data). Drop the now-unused
+adf_cfg_user.h header and strip adf_ctl_drv.c down to the minimal
+module_init/module_exit hooks for workqueue, AER, and crypto/compression
+algorithm registration.
+
+Clean up leftover dead code that was only reachable from the removed
+IOCTL paths: adf_cfg_del_all(), adf_devmgr_verify_id(),
+adf_devmgr_get_num_dev(), adf_devmgr_get_dev_by_id(),
+adf_get_vf_real_id() and the unused ADF_CFG macros.
+
+Additionally, drop the entry associated to QAT IOCTLs in
+ioctl-number.rst.
+
+Cc: stable@vger.kernel.org
+Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework")
+Reported-by: Zhi Wang <wangzhi@stu.xidian.edu.cn>
+Reported-by: Bin Yu <byu@xidian.edu.cn>
+Reported-by: MingYu Wang <w15303746062@163.com>
+Closes: https://lore.kernel.org/all/61d6d499.ab89.19b9b7f3186.Coremail.wangzhi_xd@stu.xidian.edu.cn/
+Link: https://lore.kernel.org/all/20260508034841.256794-1-w15303746062@163.com/
+Link: https://lore.kernel.org/all/20260508023542.256299-1-w15303746062@163.com/
+Link: https://lore.kernel.org/all/20260504025120.98242-1-w15303746062@163.com/
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Ahsan Atta <ahsan.atta@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../userspace-api/ioctl/ioctl-number.rst | 1 -
+ .../crypto/qat/qat_common/adf_cfg_common.h | 32 --
+ drivers/crypto/qat/qat_common/adf_cfg_user.h | 38 --
+ .../crypto/qat/qat_common/adf_common_drv.h | 3 -
+ drivers/crypto/qat/qat_common/adf_ctl_drv.c | 409 +-----------------
+ drivers/crypto/qat/qat_common/adf_dev_mgr.c | 70 ---
+ 6 files changed, 3 insertions(+), 550 deletions(-)
+ delete mode 100644 drivers/crypto/qat/qat_common/adf_cfg_user.h
+
+diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
+index aa8d0cf534a3d6..7c6e78f4eba07e 100644
+--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
++++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
+@@ -215,7 +215,6 @@ Code Seq# Include File Comments
+ <mailto:gregkh@linuxfoundation.org>
+ 'a' all linux/atm*.h, linux/sonet.h ATM on linux
+ <http://lrcwww.epfl.ch/>
+-'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
+ 'b' 00-FF conflict! bit3 vme host bridge
+ <mailto:natalia@nikhefk.nikhef.nl>
+ 'c' all linux/cm4000_cs.h conflict!
+diff --git a/drivers/crypto/qat/qat_common/adf_cfg_common.h b/drivers/crypto/qat/qat_common/adf_cfg_common.h
+index 1ef46ccfba47b1..cf0d29cc58e87f 100644
+--- a/drivers/crypto/qat/qat_common/adf_cfg_common.h
++++ b/drivers/crypto/qat/qat_common/adf_cfg_common.h
+@@ -4,18 +4,11 @@
+ #define ADF_CFG_COMMON_H_
+
+ #include <linux/types.h>
+-#include <linux/ioctl.h>
+
+ #define ADF_CFG_MAX_STR_LEN 64
+ #define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+ #define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+ #define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+-#define ADF_CFG_BASE_DEC 10
+-#define ADF_CFG_BASE_HEX 16
+-#define ADF_CFG_ALL_DEVICES 0xFE
+-#define ADF_CFG_NO_DEVICE 0xFF
+-#define ADF_CFG_AFFINITY_WHATEVER 0xFF
+-#define MAX_DEVICE_NAME_SIZE 32
+ #define ADF_MAX_DEVICES (32 * 32)
+ #define ADF_DEVS_ARRAY_SIZE BITS_TO_LONGS(ADF_MAX_DEVICES)
+
+@@ -34,29 +27,4 @@ enum adf_device_type {
+ DEV_C3XXX,
+ DEV_C3XXXVF
+ };
+-
+-struct adf_dev_status_info {
+- enum adf_device_type type;
+- __u32 accel_id;
+- __u32 instance_id;
+- __u8 num_ae;
+- __u8 num_accel;
+- __u8 num_logical_accel;
+- __u8 banks_per_accel;
+- __u8 state;
+- __u8 bus;
+- __u8 dev;
+- __u8 fun;
+- char name[MAX_DEVICE_NAME_SIZE];
+-};
+-
+-#define ADF_CTL_IOC_MAGIC 'a'
+-#define IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS _IOW(ADF_CTL_IOC_MAGIC, 0, \
+- struct adf_user_cfg_ctl_data)
+-#define IOCTL_STOP_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 1, \
+- struct adf_user_cfg_ctl_data)
+-#define IOCTL_START_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 2, \
+- struct adf_user_cfg_ctl_data)
+-#define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, __u32)
+-#define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, __s32)
+ #endif
+diff --git a/drivers/crypto/qat/qat_common/adf_cfg_user.h b/drivers/crypto/qat/qat_common/adf_cfg_user.h
+deleted file mode 100644
+index 421f4fb8b4dd2f..00000000000000
+--- a/drivers/crypto/qat/qat_common/adf_cfg_user.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */
+-/* Copyright(c) 2014 - 2020 Intel Corporation */
+-#ifndef ADF_CFG_USER_H_
+-#define ADF_CFG_USER_H_
+-
+-#include "adf_cfg_common.h"
+-#include "adf_cfg_strings.h"
+-
+-struct adf_user_cfg_key_val {
+- char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+- char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+- union {
+- struct adf_user_cfg_key_val *next;
+- __u64 padding3;
+- };
+- enum adf_cfg_val_type type;
+-} __packed;
+-
+-struct adf_user_cfg_section {
+- char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES];
+- union {
+- struct adf_user_cfg_key_val *params;
+- __u64 padding1;
+- };
+- union {
+- struct adf_user_cfg_section *next;
+- __u64 padding3;
+- };
+-} __packed;
+-
+-struct adf_user_cfg_ctl_data {
+- union {
+- struct adf_user_cfg_section *config_section;
+- __u64 padding;
+- };
+- __u8 device_id;
+-} __packed;
+-#endif
+diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
+index 469e06c93fafeb..e84b1ca844032a 100644
+--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
++++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
+@@ -79,11 +79,8 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev,
+ void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev,
+ struct adf_accel_dev *pf);
+ struct list_head *adf_devmgr_get_head(void);
+-struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id);
+ struct adf_accel_dev *adf_devmgr_get_first(void);
+ struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev);
+-int adf_devmgr_verify_id(u32 id);
+-void adf_devmgr_get_num_dev(u32 *num);
+ int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev);
+ int adf_dev_started(struct adf_accel_dev *accel_dev);
+ int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev);
+diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+index 543ffe00de67b2..ba220f5d35a66b 100644
+--- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c
++++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+@@ -1,412 +1,14 @@
+ // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
+ /* Copyright(c) 2014 - 2020 Intel Corporation */
++
++#include <crypto/algapi.h>
++#include <linux/errno.h>
+ #include <linux/module.h>
+-#include <linux/mutex.h>
+-#include <linux/slab.h>
+-#include <linux/fs.h>
+-#include <linux/bitops.h>
+-#include <linux/pci.h>
+-#include <linux/cdev.h>
+-#include <linux/uaccess.h>
+-#include <linux/crypto.h>
+
+-#include "adf_accel_devices.h"
+ #include "adf_common_drv.h"
+-#include "adf_cfg.h"
+-#include "adf_cfg_common.h"
+-#include "adf_cfg_user.h"
+-
+-#define DEVICE_NAME "qat_adf_ctl"
+-
+-static DEFINE_MUTEX(adf_ctl_lock);
+-static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
+-
+-static const struct file_operations adf_ctl_ops = {
+- .owner = THIS_MODULE,
+- .unlocked_ioctl = adf_ctl_ioctl,
+- .compat_ioctl = compat_ptr_ioctl,
+-};
+-
+-struct adf_ctl_drv_info {
+- unsigned int major;
+- struct cdev drv_cdev;
+- struct class *drv_class;
+-};
+-
+-static struct adf_ctl_drv_info adf_ctl_drv;
+-
+-static void adf_chr_drv_destroy(void)
+-{
+- device_destroy(adf_ctl_drv.drv_class, MKDEV(adf_ctl_drv.major, 0));
+- cdev_del(&adf_ctl_drv.drv_cdev);
+- class_destroy(adf_ctl_drv.drv_class);
+- unregister_chrdev_region(MKDEV(adf_ctl_drv.major, 0), 1);
+-}
+-
+-static int adf_chr_drv_create(void)
+-{
+- dev_t dev_id;
+- struct device *drv_device;
+-
+- if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
+- pr_err("QAT: unable to allocate chrdev region\n");
+- return -EFAULT;
+- }
+-
+- adf_ctl_drv.drv_class = class_create(THIS_MODULE, DEVICE_NAME);
+- if (IS_ERR(adf_ctl_drv.drv_class)) {
+- pr_err("QAT: class_create failed for adf_ctl\n");
+- goto err_chrdev_unreg;
+- }
+- adf_ctl_drv.major = MAJOR(dev_id);
+- cdev_init(&adf_ctl_drv.drv_cdev, &adf_ctl_ops);
+- if (cdev_add(&adf_ctl_drv.drv_cdev, dev_id, 1)) {
+- pr_err("QAT: cdev add failed\n");
+- goto err_class_destr;
+- }
+-
+- drv_device = device_create(adf_ctl_drv.drv_class, NULL,
+- MKDEV(adf_ctl_drv.major, 0),
+- NULL, DEVICE_NAME);
+- if (IS_ERR(drv_device)) {
+- pr_err("QAT: failed to create device\n");
+- goto err_cdev_del;
+- }
+- return 0;
+-err_cdev_del:
+- cdev_del(&adf_ctl_drv.drv_cdev);
+-err_class_destr:
+- class_destroy(adf_ctl_drv.drv_class);
+-err_chrdev_unreg:
+- unregister_chrdev_region(dev_id, 1);
+- return -EFAULT;
+-}
+-
+-static struct adf_user_cfg_ctl_data *adf_ctl_alloc_resources(unsigned long arg)
+-{
+- struct adf_user_cfg_ctl_data *cfg_data;
+-
+- cfg_data = memdup_user((void __user *)arg, sizeof(*cfg_data));
+- if (IS_ERR(cfg_data))
+- pr_err("QAT: failed to copy from user cfg_data.\n");
+- return cfg_data;
+-}
+-
+-static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
+- const char *section,
+- const struct adf_user_cfg_key_val *key_val)
+-{
+- if (key_val->type == ADF_HEX) {
+- long *ptr = (long *)key_val->val;
+- long val = *ptr;
+-
+- if (adf_cfg_add_key_value_param(accel_dev, section,
+- key_val->key, (void *)val,
+- key_val->type)) {
+- dev_err(&GET_DEV(accel_dev),
+- "failed to add hex keyvalue.\n");
+- return -EFAULT;
+- }
+- } else {
+- if (adf_cfg_add_key_value_param(accel_dev, section,
+- key_val->key, key_val->val,
+- key_val->type)) {
+- dev_err(&GET_DEV(accel_dev),
+- "failed to add keyvalue.\n");
+- return -EFAULT;
+- }
+- }
+- return 0;
+-}
+-
+-static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
+- struct adf_user_cfg_ctl_data *ctl_data)
+-{
+- struct adf_user_cfg_key_val key_val;
+- struct adf_user_cfg_key_val *params_head;
+- struct adf_user_cfg_section section, *section_head;
+-
+- section_head = ctl_data->config_section;
+-
+- while (section_head) {
+- if (copy_from_user(§ion, (void __user *)section_head,
+- sizeof(*section_head))) {
+- dev_err(&GET_DEV(accel_dev),
+- "failed to copy section info\n");
+- goto out_err;
+- }
+-
+- if (adf_cfg_section_add(accel_dev, section.name)) {
+- dev_err(&GET_DEV(accel_dev),
+- "failed to add section.\n");
+- goto out_err;
+- }
+-
+- params_head = section.params;
+-
+- while (params_head) {
+- if (copy_from_user(&key_val, (void __user *)params_head,
+- sizeof(key_val))) {
+- dev_err(&GET_DEV(accel_dev),
+- "Failed to copy keyvalue.\n");
+- goto out_err;
+- }
+- if (adf_add_key_value_data(accel_dev, section.name,
+- &key_val)) {
+- goto out_err;
+- }
+- params_head = key_val.next;
+- }
+- section_head = section.next;
+- }
+- return 0;
+-out_err:
+- adf_cfg_del_all(accel_dev);
+- return -EFAULT;
+-}
+-
+-static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
+- unsigned long arg)
+-{
+- struct adf_user_cfg_ctl_data *ctl_data;
+- struct adf_accel_dev *accel_dev;
+- int ret = 0;
+-
+- ctl_data = adf_ctl_alloc_resources(arg);
+- if (IS_ERR(ctl_data))
+- return PTR_ERR(ctl_data);
+-
+- accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+- if (!accel_dev) {
+- ret = -EFAULT;
+- goto out;
+- }
+-
+- if (adf_dev_started(accel_dev)) {
+- ret = -EFAULT;
+- goto out;
+- }
+-
+- if (adf_copy_key_value_data(accel_dev, ctl_data)) {
+- ret = -EFAULT;
+- goto out;
+- }
+- set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+-out:
+- kfree(ctl_data);
+- return ret;
+-}
+-
+-static int adf_ctl_is_device_in_use(int id)
+-{
+- struct adf_accel_dev *dev;
+-
+- list_for_each_entry(dev, adf_devmgr_get_head(), list) {
+- if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+- if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
+- dev_info(&GET_DEV(dev),
+- "device qat_dev%d is busy\n",
+- dev->accel_id);
+- return -EBUSY;
+- }
+- }
+- }
+- return 0;
+-}
+-
+-static void adf_ctl_stop_devices(u32 id)
+-{
+- struct adf_accel_dev *accel_dev;
+-
+- list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
+- if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+- if (!adf_dev_started(accel_dev))
+- continue;
+-
+- /* First stop all VFs */
+- if (!accel_dev->is_vf)
+- continue;
+-
+- adf_dev_stop(accel_dev);
+- adf_dev_shutdown(accel_dev);
+- }
+- }
+-
+- list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
+- if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+- if (!adf_dev_started(accel_dev))
+- continue;
+-
+- adf_dev_stop(accel_dev);
+- adf_dev_shutdown(accel_dev);
+- }
+- }
+-}
+-
+-static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
+- unsigned long arg)
+-{
+- int ret;
+- struct adf_user_cfg_ctl_data *ctl_data;
+-
+- ctl_data = adf_ctl_alloc_resources(arg);
+- if (IS_ERR(ctl_data))
+- return PTR_ERR(ctl_data);
+-
+- if (adf_devmgr_verify_id(ctl_data->device_id)) {
+- pr_err("QAT: Device %d not found\n", ctl_data->device_id);
+- ret = -ENODEV;
+- goto out;
+- }
+-
+- ret = adf_ctl_is_device_in_use(ctl_data->device_id);
+- if (ret)
+- goto out;
+-
+- if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
+- pr_info("QAT: Stopping all acceleration devices.\n");
+- else
+- pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
+- ctl_data->device_id);
+-
+- adf_ctl_stop_devices(ctl_data->device_id);
+-
+-out:
+- kfree(ctl_data);
+- return ret;
+-}
+-
+-static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
+- unsigned long arg)
+-{
+- int ret;
+- struct adf_user_cfg_ctl_data *ctl_data;
+- struct adf_accel_dev *accel_dev;
+-
+- ctl_data = adf_ctl_alloc_resources(arg);
+- if (IS_ERR(ctl_data))
+- return PTR_ERR(ctl_data);
+-
+- ret = -ENODEV;
+- accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+- if (!accel_dev)
+- goto out;
+-
+- if (!adf_dev_started(accel_dev)) {
+- dev_info(&GET_DEV(accel_dev),
+- "Starting acceleration device qat_dev%d.\n",
+- ctl_data->device_id);
+- ret = adf_dev_init(accel_dev);
+- if (!ret)
+- ret = adf_dev_start(accel_dev);
+- } else {
+- dev_info(&GET_DEV(accel_dev),
+- "Acceleration device qat_dev%d already started.\n",
+- ctl_data->device_id);
+- }
+- if (ret) {
+- dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
+- ctl_data->device_id);
+- adf_dev_stop(accel_dev);
+- adf_dev_shutdown(accel_dev);
+- }
+-out:
+- kfree(ctl_data);
+- return ret;
+-}
+-
+-static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
+- unsigned long arg)
+-{
+- u32 num_devices = 0;
+-
+- adf_devmgr_get_num_dev(&num_devices);
+- if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
+- unsigned long arg)
+-{
+- struct adf_hw_device_data *hw_data;
+- struct adf_dev_status_info dev_info;
+- struct adf_accel_dev *accel_dev;
+-
+- if (copy_from_user(&dev_info, (void __user *)arg,
+- sizeof(struct adf_dev_status_info))) {
+- pr_err("QAT: failed to copy from user.\n");
+- return -EFAULT;
+- }
+-
+- accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
+- if (!accel_dev)
+- return -ENODEV;
+-
+- hw_data = accel_dev->hw_device;
+- dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
+- dev_info.num_ae = hw_data->get_num_aes(hw_data);
+- dev_info.num_accel = hw_data->get_num_accels(hw_data);
+- dev_info.num_logical_accel = hw_data->num_logical_accel;
+- dev_info.banks_per_accel = hw_data->num_banks
+- / hw_data->num_logical_accel;
+- strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
+- dev_info.instance_id = hw_data->instance_id;
+- dev_info.type = hw_data->dev_class->type;
+- dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
+- dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
+- dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
+-
+- if (copy_to_user((void __user *)arg, &dev_info,
+- sizeof(struct adf_dev_status_info))) {
+- dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+-{
+- int ret;
+-
+- if (mutex_lock_interruptible(&adf_ctl_lock))
+- return -EFAULT;
+-
+- switch (cmd) {
+- case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
+- ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
+- break;
+-
+- case IOCTL_STOP_ACCEL_DEV:
+- ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
+- break;
+-
+- case IOCTL_START_ACCEL_DEV:
+- ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
+- break;
+-
+- case IOCTL_GET_NUM_DEVICES:
+- ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
+- break;
+-
+- case IOCTL_STATUS_ACCEL_DEV:
+- ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
+- break;
+- default:
+- pr_err("QAT: Invalid ioctl\n");
+- ret = -EFAULT;
+- break;
+- }
+- mutex_unlock(&adf_ctl_lock);
+- return ret;
+-}
+
+ static int __init adf_register_ctl_device_driver(void)
+ {
+- if (adf_chr_drv_create())
+- goto err_chr_dev;
+-
+ if (adf_init_aer())
+ goto err_aer;
+
+@@ -428,21 +30,16 @@ static int __init adf_register_ctl_device_driver(void)
+ err_pf_wq:
+ adf_exit_aer();
+ err_aer:
+- adf_chr_drv_destroy();
+-err_chr_dev:
+- mutex_destroy(&adf_ctl_lock);
+ return -EFAULT;
+ }
+
+ static void __exit adf_unregister_ctl_device_driver(void)
+ {
+- adf_chr_drv_destroy();
+ adf_exit_aer();
+ adf_exit_vf_wq();
+ adf_exit_pf_wq();
+ qat_crypto_unregister();
+ adf_clean_vf_map(false);
+- mutex_destroy(&adf_ctl_lock);
+ }
+
+ module_init(adf_register_ctl_device_driver);
+diff --git a/drivers/crypto/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/qat/qat_common/adf_dev_mgr.c
+index 92ec035576dfd8..9c4dd70865b3b8 100644
+--- a/drivers/crypto/qat/qat_common/adf_dev_mgr.c
++++ b/drivers/crypto/qat/qat_common/adf_dev_mgr.c
+@@ -45,19 +45,6 @@ static struct vf_id_map *adf_find_vf(u32 bdf)
+ return NULL;
+ }
+
+-static int adf_get_vf_real_id(u32 fake)
+-{
+- struct list_head *itr;
+-
+- list_for_each(itr, &vfs_table) {
+- struct vf_id_map *ptr =
+- list_entry(itr, struct vf_id_map, list);
+- if (ptr->fake_id == fake)
+- return ptr->id;
+- }
+- return -1;
+-}
+-
+ /**
+ * adf_clean_vf_map() - Cleans VF id mapings
+ *
+@@ -311,63 +298,6 @@ struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev)
+ }
+ EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev);
+
+-struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id)
+-{
+- struct list_head *itr;
+- int real_id;
+-
+- mutex_lock(&table_lock);
+- real_id = adf_get_vf_real_id(id);
+- if (real_id < 0)
+- goto unlock;
+-
+- id = real_id;
+-
+- list_for_each(itr, &accel_table) {
+- struct adf_accel_dev *ptr =
+- list_entry(itr, struct adf_accel_dev, list);
+- if (ptr->accel_id == id) {
+- mutex_unlock(&table_lock);
+- return ptr;
+- }
+- }
+-unlock:
+- mutex_unlock(&table_lock);
+- return NULL;
+-}
+-
+-int adf_devmgr_verify_id(u32 id)
+-{
+- if (id == ADF_CFG_ALL_DEVICES)
+- return 0;
+-
+- if (adf_devmgr_get_dev_by_id(id))
+- return 0;
+-
+- return -ENODEV;
+-}
+-
+-static int adf_get_num_dettached_vfs(void)
+-{
+- struct list_head *itr;
+- int vfs = 0;
+-
+- mutex_lock(&table_lock);
+- list_for_each(itr, &vfs_table) {
+- struct vf_id_map *ptr =
+- list_entry(itr, struct vf_id_map, list);
+- if (ptr->bdf != ~0 && !ptr->attached)
+- vfs++;
+- }
+- mutex_unlock(&table_lock);
+- return vfs;
+-}
+-
+-void adf_devmgr_get_num_dev(u32 *num)
+-{
+- *num = num_devices - adf_get_num_dettached_vfs();
+-}
+-
+ /**
+ * adf_dev_in_use() - Check whether accel_dev is currently in use
+ * @accel_dev: Pointer to acceleration device.
+--
+2.53.0
+
--- /dev/null
+From f78d14b0942ca53f27ec203d4e6a8ea2de8b444f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jun 2026 22:25:09 -0400
+Subject: crypto: qat - Replace kzalloc() + copy_from_user() with memdup_user()
+
+From: Thorsten Blum <thorsten.blum@linux.dev>
+
+[ Upstream commit 1e26339703e2afd397037defa798682b2b93dcc0 ]
+
+Replace kzalloc() followed by copy_from_user() with memdup_user() to
+improve and simplify adf_ctl_alloc_resources(). memdup_user() returns
+either -ENOMEM or -EFAULT (instead of -EIO) if an error occurs.
+
+Remove the unnecessary device id initialization, since memdup_user()
+(like copy_from_user()) immediately overwrites it.
+
+No functional changes intended other than returning the more idiomatic
+error code -EFAULT.
+
+Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: d237230728c5 ("crypto: qat - remove unused character device and IOCTLs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/adf_ctl_drv.c | 13 +++----------
+ 1 file changed, 3 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+index eb9b3be9d8ebed..cd2ab4e9c7c4e6 100644
+--- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c
++++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+@@ -87,17 +87,10 @@ static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
+ {
+ struct adf_user_cfg_ctl_data *cfg_data;
+
+- cfg_data = kzalloc(sizeof(*cfg_data), GFP_KERNEL);
+- if (!cfg_data)
+- return -ENOMEM;
+-
+- /* Initialize device id to NO DEVICE as 0 is a valid device id */
+- cfg_data->device_id = ADF_CFG_NO_DEVICE;
+-
+- if (copy_from_user(cfg_data, (void __user *)arg, sizeof(*cfg_data))) {
++ cfg_data = memdup_user((void __user *)arg, sizeof(*cfg_data));
++ if (IS_ERR(cfg_data)) {
+ pr_err("QAT: failed to copy from user cfg_data.\n");
+- kfree(cfg_data);
+- return -EIO;
++ return PTR_ERR(cfg_data);
+ }
+
+ *ctl_data = cfg_data;
+--
+2.53.0
+
--- /dev/null
+From a3b092562a8386936b56858839419c847a2369a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jun 2026 22:25:10 -0400
+Subject: crypto: qat - Return pointer directly in adf_ctl_alloc_resources
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit 5ce9891ea928208a915411ce8227f8c3e37e5ad9 ]
+
+Returning values through arguments is confusing and that has
+upset the compiler with the recent change to memdup_user:
+
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c: In function ‘adf_ctl_ioctl’:
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:308:26: warning: ‘ctl_data’ may be used uninitialized [-Wmaybe-uninitialized]
+ 308 | ctl_data->device_id);
+ | ^~
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:294:39: note: ‘ctl_data’ was declared here
+ 294 | struct adf_user_cfg_ctl_data *ctl_data;
+ | ^~~~~~~~
+In function ‘adf_ctl_ioctl_dev_stop’,
+ inlined from ‘adf_ctl_ioctl’ at ../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:386:9:
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:273:48: warning: ‘ctl_data’ may be used uninitialized [-Wmaybe-uninitialized]
+ 273 | ret = adf_ctl_is_device_in_use(ctl_data->device_id);
+ | ~~~~~~~~^~~~~~~~~~~
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c: In function ‘adf_ctl_ioctl’:
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:261:39: note: ‘ctl_data’ was declared here
+ 261 | struct adf_user_cfg_ctl_data *ctl_data;
+ | ^~~~~~~~
+In function ‘adf_ctl_ioctl_dev_config’,
+ inlined from ‘adf_ctl_ioctl’ at ../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:382:9:
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:192:54: warning: ‘ctl_data’ may be used uninitialized [-Wmaybe-uninitialized]
+ 192 | accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+ | ~~~~~~~~^~~~~~~~~~~
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c: In function ‘adf_ctl_ioctl’:
+../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:185:39: note: ‘ctl_data’ was declared here
+ 185 | struct adf_user_cfg_ctl_data *ctl_data;
+ | ^~~~~~~~
+
+Fix this by returning the pointer directly.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Reviewed-by: Thorsten Blum <thorsten.blum@linux.dev>
+Acked-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: d237230728c5 ("crypto: qat - remove unused character device and IOCTLs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/adf_ctl_drv.c | 31 +++++++++------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+index cd2ab4e9c7c4e6..543ffe00de67b2 100644
+--- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c
++++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
+@@ -82,19 +82,14 @@ static int adf_chr_drv_create(void)
+ return -EFAULT;
+ }
+
+-static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
+- unsigned long arg)
++static struct adf_user_cfg_ctl_data *adf_ctl_alloc_resources(unsigned long arg)
+ {
+ struct adf_user_cfg_ctl_data *cfg_data;
+
+ cfg_data = memdup_user((void __user *)arg, sizeof(*cfg_data));
+- if (IS_ERR(cfg_data)) {
++ if (IS_ERR(cfg_data))
+ pr_err("QAT: failed to copy from user cfg_data.\n");
+- return PTR_ERR(cfg_data);
+- }
+-
+- *ctl_data = cfg_data;
+- return 0;
++ return cfg_data;
+ }
+
+ static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
+@@ -173,13 +168,13 @@ static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
+ static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+ {
+- int ret;
+ struct adf_user_cfg_ctl_data *ctl_data;
+ struct adf_accel_dev *accel_dev;
++ int ret = 0;
+
+- ret = adf_ctl_alloc_resources(&ctl_data, arg);
+- if (ret)
+- return ret;
++ ctl_data = adf_ctl_alloc_resources(arg);
++ if (IS_ERR(ctl_data))
++ return PTR_ERR(ctl_data);
+
+ accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+ if (!accel_dev) {
+@@ -254,9 +249,9 @@ static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
+ int ret;
+ struct adf_user_cfg_ctl_data *ctl_data;
+
+- ret = adf_ctl_alloc_resources(&ctl_data, arg);
+- if (ret)
+- return ret;
++ ctl_data = adf_ctl_alloc_resources(arg);
++ if (IS_ERR(ctl_data))
++ return PTR_ERR(ctl_data);
+
+ if (adf_devmgr_verify_id(ctl_data->device_id)) {
+ pr_err("QAT: Device %d not found\n", ctl_data->device_id);
+@@ -288,9 +283,9 @@ static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
+ struct adf_user_cfg_ctl_data *ctl_data;
+ struct adf_accel_dev *accel_dev;
+
+- ret = adf_ctl_alloc_resources(&ctl_data, arg);
+- if (ret)
+- return ret;
++ ctl_data = adf_ctl_alloc_resources(arg);
++ if (IS_ERR(ctl_data))
++ return PTR_ERR(ctl_data);
+
+ ret = -ENODEV;
+ accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+--
+2.53.0
+
--- /dev/null
+From 420193744e29115f4cf8624d6934291537ccb4e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jun 2026 22:25:08 -0400
+Subject: Documentation: ioctl-number: Extend "Include File" column width
+
+From: Bagas Sanjaya <bagasdotme@gmail.com>
+
+[ Upstream commit 15afd5def819e4df2a29cef6fcfa6ae7ba167c0f ]
+
+Extend width of "Include File" column to fit full path to
+papr-physical-attestation.h in later commit.
+
+Reviewed-by: Haren Myneni <haren@linux.ibm.com>
+Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com>
+Acked-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Signed-off-by: Jonathan Corbet <corbet@lwn.net>
+Link: https://lore.kernel.org/r/20250714015711.14525-3-bagasdotme@gmail.com
+Stable-dep-of: d237230728c5 ("crypto: qat - remove unused character device and IOCTLs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../userspace-api/ioctl/ioctl-number.rst | 428 +++++++++---------
+ 1 file changed, 214 insertions(+), 214 deletions(-)
+
+diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
+index a7373d4e3984cf..aa8d0cf534a3d6 100644
+--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
++++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
+@@ -66,17 +66,17 @@ This table lists ioctls visible from user land for Linux/x86. It contains
+ most drivers up to 2.6.31, but I know I am missing some. There has been
+ no attempt to list non-X86 architectures or ioctls from drivers/staging/.
+
+-==== ===== ======================================================= ================================================================
+-Code Seq# Include File Comments
++==== ===== ========================================================= ================================================================
++Code Seq# Include File Comments
+ (hex)
+-==== ===== ======================================================= ================================================================
+-0x00 00-1F linux/fs.h conflict!
+-0x00 00-1F scsi/scsi_ioctl.h conflict!
+-0x00 00-1F linux/fb.h conflict!
+-0x00 00-1F linux/wavefront.h conflict!
++==== ===== ========================================================= ================================================================
++0x00 00-1F linux/fs.h conflict!
++0x00 00-1F scsi/scsi_ioctl.h conflict!
++0x00 00-1F linux/fb.h conflict!
++0x00 00-1F linux/wavefront.h conflict!
+ 0x02 all linux/fd.h
+ 0x03 all linux/hdreg.h
+-0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these.
++0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these.
+ 0x06 all linux/lp.h
+ 0x09 all linux/raid/md_u.h
+ 0x10 00-0F drivers/char/s390/vmcp.h
+@@ -84,282 +84,282 @@ Code Seq# Include File Comments
+ 0x10 20-2F arch/s390/include/uapi/asm/hypfs.h
+ 0x12 all linux/fs.h
+ linux/blkpg.h
+-0x1b all InfiniBand Subsystem
+- <http://infiniband.sourceforge.net/>
++0x1b all InfiniBand Subsystem
++ <http://infiniband.sourceforge.net/>
+ 0x20 all drivers/cdrom/cm206.h
+ 0x22 all scsi/sg.h
+ '!' 00-1F uapi/linux/seccomp.h
+-'#' 00-3F IEEE 1394 Subsystem
+- Block for the entire subsystem
++'#' 00-3F IEEE 1394 Subsystem
++ Block for the entire subsystem
+ '$' 00-0F linux/perf_counter.h, linux/perf_event.h
+-'%' 00-0F include/uapi/linux/stm.h System Trace Module subsystem
+- <mailto:alexander.shishkin@linux.intel.com>
++'%' 00-0F include/uapi/linux/stm.h System Trace Module subsystem
++ <mailto:alexander.shishkin@linux.intel.com>
+ '&' 00-07 drivers/firewire/nosy-user.h
+-'1' 00-1F linux/timepps.h PPS kit from Ulrich Windl
+- <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
++'1' 00-1F linux/timepps.h PPS kit from Ulrich Windl
++ <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
+ '2' 01-04 linux/i2o.h
+-'3' 00-0F drivers/s390/char/raw3270.h conflict!
+-'3' 00-1F linux/suspend_ioctls.h, conflict!
++'3' 00-0F drivers/s390/char/raw3270.h conflict!
++'3' 00-1F linux/suspend_ioctls.h, conflict!
+ kernel/power/user.c
+-'8' all SNP8023 advanced NIC card
+- <mailto:mcr@solidum.com>
++'8' all SNP8023 advanced NIC card
++ <mailto:mcr@solidum.com>
+ ';' 64-7F linux/vfio.h
+-'@' 00-0F linux/radeonfb.h conflict!
+-'@' 00-0F drivers/video/aty/aty128fb.c conflict!
+-'A' 00-1F linux/apm_bios.h conflict!
+-'A' 00-0F linux/agpgart.h, conflict!
++'@' 00-0F linux/radeonfb.h conflict!
++'@' 00-0F drivers/video/aty/aty128fb.c conflict!
++'A' 00-1F linux/apm_bios.h conflict!
++'A' 00-0F linux/agpgart.h, conflict!
+ drivers/char/agp/compat_ioctl.h
+-'A' 00-7F sound/asound.h conflict!
+-'B' 00-1F linux/cciss_ioctl.h conflict!
+-'B' 00-0F include/linux/pmu.h conflict!
+-'B' C0-FF advanced bbus <mailto:maassen@uni-freiburg.de>
+-'C' all linux/soundcard.h conflict!
+-'C' 01-2F linux/capi.h conflict!
+-'C' F0-FF drivers/net/wan/cosa.h conflict!
++'A' 00-7F sound/asound.h conflict!
++'B' 00-1F linux/cciss_ioctl.h conflict!
++'B' 00-0F include/linux/pmu.h conflict!
++'B' C0-FF advanced bbus <mailto:maassen@uni-freiburg.de>
++'C' all linux/soundcard.h conflict!
++'C' 01-2F linux/capi.h conflict!
++'C' F0-FF drivers/net/wan/cosa.h conflict!
+ 'D' all arch/s390/include/asm/dasd.h
+ 'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h
+ 'D' 05 drivers/scsi/pmcraid.h
+-'E' all linux/input.h conflict!
+-'E' 00-0F xen/evtchn.h conflict!
+-'F' all linux/fb.h conflict!
+-'F' 01-02 drivers/scsi/pmcraid.h conflict!
+-'F' 20 drivers/video/fsl-diu-fb.h conflict!
+-'F' 20 drivers/video/intelfb/intelfb.h conflict!
+-'F' 20 linux/ivtvfb.h conflict!
+-'F' 20 linux/matroxfb.h conflict!
+-'F' 20 drivers/video/aty/atyfb_base.c conflict!
+-'F' 00-0F video/da8xx-fb.h conflict!
+-'F' 80-8F linux/arcfb.h conflict!
+-'F' DD video/sstfb.h conflict!
+-'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict!
+-'H' 00-7F linux/hiddev.h conflict!
+-'H' 00-0F linux/hidraw.h conflict!
+-'H' 01 linux/mei.h conflict!
+-'H' 02 linux/mei.h conflict!
+-'H' 03 linux/mei.h conflict!
+-'H' 00-0F sound/asound.h conflict!
+-'H' 20-40 sound/asound_fm.h conflict!
+-'H' 80-8F sound/sfnt_info.h conflict!
+-'H' 10-8F sound/emu10k1.h conflict!
+-'H' 10-1F sound/sb16_csp.h conflict!
+-'H' 10-1F sound/hda_hwdep.h conflict!
+-'H' 40-4F sound/hdspm.h conflict!
+-'H' 40-4F sound/hdsp.h conflict!
++'E' all linux/input.h conflict!
++'E' 00-0F xen/evtchn.h conflict!
++'F' all linux/fb.h conflict!
++'F' 01-02 drivers/scsi/pmcraid.h conflict!
++'F' 20 drivers/video/fsl-diu-fb.h conflict!
++'F' 20 drivers/video/intelfb/intelfb.h conflict!
++'F' 20 linux/ivtvfb.h conflict!
++'F' 20 linux/matroxfb.h conflict!
++'F' 20 drivers/video/aty/atyfb_base.c conflict!
++'F' 00-0F video/da8xx-fb.h conflict!
++'F' 80-8F linux/arcfb.h conflict!
++'F' DD video/sstfb.h conflict!
++'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict!
++'H' 00-7F linux/hiddev.h conflict!
++'H' 00-0F linux/hidraw.h conflict!
++'H' 01 linux/mei.h conflict!
++'H' 02 linux/mei.h conflict!
++'H' 03 linux/mei.h conflict!
++'H' 00-0F sound/asound.h conflict!
++'H' 20-40 sound/asound_fm.h conflict!
++'H' 80-8F sound/sfnt_info.h conflict!
++'H' 10-8F sound/emu10k1.h conflict!
++'H' 10-1F sound/sb16_csp.h conflict!
++'H' 10-1F sound/hda_hwdep.h conflict!
++'H' 40-4F sound/hdspm.h conflict!
++'H' 40-4F sound/hdsp.h conflict!
+ 'H' 90 sound/usb/usx2y/usb_stream.h
+-'H' 00-0F uapi/misc/habanalabs.h conflict!
++'H' 00-0F uapi/misc/habanalabs.h conflict!
+ 'H' A0 uapi/linux/usb/cdc-wdm.h
+-'H' C0-F0 net/bluetooth/hci.h conflict!
+-'H' C0-DF net/bluetooth/hidp/hidp.h conflict!
+-'H' C0-DF net/bluetooth/cmtp/cmtp.h conflict!
+-'H' C0-DF net/bluetooth/bnep/bnep.h conflict!
+-'H' F1 linux/hid-roccat.h <mailto:erazor_de@users.sourceforge.net>
++'H' C0-F0 net/bluetooth/hci.h conflict!
++'H' C0-DF net/bluetooth/hidp/hidp.h conflict!
++'H' C0-DF net/bluetooth/cmtp/cmtp.h conflict!
++'H' C0-DF net/bluetooth/bnep/bnep.h conflict!
++'H' F1 linux/hid-roccat.h <mailto:erazor_de@users.sourceforge.net>
+ 'H' F8-FA sound/firewire.h
+-'I' all linux/isdn.h conflict!
+-'I' 00-0F drivers/isdn/divert/isdn_divert.h conflict!
+-'I' 40-4F linux/mISDNif.h conflict!
++'I' all linux/isdn.h conflict!
++'I' 00-0F drivers/isdn/divert/isdn_divert.h conflict!
++'I' 40-4F linux/mISDNif.h conflict!
+ 'J' 00-1F drivers/scsi/gdth_ioctl.h
+ 'K' all linux/kd.h
+-'L' 00-1F linux/loop.h conflict!
+-'L' 10-1F drivers/scsi/mpt3sas/mpt3sas_ctl.h conflict!
++'L' 00-1F linux/loop.h conflict!
++'L' 10-1F drivers/scsi/mpt3sas/mpt3sas_ctl.h conflict!
+ 'L' 20-2F linux/lightnvm.h
+-'L' E0-FF linux/ppdd.h encrypted disk device driver
+- <http://linux01.gwdg.de/~alatham/ppdd.html>
+-'M' all linux/soundcard.h conflict!
+-'M' 01-16 mtd/mtd-abi.h conflict!
++'L' E0-FF linux/ppdd.h encrypted disk device driver
++ <http://linux01.gwdg.de/~alatham/ppdd.html>
++'M' all linux/soundcard.h conflict!
++'M' 01-16 mtd/mtd-abi.h conflict!
+ and drivers/mtd/mtdchar.c
+ 'M' 01-03 drivers/scsi/megaraid/megaraid_sas.h
+-'M' 00-0F drivers/video/fsl-diu-fb.h conflict!
++'M' 00-0F drivers/video/fsl-diu-fb.h conflict!
+ 'N' 00-1F drivers/usb/scanner.h
+ 'N' 40-7F drivers/block/nvme.c
+-'O' 00-06 mtd/ubi-user.h UBI
+-'P' all linux/soundcard.h conflict!
+-'P' 60-6F sound/sscape_ioctl.h conflict!
+-'P' 00-0F drivers/usb/class/usblp.c conflict!
+-'P' 01-09 drivers/misc/pci_endpoint_test.c conflict!
++'O' 00-06 mtd/ubi-user.h UBI
++'P' all linux/soundcard.h conflict!
++'P' 60-6F sound/sscape_ioctl.h conflict!
++'P' 00-0F drivers/usb/class/usblp.c conflict!
++'P' 01-09 drivers/misc/pci_endpoint_test.c conflict!
+ 'Q' all linux/soundcard.h
+-'R' 00-1F linux/random.h conflict!
+-'R' 01 linux/rfkill.h conflict!
++'R' 00-1F linux/random.h conflict!
++'R' 01 linux/rfkill.h conflict!
+ 'R' C0-DF net/bluetooth/rfcomm.h
+-'S' all linux/cdrom.h conflict!
+-'S' 80-81 scsi/scsi_ioctl.h conflict!
+-'S' 82-FF scsi/scsi.h conflict!
+-'S' 00-7F sound/asequencer.h conflict!
+-'T' all linux/soundcard.h conflict!
+-'T' 00-AF sound/asound.h conflict!
+-'T' all arch/x86/include/asm/ioctls.h conflict!
+-'T' C0-DF linux/if_tun.h conflict!
+-'U' all sound/asound.h conflict!
+-'U' 00-CF linux/uinput.h conflict!
++'S' all linux/cdrom.h conflict!
++'S' 80-81 scsi/scsi_ioctl.h conflict!
++'S' 82-FF scsi/scsi.h conflict!
++'S' 00-7F sound/asequencer.h conflict!
++'T' all linux/soundcard.h conflict!
++'T' 00-AF sound/asound.h conflict!
++'T' all arch/x86/include/asm/ioctls.h conflict!
++'T' C0-DF linux/if_tun.h conflict!
++'U' all sound/asound.h conflict!
++'U' 00-CF linux/uinput.h conflict!
+ 'U' 00-EF linux/usbdevice_fs.h
+ 'U' C0-CF drivers/bluetooth/hci_uart.h
+-'V' all linux/vt.h conflict!
+-'V' all linux/videodev2.h conflict!
+-'V' C0 linux/ivtvfb.h conflict!
+-'V' C0 linux/ivtv.h conflict!
+-'V' C0 media/davinci/vpfe_capture.h conflict!
+-'V' C0 media/si4713.h conflict!
+-'W' 00-1F linux/watchdog.h conflict!
+-'W' 00-1F linux/wanrouter.h conflict! (pre 3.9)
+-'W' 00-3F sound/asound.h conflict!
++'V' all linux/vt.h conflict!
++'V' all linux/videodev2.h conflict!
++'V' C0 linux/ivtvfb.h conflict!
++'V' C0 linux/ivtv.h conflict!
++'V' C0 media/davinci/vpfe_capture.h conflict!
++'V' C0 media/si4713.h conflict!
++'W' 00-1F linux/watchdog.h conflict!
++'W' 00-1F linux/wanrouter.h conflict! (pre 3.9)
++'W' 00-3F sound/asound.h conflict!
+ 'W' 40-5F drivers/pci/switch/switchtec.c
+ 'W' 60-61 linux/watch_queue.h
+-'X' all fs/xfs/xfs_fs.h, conflict!
++'X' all fs/xfs/xfs_fs.h, conflict!
+ fs/xfs/linux-2.6/xfs_ioctl32.h,
+ include/linux/falloc.h,
+ linux/fs.h,
+-'X' all fs/ocfs2/ocfs_fs.h conflict!
+-'X' 01 linux/pktcdvd.h conflict!
++'X' all fs/ocfs2/ocfs_fs.h conflict!
++'X' 01 linux/pktcdvd.h conflict!
+ 'Y' all linux/cyclades.h
+ 'Z' 14-15 drivers/message/fusion/mptctl.h
+-'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices
+- <mailto:gregkh@linuxfoundation.org>
+-'a' all linux/atm*.h, linux/sonet.h ATM on linux
+- <http://lrcwww.epfl.ch/>
+-'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
+-'b' 00-FF conflict! bit3 vme host bridge
+- <mailto:natalia@nikhefk.nikhef.nl>
+-'c' all linux/cm4000_cs.h conflict!
+-'c' 00-7F linux/comstats.h conflict!
+-'c' 00-7F linux/coda.h conflict!
+-'c' 00-1F linux/chio.h conflict!
+-'c' 80-9F arch/s390/include/asm/chsc.h conflict!
++'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices
++ <mailto:gregkh@linuxfoundation.org>
++'a' all linux/atm*.h, linux/sonet.h ATM on linux
++ <http://lrcwww.epfl.ch/>
++'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
++'b' 00-FF conflict! bit3 vme host bridge
++ <mailto:natalia@nikhefk.nikhef.nl>
++'c' all linux/cm4000_cs.h conflict!
++'c' 00-7F linux/comstats.h conflict!
++'c' 00-7F linux/coda.h conflict!
++'c' 00-1F linux/chio.h conflict!
++'c' 80-9F arch/s390/include/asm/chsc.h conflict!
+ 'c' A0-AF arch/x86/include/asm/msr.h conflict!
+-'d' 00-FF linux/char/drm/drm.h conflict!
+-'d' 02-40 pcmcia/ds.h conflict!
++'d' 00-FF linux/char/drm/drm.h conflict!
++'d' 02-40 pcmcia/ds.h conflict!
+ 'd' F0-FF linux/digi1.h
+-'e' all linux/digi1.h conflict!
+-'f' 00-1F linux/ext2_fs.h conflict!
+-'f' 00-1F linux/ext3_fs.h conflict!
+-'f' 00-0F fs/jfs/jfs_dinode.h conflict!
+-'f' 00-0F fs/ext4/ext4.h conflict!
+-'f' 00-0F linux/fs.h conflict!
+-'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict!
++'e' all linux/digi1.h conflict!
++'f' 00-1F linux/ext2_fs.h conflict!
++'f' 00-1F linux/ext3_fs.h conflict!
++'f' 00-0F fs/jfs/jfs_dinode.h conflict!
++'f' 00-0F fs/ext4/ext4.h conflict!
++'f' 00-0F linux/fs.h conflict!
++'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict!
+ 'f' 13-27 linux/fscrypt.h
+ 'f' 81-8F linux/fsverity.h
+ 'g' 00-0F linux/usb/gadgetfs.h
+ 'g' 20-2F linux/usb/g_printer.h
+-'h' 00-7F conflict! Charon filesystem
+- <mailto:zapman@interlan.net>
+-'h' 00-1F linux/hpet.h conflict!
++'h' 00-7F conflict! Charon filesystem
++ <mailto:zapman@interlan.net>
++'h' 00-1F linux/hpet.h conflict!
+ 'h' 80-8F fs/hfsplus/ioctl.c
+-'i' 00-3F linux/i2o-dev.h conflict!
+-'i' 0B-1F linux/ipmi.h conflict!
++'i' 00-3F linux/i2o-dev.h conflict!
++'i' 0B-1F linux/ipmi.h conflict!
+ 'i' 80-8F linux/i8k.h
+ 'j' 00-3F linux/joystick.h
+-'k' 00-0F linux/spi/spidev.h conflict!
+-'k' 00-05 video/kyro.h conflict!
+-'k' 10-17 linux/hsi/hsi_char.h HSI character device
+-'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system
+- <http://web.archive.org/web/%2A/http://mikonos.dia.unisa.it/tcfs>
+-'l' 40-7F linux/udf_fs_i.h in development:
+- <http://sourceforge.net/projects/linux-udf/>
+-'m' 00-09 linux/mmtimer.h conflict!
+-'m' all linux/mtio.h conflict!
+-'m' all linux/soundcard.h conflict!
+-'m' all linux/synclink.h conflict!
+-'m' 00-19 drivers/message/fusion/mptctl.h conflict!
+-'m' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict!
++'k' 00-0F linux/spi/spidev.h conflict!
++'k' 00-05 video/kyro.h conflict!
++'k' 10-17 linux/hsi/hsi_char.h HSI character device
++'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system
++ <http://web.archive.org/web/%2A/http://mikonos.dia.unisa.it/tcfs>
++'l' 40-7F linux/udf_fs_i.h in development:
++ <http://sourceforge.net/projects/linux-udf/>
++'m' 00-09 linux/mmtimer.h conflict!
++'m' all linux/mtio.h conflict!
++'m' all linux/soundcard.h conflict!
++'m' all linux/synclink.h conflict!
++'m' 00-19 drivers/message/fusion/mptctl.h conflict!
++'m' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict!
+ 'n' 00-7F linux/ncp_fs.h and fs/ncpfs/ioctl.c
+-'n' 80-8F uapi/linux/nilfs2_api.h NILFS2
+-'n' E0-FF linux/matroxfb.h matroxfb
+-'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
+-'o' 00-03 mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
+-'o' 40-41 mtd/ubi-user.h UBI
+-'o' 01-A1 `linux/dvb/*.h` DVB
+-'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this)
+-'p' 00-1F linux/rtc.h conflict!
++'n' 80-8F uapi/linux/nilfs2_api.h NILFS2
++'n' E0-FF linux/matroxfb.h matroxfb
++'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
++'o' 00-03 mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
++'o' 40-41 mtd/ubi-user.h UBI
++'o' 01-A1 `linux/dvb/*.h` DVB
++'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this)
++'p' 00-1F linux/rtc.h conflict!
+ 'p' 40-7F linux/nvram.h
+-'p' 80-9F linux/ppdev.h user-space parport
+- <mailto:tim@cyberelk.net>
+-'p' A1-A5 linux/pps.h LinuxPPS
+- <mailto:giometti@linux.it>
++'p' 80-9F linux/ppdev.h user-space parport
++ <mailto:tim@cyberelk.net>
++'p' A1-A5 linux/pps.h LinuxPPS
++ <mailto:giometti@linux.it>
+ 'q' 00-1F linux/serio.h
+-'q' 80-FF linux/telephony.h Internet PhoneJACK, Internet LineJACK
+- linux/ixjuser.h <http://web.archive.org/web/%2A/http://www.quicknet.net>
++'q' 80-FF linux/telephony.h Internet PhoneJACK, Internet LineJACK
++ linux/ixjuser.h <http://web.archive.org/web/%2A/http://www.quicknet.net>
+ 'r' 00-1F linux/msdos_fs.h and fs/fat/dir.c
+ 's' all linux/cdk.h
+ 't' 00-7F linux/ppp-ioctl.h
+ 't' 80-8F linux/isdn_ppp.h
+-'t' 90-91 linux/toshiba.h toshiba and toshiba_acpi SMM
+-'u' 00-1F linux/smb_fs.h gone
+-'u' 20-3F linux/uvcvideo.h USB video class host driver
+-'u' 40-4f linux/udmabuf.h userspace dma-buf misc device
+-'v' 00-1F linux/ext2_fs.h conflict!
+-'v' 00-1F linux/fs.h conflict!
+-'v' 00-0F linux/sonypi.h conflict!
+-'v' 00-0F media/v4l2-subdev.h conflict!
+-'v' 20-27 arch/powerpc/include/uapi/asm/vas-api.h VAS API
+-'v' C0-FF linux/meye.h conflict!
+-'w' all CERN SCI driver
+-'y' 00-1F packet based user level communications
+- <mailto:zapman@interlan.net>
+-'z' 00-3F CAN bus card conflict!
+- <mailto:hdstich@connectu.ulm.circular.de>
+-'z' 40-7F CAN bus card conflict!
+- <mailto:oe@port.de>
+-'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict!
++'t' 90-91 linux/toshiba.h toshiba and toshiba_acpi SMM
++'u' 00-1F linux/smb_fs.h gone
++'u' 20-3F linux/uvcvideo.h USB video class host driver
++'u' 40-4f linux/udmabuf.h userspace dma-buf misc device
++'v' 00-1F linux/ext2_fs.h conflict!
++'v' 00-1F linux/fs.h conflict!
++'v' 00-0F linux/sonypi.h conflict!
++'v' 00-0F media/v4l2-subdev.h conflict!
++'v' 20-27 arch/powerpc/include/uapi/asm/vas-api.h VAS API
++'v' C0-FF linux/meye.h conflict!
++'w' all CERN SCI driver
++'y' 00-1F packet based user level communications
++ <mailto:zapman@interlan.net>
++'z' 00-3F CAN bus card conflict!
++ <mailto:hdstich@connectu.ulm.circular.de>
++'z' 40-7F CAN bus card conflict!
++ <mailto:oe@port.de>
++'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict!
+ '|' 00-7F linux/media.h
+ 0x80 00-1F linux/fb.h
+ 0x89 00-06 arch/x86/include/asm/sockios.h
+ 0x89 0B-DF linux/sockios.h
+-0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
+-0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
++0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
++0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
+ 0x8B all linux/wireless.h
+-0x8C 00-3F WiNRADiO driver
+- <http://www.winradio.com.au/>
++0x8C 00-3F WiNRADiO driver
++ <http://www.winradio.com.au/>
+ 0x90 00 drivers/cdrom/sbpcd.h
+ 0x92 00-0F drivers/usb/mon/mon_bin.c
+ 0x93 60-7F linux/auto_fs.h
+-0x94 all fs/btrfs/ioctl.h Btrfs filesystem
+- and linux/fs.h some lifted to vfs/generic
+-0x97 00-7F fs/ceph/ioctl.h Ceph file system
+-0x99 00-0F 537-Addinboard driver
+- <mailto:buk@buks.ipn.de>
+-0xA0 all linux/sdp/sdp.h Industrial Device Project
+- <mailto:kenji@bitgate.com>
+-0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver
+-0xA3 80-8F Port ACL in development:
+- <mailto:tlewis@mindspring.com>
++0x94 all fs/btrfs/ioctl.h Btrfs filesystem
++ and linux/fs.h some lifted to vfs/generic
++0x97 00-7F fs/ceph/ioctl.h Ceph file system
++0x99 00-0F 537-Addinboard driver
++ <mailto:buk@buks.ipn.de>
++0xA0 all linux/sdp/sdp.h Industrial Device Project
++ <mailto:kenji@bitgate.com>
++0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver
++0xA3 80-8F Port ACL in development:
++ <mailto:tlewis@mindspring.com>
+ 0xA3 90-9F linux/dtlk.h
+-0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem
++0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem
+ 0xAA 00-3F linux/uapi/linux/userfaultfd.h
+ 0xAB 00-1F linux/nbd.h
+ 0xAC 00-1F linux/raw.h
+-0xAD 00 Netfilter device in development:
+- <mailto:rusty@rustcorp.com.au>
+-0xAE 00-1F linux/kvm.h Kernel-based Virtual Machine
+- <mailto:kvm@vger.kernel.org>
+-0xAE 40-FF linux/kvm.h Kernel-based Virtual Machine
+- <mailto:kvm@vger.kernel.org>
+-0xAE 20-3F linux/nitro_enclaves.h Nitro Enclaves
+-0xAF 00-1F linux/fsl_hypervisor.h Freescale hypervisor
+-0xB0 all RATIO devices in development:
+- <mailto:vgo@ratio.de>
+-0xB1 00-1F PPPoX
+- <mailto:mostrows@styx.uwaterloo.ca>
++0xAD 00 Netfilter device in development:
++ <mailto:rusty@rustcorp.com.au>
++0xAE 00-1F linux/kvm.h Kernel-based Virtual Machine
++ <mailto:kvm@vger.kernel.org>
++0xAE 40-FF linux/kvm.h Kernel-based Virtual Machine
++ <mailto:kvm@vger.kernel.org>
++0xAE 20-3F linux/nitro_enclaves.h Nitro Enclaves
++0xAF 00-1F linux/fsl_hypervisor.h Freescale hypervisor
++0xB0 all RATIO devices in development:
++ <mailto:vgo@ratio.de>
++0xB1 00-1F PPPoX
++ <mailto:mostrows@styx.uwaterloo.ca>
+ 0xB3 00 linux/mmc/ioctl.h
+-0xB4 00-0F linux/gpio.h <mailto:linux-gpio@vger.kernel.org>
+-0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
++0xB4 00-0F linux/gpio.h <mailto:linux-gpio@vger.kernel.org>
++0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
+ 0xB6 all linux/fpga-dfl.h
+-0xB7 all uapi/linux/remoteproc_cdev.h <mailto:linux-remoteproc@vger.kernel.org>
++0xB7 all uapi/linux/remoteproc_cdev.h <mailto:linux-remoteproc@vger.kernel.org>
+ 0xC0 00-0F linux/usb/iowarrior.h
+ 0xCA 00-0F uapi/misc/cxl.h
+ 0xCA 10-2F uapi/misc/ocxl.h
+ 0xCA 80-BF uapi/scsi/cxlflash_ioctl.h
+-0xCB 00-1F CBM serial IEC bus in development:
+- <mailto:michael.klein@puffin.lb.shuttle.de>
+-0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver
++0xCB 00-1F CBM serial IEC bus in development:
++ <mailto:michael.klein@puffin.lb.shuttle.de>
++0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver
+ 0xCD 01 linux/reiserfs_fs.h
+ 0xCF 02 fs/cifs/ioctl.c
+ 0xDB 00-0F drivers/char/mwave/mwavepub.h
+-0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
+- <mailto:aherrman@de.ibm.com>
++0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
++ <mailto:aherrman@de.ibm.com>
+ 0xE5 00-3F linux/fuse.h
+-0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver
+-0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development)
+- <mailto:thomas@winischhofer.net>
+-0xF6 all LTTng Linux Trace Toolkit Next Generation
+- <mailto:mathieu.desnoyers@efficios.com>
++0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver
++0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development)
++ <mailto:thomas@winischhofer.net>
++0xF6 all LTTng Linux Trace Toolkit Next Generation
++ <mailto:mathieu.desnoyers@efficios.com>
+ 0xFD all linux/dm-ioctl.h
+ 0xFE all linux/isst_if.h
+-==== ===== ======================================================= ================================================================
++==== ===== ========================================================= ================================================================
+--
+2.53.0
+
--- /dev/null
+From c40ff0ac509e7e604a906b2406210c1fa3cd5bd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jun 2026 02:07:35 +0800
+Subject: net/sched: act_pedit: fix action bind logic
+
+From: Pedro Tammela <pctammela@mojatatu.com>
+
+[ Upstream commit e9e42292ea76a8358b0c02ffd530d78e133a1b73 ]
+
+The TC architecture allows filters and actions to be created independently.
+In filters the user can reference action objects using:
+tc action add action pedit ... index 1
+tc filter add ... action pedit index 1
+
+In the current code for act_pedit this is broken as it checks netlink
+attributes for create/update before actually checking if we are binding to an
+existing action.
+
+tdc results:
+1..69
+ok 1 319a - Add pedit action that mangles IP TTL
+ok 2 7e67 - Replace pedit action with invalid goto chain
+ok 3 377e - Add pedit action with RAW_OP offset u32
+ok 4 a0ca - Add pedit action with RAW_OP offset u32 (INVALID)
+ok 5 dd8a - Add pedit action with RAW_OP offset u16 u16
+ok 6 53db - Add pedit action with RAW_OP offset u16 (INVALID)
+ok 7 5c7e - Add pedit action with RAW_OP offset u8 add value
+ok 8 2893 - Add pedit action with RAW_OP offset u8 quad
+ok 9 3a07 - Add pedit action with RAW_OP offset u8-u16-u8
+ok 10 ab0f - Add pedit action with RAW_OP offset u16-u8-u8
+ok 11 9d12 - Add pedit action with RAW_OP offset u32 set u16 clear u8 invert
+ok 12 ebfa - Add pedit action with RAW_OP offset overflow u32 (INVALID)
+ok 13 f512 - Add pedit action with RAW_OP offset u16 at offmask shift set
+ok 14 c2cb - Add pedit action with RAW_OP offset u32 retain value
+ok 15 1762 - Add pedit action with RAW_OP offset u8 clear value
+ok 16 bcee - Add pedit action with RAW_OP offset u8 retain value
+ok 17 e89f - Add pedit action with RAW_OP offset u16 retain value
+ok 18 c282 - Add pedit action with RAW_OP offset u32 clear value
+ok 19 c422 - Add pedit action with RAW_OP offset u16 invert value
+ok 20 d3d3 - Add pedit action with RAW_OP offset u32 invert value
+ok 21 57e5 - Add pedit action with RAW_OP offset u8 preserve value
+ok 22 99e0 - Add pedit action with RAW_OP offset u16 preserve value
+ok 23 1892 - Add pedit action with RAW_OP offset u32 preserve value
+ok 24 4b60 - Add pedit action with RAW_OP negative offset u16/u32 set value
+ok 25 a5a7 - Add pedit action with LAYERED_OP eth set src
+ok 26 86d4 - Add pedit action with LAYERED_OP eth set src & dst
+ok 27 f8a9 - Add pedit action with LAYERED_OP eth set dst
+ok 28 c715 - Add pedit action with LAYERED_OP eth set src (INVALID)
+ok 29 8131 - Add pedit action with LAYERED_OP eth set dst (INVALID)
+ok 30 ba22 - Add pedit action with LAYERED_OP eth type set/clear sequence
+ok 31 dec4 - Add pedit action with LAYERED_OP eth set type (INVALID)
+ok 32 ab06 - Add pedit action with LAYERED_OP eth add type
+ok 33 918d - Add pedit action with LAYERED_OP eth invert src
+ok 34 a8d4 - Add pedit action with LAYERED_OP eth invert dst
+ok 35 ee13 - Add pedit action with LAYERED_OP eth invert type
+ok 36 7588 - Add pedit action with LAYERED_OP ip set src
+ok 37 0fa7 - Add pedit action with LAYERED_OP ip set dst
+ok 38 5810 - Add pedit action with LAYERED_OP ip set src & dst
+ok 39 1092 - Add pedit action with LAYERED_OP ip set ihl & dsfield
+ok 40 02d8 - Add pedit action with LAYERED_OP ip set ttl & protocol
+ok 41 3e2d - Add pedit action with LAYERED_OP ip set ttl (INVALID)
+ok 42 31ae - Add pedit action with LAYERED_OP ip ttl clear/set
+ok 43 486f - Add pedit action with LAYERED_OP ip set duplicate fields
+ok 44 e790 - Add pedit action with LAYERED_OP ip set ce, df, mf, firstfrag, nofrag fields
+ok 45 cc8a - Add pedit action with LAYERED_OP ip set tos
+ok 46 7a17 - Add pedit action with LAYERED_OP ip set precedence
+ok 47 c3b6 - Add pedit action with LAYERED_OP ip add tos
+ok 48 43d3 - Add pedit action with LAYERED_OP ip add precedence
+ok 49 438e - Add pedit action with LAYERED_OP ip clear tos
+ok 50 6b1b - Add pedit action with LAYERED_OP ip clear precedence
+ok 51 824a - Add pedit action with LAYERED_OP ip invert tos
+ok 52 106f - Add pedit action with LAYERED_OP ip invert precedence
+ok 53 6829 - Add pedit action with LAYERED_OP beyond ip set dport & sport
+ok 54 afd8 - Add pedit action with LAYERED_OP beyond ip set icmp_type & icmp_code
+ok 55 3143 - Add pedit action with LAYERED_OP beyond ip set dport (INVALID)
+ok 56 815c - Add pedit action with LAYERED_OP ip6 set src
+ok 57 4dae - Add pedit action with LAYERED_OP ip6 set dst
+ok 58 fc1f - Add pedit action with LAYERED_OP ip6 set src & dst
+ok 59 6d34 - Add pedit action with LAYERED_OP ip6 dst retain value (INVALID)
+ok 60 94bb - Add pedit action with LAYERED_OP ip6 traffic_class
+ok 61 6f5e - Add pedit action with LAYERED_OP ip6 flow_lbl
+ok 62 6795 - Add pedit action with LAYERED_OP ip6 set payload_len, nexthdr, hoplimit
+ok 63 1442 - Add pedit action with LAYERED_OP tcp set dport & sport
+ok 64 b7ac - Add pedit action with LAYERED_OP tcp sport set (INVALID)
+ok 65 cfcc - Add pedit action with LAYERED_OP tcp flags set
+ok 66 3bc4 - Add pedit action with LAYERED_OP tcp set dport, sport & flags fields
+ok 67 f1c8 - Add pedit action with LAYERED_OP udp set dport & sport
+ok 68 d784 - Add pedit action with mixed RAW/LAYERED_OP #1
+ok 69 70ca - Add pedit action with mixed RAW/LAYERED_OP #2
+
+Fixes: 71d0ed7079df ("net/act_pedit: Support using offset relative to the conventional network headers")
+Fixes: f67169fef8db ("net/sched: act_pedit: fix WARN() in the traffic path")
+Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_pedit.c | 58 +++++++++++++++++++++++--------------------
+ 1 file changed, 31 insertions(+), 27 deletions(-)
+
+diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
+index 0601deea04d725..fe9e826184c168 100644
+--- a/net/sched/act_pedit.c
++++ b/net/sched/act_pedit.c
+@@ -182,26 +182,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+ }
+
+ parm = nla_data(pattr);
+- if (!parm->nkeys) {
+- NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
+- return -EINVAL;
+- }
+- ksize = parm->nkeys * sizeof(struct tc_pedit_key);
+- if (nla_len(pattr) < sizeof(*parm) + ksize) {
+- NL_SET_ERR_MSG_ATTR(extack, pattr, "Length of TCA_PEDIT_PARMS or TCA_PEDIT_PARMS_EX pedit attribute is invalid");
+- return -EINVAL;
+- }
+-
+- nparms = kzalloc(sizeof(*nparms), GFP_KERNEL);
+- if (!nparms)
+- return -ENOMEM;
+-
+- nparms->tcfp_keys_ex =
+- tcf_pedit_keys_ex_parse(tb[TCA_PEDIT_KEYS_EX], parm->nkeys);
+- if (IS_ERR(nparms->tcfp_keys_ex)) {
+- ret = PTR_ERR(nparms->tcfp_keys_ex);
+- goto out_free;
+- }
+
+ index = parm->index;
+ err = tcf_idr_check_alloc(tn, &index, a, bind);
+@@ -210,25 +190,49 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+ &act_pedit_ops, bind, flags);
+ if (ret) {
+ tcf_idr_cleanup(tn, index);
+- goto out_free_ex;
++ return ret;
+ }
+ ret = ACT_P_CREATED;
+ } else if (err > 0) {
+ if (bind)
+- goto out_free;
++ return 0;
+ if (!ovr) {
+ ret = -EEXIST;
+ goto out_release;
+ }
+ } else {
+- ret = err;
+- goto out_free_ex;
++ return err;
++ }
++
++ if (!parm->nkeys) {
++ NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
++ ret = -EINVAL;
++ goto out_release;
++ }
++ ksize = parm->nkeys * sizeof(struct tc_pedit_key);
++ if (nla_len(pattr) < sizeof(*parm) + ksize) {
++ NL_SET_ERR_MSG_ATTR(extack, pattr, "Length of TCA_PEDIT_PARMS or TCA_PEDIT_PARMS_EX pedit attribute is invalid");
++ ret = -EINVAL;
++ goto out_release;
++ }
++
++ nparms = kzalloc(sizeof(*nparms), GFP_KERNEL);
++ if (!nparms) {
++ ret = -ENOMEM;
++ goto out_release;
++ }
++
++ nparms->tcfp_keys_ex =
++ tcf_pedit_keys_ex_parse(tb[TCA_PEDIT_KEYS_EX], parm->nkeys);
++ if (IS_ERR(nparms->tcfp_keys_ex)) {
++ ret = PTR_ERR(nparms->tcfp_keys_ex);
++ goto out_free;
+ }
+
+ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
+ if (err < 0) {
+ ret = err;
+- goto out_release;
++ goto out_free_ex;
+ }
+
+ nparms->tcfp_flags = parm->flags;
+@@ -280,12 +284,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
+ put_chain:
+ if (goto_ch)
+ tcf_chain_put_by_act(goto_ch);
+-out_release:
+- tcf_idr_release(*a, bind);
+ out_free_ex:
+ kfree(nparms->tcfp_keys_ex);
+ out_free:
+ kfree(nparms);
++out_release:
++ tcf_idr_release(*a, bind);
+ return ret;
+ }
+
+--
+2.53.0
+
regulator-core-fix-locking-in-regulator_resolve_supply-error-path.patch
vc_screen-fix-null-ptr-deref-in-vcs_notifier-during-concurrent-vcs_write.patch
media-vidtv-fix-null-pointer-dereference-in-vidtv_mux_push_si.patch
+documentation-ioctl-number-extend-include-file-colum.patch
+crypto-qat-replace-kzalloc-copy_from_user-with-memdu.patch
+crypto-qat-return-pointer-directly-in-adf_ctl_alloc_.patch
+crypto-qat-remove-unused-character-device-and-ioctls.patch
+net-sched-act_pedit-fix-action-bind-logic.patch
--- /dev/null
+From 841e923db3f66058241a83f7c2fb43ac2ebd91aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jun 2026 11:22:59 +0800
+Subject: kselftest/arm64: signal: Skip SVE signal test if not enough VLs
+ supported
+
+From: Yijia Wang <wangyijia.yeah@bytedance.com>
+
+[ Upstream commit 78c09c0f4df89fabdcfb3e5e53d3196cf67f64ef ]
+
+On platform where SVE is supported but there are less than 2 VLs available
+the signal SVE change test should be skipped instead of failing.
+
+Reported-by: Andre Przywara <andre.przywara@arm.com>
+Tested-by: Andre Przywara <andre.przywara@arm.com>
+Cc: Mark Brown <broonie@kernel.org>
+Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20220524103149.2802-1-cristian.marussi@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Yijia Wang <wangyijia.yeah@bytedance.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../arm64/signal/testcases/fake_sigreturn_sve_change_vl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
+index bb50b5adbf10de..915821375b0a44 100644
+--- a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
++++ b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
+@@ -6,6 +6,7 @@
+ * supported and is expected to segfault.
+ */
+
++#include <kselftest.h>
+ #include <signal.h>
+ #include <ucontext.h>
+ #include <sys/prctl.h>
+@@ -40,6 +41,7 @@ static bool sve_get_vls(struct tdescr *td)
+ /* We need at least two VLs */
+ if (nvls < 2) {
+ fprintf(stderr, "Only %d VL supported\n", nvls);
++ td->result = KSFT_SKIP;
+ return false;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From c5187da0baea9ce4ae374f34426c36ca619aa217 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:17 +0200
+Subject: KVM: x86: Fix shadow paging use-after-free due to unexpected GFN
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 0cb2af2ea66ad8ff195c156ea690f11216285bdf upstream.
+
+The shadow MMU computes GFNs for direct shadow pages using sp->gfn plus
+the SPTE index. This assumption breaks for shadow paging if the guest
+page tables are modified between VM entries (similar to commit
+aad885e77496, "KVM: x86/mmu: Drop/zap existing present SPTE even
+when creating an MMIO SPTE", 2026-03-27). The flow is as follows:
+
+- a PDE is installed for a 2MB mapping, and a page in that area is
+ accessed. KVM creates a kvm_mmu_page consisting of 512 4KB pages;
+ the kvm_mmu_page is marked by FNAME(fetch) as direct-mapped because
+ the guest's mapping is a huge page (and thus contiguous).
+
+- the PDE mapping is changed from outside the guest.
+
+- the guest accesses another page in the same 2MB area. KVM installs
+ a new leaf SPTE and rmap entry; the SPTE uses the "correct" GFN
+ (i.e. based on the new mapping, as changed in the previous step) but
+ that GFN is outside of the [sp->gfn, sp->gfn + 511] range; therefore
+ the rmap entry cannot be found and removed when the kvm_mmu_page
+ is zapped.
+
+- the memslot that covers the first 2MB mapping is deleted, and the
+ kvm_mmu_page for the now-invalid GPA is zapped. However, rmap_remove()
+ only looks at the [sp->gfn, sp->gfn + 511] range established in step 1,
+ and fails to find the rmap entry that was recorded by step 3.
+
+- any operation that causes an rmap walk for the same page accessed
+ by step 3 then walks a stale rmap and dereferences a freed kvm_mmu_page.
+ This includes dirty logging or MMU notifier invalidations (e.g., from
+ MADV_DONTNEED).
+
+The underlying issue is that KVM's walking of shadow PTEs assumes that
+if a SPTE is present when KVM wants to install a non-leaf SPTE, then the
+existing kvm_mmu_page must be for the correct gfn. Because the only way
+for the gfn to be wrong is if KVM messed up and failed to zap a SPTE...
+which shouldn't happen, but *actually* only happens in response to a
+guest write.
+
+That bug dates back literally forever, as even the first version of KVM
+assumes that the GFN matches and walks into the "wrong" shadow page.
+However, that was only an imprecision until 2032a93d66fa ("KVM: MMU:
+Don't allocate gfns page for direct mmu pages") came along.
+
+Fix it by checking for a target gfn mismatch and zapping the existing
+SPTE. That way the old SP and rmap entries are gone, KVM installs
+the rmap in the right location, and everyone is happy.
+
+Fixes: 2032a93d66fa ("KVM: MMU: Don't allocate gfns page for direct mmu pages")
+Fixes: 6aa8b732ca01 ("kvm: userspace interface")
+Reported-by: Alexander Bulekov <bkov@amazon.com>
+Reported-by: Fred Griffoul <fgriffo@amazon.co.uk>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Link: https://patch.msgid.link/20260503201029.106481-1-pbonzini@redhat.com/
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 33 ++++++++++++++-------------------
+ arch/x86/kvm/mmu/spte.h | 5 +++++
+ 2 files changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index d58be2e698f795..6c9656b8062e4e 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -188,6 +188,8 @@ static struct percpu_counter kvm_total_used_mmu_pages;
+ static void mmu_spte_set(u64 *sptep, u64 spte);
+ static union kvm_mmu_page_role
+ kvm_mmu_calc_root_page_role(struct kvm_vcpu *vcpu);
++static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
++ u64 *spte, struct list_head *invalid_list);
+
+ struct kvm_mmu_role_regs {
+ const unsigned long cr0;
+@@ -1179,18 +1181,6 @@ static void drop_spte(struct kvm *kvm, u64 *sptep)
+ rmap_remove(kvm, sptep);
+ }
+
+-static void drop_large_spte(struct kvm *kvm, u64 *sptep)
+-{
+- struct kvm_mmu_page *sp;
+-
+- sp = sptep_to_sp(sptep);
+- WARN_ON(sp->role.level == PG_LEVEL_4K);
+-
+- drop_spte(kvm, sptep);
+- kvm_flush_remote_tlbs_with_address(kvm, sp->gfn,
+- KVM_PAGES_PER_HPAGE(sp->role.level));
+-}
+-
+ /*
+ * Write-protect on the specified @sptep, @pt_protect indicates whether
+ * spte write-protection is caused by protecting shadow page table.
+@@ -2187,7 +2177,8 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu,
+ {
+ union kvm_mmu_page_role role;
+
+- if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
++ if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep) &&
++ spte_to_child_sp(*sptep) && spte_to_child_sp(*sptep)->gfn == gfn)
+ return ERR_PTR(-EEXIST);
+
+ role = kvm_mmu_child_role(sptep, direct, access);
+@@ -2265,12 +2256,16 @@ static void __link_shadow_page(struct kvm_vcpu *vcpu,
+
+ BUILD_BUG_ON(VMX_EPT_WRITABLE_MASK != PT_WRITABLE_MASK);
+
+- /*
+- * If an SPTE is present already, it must be a leaf and therefore
+- * a large one. Drop it and flush the TLB before installing sp.
+- */
+- if (is_shadow_present_pte(*sptep))
+- drop_large_spte(vcpu->kvm, sptep);
++ if (is_shadow_present_pte(*sptep)) {
++ struct kvm_mmu_page *parent_sp;
++ LIST_HEAD(invalid_list);
++
++ parent_sp = sptep_to_sp(sptep);
++ WARN_ON_ONCE(parent_sp->role.level == PG_LEVEL_4K);
++
++ mmu_page_zap_pte(vcpu->kvm, parent_sp, sptep, &invalid_list);
++ kvm_mmu_remote_flush_or_zap(vcpu->kvm, &invalid_list, true);
++ }
+
+ spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp));
+
+diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
+index 31d6456d8ac333..31d03d15415c01 100644
+--- a/arch/x86/kvm/mmu/spte.h
++++ b/arch/x86/kvm/mmu/spte.h
+@@ -267,6 +267,11 @@ static inline bool is_executable_pte(u64 spte)
+ return (spte & (shadow_x_mask | shadow_nx_mask)) == shadow_x_mask;
+ }
+
++static inline struct kvm_mmu_page *spte_to_child_sp(u64 spte)
++{
++ return to_shadow_page(spte & PT64_BASE_ADDR_MASK);
++}
++
+ static inline kvm_pfn_t spte_to_pfn(u64 pte)
+ {
+ return (pte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
+--
+2.53.0
+
--- /dev/null
+From 6d15eee7dcdbc7794d7e83bb36847eeeea7d4938 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:18 +0200
+Subject: KVM: x86: Fix shadow paging use-after-free due to unexpected role
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+[ Upstream commit 81ccda30b4e83d8f5cc4fd50503c44e3a33abfeb ]
+
+Commit 0cb2af2ea66ad ("KVM: x86: Fix shadow paging use-after-free due
+to unexpected GFN") fixed a shadow paging mismatch between stored and
+computed GFNs; the bug could be triggered by changing a PDE mapping from
+outside the guest, and then deleting a memslot. The rmap_remove()
+call would miss entries created after the PDE change because the GFN
+of the leaf SPTE does not match the GFN of the struct kvm_mmu_page.
+
+A similar hole however remains if the modified PDE points to a non-leaf
+page. In this case the gfn can be made to match, but the role does not
+match: the original large 2MB page creates a kvm_mmu_page with direct=1,
+while the new 4KB needs a kvm_mmu_page with direct=0. However,
+kvm_mmu_get_child_sp() does not compare the role, and therefore reuses
+the page.
+
+The next step is installing a leaf (4KB) SPTE on the new path which
+records an rmap entry under the gfn resolved by the walk. But when
+that child is zapped its parent kvm_mmu_page has direct=1 and
+kvm_mmu_page_get_gfn() computes the gfn for the 4KB page as
+sp->gfn + index instead of using sp->shadowed_translation[] (or sp->gfns[]
+in older kernels). It therefore fails to remove the recorded entry.
+
+When the memslot is dropped the shadow page is freed but the rmap
+entry survives, as in the scenario that was already fixed. Code that
+later walks that gfn (dirty logging, MMU notifier invalidation, and
+so on) dereferences an sptep that lies in the freed page, causing the
+use-after-free.
+
+Fixes: 2032a93d66fa ("KVM: MMU: Don't allocate gfns page for direct mmu pages")
+Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index 6c9656b8062e4e..e9dbe3e7ec622f 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -2175,13 +2175,15 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu,
+ u64 *sptep, gfn_t gfn,
+ bool direct, unsigned int access)
+ {
+- union kvm_mmu_page_role role;
++ union kvm_mmu_page_role role = kvm_mmu_child_role(sptep, direct, access);
+
+- if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep) &&
+- spte_to_child_sp(*sptep) && spte_to_child_sp(*sptep)->gfn == gfn)
++ if (is_shadow_present_pte(*sptep) &&
++ !is_large_pte(*sptep) &&
++ spte_to_child_sp(*sptep) &&
++ spte_to_child_sp(*sptep)->gfn == gfn &&
++ spte_to_child_sp(*sptep)->role.word == role.word)
+ return ERR_PTR(-EEXIST);
+
+- role = kvm_mmu_child_role(sptep, direct, access);
+ return kvm_mmu_get_page(vcpu, gfn, role);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From cd2b29b10c0f8055c823c5df970fb98e897f65b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:15 +0200
+Subject: KVM: x86/mmu: Always pass 0 for @quadrant when gptes are 8 bytes
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 7f49777550e55a7d6832cbb0873f48f91c175b9c upstream.
+
+The quadrant is only used when gptes are 4 bytes, but
+mmu_alloc_{direct,shadow}_roots() pass in a non-zero quadrant for PAE
+page directories regardless. Make this less confusing by only passing in
+a non-zero quadrant when it is actually necessary.
+
+Signed-off-by: David Matlack <dmatlack@google.com>
+Message-Id: <20220516232138.1783324-6-dmatlack@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index 3a5ed967037765..dbc18d4cc572c1 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -3444,9 +3444,10 @@ static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, int quadrant,
+ struct kvm_mmu_page *sp;
+
+ role.level = level;
++ role.quadrant = quadrant;
+
+- if (!role.gpte_is_8_bytes)
+- role.quadrant = quadrant;
++ WARN_ON_ONCE(quadrant && role.gpte_is_8_bytes);
++ WARN_ON_ONCE(role.direct && !role.gpte_is_8_bytes);
+
+ sp = kvm_mmu_get_page(vcpu, gfn, role);
+ ++sp->root_count;
+@@ -3482,7 +3483,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
+ for (i = 0; i < 4; ++i) {
+ WARN_ON_ONCE(IS_VALID_PAE_ROOT(mmu->pae_root[i]));
+
+- root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), i,
++ root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), 0,
+ PT32_ROOT_LEVEL);
+ mmu->pae_root[i] = root | PT_PRESENT_MASK |
+ shadow_me_mask;
+@@ -3506,9 +3507,8 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
+ struct kvm_mmu *mmu = vcpu->arch.mmu;
+ u64 pdptrs[4], pm_mask;
+ gfn_t root_gfn, root_pgd;
++ int quadrant, i, r;
+ hpa_t root;
+- unsigned i;
+- int r;
+
+ root_pgd = mmu->get_guest_pgd(vcpu);
+ root_gfn = root_pgd >> PAGE_SHIFT;
+@@ -3591,7 +3591,15 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
+ root_gfn = pdptrs[i] >> PAGE_SHIFT;
+ }
+
+- root = mmu_alloc_root(vcpu, root_gfn, i, PT32_ROOT_LEVEL);
++ /*
++ * If shadowing 32-bit non-PAE page tables, each PAE page
++ * directory maps one quarter of the guest's non-PAE page
++ * directory. Othwerise each PAE page direct shadows one guest
++ * PAE page directory so that quadrant should be 0.
++ */
++ quadrant = !mmu->mmu_role.base.gpte_is_8_bytes ? i : 0;
++
++ root = mmu_alloc_root(vcpu, root_gfn, quadrant, PT32_ROOT_LEVEL);
+ mmu->pae_root[i] = root | pm_mask;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 3776b66e4f8c1d6c8b888792cf8a31987b316bd6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:14 +0200
+Subject: KVM: x86/mmu: Derive shadow MMU page role from parent
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 2e65e842c57d72e9a573ba42bc2055b7f626ea1f upstream.
+
+Instead of computing the shadow page role from scratch for every new
+page, derive most of the information from the parent shadow page. This
+eliminates the dependency on the vCPU root role to allocate shadow page
+tables, and reduces the number of parameters to kvm_mmu_get_page().
+
+Preemptively split out the role calculation to a separate function for
+use in a following commit.
+
+Note that when calculating the MMU root role, we can take
+@role.passthrough, @role.direct, and @role.access directly from
+@vcpu->arch.mmu->root_role. Only @role.level and @role.quadrant still
+must be overridden for PAE page directories, when shadowing 32-bit
+guest page tables with PAE page tables.
+
+No functional change intended.
+
+Reviewed-by: Peter Xu <peterx@redhat.com>
+Signed-off-by: David Matlack <dmatlack@google.com>
+Message-Id: <20220516232138.1783324-5-dmatlack@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 99 ++++++++++++++++++++++------------
+ arch/x86/kvm/mmu/paging_tmpl.h | 9 ++--
+ 2 files changed, 71 insertions(+), 37 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index bd7650380ad9e7..3a5ed967037765 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -2070,33 +2070,15 @@ static void clear_sp_write_flooding_count(u64 *spte)
+ __clear_sp_write_flooding_count(sptep_to_sp(spte));
+ }
+
+-static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+- gfn_t gfn,
+- gva_t gaddr,
+- unsigned level,
+- bool direct,
+- unsigned int access)
++static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, gfn_t gfn,
++ union kvm_mmu_page_role role)
+ {
+ bool direct_mmu = vcpu->arch.mmu->direct_map;
+- union kvm_mmu_page_role role;
+ struct hlist_head *sp_list;
+- unsigned quadrant;
+ struct kvm_mmu_page *sp;
+ int collisions = 0;
+ LIST_HEAD(invalid_list);
+
+- role = vcpu->arch.mmu->mmu_role.base;
+- role.level = level;
+- role.direct = direct;
+- if (role.direct)
+- role.gpte_is_8_bytes = true;
+- role.access = access;
+- if (!direct_mmu && vcpu->arch.mmu->root_level <= PT32_ROOT_LEVEL) {
+- quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level));
+- quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
+- role.quadrant = quadrant;
+- }
+-
+ sp_list = &vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)];
+ for_each_valid_sp(vcpu->kvm, sp, sp_list) {
+ if (sp->gfn != gfn) {
+@@ -2114,7 +2096,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+ * Unsync pages must not be left as is, because the new
+ * upper-level page will be write-protected.
+ */
+- if (level > PG_LEVEL_4K && sp->unsync)
++ if (role.level > PG_LEVEL_4K && sp->unsync)
+ kvm_mmu_prepare_zap_page(vcpu->kvm, sp,
+ &invalid_list);
+ continue;
+@@ -2152,14 +2134,14 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+
+ ++vcpu->kvm->stat.mmu_cache_miss;
+
+- sp = kvm_mmu_alloc_page(vcpu, direct);
++ sp = kvm_mmu_alloc_page(vcpu, role.direct);
+
+ sp->gfn = gfn;
+ sp->role = role;
+ hlist_add_head(&sp->hash_link, sp_list);
+- if (!direct) {
++ if (!role.direct) {
+ account_shadowed(vcpu->kvm, sp);
+- if (level == PG_LEVEL_4K && rmap_write_protect(vcpu, gfn))
++ if (role.level == PG_LEVEL_4K && rmap_write_protect(vcpu, gfn))
+ kvm_flush_remote_tlbs_with_address(vcpu->kvm, gfn, 1);
+ }
+ trace_kvm_mmu_get_page(sp, true);
+@@ -2171,6 +2153,54 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+ return sp;
+ }
+
++static union kvm_mmu_page_role kvm_mmu_child_role(u64 *sptep, bool direct, unsigned int access)
++{
++ struct kvm_mmu_page *parent_sp = sptep_to_sp(sptep);
++ union kvm_mmu_page_role role;
++
++ role = parent_sp->role;
++ role.level--;
++ role.access = access;
++ role.direct = direct;
++
++ /*
++ * If the guest has 4-byte PTEs then that means it's using 32-bit,
++ * 2-level, non-PAE paging. KVM shadows such guests with PAE paging
++ * (i.e. 8-byte PTEs). The difference in PTE size means that KVM must
++ * shadow each guest page table with multiple shadow page tables, which
++ * requires extra bookkeeping in the role.
++ *
++ * Specifically, to shadow the guest's page directory (which covers a
++ * 4GiB address space), KVM uses 4 PAE page directories, each mapping
++ * 1GiB of the address space. @role.quadrant encodes which quarter of
++ * the address space each maps.
++ *
++ * To shadow the guest's page tables (which each map a 4MiB region), KVM
++ * uses 2 PAE page tables, each mapping a 2MiB region. For these,
++ * @role.quadrant encodes which half of the region they map.
++ *
++ * Note, the 4 PAE page directories are pre-allocated and the quadrant
++ * assigned in mmu_alloc_root(). So only page tables need to be handled
++ * here.
++ */
++ if (!role.gpte_is_8_bytes) {
++ WARN_ON_ONCE(role.level != PG_LEVEL_4K);
++ role.quadrant = (sptep - parent_sp->spt) % 2;
++ }
++
++ return role;
++}
++
++static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu,
++ u64 *sptep, gfn_t gfn,
++ bool direct, unsigned int access)
++{
++ union kvm_mmu_page_role role;
++
++ role = kvm_mmu_child_role(sptep, direct, access);
++ return kvm_mmu_get_page(vcpu, gfn, role);
++}
++
+ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterator,
+ struct kvm_vcpu *vcpu, hpa_t root,
+ u64 addr)
+@@ -3013,8 +3043,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
+ if (is_shadow_present_pte(*it.sptep))
+ continue;
+
+- sp = kvm_mmu_get_page(vcpu, base_gfn, it.addr,
+- it.level - 1, true, ACC_ALL);
++ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, true, ACC_ALL);
+
+ link_shadow_page(vcpu, it.sptep, sp);
+ if (is_tdp && huge_page_disallowed &&
+@@ -3408,13 +3437,18 @@ static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn)
+ return ret;
+ }
+
+-static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva,
++static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, int quadrant,
+ u8 level)
+ {
+- bool direct = vcpu->arch.mmu->mmu_role.base.direct;
++ union kvm_mmu_page_role role = vcpu->arch.mmu->mmu_role.base;
+ struct kvm_mmu_page *sp;
+
+- sp = kvm_mmu_get_page(vcpu, gfn, gva, level, direct, ACC_ALL);
++ role.level = level;
++
++ if (!role.gpte_is_8_bytes)
++ role.quadrant = quadrant;
++
++ sp = kvm_mmu_get_page(vcpu, gfn, role);
+ ++sp->root_count;
+
+ return __pa(sp->spt);
+@@ -3448,8 +3482,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
+ for (i = 0; i < 4; ++i) {
+ WARN_ON_ONCE(IS_VALID_PAE_ROOT(mmu->pae_root[i]));
+
+- root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT),
+- i << 30, PT32_ROOT_LEVEL);
++ root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT), i,
++ PT32_ROOT_LEVEL);
+ mmu->pae_root[i] = root | PT_PRESENT_MASK |
+ shadow_me_mask;
+ }
+@@ -3557,8 +3591,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
+ root_gfn = pdptrs[i] >> PAGE_SHIFT;
+ }
+
+- root = mmu_alloc_root(vcpu, root_gfn, i << 30,
+- PT32_ROOT_LEVEL);
++ root = mmu_alloc_root(vcpu, root_gfn, i, PT32_ROOT_LEVEL);
+ mmu->pae_root[i] = root | pm_mask;
+ }
+
+diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
+index a1811f51eda925..cc70cbb3f261ba 100644
+--- a/arch/x86/kvm/mmu/paging_tmpl.h
++++ b/arch/x86/kvm/mmu/paging_tmpl.h
+@@ -704,8 +704,9 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
+ if (!is_shadow_present_pte(*it.sptep)) {
+ table_gfn = gw->table_gfn[it.level - 2];
+ access = gw->pt_access[it.level - 2];
+- sp = kvm_mmu_get_page(vcpu, table_gfn, addr,
+- it.level-1, false, access);
++ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn,
++ false, access);
++
+ /*
+ * We must synchronize the pagetable before linking it
+ * because the guest doesn't need to flush tlb when
+@@ -763,8 +764,8 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
+ drop_large_spte(vcpu, it.sptep);
+
+ if (!is_shadow_present_pte(*it.sptep)) {
+- sp = kvm_mmu_get_page(vcpu, base_gfn, addr,
+- it.level - 1, true, direct_access);
++ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn,
++ true, direct_access);
+ link_shadow_page(vcpu, it.sptep, sp);
+ if (huge_page_disallowed && req_level >= it.level)
+ account_huge_nx_page(vcpu->kvm, sp);
+--
+2.53.0
+
--- /dev/null
+From 53868487a36b1a092a7b7cdb98b5375fd4271ce4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:19 +0200
+Subject: KVM: x86/mmu: Ensure hugepage is in by slot before checking max
+ mapping level
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit ef057cbf825e03b63f6edf5980f96abf3c53089d upstream.
+
+When recovering hugepages in the shadow MMU, verify that the base gfn of
+the shadow page is actually contained within the target memslot, *before*
+querying the max mapping level given the shadow page's gfn. Failure to
+pre-check the validity of the gfn can lead to an out-of-bounds access to
+the slot's lpage_info (which typically manifests as a host #PF because the
+lpage_info is vmalloc'd) if the guest creates a hugepage mapping (in its
+PTEs) that extends "below" the bounds of a memslot.
+
+When faulting in memory for a guest, and the size of the guest mapping is
+greater than KVM's (current) max mapping, then KVM will create a "direct"
+shadow page (direct in that there are no gPTEs to shadow, and so the target
+gfn is a direct calculation given the base gfn of the shadow page). The
+hugepage recovery flow looks for such direct shadow pages, as forcing 4KiB
+mappings when dirty logging generates the guest > host mapping size case.
+When the 4KiB restriction is lifted, then KVM can replace the shadow page
+with a hugepage.
+
+But if KVM originally used a smaller mapping than the guest because the
+range of memory covered by the guest hugepage exceeds the bounds of a
+memslot, then KVM will link a direct shadow page with a gfn that is outside
+the bounds of the memslot being used to fault in memory. The rmap entry
+added for the leaf mapping is correct and within bounds, but the gfn of the
+leaf SPTE's parent shadow page will be out of bounds.
+
+ BUG: unable to handle page fault for address: ffffc90000806ffc
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 100000067 P4D 100000067 PUD 1002a7067 PMD 10612f067 PTE 0
+ Oops: Oops: 0000 [#1] SMP
+ CPU: 13 UID: 1000 PID: 757 Comm: mmu_stress_test Not tainted 7.1.0-rc1-48ce1e26eace-x86_pir_to_irr_comments-vm #341 PREEMPT
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
+ RIP: 0010:kvm_mmu_max_mapping_level+0x79/0x2b0 [kvm]
+ Call Trace:
+ <TASK>
+ kvm_mmu_recover_huge_pages+0x21b/0x320 [kvm]
+ kvm_set_memslot+0x1ee/0x590 [kvm]
+ kvm_set_memory_region.part.0+0x3a1/0x4d0 [kvm]
+ kvm_vm_ioctl+0x9bf/0x15d0 [kvm]
+ __x64_sys_ioctl+0x8a/0xd0
+ do_syscall_64+0xb7/0xbb0
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ RIP: 0033:0x7f21c0f1a9bf
+ </TASK>
+
+Don't bother pre-checking the bounds of the potential hugepage, i.e. don't
+check that e.g. sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level + 1) is also
+within the memslot, as the checks performed by kvm_mmu_max_mapping_level()
+are a superset of the basic bounds checks. I.e. pre-checking the full
+range would be a dubious micro-optimization.
+
+Fixes: 9eba50f8d7fc ("KVM: x86/mmu: Consult max mapping level when zapping collapsible SPTEs")
+Cc: stable@vger.kernel.org
+Cc: David Matlack <dmatlack@google.com>
+Cc: James Houghton <jthoughton@google.com>
+Cc: Alexander Bulekov <bkov@amazon.com>
+Cc: Fred Griffoul <fgriffo@amazon.co.uk>
+Cc: Alexander Graf <graf@amazon.de>
+Cc: David Woodhouse <dwmw@amazon.co.uk>
+Cc: Filippo Sironi <sironi@amazon.de>
+Cc: Ivan Orlov <iorlov@amazon.co.uk>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 19 +++++++++++++------
+ include/linux/kvm_host.h | 7 ++++++-
+ 2 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index e9dbe3e7ec622f..3b993fade5f712 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -5883,13 +5883,20 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
+ pfn = spte_to_pfn(*sptep);
+
+ /*
+- * We cannot do huge page mapping for indirect shadow pages,
+- * which are found on the last rmap (level = 1) when not using
+- * tdp; such shadow pages are synced with the page table in
+- * the guest, and the guest page table is using 4K page size
+- * mapping if the indirect sp has level = 1.
++ * Direct shadow page can be replaced by a hugepage if the host
++ * mapping level allows it and the memslot maps all of the host
++ * hugepage. Note! If the memslot maps only part of the
++ * hugepage, sp->gfn may be below slot->base_gfn, and querying
++ * the max mapping level would cause an out-of-bounds lpage_info
++ * access. So the gfn bounds check *must* be done first.
++ *
++ * Indirect shadow pages are created when the guest page tables
++ * are using 4K pages. Since the host mapping is always
++ * constrained by the page size in the guest, indirect shadow
++ * pages are never collapsible.
+ */
+- if (sp->role.direct && !kvm_is_reserved_pfn(pfn) &&
++ if (sp->role.direct && is_gfn_in_memslot(slot, sp->gfn) &&
++ !kvm_is_reserved_pfn(pfn) &&
+ sp->role.level < kvm_mmu_max_mapping_level(kvm, slot, sp->gfn,
+ pfn, PG_LEVEL_NUM)) {
+ pte_list_remove(kvm, rmap_head, sptep);
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index ec12082e587df3..118a3905afb006 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -1312,6 +1312,11 @@ int kvm_request_irq_source_id(struct kvm *kvm);
+ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
+ bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
+
++static inline bool is_gfn_in_memslot(const struct kvm_memory_slot *slot, gfn_t gfn)
++{
++ return gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages;
++}
++
+ /*
+ * Returns a pointer to the memslot at slot_index if it contains gfn.
+ * Otherwise returns NULL.
+@@ -1332,7 +1337,7 @@ try_get_memslot(struct kvm_memslots *slots, int slot_index, gfn_t gfn)
+ slot_index = array_index_nospec(slot_index, slots->used_slots);
+ slot = &slots->memslots[slot_index];
+
+- if (gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages)
++ if (is_gfn_in_memslot(slot, gfn))
+ return slot;
+ else
+ return NULL;
+--
+2.53.0
+
--- /dev/null
+From bcc6397d244844807014d82fa65afa416d431f0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:16 +0200
+Subject: KVM: x86/mmu: pull call to drop_large_spte() into
+ __link_shadow_page()
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 0cd8dc739833080aa0813cbd94d907a93e3a14c3 upstream.
+
+Before allocating a child shadow page table, all callers check
+whether the parent already points to a huge page and, if so, they
+drop that SPTE. This is done by drop_large_spte().
+
+However, dropping the large SPTE is really only necessary before the
+sp is installed. While the sp is returned by kvm_mmu_get_child_sp(),
+installing it happens later in __link_shadow_page(). Move the call
+there instead of having it in each and every caller.
+
+To ensure that the shadow page is not linked twice if it was present,
+do _not_ opportunistically make kvm_mmu_get_child_sp() idempotent:
+instead, return an error value if the shadow page already existed.
+This is a bit more verbose, but clearer than NULL.
+
+Finally, now that the drop_large_spte() name is not taken anymore,
+remove the two underscores in front of __drop_large_spte().
+
+Reviewed-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 49 +++++++++++++++++++---------------
+ arch/x86/kvm/mmu/paging_tmpl.h | 29 +++++++++-----------
+ 2 files changed, 40 insertions(+), 38 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index dbc18d4cc572c1..d58be2e698f795 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -1179,26 +1179,16 @@ static void drop_spte(struct kvm *kvm, u64 *sptep)
+ rmap_remove(kvm, sptep);
+ }
+
+-
+-static bool __drop_large_spte(struct kvm *kvm, u64 *sptep)
++static void drop_large_spte(struct kvm *kvm, u64 *sptep)
+ {
+- if (is_large_pte(*sptep)) {
+- WARN_ON(sptep_to_sp(sptep)->role.level == PG_LEVEL_4K);
+- drop_spte(kvm, sptep);
+- return true;
+- }
+-
+- return false;
+-}
++ struct kvm_mmu_page *sp;
+
+-static void drop_large_spte(struct kvm_vcpu *vcpu, u64 *sptep)
+-{
+- if (__drop_large_spte(vcpu->kvm, sptep)) {
+- struct kvm_mmu_page *sp = sptep_to_sp(sptep);
++ sp = sptep_to_sp(sptep);
++ WARN_ON(sp->role.level == PG_LEVEL_4K);
+
+- kvm_flush_remote_tlbs_with_address(vcpu->kvm, sp->gfn,
++ drop_spte(kvm, sptep);
++ kvm_flush_remote_tlbs_with_address(kvm, sp->gfn,
+ KVM_PAGES_PER_HPAGE(sp->role.level));
+- }
+ }
+
+ /*
+@@ -2197,6 +2187,9 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu,
+ {
+ union kvm_mmu_page_role role;
+
++ if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
++ return ERR_PTR(-EEXIST);
++
+ role = kvm_mmu_child_role(sptep, direct, access);
+ return kvm_mmu_get_page(vcpu, gfn, role);
+ }
+@@ -2264,13 +2257,21 @@ static void shadow_walk_next(struct kvm_shadow_walk_iterator *iterator)
+ __shadow_walk_next(iterator, *iterator->sptep);
+ }
+
+-static void link_shadow_page(struct kvm_vcpu *vcpu, u64 *sptep,
+- struct kvm_mmu_page *sp)
++static void __link_shadow_page(struct kvm_vcpu *vcpu,
++ struct kvm_mmu_memory_cache *cache, u64 *sptep,
++ struct kvm_mmu_page *sp)
+ {
+ u64 spte;
+
+ BUILD_BUG_ON(VMX_EPT_WRITABLE_MASK != PT_WRITABLE_MASK);
+
++ /*
++ * If an SPTE is present already, it must be a leaf and therefore
++ * a large one. Drop it and flush the TLB before installing sp.
++ */
++ if (is_shadow_present_pte(*sptep))
++ drop_large_spte(vcpu->kvm, sptep);
++
+ spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp));
+
+ mmu_spte_set(sptep, spte);
+@@ -2281,6 +2282,12 @@ static void link_shadow_page(struct kvm_vcpu *vcpu, u64 *sptep,
+ mark_unsync(sptep);
+ }
+
++static void link_shadow_page(struct kvm_vcpu *vcpu, u64 *sptep,
++ struct kvm_mmu_page *sp)
++{
++ __link_shadow_page(vcpu, &vcpu->arch.mmu_pte_list_desc_cache, sptep, sp);
++}
++
+ static void validate_direct_spte(struct kvm_vcpu *vcpu, u64 *sptep,
+ unsigned direct_access)
+ {
+@@ -3039,11 +3046,9 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
+ if (it.level == level)
+ break;
+
+- drop_large_spte(vcpu, it.sptep);
+- if (is_shadow_present_pte(*it.sptep))
+- continue;
+-
+ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn, true, ACC_ALL);
++ if (sp == ERR_PTR(-EEXIST))
++ continue;
+
+ link_shadow_page(vcpu, it.sptep, sp);
+ if (is_tdp && huge_page_disallowed &&
+diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
+index cc70cbb3f261ba..0f68f5afa642c8 100644
+--- a/arch/x86/kvm/mmu/paging_tmpl.h
++++ b/arch/x86/kvm/mmu/paging_tmpl.h
+@@ -698,15 +698,13 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
+ gfn_t table_gfn;
+
+ clear_sp_write_flooding_count(it.sptep);
+- drop_large_spte(vcpu, it.sptep);
+
+- sp = NULL;
+- if (!is_shadow_present_pte(*it.sptep)) {
+- table_gfn = gw->table_gfn[it.level - 2];
+- access = gw->pt_access[it.level - 2];
+- sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn,
+- false, access);
++ table_gfn = gw->table_gfn[it.level - 2];
++ access = gw->pt_access[it.level - 2];
++ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, table_gfn,
++ false, access);
+
++ if (sp != ERR_PTR(-EEXIST)) {
+ /*
+ * We must synchronize the pagetable before linking it
+ * because the guest doesn't need to flush tlb when
+@@ -735,7 +733,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
+ if (FNAME(gpte_changed)(vcpu, gw, it.level - 1))
+ goto out_gpte_changed;
+
+- if (sp)
++ if (sp != ERR_PTR(-EEXIST))
+ link_shadow_page(vcpu, it.sptep, sp);
+ }
+
+@@ -761,15 +759,14 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
+
+ validate_direct_spte(vcpu, it.sptep, direct_access);
+
+- drop_large_spte(vcpu, it.sptep);
++ sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn,
++ true, direct_access);
++ if (sp == ERR_PTR(-EEXIST))
++ continue;
+
+- if (!is_shadow_present_pte(*it.sptep)) {
+- sp = kvm_mmu_get_child_sp(vcpu, it.sptep, base_gfn,
+- true, direct_access);
+- link_shadow_page(vcpu, it.sptep, sp);
+- if (huge_page_disallowed && req_level >= it.level)
+- account_huge_nx_page(vcpu->kvm, sp);
+- }
++ link_shadow_page(vcpu, it.sptep, sp);
++ if (huge_page_disallowed && req_level >= it.level)
++ account_huge_nx_page(vcpu->kvm, sp);
+ }
+
+ ret = mmu_set_spte(vcpu, it.sptep, gw->pte_access, write_fault,
+--
+2.53.0
+
--- /dev/null
+From 18d012c4f2b01a72e0682e509dad85caf3248d11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:13 +0200
+Subject: KVM: x86/mmu: Stop passing "direct" to mmu_alloc_root()
+
+From: David Matlack <dmatlack@google.com>
+
+commit 86938ab6925b8fe174ca6abf397e6ea9d3c054a4 upstream.
+
+The "direct" argument is vcpu->arch.mmu->root_role.direct,
+because unlike non-root page tables, it's impossible to have
+a direct root in an indirect MMU. So just use that.
+
+Suggested-by: Lai Jiangshan <jiangshanlai@gmail.com>
+Signed-off-by: David Matlack <dmatlack@google.com>
+Message-Id: <20220516232138.1783324-4-dmatlack@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index c03c4341a87fd7..bd7650380ad9e7 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -3409,8 +3409,9 @@ static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn)
+ }
+
+ static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva,
+- u8 level, bool direct)
++ u8 level)
+ {
++ bool direct = vcpu->arch.mmu->mmu_role.base.direct;
+ struct kvm_mmu_page *sp;
+
+ sp = kvm_mmu_get_page(vcpu, gfn, gva, level, direct, ACC_ALL);
+@@ -3436,7 +3437,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
+ root = kvm_tdp_mmu_get_vcpu_root_hpa(vcpu);
+ mmu->root_hpa = root;
+ } else if (shadow_root_level >= PT64_ROOT_4LEVEL) {
+- root = mmu_alloc_root(vcpu, 0, 0, shadow_root_level, true);
++ root = mmu_alloc_root(vcpu, 0, 0, shadow_root_level);
+ mmu->root_hpa = root;
+ } else if (shadow_root_level == PT32E_ROOT_LEVEL) {
+ if (WARN_ON_ONCE(!mmu->pae_root)) {
+@@ -3448,7 +3449,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
+ WARN_ON_ONCE(IS_VALID_PAE_ROOT(mmu->pae_root[i]));
+
+ root = mmu_alloc_root(vcpu, i << (30 - PAGE_SHIFT),
+- i << 30, PT32_ROOT_LEVEL, true);
++ i << 30, PT32_ROOT_LEVEL);
+ mmu->pae_root[i] = root | PT_PRESENT_MASK |
+ shadow_me_mask;
+ }
+@@ -3511,7 +3512,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
+ */
+ if (mmu->root_level >= PT64_ROOT_4LEVEL) {
+ root = mmu_alloc_root(vcpu, root_gfn, 0,
+- mmu->shadow_root_level, false);
++ mmu->shadow_root_level);
+ mmu->root_hpa = root;
+ goto set_root_pgd;
+ }
+@@ -3557,7 +3558,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
+ }
+
+ root = mmu_alloc_root(vcpu, root_gfn, i << 30,
+- PT32_ROOT_LEVEL, false);
++ PT32_ROOT_LEVEL);
+ mmu->pae_root[i] = root | pm_mask;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 88a03cd0c1f9927e56dc6fd8cb5dc4c44b2666d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 19:46:12 +0200
+Subject: KVM: x86/mmu: Use a bool for direct
+
+From: David Matlack <dmatlack@google.com>
+
+commit 27a59d57f073f21f029df1517c2c0a1abea5b0ce upstream.
+
+The parameter "direct" can either be true or false, and all of the
+callers pass in a bool variable or true/false literal, so just use the
+type bool.
+
+No functional change intended.
+
+Reviewed-by: Lai Jiangshan <jiangshanlai@gmail.com>
+Reviewed-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: David Matlack <dmatlack@google.com>
+Message-Id: <20220516232138.1783324-3-dmatlack@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/mmu/mmu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index e4813964bfa07a..c03c4341a87fd7 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -1737,7 +1737,7 @@ static void drop_parent_pte(struct kvm_mmu_page *sp,
+ mmu_spte_clear_no_track(parent_pte);
+ }
+
+-static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, int direct)
++static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, bool direct)
+ {
+ struct kvm_mmu_page *sp;
+
+@@ -2074,7 +2074,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
+ gfn_t gfn,
+ gva_t gaddr,
+ unsigned level,
+- int direct,
++ bool direct,
+ unsigned int access)
+ {
+ bool direct_mmu = vcpu->arch.mmu->direct_map;
+--
+2.53.0
+
virtiofs-fix-uaf-on-submount-umount.patch
revert-selftest-ptp-update-ptp-selftest-to-exercise-.patch
revert-ptp-add-testptp-mask-test.patch
+kvm-x86-mmu-use-a-bool-for-direct.patch
+kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch
+kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch
+kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch
+kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch
+kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch
+kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529
+kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch
+kselftest-arm64-signal-skip-sve-signal-test-if-not-e.patch
--- /dev/null
+From a7260c5e57af3037cb73c10921723f4d3ca3a5d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 21:28:54 +0200
+Subject: KVM: SEV: Ignore MMIO requests of length '0'
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 1aa8a6dc7dac8b83234b53518311bf78231f4fa5 upstream.
+
+Explicitly ignore MMIO requests of length '0', so that setting up the
+software scratch area (and other code) doesn't have to worry about
+underflowing the length, and to allow for special casing '0' in the
+future.
+
+Fixes: 8f423a80d299 ("KVM: SVM: Support MMIO for an SEV-ES guest")
+Cc: stable@vger.kernel.org
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-ID: <20260501202250.2115252-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Jack Wang <jinpu.wang@ionos.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 115c59c86f448a..0a01971e33f0b7 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -4347,6 +4347,9 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+ exit_code = kvm_ghcb_get_sw_exit_code(control);
+ switch (exit_code) {
+ case SVM_VMGEXIT_MMIO_READ:
++ if (!control->exit_info_2)
++ return 1;
++
+ ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
+ if (ret)
+ break;
+@@ -4357,6 +4360,9 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+ svm->sev_es.ghcb_sa);
+ break;
+ case SVM_VMGEXIT_MMIO_WRITE:
++ if (!control->exit_info_2)
++ return 1;
++
+ ret = setup_vmgexit_scratch(svm, false, control->exit_info_2);
+ if (ret)
+ break;
+--
+2.53.0
+
--- /dev/null
+From 5e0c1f8fce4de31722a7f8a96fa4b3c5cf82a90b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 21:28:56 +0200
+Subject: KVM: SEV: Ignore Port I/O requests of length '0'
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 3988bd2723de407ae90fa7a6f6029b4e60238c58 upstream.
+
+Explicitly ignore Port I/O requests of length '0' (or count '0'), so that
+setting up the software scratch area (and other code) doesn't have to
+worry about underflowing the length, and to allow for WARNing on trying
+to configure the scratch area with len==0.
+
+Fixes: 291bd20d5d88 ("KVM: SVM: Add initial support for a VMGEXIT VMEXIT")
+Cc: stable@vger.kernel.org
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-ID: <20260501202250.2115252-5-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Jack Wang <jinpu.wang@ionos.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 497a6e70513570..73e49317735173 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -4459,6 +4459,11 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+ control->exit_info_1, control->exit_info_2);
+ ret = -EINVAL;
+ break;
++ case SVM_EXIT_IOIO:
++ if (!((control->exit_info_1 & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT))
++ return 1;
++
++ fallthrough;
+ default:
+ ret = svm_invoke_exit_handler(vcpu, exit_code);
+ }
+@@ -4479,6 +4484,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
+ if (unlikely(check_mul_overflow(count, size, &bytes)))
+ return -EINVAL;
+
++ if (!bytes)
++ return 1;
++
+ r = setup_vmgexit_scratch(svm, in, bytes);
+ if (r)
+ return r;
+--
+2.53.0
+
--- /dev/null
+From 3a4a2c93944cea17c985feb4c198417b5f324ff3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 21:28:55 +0200
+Subject: KVM: SEV: Reject MMIO requests larger than 8 bytes with GHCB v2+
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit dcf1b2d4b0564a27e4ca7c654871aab4f9620046 upstream.
+
+When using GHCB v2+, reject MMIO requests that are larger than 8 bytes.
+Per the GHCB spec:
+
+ SW_EXITINFO2 must be less than or equal to 0x7fffffff for version 1 and
+ less than or equal to 0x8 for all other versions.
+
+Fixes: 4af663c2f64a ("KVM: SEV: Allow per-guest configuration of GHCB protocol version")
+Cc: stable@vger.kernel.org
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-ID: <20260501202250.2115252-4-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Jack Wang <jinpu.wang@ionos.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 0a01971e33f0b7..497a6e70513570 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -4350,6 +4350,13 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+ if (!control->exit_info_2)
+ return 1;
+
++ if (to_kvm_sev_info(vcpu->kvm)->ghcb_version >= 2 &&
++ control->exit_info_2 > 8) {
++ ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
++ ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
++ return 1;
++ }
++
+ ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
+ if (ret)
+ break;
+@@ -4363,6 +4370,13 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+ if (!control->exit_info_2)
+ return 1;
+
++ if (to_kvm_sev_info(vcpu->kvm)->ghcb_version >= 2 &&
++ control->exit_info_2 > 8) {
++ ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2);
++ ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT);
++ return 1;
++ }
++
+ ret = setup_vmgexit_scratch(svm, false, control->exit_info_2);
+ if (ret)
+ break;
+--
+2.53.0
+
--- /dev/null
+From b1d26b5ab59e4ab1787d3aef80f98b753abf396d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jun 2026 10:53:51 -0400
+Subject: Revert "PCI: qcom: Advertise Hotplug Slot Capability with no Command
+ Completion support"
+
+This reverts commit 480c94d3affbc11b9e98ca223a9fa19d90b84fbb.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-qcom.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
+index ae0f36e270baa1..5d27cd149f5120 100644
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -329,20 +329,15 @@ static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci)
+ dw_pcie_dbi_ro_wr_dis(pci);
+ }
+
+-static void qcom_pcie_set_slot_nccs(struct dw_pcie *pci)
++static void qcom_pcie_clear_hpc(struct dw_pcie *pci)
+ {
+ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ u32 val;
+
+ dw_pcie_dbi_ro_wr_en(pci);
+
+- /*
+- * Qcom PCIe Root Ports do not support generating command completion
+- * notifications for the Hot-Plug commands. So set the NCCS field to
+- * avoid waiting for the completions.
+- */
+ val = readl(pci->dbi_base + offset + PCI_EXP_SLTCAP);
+- val |= PCI_EXP_SLTCAP_NCCS;
++ val &= ~PCI_EXP_SLTCAP_HPC;
+ writel(val, pci->dbi_base + offset + PCI_EXP_SLTCAP);
+
+ dw_pcie_dbi_ro_wr_dis(pci);
+@@ -537,7 +532,7 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie)
+ writel(CFG_BRIDGE_SB_INIT,
+ pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL1);
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+@@ -617,7 +612,7 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
+ writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT);
+ }
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+@@ -710,7 +705,7 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie)
+ val |= EN;
+ writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+@@ -1014,7 +1009,7 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
+ writel(WR_NO_SNOOP_OVERIDE_EN | RD_NO_SNOOP_OVERIDE_EN,
+ pcie->parf + PARF_NO_SNOOP_OVERIDE);
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+--
+2.53.0
+
virtiofs-fix-uaf-on-submount-umount.patch
kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch
kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch
+revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch
+kvm-sev-ignore-mmio-requests-of-length-0.patch
+kvm-sev-reject-mmio-requests-larger-than-8-bytes-wit.patch
+kvm-sev-ignore-port-i-o-requests-of-length-0.patch
--- /dev/null
+From e05991356efd662f8a9fb480feea90862857424d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Jun 2026 10:31:22 -0400
+Subject: lockd: fix TEST handling when not all permissions are available.
+
+From: NeilBrown <neil@brown.name>
+
+[ Upstream commit 0b474240327cebeff08ad429e8ed3cfc6c8ee816 ]
+
+The F_GETLK fcntl can work with either read access or write access or
+both. It can query F_RDLCK and F_WRLCK locks in either case.
+
+However lockd currently treats F_GETLK similar to F_SETLK in that read
+access is required to query an F_RDLCK lock and write access is required
+to query a F_WRLCK lock.
+
+This is wrong and can cause problems - e.g. when qemu accesses a
+read-only (e.g. iso) filesystem image over NFS (though why it queries
+if it can get a write lock - I don't know. But it does, and this works
+with local filesystems).
+
+So we need TEST requests to be handled differently. To do this:
+
+- change nlm_do_fopen() to accept O_RDWR as a mode and in that case
+ succeed if either a O_RDONLY or O_WRONLY file can be opened.
+- change nlm_lookup_file() to accept a mode argument from caller,
+ instead of deducing base on lock time, and pass that on to nlm_do_fopen()
+- change nlm4svc_retrieve_args() and nlmsvc_retrieve_args() to detect
+ TEST requests and pass O_RDWR as a mode to nlm_lookup_file, passing
+ the same mode as before for other requests. Also set
+ lock->fl.c.flc_file to whichever file is available for TEST requests.
+- change nlmsvc_testlock() to also not calculate the mode, but to use
+ whatever was stored in lock->fl.c.flc_file.
+
+This behaviour of lockd - requesting O_WRONLY access to TEST for
+exclusive locks - has been present at least since git history began.
+However it was hidden until recently because knfsd ignored the access
+requested by lockd and required only READ access for all locking
+requests (unless the underlying filesystem provided an f_op->open
+function which checked access permissions).
+
+The commit mentioned in Fixes: below changed nfsd_permission() to NOT
+override the access request for LOCK requests and this exposed the bug
+that we are now fixing.
+
+Note that there is another issue that this patch does not address.
+The flock(.., LOCK_EX) call is permitted on a read-only file descriptor.
+Linux NFS maps this to NLM locking as whole-file byte-range locks.
+nfsd will see this as though it were fcntl( F_SETLK (F_WRLCK)) and will
+now require write access, which it might not be able to get.
+It is not clear if this is a problem in practice, or what the best
+solution might be. So no attempt is made to address it.
+
+Reported-by: Tj <tj.iam.tj@proton.me>
+Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1128861
+Fixes: 4cc9b9f2bf4d ("nfsd: refine and rename NFSD_MAY_LOCK")
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: NeilBrown <neil@brown.name>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/lockd/svc4proc.c | 13 ++++++++++---
+ fs/lockd/svclock.c | 4 +---
+ fs/lockd/svcproc.c | 15 ++++++++++++---
+ fs/lockd/svcsubs.c | 35 +++++++++++++++++++++++++----------
+ include/linux/lockd/lockd.h | 2 +-
+ 5 files changed, 49 insertions(+), 20 deletions(-)
+
+diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
+index 4b6f18d977343d..75e020a8bfd072 100644
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -26,6 +26,8 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
+ struct nlm_lock *lock = &argp->lock;
++ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
++ rqstp->rq_proc == NLMPROC_TEST_MSG);
+ __be32 error = 0;
+
+ /* nfsd callbacks must have been installed for this procedure */
+@@ -46,15 +48,20 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+ if (filp != NULL) {
+ int mode = lock_to_openmode(&lock->fl);
+
++ if (is_test)
++ mode = O_RDWR;
++
+ lock->fl.c.flc_flags = FL_POSIX;
+
+- error = nlm_lookup_file(rqstp, &file, lock);
++ error = nlm_lookup_file(rqstp, &file, lock, mode);
+ if (error)
+ goto no_locks;
+ *filp = file;
+-
+ /* Set up the missing parts of the file_lock structure */
+- lock->fl.c.flc_file = file->f_file[mode];
++ if (is_test)
++ lock->fl.c.flc_file = nlmsvc_file_file(file);
++ else
++ lock->fl.c.flc_file = file->f_file[mode];
+ lock->fl.c.flc_pid = current->tgid;
+ lock->fl.fl_start = (loff_t)lock->lock_start;
+ lock->fl.fl_end = lock->lock_len ?
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index d66e8285159996..c35ffa1b4b89d4 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -611,7 +611,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+ struct nlm_lock *conflock)
+ {
+ int error;
+- int mode;
+ __be32 ret;
+
+ dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
+@@ -626,14 +625,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+ goto out;
+ }
+
+- mode = lock_to_openmode(&lock->fl);
+ locks_init_lock(&conflock->fl);
+ /* vfs_test_lock only uses start, end, and owner, but tests flc_file */
+ conflock->fl.c.flc_file = lock->fl.c.flc_file;
+ conflock->fl.fl_start = lock->fl.fl_start;
+ conflock->fl.fl_end = lock->fl.fl_end;
+ conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
+- error = vfs_test_lock(file->f_file[mode], &conflock->fl);
++ error = vfs_test_lock(lock->fl.c.flc_file, &conflock->fl);
+ if (error) {
+ /* We can't currently deal with deferred test requests */
+ if (error == FILE_LOCK_DEFERRED)
+diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
+index 5817ef272332d9..d98e8d684376b7 100644
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -55,6 +55,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
+ struct nlm_lock *lock = &argp->lock;
++ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
++ rqstp->rq_proc == NLMPROC_TEST_MSG);
+ int mode;
+ __be32 error = 0;
+
+@@ -70,15 +72,22 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+
+ /* Obtain file pointer. Not used by FREE_ALL call. */
+ if (filp != NULL) {
+- error = cast_status(nlm_lookup_file(rqstp, &file, lock));
++ mode = lock_to_openmode(&lock->fl);
++
++ if (is_test)
++ mode = O_RDWR;
++
++ error = cast_status(nlm_lookup_file(rqstp, &file, lock, mode));
+ if (error != 0)
+ goto no_locks;
+ *filp = file;
+
+ /* Set up the missing parts of the file_lock structure */
+- mode = lock_to_openmode(&lock->fl);
+ lock->fl.c.flc_flags = FL_POSIX;
+- lock->fl.c.flc_file = file->f_file[mode];
++ if (is_test)
++ lock->fl.c.flc_file = nlmsvc_file_file(file);
++ else
++ lock->fl.c.flc_file = file->f_file[mode];
+ lock->fl.c.flc_pid = current->tgid;
+ lock->fl.fl_lmops = &nlmsvc_lock_operations;
+ nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
+diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
+index 9103896164f688..7ea204eadfcace 100644
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -82,18 +82,35 @@ int lock_to_openmode(struct file_lock *lock)
+ *
+ * We have to make sure we have the right credential to open
+ * the file.
++ *
++ * mode can be O_RDONLY(0), O_WRONLY(1) or O_RDWR(2). The latter
++ * means success can be achieved with EITHER O_RDONLY or O_WRONLY.
++ * It does NOT mean both read and write are required.
+ */
+ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
+ struct nlm_file *file, int mode)
+ {
+- struct file **fp = &file->f_file[mode];
+- __be32 nfserr;
++ __be32 nfserr = nlm_lck_denied_nolocks;
++ __be32 deferred = 0;
++ struct file **fp;
++ int m;
+
+- if (*fp)
+- return 0;
+- nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
+- if (nfserr)
+- dprintk("lockd: open failed (error %d)\n", nfserr);
++ for (m = O_RDONLY ; m <= O_WRONLY ; m++) {
++ if (mode != O_RDWR && mode != m)
++ continue;
++
++ fp = &file->f_file[m];
++ if (*fp)
++ return 0;
++ nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, m);
++ if (!nfserr)
++ return 0;
++ if (nfserr == nlm_drop_reply)
++ deferred = nfserr;
++ }
++ if (deferred)
++ return deferred;
++ dprintk("lockd: open failed (error %d)\n", ntohl(nfserr));
+ return nfserr;
+ }
+
+@@ -103,17 +120,15 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
+ */
+ __be32
+ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
+- struct nlm_lock *lock)
++ struct nlm_lock *lock, int mode)
+ {
+ struct nlm_file *file;
+ unsigned int hash;
+ __be32 nfserr;
+- int mode;
+
+ nlm_debug_print_fh("nlm_lookup_file", &lock->fh);
+
+ hash = file_hash(&lock->fh);
+- mode = lock_to_openmode(&lock->fl);
+
+ /* Lock file table */
+ mutex_lock(&nlm_file_mutex);
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
+index c8f0f9458f2cc0..d9930fc43ca540 100644
+--- a/include/linux/lockd/lockd.h
++++ b/include/linux/lockd/lockd.h
+@@ -293,7 +293,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
+ * File handling for the server personality
+ */
+ __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
+- struct nlm_lock *);
++ struct nlm_lock *, int);
+ void nlm_release_file(struct nlm_file *);
+ void nlmsvc_put_lockowner(struct nlm_lockowner *);
+ void nlmsvc_release_lockowner(struct nlm_lock *);
+--
+2.53.0
+
--- /dev/null
+From 8a29c0407dd15336ee5619acadda00de8fc7071a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jun 2026 10:53:39 -0400
+Subject: Revert "PCI: qcom: Advertise Hotplug Slot Capability with no Command
+ Completion support"
+
+This reverts commit f176c47683bf6365e2f6d580d557fae49169a703.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-qcom.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
+index 43555ad9e5dcf5..789cc0e3c10da9 100644
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -341,20 +341,15 @@ static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci)
+ dw_pcie_dbi_ro_wr_dis(pci);
+ }
+
+-static void qcom_pcie_set_slot_nccs(struct dw_pcie *pci)
++static void qcom_pcie_clear_hpc(struct dw_pcie *pci)
+ {
+ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ u32 val;
+
+ dw_pcie_dbi_ro_wr_en(pci);
+
+- /*
+- * Qcom PCIe Root Ports do not support generating command completion
+- * notifications for the Hot-Plug commands. So set the NCCS field to
+- * avoid waiting for the completions.
+- */
+ val = readl(pci->dbi_base + offset + PCI_EXP_SLTCAP);
+- val |= PCI_EXP_SLTCAP_NCCS;
++ val &= ~PCI_EXP_SLTCAP_HPC;
+ writel(val, pci->dbi_base + offset + PCI_EXP_SLTCAP);
+
+ dw_pcie_dbi_ro_wr_dis(pci);
+@@ -554,7 +549,7 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie)
+ writel(CFG_BRIDGE_SB_INIT,
+ pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL1);
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+@@ -634,7 +629,7 @@ static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie)
+ writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT);
+ }
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+@@ -727,7 +722,7 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie)
+ val |= EN;
+ writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+@@ -1033,7 +1028,7 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
+ writel(WR_NO_SNOOP_OVERRIDE_EN | RD_NO_SNOOP_OVERRIDE_EN,
+ pcie->parf + PARF_NO_SNOOP_OVERRIDE);
+
+- qcom_pcie_set_slot_nccs(pcie->pci);
++ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+ }
+--
+2.53.0
+
kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch
lsm-add-backing_file-lsm-hooks.patch
selinux-fix-overlayfs-mmap-and-mprotect-access-check.patch
+revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch
+lockd-fix-test-handling-when-not-all-permissions-are.patch
--- /dev/null
+From a78ebf762f6dc914ac28c8da87656d4c424a9308 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Apr 2026 22:24:29 +0300
+Subject: Bluetooth: btmtk: accept too short WMT FUNC_CTRL events
+
+From: Pauli Virtanen <pav@iki.fi>
+
+[ Upstream commit e3ac0d9f1a205f33a43fba3b79ef74d2f604c78b ]
+
+MT7925 (USB ID 0e8d:e025) on fw version 20260106153314 sends WMT
+FUNC_CTRL events that are missing the status field.
+
+Prior to commit 006b9943b982 ("Bluetooth: btmtk: validate WMT event SKB
+length before struct access") the status was read from out-of-bounds of
+SKB data, which usually would result to success with
+BTMTK_WMT_ON_UNDONE, although I don't know the intent here. The bounds
+check added in that commit returns with error instead, producing
+"Bluetooth: hci0: Failed to send wmt func ctrl (-22)" and makes the
+device unusable.
+
+Fix the regression by interpreting too short packet as status
+BTMTK_WMT_ON_UNDONE, which makes the device work normally again.
+
+Fixes: 634a4408c061 ("Bluetooth: btmtk: validate WMT event SKB length before struct access")
+Signed-off-by: Pauli Virtanen <pav@iki.fi>
+Tested-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> # MT7922 (0489:e0e2)
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btmtk.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
+index 5c6f4d4b2e7f0c..582915f9a8d700 100644
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -679,8 +679,8 @@ int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+ case BTMTK_WMT_FUNC_CTRL:
+ if (!skb_pull_data(data->evt_skb,
+ sizeof(wmt_evt_funcc->status))) {
+- err = -EINVAL;
+- goto err_free_skb;
++ status = BTMTK_WMT_ON_UNDONE;
++ break;
+ }
+
+ wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
+--
+2.53.0
+
--- /dev/null
+From 42ef3948ea9c63f31e5ef989f2df198010b03ba0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Apr 2026 11:14:54 +0000
+Subject: Bluetooth: btmtk: validate WMT event SKB length before struct access
+
+From: Tristan Madani <tristan@talencesecurity.com>
+
+[ Upstream commit 634a4408c0615c523cf7531790f4f14a422b9206 ]
+
+btmtk_usb_hci_wmt_sync() casts the WMT event response SKB data to
+struct btmtk_hci_wmt_evt (7 bytes) and struct btmtk_hci_wmt_evt_funcc
+(9 bytes) without first checking that the SKB contains enough data.
+A short firmware response causes out-of-bounds reads from SKB tailroom.
+
+Use skb_pull_data() to validate and advance past the base WMT event
+header. For the FUNC_CTRL case, pull the additional status field bytes
+before accessing them.
+
+Fixes: d019930b0049 ("Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btmtk.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
+index ad8753dda826bb..5c6f4d4b2e7f0c 100644
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -655,8 +655,13 @@ int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+ if (data->evt_skb == NULL)
+ goto err_free_wc;
+
+- /* Parse and handle the return WMT event */
+- wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
++ wmt_evt = skb_pull_data(data->evt_skb, sizeof(*wmt_evt));
++ if (!wmt_evt) {
++ bt_dev_err(hdev, "WMT event too short (%u bytes)",
++ data->evt_skb->len);
++ err = -EINVAL;
++ goto err_free_skb;
++ }
+ if (wmt_evt->whdr.op != hdr->op) {
+ bt_dev_err(hdev, "Wrong op received %d expected %d",
+ wmt_evt->whdr.op, hdr->op);
+@@ -672,6 +677,12 @@ int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
+ status = BTMTK_WMT_PATCH_DONE;
+ break;
+ case BTMTK_WMT_FUNC_CTRL:
++ if (!skb_pull_data(data->evt_skb,
++ sizeof(wmt_evt_funcc->status))) {
++ err = -EINVAL;
++ goto err_free_skb;
++ }
++
+ wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
+ if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
+ status = BTMTK_WMT_ON_DONE;
+--
+2.53.0
+
kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch
kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch
revert-ptp-add-testptp-mask-test.patch
+bluetooth-btmtk-validate-wmt-event-skb-length-before.patch
+bluetooth-btmtk-accept-too-short-wmt-func_ctrl-event.patch