loadpin.c (ecb41832bd2a7a3f8ac93527cec5e51e3827daed) loadpin.c (eec4844fae7c033a0c1fc1eb3b8517aeb8b6cc49)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Module and Firmware Pinning Security Module
4 *
5 * Copyright 2011-2016 Google Inc.
6 *
7 * Author: Kees Cook <keescook@chromium.org>
8 */

--- 23 unchanged lines hidden (view full) ---

32 task_pid_nr(current),
33 cmdline ? "\"" : "", cmdline, cmdline ? "\"" : "");
34
35 kfree(cmdline);
36 kfree(pathname);
37}
38
39static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE);
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Module and Firmware Pinning Security Module
4 *
5 * Copyright 2011-2016 Google Inc.
6 *
7 * Author: Kees Cook <keescook@chromium.org>
8 */

--- 23 unchanged lines hidden (view full) ---

32 task_pid_nr(current),
33 cmdline ? "\"" : "", cmdline, cmdline ? "\"" : "");
34
35 kfree(cmdline);
36 kfree(pathname);
37}
38
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;
41static DEFINE_SPINLOCK(pinned_root_spinlock);
42
43#ifdef CONFIG_SYSCTL
42static struct super_block *pinned_root;
43static DEFINE_SPINLOCK(pinned_root_spinlock);
44
45#ifdef CONFIG_SYSCTL
44static int zero;
45static int one = 1;
46
47static struct ctl_path loadpin_sysctl_path[] = {
48 { .procname = "kernel", },
49 { .procname = "loadpin", },
50 { }
51};
52
53static struct ctl_table loadpin_sysctl_table[] = {
54 {
55 .procname = "enforce",
56 .data = &enforce,
57 .maxlen = sizeof(int),
58 .mode = 0644,
59 .proc_handler = proc_dointvec_minmax,
46
47static struct ctl_path loadpin_sysctl_path[] = {
48 { .procname = "kernel", },
49 { .procname = "loadpin", },
50 { }
51};
52
53static struct ctl_table loadpin_sysctl_table[] = {
54 {
55 .procname = "enforce",
56 .data = &enforce,
57 .maxlen = sizeof(int),
58 .mode = 0644,
59 .proc_handler = proc_dointvec_minmax,
60 .extra1 = &zero,
61 .extra2 = &one,
60 .extra1 = SYSCTL_ZERO,
61 .extra2 = SYSCTL_ONE,
62 },
63 { }
64};
65
66/*
67 * This must be called after early kernel init, since then the rootdev
68 * is available.
69 */

--- 46 unchanged lines hidden (view full) ---

116 }
117}
118
119static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
120{
121 struct super_block *load_root;
122 const char *origin = kernel_read_file_id_str(id);
123
62 },
63 { }
64};
65
66/*
67 * This must be called after early kernel init, since then the rootdev
68 * is available.
69 */

--- 46 unchanged lines hidden (view full) ---

116 }
117}
118
119static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
120{
121 struct super_block *load_root;
122 const char *origin = kernel_read_file_id_str(id);
123
124 /* If the file id is excluded, ignore the pinning. */
125 if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) &&
126 ignore_read_file_id[id]) {
127 report_load(origin, file, "pinning-excluded");
128 return 0;
129 }
130
124 /* This handles the older init_module API that has a NULL file. */
125 if (!file) {
126 if (!enforce) {
127 report_load(origin, NULL, "old-api-pinning-ignored");
128 return 0;
129 }
130
131 report_load(origin, NULL, "old-api-denied");

--- 42 unchanged lines hidden (view full) ---

174}
175
176static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
177 LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
178 LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
179 LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
180};
181
131 /* This handles the older init_module API that has a NULL file. */
132 if (!file) {
133 if (!enforce) {
134 report_load(origin, NULL, "old-api-pinning-ignored");
135 return 0;
136 }
137
138 report_load(origin, NULL, "old-api-denied");

--- 42 unchanged lines hidden (view full) ---

181}
182
183static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
184 LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
185 LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
186 LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
187};
188
189static void __init parse_exclude(void)
190{
191 int i, j;
192 char *cur;
193
194 /*
195 * Make sure all the arrays stay within expected sizes. This
196 * is slightly weird because kernel_read_file_str[] includes
197 * READING_MAX_ID, which isn't actually meaningful here.
198 */
199 BUILD_BUG_ON(ARRAY_SIZE(exclude_read_files) !=
200 ARRAY_SIZE(ignore_read_file_id));
201 BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) <
202 ARRAY_SIZE(ignore_read_file_id));
203
204 for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) {
205 cur = exclude_read_files[i];
206 if (!cur)
207 break;
208 if (*cur == '\0')
209 continue;
210
211 for (j = 0; j < ARRAY_SIZE(ignore_read_file_id); j++) {
212 if (strcmp(cur, kernel_read_file_str[j]) == 0) {
213 pr_info("excluding: %s\n",
214 kernel_read_file_str[j]);
215 ignore_read_file_id[j] = 1;
216 /*
217 * Can not break, because one read_file_str
218 * may map to more than on read_file_id.
219 */
220 }
221 }
222 }
223}
224
182static int __init loadpin_init(void)
183{
184 pr_info("ready to pin (currently %senforcing)\n",
185 enforce ? "" : "not ");
225static int __init loadpin_init(void)
226{
227 pr_info("ready to pin (currently %senforcing)\n",
228 enforce ? "" : "not ");
229 parse_exclude();
186 security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
187 return 0;
188}
189
190DEFINE_LSM(loadpin) = {
191 .name = "loadpin",
192 .init = loadpin_init,
193};
194
195/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
196module_param(enforce, int, 0);
197MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");
230 security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
231 return 0;
232}
233
234DEFINE_LSM(loadpin) = {
235 .name = "loadpin",
236 .init = loadpin_init,
237};
238
239/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
240module_param(enforce, int, 0);
241MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");
242module_param_array_named(exclude, exclude_read_files, charp, NULL, 0);
243MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types");