lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Sat, 28 Nov 2009 23:39:53 -0500
From:	Masami Hiramatsu <mhiramat@...hat.com>
To:	Oleg Nesterov <oleg@...hat.com>
CC:	KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>,
	linux-kernel@...r.kernel.org, dhowells@...hat.com,
	hidehiro.kawai.ez@...achi.com, lethal@...ux-sh.org, mingo@...e.hu,
	roland@...hat.com, vapier@...too.org,
	Takahiro Yasui <tyasui@...hat.com>
Subject: [PATCH v2] mm: Introduce coredump parameter structure

Introduce coredump parameter data structure (struct coredump_params)
for simplifying binfmt->core_dump() arguments.

Changes in v2:
  - Don't remove DUMP_WRITE() macro.

Signed-off-by: Masami Hiramatsu <mhiramat@...hat.com>
Suggested-by: Ingo Molnar <mingo@...e.hu>
Cc: Hidehiro Kawai <hidehiro.kawai.ez@...achi.com>
Cc: Andrew Morton <akpm@...ux-foundation.org>
Cc: Oleg Nesterov <oleg@...hat.com>
Cc: Roland McGrath <roland@...hat.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>
---

Andrew, please replace the previous buggy patch with this version.

Thank you,

   fs/binfmt_aout.c        |   13 +++++++------
   fs/binfmt_elf.c         |   24 +++++++++++++-----------
   fs/binfmt_elf_fdpic.c   |   29 +++++++++++++++--------------
   fs/binfmt_flat.c        |    6 +++---
   fs/binfmt_som.c         |    2 +-
   fs/exec.c               |   38 +++++++++++++++++++++-----------------
   include/linux/binfmts.h |   10 +++++++++-
   7 files changed, 69 insertions(+), 53 deletions(-)


diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index b639dcf..346b694 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -32,7 +32,7 @@

   static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
   static int load_aout_library(struct file*);
-static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int aout_core_dump(struct coredump_params *cprm);

   static struct linux_binfmt aout_format = {
   	.module		= THIS_MODULE,
@@ -89,8 +89,9 @@ if (file->f_op->llseek) { \
    * dumping of the process results in another error..
    */

-static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int aout_core_dump(struct coredump_params *cprm)
   {
+	struct file *file = cprm->file;
   	mm_segment_t fs;
   	int has_dumped = 0;
   	unsigned long dump_start, dump_size;
@@ -108,16 +109,16 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, u
   	current->flags |= PF_DUMPCORE;
          	strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
   	dump.u_ar0 = offsetof(struct user, regs);
-	dump.signal = signr;
-	aout_dump_thread(regs, &dump);
+	dump.signal = cprm->signr;
+	aout_dump_thread(cprm->regs, &dump);

   /* If the size of the dump file exceeds the rlimit, then see what would happen
      if we wrote the stack, but not the data area.  */
-	if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
+	if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > cprm->limit)
   		dump.u_dsize = 0;

   /* Make sure we have enough room to write the stack and data areas. */
-	if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
+	if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
   		dump.u_ssize = 0;

   /* make sure we actually have a data and stack area to dump */
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index b9b3bb5..4ee5bb2 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -45,7 +45,7 @@ static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
    * don't even try.
    */
   #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int elf_core_dump(struct coredump_params *cprm);
   #else
   #define elf_core_dump	NULL
   #endif
@@ -1277,8 +1277,9 @@ static int writenote(struct memelfnote *men, struct file *file,
   }
   #undef DUMP_WRITE

-#define DUMP_WRITE(addr, nr)	\
-	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+#define DUMP_WRITE(addr, nr)				\
+	if ((size += (nr)) > cprm->limit ||		\
+	    !dump_write(cprm->file, (addr), (nr)))	\
   		goto end_coredump;

   static void fill_elf_header(struct elfhdr *elf, int segs,
@@ -1906,7 +1907,7 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
    * and then they are actually written out.  If we run out of core limit
    * we just truncate.
    */
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int elf_core_dump(struct coredump_params *cprm)
   {
   	int has_dumped = 0;
   	mm_segment_t fs;
@@ -1952,7 +1953,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
   	 * notes.  This also sets up the file header.
   	 */
   	if (!fill_note_info(elf, segs + 1, /* including notes section */
-			    &info, signr, regs))
+			    &info, cprm->signr, cprm->regs))
   		goto cleanup;

   	has_dumped = 1;
@@ -2014,14 +2015,14 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
   #endif

    	/* write out the notes section */
-	if (!write_note_info(&info, file, &foffset))
+	if (!write_note_info(&info, cprm->file, &foffset))
   		goto end_coredump;

-	if (elf_coredump_extra_notes_write(file, &foffset))
+	if (elf_coredump_extra_notes_write(cprm->file, &foffset))
   		goto end_coredump;

   	/* Align to page */
-	if (!dump_seek(file, dataoff - foffset))
+	if (!dump_seek(cprm->file, dataoff - foffset))
   		goto end_coredump;

   	for (vma = first_vma(current, gate_vma); vma != NULL;
@@ -2038,12 +2039,13 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
   			page = get_dump_page(addr);
   			if (page) {
   				void *kaddr = kmap(page);
-				stop = ((size += PAGE_SIZE) > limit) ||
-					!dump_write(file, kaddr, PAGE_SIZE);
+				stop = ((size += PAGE_SIZE) > cprm->limit) ||
+					!dump_write(cprm->file, kaddr,
+						    PAGE_SIZE);
   				kunmap(page);
   				page_cache_release(page);
   			} else
-				stop = !dump_seek(file, PAGE_SIZE);
+				stop = !dump_seek(cprm->file, PAGE_SIZE);
   			if (stop)
   				goto end_coredump;
   		}
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 38502c6..917e1b4 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -76,7 +76,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
   					     struct file *, struct mm_struct *);

   #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *, unsigned long limit);
+static int elf_fdpic_core_dump(struct coredump_params *cprm);
   #endif

   static struct linux_binfmt elf_fdpic_format = {
@@ -1325,8 +1325,9 @@ static int writenote(struct memelfnote *men, struct file *file)
   #undef DUMP_WRITE
   #undef DUMP_SEEK

-#define DUMP_WRITE(addr, nr)	\
-	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+#define DUMP_WRITE(addr, nr)				\
+	if ((size += (nr)) > cprm->limit ||		\
+	    !dump_write(cprm->file, (addr), (nr)))	\
   		goto end_coredump;

   static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
@@ -1581,8 +1582,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
    * and then they are actually written out.  If we run out of core limit
    * we just truncate.
    */
-static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
-			       struct file *file, unsigned long limit)
+static int elf_fdpic_core_dump(struct coredump_params *cprm)
   {
   #define	NUM_NOTES	6
   	int has_dumped = 0;
@@ -1641,7 +1641,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
   		goto cleanup;
   #endif

-	if (signr) {
+	if (cprm->signr) {
   		struct core_thread *ct;
   		struct elf_thread_status *tmp;

@@ -1660,14 +1660,14 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
   			int sz;

   			tmp = list_entry(t, struct elf_thread_status, list);
-			sz = elf_dump_thread_status(signr, tmp);
+			sz = elf_dump_thread_status(cprm->signr, tmp);
   			thread_status_size += sz;
   		}
   	}

   	/* now collect the dump for the current */
-	fill_prstatus(prstatus, current, signr);
-	elf_core_copy_regs(&prstatus->pr_reg, regs);
+	fill_prstatus(prstatus, current, cprm->signr);
+	elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);

   	segs = current->mm->map_count;
   #ifdef ELF_CORE_EXTRA_PHDRS
@@ -1702,7 +1702,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,

     	/* Try to dump the FPU. */
   	if ((prstatus->pr_fpvalid =
-	     elf_core_copy_task_fpregs(current, regs, fpu)))
+	     elf_core_copy_task_fpregs(current, cprm->regs, fpu)))
   		fill_note(notes + numnote++,
   			  "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
   #ifdef ELF_CORE_COPY_XFPREGS
@@ -1773,7 +1773,7 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,

    	/* write out the notes section */
   	for (i = 0; i < numnote; i++)
-		if (!writenote(notes + i, file))
+		if (!writenote(notes + i, cprm->file))
   			goto end_coredump;

   	/* write out the thread status notes section */
@@ -1782,14 +1782,15 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
   				list_entry(t, struct elf_thread_status, list);

   		for (i = 0; i < tmp->num_notes; i++)
-			if (!writenote(&tmp->notes[i], file))
+			if (!writenote(&tmp->notes[i], cprm->file))
   				goto end_coredump;
   	}

-	if (!dump_seek(file, dataoff))
+	if (!dump_seek(cprm->file, dataoff))
   		goto end_coredump;

-	if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0)
+	if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
+				    mm_flags) < 0)
   		goto end_coredump;

   #ifdef ELF_CORE_WRITE_EXTRA_DATA
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index a279665..d4a00ea 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -87,7 +87,7 @@ static int load_flat_shared_library(int id, struct lib_info *p);
   #endif

   static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int flat_core_dump(struct coredump_params *cprm);

   static struct linux_binfmt flat_format = {
   	.module		= THIS_MODULE,
@@ -102,10 +102,10 @@ static struct linux_binfmt flat_format = {
    * Currently only a stub-function.
    */

-static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int flat_core_dump(struct coredump_params *cprm)
   {
   	printk("Process %s:%d received signr %d and should have core dumped\n",
-			current->comm, current->pid, (int) signr);
+			current->comm, current->pid, (int) cprm->signr);
   	return(1);
   }

diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index eff74b9..2a9b533 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -43,7 +43,7 @@ static int load_som_library(struct file *);
    * don't even try.
    */
   #if 0
-static int som_core_dump(long signr, struct pt_regs *regs, unsigned long limit);
+static int som_core_dump(struct coredump_params *cprm);
   #else
   #define som_core_dump	NULL
   #endif
diff --git a/fs/exec.c b/fs/exec.c
index ba112bd..5daf7d5 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1756,17 +1756,20 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
   	struct mm_struct *mm = current->mm;
   	struct linux_binfmt * binfmt;
   	struct inode * inode;
-	struct file * file;
   	const struct cred *old_cred;
   	struct cred *cred;
   	int retval = 0;
   	int flag = 0;
   	int ispipe = 0;
-	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
   	char **helper_argv = NULL;
   	int helper_argc = 0;
   	int dump_count = 0;
   	static atomic_t core_dump_count = ATOMIC_INIT(0);
+	struct coredump_params cprm = {
+		.signr = signr,
+		.regs = regs,
+		.limit = current->signal->rlim[RLIMIT_CORE].rlim_cur,
+	};

   	audit_core_dumps(signr);

@@ -1822,15 +1825,15 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
   	ispipe = format_corename(corename, signr);
   	unlock_kernel();

-	if ((!ispipe) && (core_limit < binfmt->min_coredump))
+	if ((!ispipe) && (cprm.limit < binfmt->min_coredump))
   		goto fail_unlock;

    	if (ispipe) {
-		if (core_limit == 0) {
+		if (cprm.limit == 0) {
   			/*
   			 * Normally core limits are irrelevant to pipes, since
   			 * we're not writing to the file system, but we use
-			 * core_limit of 0 here as a speacial value. Any
+			 * cprm.limit of 0 here as a speacial value. Any
   			 * non-zero limit gets set to RLIM_INFINITY below, but
   			 * a limit of 0 skips the dump.  This is a consistent
   			 * way to catch recursive crashes.  We can still crash
@@ -1863,25 +1866,25 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
   			goto fail_dropcount;
   		}

-		core_limit = RLIM_INFINITY;
+		cprm.limit = RLIM_INFINITY;

   		/* SIGPIPE can happen, but it's just never processed */
   		if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL,
-				&file)) {
+				&cprm.file)) {
    			printk(KERN_INFO "Core dump to %s pipe failed\n",
   			       corename);
   			goto fail_dropcount;
    		}
    	} else
- 		file = filp_open(corename,
+		cprm.file = filp_open(corename,
   				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
   				 0600);
-	if (IS_ERR(file))
+	if (IS_ERR(cprm.file))
   		goto fail_dropcount;
-	inode = file->f_path.dentry->d_inode;
+	inode = cprm.file->f_path.dentry->d_inode;
   	if (inode->i_nlink > 1)
   		goto close_fail;	/* multiple links - don't dump */
-	if (!ispipe && d_unhashed(file->f_path.dentry))
+	if (!ispipe && d_unhashed(cprm.file->f_path.dentry))
   		goto close_fail;

   	/* AK: actually i see no reason to not allow this for named pipes etc.,
@@ -1894,21 +1897,22 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
   	 */
   	if (inode->i_uid != current_fsuid())
   		goto close_fail;
-	if (!file->f_op)
+	if (!cprm.file->f_op)
   		goto close_fail;
-	if (!file->f_op->write)
+	if (!cprm.file->f_op->write)
   		goto close_fail;
-	if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
+	if (!ispipe &&
+	    do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file) != 0)
   		goto close_fail;

-	retval = binfmt->core_dump(signr, regs, file, core_limit);
+	retval = binfmt->core_dump(&cprm);

   	if (retval)
   		current->signal->group_exit_code |= 0x80;
   close_fail:
   	if (ispipe && core_pipe_limit)
-		wait_for_dump_helpers(file);
-	filp_close(file, NULL);
+		wait_for_dump_helpers(cprm.file);
+	filp_close(cprm.file, NULL);
   fail_dropcount:
   	if (dump_count)
   		atomic_dec(&core_dump_count);
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index aece486..cd4349b 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -68,6 +68,14 @@ struct linux_binprm{

   #define BINPRM_MAX_RECURSION 4

+/* Function parameter for binfmt->coredump */
+struct coredump_params {
+	long signr;
+	struct pt_regs *regs;
+	struct file *file;
+	unsigned long limit;
+};
+
   /*
    * This structure defines the functions that are used to load the binary formats that
    * linux accepts.
@@ -77,7 +85,7 @@ struct linux_binfmt {
   	struct module *module;
   	int (*load_binary)(struct linux_binprm *, struct  pt_regs * regs);
   	int (*load_shlib)(struct file *);
-	int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+	int (*core_dump)(struct coredump_params *cprm);
   	unsigned long min_coredump;	/* minimal dump size */
   	int hasvdso;
   };
-- 
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division

e-mail: mhiramat@...hat.com

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists