Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 198737
b: refs/heads/master
c: 898b374
h: refs/heads/master
i:
  198735: 120599c
v: v3
  • Loading branch information
Neil Horman authored and Linus Torvalds committed May 27, 2010
1 parent 9b8da11 commit c567126
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 97 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a06a4dc3a08201ff6a8a958f935b3cbf7744115f
refs/heads/master: 898b374af6f71041bd3bceebe257e564f3f1d458
63 changes: 56 additions & 7 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,50 @@ static void wait_for_dump_helpers(struct file *file)
}


/*
* uhm_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 file *rp, *wp;
struct fdtable *fdt;
struct coredump_params *cp = (struct coredump_params *)info->data;
struct files_struct *cf = current->files;

wp = create_write_pipe(0);
if (IS_ERR(wp))
return PTR_ERR(wp);

rp = create_read_pipe(wp, 0);
if (IS_ERR(rp)) {
free_write_pipe(wp);
return PTR_ERR(rp);
}

cp->file = wp;

sys_close(0);
fd_install(0, rp);
spin_lock(&cf->file_lock);
fdt = files_fdtable(cf);
FD_SET(0, fdt->open_fds);
FD_CLR(0, fdt->close_on_exec);
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;
Expand Down Expand Up @@ -1874,23 +1918,23 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
goto fail_unlock;

if (ispipe) {
if (cprm.limit == 0) {
if (cprm.limit == 1) {
/*
* Normally core limits are irrelevant to pipes, since
* we're not writing to the file system, but we use
* cprm.limit of 0 here as a speacial value. Any
* non-zero limit gets set to RLIM_INFINITY below, but
* cprm.limit of 1 here as a speacial value. Any
* non-1 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
* if the core_pattern binary sets RLIM_CORE = !0
* 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 0\n",
"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;
Expand All @@ -1914,8 +1958,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
cprm.limit = RLIM_INFINITY;

/* SIGPIPE can happen, but it's just never processed */
if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL,
&cprm.file)) {
cprm.file = NULL;
if (call_usermodehelper_fns(helper_argv[0], helper_argv, NULL,
UMH_WAIT_EXEC, umh_pipe_setup,
NULL, &cprm)) {
if (cprm.file)
filp_close(cprm.file, NULL);

printk(KERN_INFO "Core dump to %s pipe failed\n",
corename);
goto fail_dropcount;
Expand Down
7 changes: 0 additions & 7 deletions trunk/include/linux/kmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ struct subprocess_info {
char **envp;
enum umh_wait wait;
int retval;
struct file *stdin;
int (*init)(struct subprocess_info *info);
void (*cleanup)(struct subprocess_info *info);
void *data;
Expand All @@ -75,8 +74,6 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
/* Set various pieces of state into the subprocess_info structure */
void call_usermodehelper_setkeys(struct subprocess_info *info,
struct key *session_keyring);
int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
struct file **filp);
void call_usermodehelper_setfns(struct subprocess_info *info,
int (*init)(struct subprocess_info *info),
void (*cleanup)(struct subprocess_info *info),
Expand Down Expand Up @@ -132,10 +129,6 @@ call_usermodehelper_keys(char *path, char **argv, char **envp,

extern void usermodehelper_init(void);

struct file;
extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[],
struct file **filp);

extern int usermodehelper_disable(void);
extern void usermodehelper_enable(void);

Expand Down
82 changes: 0 additions & 82 deletions trunk/kernel/kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,23 +147,6 @@ static int ____call_usermodehelper(void *data)
commit_creds(sub_info->cred);
sub_info->cred = NULL;

/* Install input pipe when needed */
if (sub_info->stdin) {
struct files_struct *f = current->files;
struct fdtable *fdt;
/* no races because files should be private here */
sys_close(0);
fd_install(0, sub_info->stdin);
spin_lock(&f->file_lock);
fdt = files_fdtable(f);
FD_SET(0, fdt->open_fds);
FD_CLR(0, fdt->close_on_exec);
spin_unlock(&f->file_lock);

/* and disallow core files too */
current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0};
}

/* We can run anywhere, unlike our parent keventd(). */
set_cpus_allowed_ptr(current, cpu_all_mask);

Expand Down Expand Up @@ -428,35 +411,6 @@ void call_usermodehelper_setfns(struct subprocess_info *info,
}
EXPORT_SYMBOL(call_usermodehelper_setfns);

/**
* call_usermodehelper_stdinpipe - set up a pipe to be used for stdin
* @sub_info: a subprocess_info returned by call_usermodehelper_setup
* @filp: set to the write-end of a pipe
*
* This constructs a pipe, and sets the read end to be the stdin of the
* subprocess, and returns the write-end in *@filp.
*/
int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
struct file **filp)
{
struct file *f;

f = create_write_pipe(0);
if (IS_ERR(f))
return PTR_ERR(f);
*filp = f;

f = create_read_pipe(f, 0);
if (IS_ERR(f)) {
free_write_pipe(*filp);
return PTR_ERR(f);
}
sub_info->stdin = f;

return 0;
}
EXPORT_SYMBOL(call_usermodehelper_stdinpipe);

/**
* call_usermodehelper_exec - start a usermode application
* @sub_info: information about the subprocessa
Expand Down Expand Up @@ -504,42 +458,6 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info,
}
EXPORT_SYMBOL(call_usermodehelper_exec);

/**
* call_usermodehelper_pipe - call a usermode helper process with a pipe stdin
* @path: path to usermode executable
* @argv: arg vector for process
* @envp: environment for process
* @filp: set to the write-end of a pipe
*
* This is a simple wrapper which executes a usermode-helper function
* with a pipe as stdin. It is implemented entirely in terms of
* lower-level call_usermodehelper_* functions.
*/
int call_usermodehelper_pipe(char *path, char **argv, char **envp,
struct file **filp)
{
struct subprocess_info *sub_info;
int ret;

sub_info = call_usermodehelper_setup(path, argv, envp,
GFP_KERNEL);
if (sub_info == NULL)
return -ENOMEM;

ret = call_usermodehelper_stdinpipe(sub_info, filp);
if (ret < 0) {
call_usermodehelper_freeinfo(sub_info);
return ret;
}

ret = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
if (ret < 0) /* Failed to execute helper, close pipe */
filp_close(*filp, NULL);

return ret;
}
EXPORT_SYMBOL(call_usermodehelper_pipe);

void __init usermodehelper_init(void)
{
khelper_wq = create_singlethread_workqueue("khelper");
Expand Down

0 comments on commit c567126

Please sign in to comment.