aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/base.c65
-rw-r--r--include/linux/fault-inject.h2
-rw-r--r--include/linux/sched.h3
-rw-r--r--lib/fault-inject.c17
4 files changed, 86 insertions, 1 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a3b5074118a7..fd959d5b5a80 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -853,6 +853,65 @@ static struct file_operations proc_seccomp_operations = {
853}; 853};
854#endif /* CONFIG_SECCOMP */ 854#endif /* CONFIG_SECCOMP */
855 855
856#ifdef CONFIG_FAULT_INJECTION
857static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
858 size_t count, loff_t *ppos)
859{
860 struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
861 char buffer[PROC_NUMBUF];
862 size_t len;
863 int make_it_fail;
864 loff_t __ppos = *ppos;
865
866 if (!task)
867 return -ESRCH;
868 make_it_fail = task->make_it_fail;
869 put_task_struct(task);
870
871 len = snprintf(buffer, sizeof(buffer), "%i\n", make_it_fail);
872 if (__ppos >= len)
873 return 0;
874 if (count > len-__ppos)
875 count = len-__ppos;
876 if (copy_to_user(buf, buffer + __ppos, count))
877 return -EFAULT;
878 *ppos = __ppos + count;
879 return count;
880}
881
882static ssize_t proc_fault_inject_write(struct file * file,
883 const char __user * buf, size_t count, loff_t *ppos)
884{
885 struct task_struct *task;
886 char buffer[PROC_NUMBUF], *end;
887 int make_it_fail;
888
889 if (!capable(CAP_SYS_RESOURCE))
890 return -EPERM;
891 memset(buffer, 0, sizeof(buffer));
892 if (count > sizeof(buffer) - 1)
893 count = sizeof(buffer) - 1;
894 if (copy_from_user(buffer, buf, count))
895 return -EFAULT;
896 make_it_fail = simple_strtol(buffer, &end, 0);
897 if (*end == '\n')
898 end++;
899 task = get_proc_task(file->f_dentry->d_inode);
900 if (!task)
901 return -ESRCH;
902 task->make_it_fail = make_it_fail;
903 put_task_struct(task);
904 if (end - buffer == 0)
905 return -EIO;
906 return end - buffer;
907}
908
909static struct file_operations proc_fault_inject_operations = {
910 .read = proc_fault_inject_read,
911 .write = proc_fault_inject_write,
912};
913#endif
914
856static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) 915static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
857{ 916{
858 struct inode *inode = dentry->d_inode; 917 struct inode *inode = dentry->d_inode;
@@ -1793,6 +1852,9 @@ static struct pid_entry tgid_base_stuff[] = {
1793#ifdef CONFIG_AUDITSYSCALL 1852#ifdef CONFIG_AUDITSYSCALL
1794 REG("loginuid", S_IWUSR|S_IRUGO, loginuid), 1853 REG("loginuid", S_IWUSR|S_IRUGO, loginuid),
1795#endif 1854#endif
1855#ifdef CONFIG_FAULT_INJECTION
1856 REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
1857#endif
1796}; 1858};
1797 1859
1798static int proc_tgid_base_readdir(struct file * filp, 1860static int proc_tgid_base_readdir(struct file * filp,
@@ -2068,6 +2130,9 @@ static struct pid_entry tid_base_stuff[] = {
2068#ifdef CONFIG_AUDITSYSCALL 2130#ifdef CONFIG_AUDITSYSCALL
2069 REG("loginuid", S_IWUSR|S_IRUGO, loginuid), 2131 REG("loginuid", S_IWUSR|S_IRUGO, loginuid),
2070#endif 2132#endif
2133#ifdef CONFIG_FAULT_INJECTION
2134 REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
2135#endif
2071}; 2136};
2072 2137
2073static int proc_tid_base_readdir(struct file * filp, 2138static int proc_tid_base_readdir(struct file * filp,
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h
index 4df4902bc8d8..a525f9b9f015 100644
--- a/include/linux/fault-inject.h
+++ b/include/linux/fault-inject.h
@@ -17,6 +17,7 @@ struct fault_attr {
17 atomic_t times; 17 atomic_t times;
18 atomic_t space; 18 atomic_t space;
19 unsigned long verbose; 19 unsigned long verbose;
20 u32 task_filter;
20 21
21 unsigned long count; 22 unsigned long count;
22 23
@@ -30,6 +31,7 @@ struct fault_attr {
30 struct dentry *times_file; 31 struct dentry *times_file;
31 struct dentry *space_file; 32 struct dentry *space_file;
32 struct dentry *verbose_file; 33 struct dentry *verbose_file;
34 struct dentry *task_filter_file;
33 } dentries; 35 } dentries;
34 36
35#endif 37#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f0317edea141..ad9c46071ff8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1045,6 +1045,9 @@ struct task_struct {
1045#ifdef CONFIG_TASK_DELAY_ACCT 1045#ifdef CONFIG_TASK_DELAY_ACCT
1046 struct task_delay_info *delays; 1046 struct task_delay_info *delays;
1047#endif 1047#endif
1048#ifdef CONFIG_FAULT_INJECTION
1049 int make_it_fail;
1050#endif
1048}; 1051};
1049 1052
1050static inline pid_t process_group(struct task_struct *tsk) 1053static inline pid_t process_group(struct task_struct *tsk)
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
index a7cb3afd132a..03468609d701 100644
--- a/lib/fault-inject.c
+++ b/lib/fault-inject.c
@@ -5,6 +5,7 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/fs.h> 6#include <linux/fs.h>
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/interrupt.h>
8#include <linux/fault-inject.h> 9#include <linux/fault-inject.h>
9 10
10/* 11/*
@@ -44,6 +45,11 @@ static void fail_dump(struct fault_attr *attr)
44 45
45#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) 46#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
46 47
48static int fail_task(struct fault_attr *attr, struct task_struct *task)
49{
50 return !in_interrupt() && task->make_it_fail;
51}
52
47/* 53/*
48 * This code is stolen from failmalloc-1.0 54 * This code is stolen from failmalloc-1.0
49 * http://www.nongnu.org/failmalloc/ 55 * http://www.nongnu.org/failmalloc/
@@ -51,6 +57,9 @@ static void fail_dump(struct fault_attr *attr)
51 57
52int should_fail(struct fault_attr *attr, ssize_t size) 58int should_fail(struct fault_attr *attr, ssize_t size)
53{ 59{
60 if (attr->task_filter && !fail_task(attr, current))
61 return 0;
62
54 if (atomic_read(&attr->times) == 0) 63 if (atomic_read(&attr->times) == 0)
55 return 0; 64 return 0;
56 65
@@ -135,6 +144,9 @@ void cleanup_fault_attr_dentries(struct fault_attr *attr)
135 debugfs_remove(attr->dentries.verbose_file); 144 debugfs_remove(attr->dentries.verbose_file);
136 attr->dentries.verbose_file = NULL; 145 attr->dentries.verbose_file = NULL;
137 146
147 debugfs_remove(attr->dentries.task_filter_file);
148 attr->dentries.task_filter_file = NULL;
149
138 if (attr->dentries.dir) 150 if (attr->dentries.dir)
139 WARN_ON(!simple_empty(attr->dentries.dir)); 151 WARN_ON(!simple_empty(attr->dentries.dir));
140 152
@@ -169,9 +181,12 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
169 attr->dentries.verbose_file = 181 attr->dentries.verbose_file =
170 debugfs_create_ul("verbose", mode, dir, &attr->verbose); 182 debugfs_create_ul("verbose", mode, dir, &attr->verbose);
171 183
184 attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
185 mode, dir, &attr->task_filter);
186
172 if (!attr->dentries.probability_file || !attr->dentries.interval_file 187 if (!attr->dentries.probability_file || !attr->dentries.interval_file
173 || !attr->dentries.times_file || !attr->dentries.space_file 188 || !attr->dentries.times_file || !attr->dentries.space_file
174 || !attr->dentries.verbose_file) 189 || !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
175 goto fail; 190 goto fail;
176 191
177 return 0; 192 return 0;