You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
sstable: prevent block metadata pointers to garbage
When allocating memory for a new block, we allocate an additional
block.MetadataSize bytes for holding a Go structure containing decoded data
describing the block and maintaining pointers into the block's contents. This
allows us to decode the block structure once when the block is loaded into the
block cache. Readers that find the block in the cache simply cast this 'block
metadata' preamble into the appropriate type.
When a block is not found within the block cache, we: load the block, decode
the block's header and initialize the block's unique metadata. We initialize
the metadata by first casting the allocation's pointer to the appropriate Go
pointer type. Then we decode the block's data, initializing the metadata struct
accordingly. In the interim between the pointer cast and the initialization,
the contents of the metadata are undefined.
The per-block metadata types typically contain pointer fields. Once
initialized, these pointers point into the block's data, all part of the same
CGo manual allocation. If the Go garbage collector examines this Go struct
before it's been fully initialized, it may observe arbitrary garbage within the
pointer fields. If one of these values looks like a pointer to a Go-allocated
part of the address space, the Go garbage collector crashes the process. It's a
little unclear the circumstances in which the Go garbage collector will examine
these metadata structs that exist within CGo memory, but experimentally it
appears to be the case.
This commit fixes the issue by always zeroing block metadata memory before
casting it into the appropriate metadata struct. Additionally, it solves an
analogous problem during de-allocation by nil-ing metadata pointers into blocks
before we release the blocks back to the cache or buffer pool. Together, these
changes ensure that whenever we have a pointer to a block metadata Go
structure, the structure's backing memory is either zeroed or the result of
initialization based on decoding the block.
Informs cockroachdb/cockroach#149955.
Informs cockroachdb/cockroach#150216.
Co-authored-by: Radu Berinde <radu@cockroachlabs.com>
0 commit comments