linux/security/loadpin/loadpin.c
<<
>>
Prefs
   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
  22static void report_load(const char *origin, struct file *file, char *operation)
  23{
  24        char *cmdline, *pathname;
  25
  26        pathname = kstrdup_quotable_file(file, GFP_KERNEL);
  27        cmdline = kstrdup_quotable_cmdline(current, GFP_KERNEL);
  28
  29        pr_notice("%s %s obj=%s%s%s pid=%d cmdline=%s%s%s\n",
  30                  origin, operation,
  31                  (pathname && pathname[0] != '<') ? "\"" : "",
  32                  pathname,
  33                  (pathname && pathname[0] != '<') ? "\"" : "",
  34                  task_pid_nr(current),
  35                  cmdline ? "\"" : "", cmdline, cmdline ? "\"" : "");
  36
  37        kfree(cmdline);
  38        kfree(pathname);
  39}
  40
  41static int enforce = IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE);
  42static char *exclude_read_files[READING_MAX_ID];
  43static int ignore_read_file_id[READING_MAX_ID] __ro_after_init;
  44static struct super_block *pinned_root;
  45static DEFINE_SPINLOCK(pinned_root_spinlock);
  46
  47#ifdef CONFIG_SYSCTL
  48
  49static struct ctl_path loadpin_sysctl_path[] = {
  50        { .procname = "kernel", },
  51        { .procname = "loadpin", },
  52        { }
  53};
  54
  55static struct ctl_table loadpin_sysctl_table[] = {
  56        {
  57                .procname       = "enforce",
  58                .data           = &enforce,
  59                .maxlen         = sizeof(int),
  60                .mode           = 0644,
  61                .proc_handler   = proc_dointvec_minmax,
  62                .extra1         = SYSCTL_ZERO,
  63                .extra2         = SYSCTL_ONE,
  64        },
  65        { }
  66};
  67
  68/*
  69 * This must be called after early kernel init, since then the rootdev
  70 * is available.
  71 */
  72static void check_pinning_enforcement(struct super_block *mnt_sb)
  73{
  74        bool ro = false;
  75
  76        /*
  77         * If load pinning is not enforced via a read-only block
  78         * device, allow sysctl to change modes for testing.
  79         */
  80        if (mnt_sb->s_bdev) {
  81                char bdev[BDEVNAME_SIZE];
  82
  83                ro = bdev_read_only(mnt_sb->s_bdev);
  84                bdevname(mnt_sb->s_bdev, bdev);
  85                pr_info("%s (%u:%u): %s\n", bdev,
  86                        MAJOR(mnt_sb->s_bdev->bd_dev),
  87                        MINOR(mnt_sb->s_bdev->bd_dev),
  88                        ro ? "read-only" : "writable");
  89        } else
  90                pr_info("mnt_sb lacks block device, treating as: writable\n");
  91
  92        if (!ro) {
  93                if (!register_sysctl_paths(loadpin_sysctl_path,
  94                                           loadpin_sysctl_table))
  95                        pr_notice("sysctl registration failed!\n");
  96                else
  97                        pr_info("enforcement can be disabled.\n");
  98        } else
  99                pr_info("load pinning engaged.\n");
 100}
 101#else
 102static void check_pinning_enforcement(struct super_block *mnt_sb)
 103{
 104        pr_info("load pinning engaged.\n");
 105}
 106#endif
 107
 108static void loadpin_sb_free_security(struct super_block *mnt_sb)
 109{
 110        /*
 111         * When unmounting the filesystem we were using for load
 112         * pinning, we acknowledge the superblock release, but make sure
 113         * no other modules or firmware can be loaded.
 114         */
 115        if (!IS_ERR_OR_NULL(pinned_root) && mnt_sb == pinned_root) {
 116                pinned_root = ERR_PTR(-EIO);
 117                pr_info("umount pinned fs: refusing further loads\n");
 118        }
 119}
 120
 121static int loadpin_read_file(struct file *file, enum kernel_read_file_id id,
 122                             bool contents)
 123{
 124        struct super_block *load_root;
 125        const char *origin = kernel_read_file_id_str(id);
 126
 127        /*
 128         * If we will not know that we'll be seeing the full contents
 129         * then we cannot trust a load will be complete and unchanged
 130         * off disk. Treat all contents=false hooks as if there were
 131         * no associated file struct.
 132         */
 133        if (!contents)
 134                file = NULL;
 135
 136        /* If the file id is excluded, ignore the pinning. */
 137        if ((unsigned int)id < ARRAY_SIZE(ignore_read_file_id) &&
 138            ignore_read_file_id[id]) {
 139                report_load(origin, file, "pinning-excluded");
 140                return 0;
 141        }
 142
 143        /* This handles the older init_module API that has a NULL file. */
 144        if (!file) {
 145                if (!enforce) {
 146                        report_load(origin, NULL, "old-api-pinning-ignored");
 147                        return 0;
 148                }
 149
 150                report_load(origin, NULL, "old-api-denied");
 151                return -EPERM;
 152        }
 153
 154        load_root = file->f_path.mnt->mnt_sb;
 155
 156        /* First loaded module/firmware defines the root for all others. */
 157        spin_lock(&pinned_root_spinlock);
 158        /*
 159         * pinned_root is only NULL at startup. Otherwise, it is either
 160         * a valid reference, or an ERR_PTR.
 161         */
 162        if (!pinned_root) {
 163                pinned_root = load_root;
 164                /*
 165                 * Unlock now since it's only pinned_root we care about.
 166                 * In the worst case, we will (correctly) report pinning
 167                 * failures before we have announced that pinning is
 168                 * enforcing. This would be purely cosmetic.
 169                 */
 170                spin_unlock(&pinned_root_spinlock);
 171                check_pinning_enforcement(pinned_root);
 172                report_load(origin, file, "pinned");
 173        } else {
 174                spin_unlock(&pinned_root_spinlock);
 175        }
 176
 177        if (IS_ERR_OR_NULL(pinned_root) || load_root != pinned_root) {
 178                if (unlikely(!enforce)) {
 179                        report_load(origin, file, "pinning-ignored");
 180                        return 0;
 181                }
 182
 183                report_load(origin, file, "denied");
 184                return -EPERM;
 185        }
 186
 187        return 0;
 188}
 189
 190static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
 191{
 192        return loadpin_read_file(NULL, (enum kernel_read_file_id) id, contents);
 193}
 194
 195static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
 196        LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
 197        LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
 198        LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
 199};
 200
 201static void __init parse_exclude(void)
 202{
 203        int i, j;
 204        char *cur;
 205
 206        /*
 207         * Make sure all the arrays stay within expected sizes. This
 208         * is slightly weird because kernel_read_file_str[] includes
 209         * READING_MAX_ID, which isn't actually meaningful here.
 210         */
 211        BUILD_BUG_ON(ARRAY_SIZE(exclude_read_files) !=
 212                     ARRAY_SIZE(ignore_read_file_id));
 213        BUILD_BUG_ON(ARRAY_SIZE(kernel_read_file_str) <
 214                     ARRAY_SIZE(ignore_read_file_id));
 215
 216        for (i = 0; i < ARRAY_SIZE(exclude_read_files); i++) {
 217                cur = exclude_read_files[i];
 218                if (!cur)
 219                        break;
 220                if (*cur == '\0')
 221                        continue;
 222
 223                for (j = 0; j < ARRAY_SIZE(ignore_read_file_id); j++) {
 224                        if (strcmp(cur, kernel_read_file_str[j]) == 0) {
 225                                pr_info("excluding: %s\n",
 226                                        kernel_read_file_str[j]);
 227                                ignore_read_file_id[j] = 1;
 228                                /*
 229                                 * Can not break, because one read_file_str
 230                                 * may map to more than on read_file_id.
 231                                 */
 232                        }
 233                }
 234        }
 235}
 236
 237static int __init loadpin_init(void)
 238{
 239        pr_info("ready to pin (currently %senforcing)\n",
 240                enforce ? "" : "not ");
 241        parse_exclude();
 242        security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
 243        return 0;
 244}
 245
 246DEFINE_LSM(loadpin) = {
 247        .name = "loadpin",
 248        .init = loadpin_init,
 249};
 250
 251/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */
 252module_param(enforce, int, 0);
 253MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning");
 254module_param_array_named(exclude, exclude_read_files, charp, NULL, 0);
 255MODULE_PARM_DESC(exclude, "Exclude pinning specific read file types");
 256