From df323337e507a0009d3db1ea25948d4c7f320d62 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 3 May 2019 16:12:21 +0200 Subject: apparmor: Use a memory pool instead per-CPU caches The get_buffers() macro may provide one or two buffers to the caller. Those buffers are pre-allocated on init for each CPU. By default it allocates 2* 2 * MAX_PATH * POSSIBLE_CPU which equals 64KiB on a system with 4 CPUs or 1MiB with 64 CPUs and so on. Replace the per-CPU buffers with a common memory pool which is shared across all CPUs. The pool grows on demand and never shrinks. The pool starts with two (UP) or four (SMP) elements. By using this pool it is possible to request a buffer and keeping preemption enabled which avoids the hack in profile_transition(). It has been pointed out by Tetsuo Handa that GFP_KERNEL allocations for small amount of memory do not fail. In order not to have an endless retry, __GFP_RETRY_MAYFAIL is passed (so the memory allocation is not repeated until success) and retried once hoping that in the meantime a buffer has been returned to the pool. Since now NULL is possible all allocation paths check the buffer pointer and return -ENOMEM on failure. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: John Johansen --- security/apparmor/include/path.h | 49 ++-------------------------------------- 1 file changed, 2 insertions(+), 47 deletions(-) (limited to 'security/apparmor/include/path.h') diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h index b6380c5f0097..b0b2ab85e42d 100644 --- a/security/apparmor/include/path.h +++ b/security/apparmor/include/path.h @@ -15,7 +15,6 @@ #ifndef __AA_PATH_H #define __AA_PATH_H - enum path_flags { PATH_IS_DIR = 0x1, /* path is a directory */ PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */ @@ -30,51 +29,7 @@ int aa_path_name(const struct path *path, int flags, char *buffer, const char **name, const char **info, const char *disconnected); -#define MAX_PATH_BUFFERS 2 - -/* Per cpu buffers used during mediation */ -/* preallocated buffers to use during path lookups */ -struct aa_buffers { - char *buf[MAX_PATH_BUFFERS]; -}; - -#include -#include - -DECLARE_PER_CPU(struct aa_buffers, aa_buffers); - -#define ASSIGN(FN, A, X, N) ((X) = FN(A, N)) -#define EVAL1(FN, A, X) ASSIGN(FN, A, X, 0) /*X = FN(0)*/ -#define EVAL2(FN, A, X, Y...) \ - do { ASSIGN(FN, A, X, 1); EVAL1(FN, A, Y); } while (0) -#define EVAL(FN, A, X...) CONCATENATE(EVAL, COUNT_ARGS(X))(FN, A, X) - -#define for_each_cpu_buffer(I) for ((I) = 0; (I) < MAX_PATH_BUFFERS; (I)++) - -#ifdef CONFIG_DEBUG_PREEMPT -#define AA_BUG_PREEMPT_ENABLED(X) AA_BUG(preempt_count() <= 0, X) -#else -#define AA_BUG_PREEMPT_ENABLED(X) /* nop */ -#endif - -#define __get_buffer(C, N) ({ \ - AA_BUG_PREEMPT_ENABLED("__get_buffer without preempt disabled"); \ - (C)->buf[(N)]; }) - -#define __get_buffers(C, X...) EVAL(__get_buffer, C, X) - -#define __put_buffers(X, Y...) ((void)&(X)) - -#define get_buffers(X...) \ -do { \ - struct aa_buffers *__cpu_var = get_cpu_ptr(&aa_buffers); \ - __get_buffers(__cpu_var, X); \ -} while (0) - -#define put_buffers(X, Y...) \ -do { \ - __put_buffers(X, Y); \ - put_cpu_ptr(&aa_buffers); \ -} while (0) +char *aa_get_buffer(void); +void aa_put_buffer(char *buf); #endif /* __AA_PATH_H */ -- cgit v1.2.3 From 341c1fda5e17156619fb71acfc7082b2669b4b72 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Sat, 14 Sep 2019 03:34:06 -0700 Subject: apparmor: make it so work buffers can be allocated from atomic context In some situations AppArmor needs to be able to use its work buffers from atomic context. Add the ability to specify when in atomic context and hold a set of work buffers in reserve for atomic context to reduce the chance that a large work buffer allocation will need to be done. Fixes: df323337e507 ("apparmor: Use a memory pool instead per-CPU caches") Signed-off-by: John Johansen --- security/apparmor/include/path.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security/apparmor/include/path.h') diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h index b0b2ab85e42d..d2ab8a932bad 100644 --- a/security/apparmor/include/path.h +++ b/security/apparmor/include/path.h @@ -29,7 +29,8 @@ int aa_path_name(const struct path *path, int flags, char *buffer, const char **name, const char **info, const char *disconnected); -char *aa_get_buffer(void); +#define IN_ATOMIC true +char *aa_get_buffer(bool in_atomic); void aa_put_buffer(char *buf); #endif /* __AA_PATH_H */ -- cgit v1.2.3