Hi Greg, On Mon, Jul 01, 2024 at 04:22:20PM +0200, gregkh@xxxxxxxxxxxxxxxxxxx wrote: > > The patch below does not apply to the 6.1-stable tree. > If someone wants it applied there, or to any other stable or longterm > tree, then please email the backport, including the original git commit > id to <stable@xxxxxxxxxxxxxxx>. > I can’t repro the UAF in 6.1. Looking more, I think the bug was actual introduced when MSI_COMMON_FLAGS was added with MSI_FLAG_FREE_MSI_DESCS in commit "a737b7d0e721 (PCI/MSI: Add support for per device MSI[X] domains)" And not from the freeing logic mentioned in the Fixes, so the first affected version is 6.2 Thanks, Mostafa > To reproduce the conflict and resubmit, you may use the following commands: > > git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y > git checkout FETCH_HEAD > git cherry-pick -x 9eee5330656bf92f51cb1f09b2dc9f8cf975b3d1 > # <resolve conflicts, build, test, etc.> > git commit -s > git send-email --to '<stable@xxxxxxxxxxxxxxx>' --in-reply-to '2024070120-undergo-stipulate-9aae@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^.. > > Possible dependencies: > > 9eee5330656b ("PCI/MSI: Fix UAF in msi_capability_init") > b12d0bec385b ("PCI/MSI: Move pci_disable_msi() to api.c") > c93fd5266cff ("PCI/MSI: Move mask and unmask helpers to msi.h") > a474d3fbe287 ("PCI/MSI: Get rid of PCI_MSI_IRQ_DOMAIN") > > thanks, > > greg k-h > > ------------------ original commit in Linus's tree ------------------ > > From 9eee5330656bf92f51cb1f09b2dc9f8cf975b3d1 Mon Sep 17 00:00:00 2001 > From: Mostafa Saleh <smostafa@xxxxxxxxxx> > Date: Mon, 24 Jun 2024 20:37:28 +0000 > Subject: [PATCH] PCI/MSI: Fix UAF in msi_capability_init > > KFENCE reports the following UAF: > > BUG: KFENCE: use-after-free read in __pci_enable_msi_range+0x2c0/0x488 > > Use-after-free read at 0x0000000024629571 (in kfence-#12): > __pci_enable_msi_range+0x2c0/0x488 > pci_alloc_irq_vectors_affinity+0xec/0x14c > pci_alloc_irq_vectors+0x18/0x28 > > kfence-#12: 0x0000000008614900-0x00000000e06c228d, size=104, cache=kmalloc-128 > > allocated by task 81 on cpu 7 at 10.808142s: > __kmem_cache_alloc_node+0x1f0/0x2bc > kmalloc_trace+0x44/0x138 > msi_alloc_desc+0x3c/0x9c > msi_domain_insert_msi_desc+0x30/0x78 > msi_setup_msi_desc+0x13c/0x184 > __pci_enable_msi_range+0x258/0x488 > pci_alloc_irq_vectors_affinity+0xec/0x14c > pci_alloc_irq_vectors+0x18/0x28 > > freed by task 81 on cpu 7 at 10.811436s: > msi_domain_free_descs+0xd4/0x10c > msi_domain_free_locked.part.0+0xc0/0x1d8 > msi_domain_alloc_irqs_all_locked+0xb4/0xbc > pci_msi_setup_msi_irqs+0x30/0x4c > __pci_enable_msi_range+0x2a8/0x488 > pci_alloc_irq_vectors_affinity+0xec/0x14c > pci_alloc_irq_vectors+0x18/0x28 > > Descriptor allocation done in: > __pci_enable_msi_range > msi_capability_init > msi_setup_msi_desc > msi_insert_msi_desc > msi_domain_insert_msi_desc > msi_alloc_desc > ... > > Freed in case of failure in __msi_domain_alloc_locked() > __pci_enable_msi_range > msi_capability_init > pci_msi_setup_msi_irqs > msi_domain_alloc_irqs_all_locked > msi_domain_alloc_locked > __msi_domain_alloc_locked => fails > msi_domain_free_locked > ... > > That failure propagates back to pci_msi_setup_msi_irqs() in > msi_capability_init() which accesses the descriptor for unmasking in the > error exit path. > > Cure it by copying the descriptor and using the copy for the error exit path > unmask operation. > > [ tglx: Massaged change log ] > > Fixes: bf6e054e0e3f ("genirq/msi: Provide msi_device_populate/destroy_sysfs()") > Suggested-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Signed-off-by: Mostafa Saleh <smostafa@xxxxxxxxxx> > Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Cc: Bjorn Heelgas <bhelgaas@xxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx > Link: https://lore.kernel.org/r/20240624203729.1094506-1-smostafa@xxxxxxxxxx > > diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c > index c5625dd9bf49..3a45879d85db 100644 > --- a/drivers/pci/msi/msi.c > +++ b/drivers/pci/msi/msi.c > @@ -352,7 +352,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, > struct irq_affinity *affd) > { > struct irq_affinity_desc *masks = NULL; > - struct msi_desc *entry; > + struct msi_desc *entry, desc; > int ret; > > /* Reject multi-MSI early on irq domain enabled architectures */ > @@ -377,6 +377,12 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, > /* All MSIs are unmasked by default; mask them all */ > entry = msi_first_desc(&dev->dev, MSI_DESC_ALL); > pci_msi_mask(entry, msi_multi_mask(entry)); > + /* > + * Copy the MSI descriptor for the error path because > + * pci_msi_setup_msi_irqs() will free it for the hierarchical > + * interrupt domain case. > + */ > + memcpy(&desc, entry, sizeof(desc)); > > /* Configure MSI capability structure */ > ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); > @@ -396,7 +402,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, > goto unlock; > > err: > - pci_msi_unmask(entry, msi_multi_mask(entry)); > + pci_msi_unmask(&desc, msi_multi_mask(&desc)); > pci_free_msi_irqs(dev); > fail: > dev->msi_enabled = 0; >