Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'loadpin-v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull security/loadpin updates from Kees Cook:

- Allow exclusion of specific file types (Ke Wu)

* tag 'loadpin-v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
security/loadpin: Allow to exclude specific file types

+58
+10
Documentation/admin-guide/LSM/LoadPin.rst
··· 19 19 created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having 20 20 a mutable filesystem means pinning is mutable too, but having the 21 21 sysctl allows for easy testing on systems with a mutable filesystem.) 22 + 23 + It's also possible to exclude specific file types from LoadPin using kernel 24 + command line option "``loadpin.exclude``". By default, all files are 25 + included, but they can be excluded using kernel command line option such 26 + as "``loadpin.exclude=kernel-module,kexec-image``". This allows to use 27 + different mechanisms such as ``CONFIG_MODULE_SIG`` and 28 + ``CONFIG_KEXEC_VERIFY_SIG`` to verify kernel module and kernel image while 29 + still use LoadPin to protect the integrity of other files kernel loads. The 30 + full list of valid file types can be found in ``kernel_read_file_str`` 31 + defined in ``include/linux/fs.h``.
+48
security/loadpin/loadpin.c
··· 37 37 } 38 38 39 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 42 static struct super_block *pinned_root; 41 43 static DEFINE_SPINLOCK(pinned_root_spinlock); 42 44 ··· 123 121 struct super_block *load_root; 124 122 const char *origin = kernel_read_file_id_str(id); 125 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 + 126 131 /* This handles the older init_module API that has a NULL file. */ 127 132 if (!file) { 128 133 if (!enforce) { ··· 188 179 LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), 189 180 }; 190 181 182 + static void __init parse_exclude(void) 183 + { 184 + int i, j; 185 + char *cur; 186 + 187 + /* 188 + * Make sure all the arrays stay within expected sizes. This 189 + * is slightly weird because kernel_read_file_str[] includes 190 + * READING_MAX_ID, which isn't actually meaningful here. 191 + */ 192 + BUILD_BUG_ON(ARRAY_SIZE(exclude_read_files) != 193 + ARRAY_SIZE(ignore_read_file_id)); 194 + BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) < 195 + ARRAY_SIZE(ignore_read_file_id)); 196 + 197 + for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) { 198 + cur = exclude_read_files[i]; 199 + if (!cur) 200 + break; 201 + if (*cur == '\0') 202 + continue; 203 + 204 + for (j = 0; j < ARRAY_SIZE(ignore_read_file_id); j++) { 205 + if (strcmp(cur, kernel_read_file_str[j]) == 0) { 206 + pr_info("excluding: %s\n", 207 + kernel_read_file_str[j]); 208 + ignore_read_file_id[j] = 1; 209 + /* 210 + * Can not break, because one read_file_str 211 + * may map to more than on read_file_id. 212 + */ 213 + } 214 + } 215 + } 216 + } 217 + 191 218 static int __init loadpin_init(void) 192 219 { 193 220 pr_info("ready to pin (currently %senforcing)\n", 194 221 enforce ? "" : "not "); 222 + parse_exclude(); 195 223 security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); 196 224 return 0; 197 225 } ··· 241 195 /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ 242 196 module_param(enforce, int, 0); 243 197 MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); 198 + module_param_array_named(exclude, exclude_read_files, charp, NULL, 0); 199 + MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types");