Commit e239ca540594cff00adcce163dc332b27015d8e5

Authored by Andi Kleen
Committed by Linus Torvalds
1 parent d6cbd281d1

[PATCH] Create call_usermodehelper_pipe()

A new member in the ever growing family of call_usermode* functions is
born.  The new call_usermodehelper_pipe() function allows to pipe data to
the stdin of the called user mode progam and behaves otherwise like the
normal call_usermodehelp() (except that it always waits for the child to
finish)

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 58 additions and 1 deletions Side-by-side Diff

include/linux/kmod.h
... ... @@ -47,5 +47,9 @@
47 47  
48 48 extern void usermodehelper_init(void);
49 49  
  50 +struct file;
  51 +extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[],
  52 + struct file **filp);
  53 +
50 54 #endif /* __LINUX_KMOD_H__ */
... ... @@ -122,6 +122,7 @@
122 122 struct key *ring;
123 123 int wait;
124 124 int retval;
  125 + struct file *stdin;
125 126 };
126 127  
127 128 /*
128 129  
... ... @@ -145,12 +146,26 @@
145 146  
146 147 key_put(old_session);
147 148  
  149 + /* Install input pipe when needed */
  150 + if (sub_info->stdin) {
  151 + struct files_struct *f = current->files;
  152 + struct fdtable *fdt;
  153 + /* no races because files should be private here */
  154 + sys_close(0);
  155 + fd_install(0, sub_info->stdin);
  156 + spin_lock(&f->file_lock);
  157 + fdt = files_fdtable(f);
  158 + FD_SET(0, fdt->open_fds);
  159 + FD_CLR(0, fdt->close_on_exec);
  160 + spin_unlock(&f->file_lock);
  161 + }
  162 +
148 163 /* We can run anywhere, unlike our parent keventd(). */
149 164 set_cpus_allowed(current, CPU_MASK_ALL);
150 165  
151 166 retval = -EPERM;
152 167 if (current->fs->root)
153   - retval = execve(sub_info->path, sub_info->argv,sub_info->envp);
  168 + retval = execve(sub_info->path, sub_info->argv, sub_info->envp);
154 169  
155 170 /* Exec failed? */
156 171 sub_info->retval = retval;
... ... @@ -267,6 +282,44 @@
267 282 return sub_info.retval;
268 283 }
269 284 EXPORT_SYMBOL(call_usermodehelper_keys);
  285 +
  286 +int call_usermodehelper_pipe(char *path, char **argv, char **envp,
  287 + struct file **filp)
  288 +{
  289 + DECLARE_COMPLETION(done);
  290 + struct subprocess_info sub_info = {
  291 + .complete = &done,
  292 + .path = path,
  293 + .argv = argv,
  294 + .envp = envp,
  295 + .retval = 0,
  296 + };
  297 + struct file *f;
  298 + DECLARE_WORK(work, __call_usermodehelper, &sub_info);
  299 +
  300 + if (!khelper_wq)
  301 + return -EBUSY;
  302 +
  303 + if (path[0] == '\0')
  304 + return 0;
  305 +
  306 + f = create_write_pipe();
  307 + if (!f)
  308 + return -ENOMEM;
  309 + *filp = f;
  310 +
  311 + f = create_read_pipe(f);
  312 + if (!f) {
  313 + free_write_pipe(*filp);
  314 + return -ENOMEM;
  315 + }
  316 + sub_info.stdin = f;
  317 +
  318 + queue_work(khelper_wq, &work);
  319 + wait_for_completion(&done);
  320 + return sub_info.retval;
  321 +}
  322 +EXPORT_SYMBOL(call_usermodehelper_pipe);
270 323  
271 324 void __init usermodehelper_init(void)
272 325 {