diff options
author | Kees Cook <keescook@chromium.org> | 2018-09-19 19:58:31 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2019-01-08 16:18:42 -0500 |
commit | 2d4d51198c730adbbc5e071b18c84e5d0d2d65df (patch) | |
tree | f3c9c1306ab7f7feb862863b03c3c7c4be9dc35e /security/security.c | |
parent | f4941d75b9cba5e1fae1aebe0139dcca0703a294 (diff) |
LSM: Build ordered list of LSMs to initialize
This constructs an ordered list of LSMs to initialize, using a hard-coded
list of only "integrity": minor LSMs continue to have direct hook calls,
and major LSMs continue to initialize separately.
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/security.c')
-rw-r--r-- | security/security.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/security/security.c b/security/security.c index c900d7a1441a..3a277fbf6023 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -37,6 +37,9 @@ | |||
37 | /* Maximum number of letters for an LSM name string */ | 37 | /* Maximum number of letters for an LSM name string */ |
38 | #define SECURITY_NAME_MAX 10 | 38 | #define SECURITY_NAME_MAX 10 |
39 | 39 | ||
40 | /* How many LSMs were built into the kernel? */ | ||
41 | #define LSM_COUNT (__end_lsm_info - __start_lsm_info) | ||
42 | |||
40 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; | 43 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; |
41 | static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); | 44 | static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); |
42 | 45 | ||
@@ -45,6 +48,9 @@ char *lsm_names; | |||
45 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | 48 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = |
46 | CONFIG_DEFAULT_SECURITY; | 49 | CONFIG_DEFAULT_SECURITY; |
47 | 50 | ||
51 | /* Ordered list of LSMs to initialize. */ | ||
52 | static __initdata struct lsm_info **ordered_lsms; | ||
53 | |||
48 | static __initdata bool debug; | 54 | static __initdata bool debug; |
49 | #define init_debug(...) \ | 55 | #define init_debug(...) \ |
50 | do { \ | 56 | do { \ |
@@ -85,6 +91,34 @@ static void __init set_enabled(struct lsm_info *lsm, bool enabled) | |||
85 | } | 91 | } |
86 | } | 92 | } |
87 | 93 | ||
94 | /* Is an LSM already listed in the ordered LSMs list? */ | ||
95 | static bool __init exists_ordered_lsm(struct lsm_info *lsm) | ||
96 | { | ||
97 | struct lsm_info **check; | ||
98 | |||
99 | for (check = ordered_lsms; *check; check++) | ||
100 | if (*check == lsm) | ||
101 | return true; | ||
102 | |||
103 | return false; | ||
104 | } | ||
105 | |||
106 | /* Append an LSM to the list of ordered LSMs to initialize. */ | ||
107 | static int last_lsm __initdata; | ||
108 | static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from) | ||
109 | { | ||
110 | /* Ignore duplicate selections. */ | ||
111 | if (exists_ordered_lsm(lsm)) | ||
112 | return; | ||
113 | |||
114 | if (WARN(last_lsm == LSM_COUNT, "%s: out of LSM slots!?\n", from)) | ||
115 | return; | ||
116 | |||
117 | ordered_lsms[last_lsm++] = lsm; | ||
118 | init_debug("%s ordering: %s (%sabled)\n", from, lsm->name, | ||
119 | is_enabled(lsm) ? "en" : "dis"); | ||
120 | } | ||
121 | |||
88 | /* Is an LSM allowed to be initialized? */ | 122 | /* Is an LSM allowed to be initialized? */ |
89 | static bool __init lsm_allowed(struct lsm_info *lsm) | 123 | static bool __init lsm_allowed(struct lsm_info *lsm) |
90 | { | 124 | { |
@@ -121,18 +155,32 @@ static void __init maybe_initialize_lsm(struct lsm_info *lsm) | |||
121 | } | 155 | } |
122 | } | 156 | } |
123 | 157 | ||
124 | static void __init ordered_lsm_init(void) | 158 | /* Populate ordered LSMs list from single LSM name. */ |
159 | static void __init ordered_lsm_parse(const char *order, const char *origin) | ||
125 | { | 160 | { |
126 | struct lsm_info *lsm; | 161 | struct lsm_info *lsm; |
127 | 162 | ||
128 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | 163 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { |
129 | if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0) | 164 | if (strcmp(lsm->name, order) == 0) |
130 | continue; | 165 | append_ordered_lsm(lsm, origin); |
131 | |||
132 | maybe_initialize_lsm(lsm); | ||
133 | } | 166 | } |
134 | } | 167 | } |
135 | 168 | ||
169 | static void __init ordered_lsm_init(void) | ||
170 | { | ||
171 | struct lsm_info **lsm; | ||
172 | |||
173 | ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms), | ||
174 | GFP_KERNEL); | ||
175 | |||
176 | ordered_lsm_parse("integrity", "builtin"); | ||
177 | |||
178 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
179 | maybe_initialize_lsm(*lsm); | ||
180 | |||
181 | kfree(ordered_lsms); | ||
182 | } | ||
183 | |||
136 | static void __init major_lsm_init(void) | 184 | static void __init major_lsm_init(void) |
137 | { | 185 | { |
138 | struct lsm_info *lsm; | 186 | struct lsm_info *lsm; |