aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKawai, Hidehiro <hidehiro.kawai.ez@hitachi.com>2007-07-19 04:48:28 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:47 -0400
commit3cb4a0bb1e773e3c41800b33a3f7dab32bd06c64 (patch)
treed363522865706f0674b7b104a8fc7b151f336764
parent6c5d523826dc639df709ed0f88c5d2ce25379652 (diff)
coredump masking: add an interface for core dump filter
This patch adds an interface to set/reset flags which determines each memory segment should be dumped or not when a core file is generated. /proc/<pid>/coredump_filter file is provided to access the flags. You can change the flag status for a particular process by writing to or reading from the file. The flag status is inherited to the child process when it is created. Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: David Howells <dhowells@redhat.com> Cc: Hugh Dickins <hugh@veritas.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/proc/base.c89
-rw-r--r--include/linux/sched.h14
-rw-r--r--kernel/fork.c2
3 files changed, 105 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 49b3ab0175e0..3c77d5a64e7c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -72,6 +72,7 @@
72#include <linux/poll.h> 72#include <linux/poll.h>
73#include <linux/nsproxy.h> 73#include <linux/nsproxy.h>
74#include <linux/oom.h> 74#include <linux/oom.h>
75#include <linux/elf.h>
75#include "internal.h" 76#include "internal.h"
76 77
77/* NOTE: 78/* NOTE:
@@ -1785,6 +1786,91 @@ static const struct inode_operations proc_attr_dir_inode_operations = {
1785 1786
1786#endif 1787#endif
1787 1788
1789#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
1790static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
1791 size_t count, loff_t *ppos)
1792{
1793 struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
1794 struct mm_struct *mm;
1795 char buffer[PROC_NUMBUF];
1796 size_t len;
1797 int ret;
1798
1799 if (!task)
1800 return -ESRCH;
1801
1802 ret = 0;
1803 mm = get_task_mm(task);
1804 if (mm) {
1805 len = snprintf(buffer, sizeof(buffer), "%08lx\n",
1806 ((mm->flags & MMF_DUMP_FILTER_MASK) >>
1807 MMF_DUMP_FILTER_SHIFT));
1808 mmput(mm);
1809 ret = simple_read_from_buffer(buf, count, ppos, buffer, len);
1810 }
1811
1812 put_task_struct(task);
1813
1814 return ret;
1815}
1816
1817static ssize_t proc_coredump_filter_write(struct file *file,
1818 const char __user *buf,
1819 size_t count,
1820 loff_t *ppos)
1821{
1822 struct task_struct *task;
1823 struct mm_struct *mm;
1824 char buffer[PROC_NUMBUF], *end;
1825 unsigned int val;
1826 int ret;
1827 int i;
1828 unsigned long mask;
1829
1830 ret = -EFAULT;
1831 memset(buffer, 0, sizeof(buffer));
1832 if (count > sizeof(buffer) - 1)
1833 count = sizeof(buffer) - 1;
1834 if (copy_from_user(buffer, buf, count))
1835 goto out_no_task;
1836
1837 ret = -EINVAL;
1838 val = (unsigned int)simple_strtoul(buffer, &end, 0);
1839 if (*end == '\n')
1840 end++;
1841 if (end - buffer == 0)
1842 goto out_no_task;
1843
1844 ret = -ESRCH;
1845 task = get_proc_task(file->f_dentry->d_inode);
1846 if (!task)
1847 goto out_no_task;
1848
1849 ret = end - buffer;
1850 mm = get_task_mm(task);
1851 if (!mm)
1852 goto out_no_mm;
1853
1854 for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
1855 if (val & mask)
1856 set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
1857 else
1858 clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);
1859 }
1860
1861 mmput(mm);
1862 out_no_mm:
1863 put_task_struct(task);
1864 out_no_task:
1865 return ret;
1866}
1867
1868static const struct file_operations proc_coredump_filter_operations = {
1869 .read = proc_coredump_filter_read,
1870 .write = proc_coredump_filter_write,
1871};
1872#endif
1873
1788/* 1874/*
1789 * /proc/self: 1875 * /proc/self:
1790 */ 1876 */
@@ -2005,6 +2091,9 @@ static const struct pid_entry tgid_base_stuff[] = {
2005#ifdef CONFIG_FAULT_INJECTION 2091#ifdef CONFIG_FAULT_INJECTION
2006 REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject), 2092 REG("make-it-fail", S_IRUGO|S_IWUSR, fault_inject),
2007#endif 2093#endif
2094#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
2095 REG("coredump_filter", S_IRUGO|S_IWUSR, coredump_filter),
2096#endif
2008#ifdef CONFIG_TASK_IO_ACCOUNTING 2097#ifdef CONFIG_TASK_IO_ACCOUNTING
2009 INF("io", S_IRUGO, pid_io_accounting), 2098 INF("io", S_IRUGO, pid_io_accounting),
2010#endif 2099#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8dbd08366400..94f624aef017 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -349,8 +349,22 @@ extern void set_dumpable(struct mm_struct *mm, int value);
349extern int get_dumpable(struct mm_struct *mm); 349extern int get_dumpable(struct mm_struct *mm);
350 350
351/* mm flags */ 351/* mm flags */
352/* dumpable bits */
352#define MMF_DUMPABLE 0 /* core dump is permitted */ 353#define MMF_DUMPABLE 0 /* core dump is permitted */
353#define MMF_DUMP_SECURELY 1 /* core file is readable only by root */ 354#define MMF_DUMP_SECURELY 1 /* core file is readable only by root */
355#define MMF_DUMPABLE_BITS 2
356
357/* coredump filter bits */
358#define MMF_DUMP_ANON_PRIVATE 2
359#define MMF_DUMP_ANON_SHARED 3
360#define MMF_DUMP_MAPPED_PRIVATE 4
361#define MMF_DUMP_MAPPED_SHARED 5
362#define MMF_DUMP_FILTER_SHIFT MMF_DUMPABLE_BITS
363#define MMF_DUMP_FILTER_BITS 4
364#define MMF_DUMP_FILTER_MASK \
365 (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
366#define MMF_DUMP_FILTER_DEFAULT \
367 ((1 << MMF_DUMP_ANON_PRIVATE) | (1 << MMF_DUMP_ANON_SHARED))
354 368
355struct mm_struct { 369struct mm_struct {
356 struct vm_area_struct * mmap; /* list of VMAs */ 370 struct vm_area_struct * mmap; /* list of VMAs */
diff --git a/kernel/fork.c b/kernel/fork.c
index ba39bdb2a7b8..469838998220 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -334,6 +334,8 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
334 atomic_set(&mm->mm_count, 1); 334 atomic_set(&mm->mm_count, 1);
335 init_rwsem(&mm->mmap_sem); 335 init_rwsem(&mm->mmap_sem);
336 INIT_LIST_HEAD(&mm->mmlist); 336 INIT_LIST_HEAD(&mm->mmlist);
337 mm->flags = (current->mm) ? current->mm->flags
338 : MMF_DUMP_FILTER_DEFAULT;
337 mm->core_waiters = 0; 339 mm->core_waiters = 0;
338 mm->nr_ptes = 0; 340 mm->nr_ptes = 0;
339 set_mm_counter(mm, file_rss, 0); 341 set_mm_counter(mm, file_rss, 0);