summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-07-11 17:42:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-11 17:42:44 -0400
commitc079512aad9718c12c6bb1b661880b15a73dfd69 (patch)
treeb8cb70b4d40102bb806287fe7592b713e032a16c
parent6b44fccdb8cdcc7c1df522529307566aa89a4ab1 (diff)
parent0ff9848067b7b950a4ed70de7f5028600a2157e3 (diff)
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
-rw-r--r--Documentation/admin-guide/LSM/LoadPin.rst10
-rw-r--r--security/loadpin/loadpin.c48
2 files changed, 58 insertions, 0 deletions
diff --git a/Documentation/admin-guide/LSM/LoadPin.rst b/Documentation/admin-guide/LSM/LoadPin.rst
index 32070762d24c..716ad9b23c9a 100644
--- a/Documentation/admin-guide/LSM/LoadPin.rst
+++ b/Documentation/admin-guide/LSM/LoadPin.rst
@@ -19,3 +19,13 @@ block device backing the filesystem is not read-only, a sysctl is
19created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having 19created to toggle pinning: ``/proc/sys/kernel/loadpin/enabled``. (Having
20a mutable filesystem means pinning is mutable too, but having the 20a mutable filesystem means pinning is mutable too, but having the
21sysctl allows for easy testing on systems with a mutable filesystem.) 21sysctl allows for easy testing on systems with a mutable filesystem.)
22
23It's also possible to exclude specific file types from LoadPin using kernel
24command line option "``loadpin.exclude``". By default, all files are
25included, but they can be excluded using kernel command line option such
26as "``loadpin.exclude=kernel-module,kexec-image``". This allows to use
27different mechanisms such as ``CONFIG_MODULE_SIG`` and
28``CONFIG_KEXEC_VERIFY_SIG`` to verify kernel module and kernel image while
29still use LoadPin to protect the integrity of other files kernel loads. The
30full list of valid file types can be found in ``kernel_read_file_str``
31defined in ``include/linux/fs.h``.
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");