diff options
Diffstat (limited to 'security/loadpin/loadpin.c')
-rw-r--r-- | security/loadpin/loadpin.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index 79131efa9634..81519c804888 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c | |||
@@ -37,6 +37,8 @@ static void report_load(const char *origin, struct file *file, char *operation) | |||
37 | } | 37 | } |
38 | 38 | ||
39 | static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE); | 39 | static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE); |
40 | static char *exclude_read_files[READING_MAX_ID]; | ||
41 | static int ignore_read_file_id[READING_MAX_ID] __ro_after_init; | ||
40 | static struct super_block *pinned_root; | 42 | static struct super_block *pinned_root; |
41 | static DEFINE_SPINLOCK(pinned_root_spinlock); | 43 | static DEFINE_SPINLOCK(pinned_root_spinlock); |
42 | 44 | ||
@@ -121,6 +123,13 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id) | |||
121 | struct super_block *load_root; | 123 | struct super_block *load_root; |
122 | const char *origin = kernel_read_file_id_str(id); | 124 | const char *origin = kernel_read_file_id_str(id); |
123 | 125 | ||
126 | /* If the file id is excluded, ignore the pinning. */ | ||
127 | if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) && | ||
128 | ignore_read_file_id[id]) { | ||
129 | report_load(origin, file, "pinning-excluded"); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
124 | /* This handles the older init_module API that has a NULL file. */ | 133 | /* This handles the older init_module API that has a NULL file. */ |
125 | if (!file) { | 134 | if (!file) { |
126 | if (!enforce) { | 135 | if (!enforce) { |
@@ -179,10 +188,47 @@ static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { | |||
179 | LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), | 188 | LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), |
180 | }; | 189 | }; |
181 | 190 | ||
191 | static void __init parse_exclude(void) | ||
192 | { | ||
193 | int i, j; | ||
194 | char *cur; | ||
195 | |||
196 | /* | ||
197 | * Make sure all the arrays stay within expected sizes. This | ||
198 | * is slightly weird because kernel_read_file_str[] includes | ||
199 | * READING_MAX_ID, which isn't actually meaningful here. | ||
200 | */ | ||
201 | BUILD_BUG_ON(ARRAY_SIZE(exclude_read_files) != | ||
202 | ARRAY_SIZE(ignore_read_file_id)); | ||
203 | BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) < | ||
204 | ARRAY_SIZE(ignore_read_file_id)); | ||
205 | |||
206 | for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) { | ||
207 | cur = exclude_read_files[i]; | ||
208 | if (!cur) | ||
209 | break; | ||
210 | if (*cur == '\0') | ||
211 | continue; | ||
212 | |||
213 | for (j = 0; j < ARRAY_SIZE(ignore_read_file_id); j++) { | ||
214 | if (strcmp(cur, kernel_read_file_str[j]) == 0) { | ||
215 | pr_info("excluding: %s\n", | ||
216 | kernel_read_file_str[j]); | ||
217 | ignore_read_file_id[j] = 1; | ||
218 | /* | ||
219 | * Can not break, because one read_file_str | ||
220 | * may map to more than on read_file_id. | ||
221 | */ | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | |||
182 | static int __init loadpin_init(void) | 227 | static int __init loadpin_init(void) |
183 | { | 228 | { |
184 | pr_info("ready to pin (currently %senforcing)\n", | 229 | pr_info("ready to pin (currently %senforcing)\n", |
185 | enforce ? "" : "not "); | 230 | enforce ? "" : "not "); |
231 | parse_exclude(); | ||
186 | security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); | 232 | security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); |
187 | return 0; | 233 | return 0; |
188 | } | 234 | } |
@@ -195,3 +241,5 @@ DEFINE_LSM(loadpin) = { | |||
195 | /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ | 241 | /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ |
196 | module_param(enforce, int, 0); | 242 | module_param(enforce, int, 0); |
197 | MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); | 243 | MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); |
244 | module_param_array_named(exclude, exclude_read_files, charp, NULL, 0); | ||
245 | MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types"); | ||