From 3af550b1f169f65f4fa0107c3841de18d1abc4e6 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Fri, 10 Jul 2020 10:32:33 +0200 Subject: [PATCH 01/15] Proof of Concept create keys and add to static list minimum working poc wip cleanup --- security/security.c | 73 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/security/security.c b/security/security.c index 70a7ad357bc6ab..f1278ce5da4fcc 100644 --- a/security/security.c +++ b/security/security.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #define MAX_LSM_EVM_XATTR 2 @@ -464,6 +467,45 @@ static int lsm_append(const char *new, char **result) return 0; } +#define LSM_FUNC_DEFAULT(NAME) NAME##_func_default +#define HOOK_STATIC_CALL(HOOK, NUM) static_call_##HOOK##_##NUM +#define HOOK_STATIC_CHECK(HOOK, NUM) static_check_##HOOK##_##NUM + +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +noinline RET LSM_FUNC_DEFAULT(NAME)(__VA_ARGS__) \ +{ \ + return DEFAULT; \ +} +#include +#undef LSM_HOOK + +#define CREATE_STATIC(NAME, NUM) \ + DEFINE_STATIC_CALL(HOOK_STATIC_CALL(NAME, NUM), LSM_FUNC_DEFAULT(NAME));\ + DEFINE_STATIC_KEY_FALSE(HOOK_STATIC_CHECK(NAME, NUM)); + +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + CREATE_STATIC(NAME, 1) \ + CREATE_STATIC(NAME, 2) \ + CREATE_STATIC(NAME, 3) +#include +#undef LSM_HOOK +#undef CREATE_STATIC + +#define TRY_TO_ADD(HOOK, FUNC, NUM) \ + if (!static_branch_unlikely(&HOOK_STATIC_CHECK(HOOK, NUM))) { \ + static_call_update(HOOK_STATIC_CALL(HOOK, NUM), FUNC); \ + static_branch_enable(&HOOK_STATIC_CHECK(HOOK, NUM)); \ + break; \ + } + +#define ADD_STATIC_HOOK(HOOK, FUNC) \ + do { \ + TRY_TO_ADD(HOOK, FUNC, 1) \ + TRY_TO_ADD(HOOK, FUNC, 2) \ + TRY_TO_ADD(HOOK, FUNC, 3) \ + printk(KERN_ERR "No slot remaining to add LSM hook for " #HOOK "\n"); \ + } while(0) + /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add @@ -480,6 +522,12 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, for (i = 0; i < count; i++) { hooks[i].lsm = lsm; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); + + #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + if (&security_hook_heads.NAME == hooks[i].head) \ + ADD_STATIC_HOOK(NAME, hooks[i].hook.NAME); + #include + #undef LSM_HOOK } /* @@ -687,6 +735,14 @@ static void __init lsm_early_task(struct task_struct *task) #include #undef LSM_HOOK + +#define TRY_TO_STATIC_CALL(R, HOOK, NUM, ...) \ + if (static_branch_unlikely(&HOOK_STATIC_CHECK(HOOK, NUM))) { \ + R = static_call(HOOK_STATIC_CALL(HOOK, NUM))(__VA_ARGS__); \ + if (R != 0) \ + break; \ + } + /* * Hook list operation macros. * @@ -698,6 +754,13 @@ static void __init lsm_early_task(struct task_struct *task) */ #define call_void_hook(FUNC, ...) \ + do { \ + static_call_cond(HOOK_STATIC_CALL(FUNC, 1))(__VA_ARGS__); \ + static_call_cond(HOOK_STATIC_CALL(FUNC, 2))(__VA_ARGS__); \ + static_call_cond(HOOK_STATIC_CALL(FUNC, 3))(__VA_ARGS__); \ + } while (0) + +// #define call_void_hook(FUNC, ...) \ do { \ struct security_hook_list *P; \ \ @@ -706,6 +769,16 @@ static void __init lsm_early_task(struct task_struct *task) } while (0) #define call_int_hook(FUNC, IRC, ...) ({ \ + int RC = IRC; \ + do { \ + TRY_TO_STATIC_CALL(RC, FUNC, 1, __VA_ARGS__) \ + TRY_TO_STATIC_CALL(RC, FUNC, 2, __VA_ARGS__) \ + TRY_TO_STATIC_CALL(RC, FUNC, 3, __VA_ARGS__) \ + } while (0); \ + RC; \ +}) + +// #define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ do { \ struct security_hook_list *P; \ From 58659bff5a9e160304d4e393be4518a164659b73 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Tue, 14 Jul 2020 14:35:47 +0200 Subject: [PATCH 02/15] Remove macro magic to add LSM in a slot for-loop like struct slot get rid of macros use generic array of slots cleanup --- include/linux/lsm_hooks.h | 27 +++++++- security/security.c | 137 ++++++++++++++++++-------------------- 2 files changed, 90 insertions(+), 74 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 95b7c1d3206218..c6d9dd341f442f 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include /** * union security_list_options - Linux Security Module hook function list @@ -1524,6 +1526,7 @@ union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); #include "lsm_hook_defs.h" #undef LSM_HOOK + void *generic_func; }; struct security_hook_heads { @@ -1532,6 +1535,25 @@ struct security_hook_heads { #undef LSM_HOOK } __randomize_layout; +#define SLOT_COUNT 3 +#define FOR_EACH_HOOK_SLOT(M, ...) \ + M(0, __VA_ARGS__) \ + M(1, __VA_ARGS__) \ + M(2, __VA_ARGS__) + +struct static_slot { + struct static_key_false *key; + struct static_call_key *call_key; + void *call_tramp; +}; + +struct hook_static_slots { + #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + struct static_slot NAME[SLOT_COUNT]; + #include "lsm_hook_defs.h" + #undef LSM_HOOK +} __randomize_layout; + /* * Security module hook list structure. * For use with generic list macros for common operations. @@ -1541,6 +1563,7 @@ struct security_hook_list { struct hlist_head *head; union security_list_options hook; char *lsm; + struct static_slot *slots; } __randomize_layout; /* @@ -1568,9 +1591,11 @@ struct lsm_blob_sizes { * text involved. */ #define LSM_HOOK_INIT(HEAD, HOOK) \ - { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } } + { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK }, \ + .slots = hook_static_slots.HEAD } extern struct security_hook_heads security_hook_heads; +extern struct hook_static_slots hook_static_slots; extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, diff --git a/security/security.c b/security/security.c index f1278ce5da4fcc..64eb08d498950a 100644 --- a/security/security.c +++ b/security/security.c @@ -32,6 +32,7 @@ #include #include + #define MAX_LSM_EVM_XATTR 2 /* How many LSMs were built into the kernel? */ @@ -89,6 +90,45 @@ static __initconst const char * const builtin_lsm_order = CONFIG_LSM; static __initdata struct lsm_info **ordered_lsms; static __initdata struct lsm_info *exclusive; +/* static slots init */ +#define LSM_FUNC_DEFAULT(NAME) NAME##_func_default +#define HOOK_STATIC_CALL(HOOK, NUM) static_call_##HOOK##_##NUM +#define HOOK_STATIC_CHECK(HOOK, NUM) static_check_##HOOK##_##NUM + +#define CREATE_STATIC(NUM, NAME) \ + DEFINE_STATIC_CALL(HOOK_STATIC_CALL(NAME, NUM), \ + LSM_FUNC_DEFAULT(NAME)); \ + DEFINE_STATIC_KEY_FALSE(HOOK_STATIC_CHECK(NAME, NUM)); + +// We need a default function that will not be called so that +// static_call can infer the expected type +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + noinline RET LSM_FUNC_DEFAULT(NAME)(__VA_ARGS__)\ + { \ + return DEFAULT; \ + } \ + FOR_EACH_HOOK_SLOT(CREATE_STATIC, NAME) +#include +#undef LSM_HOOK +#undef CREATE_STATIC + +struct hook_static_slots hook_static_slots __lsm_ro_after_init = { +#define SLOT_DEFINITION(NUM, NAME) \ + (struct static_slot) { \ + .key = &HOOK_STATIC_CHECK(NAME, NUM), \ + .call_key = &STATIC_CALL_KEY(HOOK_STATIC_CALL(NAME, NUM)), \ + .call_tramp = &STATIC_CALL_TRAMP(HOOK_STATIC_CALL(NAME, NUM)) \ + }, +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + .NAME = { \ + FOR_EACH_HOOK_SLOT(SLOT_DEFINITION, NAME) \ + }, +#include +#undef LSM_HOOK +#undef SLOT_DEFINITION +}; + + static __initdata bool debug; #define init_debug(...) \ do { \ @@ -467,45 +507,6 @@ static int lsm_append(const char *new, char **result) return 0; } -#define LSM_FUNC_DEFAULT(NAME) NAME##_func_default -#define HOOK_STATIC_CALL(HOOK, NUM) static_call_##HOOK##_##NUM -#define HOOK_STATIC_CHECK(HOOK, NUM) static_check_##HOOK##_##NUM - -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ -noinline RET LSM_FUNC_DEFAULT(NAME)(__VA_ARGS__) \ -{ \ - return DEFAULT; \ -} -#include -#undef LSM_HOOK - -#define CREATE_STATIC(NAME, NUM) \ - DEFINE_STATIC_CALL(HOOK_STATIC_CALL(NAME, NUM), LSM_FUNC_DEFAULT(NAME));\ - DEFINE_STATIC_KEY_FALSE(HOOK_STATIC_CHECK(NAME, NUM)); - -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - CREATE_STATIC(NAME, 1) \ - CREATE_STATIC(NAME, 2) \ - CREATE_STATIC(NAME, 3) -#include -#undef LSM_HOOK -#undef CREATE_STATIC - -#define TRY_TO_ADD(HOOK, FUNC, NUM) \ - if (!static_branch_unlikely(&HOOK_STATIC_CHECK(HOOK, NUM))) { \ - static_call_update(HOOK_STATIC_CALL(HOOK, NUM), FUNC); \ - static_branch_enable(&HOOK_STATIC_CHECK(HOOK, NUM)); \ - break; \ - } - -#define ADD_STATIC_HOOK(HOOK, FUNC) \ - do { \ - TRY_TO_ADD(HOOK, FUNC, 1) \ - TRY_TO_ADD(HOOK, FUNC, 2) \ - TRY_TO_ADD(HOOK, FUNC, 3) \ - printk(KERN_ERR "No slot remaining to add LSM hook for " #HOOK "\n"); \ - } while(0) - /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add @@ -518,16 +519,28 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, char *lsm) { int i; + struct static_slot *slot; for (i = 0; i < count; i++) { hooks[i].lsm = lsm; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - if (&security_hook_heads.NAME == hooks[i].head) \ - ADD_STATIC_HOOK(NAME, hooks[i].hook.NAME); - #include - #undef LSM_HOOK + if (!hooks[i].slots || !hooks[i].hook.generic_func) + continue; + for (slot = hooks[i].slots; + slot < hooks[i].slots + SLOT_COUNT; slot++) { + if (!static_key_enabled(&slot->key->key)) { + __static_call_update( + slot->call_key, slot->call_tramp, + hooks[i].hook.generic_func); + static_branch_enable(slot->key); + break; + } + } + if (slot == hooks[i].slots + SLOT_COUNT) { + printk(KERN_ERR + "No slot remaining to add LSM hook %s\n", lsm); + } } /* @@ -736,13 +749,15 @@ static void __init lsm_early_task(struct task_struct *task) #undef LSM_HOOK -#define TRY_TO_STATIC_CALL(R, HOOK, NUM, ...) \ +#define TRY_TO_STATIC_CALL_INT(NUM, R, HOOK, ...) \ if (static_branch_unlikely(&HOOK_STATIC_CHECK(HOOK, NUM))) { \ R = static_call(HOOK_STATIC_CALL(HOOK, NUM))(__VA_ARGS__); \ if (R != 0) \ break; \ } +#define TRY_TO_STATIC_CALL_VOID(NUM, HOOK, ...) \ + static_call_cond(HOOK_STATIC_CALL(HOOK, NUM))(__VA_ARGS__); /* * Hook list operation macros. * @@ -755,39 +770,15 @@ static void __init lsm_early_task(struct task_struct *task) #define call_void_hook(FUNC, ...) \ do { \ - static_call_cond(HOOK_STATIC_CALL(FUNC, 1))(__VA_ARGS__); \ - static_call_cond(HOOK_STATIC_CALL(FUNC, 2))(__VA_ARGS__); \ - static_call_cond(HOOK_STATIC_CALL(FUNC, 3))(__VA_ARGS__); \ - } while (0) - -// #define call_void_hook(FUNC, ...) \ - do { \ - struct security_hook_list *P; \ - \ - hlist_for_each_entry(P, &security_hook_heads.FUNC, list) \ - P->hook.FUNC(__VA_ARGS__); \ + FOR_EACH_HOOK_SLOT(TRY_TO_STATIC_CALL_VOID, \ + FUNC, __VA_ARGS__) \ } while (0) #define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ do { \ - TRY_TO_STATIC_CALL(RC, FUNC, 1, __VA_ARGS__) \ - TRY_TO_STATIC_CALL(RC, FUNC, 2, __VA_ARGS__) \ - TRY_TO_STATIC_CALL(RC, FUNC, 3, __VA_ARGS__) \ - } while (0); \ - RC; \ -}) - -// #define call_int_hook(FUNC, IRC, ...) ({ \ - int RC = IRC; \ - do { \ - struct security_hook_list *P; \ - \ - hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \ - RC = P->hook.FUNC(__VA_ARGS__); \ - if (RC != 0) \ - break; \ - } \ + FOR_EACH_HOOK_SLOT(TRY_TO_STATIC_CALL_INT, \ + RC, FUNC, __VA_ARGS__) \ } while (0); \ RC; \ }) From 5cb91dddaeb74f5cfdccf884ce10b8925b43633a Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Thu, 23 Jul 2020 12:47:27 +0200 Subject: [PATCH 03/15] remove default functions --- security/security.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/security/security.c b/security/security.c index 64eb08d498950a..6e441bf5d3f92c 100644 --- a/security/security.c +++ b/security/security.c @@ -95,19 +95,15 @@ static __initdata struct lsm_info *exclusive; #define HOOK_STATIC_CALL(HOOK, NUM) static_call_##HOOK##_##NUM #define HOOK_STATIC_CHECK(HOOK, NUM) static_check_##HOOK##_##NUM -#define CREATE_STATIC(NUM, NAME) \ - DEFINE_STATIC_CALL(HOOK_STATIC_CALL(NAME, NUM), \ - LSM_FUNC_DEFAULT(NAME)); \ +#define CREATE_STATIC(NUM, NAME, RET, ...) \ + DEFINE_STATIC_CALL_NULL(HOOK_STATIC_CALL(NAME, NUM), \ + *((RET(*)(__VA_ARGS__))NULL)); \ DEFINE_STATIC_KEY_FALSE(HOOK_STATIC_CHECK(NAME, NUM)); // We need a default function that will not be called so that // static_call can infer the expected type #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - noinline RET LSM_FUNC_DEFAULT(NAME)(__VA_ARGS__)\ - { \ - return DEFAULT; \ - } \ - FOR_EACH_HOOK_SLOT(CREATE_STATIC, NAME) + FOR_EACH_HOOK_SLOT(CREATE_STATIC, NAME, RET, __VA_ARGS__) #include #undef LSM_HOOK #undef CREATE_STATIC From c376984c94999a01c59ef277767575295514df45 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Thu, 23 Jul 2020 17:55:32 +0200 Subject: [PATCH 04/15] Remove static keys and introduce static_call_cond_int With the addition of static_call_cond_int to the static call API, we don't need static keys anymore. A default value is provided, which is put into %eax before the call. This way, if the call is replaced by a nop, the default value will be in the place of the returned value. For now, this does not work when one of the arguments of the call is a function call (eax will be overwritten), hence the modification to security_mmap_file --- arch/x86/include/asm/static_call.h | 3 +++ include/linux/lsm_hooks.h | 2 -- include/linux/static_call.h | 5 +++++ security/security.c | 21 ++++++++------------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/static_call.h b/arch/x86/include/asm/static_call.h index c37f11999d0c0f..8672f1fb28663f 100644 --- a/arch/x86/include/asm/static_call.h +++ b/arch/x86/include/asm/static_call.h @@ -37,4 +37,7 @@ #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \ __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; nop; nop; nop; nop") +#define ARCH_SET_STATIC_CALL_DEFAULT_VALUE(i) \ + asm("mov $" #i ",%eax\t\n") + #endif /* _ASM_STATIC_CALL_H */ diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index c6d9dd341f442f..cf35815950f5fa 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -29,7 +29,6 @@ #include #include #include -#include /** * union security_list_options - Linux Security Module hook function list @@ -1542,7 +1541,6 @@ struct security_hook_heads { M(2, __VA_ARGS__) struct static_slot { - struct static_key_false *key; struct static_call_key *call_key; void *call_tramp; }; diff --git a/include/linux/static_call.h b/include/linux/static_call.h index bfa2ba39be57e3..f40ad5569061fb 100644 --- a/include/linux/static_call.h +++ b/include/linux/static_call.h @@ -176,6 +176,11 @@ extern int static_call_text_reserved(void *start, void *end); #define static_call(name) __static_call(name) #define static_call_cond(name) (void)__static_call(name) +#define static_call_cond_int(name, _default) \ +({ \ + ARCH_SET_STATIC_CALL_DEFAULT_VALUE(_default); \ + __static_call(name); \ +}) #define EXPORT_STATIC_CALL(name) \ EXPORT_SYMBOL(STATIC_CALL_KEY(name)); \ diff --git a/security/security.c b/security/security.c index 6e441bf5d3f92c..5af82248df05a4 100644 --- a/security/security.c +++ b/security/security.c @@ -93,12 +93,10 @@ static __initdata struct lsm_info *exclusive; /* static slots init */ #define LSM_FUNC_DEFAULT(NAME) NAME##_func_default #define HOOK_STATIC_CALL(HOOK, NUM) static_call_##HOOK##_##NUM -#define HOOK_STATIC_CHECK(HOOK, NUM) static_check_##HOOK##_##NUM #define CREATE_STATIC(NUM, NAME, RET, ...) \ DEFINE_STATIC_CALL_NULL(HOOK_STATIC_CALL(NAME, NUM), \ - *((RET(*)(__VA_ARGS__))NULL)); \ - DEFINE_STATIC_KEY_FALSE(HOOK_STATIC_CHECK(NAME, NUM)); + *((RET(*)(__VA_ARGS__))NULL)); // We need a default function that will not be called so that // static_call can infer the expected type @@ -111,7 +109,6 @@ static __initdata struct lsm_info *exclusive; struct hook_static_slots hook_static_slots __lsm_ro_after_init = { #define SLOT_DEFINITION(NUM, NAME) \ (struct static_slot) { \ - .key = &HOOK_STATIC_CHECK(NAME, NUM), \ .call_key = &STATIC_CALL_KEY(HOOK_STATIC_CALL(NAME, NUM)), \ .call_tramp = &STATIC_CALL_TRAMP(HOOK_STATIC_CALL(NAME, NUM)) \ }, @@ -525,11 +522,10 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, continue; for (slot = hooks[i].slots; slot < hooks[i].slots + SLOT_COUNT; slot++) { - if (!static_key_enabled(&slot->key->key)) { + if (!slot->call_key->func) { __static_call_update( slot->call_key, slot->call_tramp, hooks[i].hook.generic_func); - static_branch_enable(slot->key); break; } } @@ -745,12 +741,10 @@ static void __init lsm_early_task(struct task_struct *task) #undef LSM_HOOK -#define TRY_TO_STATIC_CALL_INT(NUM, R, HOOK, ...) \ - if (static_branch_unlikely(&HOOK_STATIC_CHECK(HOOK, NUM))) { \ - R = static_call(HOOK_STATIC_CALL(HOOK, NUM))(__VA_ARGS__); \ - if (R != 0) \ - break; \ - } +#define TRY_TO_STATIC_CALL_INT(NUM, R, HOOK, ...) \ + R = static_call_cond_int(HOOK_STATIC_CALL(HOOK, NUM), 0)(__VA_ARGS__); \ + if (R != 0) \ + break; #define TRY_TO_STATIC_CALL_VOID(NUM, HOOK, ...) \ static_call_cond(HOOK_STATIC_CALL(HOOK, NUM))(__VA_ARGS__); @@ -1578,8 +1572,9 @@ int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { int ret; + long mmap_p = mmap_prot(file, prot); ret = call_int_hook(mmap_file, 0, file, prot, - mmap_prot(file, prot), flags); + mmap_p, flags); if (ret) return ret; return ima_file_mmap(file, prot); From 4d3a07df834de4c5d0f7576ca371a811686c19cc Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Mon, 27 Jul 2020 17:53:01 +0200 Subject: [PATCH 05/15] Clean up --- include/linux/lsm_hooks.h | 41 ++++++++------ security/security.c | 110 +++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index cf35815950f5fa..7a39d4c2fcfc43 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1534,20 +1534,30 @@ struct security_hook_heads { #undef LSM_HOOK } __randomize_layout; -#define SLOT_COUNT 3 -#define FOR_EACH_HOOK_SLOT(M, ...) \ - M(0, __VA_ARGS__) \ - M(1, __VA_ARGS__) \ +/* + * Static slots are placeholders for potential LSM hooks. + * Instead of a costly indirect call, they use static calls. + */ +#define SECURITY_STATIC_SLOT_COUNT 3 +#define SECURITY_FOREACH_STATIC_SLOT(M, ...) \ + M(0, __VA_ARGS__) \ + M(1, __VA_ARGS__) \ M(2, __VA_ARGS__) -struct static_slot { - struct static_call_key *call_key; - void *call_tramp; +/* + * Necessary information about a static + * slot to call __static_call_update + */ +struct security_static_slot { + /* static call key as defined by STATIC_CALL_KEY */ + struct static_call_key *key; + /* static call tramp as defined by STATIC_CALL_TRAMP */ + void *tramp; }; -struct hook_static_slots { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - struct static_slot NAME[SLOT_COUNT]; +struct security_list_static_slots { + #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + struct security_static_slot NAME[SECURITY_STATIC_SLOT_COUNT]; #include "lsm_hook_defs.h" #undef LSM_HOOK } __randomize_layout; @@ -1561,7 +1571,7 @@ struct security_hook_list { struct hlist_head *head; union security_list_options hook; char *lsm; - struct static_slot *slots; + struct security_static_slot *slots; } __randomize_layout; /* @@ -1588,12 +1598,13 @@ struct lsm_blob_sizes { * care of the common case and reduces the amount of * text involved. */ -#define LSM_HOOK_INIT(HEAD, HOOK) \ - { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK }, \ - .slots = hook_static_slots.HEAD } +#define LSM_HOOK_INIT(HEAD, HOOK) \ + { .head = &security_hook_heads.HEAD, \ + .hook = { .HEAD = HOOK }, \ + .slots = security_list_static_slots.HEAD } extern struct security_hook_heads security_hook_heads; -extern struct hook_static_slots hook_static_slots; +extern struct security_list_static_slots security_list_static_slots; extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, diff --git a/security/security.c b/security/security.c index 5af82248df05a4..4e74fc6b9906d7 100644 --- a/security/security.c +++ b/security/security.c @@ -38,6 +38,8 @@ /* How many LSMs were built into the kernel? */ #define LSM_COUNT (__end_lsm_info - __start_lsm_info) +#define STATIC_SLOT(HOOK, NUM) security_static_slot_##HOOK##_##NUM + /* * These are descriptions of the reasons that can be passed to the * security_locked_down() LSM hook. Placing this array here allows @@ -90,38 +92,33 @@ static __initconst const char * const builtin_lsm_order = CONFIG_LSM; static __initdata struct lsm_info **ordered_lsms; static __initdata struct lsm_info *exclusive; -/* static slots init */ -#define LSM_FUNC_DEFAULT(NAME) NAME##_func_default -#define HOOK_STATIC_CALL(HOOK, NUM) static_call_##HOOK##_##NUM - -#define CREATE_STATIC(NUM, NAME, RET, ...) \ - DEFINE_STATIC_CALL_NULL(HOOK_STATIC_CALL(NAME, NUM), \ +/* Create the static slots for each LSM hook */ +#define CREATE_STATIC_SLOT(NUM, NAME, RET, ...) \ + DEFINE_STATIC_CALL_NULL(STATIC_SLOT(NAME, NUM), \ *((RET(*)(__VA_ARGS__))NULL)); -// We need a default function that will not be called so that -// static_call can infer the expected type -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - FOR_EACH_HOOK_SLOT(CREATE_STATIC, NAME, RET, __VA_ARGS__) +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + SECURITY_FOREACH_STATIC_SLOT(CREATE_STATIC_SLOT, NAME, RET, __VA_ARGS__) #include #undef LSM_HOOK #undef CREATE_STATIC -struct hook_static_slots hook_static_slots __lsm_ro_after_init = { -#define SLOT_DEFINITION(NUM, NAME) \ - (struct static_slot) { \ - .call_key = &STATIC_CALL_KEY(HOOK_STATIC_CALL(NAME, NUM)), \ - .call_tramp = &STATIC_CALL_TRAMP(HOOK_STATIC_CALL(NAME, NUM)) \ +struct security_list_static_slots security_list_static_slots +__lsm_ro_after_init = { +#define SLOT_DEFINITION(NUM, NAME) \ + (struct security_static_slot) { \ + .key = &STATIC_CALL_KEY(STATIC_SLOT(NAME, NUM)), \ + .tramp = &STATIC_CALL_TRAMP(STATIC_SLOT(NAME, NUM)) \ }, -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - .NAME = { \ - FOR_EACH_HOOK_SLOT(SLOT_DEFINITION, NAME) \ +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + .NAME = { \ + SECURITY_FOREACH_STATIC_SLOT(SLOT_DEFINITION, NAME) \ }, #include #undef LSM_HOOK #undef SLOT_DEFINITION }; - static __initdata bool debug; #define init_debug(...) \ do { \ @@ -500,6 +497,26 @@ static int lsm_append(const char *new, char **result) return 0; } +static inline void add_to_static_slots(struct security_static_slot *slot_list, + void *func) +{ + struct security_static_slot *slot; + + if (!slot_list || !func) + panic("%s - Incorrectly initialized hook.\n", __func__); + + for (slot = slot_list; slot < slot_list + SECURITY_STATIC_SLOT_COUNT; + slot++) { + if (!slot->key->func) { + __static_call_update(slot->key, slot->tramp, func); + break; + } + } + if (slot == slot_list + SECURITY_STATIC_SLOT_COUNT) + panic("%s - No static hook slot remaining to add LSM hook.\n", + __func__); +} + /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add @@ -512,27 +529,11 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, char *lsm) { int i; - struct static_slot *slot; for (i = 0; i < count; i++) { hooks[i].lsm = lsm; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); - - if (!hooks[i].slots || !hooks[i].hook.generic_func) - continue; - for (slot = hooks[i].slots; - slot < hooks[i].slots + SLOT_COUNT; slot++) { - if (!slot->call_key->func) { - __static_call_update( - slot->call_key, slot->call_tramp, - hooks[i].hook.generic_func); - break; - } - } - if (slot == hooks[i].slots + SLOT_COUNT) { - printk(KERN_ERR - "No slot remaining to add LSM hook %s\n", lsm); - } + add_to_static_slots(hooks[i].slots, hooks[i].hook.generic_func); } /* @@ -740,14 +741,6 @@ static void __init lsm_early_task(struct task_struct *task) #include #undef LSM_HOOK - -#define TRY_TO_STATIC_CALL_INT(NUM, R, HOOK, ...) \ - R = static_call_cond_int(HOOK_STATIC_CALL(HOOK, NUM), 0)(__VA_ARGS__); \ - if (R != 0) \ - break; - -#define TRY_TO_STATIC_CALL_VOID(NUM, HOOK, ...) \ - static_call_cond(HOOK_STATIC_CALL(HOOK, NUM))(__VA_ARGS__); /* * Hook list operation macros. * @@ -757,20 +750,27 @@ static void __init lsm_early_task(struct task_struct *task) * call_int_hook: * This is a hook that returns a value. */ +#define CALL_STATIC_SLOT_VOID(NUM, HOOK, ...) \ + static_call_cond(STATIC_SLOT(HOOK, NUM))(__VA_ARGS__); -#define call_void_hook(FUNC, ...) \ - do { \ - FOR_EACH_HOOK_SLOT(TRY_TO_STATIC_CALL_VOID, \ - FUNC, __VA_ARGS__) \ +#define call_void_hook(FUNC, ...) \ + do { \ + SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_VOID, \ + FUNC, __VA_ARGS__) \ } while (0) -#define call_int_hook(FUNC, IRC, ...) ({ \ - int RC = IRC; \ - do { \ - FOR_EACH_HOOK_SLOT(TRY_TO_STATIC_CALL_INT, \ - RC, FUNC, __VA_ARGS__) \ - } while (0); \ - RC; \ +#define CALL_STATIC_SLOT_INT(NUM, R, HOOK, ...) \ + R = static_call_cond_int(STATIC_SLOT(HOOK, NUM), 0)(__VA_ARGS__);\ + if (R != 0) \ + break; + +#define call_int_hook(FUNC, IRC, ...) ({ \ + int RC = IRC; \ + do { \ + SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_INT, \ + RC, FUNC, __VA_ARGS__) \ + } while (0); \ + RC; \ }) /* Security operations */ From b7d05cb0c8a12843a48383638accf22637c0e627 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Fri, 31 Jul 2020 13:07:19 +0200 Subject: [PATCH 06/15] more cleanup --- security/security.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/security/security.c b/security/security.c index 4e74fc6b9906d7..18ac006f11314f 100644 --- a/security/security.c +++ b/security/security.c @@ -30,8 +30,6 @@ #include #include #include -#include - #define MAX_LSM_EVM_XATTR 2 @@ -756,7 +754,7 @@ static void __init lsm_early_task(struct task_struct *task) #define call_void_hook(FUNC, ...) \ do { \ SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_VOID, \ - FUNC, __VA_ARGS__) \ + FUNC, __VA_ARGS__) \ } while (0) #define CALL_STATIC_SLOT_INT(NUM, R, HOOK, ...) \ From 08fbfbc993da018e9f27250e7c7a7c93e65f3e6f Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Tue, 4 Aug 2020 15:09:24 +0200 Subject: [PATCH 07/15] Replace static_call_cond_int by switch statement --- include/linux/lsm_hooks.h | 20 ++++++--- security/security.c | 92 +++++++++++++++++++++++++++------------ 2 files changed, 78 insertions(+), 34 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 7a39d4c2fcfc43..aacbd21eefe5b6 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1555,9 +1555,22 @@ struct security_static_slot { void *tramp; }; +/* Static slots and related information for a hook */ +struct security_hook_static_slots { + struct security_static_slot slots[SECURITY_STATIC_SLOT_COUNT]; + /* + * Index of first slot to be used. + * All slots with greater index are used. + * INT_MAX if no slot is used. + */ + int first_slot; + /* hlist corresponding to this hook */ + struct hlist_head *head; +}; + struct security_list_static_slots { #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - struct security_static_slot NAME[SECURITY_STATIC_SLOT_COUNT]; + struct security_hook_static_slots NAME; #include "lsm_hook_defs.h" #undef LSM_HOOK } __randomize_layout; @@ -1571,7 +1584,6 @@ struct security_hook_list { struct hlist_head *head; union security_list_options hook; char *lsm; - struct security_static_slot *slots; } __randomize_layout; /* @@ -1599,9 +1611,7 @@ struct lsm_blob_sizes { * text involved. */ #define LSM_HOOK_INIT(HEAD, HOOK) \ - { .head = &security_hook_heads.HEAD, \ - .hook = { .HEAD = HOOK }, \ - .slots = security_list_static_slots.HEAD } + { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } } extern struct security_hook_heads security_hook_heads; extern struct security_list_static_slots security_list_static_slots; diff --git a/security/security.c b/security/security.c index 18ac006f11314f..6a54c0eb641528 100644 --- a/security/security.c +++ b/security/security.c @@ -8,6 +8,7 @@ * Copyright (C) 2016 Mellanox Technologies */ +#include "vdso/limits.h" #define pr_fmt(fmt) "LSM: " fmt #include @@ -103,18 +104,22 @@ static __initdata struct lsm_info *exclusive; struct security_list_static_slots security_list_static_slots __lsm_ro_after_init = { -#define SLOT_DEFINITION(NUM, NAME) \ +#define DEFINE_SLOT(NUM, NAME) \ (struct security_static_slot) { \ .key = &STATIC_CALL_KEY(STATIC_SLOT(NAME, NUM)), \ .tramp = &STATIC_CALL_TRAMP(STATIC_SLOT(NAME, NUM)) \ }, #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ .NAME = { \ - SECURITY_FOREACH_STATIC_SLOT(SLOT_DEFINITION, NAME) \ + .slots = { \ + SECURITY_FOREACH_STATIC_SLOT(DEFINE_SLOT, NAME) \ + }, \ + .first_slot = INT_MAX, \ + .head = &security_hook_heads.NAME \ }, #include #undef LSM_HOOK -#undef SLOT_DEFINITION +#undef DEFINE_SLOT }; static __initdata bool debug; @@ -338,6 +343,52 @@ static void __init ordered_lsm_parse(const char *order, const char *origin) kfree(sep); } +static void __init +lsm_init_hook_static_slot(struct security_hook_static_slots *hook) +{ + struct security_hook_list *pos; + struct security_static_slot *slot; + int slot_idx, slot_cnt, first_slot; + + slot_cnt = 0; + // todo: race condition if hlist modified in between the two foreach + hlist_for_each_entry_rcu (pos, hook->head, list) { + slot_cnt++; + } + + first_slot = SECURITY_STATIC_SLOT_COUNT - slot_cnt; + if (first_slot < 0) + panic("%s - No static hook slot remaining to add LSM hook.\n", + __func__); + + if (slot_cnt == 0) { + hook->first_slot = INT_MAX; + return; + } + + slot_idx = first_slot; + hlist_for_each_entry_rcu (pos, hook->head, list) { + slot = &hook->slots[slot_idx]; + __static_call_update(slot->key, slot->tramp, + pos->hook.generic_func); + slot_idx++; + } + + hook->first_slot = first_slot; +} + +static void __init lsm_init_static_slots(void) +{ + int i, hook_cnt; + struct security_hook_static_slots *hooks = + (struct security_hook_static_slots *)&security_list_static_slots; + hook_cnt = sizeof(security_list_static_slots) / + sizeof(struct security_hook_static_slots); + + for (i = 0; i < hook_cnt; i++) + lsm_init_hook_static_slot(hooks + i); +} + static void __init lsm_early_cred(struct cred *cred); static void __init lsm_early_task(struct task_struct *task); @@ -385,6 +436,7 @@ static void __init ordered_lsm_init(void) lsm_early_task(current); for (lsm = ordered_lsms; *lsm; lsm++) initialize_lsm(*lsm); + lsm_init_static_slots(); kfree(ordered_lsms); } @@ -405,6 +457,7 @@ int __init early_security_init(void) prepare_lsm(lsm); initialize_lsm(lsm); } + lsm_init_static_slots(); return 0; } @@ -495,26 +548,6 @@ static int lsm_append(const char *new, char **result) return 0; } -static inline void add_to_static_slots(struct security_static_slot *slot_list, - void *func) -{ - struct security_static_slot *slot; - - if (!slot_list || !func) - panic("%s - Incorrectly initialized hook.\n", __func__); - - for (slot = slot_list; slot < slot_list + SECURITY_STATIC_SLOT_COUNT; - slot++) { - if (!slot->key->func) { - __static_call_update(slot->key, slot->tramp, func); - break; - } - } - if (slot == slot_list + SECURITY_STATIC_SLOT_COUNT) - panic("%s - No static hook slot remaining to add LSM hook.\n", - __func__); -} - /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add @@ -531,7 +564,6 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, for (i = 0; i < count; i++) { hooks[i].lsm = lsm; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); - add_to_static_slots(hooks[i].slots, hooks[i].hook.generic_func); } /* @@ -758,16 +790,18 @@ static void __init lsm_early_task(struct task_struct *task) } while (0) #define CALL_STATIC_SLOT_INT(NUM, R, HOOK, ...) \ - R = static_call_cond_int(STATIC_SLOT(HOOK, NUM), 0)(__VA_ARGS__);\ - if (R != 0) \ - break; + case NUM: \ + R = static_call(STATIC_SLOT(HOOK, NUM))(__VA_ARGS__); \ + if (R != 0) break; \ + fallthrough; #define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ - do { \ + switch (security_list_static_slots.FUNC.first_slot) { \ SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_INT, \ RC, FUNC, __VA_ARGS__) \ - } while (0); \ + default: break; \ + } \ RC; \ }) From 6507fd3dedeae4bb25dc153b99535ae197009aa3 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Tue, 4 Aug 2020 15:15:47 +0200 Subject: [PATCH 08/15] Remove static call API extension --- arch/x86/include/asm/static_call.h | 3 --- include/linux/static_call.h | 5 ----- 2 files changed, 8 deletions(-) diff --git a/arch/x86/include/asm/static_call.h b/arch/x86/include/asm/static_call.h index 8672f1fb28663f..c37f11999d0c0f 100644 --- a/arch/x86/include/asm/static_call.h +++ b/arch/x86/include/asm/static_call.h @@ -37,7 +37,4 @@ #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \ __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; nop; nop; nop; nop") -#define ARCH_SET_STATIC_CALL_DEFAULT_VALUE(i) \ - asm("mov $" #i ",%eax\t\n") - #endif /* _ASM_STATIC_CALL_H */ diff --git a/include/linux/static_call.h b/include/linux/static_call.h index f40ad5569061fb..bfa2ba39be57e3 100644 --- a/include/linux/static_call.h +++ b/include/linux/static_call.h @@ -176,11 +176,6 @@ extern int static_call_text_reserved(void *start, void *end); #define static_call(name) __static_call(name) #define static_call_cond(name) (void)__static_call(name) -#define static_call_cond_int(name, _default) \ -({ \ - ARCH_SET_STATIC_CALL_DEFAULT_VALUE(_default); \ - __static_call(name); \ -}) #define EXPORT_STATIC_CALL(name) \ EXPORT_SYMBOL(STATIC_CALL_KEY(name)); \ From fa08676c6c0072017ca9cd6823a8bab77d661c20 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Tue, 4 Aug 2020 15:20:40 +0200 Subject: [PATCH 09/15] cleanup --- include/linux/lsm_hooks.h | 4 ++-- security/security.c | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index aacbd21eefe5b6..3fe687b57a8928 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1569,7 +1569,7 @@ struct security_hook_static_slots { }; struct security_list_static_slots { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ struct security_hook_static_slots NAME; #include "lsm_hook_defs.h" #undef LSM_HOOK @@ -1610,7 +1610,7 @@ struct lsm_blob_sizes { * care of the common case and reduces the amount of * text involved. */ -#define LSM_HOOK_INIT(HEAD, HOOK) \ +#define LSM_HOOK_INIT(HEAD, HOOK) \ { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } } extern struct security_hook_heads security_hook_heads; diff --git a/security/security.c b/security/security.c index 6a54c0eb641528..9bc32945c64c6b 100644 --- a/security/security.c +++ b/security/security.c @@ -8,7 +8,6 @@ * Copyright (C) 2016 Mellanox Technologies */ -#include "vdso/limits.h" #define pr_fmt(fmt) "LSM: " fmt #include @@ -29,8 +28,6 @@ #include #include #include -#include -#include #define MAX_LSM_EVM_XATTR 2 @@ -104,7 +101,7 @@ static __initdata struct lsm_info *exclusive; struct security_list_static_slots security_list_static_slots __lsm_ro_after_init = { -#define DEFINE_SLOT(NUM, NAME) \ +#define DEFINE_SLOT(NUM, NAME) \ (struct security_static_slot) { \ .key = &STATIC_CALL_KEY(STATIC_SLOT(NAME, NUM)), \ .tramp = &STATIC_CALL_TRAMP(STATIC_SLOT(NAME, NUM)) \ @@ -1604,9 +1601,8 @@ int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { int ret; - long mmap_p = mmap_prot(file, prot); ret = call_int_hook(mmap_file, 0, file, prot, - mmap_p, flags); + mmap_prot(file, prot), flags); if (ret) return ret; return ima_file_mmap(file, prot); From 684ade3ccec0ca33aa5e3b7f910297c28354b410 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Mon, 10 Aug 2020 15:05:28 +0200 Subject: [PATCH 10/15] Move changes from lsm_hooks.h to security.c, and use xmacro to copy the init the static calls --- include/linux/lsm_hooks.h | 44 ------------------ security/security.c | 94 ++++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 71 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 3fe687b57a8928..95b7c1d3206218 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -28,7 +28,6 @@ #include #include #include -#include /** * union security_list_options - Linux Security Module hook function list @@ -1525,7 +1524,6 @@ union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); #include "lsm_hook_defs.h" #undef LSM_HOOK - void *generic_func; }; struct security_hook_heads { @@ -1534,47 +1532,6 @@ struct security_hook_heads { #undef LSM_HOOK } __randomize_layout; -/* - * Static slots are placeholders for potential LSM hooks. - * Instead of a costly indirect call, they use static calls. - */ -#define SECURITY_STATIC_SLOT_COUNT 3 -#define SECURITY_FOREACH_STATIC_SLOT(M, ...) \ - M(0, __VA_ARGS__) \ - M(1, __VA_ARGS__) \ - M(2, __VA_ARGS__) - -/* - * Necessary information about a static - * slot to call __static_call_update - */ -struct security_static_slot { - /* static call key as defined by STATIC_CALL_KEY */ - struct static_call_key *key; - /* static call tramp as defined by STATIC_CALL_TRAMP */ - void *tramp; -}; - -/* Static slots and related information for a hook */ -struct security_hook_static_slots { - struct security_static_slot slots[SECURITY_STATIC_SLOT_COUNT]; - /* - * Index of first slot to be used. - * All slots with greater index are used. - * INT_MAX if no slot is used. - */ - int first_slot; - /* hlist corresponding to this hook */ - struct hlist_head *head; -}; - -struct security_list_static_slots { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ - struct security_hook_static_slots NAME; - #include "lsm_hook_defs.h" - #undef LSM_HOOK -} __randomize_layout; - /* * Security module hook list structure. * For use with generic list macros for common operations. @@ -1614,7 +1571,6 @@ struct lsm_blob_sizes { { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } } extern struct security_hook_heads security_hook_heads; -extern struct security_list_static_slots security_list_static_slots; extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, diff --git a/security/security.c b/security/security.c index 9bc32945c64c6b..a0a538498dbda2 100644 --- a/security/security.c +++ b/security/security.c @@ -28,6 +28,7 @@ #include #include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -36,6 +37,16 @@ #define STATIC_SLOT(HOOK, NUM) security_static_slot_##HOOK##_##NUM +/* + * Static slots are placeholders for potential LSM hooks. + * Instead of a costly indirect call, they use static calls. + */ +#define SECURITY_STATIC_SLOT_COUNT 3 +#define SECURITY_FOREACH_STATIC_SLOT(M, ...) \ + M(0, __VA_ARGS__) \ + M(1, __VA_ARGS__) \ + M(2, __VA_ARGS__) + /* * These are descriptions of the reasons that can be passed to the * security_locked_down() LSM hook. Placing this array here allows @@ -88,6 +99,37 @@ static __initconst const char * const builtin_lsm_order = CONFIG_LSM; static __initdata struct lsm_info **ordered_lsms; static __initdata struct lsm_info *exclusive; +/* + * Necessary information about a static + * slot to call __static_call_update + */ +struct security_static_slot { + /* static call key as defined by STATIC_CALL_KEY */ + struct static_call_key *key; + /* static call tramp as defined by STATIC_CALL_TRAMP */ + void *tramp; +}; + +/* Table of the static calls for each LSM hook */ +struct security_list_static_slots { + #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + struct security_static_slot NAME[SECURITY_STATIC_SLOT_COUNT]; + #include + #undef LSM_HOOK +} __randomize_layout; + +/* + * Index of the first used static call for each LSM hook + * in the corresponding security_list_static_slots table. + * All calls with greater indices are used, INT_MAX if no call is used. + */ +struct security_first_static_slot_idx { + #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + int NAME; + #include + #undef LSM_HOOK +} __randomize_layout; + /* Create the static slots for each LSM hook */ #define CREATE_STATIC_SLOT(NUM, NAME, RET, ...) \ DEFINE_STATIC_CALL_NULL(STATIC_SLOT(NAME, NUM), \ @@ -99,8 +141,8 @@ static __initdata struct lsm_info *exclusive; #undef LSM_HOOK #undef CREATE_STATIC -struct security_list_static_slots security_list_static_slots -__lsm_ro_after_init = { +static struct security_list_static_slots security_list_static_slots +__initdata = { #define DEFINE_SLOT(NUM, NAME) \ (struct security_static_slot) { \ .key = &STATIC_CALL_KEY(STATIC_SLOT(NAME, NUM)), \ @@ -108,17 +150,16 @@ __lsm_ro_after_init = { }, #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ .NAME = { \ - .slots = { \ - SECURITY_FOREACH_STATIC_SLOT(DEFINE_SLOT, NAME) \ - }, \ - .first_slot = INT_MAX, \ - .head = &security_hook_heads.NAME \ + SECURITY_FOREACH_STATIC_SLOT(DEFINE_SLOT, NAME) \ }, #include #undef LSM_HOOK #undef DEFINE_SLOT }; +static struct security_first_static_slot_idx security_first_static_slot_idx + __lsm_ro_after_init = {}; + static __initdata bool debug; #define init_debug(...) \ do { \ @@ -340,16 +381,17 @@ static void __init ordered_lsm_parse(const char *order, const char *origin) kfree(sep); } -static void __init -lsm_init_hook_static_slot(struct security_hook_static_slots *hook) +static void __init lsm_init_hook_static_slot(struct security_static_slot *slots, + struct hlist_head *head, + int *first_slot_idx) { struct security_hook_list *pos; struct security_static_slot *slot; - int slot_idx, slot_cnt, first_slot; + int slot_cnt, first_slot; slot_cnt = 0; // todo: race condition if hlist modified in between the two foreach - hlist_for_each_entry_rcu (pos, hook->head, list) { + hlist_for_each_entry_rcu (pos, head, list) { slot_cnt++; } @@ -359,31 +401,29 @@ lsm_init_hook_static_slot(struct security_hook_static_slots *hook) __func__); if (slot_cnt == 0) { - hook->first_slot = INT_MAX; + *first_slot_idx = INT_MAX; return; } - slot_idx = first_slot; - hlist_for_each_entry_rcu (pos, hook->head, list) { - slot = &hook->slots[slot_idx]; + slot = slots + first_slot; + hlist_for_each_entry_rcu (pos, head, list) { __static_call_update(slot->key, slot->tramp, - pos->hook.generic_func); - slot_idx++; + (void *) &pos->hook); + slot++; } - hook->first_slot = first_slot; + // write only after the static calls are filled + *first_slot_idx = first_slot; } static void __init lsm_init_static_slots(void) { - int i, hook_cnt; - struct security_hook_static_slots *hooks = - (struct security_hook_static_slots *)&security_list_static_slots; - hook_cnt = sizeof(security_list_static_slots) / - sizeof(struct security_hook_static_slots); - - for (i = 0; i < hook_cnt; i++) - lsm_init_hook_static_slot(hooks + i); +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + lsm_init_hook_static_slot(security_list_static_slots.NAME, \ + &security_hook_heads.NAME, \ + &security_first_static_slot_idx.NAME); +#include +#undef LSM_HOOK } static void __init lsm_early_cred(struct cred *cred); @@ -794,7 +834,7 @@ static void __init lsm_early_task(struct task_struct *task) #define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ - switch (security_list_static_slots.FUNC.first_slot) { \ + switch (security_first_static_slot_idx.FUNC) { \ SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_INT, \ RC, FUNC, __VA_ARGS__) \ default: break; \ From 43f3d2154123743bdbb95a37372a697ab3326eaa Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Mon, 10 Aug 2020 16:48:46 +0200 Subject: [PATCH 11/15] Move changes from lsm_hooks.h to security.c, and use xmacroaddress comments --- security/security.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/security/security.c b/security/security.c index a0a538498dbda2..3ea1b8a0309c2f 100644 --- a/security/security.c +++ b/security/security.c @@ -139,7 +139,7 @@ struct security_first_static_slot_idx { SECURITY_FOREACH_STATIC_SLOT(CREATE_STATIC_SLOT, NAME, RET, __VA_ARGS__) #include #undef LSM_HOOK -#undef CREATE_STATIC +#undef CREATE_STATIC_SLOT static struct security_list_static_slots security_list_static_slots __initdata = { @@ -817,16 +817,18 @@ static void __init lsm_early_task(struct task_struct *task) * call_int_hook: * This is a hook that returns a value. */ -#define CALL_STATIC_SLOT_VOID(NUM, HOOK, ...) \ +#define __CASE_CALL_STATIC_VOID(NUM, HOOK, ...) \ static_call_cond(STATIC_SLOT(HOOK, NUM))(__VA_ARGS__); -#define call_void_hook(FUNC, ...) \ - do { \ - SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_VOID, \ - FUNC, __VA_ARGS__) \ - } while (0) +#define call_void_hook(FUNC, ...) do { \ + switch (security_first_static_slot_idx.FUNC) { \ + SECURITY_FOREACH_STATIC_SLOT(__CASE_CALL_STATIC_VOID, \ + FUNC, __VA_ARGS__) \ + default: break; \ + } \ +} while (0) -#define CALL_STATIC_SLOT_INT(NUM, R, HOOK, ...) \ +#define __CASE_CALL_STATIC_INT(NUM, R, HOOK, ...) \ case NUM: \ R = static_call(STATIC_SLOT(HOOK, NUM))(__VA_ARGS__); \ if (R != 0) break; \ @@ -835,7 +837,7 @@ static void __init lsm_early_task(struct task_struct *task) #define call_int_hook(FUNC, IRC, ...) ({ \ int RC = IRC; \ switch (security_first_static_slot_idx.FUNC) { \ - SECURITY_FOREACH_STATIC_SLOT(CALL_STATIC_SLOT_INT, \ + SECURITY_FOREACH_STATIC_SLOT(__CASE_CALL_STATIC_INT, \ RC, FUNC, __VA_ARGS__) \ default: break; \ } \ From 5d9f58b0c73faf462f95322390438cb18c970fad Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Thu, 13 Aug 2020 15:32:08 +0200 Subject: [PATCH 12/15] fix call void hook --- security/security.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/security/security.c b/security/security.c index 3ea1b8a0309c2f..9d1533bcb2c64f 100644 --- a/security/security.c +++ b/security/security.c @@ -818,7 +818,9 @@ static void __init lsm_early_task(struct task_struct *task) * This is a hook that returns a value. */ #define __CASE_CALL_STATIC_VOID(NUM, HOOK, ...) \ - static_call_cond(STATIC_SLOT(HOOK, NUM))(__VA_ARGS__); + case NUM: \ + static_call_cond(STATIC_SLOT(HOOK, NUM))(__VA_ARGS__); \ + fallthrough; #define call_void_hook(FUNC, ...) do { \ switch (security_first_static_slot_idx.FUNC) { \ From d243369273fa86561c5653439af80f7e594cfb27 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Thu, 13 Aug 2020 18:00:41 +0200 Subject: [PATCH 13/15] fix lsm_init_hook_static_slot --- include/linux/lsm_hooks.h | 1 + security/security.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 95b7c1d3206218..d11e116b588e7c 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1524,6 +1524,7 @@ union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); #include "lsm_hook_defs.h" #undef LSM_HOOK + void *generic_func; }; struct security_hook_heads { diff --git a/security/security.c b/security/security.c index 9d1533bcb2c64f..848a076c469e88 100644 --- a/security/security.c +++ b/security/security.c @@ -408,7 +408,7 @@ static void __init lsm_init_hook_static_slot(struct security_static_slot *slots, slot = slots + first_slot; hlist_for_each_entry_rcu (pos, head, list) { __static_call_update(slot->key, slot->tramp, - (void *) &pos->hook); + pos->hook.generic_func); slot++; } From 5f492ae79b688764f8059ac1e019ed38edd64283 Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Thu, 13 Aug 2020 18:17:26 +0200 Subject: [PATCH 14/15] add loop_unrolling.h --- include/linux/loop_unrolling.h | 116 +++++++++++++++++++++++++++++++++ security/security.c | 7 +- 2 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 include/linux/loop_unrolling.h diff --git a/include/linux/loop_unrolling.h b/include/linux/loop_unrolling.h new file mode 100644 index 00000000000000..b8bde6fa82def9 --- /dev/null +++ b/include/linux/loop_unrolling.h @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (C) 2020 Google LLC. + */ + +#ifndef __LINUX_LOOP_UNROLLING_H +#define __LINUX_LOOP_UNROLLING_H + +/* + * Call MACRO N times. + * N must be an integer constant no greater than M_MAX_LOOP_UNROLLING + * MACRO should take as first argument the index and then + * the same __VA_ARGS__ + * Essenially, this will expand to: + * MACRO(0, ...) + * MACRO(1, ...) + * MACRO(2, ...) + * ... + */ +#define M_LOOP_UNROLLING(N, MACRO, ...) \ + _M_LOOP_UNROLLING(N, MACRO, __VA_ARGS__) + +#define M_MAX_LOOP_UNROLLING (20) + +// Intermediate macros to expand N if it is itself a macro +#define _M_LOOP_UNROLLING(N, MACRO, ...) \ + __M_LOOP_UNROLLING(N, MACRO, __VA_ARGS__) + +#define __M_LOOP_UNROLLING(N, MACRO, ...) \ + __M_LOOP_UNROLLING_##N(MACRO, __VA_ARGS__) + + +#define __M_LOOP_UNROLLING_0(MACRO, ...) + +#define __M_LOOP_UNROLLING_1(MACRO, ...) \ + __M_LOOP_UNROLLING_0(MACRO, __VA_ARGS__) \ + MACRO(0, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_2(MACRO, ...) \ + __M_LOOP_UNROLLING_1(MACRO, __VA_ARGS__) \ + MACRO(1, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_3(MACRO, ...) \ + __M_LOOP_UNROLLING_2(MACRO, __VA_ARGS__) \ + MACRO(2, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_4(MACRO, ...) \ + __M_LOOP_UNROLLING_3(MACRO, __VA_ARGS__) \ + MACRO(3, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_5(MACRO, ...) \ + __M_LOOP_UNROLLING_4(MACRO, __VA_ARGS__) \ + MACRO(4, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_6(MACRO, ...) \ + __M_LOOP_UNROLLING_5(MACRO, __VA_ARGS__) \ + MACRO(5, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_7(MACRO, ...) \ + __M_LOOP_UNROLLING_6(MACRO, __VA_ARGS__) \ + MACRO(6, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_8(MACRO, ...) \ + __M_LOOP_UNROLLING_7(MACRO, __VA_ARGS__) \ + MACRO(7, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_9(MACRO, ...) \ + __M_LOOP_UNROLLING_8(MACRO, __VA_ARGS__) \ + MACRO(8, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_10(MACRO, ...) \ + __M_LOOP_UNROLLING_9(MACRO, __VA_ARGS__) \ + MACRO(9, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_11(MACRO, ...) \ + __M_LOOP_UNROLLING_10(MACRO, __VA_ARGS__) \ + MACRO(10, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_12(MACRO, ...) \ + __M_LOOP_UNROLLING_11(MACRO, __VA_ARGS__) \ + MACRO(11, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_13(MACRO, ...) \ + __M_LOOP_UNROLLING_12(MACRO, __VA_ARGS__) \ + MACRO(12, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_14(MACRO, ...) \ + __M_LOOP_UNROLLING_13(MACRO, __VA_ARGS__) \ + MACRO(13, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_15(MACRO, ...) \ + __M_LOOP_UNROLLING_14(MACRO, __VA_ARGS__) \ + MACRO(14, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_16(MACRO, ...) \ + __M_LOOP_UNROLLING_15(MACRO, __VA_ARGS__) \ + MACRO(15, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_17(MACRO, ...) \ + __M_LOOP_UNROLLING_16(MACRO, __VA_ARGS__) \ + MACRO(16, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_18(MACRO, ...) \ + __M_LOOP_UNROLLING_17(MACRO, __VA_ARGS__) \ + MACRO(17, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_19(MACRO, ...) \ + __M_LOOP_UNROLLING_18(MACRO, __VA_ARGS__) \ + MACRO(18, __VA_ARGS__) + +#define __M_LOOP_UNROLLING_20(MACRO, ...) \ + __M_LOOP_UNROLLING_19(MACRO, __VA_ARGS__) \ + MACRO(19, __VA_ARGS__) + +#endif /* __LINUX_LOOP_UNROLLING_H */ \ No newline at end of file diff --git a/security/security.c b/security/security.c index 848a076c469e88..9b8479e399383c 100644 --- a/security/security.c +++ b/security/security.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #define MAX_LSM_EVM_XATTR 2 @@ -42,10 +44,9 @@ * Instead of a costly indirect call, they use static calls. */ #define SECURITY_STATIC_SLOT_COUNT 3 +static_assert(SECURITY_STATIC_SLOT_COUNT <= M_MAX_LOOP_UNROLLING); #define SECURITY_FOREACH_STATIC_SLOT(M, ...) \ - M(0, __VA_ARGS__) \ - M(1, __VA_ARGS__) \ - M(2, __VA_ARGS__) + M_LOOP_UNROLLING(SECURITY_STATIC_SLOT_COUNT, M, __VA_ARGS__) /* * These are descriptions of the reasons that can be passed to the From 7eef88cf9378575515c2554809c8b2051e83d6ff Mon Sep 17 00:00:00 2001 From: Paul Renauld Date: Fri, 14 Aug 2020 15:37:07 +0200 Subject: [PATCH 15/15] address comments --- include/linux/loop_unrolling.h | 98 +++++++++++++++++----------------- security/security.c | 7 ++- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/include/linux/loop_unrolling.h b/include/linux/loop_unrolling.h index b8bde6fa82def9..dca96140f2230f 100644 --- a/include/linux/loop_unrolling.h +++ b/include/linux/loop_unrolling.h @@ -9,7 +9,7 @@ /* * Call MACRO N times. - * N must be an integer constant no greater than M_MAX_LOOP_UNROLLING + * N must be an integer constant no greater than MAX_UNROLL_MACRO_LOOP * MACRO should take as first argument the index and then * the same __VA_ARGS__ * Essenially, this will expand to: @@ -18,99 +18,99 @@ * MACRO(2, ...) * ... */ -#define M_LOOP_UNROLLING(N, MACRO, ...) \ - _M_LOOP_UNROLLING(N, MACRO, __VA_ARGS__) +#define UNROLL_MACRO_LOOP(N, MACRO, ...) \ + _UNROLL_MACRO_LOOP(N, MACRO, __VA_ARGS__) -#define M_MAX_LOOP_UNROLLING (20) +#define MAX_UNROLL_MACRO_LOOP (20) // Intermediate macros to expand N if it is itself a macro -#define _M_LOOP_UNROLLING(N, MACRO, ...) \ - __M_LOOP_UNROLLING(N, MACRO, __VA_ARGS__) +#define _UNROLL_MACRO_LOOP(N, MACRO, ...) \ + __UNROLL_MACRO_LOOP(N, MACRO, __VA_ARGS__) -#define __M_LOOP_UNROLLING(N, MACRO, ...) \ - __M_LOOP_UNROLLING_##N(MACRO, __VA_ARGS__) +#define __UNROLL_MACRO_LOOP(N, MACRO, ...) \ + __UNROLL_MACRO_LOOP_##N(MACRO, __VA_ARGS__) -#define __M_LOOP_UNROLLING_0(MACRO, ...) +#define __UNROLL_MACRO_LOOP_0(MACRO, ...) -#define __M_LOOP_UNROLLING_1(MACRO, ...) \ - __M_LOOP_UNROLLING_0(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_1(MACRO, ...) \ + __UNROLL_MACRO_LOOP_0(MACRO, __VA_ARGS__) \ MACRO(0, __VA_ARGS__) -#define __M_LOOP_UNROLLING_2(MACRO, ...) \ - __M_LOOP_UNROLLING_1(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_2(MACRO, ...) \ + __UNROLL_MACRO_LOOP_1(MACRO, __VA_ARGS__) \ MACRO(1, __VA_ARGS__) -#define __M_LOOP_UNROLLING_3(MACRO, ...) \ - __M_LOOP_UNROLLING_2(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_3(MACRO, ...) \ + __UNROLL_MACRO_LOOP_2(MACRO, __VA_ARGS__) \ MACRO(2, __VA_ARGS__) -#define __M_LOOP_UNROLLING_4(MACRO, ...) \ - __M_LOOP_UNROLLING_3(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_4(MACRO, ...) \ + __UNROLL_MACRO_LOOP_3(MACRO, __VA_ARGS__) \ MACRO(3, __VA_ARGS__) -#define __M_LOOP_UNROLLING_5(MACRO, ...) \ - __M_LOOP_UNROLLING_4(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_5(MACRO, ...) \ + __UNROLL_MACRO_LOOP_4(MACRO, __VA_ARGS__) \ MACRO(4, __VA_ARGS__) -#define __M_LOOP_UNROLLING_6(MACRO, ...) \ - __M_LOOP_UNROLLING_5(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_6(MACRO, ...) \ + __UNROLL_MACRO_LOOP_5(MACRO, __VA_ARGS__) \ MACRO(5, __VA_ARGS__) -#define __M_LOOP_UNROLLING_7(MACRO, ...) \ - __M_LOOP_UNROLLING_6(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_7(MACRO, ...) \ + __UNROLL_MACRO_LOOP_6(MACRO, __VA_ARGS__) \ MACRO(6, __VA_ARGS__) -#define __M_LOOP_UNROLLING_8(MACRO, ...) \ - __M_LOOP_UNROLLING_7(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_8(MACRO, ...) \ + __UNROLL_MACRO_LOOP_7(MACRO, __VA_ARGS__) \ MACRO(7, __VA_ARGS__) -#define __M_LOOP_UNROLLING_9(MACRO, ...) \ - __M_LOOP_UNROLLING_8(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_9(MACRO, ...) \ + __UNROLL_MACRO_LOOP_8(MACRO, __VA_ARGS__) \ MACRO(8, __VA_ARGS__) -#define __M_LOOP_UNROLLING_10(MACRO, ...) \ - __M_LOOP_UNROLLING_9(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_10(MACRO, ...) \ + __UNROLL_MACRO_LOOP_9(MACRO, __VA_ARGS__) \ MACRO(9, __VA_ARGS__) -#define __M_LOOP_UNROLLING_11(MACRO, ...) \ - __M_LOOP_UNROLLING_10(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_11(MACRO, ...) \ + __UNROLL_MACRO_LOOP_10(MACRO, __VA_ARGS__) \ MACRO(10, __VA_ARGS__) -#define __M_LOOP_UNROLLING_12(MACRO, ...) \ - __M_LOOP_UNROLLING_11(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_12(MACRO, ...) \ + __UNROLL_MACRO_LOOP_11(MACRO, __VA_ARGS__) \ MACRO(11, __VA_ARGS__) -#define __M_LOOP_UNROLLING_13(MACRO, ...) \ - __M_LOOP_UNROLLING_12(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_13(MACRO, ...) \ + __UNROLL_MACRO_LOOP_12(MACRO, __VA_ARGS__) \ MACRO(12, __VA_ARGS__) -#define __M_LOOP_UNROLLING_14(MACRO, ...) \ - __M_LOOP_UNROLLING_13(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_14(MACRO, ...) \ + __UNROLL_MACRO_LOOP_13(MACRO, __VA_ARGS__) \ MACRO(13, __VA_ARGS__) -#define __M_LOOP_UNROLLING_15(MACRO, ...) \ - __M_LOOP_UNROLLING_14(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_15(MACRO, ...) \ + __UNROLL_MACRO_LOOP_14(MACRO, __VA_ARGS__) \ MACRO(14, __VA_ARGS__) -#define __M_LOOP_UNROLLING_16(MACRO, ...) \ - __M_LOOP_UNROLLING_15(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_16(MACRO, ...) \ + __UNROLL_MACRO_LOOP_15(MACRO, __VA_ARGS__) \ MACRO(15, __VA_ARGS__) -#define __M_LOOP_UNROLLING_17(MACRO, ...) \ - __M_LOOP_UNROLLING_16(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_17(MACRO, ...) \ + __UNROLL_MACRO_LOOP_16(MACRO, __VA_ARGS__) \ MACRO(16, __VA_ARGS__) -#define __M_LOOP_UNROLLING_18(MACRO, ...) \ - __M_LOOP_UNROLLING_17(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_18(MACRO, ...) \ + __UNROLL_MACRO_LOOP_17(MACRO, __VA_ARGS__) \ MACRO(17, __VA_ARGS__) -#define __M_LOOP_UNROLLING_19(MACRO, ...) \ - __M_LOOP_UNROLLING_18(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_19(MACRO, ...) \ + __UNROLL_MACRO_LOOP_18(MACRO, __VA_ARGS__) \ MACRO(18, __VA_ARGS__) -#define __M_LOOP_UNROLLING_20(MACRO, ...) \ - __M_LOOP_UNROLLING_19(MACRO, __VA_ARGS__) \ +#define __UNROLL_MACRO_LOOP_20(MACRO, ...) \ + __UNROLL_MACRO_LOOP_19(MACRO, __VA_ARGS__) \ MACRO(19, __VA_ARGS__) #endif /* __LINUX_LOOP_UNROLLING_H */ \ No newline at end of file diff --git a/security/security.c b/security/security.c index 9b8479e399383c..a53e57b26e8788 100644 --- a/security/security.c +++ b/security/security.c @@ -43,10 +43,10 @@ * Static slots are placeholders for potential LSM hooks. * Instead of a costly indirect call, they use static calls. */ -#define SECURITY_STATIC_SLOT_COUNT 3 -static_assert(SECURITY_STATIC_SLOT_COUNT <= M_MAX_LOOP_UNROLLING); +#define SECURITY_STATIC_SLOT_COUNT 11 +static_assert(SECURITY_STATIC_SLOT_COUNT <= MAX_UNROLL_MACRO_LOOP); #define SECURITY_FOREACH_STATIC_SLOT(M, ...) \ - M_LOOP_UNROLLING(SECURITY_STATIC_SLOT_COUNT, M, __VA_ARGS__) + UNROLL_MACRO_LOOP(SECURITY_STATIC_SLOT_COUNT, M, __VA_ARGS__) /* * These are descriptions of the reasons that can be passed to the @@ -391,7 +391,6 @@ static void __init lsm_init_hook_static_slot(struct security_static_slot *slots, int slot_cnt, first_slot; slot_cnt = 0; - // todo: race condition if hlist modified in between the two foreach hlist_for_each_entry_rcu (pos, head, list) { slot_cnt++; }