zephyr/include
Nicolas Pitre 465b2cf31b mempool: fix corruption of the free block bitmap and beyond
In z_sys_mem_pool_block_alloc() the size of the first level block
allocation is rounded up to the next 4-bite boundary. This means one
or more of the trailing blocks could overlap the free block bitmap.

Let's consider this code from kernel.h:

  #define K_MEM_POOL_DEFINE(name, minsz, maxsz, nmax, align) \
       char __aligned(align) _mpool_buf_##name[_ALIGN4(maxsz * nmax) \
                              + _MPOOL_BITS_SIZE(maxsz, minsz, nmax)]; \

The static pool allocation rounds up the product of maxsz and nmax not
size of individual blocks. If we have, say maxsz = 10 and nmax = 20,
the result of _ALIGN4(10 * 20) is 200. That's the offset at which the
free block bitmap will be located.

However, because z_sys_mem_pool_block_alloc() does this:

        lsizes[0] = _ALIGN4(p->max_sz);

Individual level 0 blocks will have a size of 12 not 10. That means
the 17th block will extend up to offset 204, 18th block up to 216, 19th
block to 228, and 20th block to 240. So 4 out of the 20 blocks are
overflowing the static pool area and 3 of them are even located
completely outside of it.

In this example, we have only 20 blocks that can't be split so there is
no extra free block bitmap allocation beyond the bitmap embedded in the
sys_mem_pool_lvl structure. This means that memory corruption will
happen in whatever data is located alongside the _mpool_buf_##name
array. But even with, say, 40 blocks, or larger blocks, the extra bitmap
size would be small compared to the extent of the overflow, and it would
get corrupted too of course.

And the data corruption will happen even without allocating any memory
since z_sys_mem_pool_base_init() stores free_list pointer nodes into
those blocks, which in turn may get corrupted if that other data is
later modified instead.

Fixing this issue is simple: rounding on the static pool allocation is
"misparenthesized". Let's turn

	_ALIGN4(maxsz * nmax)

into

	_ALIGN4(maxsz) * nmax

But that's not sufficient.

In z_sys_mem_pool_base_init() we have:

        size_t buflen = p->n_max * p->max_sz, sz = p->max_sz;
        u32_t *bits = (u32_t *)((u8_t *)p->buf + buflen);

Considering the same parameters as above, here we're locating the extra
free block bitmap at offset `buflen` which is 20 * 10 = 200, again below
the reach of the last 4 memory blocks. If the number of blocks gets past
the size of the embedded bitmap, it will overlap memory blocks.

Also, the block_ptr() call used here to initialize the free block linked
list uses unrounded p->max_sz, meaning that it is initially not locating
dlist nodes within the same block boundaries as what is expected from
z_sys_mem_pool_block_alloc(). This opens the possibility for allocated
adjacent blocks to overwrite dlist nodes, leading to random crashes in
the future.

So a complete fix must round up p->max_sz here too.

Given that runtime usage of max_sz should always be rounded up, it is
then preferable to round it up once at compile time instead and avoid
further mistakes of that sort. The existing _ALIGN4() usage on p->max_sz
at run time are then redundant.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2019-06-24 12:10:09 -07:00
..
app_memory kernel: app_memdomain: remove unused defines 2019-06-17 10:00:22 -07:00
arch arch: arm: introduce macro to describe the privilege stack alignment 2019-06-24 10:16:57 -07:00
audio all: Add 'U' suffix when using unsigned variables 2019-03-28 17:15:58 -05:00
bluetooth docs: fix misspelling across the tree 2019-06-19 15:34:13 -05:00
cmsis_rtos_v1 all: Add 'U' suffix when using unsigned variables 2019-03-28 17:15:58 -05:00
cmsis_rtos_v2
crypto all: Add 'U' suffix when using unsigned variables 2019-03-28 17:15:58 -05:00
debug
dfu dfu: mcuboot: Added defines for upgrade request modes 2019-05-21 15:31:00 -04:00
display arch/x86: drivers/display: add framebuffer driver w/ multiboot support 2019-06-06 10:47:29 -07:00
drivers include/drivers/system_timer.h: Clean up docs 2019-06-17 20:32:50 -04:00
dt-bindings dts: bindings: usb: Add enum to maximum-speed property 2019-05-17 09:53:20 -05:00
fs
linker arch: arm: expose start/end limits of the thread priv stack section 2019-06-24 10:16:57 -07:00
logging log facility: make its records 64-bit compatible 2019-06-24 08:58:52 +02:00
mgmt
misc mempool: fix corruption of the free block bitmap and beyond 2019-06-24 12:10:09 -07:00
net net: mqtt: add mqtt_readall_publish_payload() 2019-06-20 13:06:08 +03:00
nvs fs/nvs: Improve init speed and remove fs->locked 2019-02-21 09:32:52 -05:00
posix PTHREAD_MUTEX_DEFINE(): don't store into the _k_mutex section 2019-06-04 09:24:08 -04:00
random
settings subsys/settings: change processing to const char 2019-06-18 17:57:08 +02:00
shell doc: fix doxygen comments with embedded reST 2019-06-10 18:16:12 -04:00
toolchain docs: fix misspelling across the tree 2019-06-19 15:34:13 -05:00
usb usb: enforce byte alignment on USB records 2019-06-17 16:41:43 -04:00
zephyr
adc.h drivers: adc: add API to support calibration 2019-05-30 17:18:17 -04:00
aio_comparator.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
atomic.h include: Make statements evaluate boolean expressions 2019-03-26 14:31:29 -04:00
base64.h
cache.h
can.h drivers: can: Add loopback driver 2019-05-12 16:54:49 -04:00
clock_control.h C++: Fix compilation error "invalid conversion" 2019-05-03 14:27:07 -04:00
console.h console: deprecate console_register_line_input() 2019-03-26 12:48:38 -05:00
counter.h drivers: counter: Add flags to counter_config_info structure 2019-05-27 09:18:34 -04:00
crc.h
device.h linker generated list: explicit alignment on data definitions 2019-06-06 14:21:32 -07:00
disk_access.h
display.h
dma.h api: dma: add api to retrieve runtime status 2019-05-07 22:14:36 -04:00
entropy.h entropy: fix C++ compiler warnings 2019-05-21 08:26:12 -04:00
exc_handle.h
fcb.h
flash_map.h doc: Fix typos in flashmap.h 2019-05-28 12:27:43 -04:00
flash.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
fs.h fs: Added API to read mount point 2019-06-11 08:31:54 -04:00
generated_dts_board.h
gna.h
gpio.h include: Make statements evaluate boolean expressions 2019-03-26 14:31:29 -04:00
hwinfo.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
i2c.h all: Add 'U' suffix when using unsigned variables 2019-03-28 17:15:58 -05:00
i2s.h include: Use macro BIT for shift operations 2019-03-26 14:31:29 -04:00
init.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
ipm.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
irq_nextlevel.h
irq_offload.h
irq.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
json.h docs: fix misspelling across the tree 2019-06-19 15:34:13 -05:00
kernel_includes.h
kernel_version.h
kernel.h mempool: fix corruption of the free block bitmap and beyond 2019-06-24 12:10:09 -07:00
led_strip.h
led.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
pinmux.h C++: Fix compilation error "invalid conversion" 2019-05-03 14:27:07 -04:00
power.h all: Add 'U' suffix when using unsigned variables 2019-03-28 17:15:58 -05:00
ptp_clock.h
pwm.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
ring_buffer.h ring_buffer: Add functions for getting capacity and reseting 2019-05-30 09:44:03 -04:00
rtc.h all: Add 'U' suffix when using unsigned variables 2019-03-28 17:15:58 -05:00
sched_priq.h docs: fix misspelling across the tree 2019-06-19 15:34:13 -05:00
sensor.h include: added new sensor channel SENSOR_CHAN_GAS_RES 2019-05-31 10:27:13 -05:00
shared_irq.h
spi.h all: Update reserved function names 2019-03-11 13:48:42 -04:00
spinlock.h thread_cpu: make it 64-bit compatible 2019-05-30 09:42:23 -04:00
stats.h stats: changed API to use zephyr types 2019-05-01 10:33:17 -04:00
sw_isr_table.h include: Use macro BIT for shift operations 2019-03-26 14:31:29 -04:00
sys_clock.h kernel: timeout: add syscall for runtime clk freq 2019-05-22 23:33:55 +02:00
sys_io.h misc: memory address type conversions 2019-06-03 21:14:57 -04:00
syscall.h syscall: Fix comment 2019-04-12 17:59:25 -04:00
toolchain.h toolchain: Define a HAS_BUILTIN(x) macro in toolchain.h. 2019-05-14 19:53:30 -05:00
tracing.h tracing: Fix checks of Kconfig options 2019-05-17 15:46:18 -07:00
tty.h
uart.h include/uart.h: Clarify async receive event length 2019-05-27 09:23:39 -04:00
updatehub.h lib: updatehub: Add UpdateHub.io support 2019-06-05 00:20:37 +02:00
watchdog.h include: Removing legacy left-overs in wdt.h API header 2019-06-17 16:45:27 -04:00
zephyr.h