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 | */ |
9 | |
10 | #define pr_fmt(fmt) "LoadPin: " fmt |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/fs.h> |
14 | #include <linux/kernel_read_file.h> |
15 | #include <linux/lsm_hooks.h> |
16 | #include <linux/mount.h> |
17 | #include <linux/blkdev.h> |
18 | #include <linux/path.h> |
19 | #include <linux/sched.h> /* current */ |
20 | #include <linux/string_helpers.h> |
21 | #include <linux/dm-verity-loadpin.h> |
22 | #include <uapi/linux/loadpin.h> |
23 | #include <uapi/linux/lsm.h> |
24 | |
25 | #define "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS" |
26 | |
27 | static void report_load(const char *origin, struct file *file, char *operation) |
28 | { |
29 | char *cmdline, *pathname; |
30 | |
31 | pathname = kstrdup_quotable_file(file, GFP_KERNEL); |
32 | cmdline = kstrdup_quotable_cmdline(current, GFP_KERNEL); |
33 | |
34 | pr_notice("%s %s obj=%s%s%s pid=%d cmdline=%s%s%s\n" , |
35 | origin, operation, |
36 | (pathname && pathname[0] != '<') ? "\"" : "" , |
37 | pathname, |
38 | (pathname && pathname[0] != '<') ? "\"" : "" , |
39 | task_pid_nr(current), |
40 | cmdline ? "\"" : "" , cmdline, cmdline ? "\"" : "" ); |
41 | |
42 | kfree(objp: cmdline); |
43 | kfree(objp: pathname); |
44 | } |
45 | |
46 | static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE); |
47 | static char *exclude_read_files[READING_MAX_ID]; |
48 | static int ignore_read_file_id[READING_MAX_ID] __ro_after_init; |
49 | static struct super_block *pinned_root; |
50 | static DEFINE_SPINLOCK(pinned_root_spinlock); |
51 | #ifdef CONFIG_SECURITY_LOADPIN_VERITY |
52 | static bool deny_reading_verity_digests; |
53 | #endif |
54 | |
55 | #ifdef CONFIG_SYSCTL |
56 | static struct ctl_table loadpin_sysctl_table[] = { |
57 | { |
58 | .procname = "enforce" , |
59 | .data = &enforce, |
60 | .maxlen = sizeof(int), |
61 | .mode = 0644, |
62 | .proc_handler = proc_dointvec_minmax, |
63 | .extra1 = SYSCTL_ONE, |
64 | .extra2 = SYSCTL_ONE, |
65 | }, |
66 | { } |
67 | }; |
68 | |
69 | static void set_sysctl(bool is_writable) |
70 | { |
71 | /* |
72 | * If load pinning is not enforced via a read-only block |
73 | * device, allow sysctl to change modes for testing. |
74 | */ |
75 | if (is_writable) |
76 | loadpin_sysctl_table[0].extra1 = SYSCTL_ZERO; |
77 | else |
78 | loadpin_sysctl_table[0].extra1 = SYSCTL_ONE; |
79 | } |
80 | #else |
81 | static inline void set_sysctl(bool is_writable) { } |
82 | #endif |
83 | |
84 | static void report_writable(struct super_block *mnt_sb, bool writable) |
85 | { |
86 | if (mnt_sb->s_bdev) { |
87 | pr_info("%pg (%u:%u): %s\n" , mnt_sb->s_bdev, |
88 | MAJOR(mnt_sb->s_bdev->bd_dev), |
89 | MINOR(mnt_sb->s_bdev->bd_dev), |
90 | writable ? "writable" : "read-only" ); |
91 | } else |
92 | pr_info("mnt_sb lacks block device, treating as: writable\n" ); |
93 | |
94 | if (!writable) |
95 | pr_info("load pinning engaged.\n" ); |
96 | } |
97 | |
98 | /* |
99 | * This must be called after early kernel init, since then the rootdev |
100 | * is available. |
101 | */ |
102 | static bool sb_is_writable(struct super_block *mnt_sb) |
103 | { |
104 | bool writable = true; |
105 | |
106 | if (mnt_sb->s_bdev) |
107 | writable = !bdev_read_only(bdev: mnt_sb->s_bdev); |
108 | |
109 | return writable; |
110 | } |
111 | |
112 | static void loadpin_sb_free_security(struct super_block *mnt_sb) |
113 | { |
114 | /* |
115 | * When unmounting the filesystem we were using for load |
116 | * pinning, we acknowledge the superblock release, but make sure |
117 | * no other modules or firmware can be loaded when we are in |
118 | * enforcing mode. Otherwise, allow the root to be reestablished. |
119 | */ |
120 | if (!IS_ERR_OR_NULL(ptr: pinned_root) && mnt_sb == pinned_root) { |
121 | if (enforce) { |
122 | pinned_root = ERR_PTR(error: -EIO); |
123 | pr_info("umount pinned fs: refusing further loads\n" ); |
124 | } else { |
125 | pinned_root = NULL; |
126 | } |
127 | } |
128 | } |
129 | |
130 | static int loadpin_check(struct file *file, enum kernel_read_file_id id) |
131 | { |
132 | struct super_block *load_root; |
133 | const char *origin = kernel_read_file_id_str(id); |
134 | bool first_root_pin = false; |
135 | bool load_root_writable; |
136 | |
137 | /* If the file id is excluded, ignore the pinning. */ |
138 | if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) && |
139 | ignore_read_file_id[id]) { |
140 | report_load(origin, file, operation: "pinning-excluded" ); |
141 | return 0; |
142 | } |
143 | |
144 | /* This handles the older init_module API that has a NULL file. */ |
145 | if (!file) { |
146 | if (!enforce) { |
147 | report_load(origin, NULL, operation: "old-api-pinning-ignored" ); |
148 | return 0; |
149 | } |
150 | |
151 | report_load(origin, NULL, operation: "old-api-denied" ); |
152 | return -EPERM; |
153 | } |
154 | |
155 | load_root = file->f_path.mnt->mnt_sb; |
156 | load_root_writable = sb_is_writable(mnt_sb: load_root); |
157 | |
158 | /* First loaded module/firmware defines the root for all others. */ |
159 | spin_lock(lock: &pinned_root_spinlock); |
160 | /* |
161 | * pinned_root is only NULL at startup or when the pinned root has |
162 | * been unmounted while we are not in enforcing mode. Otherwise, it |
163 | * is either a valid reference, or an ERR_PTR. |
164 | */ |
165 | if (!pinned_root) { |
166 | pinned_root = load_root; |
167 | first_root_pin = true; |
168 | } |
169 | spin_unlock(lock: &pinned_root_spinlock); |
170 | |
171 | if (first_root_pin) { |
172 | report_writable(mnt_sb: pinned_root, writable: load_root_writable); |
173 | set_sysctl(load_root_writable); |
174 | report_load(origin, file, operation: "pinned" ); |
175 | } |
176 | |
177 | if (IS_ERR_OR_NULL(ptr: pinned_root) || |
178 | ((load_root != pinned_root) && !dm_verity_loadpin_is_bdev_trusted(bdev: load_root->s_bdev))) { |
179 | if (unlikely(!enforce)) { |
180 | report_load(origin, file, operation: "pinning-ignored" ); |
181 | return 0; |
182 | } |
183 | |
184 | report_load(origin, file, operation: "denied" ); |
185 | return -EPERM; |
186 | } |
187 | |
188 | return 0; |
189 | } |
190 | |
191 | static int loadpin_read_file(struct file *file, enum kernel_read_file_id id, |
192 | bool contents) |
193 | { |
194 | /* |
195 | * LoadPin only cares about the _origin_ of a file, not its |
196 | * contents, so we can ignore the "are full contents available" |
197 | * argument here. |
198 | */ |
199 | return loadpin_check(file, id); |
200 | } |
201 | |
202 | static int loadpin_load_data(enum kernel_load_data_id id, bool contents) |
203 | { |
204 | /* |
205 | * LoadPin only cares about the _origin_ of a file, not its |
206 | * contents, so a NULL file is passed, and we can ignore the |
207 | * state of "contents". |
208 | */ |
209 | return loadpin_check(NULL, id: (enum kernel_read_file_id) id); |
210 | } |
211 | |
212 | static const struct lsm_id loadpin_lsmid = { |
213 | .name = "loadpin" , |
214 | .id = LSM_ID_LOADPIN, |
215 | }; |
216 | |
217 | static struct security_hook_list loadpin_hooks[] __ro_after_init = { |
218 | LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), |
219 | LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), |
220 | LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), |
221 | }; |
222 | |
223 | static void __init parse_exclude(void) |
224 | { |
225 | int i, j; |
226 | char *cur; |
227 | |
228 | /* |
229 | * Make sure all the arrays stay within expected sizes. This |
230 | * is slightly weird because kernel_read_file_str[] includes |
231 | * READING_MAX_ID, which isn't actually meaningful here. |
232 | */ |
233 | BUILD_BUG_ON(ARRAY_SIZE(exclude_read_files) != |
234 | ARRAY_SIZE(ignore_read_file_id)); |
235 | BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) < |
236 | ARRAY_SIZE(ignore_read_file_id)); |
237 | |
238 | for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) { |
239 | cur = exclude_read_files[i]; |
240 | if (!cur) |
241 | break; |
242 | if (*cur == '\0') |
243 | continue; |
244 | |
245 | for (j = 0; j < ARRAY_SIZE(ignore_read_file_id); j++) { |
246 | if (strcmp(cur, kernel_read_file_str[j]) == 0) { |
247 | pr_info("excluding: %s\n" , |
248 | kernel_read_file_str[j]); |
249 | ignore_read_file_id[j] = 1; |
250 | /* |
251 | * Can not break, because one read_file_str |
252 | * may map to more than on read_file_id. |
253 | */ |
254 | } |
255 | } |
256 | } |
257 | } |
258 | |
259 | static int __init loadpin_init(void) |
260 | { |
261 | pr_info("ready to pin (currently %senforcing)\n" , |
262 | enforce ? "" : "not " ); |
263 | parse_exclude(); |
264 | #ifdef CONFIG_SYSCTL |
265 | if (!register_sysctl("kernel/loadpin" , loadpin_sysctl_table)) |
266 | pr_notice("sysctl registration failed!\n" ); |
267 | #endif |
268 | security_add_hooks(hooks: loadpin_hooks, ARRAY_SIZE(loadpin_hooks), |
269 | lsmid: &loadpin_lsmid); |
270 | |
271 | return 0; |
272 | } |
273 | |
274 | DEFINE_LSM(loadpin) = { |
275 | .name = "loadpin" , |
276 | .init = loadpin_init, |
277 | }; |
278 | |
279 | #ifdef CONFIG_SECURITY_LOADPIN_VERITY |
280 | |
281 | enum loadpin_securityfs_interface_index { |
282 | LOADPIN_DM_VERITY, |
283 | }; |
284 | |
285 | static int read_trusted_verity_root_digests(unsigned int fd) |
286 | { |
287 | struct fd f; |
288 | void *data; |
289 | int rc; |
290 | char *p, *d; |
291 | |
292 | if (deny_reading_verity_digests) |
293 | return -EPERM; |
294 | |
295 | /* The list of trusted root digests can only be set up once */ |
296 | if (!list_empty(head: &dm_verity_loadpin_trusted_root_digests)) |
297 | return -EPERM; |
298 | |
299 | f = fdget(fd); |
300 | if (!f.file) |
301 | return -EINVAL; |
302 | |
303 | data = kzalloc(SZ_4K, GFP_KERNEL); |
304 | if (!data) { |
305 | rc = -ENOMEM; |
306 | goto err; |
307 | } |
308 | |
309 | rc = kernel_read_file(file: f.file, offset: 0, buf: (void **)&data, SZ_4K - 1, NULL, id: READING_POLICY); |
310 | if (rc < 0) |
311 | goto err; |
312 | |
313 | p = data; |
314 | p[rc] = '\0'; |
315 | p = strim(p); |
316 | |
317 | p = strim(data); |
318 | while ((d = strsep(&p, "\n" )) != NULL) { |
319 | int len; |
320 | struct dm_verity_loadpin_trusted_root_digest *trd; |
321 | |
322 | if (d == data) { |
323 | /* first line, validate header */ |
324 | if (strcmp(d, VERITY_DIGEST_FILE_HEADER)) { |
325 | rc = -EPROTO; |
326 | goto err; |
327 | } |
328 | |
329 | continue; |
330 | } |
331 | |
332 | len = strlen(d); |
333 | |
334 | if (len % 2) { |
335 | rc = -EPROTO; |
336 | goto err; |
337 | } |
338 | |
339 | len /= 2; |
340 | |
341 | trd = kzalloc(struct_size(trd, data, len), GFP_KERNEL); |
342 | if (!trd) { |
343 | rc = -ENOMEM; |
344 | goto err; |
345 | } |
346 | trd->len = len; |
347 | |
348 | if (hex2bin(dst: trd->data, src: d, count: len)) { |
349 | kfree(objp: trd); |
350 | rc = -EPROTO; |
351 | goto err; |
352 | } |
353 | |
354 | list_add_tail(new: &trd->node, head: &dm_verity_loadpin_trusted_root_digests); |
355 | } |
356 | |
357 | if (list_empty(head: &dm_verity_loadpin_trusted_root_digests)) { |
358 | rc = -EPROTO; |
359 | goto err; |
360 | } |
361 | |
362 | kfree(objp: data); |
363 | fdput(fd: f); |
364 | |
365 | return 0; |
366 | |
367 | err: |
368 | kfree(objp: data); |
369 | |
370 | /* any failure in loading/parsing invalidates the entire list */ |
371 | { |
372 | struct dm_verity_loadpin_trusted_root_digest *trd, *tmp; |
373 | |
374 | list_for_each_entry_safe(trd, tmp, &dm_verity_loadpin_trusted_root_digests, node) { |
375 | list_del(entry: &trd->node); |
376 | kfree(objp: trd); |
377 | } |
378 | } |
379 | |
380 | /* disallow further attempts after reading a corrupt/invalid file */ |
381 | deny_reading_verity_digests = true; |
382 | |
383 | fdput(fd: f); |
384 | |
385 | return rc; |
386 | } |
387 | |
388 | /******************************** securityfs ********************************/ |
389 | |
390 | static long dm_verity_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
391 | { |
392 | void __user *uarg = (void __user *)arg; |
393 | unsigned int fd; |
394 | |
395 | switch (cmd) { |
396 | case LOADPIN_IOC_SET_TRUSTED_VERITY_DIGESTS: |
397 | if (copy_from_user(to: &fd, from: uarg, n: sizeof(fd))) |
398 | return -EFAULT; |
399 | |
400 | return read_trusted_verity_root_digests(fd); |
401 | |
402 | default: |
403 | return -EINVAL; |
404 | } |
405 | } |
406 | |
407 | static const struct file_operations loadpin_dm_verity_ops = { |
408 | .unlocked_ioctl = dm_verity_ioctl, |
409 | .compat_ioctl = compat_ptr_ioctl, |
410 | }; |
411 | |
412 | /** |
413 | * init_loadpin_securityfs - create the securityfs directory for LoadPin |
414 | * |
415 | * We can not put this method normally under the loadpin_init() code path since |
416 | * the security subsystem gets initialized before the vfs caches. |
417 | * |
418 | * Returns 0 if the securityfs directory creation was successful. |
419 | */ |
420 | static int __init init_loadpin_securityfs(void) |
421 | { |
422 | struct dentry *loadpin_dir, *dentry; |
423 | |
424 | loadpin_dir = securityfs_create_dir(name: "loadpin" , NULL); |
425 | if (IS_ERR(ptr: loadpin_dir)) { |
426 | pr_err("LoadPin: could not create securityfs dir: %ld\n" , |
427 | PTR_ERR(loadpin_dir)); |
428 | return PTR_ERR(ptr: loadpin_dir); |
429 | } |
430 | |
431 | dentry = securityfs_create_file(name: "dm-verity" , mode: 0600, parent: loadpin_dir, |
432 | data: (void *)LOADPIN_DM_VERITY, fops: &loadpin_dm_verity_ops); |
433 | if (IS_ERR(ptr: dentry)) { |
434 | pr_err("LoadPin: could not create securityfs entry 'dm-verity': %ld\n" , |
435 | PTR_ERR(dentry)); |
436 | return PTR_ERR(ptr: dentry); |
437 | } |
438 | |
439 | return 0; |
440 | } |
441 | |
442 | fs_initcall(init_loadpin_securityfs); |
443 | |
444 | #endif /* CONFIG_SECURITY_LOADPIN_VERITY */ |
445 | |
446 | /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ |
447 | module_param(enforce, int, 0); |
448 | MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning" ); |
449 | module_param_array_named(exclude, exclude_read_files, charp, NULL, 0); |
450 | MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types" ); |
451 | |