Skip to content
Snippets Groups Projects
exec.c 48.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 			 * 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__);
    
    		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",
    
    			goto close_fail;
    
    	} else {
    		struct inode *inode;
    
    		if (cprm.limit < binfmt->min_coredump)
    			goto fail_unlock;
    
    
    				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
    				 0600);
    
    		if (IS_ERR(cprm.file))
    			goto fail_unlock;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    		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 (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;
    	}
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	retval = binfmt->core_dump(&cprm);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	if (retval)
    		current->signal->group_exit_code |= 0x80;
    
    		wait_for_dump_helpers(cprm.file);
    
    close_fail:
    	if (cprm.file)
    		filp_close(cprm.file, NULL);
    
    	if (ispipe)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    fail_unlock:
    
    	coredump_finish(mm);
    
    	revert_creds(old_cred);
    
    	put_cred(cred);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    fail:
    
    	return;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    
    /*
     * 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);