summaryrefslogtreecommitdiffstats
path: root/security/loadpin/loadpin.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/loadpin/loadpin.c')
-rw-r--r--security/loadpin/loadpin.c48
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
39static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE); 39static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE);
40static char *exclude_read_files[READING_MAX_ID];
41static int ignore_read_file_id[READING_MAX_ID] __ro_after_init;
40static struct super_block *pinned_root; 42static struct super_block *pinned_root;
41static DEFINE_SPINLOCK(pinned_root_spinlock); 43static 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
191static 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
182static int __init loadpin_init(void) 227static 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). */
196module_param(enforce, int, 0); 242module_param(enforce, int, 0);
197MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); 243MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");
244module_param_array_named(exclude, exclude_read_files, charp, NULL, 0);
245MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types");