Redzone: 0xfeedface
Note the pattern 0xfeedface
in the buffer shown in the previous section. This pattern is known as the redzone indicator. This pattern enables the allocator (and a programmer debugging a problem) to determine whether the boundaries of a buffer have been violated. Following the redzone is some additional information. The content of that data depends on other factors (see Memory Allocation Logging). The redzone and its suffix are collectively called the buftag region. The following figure summarizes this information.
Redzone Indicator
![Graphic described by context. Graphic described by context.](img/redzone-fig1.jpg)
The buftag is appended to each buffer in a cache when any of the KMF_AUDIT
, KMF_DEADBEEF
, or KMF_REDZONE
flags is set in that buffer's cache. The content of the buftag depends on whether KMF_AUDIT
is set.
Decomposing the memory region presented above into distinct buffers is now simple:
0x70a9add8: deadbeef deadbeef \ 0x70a9ade0: deadbeef deadbeef +- User Data (free) 0x70a9ade8: deadbeef deadbeef / 0x70a9adf0: feedface feedface -- REDZONE 0x70a9adf8: 70ae3260 8440c68e -- Debugging Data 0x70a9ae00: 5 4ef83 \ 0x70a9ae08: 0 0 +- User Data (allocated) 0x70a9ae10: 1 bbddcafe / 0x70a9ae18: feedface 139d -- REDZONE 0x70a9ae20: 70ae3200 d1befaed -- Debugging Data 0x70a9ae28: deadbeef deadbeef \ 0x70a9ae30: deadbeef deadbeef +- User Data (free) 0x70a9ae38: deadbeef deadbeef / 0x70a9ae40: feedface feedface -- REDZONE 0x70a9ae48: 70ae31a0 8440c54e -- Debugging Data
The buffers at 0x70a9add8
and 0x70a9ae28
are filled with 0xdeadbeefdeadbeef
, which shows that these buffers are free. The buffer redzones are filled with 0xfeedfacefeedface
, which indicates they are untouched (no buffer overrun has occurred).
-
0xbaddcafe
-
Buffer is allocated but uninitialized (see Uninitialized Data: 0xbaddcafe).
-
0xdeadbeef
-
Buffer is free.
-
0xfeedface
-
Buffer limits were respected (no overflow).
In the allocated buffer beginning at 0x70a9ae00
, the situation is different. Recall from Allocator Basics that there are two allocation types:
-
The client requested memory using
kmem_cache_alloc
(9F), in which case the size of the requested buffer is equal to the bufsize of the cache. -
The client requested memory using
kmem_alloc
(9F), in which case the size of the requested buffer is less than or equal to the bufsize of the cache. For example, a request for 20 bytes will be fulfilled from thekmem_alloc_24
cache. The allocator enforces the buffer boundary by placing a marker, the redzone byte, immediately following the client data:0x70a9ae00: 5 4ef83 \ 0x70a9ae08: 0 0 +- User Data (allocated) 0x70a9ae10: 1 bbddcafe / 0x70a9ae18: feedface 139d -- REDZONE 0x70a9ae20: 70ae3200 d1befaed -- Debugging Data
The 0xfeedface
value at 0x70a9ae18
is followed by a 32-bit word containing what seems to be a random value. This number is actually an encoded representation of the size of the buffer. To decode this number and find the size of the allocated buffer, use the formula:
size = redzone_value / 251
So, in this example,
size = 0x139d / 251 = 20 bytes.
This indicates that the buffer requested was of size 20 bytes. The allocator performs this decoding operation and finds that the redzone byte should be at offset 20. The redzone byte is the hex pattern 0xbb
, which is present at 0x729084e4 (0x729084d0 + 0t20)
as expected.
Sample kmem_alloc(9F)
Buffer
![Graphic illustrates a sample kmem_alloc buffer. The redzone byte, uninitialized data, and debugging data are marked. Graphic illustrates a sample kmem_alloc buffer. The redzone byte, uninitialized data, and debugging data are marked.](img/redzone-fig2.jpg)
The following figure shows the general form of this memory layout.
Redzone Byte
![Graphic shows the redzone byte being written after the end of the user data region. The redzone byte is determined by decoding the index. Graphic shows the redzone byte being written after the end of the user data region. The redzone byte is determined by decoding the index.](img/redzone-fig3.jpg)
If the allocation size is the same as the bufsize of the cache, the redzone byte overwrites the first byte of the redzone itself, as shown in the following figure.
Redzone Byte at the Beginning of the Redzone
![Graphic illustrates the overwriting of redzone bye at the beginning of the redzone Graphic illustrates the overwriting of redzone bye at the beginning of the redzone](img/redzone-fig4.jpg)
This overwriting results in the first 32-bit word of the redzone being 0xbbedface
, or 0xfeedfabb
depending on the endianness of the hardware on which the system is running.
Note:
Why is the allocation size encoded this way? To encode the size, the allocator uses the formula (251 * size + 1). When the size decode occurs, the integer division discards the remainder of '+1'. However, the addition of 1 is valuable because the allocator can check whether the size is valid by testing whether (size % 251 == 1). In this way, the allocator defends against corruption of the redzone byte index.