diff options
45 files changed, 220 insertions, 186 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 10ab2d74ecbb..f6db3032ddf0 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c | |||
@@ -590,7 +590,5 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, | |||
590 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 590 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
591 | clear_thread_flag(TIF_NOTIFY_RESUME); | 591 | clear_thread_flag(TIF_NOTIFY_RESUME); |
592 | tracehook_notify_resume(regs); | 592 | tracehook_notify_resume(regs); |
593 | if (current->replacement_session_keyring) | ||
594 | key_replace_session_keyring(); | ||
595 | } | 593 | } |
596 | } | 594 | } |
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 17fc36c41cff..63f327dd5198 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -679,7 +679,5 @@ do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) | |||
679 | if (thread_flags & _TIF_NOTIFY_RESUME) { | 679 | if (thread_flags & _TIF_NOTIFY_RESUME) { |
680 | clear_thread_flag(TIF_NOTIFY_RESUME); | 680 | clear_thread_flag(TIF_NOTIFY_RESUME); |
681 | tracehook_notify_resume(regs); | 681 | tracehook_notify_resume(regs); |
682 | if (current->replacement_session_keyring) | ||
683 | key_replace_session_keyring(); | ||
684 | } | 682 | } |
685 | } | 683 | } |
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 169268c40ae2..5e6beb2597a8 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S | |||
@@ -587,7 +587,7 @@ fault_exit_work: | |||
587 | ld.w r1, r0[TI_flags] | 587 | ld.w r1, r0[TI_flags] |
588 | rjmp fault_exit_work | 588 | rjmp fault_exit_work |
589 | 589 | ||
590 | 1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | 590 | 1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME |
591 | tst r1, r2 | 591 | tst r1, r2 |
592 | breq 2f | 592 | breq 2f |
593 | unmask_interrupts | 593 | unmask_interrupts |
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index ae386c304bee..e7595ef74f51 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c | |||
@@ -321,7 +321,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) | |||
321 | if (ti->flags & _TIF_NOTIFY_RESUME) { | 321 | if (ti->flags & _TIF_NOTIFY_RESUME) { |
322 | clear_thread_flag(TIF_NOTIFY_RESUME); | 322 | clear_thread_flag(TIF_NOTIFY_RESUME); |
323 | tracehook_notify_resume(regs); | 323 | tracehook_notify_resume(regs); |
324 | if (current->replacement_session_keyring) | ||
325 | key_replace_session_keyring(); | ||
326 | } | 324 | } |
327 | } | 325 | } |
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index e5bbc1a5edc2..fc9ecce8b6ce 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c | |||
@@ -336,8 +336,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs) | |||
336 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { | 336 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { |
337 | clear_thread_flag(TIF_NOTIFY_RESUME); | 337 | clear_thread_flag(TIF_NOTIFY_RESUME); |
338 | tracehook_notify_resume(regs); | 338 | tracehook_notify_resume(regs); |
339 | if (current->replacement_session_keyring) | ||
340 | key_replace_session_keyring(); | ||
341 | } | 339 | } |
342 | } | 340 | } |
343 | 341 | ||
diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c index cf37478c1169..9493f0bbf0a6 100644 --- a/arch/c6x/kernel/signal.c +++ b/arch/c6x/kernel/signal.c | |||
@@ -364,7 +364,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags, | |||
364 | if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { | 364 | if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { |
365 | clear_thread_flag(TIF_NOTIFY_RESUME); | 365 | clear_thread_flag(TIF_NOTIFY_RESUME); |
366 | tracehook_notify_resume(regs); | 366 | tracehook_notify_resume(regs); |
367 | if (current->replacement_session_keyring) | ||
368 | key_replace_session_keyring(); | ||
369 | } | 367 | } |
370 | } | 368 | } |
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c index d114ad3da9b1..58d44ee1a71f 100644 --- a/arch/cris/kernel/ptrace.c +++ b/arch/cris/kernel/ptrace.c | |||
@@ -40,7 +40,5 @@ void do_notify_resume(int canrestart, struct pt_regs *regs, | |||
40 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 40 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
41 | clear_thread_flag(TIF_NOTIFY_RESUME); | 41 | clear_thread_flag(TIF_NOTIFY_RESUME); |
42 | tracehook_notify_resume(regs); | 42 | tracehook_notify_resume(regs); |
43 | if (current->replacement_session_keyring) | ||
44 | key_replace_session_keyring(); | ||
45 | } | 43 | } |
46 | } | 44 | } |
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 8cf5dca01758..595bf1e5a5dc 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -562,8 +562,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) | |||
562 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 562 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
563 | clear_thread_flag(TIF_NOTIFY_RESUME); | 563 | clear_thread_flag(TIF_NOTIFY_RESUME); |
564 | tracehook_notify_resume(__frame); | 564 | tracehook_notify_resume(__frame); |
565 | if (current->replacement_session_keyring) | ||
566 | key_replace_session_keyring(); | ||
567 | } | 565 | } |
568 | 566 | ||
569 | } /* end do_notify_resume() */ | 567 | } /* end do_notify_resume() */ |
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index d4b0555d2904..e58992ad789e 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c | |||
@@ -513,7 +513,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) | |||
513 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 513 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
514 | clear_thread_flag(TIF_NOTIFY_RESUME); | 514 | clear_thread_flag(TIF_NOTIFY_RESUME); |
515 | tracehook_notify_resume(regs); | 515 | tracehook_notify_resume(regs); |
516 | if (current->replacement_session_keyring) | ||
517 | key_replace_session_keyring(); | ||
518 | } | 516 | } |
519 | } | 517 | } |
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c index 434866eb0f1c..21a3018cb9bf 100644 --- a/arch/hexagon/kernel/signal.c +++ b/arch/hexagon/kernel/signal.c | |||
@@ -273,8 +273,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
273 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 273 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
274 | clear_thread_flag(TIF_NOTIFY_RESUME); | 274 | clear_thread_flag(TIF_NOTIFY_RESUME); |
275 | tracehook_notify_resume(regs); | 275 | tracehook_notify_resume(regs); |
276 | if (current->replacement_session_keyring) | ||
277 | key_replace_session_keyring(); | ||
278 | } | 276 | } |
279 | } | 277 | } |
280 | 278 | ||
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 5e0e86ddb12f..dd6fc1449741 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -199,8 +199,6 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) | |||
199 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { | 199 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { |
200 | clear_thread_flag(TIF_NOTIFY_RESUME); | 200 | clear_thread_flag(TIF_NOTIFY_RESUME); |
201 | tracehook_notify_resume(&scr->pt); | 201 | tracehook_notify_resume(&scr->pt); |
202 | if (current->replacement_session_keyring) | ||
203 | key_replace_session_keyring(); | ||
204 | } | 202 | } |
205 | 203 | ||
206 | /* copy user rbs to kernel rbs */ | 204 | /* copy user rbs to kernel rbs */ |
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index f54d96993ea1..64804f1f5141 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c | |||
@@ -383,8 +383,6 @@ void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags) | |||
383 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 383 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
384 | clear_thread_flag(TIF_NOTIFY_RESUME); | 384 | clear_thread_flag(TIF_NOTIFY_RESUME); |
385 | tracehook_notify_resume(regs); | 385 | tracehook_notify_resume(regs); |
386 | if (current->replacement_session_keyring) | ||
387 | key_replace_session_keyring(); | ||
388 | } | 386 | } |
389 | 387 | ||
390 | clear_thread_flag(TIF_IRET); | 388 | clear_thread_flag(TIF_IRET); |
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index d9f3d1900eed..973eec60cad4 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c | |||
@@ -1193,9 +1193,6 @@ void do_notify_resume(struct pt_regs *regs) | |||
1193 | if (test_thread_flag(TIF_SIGPENDING)) | 1193 | if (test_thread_flag(TIF_SIGPENDING)) |
1194 | do_signal(regs); | 1194 | do_signal(regs); |
1195 | 1195 | ||
1196 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | 1196 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) |
1197 | tracehook_notify_resume(regs); | 1197 | tracehook_notify_resume(regs); |
1198 | if (current->replacement_session_keyring) | ||
1199 | key_replace_session_keyring(); | ||
1200 | } | ||
1201 | } | 1198 | } |
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 7f4c7bef1642..5d796e32786e 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c | |||
@@ -401,9 +401,6 @@ void do_notify_resume(struct pt_regs *regs, int in_syscall) | |||
401 | if (test_thread_flag(TIF_SIGPENDING)) | 401 | if (test_thread_flag(TIF_SIGPENDING)) |
402 | do_signal(regs, in_syscall); | 402 | do_signal(regs, in_syscall); |
403 | 403 | ||
404 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | 404 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) |
405 | tracehook_notify_resume(regs); | 405 | tracehook_notify_resume(regs); |
406 | if (current->replacement_session_keyring) | ||
407 | key_replace_session_keyring(); | ||
408 | } | ||
409 | } | 406 | } |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 17f6ee30ad0d..8a6e6d116ab0 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -636,8 +636,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | |||
636 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 636 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
637 | clear_thread_flag(TIF_NOTIFY_RESUME); | 637 | clear_thread_flag(TIF_NOTIFY_RESUME); |
638 | tracehook_notify_resume(regs); | 638 | tracehook_notify_resume(regs); |
639 | if (current->replacement_session_keyring) | ||
640 | key_replace_session_keyring(); | ||
641 | } | 639 | } |
642 | } | 640 | } |
643 | 641 | ||
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 890cf91767cc..b8b6aa1a6837 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c | |||
@@ -554,7 +554,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) | |||
554 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 554 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
555 | clear_thread_flag(TIF_NOTIFY_RESUME); | 555 | clear_thread_flag(TIF_NOTIFY_RESUME); |
556 | tracehook_notify_resume(current_frame()); | 556 | tracehook_notify_resume(current_frame()); |
557 | if (current->replacement_session_keyring) | ||
558 | key_replace_session_keyring(); | ||
559 | } | 557 | } |
560 | } | 558 | } |
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index e970743251ae..9ae611522953 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c | |||
@@ -376,7 +376,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs) | |||
376 | if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) { | 376 | if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) { |
377 | clear_thread_flag(TIF_NOTIFY_RESUME); | 377 | clear_thread_flag(TIF_NOTIFY_RESUME); |
378 | tracehook_notify_resume(regs); | 378 | tracehook_notify_resume(regs); |
379 | if (current->replacement_session_keyring) | ||
380 | key_replace_session_keyring(); | ||
381 | } | 379 | } |
382 | } | 380 | } |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 07ef351edd57..c7fbc96472f3 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -2032,7 +2032,7 @@ syscall_check_resched: | |||
2032 | .import do_signal,code | 2032 | .import do_signal,code |
2033 | syscall_check_sig: | 2033 | syscall_check_sig: |
2034 | LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 | 2034 | LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 |
2035 | ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26 | 2035 | ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r26 |
2036 | and,COND(<>) %r19, %r26, %r0 | 2036 | and,COND(<>) %r19, %r26, %r0 |
2037 | b,n syscall_restore /* skip past if we've nothing to do */ | 2037 | b,n syscall_restore /* skip past if we've nothing to do */ |
2038 | 2038 | ||
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 4b9cb0d546d1..e7a7cd3e1120 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -638,7 +638,5 @@ void do_notify_resume(struct pt_regs *regs, long in_syscall) | |||
638 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { | 638 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { |
639 | clear_thread_flag(TIF_NOTIFY_RESUME); | 639 | clear_thread_flag(TIF_NOTIFY_RESUME); |
640 | tracehook_notify_resume(regs); | 640 | tracehook_notify_resume(regs); |
641 | if (current->replacement_session_keyring) | ||
642 | key_replace_session_keyring(); | ||
643 | } | 641 | } |
644 | } | 642 | } |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 651c5963662b..bfc3ec1382fb 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -193,8 +193,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
193 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 193 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
194 | clear_thread_flag(TIF_NOTIFY_RESUME); | 194 | clear_thread_flag(TIF_NOTIFY_RESUME); |
195 | tracehook_notify_resume(regs); | 195 | tracehook_notify_resume(regs); |
196 | if (current->replacement_session_keyring) | ||
197 | key_replace_session_keyring(); | ||
198 | } | 196 | } |
199 | } | 197 | } |
200 | 198 | ||
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index f626232e216c..42a6e8b47f06 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -494,6 +494,4 @@ void do_notify_resume(struct pt_regs *regs) | |||
494 | { | 494 | { |
495 | clear_thread_flag(TIF_NOTIFY_RESUME); | 495 | clear_thread_flag(TIF_NOTIFY_RESUME); |
496 | tracehook_notify_resume(regs); | 496 | tracehook_notify_resume(regs); |
497 | if (current->replacement_session_keyring) | ||
498 | key_replace_session_keyring(); | ||
499 | } | 497 | } |
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c index d4a49011c48a..302838d3acf6 100644 --- a/arch/score/kernel/signal.c +++ b/arch/score/kernel/signal.c | |||
@@ -356,7 +356,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | |||
356 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 356 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
357 | clear_thread_flag(TIF_NOTIFY_RESUME); | 357 | clear_thread_flag(TIF_NOTIFY_RESUME); |
358 | tracehook_notify_resume(regs); | 358 | tracehook_notify_resume(regs); |
359 | if (current->replacement_session_keyring) | ||
360 | key_replace_session_keyring(); | ||
361 | } | 359 | } |
362 | } | 360 | } |
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index cb4172c8af7d..9d7bfd66f189 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c | |||
@@ -626,7 +626,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, | |||
626 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 626 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
627 | clear_thread_flag(TIF_NOTIFY_RESUME); | 627 | clear_thread_flag(TIF_NOTIFY_RESUME); |
628 | tracehook_notify_resume(regs); | 628 | tracehook_notify_resume(regs); |
629 | if (current->replacement_session_keyring) | ||
630 | key_replace_session_keyring(); | ||
631 | } | 629 | } |
632 | } | 630 | } |
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index b589a354c069..aa6428430842 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -685,7 +685,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info | |||
685 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 685 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
686 | clear_thread_flag(TIF_NOTIFY_RESUME); | 686 | clear_thread_flag(TIF_NOTIFY_RESUME); |
687 | tracehook_notify_resume(regs); | 687 | tracehook_notify_resume(regs); |
688 | if (current->replacement_session_keyring) | ||
689 | key_replace_session_keyring(); | ||
690 | } | 688 | } |
691 | } | 689 | } |
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 2b7e849f7c65..6b42e8622d12 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c | |||
@@ -590,8 +590,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, | |||
590 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 590 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
591 | clear_thread_flag(TIF_NOTIFY_RESUME); | 591 | clear_thread_flag(TIF_NOTIFY_RESUME); |
592 | tracehook_notify_resume(regs); | 592 | tracehook_notify_resume(regs); |
593 | if (current->replacement_session_keyring) | ||
594 | key_replace_session_keyring(); | ||
595 | } | 593 | } |
596 | } | 594 | } |
597 | 595 | ||
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index eafaab486b2d..c82cf1cc3965 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c | |||
@@ -607,8 +607,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long | |||
607 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 607 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
608 | clear_thread_flag(TIF_NOTIFY_RESUME); | 608 | clear_thread_flag(TIF_NOTIFY_RESUME); |
609 | tracehook_notify_resume(regs); | 609 | tracehook_notify_resume(regs); |
610 | if (current->replacement_session_keyring) | ||
611 | key_replace_session_keyring(); | ||
612 | } | 610 | } |
613 | } | 611 | } |
614 | 612 | ||
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index ba1023d8a021..6be799150501 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -565,8 +565,6 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
565 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 565 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
566 | clear_thread_flag(TIF_NOTIFY_RESUME); | 566 | clear_thread_flag(TIF_NOTIFY_RESUME); |
567 | tracehook_notify_resume(regs); | 567 | tracehook_notify_resume(regs); |
568 | if (current->replacement_session_keyring) | ||
569 | key_replace_session_keyring(); | ||
570 | return 1; | 568 | return 1; |
571 | } | 569 | } |
572 | if (thread_info_flags & _TIF_SINGLESTEP) { | 570 | if (thread_info_flags & _TIF_SINGLESTEP) { |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 3a2235e0abc3..ccb9a9d283f1 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -117,11 +117,8 @@ void interrupt_end(void) | |||
117 | schedule(); | 117 | schedule(); |
118 | if (test_thread_flag(TIF_SIGPENDING)) | 118 | if (test_thread_flag(TIF_SIGPENDING)) |
119 | do_signal(); | 119 | do_signal(); |
120 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | 120 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) |
121 | tracehook_notify_resume(¤t->thread.regs); | 121 | tracehook_notify_resume(¤t->thread.regs); |
122 | if (current->replacement_session_keyring) | ||
123 | key_replace_session_keyring(); | ||
124 | } | ||
125 | } | 122 | } |
126 | 123 | ||
127 | void exit_thread(void) | 124 | void exit_thread(void) |
diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c index 7754df6ef7d4..28782ad47b93 100644 --- a/arch/unicore32/kernel/signal.c +++ b/arch/unicore32/kernel/signal.c | |||
@@ -464,8 +464,6 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, | |||
464 | if (thread_flags & _TIF_NOTIFY_RESUME) { | 464 | if (thread_flags & _TIF_NOTIFY_RESUME) { |
465 | clear_thread_flag(TIF_NOTIFY_RESUME); | 465 | clear_thread_flag(TIF_NOTIFY_RESUME); |
466 | tracehook_notify_resume(regs); | 466 | tracehook_notify_resume(regs); |
467 | if (current->replacement_session_keyring) | ||
468 | key_replace_session_keyring(); | ||
469 | } | 467 | } |
470 | } | 468 | } |
471 | 469 | ||
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 965dfda0fd5e..2e937a5ad531 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -827,8 +827,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
827 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 827 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
828 | clear_thread_flag(TIF_NOTIFY_RESUME); | 828 | clear_thread_flag(TIF_NOTIFY_RESUME); |
829 | tracehook_notify_resume(regs); | 829 | tracehook_notify_resume(regs); |
830 | if (current->replacement_session_keyring) | ||
831 | key_replace_session_keyring(); | ||
832 | } | 830 | } |
833 | if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) | 831 | if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) |
834 | fire_user_return_notifiers(); | 832 | fire_user_return_notifiers(); |
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index c5e4ec0598d2..ea7e17778a75 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c | |||
@@ -548,9 +548,6 @@ void do_notify_resume(struct pt_regs *regs) | |||
548 | if (test_thread_flag(TIF_SIGPENDING)) | 548 | if (test_thread_flag(TIF_SIGPENDING)) |
549 | do_signal(regs); | 549 | do_signal(regs); |
550 | 550 | ||
551 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | 551 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) |
552 | tracehook_notify_resume(regs); | 552 | tracehook_notify_resume(regs); |
553 | if (current->replacement_session_keyring) | ||
554 | key_replace_session_keyring(); | ||
555 | } | ||
556 | } | 553 | } |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index c91171599cb6..e68a8e53bb59 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -142,8 +142,6 @@ request_any_context_irq(unsigned int irq, irq_handler_t handler, | |||
142 | extern int __must_check | 142 | extern int __must_check |
143 | request_percpu_irq(unsigned int irq, irq_handler_t handler, | 143 | request_percpu_irq(unsigned int irq, irq_handler_t handler, |
144 | const char *devname, void __percpu *percpu_dev_id); | 144 | const char *devname, void __percpu *percpu_dev_id); |
145 | |||
146 | extern void exit_irq_thread(void); | ||
147 | #else | 145 | #else |
148 | 146 | ||
149 | extern int __must_check | 147 | extern int __must_check |
@@ -177,8 +175,6 @@ request_percpu_irq(unsigned int irq, irq_handler_t handler, | |||
177 | { | 175 | { |
178 | return request_irq(irq, handler, 0, devname, percpu_dev_id); | 176 | return request_irq(irq, handler, 0, devname, percpu_dev_id); |
179 | } | 177 | } |
180 | |||
181 | static inline void exit_irq_thread(void) { } | ||
182 | #endif | 178 | #endif |
183 | 179 | ||
184 | extern void free_irq(unsigned int, void *); | 180 | extern void free_irq(unsigned int, void *); |
diff --git a/include/linux/key.h b/include/linux/key.h index 5231800770e1..4cd22ed627ef 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -308,9 +308,6 @@ static inline bool key_is_instantiated(const struct key *key) | |||
308 | #ifdef CONFIG_SYSCTL | 308 | #ifdef CONFIG_SYSCTL |
309 | extern ctl_table key_sysctls[]; | 309 | extern ctl_table key_sysctls[]; |
310 | #endif | 310 | #endif |
311 | |||
312 | extern void key_replace_session_keyring(void); | ||
313 | |||
314 | /* | 311 | /* |
315 | * the userspace interface | 312 | * the userspace interface |
316 | */ | 313 | */ |
@@ -334,7 +331,6 @@ extern void key_init(void); | |||
334 | #define key_fsuid_changed(t) do { } while(0) | 331 | #define key_fsuid_changed(t) do { } while(0) |
335 | #define key_fsgid_changed(t) do { } while(0) | 332 | #define key_fsgid_changed(t) do { } while(0) |
336 | #define key_init() do { } while(0) | 333 | #define key_init() do { } while(0) |
337 | #define key_replace_session_keyring() do { } while(0) | ||
338 | 334 | ||
339 | #endif /* CONFIG_KEYS */ | 335 | #endif /* CONFIG_KEYS */ |
340 | #endif /* __KERNEL__ */ | 336 | #endif /* __KERNEL__ */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index f45c0b280b5d..660c8ae93471 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1301,11 +1301,6 @@ struct task_struct { | |||
1301 | unsigned sched_reset_on_fork:1; | 1301 | unsigned sched_reset_on_fork:1; |
1302 | unsigned sched_contributes_to_load:1; | 1302 | unsigned sched_contributes_to_load:1; |
1303 | 1303 | ||
1304 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
1305 | /* IRQ handler threads */ | ||
1306 | unsigned irq_thread:1; | ||
1307 | #endif | ||
1308 | |||
1309 | pid_t pid; | 1304 | pid_t pid; |
1310 | pid_t tgid; | 1305 | pid_t tgid; |
1311 | 1306 | ||
@@ -1313,10 +1308,9 @@ struct task_struct { | |||
1313 | /* Canary value for the -fstack-protector gcc feature */ | 1308 | /* Canary value for the -fstack-protector gcc feature */ |
1314 | unsigned long stack_canary; | 1309 | unsigned long stack_canary; |
1315 | #endif | 1310 | #endif |
1316 | 1311 | /* | |
1317 | /* | ||
1318 | * pointers to (original) parent process, youngest child, younger sibling, | 1312 | * pointers to (original) parent process, youngest child, younger sibling, |
1319 | * older sibling, respectively. (p->father can be replaced with | 1313 | * older sibling, respectively. (p->father can be replaced with |
1320 | * p->real_parent->pid) | 1314 | * p->real_parent->pid) |
1321 | */ | 1315 | */ |
1322 | struct task_struct __rcu *real_parent; /* real parent process */ | 1316 | struct task_struct __rcu *real_parent; /* real parent process */ |
@@ -1363,8 +1357,6 @@ struct task_struct { | |||
1363 | * credentials (COW) */ | 1357 | * credentials (COW) */ |
1364 | const struct cred __rcu *cred; /* effective (overridable) subjective task | 1358 | const struct cred __rcu *cred; /* effective (overridable) subjective task |
1365 | * credentials (COW) */ | 1359 | * credentials (COW) */ |
1366 | struct cred *replacement_session_keyring; /* for KEYCTL_SESSION_TO_PARENT */ | ||
1367 | |||
1368 | char comm[TASK_COMM_LEN]; /* executable name excluding path | 1360 | char comm[TASK_COMM_LEN]; /* executable name excluding path |
1369 | - access with [gs]et_task_comm (which lock | 1361 | - access with [gs]et_task_comm (which lock |
1370 | it with task_lock()) | 1362 | it with task_lock()) |
@@ -1400,6 +1392,8 @@ struct task_struct { | |||
1400 | int (*notifier)(void *priv); | 1392 | int (*notifier)(void *priv); |
1401 | void *notifier_data; | 1393 | void *notifier_data; |
1402 | sigset_t *notifier_mask; | 1394 | sigset_t *notifier_mask; |
1395 | struct hlist_head task_works; | ||
1396 | |||
1403 | struct audit_context *audit_context; | 1397 | struct audit_context *audit_context; |
1404 | #ifdef CONFIG_AUDITSYSCALL | 1398 | #ifdef CONFIG_AUDITSYSCALL |
1405 | uid_t loginuid; | 1399 | uid_t loginuid; |
diff --git a/include/linux/task_work.h b/include/linux/task_work.h new file mode 100644 index 000000000000..294d5d5e90b1 --- /dev/null +++ b/include/linux/task_work.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _LINUX_TASK_WORK_H | ||
2 | #define _LINUX_TASK_WORK_H | ||
3 | |||
4 | #include <linux/list.h> | ||
5 | #include <linux/sched.h> | ||
6 | |||
7 | struct task_work; | ||
8 | typedef void (*task_work_func_t)(struct task_work *); | ||
9 | |||
10 | struct task_work { | ||
11 | struct hlist_node hlist; | ||
12 | task_work_func_t func; | ||
13 | void *data; | ||
14 | }; | ||
15 | |||
16 | static inline void | ||
17 | init_task_work(struct task_work *twork, task_work_func_t func, void *data) | ||
18 | { | ||
19 | twork->func = func; | ||
20 | twork->data = data; | ||
21 | } | ||
22 | |||
23 | int task_work_add(struct task_struct *task, struct task_work *twork, bool); | ||
24 | struct task_work *task_work_cancel(struct task_struct *, task_work_func_t); | ||
25 | void task_work_run(void); | ||
26 | |||
27 | static inline void exit_task_work(struct task_struct *task) | ||
28 | { | ||
29 | if (unlikely(!hlist_empty(&task->task_works))) | ||
30 | task_work_run(); | ||
31 | } | ||
32 | |||
33 | #endif /* _LINUX_TASK_WORK_H */ | ||
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 51bd91d911c3..6a4d82bedb03 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/sched.h> | 49 | #include <linux/sched.h> |
50 | #include <linux/ptrace.h> | 50 | #include <linux/ptrace.h> |
51 | #include <linux/security.h> | 51 | #include <linux/security.h> |
52 | #include <linux/task_work.h> | ||
52 | struct linux_binprm; | 53 | struct linux_binprm; |
53 | 54 | ||
54 | /* | 55 | /* |
@@ -153,7 +154,6 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, | |||
153 | ptrace_notify(SIGTRAP); | 154 | ptrace_notify(SIGTRAP); |
154 | } | 155 | } |
155 | 156 | ||
156 | #ifdef TIF_NOTIFY_RESUME | ||
157 | /** | 157 | /** |
158 | * set_notify_resume - cause tracehook_notify_resume() to be called | 158 | * set_notify_resume - cause tracehook_notify_resume() to be called |
159 | * @task: task that will call tracehook_notify_resume() | 159 | * @task: task that will call tracehook_notify_resume() |
@@ -165,8 +165,10 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info, | |||
165 | */ | 165 | */ |
166 | static inline void set_notify_resume(struct task_struct *task) | 166 | static inline void set_notify_resume(struct task_struct *task) |
167 | { | 167 | { |
168 | #ifdef TIF_NOTIFY_RESUME | ||
168 | if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME)) | 169 | if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME)) |
169 | kick_process(task); | 170 | kick_process(task); |
171 | #endif | ||
170 | } | 172 | } |
171 | 173 | ||
172 | /** | 174 | /** |
@@ -184,7 +186,14 @@ static inline void set_notify_resume(struct task_struct *task) | |||
184 | */ | 186 | */ |
185 | static inline void tracehook_notify_resume(struct pt_regs *regs) | 187 | static inline void tracehook_notify_resume(struct pt_regs *regs) |
186 | { | 188 | { |
189 | /* | ||
190 | * The caller just cleared TIF_NOTIFY_RESUME. This barrier | ||
191 | * pairs with task_work_add()->set_notify_resume() after | ||
192 | * hlist_add_head(task->task_works); | ||
193 | */ | ||
194 | smp_mb__after_clear_bit(); | ||
195 | if (unlikely(!hlist_empty(¤t->task_works))) | ||
196 | task_work_run(); | ||
187 | } | 197 | } |
188 | #endif /* TIF_NOTIFY_RESUME */ | ||
189 | 198 | ||
190 | #endif /* <linux/tracehook.h> */ | 199 | #endif /* <linux/tracehook.h> */ |
diff --git a/kernel/Makefile b/kernel/Makefile index 80be6ca0cc75..6f3d0ae044b2 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | obj-y = fork.o exec_domain.o panic.o printk.o \ | 5 | obj-y = fork.o exec_domain.o panic.o printk.o \ |
6 | cpu.o exit.o itimer.o time.o softirq.o resource.o \ | 6 | cpu.o exit.o itimer.o time.o softirq.o resource.o \ |
7 | sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \ | 7 | sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \ |
8 | signal.o sys.o kmod.o workqueue.o pid.o \ | 8 | signal.o sys.o kmod.o workqueue.o pid.o task_work.o \ |
9 | rcupdate.o extable.o params.o posix-timers.o \ | 9 | rcupdate.o extable.o params.o posix-timers.o \ |
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
diff --git a/kernel/cred.c b/kernel/cred.c index 430557ea488f..de728ac50d82 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -207,13 +207,6 @@ void exit_creds(struct task_struct *tsk) | |||
207 | validate_creds(cred); | 207 | validate_creds(cred); |
208 | alter_cred_subscribers(cred, -1); | 208 | alter_cred_subscribers(cred, -1); |
209 | put_cred(cred); | 209 | put_cred(cred); |
210 | |||
211 | cred = (struct cred *) tsk->replacement_session_keyring; | ||
212 | if (cred) { | ||
213 | tsk->replacement_session_keyring = NULL; | ||
214 | validate_creds(cred); | ||
215 | put_cred(cred); | ||
216 | } | ||
217 | } | 210 | } |
218 | 211 | ||
219 | /** | 212 | /** |
@@ -396,8 +389,6 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) | |||
396 | struct cred *new; | 389 | struct cred *new; |
397 | int ret; | 390 | int ret; |
398 | 391 | ||
399 | p->replacement_session_keyring = NULL; | ||
400 | |||
401 | if ( | 392 | if ( |
402 | #ifdef CONFIG_KEYS | 393 | #ifdef CONFIG_KEYS |
403 | !p->cred->thread_keyring && | 394 | !p->cred->thread_keyring && |
diff --git a/kernel/exit.c b/kernel/exit.c index 6d85655353e9..34867cc5b42a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -946,12 +946,13 @@ void do_exit(long code) | |||
946 | exit_signals(tsk); /* sets PF_EXITING */ | 946 | exit_signals(tsk); /* sets PF_EXITING */ |
947 | /* | 947 | /* |
948 | * tsk->flags are checked in the futex code to protect against | 948 | * tsk->flags are checked in the futex code to protect against |
949 | * an exiting task cleaning up the robust pi futexes. | 949 | * an exiting task cleaning up the robust pi futexes, and in |
950 | * task_work_add() to avoid the race with exit_task_work(). | ||
950 | */ | 951 | */ |
951 | smp_mb(); | 952 | smp_mb(); |
952 | raw_spin_unlock_wait(&tsk->pi_lock); | 953 | raw_spin_unlock_wait(&tsk->pi_lock); |
953 | 954 | ||
954 | exit_irq_thread(); | 955 | exit_task_work(tsk); |
955 | 956 | ||
956 | if (unlikely(in_atomic())) | 957 | if (unlikely(in_atomic())) |
957 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", | 958 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", |
diff --git a/kernel/fork.c b/kernel/fork.c index c55b61ab6d64..ab5211b9e622 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1415,6 +1415,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1415 | */ | 1415 | */ |
1416 | p->group_leader = p; | 1416 | p->group_leader = p; |
1417 | INIT_LIST_HEAD(&p->thread_group); | 1417 | INIT_LIST_HEAD(&p->thread_group); |
1418 | INIT_HLIST_HEAD(&p->task_works); | ||
1418 | 1419 | ||
1419 | /* Now that the task is set up, run cgroup callbacks if | 1420 | /* Now that the task is set up, run cgroup callbacks if |
1420 | * necessary. We need to run them before the task is visible | 1421 | * necessary. We need to run them before the task is visible |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 7c475cd3f6e6..ea0c6c2ae6f7 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/task_work.h> | ||
19 | 20 | ||
20 | #include "internals.h" | 21 | #include "internals.h" |
21 | 22 | ||
@@ -775,11 +776,39 @@ static void wake_threads_waitq(struct irq_desc *desc) | |||
775 | wake_up(&desc->wait_for_threads); | 776 | wake_up(&desc->wait_for_threads); |
776 | } | 777 | } |
777 | 778 | ||
779 | static void irq_thread_dtor(struct task_work *unused) | ||
780 | { | ||
781 | struct task_struct *tsk = current; | ||
782 | struct irq_desc *desc; | ||
783 | struct irqaction *action; | ||
784 | |||
785 | if (WARN_ON_ONCE(!(current->flags & PF_EXITING))) | ||
786 | return; | ||
787 | |||
788 | action = kthread_data(tsk); | ||
789 | |||
790 | pr_err("exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n", | ||
791 | tsk->comm ? tsk->comm : "", tsk->pid, action->irq); | ||
792 | |||
793 | |||
794 | desc = irq_to_desc(action->irq); | ||
795 | /* | ||
796 | * If IRQTF_RUNTHREAD is set, we need to decrement | ||
797 | * desc->threads_active and wake possible waiters. | ||
798 | */ | ||
799 | if (test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags)) | ||
800 | wake_threads_waitq(desc); | ||
801 | |||
802 | /* Prevent a stale desc->threads_oneshot */ | ||
803 | irq_finalize_oneshot(desc, action); | ||
804 | } | ||
805 | |||
778 | /* | 806 | /* |
779 | * Interrupt handler thread | 807 | * Interrupt handler thread |
780 | */ | 808 | */ |
781 | static int irq_thread(void *data) | 809 | static int irq_thread(void *data) |
782 | { | 810 | { |
811 | struct task_work on_exit_work; | ||
783 | static const struct sched_param param = { | 812 | static const struct sched_param param = { |
784 | .sched_priority = MAX_USER_RT_PRIO/2, | 813 | .sched_priority = MAX_USER_RT_PRIO/2, |
785 | }; | 814 | }; |
@@ -795,7 +824,9 @@ static int irq_thread(void *data) | |||
795 | handler_fn = irq_thread_fn; | 824 | handler_fn = irq_thread_fn; |
796 | 825 | ||
797 | sched_setscheduler(current, SCHED_FIFO, ¶m); | 826 | sched_setscheduler(current, SCHED_FIFO, ¶m); |
798 | current->irq_thread = 1; | 827 | |
828 | init_task_work(&on_exit_work, irq_thread_dtor, NULL); | ||
829 | task_work_add(current, &on_exit_work, false); | ||
799 | 830 | ||
800 | while (!irq_wait_for_interrupt(action)) { | 831 | while (!irq_wait_for_interrupt(action)) { |
801 | irqreturn_t action_ret; | 832 | irqreturn_t action_ret; |
@@ -817,44 +848,11 @@ static int irq_thread(void *data) | |||
817 | * cannot touch the oneshot mask at this point anymore as | 848 | * cannot touch the oneshot mask at this point anymore as |
818 | * __setup_irq() might have given out currents thread_mask | 849 | * __setup_irq() might have given out currents thread_mask |
819 | * again. | 850 | * again. |
820 | * | ||
821 | * Clear irq_thread. Otherwise exit_irq_thread() would make | ||
822 | * fuzz about an active irq thread going into nirvana. | ||
823 | */ | 851 | */ |
824 | current->irq_thread = 0; | 852 | task_work_cancel(current, irq_thread_dtor); |
825 | return 0; | 853 | return 0; |
826 | } | 854 | } |
827 | 855 | ||
828 | /* | ||
829 | * Called from do_exit() | ||
830 | */ | ||
831 | void exit_irq_thread(void) | ||
832 | { | ||
833 | struct task_struct *tsk = current; | ||
834 | struct irq_desc *desc; | ||
835 | struct irqaction *action; | ||
836 | |||
837 | if (!tsk->irq_thread) | ||
838 | return; | ||
839 | |||
840 | action = kthread_data(tsk); | ||
841 | |||
842 | pr_err("exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n", | ||
843 | tsk->comm ? tsk->comm : "", tsk->pid, action->irq); | ||
844 | |||
845 | desc = irq_to_desc(action->irq); | ||
846 | |||
847 | /* | ||
848 | * If IRQTF_RUNTHREAD is set, we need to decrement | ||
849 | * desc->threads_active and wake possible waiters. | ||
850 | */ | ||
851 | if (test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags)) | ||
852 | wake_threads_waitq(desc); | ||
853 | |||
854 | /* Prevent a stale desc->threads_oneshot */ | ||
855 | irq_finalize_oneshot(desc, action); | ||
856 | } | ||
857 | |||
858 | static void irq_setup_forced_threading(struct irqaction *new) | 856 | static void irq_setup_forced_threading(struct irqaction *new) |
859 | { | 857 | { |
860 | if (!force_irqthreads) | 858 | if (!force_irqthreads) |
diff --git a/kernel/task_work.c b/kernel/task_work.c new file mode 100644 index 000000000000..82d1c794066d --- /dev/null +++ b/kernel/task_work.c | |||
@@ -0,0 +1,84 @@ | |||
1 | #include <linux/spinlock.h> | ||
2 | #include <linux/task_work.h> | ||
3 | #include <linux/tracehook.h> | ||
4 | |||
5 | int | ||
6 | task_work_add(struct task_struct *task, struct task_work *twork, bool notify) | ||
7 | { | ||
8 | unsigned long flags; | ||
9 | int err = -ESRCH; | ||
10 | |||
11 | #ifndef TIF_NOTIFY_RESUME | ||
12 | if (notify) | ||
13 | return -ENOTSUPP; | ||
14 | #endif | ||
15 | /* | ||
16 | * We must not insert the new work if the task has already passed | ||
17 | * exit_task_work(). We rely on do_exit()->raw_spin_unlock_wait() | ||
18 | * and check PF_EXITING under pi_lock. | ||
19 | */ | ||
20 | raw_spin_lock_irqsave(&task->pi_lock, flags); | ||
21 | if (likely(!(task->flags & PF_EXITING))) { | ||
22 | hlist_add_head(&twork->hlist, &task->task_works); | ||
23 | err = 0; | ||
24 | } | ||
25 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | ||
26 | |||
27 | /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */ | ||
28 | if (likely(!err) && notify) | ||
29 | set_notify_resume(task); | ||
30 | return err; | ||
31 | } | ||
32 | |||
33 | struct task_work * | ||
34 | task_work_cancel(struct task_struct *task, task_work_func_t func) | ||
35 | { | ||
36 | unsigned long flags; | ||
37 | struct task_work *twork; | ||
38 | struct hlist_node *pos; | ||
39 | |||
40 | raw_spin_lock_irqsave(&task->pi_lock, flags); | ||
41 | hlist_for_each_entry(twork, pos, &task->task_works, hlist) { | ||
42 | if (twork->func == func) { | ||
43 | hlist_del(&twork->hlist); | ||
44 | goto found; | ||
45 | } | ||
46 | } | ||
47 | twork = NULL; | ||
48 | found: | ||
49 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | ||
50 | |||
51 | return twork; | ||
52 | } | ||
53 | |||
54 | void task_work_run(void) | ||
55 | { | ||
56 | struct task_struct *task = current; | ||
57 | struct hlist_head task_works; | ||
58 | struct hlist_node *pos; | ||
59 | |||
60 | raw_spin_lock_irq(&task->pi_lock); | ||
61 | hlist_move_list(&task->task_works, &task_works); | ||
62 | raw_spin_unlock_irq(&task->pi_lock); | ||
63 | |||
64 | if (unlikely(hlist_empty(&task_works))) | ||
65 | return; | ||
66 | /* | ||
67 | * We use hlist to save the space in task_struct, but we want fifo. | ||
68 | * Find the last entry, the list should be short, then process them | ||
69 | * in reverse order. | ||
70 | */ | ||
71 | for (pos = task_works.first; pos->next; pos = pos->next) | ||
72 | ; | ||
73 | |||
74 | for (;;) { | ||
75 | struct hlist_node **pprev = pos->pprev; | ||
76 | struct task_work *twork = container_of(pos, struct task_work, | ||
77 | hlist); | ||
78 | twork->func(twork); | ||
79 | |||
80 | if (pprev == &task_works.first) | ||
81 | break; | ||
82 | pos = container_of(pprev, struct hlist_node, next); | ||
83 | } | ||
84 | } | ||
diff --git a/security/keys/internal.h b/security/keys/internal.h index f711b094ed41..3dcbf86b0d31 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/key-type.h> | 16 | #include <linux/key-type.h> |
17 | #include <linux/task_work.h> | ||
17 | 18 | ||
18 | #ifdef __KDEBUG | 19 | #ifdef __KDEBUG |
19 | #define kenter(FMT, ...) \ | 20 | #define kenter(FMT, ...) \ |
@@ -148,6 +149,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | |||
148 | #define KEY_LOOKUP_FOR_UNLINK 0x04 | 149 | #define KEY_LOOKUP_FOR_UNLINK 0x04 |
149 | 150 | ||
150 | extern long join_session_keyring(const char *name); | 151 | extern long join_session_keyring(const char *name); |
152 | extern void key_change_session_keyring(struct task_work *twork); | ||
151 | 153 | ||
152 | extern struct work_struct key_gc_work; | 154 | extern struct work_struct key_gc_work; |
153 | extern unsigned key_gc_delay; | 155 | extern unsigned key_gc_delay; |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 21907ea35b15..0f5b3f027299 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1454,50 +1454,57 @@ long keyctl_get_security(key_serial_t keyid, | |||
1454 | */ | 1454 | */ |
1455 | long keyctl_session_to_parent(void) | 1455 | long keyctl_session_to_parent(void) |
1456 | { | 1456 | { |
1457 | #ifdef TIF_NOTIFY_RESUME | ||
1458 | struct task_struct *me, *parent; | 1457 | struct task_struct *me, *parent; |
1459 | const struct cred *mycred, *pcred; | 1458 | const struct cred *mycred, *pcred; |
1460 | struct cred *cred, *oldcred; | 1459 | struct task_work *newwork, *oldwork; |
1461 | key_ref_t keyring_r; | 1460 | key_ref_t keyring_r; |
1461 | struct cred *cred; | ||
1462 | int ret; | 1462 | int ret; |
1463 | 1463 | ||
1464 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); | 1464 | keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); |
1465 | if (IS_ERR(keyring_r)) | 1465 | if (IS_ERR(keyring_r)) |
1466 | return PTR_ERR(keyring_r); | 1466 | return PTR_ERR(keyring_r); |
1467 | 1467 | ||
1468 | ret = -ENOMEM; | ||
1469 | newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL); | ||
1470 | if (!newwork) | ||
1471 | goto error_keyring; | ||
1472 | |||
1468 | /* our parent is going to need a new cred struct, a new tgcred struct | 1473 | /* our parent is going to need a new cred struct, a new tgcred struct |
1469 | * and new security data, so we allocate them here to prevent ENOMEM in | 1474 | * and new security data, so we allocate them here to prevent ENOMEM in |
1470 | * our parent */ | 1475 | * our parent */ |
1471 | ret = -ENOMEM; | ||
1472 | cred = cred_alloc_blank(); | 1476 | cred = cred_alloc_blank(); |
1473 | if (!cred) | 1477 | if (!cred) |
1474 | goto error_keyring; | 1478 | goto error_newwork; |
1475 | 1479 | ||
1476 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); | 1480 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); |
1477 | keyring_r = NULL; | 1481 | init_task_work(newwork, key_change_session_keyring, cred); |
1478 | 1482 | ||
1479 | me = current; | 1483 | me = current; |
1480 | rcu_read_lock(); | 1484 | rcu_read_lock(); |
1481 | write_lock_irq(&tasklist_lock); | 1485 | write_lock_irq(&tasklist_lock); |
1482 | 1486 | ||
1483 | parent = me->real_parent; | ||
1484 | ret = -EPERM; | 1487 | ret = -EPERM; |
1488 | oldwork = NULL; | ||
1489 | parent = me->real_parent; | ||
1485 | 1490 | ||
1486 | /* the parent mustn't be init and mustn't be a kernel thread */ | 1491 | /* the parent mustn't be init and mustn't be a kernel thread */ |
1487 | if (parent->pid <= 1 || !parent->mm) | 1492 | if (parent->pid <= 1 || !parent->mm) |
1488 | goto not_permitted; | 1493 | goto unlock; |
1489 | 1494 | ||
1490 | /* the parent must be single threaded */ | 1495 | /* the parent must be single threaded */ |
1491 | if (!thread_group_empty(parent)) | 1496 | if (!thread_group_empty(parent)) |
1492 | goto not_permitted; | 1497 | goto unlock; |
1493 | 1498 | ||
1494 | /* the parent and the child must have different session keyrings or | 1499 | /* the parent and the child must have different session keyrings or |
1495 | * there's no point */ | 1500 | * there's no point */ |
1496 | mycred = current_cred(); | 1501 | mycred = current_cred(); |
1497 | pcred = __task_cred(parent); | 1502 | pcred = __task_cred(parent); |
1498 | if (mycred == pcred || | 1503 | if (mycred == pcred || |
1499 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) | 1504 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) { |
1500 | goto already_same; | 1505 | ret = 0; |
1506 | goto unlock; | ||
1507 | } | ||
1501 | 1508 | ||
1502 | /* the parent must have the same effective ownership and mustn't be | 1509 | /* the parent must have the same effective ownership and mustn't be |
1503 | * SUID/SGID */ | 1510 | * SUID/SGID */ |
@@ -1507,50 +1514,40 @@ long keyctl_session_to_parent(void) | |||
1507 | pcred->gid != mycred->egid || | 1514 | pcred->gid != mycred->egid || |
1508 | pcred->egid != mycred->egid || | 1515 | pcred->egid != mycred->egid || |
1509 | pcred->sgid != mycred->egid) | 1516 | pcred->sgid != mycred->egid) |
1510 | goto not_permitted; | 1517 | goto unlock; |
1511 | 1518 | ||
1512 | /* the keyrings must have the same UID */ | 1519 | /* the keyrings must have the same UID */ |
1513 | if ((pcred->tgcred->session_keyring && | 1520 | if ((pcred->tgcred->session_keyring && |
1514 | pcred->tgcred->session_keyring->uid != mycred->euid) || | 1521 | pcred->tgcred->session_keyring->uid != mycred->euid) || |
1515 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1522 | mycred->tgcred->session_keyring->uid != mycred->euid) |
1516 | goto not_permitted; | 1523 | goto unlock; |
1517 | 1524 | ||
1518 | /* if there's an already pending keyring replacement, then we replace | 1525 | /* cancel an already pending keyring replacement */ |
1519 | * that */ | 1526 | oldwork = task_work_cancel(parent, key_change_session_keyring); |
1520 | oldcred = parent->replacement_session_keyring; | ||
1521 | 1527 | ||
1522 | /* the replacement session keyring is applied just prior to userspace | 1528 | /* the replacement session keyring is applied just prior to userspace |
1523 | * restarting */ | 1529 | * restarting */ |
1524 | parent->replacement_session_keyring = cred; | 1530 | ret = task_work_add(parent, newwork, true); |
1525 | cred = NULL; | 1531 | if (!ret) |
1526 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); | 1532 | newwork = NULL; |
1527 | 1533 | unlock: | |
1528 | write_unlock_irq(&tasklist_lock); | 1534 | write_unlock_irq(&tasklist_lock); |
1529 | rcu_read_unlock(); | 1535 | rcu_read_unlock(); |
1530 | if (oldcred) | 1536 | if (oldwork) { |
1531 | put_cred(oldcred); | 1537 | put_cred(oldwork->data); |
1532 | return 0; | 1538 | kfree(oldwork); |
1533 | 1539 | } | |
1534 | already_same: | 1540 | if (newwork) { |
1535 | ret = 0; | 1541 | put_cred(newwork->data); |
1536 | not_permitted: | 1542 | kfree(newwork); |
1537 | write_unlock_irq(&tasklist_lock); | 1543 | } |
1538 | rcu_read_unlock(); | ||
1539 | put_cred(cred); | ||
1540 | return ret; | 1544 | return ret; |
1541 | 1545 | ||
1546 | error_newwork: | ||
1547 | kfree(newwork); | ||
1542 | error_keyring: | 1548 | error_keyring: |
1543 | key_ref_put(keyring_r); | 1549 | key_ref_put(keyring_r); |
1544 | return ret; | 1550 | return ret; |
1545 | |||
1546 | #else /* !TIF_NOTIFY_RESUME */ | ||
1547 | /* | ||
1548 | * To be removed when TIF_NOTIFY_RESUME has been implemented on | ||
1549 | * m68k/xtensa | ||
1550 | */ | ||
1551 | #warning TIF_NOTIFY_RESUME not implemented | ||
1552 | return -EOPNOTSUPP; | ||
1553 | #endif /* !TIF_NOTIFY_RESUME */ | ||
1554 | } | 1551 | } |
1555 | 1552 | ||
1556 | /* | 1553 | /* |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index d71056db7b67..4ad54eea1ea4 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -834,23 +834,17 @@ error: | |||
834 | * Replace a process's session keyring on behalf of one of its children when | 834 | * Replace a process's session keyring on behalf of one of its children when |
835 | * the target process is about to resume userspace execution. | 835 | * the target process is about to resume userspace execution. |
836 | */ | 836 | */ |
837 | void key_replace_session_keyring(void) | 837 | void key_change_session_keyring(struct task_work *twork) |
838 | { | 838 | { |
839 | const struct cred *old; | 839 | const struct cred *old = current_cred(); |
840 | struct cred *new; | 840 | struct cred *new = twork->data; |
841 | |||
842 | if (!current->replacement_session_keyring) | ||
843 | return; | ||
844 | 841 | ||
845 | write_lock_irq(&tasklist_lock); | 842 | kfree(twork); |
846 | new = current->replacement_session_keyring; | 843 | if (unlikely(current->flags & PF_EXITING)) { |
847 | current->replacement_session_keyring = NULL; | 844 | put_cred(new); |
848 | write_unlock_irq(&tasklist_lock); | ||
849 | |||
850 | if (!new) | ||
851 | return; | 845 | return; |
846 | } | ||
852 | 847 | ||
853 | old = current_cred(); | ||
854 | new-> uid = old-> uid; | 848 | new-> uid = old-> uid; |
855 | new-> euid = old-> euid; | 849 | new-> euid = old-> euid; |
856 | new-> suid = old-> suid; | 850 | new-> suid = old-> suid; |