Skip to contentSkip to conversation

Crash in intel_iommu_assign_device

DISCUSSION Jan Kiszka 2 participants 3 messages Nov 1, 2010 – Nov 2, 2010 KVM

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

Hi Sheng,

I'm not claiming to understand the details, but this looks like use (dereference of pte via dma_pte_addr) after release (free_pgtable_page of dmar_domain->pgd aka pte) to me:

static int intel_iommu_attach_device(struct iommu_domain *domain,
struct device *dev)

{
	[...]
		pte = dmar_domain->pgd;
		if (dma_pte_present(pte)) {
			free_pgtable_page(dmar_domain->pgd);
			dmar_domain->pgd = (struct dma_pte *)
				phys_to_virt(dma_pte_addr(pte));
		}

At least it crashes here right on pte->val access. Swap both lines?

Jan

#1 lore raw
Quoted 17 lines · On Monday 01 November 2010 19:41:21 Jan Kiszka wrote:

Hi Sheng,

I'm not claiming to understand the details, but this looks like use (dereference of pte via dma_pte_addr) after release (free_pgtable_page of dmar_domain->pgd aka pte) to me:

static int intel_iommu_attach_device(struct iommu_domain *domain,
struct device *dev)

{
	[...]
		pte = dmar_domain->pgd;
		if (dma_pte_present(pte)) {
			free_pgtable_page(dmar_domain->pgd);
			dmar_domain->pgd = (struct dma_pte *)
				phys_to_virt(dma_pte_addr(pte));
		}
Quoted 1 line

At least it crashes here right on pte->val access. Swap both lines?

I think code is right.

The comment above indicate the case: the code want to decrease the level of page table. Mostly it is a 4 level page table, and the code would turn it into 3 levels pagetable. What the code did is just get the first entry of the old pagetable level 4, then free the level 4 pagetable's page, and make the pagetable to a level 3 pagetable.

Seems it make no sense to swap the lines...

--
regards
Yang, Sheng

Quoted 2 lines

Jan

author
#2 lore raw
Quoted 22 lines · Sheng Yang
Quoted 17 lines · On Monday 01 November 2010 19:41:21 Jan Kiszka wrote:

Hi Sheng,

I'm not claiming to understand the details, but this looks like use (dereference of pte via dma_pte_addr) after release (free_pgtable_page of dmar_domain->pgd aka pte) to me:

static int intel_iommu_attach_device(struct iommu_domain *domain,
struct device *dev)

{
	[...]
		pte = dmar_domain->pgd;
		if (dma_pte_present(pte)) {
			free_pgtable_page(dmar_domain->pgd);
			dmar_domain->pgd = (struct dma_pte *)
				phys_to_virt(dma_pte_addr(pte));
		}
Quoted 1 line

At least it crashes here right on pte->val access. Swap both lines?

I think code is right.

Quoted 7 lines

The comment above indicate the case: the code want to decrease the level of page table. Mostly it is a 4 level page table, and the code would turn it into 3 levels pagetable. What the code did is just get the first entry of the old pagetable level 4, then free the level 4 pagetable's page, and make the pagetable to a level 3 pagetable.

Seems it make no sense to swap the lines...

It fixes the crash here, and I'm convinced the current code is wrong. See the patch I've just sent out.

Jan