From 63c16c3a7608558a8e5ced96b8b6b06c490fd513 Mon Sep 17 00:00:00 2001 From: Chris Coulson Date: Wed, 23 Jan 2019 19:17:09 +0000 Subject: apparmor: Initial implementation of raw policy blob compression This adds an initial implementation of raw policy blob compression, using deflate. Compression level can be controlled via a new sysctl, "apparmor.rawdata_compression_level", which can be set to a value between 0 (no compression) and 9 (highest compression). Signed-off-by: Chris Coulson Signed-off-by: John Johansen --- security/apparmor/include/apparmor.h | 1 + security/apparmor/include/policy_unpack.h | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'security/apparmor/include') diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index 73d63b58d875..fc04e422b8ba 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -40,6 +40,7 @@ extern enum audit_mode aa_g_audit; extern bool aa_g_audit_header; extern bool aa_g_debug; extern bool aa_g_hash_policy; +extern int aa_g_rawdata_compression_level; extern bool aa_g_lock_policy; extern bool aa_g_logsyscall; extern bool aa_g_paranoid_load; diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h index 8db4ab759e80..0739867bb87c 100644 --- a/security/apparmor/include/policy_unpack.h +++ b/security/apparmor/include/policy_unpack.h @@ -45,6 +45,7 @@ enum { AAFS_LOADDATA_REVISION, AAFS_LOADDATA_HASH, AAFS_LOADDATA_DATA, + AAFS_LOADDATA_COMPRESSED_SIZE, AAFS_LOADDATA_DIR, /* must be last actual entry */ AAFS_LOADDATA_NDENTS /* count of entries */ }; @@ -65,11 +66,16 @@ struct aa_loaddata { struct dentry *dents[AAFS_LOADDATA_NDENTS]; struct aa_ns *ns; char *name; - size_t size; + size_t size; /* the original size of the payload */ + size_t compressed_size; /* the compressed size of the payload */ long revision; /* the ns policy revision this caused */ int abi; unsigned char *hash; + /* Pointer to payload. If @compressed_size > 0, then this is the + * compressed version of the payload, else it is the uncompressed + * version (with the size indicated by @size). + */ char *data; }; -- cgit v1.2.3 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') 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 136db994852a9b405ac1074de0e7a1c4c840b8ee Mon Sep 17 00:00:00 2001 From: John Johansen Date: Fri, 31 May 2019 06:54:54 -0700 Subject: apparmor: increase left match history buffer size There have been cases reported where a history buffer size of 8 was not enough to resolve conflict overlaps. Increase the buffer to and get rid of the size element which is currently just storing the constant WB_HISTORY_SIZE. Signed-off-by: John Johansen --- security/apparmor/include/match.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'security/apparmor/include') diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h index 958d2b52a7b7..90fc050a6c2d 100644 --- a/security/apparmor/include/match.h +++ b/security/apparmor/include/match.h @@ -138,7 +138,7 @@ unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start, void aa_dfa_free_kref(struct kref *kref); -#define WB_HISTORY_SIZE 8 +#define WB_HISTORY_SIZE 24 struct match_workbuf { unsigned int count; unsigned int pos; @@ -151,7 +151,6 @@ struct match_workbuf N = { \ .count = 0, \ .pos = 0, \ .len = 0, \ - .size = WB_HISTORY_SIZE, \ } unsigned int aa_dfa_leftmatch(struct aa_dfa *dfa, unsigned int start, -- 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/file.h | 2 +- security/apparmor/include/path.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'security/apparmor/include') diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index 8be09208cf7c..67fadf06fa73 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -201,7 +201,7 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry); int aa_file_perm(const char *op, struct aa_label *label, struct file *file, - u32 request); + u32 request, bool in_atomic); void aa_inherit_files(const struct cred *cred, struct files_struct *files); 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