Commit e239ca540594cff00adcce163dc332b27015d8e5
Committed by
Linus Torvalds
1 parent
d6cbd281d1
Exists in
master
and in
20 other branches
[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
kernel/kmod.c
... | ... | @@ -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 | { |