]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees master
authorSasha Levin <sashal@kernel.org>
Sat, 27 Jun 2026 16:34:59 +0000 (12:34 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 27 Jun 2026 16:34:59 +0000 (12:34 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
27 files changed:
queue-5.10/crypto-qat-remove-unused-character-device-and-ioctls.patch [new file with mode: 0644]
queue-5.10/crypto-qat-replace-kzalloc-copy_from_user-with-memdu.patch [new file with mode: 0644]
queue-5.10/crypto-qat-return-pointer-directly-in-adf_ctl_alloc_.patch [new file with mode: 0644]
queue-5.10/documentation-ioctl-number-extend-include-file-colum.patch [new file with mode: 0644]
queue-5.10/net-sched-act_pedit-fix-action-bind-logic.patch [new file with mode: 0644]
queue-5.10/series
queue-5.15/kselftest-arm64-signal-skip-sve-signal-test-if-not-e.patch [new file with mode: 0644]
queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch [new file with mode: 0644]
queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529 [new file with mode: 0644]
queue-5.15/kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch [new file with mode: 0644]
queue-5.15/kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch [new file with mode: 0644]
queue-5.15/kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch [new file with mode: 0644]
queue-5.15/kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch [new file with mode: 0644]
queue-5.15/kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch [new file with mode: 0644]
queue-5.15/kvm-x86-mmu-use-a-bool-for-direct.patch [new file with mode: 0644]
queue-5.15/series
queue-6.12/kvm-sev-ignore-mmio-requests-of-length-0.patch [new file with mode: 0644]
queue-6.12/kvm-sev-ignore-port-i-o-requests-of-length-0.patch [new file with mode: 0644]
queue-6.12/kvm-sev-reject-mmio-requests-larger-than-8-bytes-wit.patch [new file with mode: 0644]
queue-6.12/revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch [new file with mode: 0644]
queue-6.12/series
queue-6.18/lockd-fix-test-handling-when-not-all-permissions-are.patch [new file with mode: 0644]
queue-6.18/revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch [new file with mode: 0644]
queue-6.18/series
queue-6.6/bluetooth-btmtk-accept-too-short-wmt-func_ctrl-event.patch [new file with mode: 0644]
queue-6.6/bluetooth-btmtk-validate-wmt-event-skb-length-before.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-5.10/crypto-qat-remove-unused-character-device-and-ioctls.patch b/queue-5.10/crypto-qat-remove-unused-character-device-and-ioctls.patch
new file mode 100644 (file)
index 0000000..12efc93
--- /dev/null
@@ -0,0 +1,714 @@
+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(&section, (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
+
diff --git a/queue-5.10/crypto-qat-replace-kzalloc-copy_from_user-with-memdu.patch b/queue-5.10/crypto-qat-replace-kzalloc-copy_from_user-with-memdu.patch
new file mode 100644 (file)
index 0000000..161f52e
--- /dev/null
@@ -0,0 +1,55 @@
+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
+
diff --git a/queue-5.10/crypto-qat-return-pointer-directly-in-adf_ctl_alloc_.patch b/queue-5.10/crypto-qat-return-pointer-directly-in-adf_ctl_alloc_.patch
new file mode 100644 (file)
index 0000000..8976571
--- /dev/null
@@ -0,0 +1,127 @@
+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
+
diff --git a/queue-5.10/documentation-ioctl-number-extend-include-file-colum.patch b/queue-5.10/documentation-ioctl-number-extend-include-file-colum.patch
new file mode 100644 (file)
index 0000000..ef98a4a
--- /dev/null
@@ -0,0 +1,545 @@
+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
+
diff --git a/queue-5.10/net-sched-act_pedit-fix-action-bind-logic.patch b/queue-5.10/net-sched-act_pedit-fix-action-bind-logic.patch
new file mode 100644 (file)
index 0000000..5b2d612
--- /dev/null
@@ -0,0 +1,206 @@
+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
+
index 6c6d385f8ab0d3baad1ebc8f8f6be0efb8a017a9..e48b2b93a924d7a1ca81f20ff29bee65ae410c53 100644 (file)
@@ -26,3 +26,8 @@ agp-amd64-fix-broken-error-propagation-in-agp_amd64_probe.patch
 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
diff --git a/queue-5.15/kselftest-arm64-signal-skip-sve-signal-test-if-not-e.patch b/queue-5.15/kselftest-arm64-signal-skip-sve-signal-test-if-not-e.patch
new file mode 100644 (file)
index 0000000..d24f73a
--- /dev/null
@@ -0,0 +1,49 @@
+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
+
diff --git a/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch b/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch
new file mode 100644 (file)
index 0000000..589f885
--- /dev/null
@@ -0,0 +1,153 @@
+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
+
diff --git a/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529 b/queue-5.15/kvm-x86-fix-shadow-paging-use-after-free-due-to-unex.patch-23529
new file mode 100644 (file)
index 0000000..772f811
--- /dev/null
@@ -0,0 +1,71 @@
+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
+
diff --git a/queue-5.15/kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch b/queue-5.15/kvm-x86-mmu-always-pass-0-for-quadrant-when-gptes-ar.patch
new file mode 100644 (file)
index 0000000..b3502dc
--- /dev/null
@@ -0,0 +1,79 @@
+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
+
diff --git a/queue-5.15/kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch b/queue-5.15/kvm-x86-mmu-derive-shadow-mmu-page-role-from-parent.patch
new file mode 100644 (file)
index 0000000..77edb26
--- /dev/null
@@ -0,0 +1,240 @@
+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
+
diff --git a/queue-5.15/kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch b/queue-5.15/kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-che.patch
new file mode 100644 (file)
index 0000000..5a3943c
--- /dev/null
@@ -0,0 +1,137 @@
+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
+
diff --git a/queue-5.15/kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch b/queue-5.15/kvm-x86-mmu-pull-call-to-drop_large_spte-into-__link.patch
new file mode 100644 (file)
index 0000000..920b801
--- /dev/null
@@ -0,0 +1,193 @@
+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
+
diff --git a/queue-5.15/kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch b/queue-5.15/kvm-x86-mmu-stop-passing-direct-to-mmu_alloc_root.patch
new file mode 100644 (file)
index 0000000..ef4721e
--- /dev/null
@@ -0,0 +1,76 @@
+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
+
diff --git a/queue-5.15/kvm-x86-mmu-use-a-bool-for-direct.patch b/queue-5.15/kvm-x86-mmu-use-a-bool-for-direct.patch
new file mode 100644 (file)
index 0000000..3798122
--- /dev/null
@@ -0,0 +1,50 @@
+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
+
index f3da244a4da4bdd474cf2649dfef39dc5e39c8be..0f0db55aee359032066822e91f185c9c75d72f98 100644 (file)
@@ -23,3 +23,12 @@ media-vidtv-fix-null-pointer-dereference-in-vidtv_mux_push_si.patch
 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
diff --git a/queue-6.12/kvm-sev-ignore-mmio-requests-of-length-0.patch b/queue-6.12/kvm-sev-ignore-mmio-requests-of-length-0.patch
new file mode 100644 (file)
index 0000000..7c11570
--- /dev/null
@@ -0,0 +1,53 @@
+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
+
diff --git a/queue-6.12/kvm-sev-ignore-port-i-o-requests-of-length-0.patch b/queue-6.12/kvm-sev-ignore-port-i-o-requests-of-length-0.patch
new file mode 100644 (file)
index 0000000..48dc715
--- /dev/null
@@ -0,0 +1,55 @@
+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
+
diff --git a/queue-6.12/kvm-sev-reject-mmio-requests-larger-than-8-bytes-wit.patch b/queue-6.12/kvm-sev-reject-mmio-requests-larger-than-8-bytes-wit.patch
new file mode 100644 (file)
index 0000000..648aeaf
--- /dev/null
@@ -0,0 +1,62 @@
+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
+
diff --git a/queue-6.12/revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch b/queue-6.12/revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch
new file mode 100644 (file)
index 0000000..db16dfb
--- /dev/null
@@ -0,0 +1,79 @@
+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
+
index cd1d4f3ab8877f1d62ece0bd9a89cefc9a05af4b..9200140766d67dcb4ce0081e5358907bd013ffa3 100644 (file)
@@ -92,3 +92,7 @@ media-vidtv-fix-null-pointer-dereference-in-vidtv_mux_push_si.patch
 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
diff --git a/queue-6.18/lockd-fix-test-handling-when-not-all-permissions-are.patch b/queue-6.18/lockd-fix-test-handling-when-not-all-permissions-are.patch
new file mode 100644 (file)
index 0000000..01325ca
--- /dev/null
@@ -0,0 +1,254 @@
+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
+
diff --git a/queue-6.18/revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch b/queue-6.18/revert-pci-qcom-advertise-hotplug-slot-capability-wi.patch
new file mode 100644 (file)
index 0000000..7ea41c1
--- /dev/null
@@ -0,0 +1,79 @@
+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
+
index d00f57e334ec7a373c7cd0ae75eb5f0a55ebe2e7..ad2d2ee538f4328bd8c890377e9b6cb60fb8bea5 100644 (file)
@@ -1,3 +1,5 @@
 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
diff --git a/queue-6.6/bluetooth-btmtk-accept-too-short-wmt-func_ctrl-event.patch b/queue-6.6/bluetooth-btmtk-accept-too-short-wmt-func_ctrl-event.patch
new file mode 100644 (file)
index 0000000..df6aee4
--- /dev/null
@@ -0,0 +1,50 @@
+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
+
diff --git a/queue-6.6/bluetooth-btmtk-validate-wmt-event-skb-length-before.patch b/queue-6.6/bluetooth-btmtk-validate-wmt-event-skb-length-before.patch
new file mode 100644 (file)
index 0000000..6617f8e
--- /dev/null
@@ -0,0 +1,63 @@
+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
+
index c79d3bee685a3280de34983a32314c8ec1280006..bf52f3ae0aac6f6822cf7de923e395cf1b1131d8 100644 (file)
@@ -83,3 +83,5 @@ eventpoll-fix-ep_remove-struct-eventpoll-struct-file.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-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