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>] [day] [month] [year] [list]
Message-Id: <20121002154820.a565ec5728901c440bd57349@canb.auug.org.au>
Date:	Tue, 2 Oct 2012 15:48:20 +1000
From:	Stephen Rothwell <sfr@...b.auug.org.au>
To:	Al Viro <viro@...IV.linux.org.uk>
Cc:	linux-next@...r.kernel.org, linux-kernel@...r.kernel.org,
	Alex Kelly <alex.page.kelly@...il.com>,
	Andrew Morton <akpm@...ux-foundation.org>
Subject: linux-next: manual merge of the signal tree with the vfs tree

Hi Al,

Today's linux-next merge of the signal tree got a conflict in fs/exec.c
between commit 5b8a94d461a7 ("coredump: move core dump functionality into
its own file") from the vfs tree and commits 282124d18626 ("generic
kernel_execve()") and 38b983b3461e ("generic sys_execve()") from the signal tree.

I fixed it up (see below) and can carry the fix as necessary (no action
is required).

-- 
Cheers,
Stephen Rothwell                    sfr@...b.auug.org.au

diff --cc fs/exec.c
index 48fb26e,50a1270..0000000
--- a/fs/exec.c
+++ b/fs/exec.c
@@@ -1645,3 -2031,342 +1644,55 @@@ int get_dumpable(struct mm_struct *mm
  {
  	return __get_dumpable(mm->flags);
  }
+ 
 -static void wait_for_dump_helpers(struct file *file)
 -{
 -	struct pipe_inode_info *pipe;
 -
 -	pipe = file->f_path.dentry->d_inode->i_pipe;
 -
 -	pipe_lock(pipe);
 -	pipe->readers++;
 -	pipe->writers--;
 -
 -	while ((pipe->readers > 1) && (!signal_pending(current))) {
 -		wake_up_interruptible_sync(&pipe->wait);
 -		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 -		pipe_wait(pipe);
 -	}
 -
 -	pipe->readers--;
 -	pipe->writers++;
 -	pipe_unlock(pipe);
 -
 -}
 -
 -
 -/*
 - * umh_pipe_setup
 - * helper function to customize the process used
 - * to collect the core in userspace.  Specifically
 - * it sets up a pipe and installs it as fd 0 (stdin)
 - * for the process.  Returns 0 on success, or
 - * PTR_ERR on failure.
 - * Note that it also sets the core limit to 1.  This
 - * is a special value that we use to trap recursive
 - * core dumps
 - */
 -static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
 -{
 -	struct file *files[2];
 -	struct fdtable *fdt;
 -	struct coredump_params *cp = (struct coredump_params *)info->data;
 -	struct files_struct *cf = current->files;
 -	int err = create_pipe_files(files, 0);
 -	if (err)
 -		return err;
 -
 -	cp->file = files[1];
 -
 -	sys_close(0);
 -	fd_install(0, files[0]);
 -	spin_lock(&cf->file_lock);
 -	fdt = files_fdtable(cf);
 -	__set_open_fd(0, fdt);
 -	__clear_close_on_exec(0, fdt);
 -	spin_unlock(&cf->file_lock);
 -
 -	/* and disallow core files too */
 -	current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1};
 -
 -	return 0;
 -}
 -
 -void do_coredump(long signr, int exit_code, struct pt_regs *regs)
 -{
 -	struct core_state core_state;
 -	struct core_name cn;
 -	struct mm_struct *mm = current->mm;
 -	struct linux_binfmt * binfmt;
 -	const struct cred *old_cred;
 -	struct cred *cred;
 -	int retval = 0;
 -	int flag = 0;
 -	int ispipe;
 -	bool need_nonrelative = false;
 -	static atomic_t core_dump_count = ATOMIC_INIT(0);
 -	struct coredump_params cprm = {
 -		.signr = signr,
 -		.regs = regs,
 -		.limit = rlimit(RLIMIT_CORE),
 -		/*
 -		 * We must use the same mm->flags while dumping core to avoid
 -		 * inconsistency of bit flags, since this flag is not protected
 -		 * by any locks.
 -		 */
 -		.mm_flags = mm->flags,
 -	};
 -
 -	audit_core_dumps(signr);
 -
 -	binfmt = mm->binfmt;
 -	if (!binfmt || !binfmt->core_dump)
 -		goto fail;
 -	if (!__get_dumpable(cprm.mm_flags))
 -		goto fail;
 -
 -	cred = prepare_creds();
 -	if (!cred)
 -		goto fail;
 -	/*
 -	 * We cannot trust fsuid as being the "true" uid of the process
 -	 * nor do we know its entire history. We only know it was tainted
 -	 * so we dump it as root in mode 2, and only into a controlled
 -	 * environment (pipe handler or fully qualified path).
 -	 */
 -	if (__get_dumpable(cprm.mm_flags) == SUID_DUMPABLE_SAFE) {
 -		/* Setuid core dump mode */
 -		flag = O_EXCL;		/* Stop rewrite attacks */
 -		cred->fsuid = GLOBAL_ROOT_UID;	/* Dump root private */
 -		need_nonrelative = true;
 -	}
 -
 -	retval = coredump_wait(exit_code, &core_state);
 -	if (retval < 0)
 -		goto fail_creds;
 -
 -	old_cred = override_creds(cred);
 -
 -	/*
 -	 * Clear any false indication of pending signals that might
 -	 * be seen by the filesystem code called to write the core file.
 -	 */
 -	clear_thread_flag(TIF_SIGPENDING);
 -
 -	ispipe = format_corename(&cn, signr);
 -
 - 	if (ispipe) {
 -		int dump_count;
 -		char **helper_argv;
 -
 -		if (ispipe < 0) {
 -			printk(KERN_WARNING "format_corename failed\n");
 -			printk(KERN_WARNING "Aborting core\n");
 -			goto fail_corename;
 -		}
 -
 -		if (cprm.limit == 1) {
 -			/* See umh_pipe_setup() which sets RLIMIT_CORE = 1.
 -			 *
 -			 * Normally core limits are irrelevant to pipes, since
 -			 * we're not writing to the file system, but we use
 -			 * cprm.limit of 1 here as a speacial value, this is a
 -			 * consistent way to catch recursive crashes.
 -			 * We can still crash if the core_pattern binary sets
 -			 * RLIM_CORE = !1, but it runs as root, and can do
 -			 * lots of stupid things.
 -			 *
 -			 * Note that we use task_tgid_vnr here to grab the pid
 -			 * of the process group leader.  That way we get the
 -			 * right pid if a thread in a multi-threaded
 -			 * core_pattern process dies.
 -			 */
 -			printk(KERN_WARNING
 -				"Process %d(%s) has RLIMIT_CORE set to 1\n",
 -				task_tgid_vnr(current), current->comm);
 -			printk(KERN_WARNING "Aborting core\n");
 -			goto fail_unlock;
 -		}
 -		cprm.limit = RLIM_INFINITY;
 -
 -		dump_count = atomic_inc_return(&core_dump_count);
 -		if (core_pipe_limit && (core_pipe_limit < dump_count)) {
 -			printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n",
 -			       task_tgid_vnr(current), current->comm);
 -			printk(KERN_WARNING "Skipping core dump\n");
 -			goto fail_dropcount;
 -		}
 -
 -		helper_argv = argv_split(GFP_KERNEL, cn.corename+1, NULL);
 -		if (!helper_argv) {
 -			printk(KERN_WARNING "%s failed to allocate memory\n",
 -			       __func__);
 -			goto fail_dropcount;
 -		}
 -
 -		retval = call_usermodehelper_fns(helper_argv[0], helper_argv,
 -					NULL, UMH_WAIT_EXEC, umh_pipe_setup,
 -					NULL, &cprm);
 -		argv_free(helper_argv);
 -		if (retval) {
 - 			printk(KERN_INFO "Core dump to %s pipe failed\n",
 -			       cn.corename);
 -			goto close_fail;
 - 		}
 -	} else {
 -		struct inode *inode;
 -
 -		if (cprm.limit < binfmt->min_coredump)
 -			goto fail_unlock;
 -
 -		if (need_nonrelative && cn.corename[0] != '/') {
 -			printk(KERN_WARNING "Pid %d(%s) can only dump core "\
 -				"to fully qualified path!\n",
 -				task_tgid_vnr(current), current->comm);
 -			printk(KERN_WARNING "Skipping core dump\n");
 -			goto fail_unlock;
 -		}
 -
 -		cprm.file = filp_open(cn.corename,
 -				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
 -				 0600);
 -		if (IS_ERR(cprm.file))
 -			goto fail_unlock;
 -
 -		inode = cprm.file->f_path.dentry->d_inode;
 -		if (inode->i_nlink > 1)
 -			goto close_fail;
 -		if (d_unhashed(cprm.file->f_path.dentry))
 -			goto close_fail;
 -		/*
 -		 * AK: actually i see no reason to not allow this for named
 -		 * pipes etc, but keep the previous behaviour for now.
 -		 */
 -		if (!S_ISREG(inode->i_mode))
 -			goto close_fail;
 -		/*
 -		 * Dont allow local users get cute and trick others to coredump
 -		 * into their pre-created files.
 -		 */
 -		if (!uid_eq(inode->i_uid, current_fsuid()))
 -			goto close_fail;
 -		if (!cprm.file->f_op || !cprm.file->f_op->write)
 -			goto close_fail;
 -		if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file))
 -			goto close_fail;
 -	}
 -
 -	retval = binfmt->core_dump(&cprm);
 -	if (retval)
 -		current->signal->group_exit_code |= 0x80;
 -
 -	if (ispipe && core_pipe_limit)
 -		wait_for_dump_helpers(cprm.file);
 -close_fail:
 -	if (cprm.file)
 -		filp_close(cprm.file, NULL);
 -fail_dropcount:
 -	if (ispipe)
 -		atomic_dec(&core_dump_count);
 -fail_unlock:
 -	kfree(cn.corename);
 -fail_corename:
 -	coredump_finish(mm);
 -	revert_creds(old_cred);
 -fail_creds:
 -	put_cred(cred);
 -fail:
 -	return;
 -}
 -
 -/*
 - * Core dumping helper functions.  These are the only things you should
 - * do on a core-file: use only these functions to write out all the
 - * necessary info.
 - */
 -int dump_write(struct file *file, const void *addr, int nr)
 -{
 -	return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr;
 -}
 -EXPORT_SYMBOL(dump_write);
 -
 -int dump_seek(struct file *file, loff_t off)
 -{
 -	int ret = 1;
 -
 -	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
 -		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
 -			return 0;
 -	} else {
 -		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
 -
 -		if (!buf)
 -			return 0;
 -		while (off > 0) {
 -			unsigned long n = off;
 -
 -			if (n > PAGE_SIZE)
 -				n = PAGE_SIZE;
 -			if (!dump_write(file, buf, n)) {
 -				ret = 0;
 -				break;
 -			}
 -			off -= n;
 -		}
 -		free_page((unsigned long)buf);
 -	}
 -	return ret;
 -}
 -EXPORT_SYMBOL(dump_seek);
 -
+ #ifdef __ARCH_WANT_SYS_EXECVE
+ SYSCALL_DEFINE3(execve,
+ 		const char __user *, filename,
+ 		const char __user *const __user *, argv,
+ 		const char __user *const __user *, envp)
+ {
+ 	const char *path = getname(filename);
+ 	int error = PTR_ERR(path);
+ 	if (!IS_ERR(path)) {
+ 		error = do_execve(path, argv, envp, current_pt_regs());
+ 		putname(path);
+ 	}
+ 	return error;
+ }
+ #ifdef CONFIG_COMPAT
+ asmlinkage long compat_sys_execve(const char __user * filename,
+ 	const compat_uptr_t __user * argv,
+ 	const compat_uptr_t __user * envp)
+ {
+ 	const char *path = getname(filename);
+ 	int error = PTR_ERR(path);
+ 	if (!IS_ERR(path)) {
+ 		error = compat_do_execve(path, argv, envp, current_pt_regs());
+ 		putname(path);
+ 	}
+ 	return error;
+ }
+ #endif
+ #endif
+ 
+ #ifdef __ARCH_WANT_KERNEL_EXECVE
+ int kernel_execve(const char *filename,
+ 		  const char *const argv[],
+ 		  const char *const envp[])
+ {
+ 	struct pt_regs *p = current_pt_regs();
+ 	int ret;
+ 
+ 	ret = do_execve(filename,
+ 			(const char __user *const __user *)argv,
+ 			(const char __user *const __user *)envp, p);
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	/*
+ 	 * We were successful.  We won't be returning to our caller, but
+ 	 * instead to user space by manipulating the kernel stack.
+ 	 */
+ 	ret_from_kernel_execve(p);
+ }
+ #endif

Content of type "application/pgp-signature" skipped

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ