Re: [PATCH] Athlon Prefetch workaround for 2.6.0test6

From: Jamie Lokier
Date: Mon Sep 29 2003 - 12:08:48 EST


Andi Kleen wrote:
> +/*
> + * Find an segment base in the LDT/GDT.
> + * Don't need to do any boundary checking because the CPU did that already
> + * when the instruction was executed
> + */

I'm not 100% sure, but I see some possible dangerous race conditions.

1. Userspace thread A has a page fault at CS:EIP == 0x000f:0xbffff000.

Simultaneously, userspace thread B calls modify_ldt() to change
the LDT descriptor base to 0x40000000.

The LDT descriptor is changed after A enters the page fault
handler, but before it takes mmap_sem. This can happen on SMP or
on a pre-empt kernel.

__is_prefetch() calls __get_user(0xfffff000), or whatever
address userspace wants to trick it into reading.

Result: unpriveleged userspace causes an MMIO read and crashes
the system, or worse.

2. segment_base sets "desc = (u32 *)&cpu_gdt_table[smp_processor_id()]".

Pre-empt switches CPU.

desc now points to the _old_ CPU, where the GDT for this task is
no longer valid, and that is read in the next few lines.

I think for completeness you should check the segment type and limit
too (because they can be changed, see 1.). These are easier to check
than they look (w.r.t. 16 bit segments etc.): you don't have to decode
the descriptor; just use the "lar" and "lsl" instructions.

If you can't decode the instruction because of transient access
problems, just return as if it was a prefetch, so that the faulting
instruction will be retried, or access permissions will cause the
program to trap in the normal ways.

-- Jamie
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/