-
paulf
is it me or is gdb in illumos 22.11 hopelessly borked?
-
paulf
whenever I debug a file it thinks that one of the headers is the C source file
-
paulf
and it gets the path wrong as well
-
paulf
if I do "set substitute-path borked-bogus-path/header.h source.c" then it is usable
-
tsoome
which illumos? oi or omnios or something else?:)
-
paulf
OpenIndiana 22.11 I think
-
tsoome
run pkg update -nv and see if there is update for gdb.
-
paulf
going straight to pkg update
-
paulf
-
paulf
it keeps on multiplying by 2 until the alignment is greater than MINSIZE+WORDSIZE (6 words or 48 bytes)
-
paulf
So an alignment if 12 gets multiplied up to 96 but an alignment of 20 only gets multiplied up to 80
-
paulf
glibc does something like
-
paulf
while (0 != (alignment & (alignment - 1))) alignment++;
-
paulf
to bump up the alignment to the next power of 2
-
paulf
and gdb is now behaving itself
-
tsoome
ou, so it was failing with memalign ?
-
paulf
no it just seems very strange
-
paulf
maybe I'm misreading the code
-
paulf
-
paulf
Trying to fix handling of the various aligned alloc functions in Valgrind
-
tsoome
did you check libumem?
-
paulf
:-) no
-
paulf
can't do everything
-
alanc
the memalign() man page does state that the alignment must be a power of two, so alignments of 12 or 20 would be invalid
-
alanc
though the check it does for _misaligned() doesn't properly catch that
-
alanc
should probably be calling ISP2() instead
-
paulf
that sounds more consistent with other platforms (which aren't particularly consistent)
-
richlowe
it'd be good to get a bug filed, about the memalign thing above.
-
richlowe
if paulf is still here, or someone else is up to summarize it.
-
richlowe
paulf: I have used gdb in openindiana at times, I don't know if it's hopelessly broken but it's shockingly old.
-
richlowe
maybe that's something toasterson and the OI people could fix pretty easily
-
paulf
gdb was OK after pkg update
-
paulf
memalign might be nice but it's a deprecated interface
-
paulf
posix_memalign is better
-
paulf
C also has aligned alloc but the alignment depends on the implementation so unportable
-
toasterson
richlowe: We are not thaaaat old on gsb. we are at 12.1 we could update to 13.1 though.
-
richlowe
ah, it must have been bumped since I updated
-
toasterson
Yeah there is a 2023 Copyright in there. Must have been shortly before 13 released in January
-
tsoome
just to be sure, kmem_cache_alloc(cache, KM_PUSHPAGE) can return NULL?
-
ryao
Good question. I thought I knew the answer, but changed my opinion recently. Let me double check to be sure.
-
tsoome
it definitely returns NULL if kmem_slab_alloc() fails.
-
tsoome
so, yes it can.
-
tsoome
now, can it return garbage....
-
ryao
tsoome: It is not supposed to return NULL, ever. NULL is supposed to only be allowed when the KM_NOSLEEP bit is set in flags.
-
tsoome
-
ryao
tsoome: That breaks many assumptions in ZFS...
-
ryao
ZFS cannot handle kmem_cache_alloc() returning NULL unless it specifies KM_NOSLEEP.
-
ryao
I thought it was like that all over the illumos kernel.
-
tsoome
ya, well, I have abd with abd_size = 0xe000, abd_chunk_size = 0x1000 (that should make 62 chunks)
-
tsoome
> 0xfffffe2d0ce11970::print abd_t abd_u.abd_scatter.abd_chunks[3]
-
tsoome
abd_u.abd_scatter.abd_chunks[3] = 0xd0f313429003041
-
tsoome
not a pointer
-
tsoome
> 0xfffffe2d0ce11970::print abd_t abd_u.abd_scatter.abd_chunks[4]
-
tsoome
abd_u.abd_scatter.abd_chunks[4] = 0
-
tsoome
so, the natural question is, was the chunk array corrupted, or allocations did fail
-
ryao
tsoome: Did you look at the subsequent array values?
-
tsoome
5 and 6 seem valid, 7 is not a pointer again
-
tsoome
10 is again not a pointer
-
igork1
tsoome: yes, it can return garbage and need cleanup it before using
-
igork
ryao: ZFS is using another implementation on Linux and BSD - they have wrappers to own
-
ryao
tsoome: I have never seen your issue until you told me about it, but to be honest, I have been saying that quite often to people recently.
-
tsoome
> abd_chunk_cache::print kmem_cache_t cache_alloc_fail
-
tsoome
cache_alloc_fail = 0
-
tsoome
but that does only mean, we did not reach the code to increment it...
-
ryao
igork: I am aware that we did not port the SLAB allocator from illumos, but the assumptions in the ZFS code are the same. We inherited these assumptions when it was ported from OpenSolaris in the first place. Even the kmflags bits are the same.
-
igork
ryao: kmem* present only on illumos and was ported to others
-
ryao
I checked the headers for both OpenZFS and illumos-gate before saying that you are supposed to need to pass KM_NOSLEEP for it to return NULL. That was the understanding of it that was used to develop ZFS.
-
igork
and was ported as saving on interfaces and logic
-
ryao
My understanding is that this idea predates both the Linux port and myself as a contributor.
-
igork
ryao: you try to speak about kmem_alloc(), but not about kmem_cache_alloc() - they are different
-
igork
ryao: i'm working with OpenZFS ports to dilos a long time :) kmem* and threads are different between platforms
-
ryao
igork: If my spot check is correct, you appear to be right. Using the same semantics for kmem_cache_alloc() would seem to be a mistake made when porting things.
-
ryao
tsoome: I guess the answer is to switch to kmem_alloc() there.
-
igork
ryao: it is not mistake, probably some platform specific things can be different
-
igork
ryao: no need to switch, we can use kmem_cache_* for abd on illumos and i did it on dilos
-
igork
but it was a long race with updates from OpenZFS with many panics :)
-
igork
as reference you can try take a look freebsd updates for abd
-
tsoome
cache_dump.kd_alloc_fails = 0xa840a05b
-
tsoome
so this one definitely has seen allocation failures
-
ryao
igork: The code expects kmem_alloc(..., KM_PUSHPAGE) semantics there. Also, if the illumos kmem_cache_alloc() is really passing non-pointers, then I am not sure how it could be used correctly...
-
igork
kmem_alloc(..., KM_PUSHPAGE) have no KM_PUSHPAGE
-
ryao
igork: Then it becomes KM_SLEEP.
-
igork
ryao: illumos version was ported to another platforms with others dependences to platform specific
-
igork
it is why linux and freebsd have some different *_os.c files with different inmplementations
-
igork
i know openzfs code :)
-
tsoome
hm, cache_dump.kd_alloc_fails should be incremented when constructor fails, but this cache has cache_constructor = 0.... interesting.
-
tsoome
well, I'm not sure if we can get garbage from kmem_cache_alloc(), so it still can be some sort of memory corruption.
-
tsoome
but returning NULL there is possibility we have to pay attention...
-
tsoome
eh, abd_alloc_struct() does abd_t *abd = kmem_alloc(size, KM_PUSHPAGE); so, while attempting to use reserved memory, it too can fail.
-
ryao
igork: In the OpenZFS tree, we have used kmem_cache_alloc() in this way in many places, including platform independent places like ddt_alloc(). :/
-
ryao
tsoome: That was my original understanding of KM_PUSHPAGE, but there is a comment in the code that suggests it is supposed to be otherwise: #define KM_PUSHPAGE 0x0004 /* can block for memory; may use reserve */
-
tsoome
err, I am stupid. KM_PUSHPAGE does leave bit 0 unset, so KM_SLEEP is present there as "flag"
-
tsoome
as KM_SLEEP is 0
-
tsoome
it is good question, if it is tested properly:D
-
ryao
KM_NOSLEEP is 1. I thought the design intent was that it would SLEEP unless told otherwise.
-
ryao
s/SLEEP/be KM_SLEEP/
-
tsoome
but kmem_alloc is also using kmem_cache_alloc(). fun.
-
rzezeski
tsoome: I don't think that line proves what you think it does
-
rzezeski
it calls into vmem
-
rzezeski
and passes the flags
-
rzezeski
I highly doubt KM_SLEEP is broken
-
rzezeski
and yea ryao, that is the default
-
tsoome
no, I do not think the KM_SLEEP is broken.
-
tsoome
but as much as I can read, there is possibility, we do get NULL from kmem_cache_alloc even with flags bit 0 unset.
-
rzezeski
which would mean KM_SLEEP is broken
-
tsoome
well.... yes:D
-
ryao
au_get_buff(), kcf_submit_request() and others will be very unhappy if kmem_cache_alloc() returns NULL with KM_SLEEP.
-
ryao
They dereference the returned pointer without a NULL check.
-
ryao
See the second kmem_cache_alloc() if you look at au_get_buff().
-
rzezeski
tsoome: and if you look at kmem_slab_create() it calls into vmem_alloc(), which honors the VM_SLEEP flag.
-
tsoome
-
ryao
-
ryao
It is not my imagination. Plenty of code in the kernel assumes that without KM_NOSLEEP, you cannot get a NULL return value. The fact that it can means there is either a few bugs, or *many* bugs, depending on how you count.
-
ryao
s/is either/are either/
-
rzezeski
tsoome: ah so that is a different line and I think a different semantic, and yes, I think that means if the constructor fails, then you get a NULL. It still honored the semantic of KM_SLEEP, but if the constructor didn't pass you can't return the object as it could be bad.
-
rzezeski
tsoome: what is the cache in question?
-
tsoome
abd_chunk_cache. that one does not have constructor.
-
tsoome
specifically, one abd record has corrupted chunk array.
-
ryao
rzezeski: I assume he is talking about abd_alloc_chunk().
-
ryao
I was scrolled up when I hit enter.
-
tsoome
yes
-
tsoome
corrupted in sense that some pointers have clearly non-pointer values, some have 0
-
rzezeski
yea, so in that case it can't even reach the second line you linked, and my read of kmem/vmem if KM/VM_SLEEP is honored just fine in kmem_cache_alloc()
-
ryao
The declaration for abd_alloc_chunk() is not valid C99 if I recall correctly. That is a K&R-ism.
-
tsoome
yes, we still have many of those...
-
rzezeski
tsoome: that could be use after free
-
tsoome
hm.
-
tsoome
good pint.
-
tsoome
point*
-
ryao
Newer compilers are beginning to complain about that sinc ethey are becoming strict. They want you to write (void).
-
tsoome
yep. except, we do not yet support that new ones:D
-
ryao
rzezeski: Use after free was my thought until igork said that you can get non-pointers from kmem_cache_alloc(). Then I became very confused.
-
ryao
I am still confused by that.
-
tsoome
well, need to get kmem to fill things with patterns and see if this panic will be repeated:D
-
rzezeski
tsoome: so you have a pointer to the cache object, maybe of a `<object addr>::kgrep |::whatis`
-
rzezeski
I think that's what I usually do when dealing with UAF (been a while)
-
tsoome
that seems to take its time:)
-
tsoome
hm, that output does not tell too much to me.
-
tsoome
no obvious hits about being freed.
-
rzezeski
well when I run something like that I'm looking to see if the ojbect is referenced by multiple different threads
-
rzezeski
and part of debugging this requires knowing how these objects are used, because it might be valid for multiple threads to have a pointer to it
-
rzezeski
but typically I can find that some thread has a pointer when it shouldn't, I think I also usually use some of the kmem mdb commands related to this as well, but I can't remember off the top of my head
-
tsoome
hrm. now this is weird. first pointer in chunklist array is perfectly valid. second one is freed from abd_chunk. the abd itself is note yet freed.
-
richlowe
rzezeski: ::kgrep?
-
richlowe
as far as finding things that might be pointers to a doodad
-
tsoome
nah, I need to dig it with fresh head.
-
rzezeski
richlowe: yea that's what I showed above, but I think I typically also like to use that with things like the audit log or whatever, though IIRC that requires kmem flag adjustment
-
ryao
tsoome: You said that some of the values were NULL. I just spotted this in abd_alloc_chunk(): ASSERT3P(c, !=, NULL);
-
ryao
tsoome: Unless you built without assertions, the allocator could not have returned NULL there. Use after free seems more likely, although that is its own headache.
-
tsoome
ASSERT's need debug kernel, yep.
-
ryao
tsoome: Did you reproduce this without a debug kernel or were you lucky and hit it without looking for it?
-
tsoome
its the dump from first panic, got no second case (yet)
-
tsoome
the abd in question is supposed to be in arc and to receive data after write completion.
-
tsoome
arc_write_ready -> abd_copy_off -> abd_iterate_func2 -> abd_copy_off_cb -> bcopy_ck_size -> GPF :)
-
ryao
tsoome: Does that mean you were just lucky/unlucky and hit this when not trying to find it?
-
tsoome
yep.