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]
Message-ID: <4B128ECF.9020906@redhat.com>
Date:	Sun, 29 Nov 2009 10:10:07 -0500
From:	Masami Hiramatsu <mhiramat@...hat.com>
To:	Andrew Morton <akpm@...ux-foundation.org>, mingo@...e.hu
CC:	Oleg Nesterov <oleg@...hat.com>,
	KOSAKI Motohiro <kosaki.motohiro@...fujitsu.com>,
	LKML <linux-kernel@...r.kernel.org>, dhowells@...hat.com,
	hidehiro.kawai.ez@...achi.com, lethal@...ux-sh.org,
	roland@...hat.com, vapier@...too.org,
	Takahiro Yasui <tyasui@...hat.com>
Subject: [PATCH][RFC] tracepoint: signal coredump (Re: [PATCH v2] mm: Introduce
 coredump parameter structure)

Hi Ingo and Andrew,

By the way, I'd like to push signal_coredump tracepoint (which I attached)
on these patches, and it also depends on signal-tracepoint patch series
which already picked up to -tip tree.

So, in this case, is it possible to pick these patches (coredump parameter
and mm->flags consistency fix (http://patchwork.kernel.org/patch/60917/))
to -tip tree too?

Thank you,

Masami Hiramatsu wrote:
> 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


View attachment "tp-signal-coredump.patch" of type "text/plain" (4956 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ