Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include <linux/kernel.h>
0003 #include <linux/init.h>
0004 #include <linux/random.h>
0005 #include <linux/sched.h>
0006 #include <linux/stat.h>
0007 #include <linux/types.h>
0008 #include <linux/fs.h>
0009 #include <linux/export.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/stacktrace.h>
0012 #include <linux/fault-inject.h>
0013 
0014 /*
0015  * setup_fault_attr() is a helper function for various __setup handlers, so it
0016  * returns 0 on error, because that is what __setup handlers do.
0017  */
0018 int setup_fault_attr(struct fault_attr *attr, char *str)
0019 {
0020     unsigned long probability;
0021     unsigned long interval;
0022     int times;
0023     int space;
0024 
0025     /* "<interval>,<probability>,<space>,<times>" */
0026     if (sscanf(str, "%lu,%lu,%d,%d",
0027             &interval, &probability, &space, &times) < 4) {
0028         printk(KERN_WARNING
0029             "FAULT_INJECTION: failed to parse arguments\n");
0030         return 0;
0031     }
0032 
0033     attr->probability = probability;
0034     attr->interval = interval;
0035     atomic_set(&attr->times, times);
0036     atomic_set(&attr->space, space);
0037 
0038     return 1;
0039 }
0040 EXPORT_SYMBOL_GPL(setup_fault_attr);
0041 
0042 static void fail_dump(struct fault_attr *attr)
0043 {
0044     if (attr->no_warn)
0045         return;
0046 
0047     if (attr->verbose > 0 && __ratelimit(&attr->ratelimit_state)) {
0048         printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n"
0049                "name %pd, interval %lu, probability %lu, "
0050                "space %d, times %d\n", attr->dname,
0051                attr->interval, attr->probability,
0052                atomic_read(&attr->space),
0053                atomic_read(&attr->times));
0054         if (attr->verbose > 1)
0055             dump_stack();
0056     }
0057 }
0058 
0059 #define atomic_dec_not_zero(v)      atomic_add_unless((v), -1, 0)
0060 
0061 static bool fail_task(struct fault_attr *attr, struct task_struct *task)
0062 {
0063     return in_task() && task->make_it_fail;
0064 }
0065 
0066 #define MAX_STACK_TRACE_DEPTH 32
0067 
0068 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
0069 
0070 static bool fail_stacktrace(struct fault_attr *attr)
0071 {
0072     int depth = attr->stacktrace_depth;
0073     unsigned long entries[MAX_STACK_TRACE_DEPTH];
0074     int n, nr_entries;
0075     bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
0076 
0077     if (depth == 0)
0078         return found;
0079 
0080     nr_entries = stack_trace_save(entries, depth, 1);
0081     for (n = 0; n < nr_entries; n++) {
0082         if (attr->reject_start <= entries[n] &&
0083                    entries[n] < attr->reject_end)
0084             return false;
0085         if (attr->require_start <= entries[n] &&
0086                    entries[n] < attr->require_end)
0087             found = true;
0088     }
0089     return found;
0090 }
0091 
0092 #else
0093 
0094 static inline bool fail_stacktrace(struct fault_attr *attr)
0095 {
0096     return true;
0097 }
0098 
0099 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
0100 
0101 /*
0102  * This code is stolen from failmalloc-1.0
0103  * http://www.nongnu.org/failmalloc/
0104  */
0105 
0106 bool should_fail(struct fault_attr *attr, ssize_t size)
0107 {
0108     if (in_task()) {
0109         unsigned int fail_nth = READ_ONCE(current->fail_nth);
0110 
0111         if (fail_nth) {
0112             fail_nth--;
0113             WRITE_ONCE(current->fail_nth, fail_nth);
0114             if (!fail_nth)
0115                 goto fail;
0116 
0117             return false;
0118         }
0119     }
0120 
0121     /* No need to check any other properties if the probability is 0 */
0122     if (attr->probability == 0)
0123         return false;
0124 
0125     if (attr->task_filter && !fail_task(attr, current))
0126         return false;
0127 
0128     if (atomic_read(&attr->times) == 0)
0129         return false;
0130 
0131     if (atomic_read(&attr->space) > size) {
0132         atomic_sub(size, &attr->space);
0133         return false;
0134     }
0135 
0136     if (attr->interval > 1) {
0137         attr->count++;
0138         if (attr->count % attr->interval)
0139             return false;
0140     }
0141 
0142     if (attr->probability <= prandom_u32() % 100)
0143         return false;
0144 
0145     if (!fail_stacktrace(attr))
0146         return false;
0147 
0148 fail:
0149     fail_dump(attr);
0150 
0151     if (atomic_read(&attr->times) != -1)
0152         atomic_dec_not_zero(&attr->times);
0153 
0154     return true;
0155 }
0156 EXPORT_SYMBOL_GPL(should_fail);
0157 
0158 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
0159 
0160 static int debugfs_ul_set(void *data, u64 val)
0161 {
0162     *(unsigned long *)data = val;
0163     return 0;
0164 }
0165 
0166 static int debugfs_ul_get(void *data, u64 *val)
0167 {
0168     *val = *(unsigned long *)data;
0169     return 0;
0170 }
0171 
0172 DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n");
0173 
0174 static void debugfs_create_ul(const char *name, umode_t mode,
0175                   struct dentry *parent, unsigned long *value)
0176 {
0177     debugfs_create_file(name, mode, parent, value, &fops_ul);
0178 }
0179 
0180 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
0181 
0182 static int debugfs_stacktrace_depth_set(void *data, u64 val)
0183 {
0184     *(unsigned long *)data =
0185         min_t(unsigned long, val, MAX_STACK_TRACE_DEPTH);
0186 
0187     return 0;
0188 }
0189 
0190 DEFINE_SIMPLE_ATTRIBUTE(fops_stacktrace_depth, debugfs_ul_get,
0191             debugfs_stacktrace_depth_set, "%llu\n");
0192 
0193 static void debugfs_create_stacktrace_depth(const char *name, umode_t mode,
0194                         struct dentry *parent,
0195                         unsigned long *value)
0196 {
0197     debugfs_create_file(name, mode, parent, value, &fops_stacktrace_depth);
0198 }
0199 
0200 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
0201 
0202 struct dentry *fault_create_debugfs_attr(const char *name,
0203             struct dentry *parent, struct fault_attr *attr)
0204 {
0205     umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
0206     struct dentry *dir;
0207 
0208     dir = debugfs_create_dir(name, parent);
0209     if (IS_ERR(dir))
0210         return dir;
0211 
0212     debugfs_create_ul("probability", mode, dir, &attr->probability);
0213     debugfs_create_ul("interval", mode, dir, &attr->interval);
0214     debugfs_create_atomic_t("times", mode, dir, &attr->times);
0215     debugfs_create_atomic_t("space", mode, dir, &attr->space);
0216     debugfs_create_ul("verbose", mode, dir, &attr->verbose);
0217     debugfs_create_u32("verbose_ratelimit_interval_ms", mode, dir,
0218                &attr->ratelimit_state.interval);
0219     debugfs_create_u32("verbose_ratelimit_burst", mode, dir,
0220                &attr->ratelimit_state.burst);
0221     debugfs_create_bool("task-filter", mode, dir, &attr->task_filter);
0222 
0223 #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
0224     debugfs_create_stacktrace_depth("stacktrace-depth", mode, dir,
0225                     &attr->stacktrace_depth);
0226     debugfs_create_ul("require-start", mode, dir, &attr->require_start);
0227     debugfs_create_ul("require-end", mode, dir, &attr->require_end);
0228     debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
0229     debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
0230 #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
0231 
0232     attr->dname = dget(dir);
0233     return dir;
0234 }
0235 EXPORT_SYMBOL_GPL(fault_create_debugfs_attr);
0236 
0237 #endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */