Commit 84b2789d authored by Johannes Berg's avatar Johannes Berg Committed by Richard Weinberger

um: separate child and parent errors in clone stub

If the two are mixed up, then it looks as though the parent
returned an error if the child failed (before) the mmap(),
and then the resulting process never gets killed. Fix this
by splitting the child and parent errors, reporting and
using them appropriately.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent a7d48886
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
struct stub_data { struct stub_data {
unsigned long offset; unsigned long offset;
int fd; int fd;
long err; long parent_err, child_err;
}; };
#endif #endif
...@@ -24,29 +24,26 @@ ...@@ -24,29 +24,26 @@
void __attribute__ ((__section__ (".__syscall_stub"))) void __attribute__ ((__section__ (".__syscall_stub")))
stub_clone_handler(void) stub_clone_handler(void)
{ {
struct stub_data *data = (struct stub_data *) STUB_DATA; int stack;
struct stub_data *data = (void *) ((unsigned long)&stack & ~(UM_KERN_PAGE_SIZE - 1));
long err; long err;
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); (unsigned long)data + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
if (err != 0) if (err) {
goto out; data->parent_err = err;
goto done;
}
err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0); err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
if (err) if (err) {
goto out; data->child_err = err;
goto done;
}
remap_stack(data->fd, data->offset); remap_stack(data->fd, data->offset);
goto done; goto done;
out:
/*
* save current result.
* Parent: pid;
* child: retcode of mmap already saved and it jumps around this
* assignment
*/
data->err = err;
done: done:
trap_myself(); trap_myself();
} }
...@@ -546,7 +546,13 @@ int copy_context_skas0(unsigned long new_stack, int pid) ...@@ -546,7 +546,13 @@ int copy_context_skas0(unsigned long new_stack, int pid)
*/ */
*data = ((struct stub_data) { *data = ((struct stub_data) {
.offset = MMAP_OFFSET(new_offset), .offset = MMAP_OFFSET(new_offset),
.fd = new_fd .fd = new_fd,
.parent_err = -ESRCH,
.child_err = 0,
});
*child_data = ((struct stub_data) {
.child_err = -ESRCH,
}); });
err = ptrace_setregs(pid, thread_regs); err = ptrace_setregs(pid, thread_regs);
...@@ -564,9 +570,6 @@ int copy_context_skas0(unsigned long new_stack, int pid) ...@@ -564,9 +570,6 @@ int copy_context_skas0(unsigned long new_stack, int pid)
return err; return err;
} }
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
/* /*
* Wait, until parent has finished its work: read child's pid from * Wait, until parent has finished its work: read child's pid from
* parent's stack, and check, if bad result. * parent's stack, and check, if bad result.
...@@ -581,7 +584,7 @@ int copy_context_skas0(unsigned long new_stack, int pid) ...@@ -581,7 +584,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
wait_stub_done(pid); wait_stub_done(pid);
pid = data->err; pid = data->parent_err;
if (pid < 0) { if (pid < 0) {
printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports " printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
"error %d\n", -pid); "error %d\n", -pid);
...@@ -593,10 +596,10 @@ int copy_context_skas0(unsigned long new_stack, int pid) ...@@ -593,10 +596,10 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* child's stack and check it. * child's stack and check it.
*/ */
wait_stub_done(pid); wait_stub_done(pid);
if (child_data->err != STUB_DATA) { if (child_data->child_err != STUB_DATA) {
printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports " printk(UM_KERN_ERR "copy_context_skas0 - stub-child %d reports "
"error %ld\n", child_data->err); "error %ld\n", pid, data->child_err);
err = child_data->err; err = data->child_err;
goto out_kill; goto out_kill;
} }
......
...@@ -86,7 +86,7 @@ static inline void remap_stack(int fd, unsigned long offset) ...@@ -86,7 +86,7 @@ static inline void remap_stack(int fd, unsigned long offset)
"d" (PROT_READ | PROT_WRITE), "d" (PROT_READ | PROT_WRITE),
"S" (MAP_FIXED | MAP_SHARED), "D" (fd), "S" (MAP_FIXED | MAP_SHARED), "D" (fd),
"a" (offset), "a" (offset),
"i" (&((struct stub_data *) STUB_DATA)->err) "i" (&((struct stub_data *) STUB_DATA)->child_err)
: "memory"); : "memory");
} }
......
...@@ -92,7 +92,7 @@ static inline void remap_stack(long fd, unsigned long offset) ...@@ -92,7 +92,7 @@ static inline void remap_stack(long fd, unsigned long offset)
"d" (PROT_READ | PROT_WRITE), "d" (PROT_READ | PROT_WRITE),
"g" (MAP_FIXED | MAP_SHARED), "g" (fd), "g" (MAP_FIXED | MAP_SHARED), "g" (fd),
"g" (offset), "g" (offset),
"i" (&((struct stub_data *) STUB_DATA)->err) "i" (&((struct stub_data *) STUB_DATA)->child_err)
: __syscall_clobber, "r10", "r8", "r9" ); : __syscall_clobber, "r10", "r8", "r9" );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment