aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/helper.c
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2006-11-25 14:09:39 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-11-25 16:28:34 -0500
commit5d48545e5e88ab7a27ba6a5cb1e8fff617754b61 (patch)
tree2da1a8d8e1ca4088cd91cc080f424b3e25e9423f /arch/um/os-Linux/helper.c
parent9dce447a542d8b4bedf13d6a4c4fc6737240372e (diff)
[PATCH] uml: make execvp safe for our usage
Reimplement execvp for our purposes - after we call fork() it is fundamentally unsafe to use the kernel allocator - current is not valid there. So we simply pass to our modified execvp() a preallocated buffer. This fixes a real bug and works very well in testing (I've seen indirectly warning messages from the forked thread - they went on the pipe connected to its stdout and where read as a number by UML, when calling read_output(). I verified the obtained number corresponded to "BUG:"). The added use of __cant_sleep() is not a new bug since __cant_sleep() is already used in the same function - passing an atomicity parameter would be better but it would require huge change, stating that this function must not be called in atomic context and can sleep is a better idea (will make sure of this gradually). Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Acked-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/os-Linux/helper.c')
-rw-r--r--arch/um/os-Linux/helper.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index d13299cfa318..c7ad6306e22f 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -8,18 +8,21 @@
8#include <unistd.h> 8#include <unistd.h>
9#include <errno.h> 9#include <errno.h>
10#include <sched.h> 10#include <sched.h>
11#include <limits.h>
11#include <sys/signal.h> 12#include <sys/signal.h>
12#include <sys/wait.h> 13#include <sys/wait.h>
13#include "user.h" 14#include "user.h"
14#include "kern_util.h" 15#include "kern_util.h"
15#include "user_util.h" 16#include "user_util.h"
16#include "os.h" 17#include "os.h"
18#include "um_malloc.h"
17 19
18struct helper_data { 20struct helper_data {
19 void (*pre_exec)(void*); 21 void (*pre_exec)(void*);
20 void *pre_data; 22 void *pre_data;
21 char **argv; 23 char **argv;
22 int fd; 24 int fd;
25 char *buf;
23}; 26};
24 27
25/* Debugging aid, changed only from gdb */ 28/* Debugging aid, changed only from gdb */
@@ -41,9 +44,8 @@ static int helper_child(void *arg)
41 } 44 }
42 if (data->pre_exec != NULL) 45 if (data->pre_exec != NULL)
43 (*data->pre_exec)(data->pre_data); 46 (*data->pre_exec)(data->pre_data);
44 execvp(argv[0], argv); 47 errval = execvp_noalloc(data->buf, argv[0], argv);
45 errval = -errno; 48 printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0], -errval);
46 printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
47 os_write_file(data->fd, &errval, sizeof(errval)); 49 os_write_file(data->fd, &errval, sizeof(errval));
48 kill(os_getpid(), SIGKILL); 50 kill(os_getpid(), SIGKILL);
49 return 0; 51 return 0;
@@ -84,11 +86,13 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
84 data.pre_data = pre_data; 86 data.pre_data = pre_data;
85 data.argv = argv; 87 data.argv = argv;
86 data.fd = fds[1]; 88 data.fd = fds[1];
89 data.buf = __cant_sleep() ? um_kmalloc_atomic(PATH_MAX) :
90 um_kmalloc(PATH_MAX);
87 pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); 91 pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
88 if (pid < 0) { 92 if (pid < 0) {
89 ret = -errno; 93 ret = -errno;
90 printk("run_helper : clone failed, errno = %d\n", errno); 94 printk("run_helper : clone failed, errno = %d\n", errno);
91 goto out_close; 95 goto out_free2;
92 } 96 }
93 97
94 close(fds[1]); 98 close(fds[1]);
@@ -109,6 +113,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
109 CATCH_EINTR(waitpid(pid, NULL, 0)); 113 CATCH_EINTR(waitpid(pid, NULL, 0));
110 } 114 }
111 115
116out_free2:
117 kfree(data.buf);
112out_close: 118out_close:
113 if (fds[1] != -1) 119 if (fds[1] != -1)
114 close(fds[1]); 120 close(fds[1]);