Revert "kmod: fix race in usermodehelper code"

This reverts commit c02e3f361c7 ("kmod: fix race in usermodehelper code")

The patch is wrong. UMH_WAIT_EXEC is called with VFORK what ensures
that the child finishes prior returing back to the parent. No race.

In fact, the patch makes it even worse because it does the thing it
claims not do:

- It calls ->complete() on UMH_WAIT_EXEC

- the complete() callback may de-allocated subinfo as seen in the
following call chain:

[<c009f904>] (__link_path_walk+0x20/0xeb4) from [<c00a094c>] (path_walk+0x48/0x94)
[<c00a094c>] (path_walk+0x48/0x94) from [<c00a0a34>] (do_path_lookup+0x24/0x4c)
[<c00a0a34>] (do_path_lookup+0x24/0x4c) from [<c00a158c>] (do_filp_open+0xa4/0x83c)
[<c00a158c>] (do_filp_open+0xa4/0x83c) from [<c009ba90>] (open_exec+0x24/0xe0)
[<c009ba90>] (open_exec+0x24/0xe0) from [<c009bfa8>] (do_execve+0x7c/0x2e4)
[<c009bfa8>] (do_execve+0x7c/0x2e4) from [<c0026a80>] (kernel_execve+0x34/0x80)
[<c0026a80>] (kernel_execve+0x34/0x80) from [<c004b514>] (____call_usermodehelper+0x130/0x148)
[<c004b514>] (____call_usermodehelper+0x130/0x148) from [<c0024858>] (kernel_thread_exit+0x0/0x8)

and the path pointer was NULL. Good that ARM's kernel_execve()
doesn't check the pointer for NULL or else I wouldn't notice it.

The only race there might be is with UMH_NO_WAIT but it is too late for
me to investigate it now. UMH_WAIT_PROC could probably also use VFORK
and we could save one exec. So the only race I see is with UMH_NO_WAIT
and recent scheduler changes where the child does not always run first
might have trigger here something but as I said, it is late....

Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Sebastian Andrzej Siewior and committed by Linus Torvalds 95e0d86b 0dd52d0d

+5 -8
+5 -8
kernel/kmod.c
··· 143 static int ____call_usermodehelper(void *data) 144 { 145 struct subprocess_info *sub_info = data; 146 - enum umh_wait wait = sub_info->wait; 147 int retval; 148 149 BUG_ON(atomic_read(&sub_info->cred->usage) != 1); ··· 184 */ 185 set_user_nice(current, 0); 186 187 - if (wait == UMH_WAIT_EXEC) 188 - complete(sub_info->complete); 189 - 190 retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp); 191 192 /* Exec failed? */ 193 - if (wait != UMH_WAIT_EXEC) 194 - sub_info->retval = retval; 195 do_exit(0); 196 } 197 ··· 266 267 switch (wait) { 268 case UMH_NO_WAIT: 269 - case UMH_WAIT_EXEC: 270 break; 271 272 case UMH_WAIT_PROC: 273 if (pid > 0) 274 break; 275 sub_info->retval = pid; 276 - break; 277 } 278 } 279
··· 143 static int ____call_usermodehelper(void *data) 144 { 145 struct subprocess_info *sub_info = data; 146 int retval; 147 148 BUG_ON(atomic_read(&sub_info->cred->usage) != 1); ··· 185 */ 186 set_user_nice(current, 0); 187 188 retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp); 189 190 /* Exec failed? */ 191 + sub_info->retval = retval; 192 do_exit(0); 193 } 194 ··· 271 272 switch (wait) { 273 case UMH_NO_WAIT: 274 break; 275 276 case UMH_WAIT_PROC: 277 if (pid > 0) 278 break; 279 sub_info->retval = pid; 280 + /* FALLTHROUGH */ 281 + 282 + case UMH_WAIT_EXEC: 283 + complete(sub_info->complete); 284 } 285 } 286