From 7502f47afaf537bbb67050b17ea095bb3976bf91 Mon Sep 17 00:00:00 2001 From: Francis Deslauriers Date: Tue, 16 Oct 2018 15:23:22 -0400 Subject: [PATCH] Fix: implicit declarations caused by buffer size checks. Issue ===== Three kernel functions used in the following commit are unavailable on some supported kernels: commit 1f0ab1eb0409d23de5f67cc588c3ea4cee4d10e0 Prevent allocation of buffers if exceeding available memory * si_mem_available() was added in kernel 4.6 with commit d02bd27. * {set, clear}_current_oom_origin() were added in kernel 3.8 with commit: e1e12d2f Solution ======== Add wrappers around these functions such that older kernels will build with these functions defined as NOP or trivial return value. wrapper_check_enough_free_pages() uses the si_mem_available() kernel function to compute if the number pages requested passed as parameter is smaller than the number of pages available on the machine. If the si_mem_available() kernel function is unavailable, we always return true. wrapper_set_current_oom_origin() function wraps the set_current_oom_origin() kernel function when it is available. If set_current_oom_origin() is unavailable the wrapper is empty. wrapper_clear_current_oom_origin() function wraps the clear_current_oom_origin() kernel function when it is available. If clear_current_oom_origin() is unavailable the wrapper is empty. Drawbacks ========= None. Signed-off-by: Francis Deslauriers Signed-off-by: Mathieu Desnoyers --- lib/ringbuffer/ring_buffer_backend.c | 18 +++---- wrapper/mm.h | 70 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 wrapper/mm.h diff --git a/lib/ringbuffer/ring_buffer_backend.c b/lib/ringbuffer/ring_buffer_backend.c index 8207f764..d4bec25f 100644 --- a/lib/ringbuffer/ring_buffer_backend.c +++ b/lib/ringbuffer/ring_buffer_backend.c @@ -12,11 +12,11 @@ #include #include #include -#include #include #include #include +#include #include /* for wrapper_vmalloc_sync_all() */ #include #include @@ -46,11 +46,13 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config num_pages = size >> PAGE_SHIFT; /* - * Verify that the number of pages requested for that buffer is smaller - * than the number of available pages on the system. si_mem_available() - * returns an _estimate_ of the number of available pages. + * Verify that there is enough free pages available on the system for + * the current allocation request. + * wrapper_check_enough_free_pages uses si_mem_available() if available + * and returns if there should be enough free pages based on the + * current estimate. */ - if (num_pages > si_mem_available()) + if (!wrapper_check_enough_free_pages(num_pages)) goto not_enough_pages; /* @@ -59,7 +61,7 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config * end up running out of memory because of this buffer allocation, we * want to kill the offending app first. */ - set_current_oom_origin(); + wrapper_set_current_oom_origin(); num_pages_per_subbuf = num_pages >> get_count_order(num_subbuf); subbuf_size = chanb->subbuf_size; @@ -155,7 +157,7 @@ int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config * will not fault. */ wrapper_vmalloc_sync_all(); - clear_current_oom_origin(); + wrapper_clear_current_oom_origin(); vfree(pages); return 0; @@ -172,7 +174,7 @@ depopulate: array_error: vfree(pages); pages_error: - clear_current_oom_origin(); + wrapper_clear_current_oom_origin(); not_enough_pages: return -ENOMEM; } diff --git a/wrapper/mm.h b/wrapper/mm.h new file mode 100644 index 00000000..672855b1 --- /dev/null +++ b/wrapper/mm.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) + * + * wrapper/mm.h + * + * Copyright (C) 2018 Francis Deslauriers + */ + +#ifndef _LTTNG_WRAPPER_MM_H +#define _LTTNG_WRAPPER_MM_H + +#include +#include + +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) \ + || LTTNG_UBUNTU_KERNEL_RANGE(4,4,25,44, 4,5,0,0)) + +/* + * Returns true if the current estimation of the number of page available is + * larger than the number of pages passed as parameter. + */ +static inline +bool wrapper_check_enough_free_pages(unsigned long num_pages) +{ + return num_pages < si_mem_available(); +} + +#else + +static inline +bool wrapper_check_enough_free_pages(unsigned long num_pages) +{ + /* + * The si_mem_available function is not available on this kernel. Since + * we can't reliably know if there is enough memory available, so we + * return true. + */ + return true; +} +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) +static inline +void wrapper_set_current_oom_origin(void) +{ + return set_current_oom_origin(); +} + +static inline +void wrapper_clear_current_oom_origin(void) +{ + return clear_current_oom_origin(); +} + +#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) */ + +static inline +void wrapper_set_current_oom_origin(void) +{ + return; +} + +static inline +void wrapper_clear_current_oom_origin() +{ + return; +} +#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) */ +#endif /* _LTTNG_WRAPPER_MM_H */ -- 2.34.1