summaryrefslogtreecommitdiffstats
path: root/security/security.c
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2018-09-14 02:17:50 -0400
committerKees Cook <keescook@chromium.org>2019-01-08 16:18:42 -0500
commitf4941d75b9cba5e1fae1aebe0139dcca0703a294 (patch)
treefca97d9b39b5291c138795b7e6262faba2dbec5b /security/security.c
parentc5459b829b716dafd226ad270f25c9a3050f7586 (diff)
LSM: Lift LSM selection out of individual LSMs
As a prerequisite to adjusting LSM selection logic in the future, this moves the selection logic up out of the individual major LSMs, making their init functions only run when actually enabled. This considers all LSMs enabled by default unless they specified an external "enable" variable. Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/security.c')
-rw-r--r--security/security.c102
1 files changed, 71 insertions, 31 deletions
diff --git a/security/security.c b/security/security.c
index 6bc591f77b1a..c900d7a1441a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -52,33 +52,96 @@ static __initdata bool debug;
52 pr_info(__VA_ARGS__); \ 52 pr_info(__VA_ARGS__); \
53 } while (0) 53 } while (0)
54 54
55static bool __init is_enabled(struct lsm_info *lsm)
56{
57 if (!lsm->enabled || *lsm->enabled)
58 return true;
59
60 return false;
61}
62
63/* Mark an LSM's enabled flag. */
64static int lsm_enabled_true __initdata = 1;
65static int lsm_enabled_false __initdata = 0;
66static void __init set_enabled(struct lsm_info *lsm, bool enabled)
67{
68 /*
69 * When an LSM hasn't configured an enable variable, we can use
70 * a hard-coded location for storing the default enabled state.
71 */
72 if (!lsm->enabled) {
73 if (enabled)
74 lsm->enabled = &lsm_enabled_true;
75 else
76 lsm->enabled = &lsm_enabled_false;
77 } else if (lsm->enabled == &lsm_enabled_true) {
78 if (!enabled)
79 lsm->enabled = &lsm_enabled_false;
80 } else if (lsm->enabled == &lsm_enabled_false) {
81 if (enabled)
82 lsm->enabled = &lsm_enabled_true;
83 } else {
84 *lsm->enabled = enabled;
85 }
86}
87
88/* Is an LSM allowed to be initialized? */
89static bool __init lsm_allowed(struct lsm_info *lsm)
90{
91 /* Skip if the LSM is disabled. */
92 if (!is_enabled(lsm))
93 return false;
94
95 /* Skip major-specific checks if not a major LSM. */
96 if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
97 return true;
98
99 /* Disabled if this LSM isn't the chosen one. */
100 if (strcmp(lsm->name, chosen_lsm) != 0)
101 return false;
102
103 return true;
104}
105
106/* Check if LSM should be initialized. */
107static void __init maybe_initialize_lsm(struct lsm_info *lsm)
108{
109 int enabled = lsm_allowed(lsm);
110
111 /* Record enablement (to handle any following exclusive LSMs). */
112 set_enabled(lsm, enabled);
113
114 /* If selected, initialize the LSM. */
115 if (enabled) {
116 int ret;
117
118 init_debug("initializing %s\n", lsm->name);
119 ret = lsm->init();
120 WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
121 }
122}
123
55static void __init ordered_lsm_init(void) 124static void __init ordered_lsm_init(void)
56{ 125{
57 struct lsm_info *lsm; 126 struct lsm_info *lsm;
58 int ret;
59 127
60 for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 128 for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
61 if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0) 129 if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0)
62 continue; 130 continue;
63 131
64 init_debug("initializing %s\n", lsm->name); 132 maybe_initialize_lsm(lsm);
65 ret = lsm->init();
66 WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
67 } 133 }
68} 134}
69 135
70static void __init major_lsm_init(void) 136static void __init major_lsm_init(void)
71{ 137{
72 struct lsm_info *lsm; 138 struct lsm_info *lsm;
73 int ret;
74 139
75 for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 140 for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
76 if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0) 141 if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
77 continue; 142 continue;
78 143
79 init_debug("initializing %s\n", lsm->name); 144 maybe_initialize_lsm(lsm);
80 ret = lsm->init();
81 WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
82 } 145 }
83} 146}
84 147
@@ -169,29 +232,6 @@ static int lsm_append(char *new, char **result)
169} 232}
170 233
171/** 234/**
172 * security_module_enable - Load given security module on boot ?
173 * @module: the name of the module
174 *
175 * Each LSM must pass this method before registering its own operations
176 * to avoid security registration races. This method may also be used
177 * to check if your LSM is currently loaded during kernel initialization.
178 *
179 * Returns:
180 *
181 * true if:
182 *
183 * - The passed LSM is the one chosen by user at boot time,
184 * - or the passed LSM is configured as the default and the user did not
185 * choose an alternate LSM at boot time.
186 *
187 * Otherwise, return false.
188 */
189int __init security_module_enable(const char *module)
190{
191 return !strcmp(module, chosen_lsm);
192}
193
194/**
195 * security_add_hooks - Add a modules hooks to the hook lists. 235 * security_add_hooks - Add a modules hooks to the hook lists.
196 * @hooks: the hooks to add 236 * @hooks: the hooks to add
197 * @count: the number of hooks to add 237 * @count: the number of hooks to add