0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) "LoadPin: " fmt
0011
0012 #include <linux/module.h>
0013 #include <linux/fs.h>
0014 #include <linux/kernel_read_file.h>
0015 #include <linux/lsm_hooks.h>
0016 #include <linux/mount.h>
0017 #include <linux/blkdev.h>
0018 #include <linux/path.h>
0019 #include <linux/sched.h> /* current */
0020 #include <linux/string_helpers.h>
0021 #include <linux/dm-verity-loadpin.h>
0022 #include <uapi/linux/loadpin.h>
0023
0024 static void report_load(const char *origin, struct file *file, char *operation)
0025 {
0026 char *cmdline, *pathname;
0027
0028 pathname = kstrdup_quotable_file(file, GFP_KERNEL);
0029 cmdline = kstrdup_quotable_cmdline(current, GFP_KERNEL);
0030
0031 pr_notice("%s %s obj=%s%s%s pid=%d cmdline=%s%s%s\n",
0032 origin, operation,
0033 (pathname && pathname[0] != '<') ? "\"" : "",
0034 pathname,
0035 (pathname && pathname[0] != '<') ? "\"" : "",
0036 task_pid_nr(current),
0037 cmdline ? "\"" : "", cmdline, cmdline ? "\"" : "");
0038
0039 kfree(cmdline);
0040 kfree(pathname);
0041 }
0042
0043 static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE);
0044 static char *exclude_read_files[READING_MAX_ID];
0045 static int ignore_read_file_id[READING_MAX_ID] __ro_after_init;
0046 static struct super_block *pinned_root;
0047 static DEFINE_SPINLOCK(pinned_root_spinlock);
0048 #ifdef CONFIG_SECURITY_LOADPIN_VERITY
0049 static bool deny_reading_verity_digests;
0050 #endif
0051
0052 #ifdef CONFIG_SYSCTL
0053
0054 static struct ctl_path loadpin_sysctl_path[] = {
0055 { .procname = "kernel", },
0056 { .procname = "loadpin", },
0057 { }
0058 };
0059
0060 static struct ctl_table loadpin_sysctl_table[] = {
0061 {
0062 .procname = "enforce",
0063 .data = &enforce,
0064 .maxlen = sizeof(int),
0065 .mode = 0644,
0066 .proc_handler = proc_dointvec_minmax,
0067 .extra1 = SYSCTL_ZERO,
0068 .extra2 = SYSCTL_ONE,
0069 },
0070 { }
0071 };
0072
0073
0074
0075
0076
0077 static void check_pinning_enforcement(struct super_block *mnt_sb)
0078 {
0079 bool ro = false;
0080
0081
0082
0083
0084
0085 if (mnt_sb->s_bdev) {
0086 ro = bdev_read_only(mnt_sb->s_bdev);
0087 pr_info("%pg (%u:%u): %s\n", mnt_sb->s_bdev,
0088 MAJOR(mnt_sb->s_bdev->bd_dev),
0089 MINOR(mnt_sb->s_bdev->bd_dev),
0090 ro ? "read-only" : "writable");
0091 } else
0092 pr_info("mnt_sb lacks block device, treating as: writable\n");
0093
0094 if (!ro) {
0095 if (!register_sysctl_paths(loadpin_sysctl_path,
0096 loadpin_sysctl_table))
0097 pr_notice("sysctl registration failed!\n");
0098 else
0099 pr_info("enforcement can be disabled.\n");
0100 } else
0101 pr_info("load pinning engaged.\n");
0102 }
0103 #else
0104 static void check_pinning_enforcement(struct super_block *mnt_sb)
0105 {
0106 pr_info("load pinning engaged.\n");
0107 }
0108 #endif
0109
0110 static void loadpin_sb_free_security(struct super_block *mnt_sb)
0111 {
0112
0113
0114
0115
0116
0117 if (!IS_ERR_OR_NULL(pinned_root) && mnt_sb == pinned_root) {
0118 pinned_root = ERR_PTR(-EIO);
0119 pr_info("umount pinned fs: refusing further loads\n");
0120 }
0121 }
0122
0123 static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
0124 bool contents)
0125 {
0126 struct super_block *load_root;
0127 const char *origin = kernel_read_file_id_str(id);
0128
0129
0130
0131
0132
0133
0134
0135 if (!contents)
0136 file = NULL;
0137
0138
0139 if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) &&
0140 ignore_read_file_id[id]) {
0141 report_load(origin, file, "pinning-excluded");
0142 return 0;
0143 }
0144
0145
0146 if (!file) {
0147 if (!enforce) {
0148 report_load(origin, NULL, "old-api-pinning-ignored");
0149 return 0;
0150 }
0151
0152 report_load(origin, NULL, "old-api-denied");
0153 return -EPERM;
0154 }
0155
0156 load_root = file->f_path.mnt->mnt_sb;
0157
0158
0159 spin_lock(&pinned_root_spinlock);
0160
0161
0162
0163
0164 if (!pinned_root) {
0165 pinned_root = load_root;
0166
0167
0168
0169
0170
0171
0172 spin_unlock(&pinned_root_spinlock);
0173 check_pinning_enforcement(pinned_root);
0174 report_load(origin, file, "pinned");
0175 } else {
0176 spin_unlock(&pinned_root_spinlock);
0177 }
0178
0179 if (IS_ERR_OR_NULL(pinned_root) ||
0180 ((load_root != pinned_root) && !dm_verity_loadpin_is_bdev_trusted(load_root->s_bdev))) {
0181 if (unlikely(!enforce)) {
0182 report_load(origin, file, "pinning-ignored");
0183 return 0;
0184 }
0185
0186 report_load(origin, file, "denied");
0187 return -EPERM;
0188 }
0189
0190 return 0;
0191 }
0192
0193 static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
0194 {
0195 return loadpin_read_file(NULL, (enum kernel_read_file_id) id, contents);
0196 }
0197
0198 static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
0199 LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
0200 LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
0201 LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
0202 };
0203
0204 static void __init parse_exclude(void)
0205 {
0206 int i, j;
0207 char *cur;
0208
0209
0210
0211
0212
0213
0214 BUILD_BUG_ON(ARRAY_SIZE(exclude_read_files) !=
0215 ARRAY_SIZE(ignore_read_file_id));
0216 BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) <
0217 ARRAY_SIZE(ignore_read_file_id));
0218
0219 for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) {
0220 cur = exclude_read_files[i];
0221 if (!cur)
0222 break;
0223 if (*cur == '\0')
0224 continue;
0225
0226 for (j = 0; j < ARRAY_SIZE(ignore_read_file_id); j++) {
0227 if (strcmp(cur, kernel_read_file_str[j]) == 0) {
0228 pr_info("excluding: %s\n",
0229 kernel_read_file_str[j]);
0230 ignore_read_file_id[j] = 1;
0231
0232
0233
0234
0235 }
0236 }
0237 }
0238 }
0239
0240 static int __init loadpin_init(void)
0241 {
0242 pr_info("ready to pin (currently %senforcing)\n",
0243 enforce ? "" : "not ");
0244 parse_exclude();
0245 security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
0246
0247 return 0;
0248 }
0249
0250 DEFINE_LSM(loadpin) = {
0251 .name = "loadpin",
0252 .init = loadpin_init,
0253 };
0254
0255 #ifdef CONFIG_SECURITY_LOADPIN_VERITY
0256
0257 enum loadpin_securityfs_interface_index {
0258 LOADPIN_DM_VERITY,
0259 };
0260
0261 static int read_trusted_verity_root_digests(unsigned int fd)
0262 {
0263 struct fd f;
0264 void *data;
0265 int rc;
0266 char *p, *d;
0267
0268 if (deny_reading_verity_digests)
0269 return -EPERM;
0270
0271
0272 if (!list_empty(&dm_verity_loadpin_trusted_root_digests))
0273 return -EPERM;
0274
0275 f = fdget(fd);
0276 if (!f.file)
0277 return -EINVAL;
0278
0279 data = kzalloc(SZ_4K, GFP_KERNEL);
0280 if (!data) {
0281 rc = -ENOMEM;
0282 goto err;
0283 }
0284
0285 rc = kernel_read_file(f.file, 0, (void **)&data, SZ_4K - 1, NULL, READING_POLICY);
0286 if (rc < 0)
0287 goto err;
0288
0289 p = data;
0290 p[rc] = '\0';
0291 p = strim(p);
0292
0293 p = strim(data);
0294 while ((d = strsep(&p, "\n")) != NULL) {
0295 int len = strlen(d);
0296 struct dm_verity_loadpin_trusted_root_digest *trd;
0297
0298 if (len % 2) {
0299 rc = -EPROTO;
0300 goto err;
0301 }
0302
0303 len /= 2;
0304
0305 trd = kzalloc(struct_size(trd, data, len), GFP_KERNEL);
0306 if (!trd) {
0307 rc = -ENOMEM;
0308 goto err;
0309 }
0310
0311 if (hex2bin(trd->data, d, len)) {
0312 kfree(trd);
0313 rc = -EPROTO;
0314 goto err;
0315 }
0316
0317 trd->len = len;
0318
0319 list_add_tail(&trd->node, &dm_verity_loadpin_trusted_root_digests);
0320 }
0321
0322 if (list_empty(&dm_verity_loadpin_trusted_root_digests)) {
0323 rc = -EPROTO;
0324 goto err;
0325 }
0326
0327 kfree(data);
0328 fdput(f);
0329
0330 return 0;
0331
0332 err:
0333 kfree(data);
0334
0335
0336 {
0337 struct dm_verity_loadpin_trusted_root_digest *trd, *tmp;
0338
0339 list_for_each_entry_safe(trd, tmp, &dm_verity_loadpin_trusted_root_digests, node) {
0340 list_del(&trd->node);
0341 kfree(trd);
0342 }
0343 }
0344
0345
0346 deny_reading_verity_digests = true;
0347
0348 fdput(f);
0349
0350 return rc;
0351 }
0352
0353
0354
0355 static long dm_verity_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
0356 {
0357 void __user *uarg = (void __user *)arg;
0358 unsigned int fd;
0359
0360 switch (cmd) {
0361 case LOADPIN_IOC_SET_TRUSTED_VERITY_DIGESTS:
0362 if (copy_from_user(&fd, uarg, sizeof(fd)))
0363 return -EFAULT;
0364
0365 return read_trusted_verity_root_digests(fd);
0366
0367 default:
0368 return -EINVAL;
0369 }
0370 }
0371
0372 static const struct file_operations loadpin_dm_verity_ops = {
0373 .unlocked_ioctl = dm_verity_ioctl,
0374 .compat_ioctl = compat_ptr_ioctl,
0375 };
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 static int __init init_loadpin_securityfs(void)
0386 {
0387 struct dentry *loadpin_dir, *dentry;
0388
0389 loadpin_dir = securityfs_create_dir("loadpin", NULL);
0390 if (IS_ERR(loadpin_dir)) {
0391 pr_err("LoadPin: could not create securityfs dir: %ld\n",
0392 PTR_ERR(loadpin_dir));
0393 return PTR_ERR(loadpin_dir);
0394 }
0395
0396 dentry = securityfs_create_file("dm-verity", 0600, loadpin_dir,
0397 (void *)LOADPIN_DM_VERITY, &loadpin_dm_verity_ops);
0398 if (IS_ERR(dentry)) {
0399 pr_err("LoadPin: could not create securityfs entry 'dm-verity': %ld\n",
0400 PTR_ERR(dentry));
0401 return PTR_ERR(dentry);
0402 }
0403
0404 return 0;
0405 }
0406
0407 fs_initcall(init_loadpin_securityfs);
0408
0409 #endif
0410
0411
0412 module_param(enforce, int, 0);
0413 MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");
0414 module_param_array_named(exclude, exclude_read_files, charp, NULL, 0);
0415 MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types");