|
@@ -72,6 +72,7 @@
|
|
|
#include <linux/poll.h>
|
|
|
#include <linux/nsproxy.h>
|
|
|
#include <linux/oom.h>
|
|
|
+#include <linux/elf.h>
|
|
|
#include "internal.h"
|
|
|
|
|
|
/* NOTE:
|
|
@@ -1785,6 +1786,91 @@ static const struct inode_operations proc_attr_dir_inode_operations = {
|
|
|
|
|
|
#endif
|
|
|
|
|
|
+#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
|
|
|
+static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
|
|
|
+ size_t count, loff_t *ppos)
|
|
|
+{
|
|
|
+ struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
|
|
|
+ struct mm_struct *mm;
|
|
|
+ char buffer[PROC_NUMBUF];
|
|
|
+ size_t len;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!task)
|
|
|
+ return -ESRCH;
|
|
|
+
|
|
|
+ ret = 0;
|
|
|
+ mm = get_task_mm(task);
|
|
|
+ if (mm) {
|
|
|
+ len = snprintf(buffer, sizeof(buffer), "%08lx\n",
|
|
|
+ ((mm->flags & MMF_DUMP_FILTER_MASK) >>
|
|
|
+ MMF_DUMP_FILTER_SHIFT));
|
|
|
+ mmput(mm);
|
|
|
+ ret = simple_read_from_buffer(buf, count, ppos, buffer, len);
|
|
|
+ }
|
|
|
+
|
|
|
+ put_task_struct(task);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t proc_coredump_filter_write(struct file *file,
|
|
|
+ const char __user *buf,
|
|
|
+ size_t count,
|
|
|
+ loff_t *ppos)
|
|
|
+{
|
|
|
+ struct task_struct *task;
|
|
|
+ struct mm_struct *mm;
|
|
|
+ char buffer[PROC_NUMBUF], *end;
|
|
|
+ unsigned int val;
|
|
|
+ int ret;
|
|
|
+ int i;
|
|
|
+ unsigned long mask;
|
|
|
+
|
|
|
+ ret = -EFAULT;
|
|
|
+ memset(buffer, 0, sizeof(buffer));
|
|
|
+ if (count > sizeof(buffer) - 1)
|
|
|
+ count = sizeof(buffer) - 1;
|
|
|
+ if (copy_from_user(buffer, buf, count))
|
|
|
+ goto out_no_task;
|
|
|
+
|
|
|
+ ret = -EINVAL;
|
|
|
+ val = (unsigned int)simple_strtoul(buffer, &end, 0);
|
|
|
+ if (*end == '\n')
|
|
|
+ end++;
|
|
|
+ if (end - buffer == 0)
|
|
|
+ goto out_no_task;
|
|
|
+
|
|
|
+ ret = -ESRCH;
|
|
|
+ task = get_proc_task(file->f_dentry->d_inode);
|
|
|
+ if (!task)
|
|
|
+ goto out_no_task;
|
|
|
+
|
|
|
+ ret = end - buffer;
|
|
|
+ mm = get_task_mm(task);
|
|
|
+ if (!mm)
|
|
|
+ goto out_no_mm;
|
|
|
+
|
|
|
+ for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
|
|
|
+ if (val & mask)
|
|
|
+ set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
|
|
|
+ else
|
|
|
+ clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ mmput(mm);
|
|
|
+ out_no_mm:
|
|
|
+ put_task_struct(task);
|
|
|
+ out_no_task:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static const struct file_operations proc_coredump_filter_operations = {
|
|
|
+ .read = proc_coredump_filter_read,
|
|
|
+ .write = proc_coredump_filter_write,
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* /proc/self:
|
|
|
*/
|
|
@@ -2005,6 +2091,9 @@ static const struct pid_entry tgid_base_stuff[] = {
|
|
|
#ifdef CONFIG_FAULT_INJECTION
|
|
|
REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
|
|
|
#endif
|
|
|
+#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
|
|
|
+ REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
|
|
|
+#endif
|
|
|
#ifdef CONFIG_TASK_IO_ACCOUNTING
|
|
|
INF("io", S_IRUGO, pid_io_accounting),
|
|
|
#endif
|