aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-03 05:54:49 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-03 05:54:49 -0700
commit2c37fa03ac935bf5f03d9ae7d7dc61ba4fda151a (patch)
treeb44b8b9a33a9c140e7913a436438e3a44bc21664 /kernel
parent1274bd1e0a9cfaaf18c40983c730badea9f7e733 (diff)
downloadhistory-2c37fa03ac935bf5f03d9ae7d7dc61ba4fda151a.tar.gz
sparse: annotate (and comment on) kmod.c user pointer usage
Big comment, because it wasn't clear why this cast was valid. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kmod.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 10d2e8fc58db20..160aa3d958ad2b 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -192,10 +192,20 @@ static int wait_for_helper(void *data)
allow_signal(SIGCHLD);
pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
- if (pid < 0)
+ if (pid < 0) {
sub_info->retval = pid;
- else
- sys_wait4(pid, &sub_info->retval, 0, NULL);
+ } else {
+ /*
+ * Normally it is bogus to call wait4() from in-kernel because
+ * wait4() wants to write the exit code to a userspace address.
+ * But wait_for_helper() always runs as keventd, and put_user()
+ * to a kernel address works OK for kernel threads, due to their
+ * having an mm_segment_t which spans the entire address space.
+ *
+ * Thus the __user pointer cast is valid here.
+ */
+ sys_wait4(pid, (int __user *) &sub_info->retval, 0, NULL);
+ }
complete(sub_info->complete);
return 0;