aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-05-04 20:11:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-10-09 02:39:00 -0400
commit19d860a140beac48a1377f179e693abe86a9dac9 (patch)
tree4da809a162a3b9aea8575828f52e150b26ca6ff1
parent2926620145095ffb0350b2312ac9d0af8537796f (diff)
handle suicide on late failure exits in execve() in search_binary_handler()
... rather than doing that in the guts of ->load_binary(). [updated to fix the bug spotted by Shentino - for SIGSEGV we really need something stronger than send_sig_info(); again, better do that in one place] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/x86/ia32/ia32_aout.c21
-rw-r--r--fs/binfmt_aout.c25
-rw-r--r--fs/binfmt_elf.c25
-rw-r--r--fs/binfmt_elf_fdpic.c24
-rw-r--r--fs/exec.c17
5 files changed, 35 insertions, 77 deletions
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index d21ff89207cd..df91466f973d 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -308,11 +308,8 @@ static int load_aout_binary(struct linux_binprm *bprm)
308 (current->mm->start_brk = N_BSSADDR(ex)); 308 (current->mm->start_brk = N_BSSADDR(ex));
309 309
310 retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); 310 retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT);
311 if (retval < 0) { 311 if (retval < 0)
312 /* Someone check-me: is this error path enough? */
313 send_sig(SIGKILL, current, 0);
314 return retval; 312 return retval;
315 }
316 313
317 install_exec_creds(bprm); 314 install_exec_creds(bprm);
318 315
@@ -324,17 +321,13 @@ static int load_aout_binary(struct linux_binprm *bprm)
324 321
325 error = vm_brk(text_addr & PAGE_MASK, map_size); 322 error = vm_brk(text_addr & PAGE_MASK, map_size);
326 323
327 if (error != (text_addr & PAGE_MASK)) { 324 if (error != (text_addr & PAGE_MASK))
328 send_sig(SIGKILL, current, 0);
329 return error; 325 return error;
330 }
331 326
332 error = read_code(bprm->file, text_addr, 32, 327 error = read_code(bprm->file, text_addr, 32,
333 ex.a_text + ex.a_data); 328 ex.a_text + ex.a_data);
334 if ((signed long)error < 0) { 329 if ((signed long)error < 0)
335 send_sig(SIGKILL, current, 0);
336 return error; 330 return error;
337 }
338 } else { 331 } else {
339#ifdef WARN_OLD 332#ifdef WARN_OLD
340 static unsigned long error_time, error_time2; 333 static unsigned long error_time, error_time2;
@@ -368,20 +361,16 @@ static int load_aout_binary(struct linux_binprm *bprm)
368 MAP_EXECUTABLE | MAP_32BIT, 361 MAP_EXECUTABLE | MAP_32BIT,
369 fd_offset); 362 fd_offset);
370 363
371 if (error != N_TXTADDR(ex)) { 364 if (error != N_TXTADDR(ex))
372 send_sig(SIGKILL, current, 0);
373 return error; 365 return error;
374 }
375 366
376 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data, 367 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
377 PROT_READ | PROT_WRITE | PROT_EXEC, 368 PROT_READ | PROT_WRITE | PROT_EXEC,
378 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | 369 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
379 MAP_EXECUTABLE | MAP_32BIT, 370 MAP_EXECUTABLE | MAP_32BIT,
380 fd_offset + ex.a_text); 371 fd_offset + ex.a_text);
381 if (error != N_DATADDR(ex)) { 372 if (error != N_DATADDR(ex))
382 send_sig(SIGKILL, current, 0);
383 return error; 373 return error;
384 }
385 } 374 }
386beyond_if: 375beyond_if:
387 set_binfmt(&aout_format); 376 set_binfmt(&aout_format);
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index ca0ba15a7306..929dec08c348 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -256,11 +256,8 @@ static int load_aout_binary(struct linux_binprm * bprm)
256 (current->mm->start_brk = N_BSSADDR(ex)); 256 (current->mm->start_brk = N_BSSADDR(ex));
257 257
258 retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); 258 retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
259 if (retval < 0) { 259 if (retval < 0)
260 /* Someone check-me: is this error path enough? */
261 send_sig(SIGKILL, current, 0);
262 return retval; 260 return retval;
263 }
264 261
265 install_exec_creds(bprm); 262 install_exec_creds(bprm);
266 263
@@ -278,17 +275,13 @@ static int load_aout_binary(struct linux_binprm * bprm)
278 map_size = ex.a_text+ex.a_data; 275 map_size = ex.a_text+ex.a_data;
279#endif 276#endif
280 error = vm_brk(text_addr & PAGE_MASK, map_size); 277 error = vm_brk(text_addr & PAGE_MASK, map_size);
281 if (error != (text_addr & PAGE_MASK)) { 278 if (error != (text_addr & PAGE_MASK))
282 send_sig(SIGKILL, current, 0);
283 return error; 279 return error;
284 }
285 280
286 error = read_code(bprm->file, text_addr, pos, 281 error = read_code(bprm->file, text_addr, pos,
287 ex.a_text+ex.a_data); 282 ex.a_text+ex.a_data);
288 if ((signed long)error < 0) { 283 if ((signed long)error < 0)
289 send_sig(SIGKILL, current, 0);
290 return error; 284 return error;
291 }
292 } else { 285 } else {
293 if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && 286 if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
294 (N_MAGIC(ex) != NMAGIC) && printk_ratelimit()) 287 (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
@@ -315,28 +308,22 @@ static int load_aout_binary(struct linux_binprm * bprm)
315 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, 308 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
316 fd_offset); 309 fd_offset);
317 310
318 if (error != N_TXTADDR(ex)) { 311 if (error != N_TXTADDR(ex))
319 send_sig(SIGKILL, current, 0);
320 return error; 312 return error;
321 }
322 313
323 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data, 314 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
324 PROT_READ | PROT_WRITE | PROT_EXEC, 315 PROT_READ | PROT_WRITE | PROT_EXEC,
325 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, 316 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
326 fd_offset + ex.a_text); 317 fd_offset + ex.a_text);
327 if (error != N_DATADDR(ex)) { 318 if (error != N_DATADDR(ex))
328 send_sig(SIGKILL, current, 0);
329 return error; 319 return error;
330 }
331 } 320 }
332beyond_if: 321beyond_if:
333 set_binfmt(&aout_format); 322 set_binfmt(&aout_format);
334 323
335 retval = set_brk(current->mm->start_brk, current->mm->brk); 324 retval = set_brk(current->mm->start_brk, current->mm->brk);
336 if (retval < 0) { 325 if (retval < 0)
337 send_sig(SIGKILL, current, 0);
338 return retval; 326 return retval;
339 }
340 327
341 current->mm->start_stack = 328 current->mm->start_stack =
342 (unsigned long) create_aout_tables((char __user *) bprm->p, bprm); 329 (unsigned long) create_aout_tables((char __user *) bprm->p, bprm);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 3892c1a23241..d8fc0605b9d2 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -738,10 +738,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
738 change some of these later */ 738 change some of these later */
739 retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), 739 retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
740 executable_stack); 740 executable_stack);
741 if (retval < 0) { 741 if (retval < 0)
742 send_sig(SIGKILL, current, 0);
743 goto out_free_dentry; 742 goto out_free_dentry;
744 }
745 743
746 current->mm->start_stack = bprm->p; 744 current->mm->start_stack = bprm->p;
747 745
@@ -763,10 +761,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
763 and clear the area. */ 761 and clear the area. */
764 retval = set_brk(elf_bss + load_bias, 762 retval = set_brk(elf_bss + load_bias,
765 elf_brk + load_bias); 763 elf_brk + load_bias);
766 if (retval) { 764 if (retval)
767 send_sig(SIGKILL, current, 0);
768 goto out_free_dentry; 765 goto out_free_dentry;
769 }
770 nbyte = ELF_PAGEOFFSET(elf_bss); 766 nbyte = ELF_PAGEOFFSET(elf_bss);
771 if (nbyte) { 767 if (nbyte) {
772 nbyte = ELF_MIN_ALIGN - nbyte; 768 nbyte = ELF_MIN_ALIGN - nbyte;
@@ -820,7 +816,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
820 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, 816 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
821 elf_prot, elf_flags, 0); 817 elf_prot, elf_flags, 0);
822 if (BAD_ADDR(error)) { 818 if (BAD_ADDR(error)) {
823 send_sig(SIGKILL, current, 0);
824 retval = IS_ERR((void *)error) ? 819 retval = IS_ERR((void *)error) ?
825 PTR_ERR((void*)error) : -EINVAL; 820 PTR_ERR((void*)error) : -EINVAL;
826 goto out_free_dentry; 821 goto out_free_dentry;
@@ -851,7 +846,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
851 elf_ppnt->p_memsz > TASK_SIZE || 846 elf_ppnt->p_memsz > TASK_SIZE ||
852 TASK_SIZE - elf_ppnt->p_memsz < k) { 847 TASK_SIZE - elf_ppnt->p_memsz < k) {
853 /* set_brk can never work. Avoid overflows. */ 848 /* set_brk can never work. Avoid overflows. */
854 send_sig(SIGKILL, current, 0);
855 retval = -EINVAL; 849 retval = -EINVAL;
856 goto out_free_dentry; 850 goto out_free_dentry;
857 } 851 }
@@ -883,12 +877,9 @@ static int load_elf_binary(struct linux_binprm *bprm)
883 * up getting placed where the bss needs to go. 877 * up getting placed where the bss needs to go.
884 */ 878 */
885 retval = set_brk(elf_bss, elf_brk); 879 retval = set_brk(elf_bss, elf_brk);
886 if (retval) { 880 if (retval)
887 send_sig(SIGKILL, current, 0);
888 goto out_free_dentry; 881 goto out_free_dentry;
889 }
890 if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { 882 if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
891 send_sig(SIGSEGV, current, 0);
892 retval = -EFAULT; /* Nobody gets to see this, but.. */ 883 retval = -EFAULT; /* Nobody gets to see this, but.. */
893 goto out_free_dentry; 884 goto out_free_dentry;
894 } 885 }
@@ -909,7 +900,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
909 elf_entry += loc->interp_elf_ex.e_entry; 900 elf_entry += loc->interp_elf_ex.e_entry;
910 } 901 }
911 if (BAD_ADDR(elf_entry)) { 902 if (BAD_ADDR(elf_entry)) {
912 force_sig(SIGSEGV, current);
913 retval = IS_ERR((void *)elf_entry) ? 903 retval = IS_ERR((void *)elf_entry) ?
914 (int)elf_entry : -EINVAL; 904 (int)elf_entry : -EINVAL;
915 goto out_free_dentry; 905 goto out_free_dentry;
@@ -922,7 +912,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
922 } else { 912 } else {
923 elf_entry = loc->elf_ex.e_entry; 913 elf_entry = loc->elf_ex.e_entry;
924 if (BAD_ADDR(elf_entry)) { 914 if (BAD_ADDR(elf_entry)) {
925 force_sig(SIGSEGV, current);
926 retval = -EINVAL; 915 retval = -EINVAL;
927 goto out_free_dentry; 916 goto out_free_dentry;
928 } 917 }
@@ -934,19 +923,15 @@ static int load_elf_binary(struct linux_binprm *bprm)
934 923
935#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES 924#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
936 retval = arch_setup_additional_pages(bprm, !!elf_interpreter); 925 retval = arch_setup_additional_pages(bprm, !!elf_interpreter);
937 if (retval < 0) { 926 if (retval < 0)
938 send_sig(SIGKILL, current, 0);
939 goto out; 927 goto out;
940 }
941#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ 928#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
942 929
943 install_exec_creds(bprm); 930 install_exec_creds(bprm);
944 retval = create_elf_tables(bprm, &loc->elf_ex, 931 retval = create_elf_tables(bprm, &loc->elf_ex,
945 load_addr, interp_load_addr); 932 load_addr, interp_load_addr);
946 if (retval < 0) { 933 if (retval < 0)
947 send_sig(SIGKILL, current, 0);
948 goto out; 934 goto out;
949 }
950 /* N.B. passed_fileno might not be initialized? */ 935 /* N.B. passed_fileno might not be initialized? */
951 current->mm->end_code = end_code; 936 current->mm->end_code = end_code;
952 current->mm->start_code = start_code; 937 current->mm->start_code = start_code;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index fe2a643ee005..d3634bfb7fe1 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -317,8 +317,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
317 goto error; 317 goto error;
318 318
319 /* there's now no turning back... the old userspace image is dead, 319 /* there's now no turning back... the old userspace image is dead,
320 * defunct, deceased, etc. after this point we have to exit via 320 * defunct, deceased, etc.
321 * error_kill */ 321 */
322 set_personality(PER_LINUX_FDPIC); 322 set_personality(PER_LINUX_FDPIC);
323 if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) 323 if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
324 current->personality |= READ_IMPLIES_EXEC; 324 current->personality |= READ_IMPLIES_EXEC;
@@ -343,24 +343,22 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
343 343
344 retval = setup_arg_pages(bprm, current->mm->start_stack, 344 retval = setup_arg_pages(bprm, current->mm->start_stack,
345 executable_stack); 345 executable_stack);
346 if (retval < 0) { 346 if (retval < 0)
347 send_sig(SIGKILL, current, 0); 347 goto error;
348 goto error_kill;
349 }
350#endif 348#endif
351 349
352 /* load the executable and interpreter into memory */ 350 /* load the executable and interpreter into memory */
353 retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm, 351 retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm,
354 "executable"); 352 "executable");
355 if (retval < 0) 353 if (retval < 0)
356 goto error_kill; 354 goto error;
357 355
358 if (interpreter_name) { 356 if (interpreter_name) {
359 retval = elf_fdpic_map_file(&interp_params, interpreter, 357 retval = elf_fdpic_map_file(&interp_params, interpreter,
360 current->mm, "interpreter"); 358 current->mm, "interpreter");
361 if (retval < 0) { 359 if (retval < 0) {
362 printk(KERN_ERR "Unable to load interpreter\n"); 360 printk(KERN_ERR "Unable to load interpreter\n");
363 goto error_kill; 361 goto error;
364 } 362 }
365 363
366 allow_write_access(interpreter); 364 allow_write_access(interpreter);
@@ -397,7 +395,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
397 if (IS_ERR_VALUE(current->mm->start_brk)) { 395 if (IS_ERR_VALUE(current->mm->start_brk)) {
398 retval = current->mm->start_brk; 396 retval = current->mm->start_brk;
399 current->mm->start_brk = 0; 397 current->mm->start_brk = 0;
400 goto error_kill; 398 goto error;
401 } 399 }
402 400
403 current->mm->brk = current->mm->start_brk; 401 current->mm->brk = current->mm->start_brk;
@@ -410,7 +408,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
410 install_exec_creds(bprm); 408 install_exec_creds(bprm);
411 if (create_elf_fdpic_tables(bprm, current->mm, 409 if (create_elf_fdpic_tables(bprm, current->mm,
412 &exec_params, &interp_params) < 0) 410 &exec_params, &interp_params) < 0)
413 goto error_kill; 411 goto error;
414 412
415 kdebug("- start_code %lx", current->mm->start_code); 413 kdebug("- start_code %lx", current->mm->start_code);
416 kdebug("- end_code %lx", current->mm->end_code); 414 kdebug("- end_code %lx", current->mm->end_code);
@@ -449,12 +447,6 @@ error:
449 kfree(interp_params.phdrs); 447 kfree(interp_params.phdrs);
450 kfree(interp_params.loadmap); 448 kfree(interp_params.loadmap);
451 return retval; 449 return retval;
452
453 /* unrecoverable error - kill the process */
454error_kill:
455 send_sig(SIGSEGV, current, 0);
456 goto error;
457
458} 450}
459 451
460/*****************************************************************************/ 452/*****************************************************************************/
diff --git a/fs/exec.c b/fs/exec.c
index a2b42a98c743..7302b75a9820 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1372,18 +1372,23 @@ int search_binary_handler(struct linux_binprm *bprm)
1372 read_unlock(&binfmt_lock); 1372 read_unlock(&binfmt_lock);
1373 bprm->recursion_depth++; 1373 bprm->recursion_depth++;
1374 retval = fmt->load_binary(bprm); 1374 retval = fmt->load_binary(bprm);
1375 read_lock(&binfmt_lock);
1376 put_binfmt(fmt);
1375 bprm->recursion_depth--; 1377 bprm->recursion_depth--;
1376 if (retval >= 0 || retval != -ENOEXEC || 1378 if (retval < 0 && !bprm->mm) {
1377 bprm->mm == NULL || bprm->file == NULL) { 1379 /* we got to flush_old_exec() and failed after it */
1378 put_binfmt(fmt); 1380 read_unlock(&binfmt_lock);
1381 force_sigsegv(SIGSEGV, current);
1382 return retval;
1383 }
1384 if (retval != -ENOEXEC || !bprm->file) {
1385 read_unlock(&binfmt_lock);
1379 return retval; 1386 return retval;
1380 } 1387 }
1381 read_lock(&binfmt_lock);
1382 put_binfmt(fmt);
1383 } 1388 }
1384 read_unlock(&binfmt_lock); 1389 read_unlock(&binfmt_lock);
1385 1390
1386 if (need_retry && retval == -ENOEXEC) { 1391 if (need_retry) {
1387 if (printable(bprm->buf[0]) && printable(bprm->buf[1]) && 1392 if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
1388 printable(bprm->buf[2]) && printable(bprm->buf[3])) 1393 printable(bprm->buf[2]) && printable(bprm->buf[3]))
1389 return retval; 1394 return retval;