cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

notifier-error-inject.c (2566B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#include <linux/module.h>
      3
      4#include "notifier-error-inject.h"
      5
      6static int debugfs_errno_set(void *data, u64 val)
      7{
      8	*(int *)data = clamp_t(int, val, -MAX_ERRNO, 0);
      9	return 0;
     10}
     11
     12static int debugfs_errno_get(void *data, u64 *val)
     13{
     14	*val = *(int *)data;
     15	return 0;
     16}
     17
     18DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set,
     19			"%lld\n");
     20
     21static struct dentry *debugfs_create_errno(const char *name, umode_t mode,
     22				struct dentry *parent, int *value)
     23{
     24	return debugfs_create_file(name, mode, parent, value, &fops_errno);
     25}
     26
     27static int notifier_err_inject_callback(struct notifier_block *nb,
     28				unsigned long val, void *p)
     29{
     30	int err = 0;
     31	struct notifier_err_inject *err_inject =
     32		container_of(nb, struct notifier_err_inject, nb);
     33	struct notifier_err_inject_action *action;
     34
     35	for (action = err_inject->actions; action->name; action++) {
     36		if (action->val == val) {
     37			err = action->error;
     38			break;
     39		}
     40	}
     41	if (err)
     42		pr_info("Injecting error (%d) to %s\n", err, action->name);
     43
     44	return notifier_from_errno(err);
     45}
     46
     47struct dentry *notifier_err_inject_dir;
     48EXPORT_SYMBOL_GPL(notifier_err_inject_dir);
     49
     50struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent,
     51			struct notifier_err_inject *err_inject, int priority)
     52{
     53	struct notifier_err_inject_action *action;
     54	umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
     55	struct dentry *dir;
     56	struct dentry *actions_dir;
     57
     58	err_inject->nb.notifier_call = notifier_err_inject_callback;
     59	err_inject->nb.priority = priority;
     60
     61	dir = debugfs_create_dir(name, parent);
     62
     63	actions_dir = debugfs_create_dir("actions", dir);
     64
     65	for (action = err_inject->actions; action->name; action++) {
     66		struct dentry *action_dir;
     67
     68		action_dir = debugfs_create_dir(action->name, actions_dir);
     69
     70		/*
     71		 * Create debugfs r/w file containing action->error. If
     72		 * notifier call chain is called with action->val, it will
     73		 * fail with the error code
     74		 */
     75		debugfs_create_errno("error", mode, action_dir, &action->error);
     76	}
     77	return dir;
     78}
     79EXPORT_SYMBOL_GPL(notifier_err_inject_init);
     80
     81static int __init err_inject_init(void)
     82{
     83	notifier_err_inject_dir =
     84		debugfs_create_dir("notifier-error-inject", NULL);
     85
     86	if (!notifier_err_inject_dir)
     87		return -ENOMEM;
     88
     89	return 0;
     90}
     91
     92static void __exit err_inject_exit(void)
     93{
     94	debugfs_remove_recursive(notifier_err_inject_dir);
     95}
     96
     97module_init(err_inject_init);
     98module_exit(err_inject_exit);
     99
    100MODULE_DESCRIPTION("Notifier error injection module");
    101MODULE_LICENSE("GPL");
    102MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");