DTrace panic while probing syscall::open (and possibly many
others)
Thomas Backman
serenity at exscape.org
Fri Jun 19 17:33:09 UTC 2009
On Jun 19, 2009, at 07:01 PM, Alan Cox wrote:
> Andriy Gapon wrote:
>> on 18/06/2009 14:42 Thomas Backman said the following:
>>
>>> On Jun 18, 2009, at 12:55 PM, Andriy Gapon wrote:
>>>
>>>
>>>> on 18/06/2009 12:43 Thomas Backman said the following:
>>>>
>>>>> at dtrace_isa.c:527
>>>>> #14 0xffffffff816b31fc in dtrace_copyinstr (uaddr=34365163021,
>>>>> kaddr=18446743524025463312, size=256, flags=0xffffffff8146e0c0)
>>>>> at dtrace_isa.c:558
>>>>>
>>>> kaddr=18446743524025463312 == FFFFFF8004467210
>>>> I think kernelbase on amd64 is 0xFFFFFFFF80000000.
>>>> FFFFFF8004467210 kaddr
>>>> is smaller than
>>>> FFFFFFFF80000000 kernelbase
>>>>
>>>> The numbers do look suspiciously similar, so I am not sure if you
>>>> are
>>>> seeing a
>>>> race or a real bug somewhere.
>>>> --
>>>> Andriy Gapon
>>>>
>>> Hmmm...
>>> Looking around a bit for these numbers, I found, in
>>> /sys/amd64/include/vmparam.h:
>>>
>>> /*
>>> * Virtual addresses of things. Derived from the page directory and
>>> * page table indexes from pmap.h for precision.
>>> *
>>> * 0x0000000000000000 - 0x00007fffffffffff user map
>>> * 0x0000800000000000 - 0xffff7fffffffffff does not exist (hole)
>>> * 0xffff800000000000 - 0xffff804020100fff recursive page table
>>> (512GB
>>> slot)
>>> * 0xffff804020101000 - 0xfffffeffffffffff unused
>>> * 0xffffff0000000000 - 0xffffff7fffffffff 512GB direct map
>>> mappings
>>> * 0xffffff8000000000 - 0xffffffffffffffff 512GB kernel map
>>> *
>>> * Within the kernel map:
>>> *
>>> * 0xffffffff80000000 KERNBASE
>>> */
>>>
>>> So, kaddr is inside the "kernel map", but not KERNBASE. What this
>>> means,
>>> I have no clue whatsoever. (I'm not a kernel developer and I don't
>>> know
>>> too much about (virtual) memory either!)
>>>
>>
>> Thomas,
>>
>> I think that you were correct that one needs to be somewhat of a VM
>> expert here.
>> It seems that amd64 is the only[?] platform where KERNBASE !=
>> VM_MIN_KERNEL_ADDRESS (0xffffffff80000000 and 0xffffff8000000000
>> correspondingly).
>> That makes the assert in sys/cddl/dev/dtrace/amd64/dtrace_isa.c
>> bogus in my opinion:
>> static int
>> dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
>> {
>> ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
>>
>> If the purpose of the assert is to ensure that [kaddr:kaddr+size)
>> is within kernel
>> memory, then it should use VM_MIN_KERNEL_ADDRESS instead of
>> KERNBASE. Or maybe
>> even use something like the macro in sys/amd64/include/stack.h:
>> #define INKERNEL(va) (((va) >= DMAP_MIN_ADDRESS && (va) <
>> DMAP_MAX_ADDRESS) \
>> || ((va) >= VM_MIN_KERNEL_ADDRESS && (va) <
>> VM_MAX_KERNEL_ADDRESS))
>>
>>
>
> Yes. Your analysis is correct.
>
> Alan
Very interesting.
I replaced the ASSERT line temporarily:
--- ../src_r194478-UNTOUCHED/sys/cddl/dev/dtrace/amd64/
dtrace_isa.c 2009-06-19 13:10:05.661079736 +0200
+++ sys/cddl/dev/dtrace/amd64/dtrace_isa.c 2009-06-19
19:24:42.362125129 +0200
@@ -524,7 +524,7 @@
static int
dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
{
- ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
+ ASSERT(kaddr >= 0xffffff8000000000 && kaddr + size >= kaddr);
if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
... and it works! I obviously haven't tried it for extended periods or
anything, but at least it's working so far.
Should the ASSERT simply use this (as a #define somewhere) or the
INKERNEL macro, though?
Regards,
Thomas
More information about the freebsd-current
mailing list