Jesse Keating 7a3296
From c2f1645ae87d5b7fc5e5973c3a93a4ae1684a76b Mon Sep 17 00:00:00 2001
Jesse Keating 7a3296
From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
Jesse Keating 7a3296
Date: Tue, 22 Jun 2010 11:31:13 +0100
Jesse Keating 7a3296
Subject: Merge remote branch 'utrace/utrace-ptrace' into rawhide
Jesse Keating 7a3296
Jesse Keating 7a3296
% git log --oneline --no-merges 7e27d6e..a91f6b7
Jesse Keating 7a3296
f979955 utrace-ptrace: fix compiling ptrace_regset under CONFIG_UTRACE
Jesse Keating 7a3296
b5f196b utrace-ptrace: copy PTRACE_GETREGSET code to utrace-ptrace
Jesse Keating 7a3296
d83135e utrace: fix utrace_maybe_reap() vs find_matching_engine() race
Jesse Keating 7a3296
9a2c607 utrace: move CONFIG_UTRACE after AUDITSYSCALL in init/Kconfig
Jesse Keating 7a3296
62f4621 utrace: s/rmb/mb/ in tracehook_notify_resume()
Jesse Keating 7a3296
65f5e9d utrace: fix utrace_maybe_reap logic
Jesse Keating 7a3296
ed1f9c2 utrace: fix syntax nit for !CONFIG_UTRACE
Jesse Keating 7a3296
71e3f39 ptrace: add utrace comment
Jesse Keating 7a3296
e7afc73 utrace: use WARN with text
Jesse Keating 7a3296
a8ced33 utrace: cosmetic restructure
Jesse Keating 7a3296
4330b80 utrace: remove some inline keywords
Jesse Keating 7a3296
d4be40a utrace: remove report_clone special priority for utrace_attach_task on child
Jesse Keating 7a3296
8c56566 ptrace: updates for utrace API changes
Jesse Keating 7a3296
1900135 utrace: streamline callback API
Jesse Keating 7a3296
97662d3 utrace: more cosmetic trivia
Jesse Keating 7a3296
fd414cd utrace: more cosmetic cleanup
Jesse Keating 7a3296
f30f068 utrace: cosmetic trivia
Jesse Keating 7a3296
cfebda7 utrace: fix the comments about rmb() in task_utrace_struct()
Jesse Keating 7a3296
875858a utrace: improve the comment in tracehook_notify_resume()
Jesse Keating 7a3296
76b49a5 utrace: fix the ->cloning check in utrace_attach_delay()
Jesse Keating 7a3296
e0755bb utrace: kill mb() in tracehook_report_death()
Jesse Keating 7a3296
9fdc988 fix __must_check warnings
Jesse Keating 7a3296
3e02499 kill suppress_sigtrap()
Jesse Keating 7a3296
f872e69 utrace: don't set ->ops = utrace_detached_ops lockless
Jesse Keating 7a3296
938482e utrace: fix doc typo
Jesse Keating 7a3296
7fae049 utrace: avoid BUG_ON when engine leaves bogus si_signo
Jesse Keating 7a3296
71b7a85 utrace: trivial, move CONFIG_UTRACE into "General setup"
Jesse Keating 7a3296
9c8dbe0 utrace: reset report action for UTRACE_SYSCALL_RESUMED iteration
Jesse Keating 7a3296
4c7514e join PTRACE_EVENT_SYSCALL_XXX states
Jesse Keating 7a3296
a8f782e export __ptrace_detach() and do_notify_parent_cldstop()
Jesse Keating 7a3296
c3473e1 ptrace_signal: check PT_PTRACED before reporting a signal
Jesse Keating 7a3296
b396f5e tracehooks: check PT_PTRACED before reporting the single-step
Jesse Keating 7a3296
45667dd tracehooks: kill some PT_PTRACED checks
Jesse Keating 7a3296
e8a2f23 ptrace: cleanup ptrace_init_task()->ptrace_link() path
Jesse Keating 7a3296
611dab8 kill CONFIG_UTRACE_PTRACE
Jesse Keating 7a3296
8d3833e rm kernel/ptrace-common.h
Jesse Keating 7a3296
494deb7 export __ptrace_detach(), add "ifndef CONFIG_UTRACE" into ptrace.c
Jesse Keating 7a3296
05cb325 (upstream) reorder the code in kernel/ptrace.c
Jesse Keating 7a3296
eb10f13 restore the old kernel/ptrace.c
Jesse Keating 7a3296
ddcc525 utrace_resume: Avoid finish_resume_report() for UTRACE_RESUME
Jesse Keating 7a3296
47852f9 mv kernel/ptrace.c kernel/ptrace-utrace.c
Jesse Keating 7a3296
de5a46e utrace: fix UTRACE_SYSCALL_RESUMED nits
Jesse Keating 7a3296
3bd4be9 stepping, accommodate to utrace-cleanup changes
Jesse Keating 7a3296
679be9e Revert "utrace: synthesize SIGTRAP for single-stepping at syscall-exit"
Jesse Keating 7a3296
23ab966 utrace: barrier nits
Jesse Keating 7a3296
d3800b8 utrace: tracehook_init_task
Jesse Keating 7a3296
64daf14 utrace: task_utrace_struct() barrier
Jesse Keating 7a3296
f19442c utrace: synthesize SIGTRAP for single-stepping at syscall-exit
Jesse Keating 7a3296
2583b32 utrace: nit for utrace-ptrace
Jesse Keating 7a3296
a88b467 ptrace: x86: change syscall_trace_leave() to rely on tracehook when stepping
Jesse Keating 7a3296
e01acf4 ptrace: x86: implement user_single_step_siginfo()
Jesse Keating 7a3296
462a57b ptrace: change tracehook_report_syscall_exit() to handle stepping
Jesse Keating 7a3296
172590d ptrace: powerpc: implement user_single_step_siginfo()
Jesse Keating 7a3296
d63b43d ptrace: introduce user_single_step_siginfo() helper
Jesse Keating 7a3296
c575558 utrace: barriers for initializing struct utrace
Jesse Keating 7a3296
89df3c7 utrace: utrace_attach_task() forgets to return when ->utrace == NULL
Jesse Keating 7a3296
4d17e95 utrace: finish_report() must never set ->resume = UTRACE_STOP
Jesse Keating 7a3296
212f67e utrace: utrace_get_signal() must check ->pending_attach
Jesse Keating 7a3296
eff6ca8 change ptrace_report_signal() to use user_single_step_siginfo()
Jesse Keating 7a3296
cba1272 don't send the unnecessary SIGTRAP after SYSCALL_EXIT
Jesse Keating 7a3296
8aa71a6 revert "turn PTRACE_EVENT_SIGTRAP into PTRACE_EVENT_SIGNAL"
Jesse Keating 7a3296
90c8237 utrace-ptrace: minimally handle UTRACE_SYSCALL_RESUMED
Jesse Keating 7a3296
a7e9198 utrace: clean up resume-action handling
Jesse Keating 7a3296
962eb2f utrace: update after merge
Jesse Keating 7a3296
e2ced71 re-introduce utrace_finish_stop() to fix the race with SIGKILL
Jesse Keating 7a3296
603e19c turn PTRACE_EVENT_SIGTRAP into PTRACE_EVENT_SIGNAL
Jesse Keating 7a3296
ff87f65 introduce suppress_sigtrap() to prevent unwanted send_sigtrap()
Jesse Keating 7a3296
6505e3c move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal()
Jesse Keating 7a3296
5261baa prepare ptrace_report_signal() to synthesize SIGTRAP
Jesse Keating 7a3296
ef9534b ptrace_request: turn ptrace_resume() into default case
Jesse Keating 7a3296
f50c776 s/context/ctx/
Jesse Keating 7a3296
228b2e3 ptrace_notify_stop: kill the temporary WARN_ON()
Jesse Keating 7a3296
93e866a ptrace_request(PTRACE_KILL) should not(?) return -ESRCH
Jesse Keating 7a3296
26fefca utrace: sticky resume action
Jesse Keating 7a3296
28b2774b utrace: remove ->stopped field
Jesse Keating 7a3296
9e0f357 utrace_set_events: nit clean up
Jesse Keating 7a3296
6d0bad3 nits
Jesse Keating 7a3296
48bab07 (utrace) utrace_get_signal: don't dequeue_signal() if ->group_stop_count
Jesse Keating 7a3296
d4ef551 (upstream) signals: check ->group_stop_count after tracehook_get_signal()
Jesse Keating 7a3296
6292daa ptrace_detach_task: don't use valid_signal()
Jesse Keating 7a3296
c5a6a82 cosmetic, renames
Jesse Keating 7a3296
e422a3f cosmetic, relocate some code in ptrace.c
Jesse Keating 7a3296
b96e4db (upstream) introduce kernel/ptrace.h
Jesse Keating 7a3296
7665564 (upstream) tracehook_signal_handler: check PT_PTRACED
Jesse Keating 7a3296
7d708ca tracehooks: revert utrace-ptrace changes
Jesse Keating 7a3296
4104e29 (upstream) ptrace_init_task: cleanup the usage of ptrace_link()
Jesse Keating 7a3296
d04ccb7 revert all utrace-ptrace changes in ptrace.h
Jesse Keating 7a3296
80786ce revert utrace-ptrace changes in kernel/signal.c
Jesse Keating 7a3296
0b02f9e introduce PT_UTRACED to replace PT_PTRACED inside ptrace.c
Jesse Keating 7a3296
030ce35 tracehooks: remove some PT_PTRACED checks
Jesse Keating 7a3296
4b7b15a revert the clone() related changes in tracehook.h
Jesse Keating 7a3296
769030e hack ptrace_check_attach() to make it almost correct
Jesse Keating 7a3296
7aa5c3a cosmetic, fold do_ptrace_resume() into ptrace_resume()
Jesse Keating 7a3296
d27ebc1 cosmetic, introduce ptrace_resume_action()
Jesse Keating 7a3296
35fbca4 turn context->sysemu into PTRACE_O_SYSEMU
Jesse Keating 7a3296
38a8c1f PTRACE_SYSEMU_SINGLESTEP support
Jesse Keating 7a3296
4367836 PTRACE_SYSEMU support
Jesse Keating 7a3296
16819db ptrace_report_clone: minor cleanups + comments
Jesse Keating 7a3296
ac1afd8 ptrace_resume: rewrite request processing
Jesse Keating 7a3296
6b0d4f6 do_ptrace_resume: always use ptrace_wake_up()
Jesse Keating 7a3296
fa92ce3 do_ptrace_resume: consolidate multiple switch stmts
Jesse Keating 7a3296
135d780 uglify the code again to report VFORK_DONE after VFORK
Jesse Keating 7a3296
4e3f362 fix PTRACE_SYSCALL after PTRACE_EVENT_VFORK_DONE stop
Jesse Keating 7a3296
3f95189 ptrace_report_clone: uglify even more to handle TRACEVFORKDONE without TRACEVFORK
Jesse Keating 7a3296
66ca8b6 ptrace_report_clone: uglify CLONE_PTRACE/CLONE_UNTRACED behaviour to match upstream
Jesse Keating 7a3296
fc82b2c pretend PTRACE_O_TRACEVFORKDONE doesn't exist
Jesse Keating 7a3296
28aa15a utrace_set_events: never return -EINPROGRESS unless clearing some event bits
Jesse Keating 7a3296
a7f4350 utrace_stop: do ptrace_notify_stop() unconditionally
Jesse Keating 7a3296
cb78492 ptrace_report_exit: fix WARN_ON() condition
Jesse Keating 7a3296
bb941c3 do_ptrace_notify_stop: document the usage of tracee->exit_code
Jesse Keating 7a3296
383ba85 ptrace_wake_up: don't clear tracee->exit_code + update comments
Jesse Keating 7a3296
3d5c221 ptrace_wake_up: add "bool force_wakeup" argument for implicit detach
Jesse Keating 7a3296
be6862e ptrace_wake_up: clear context->stop_code
Jesse Keating 7a3296
bfb40c8 detach: use ptrace_wake_up() instead of utrace_control()
Jesse Keating 7a3296
7de148a shift context re-initialization from detach to reuse
Jesse Keating 7a3296
464def3 cleanup/optimize reuse/attch in ptrace_attach_task()
Jesse Keating 7a3296
50f56b9 ptrace_attach_task: rely on utrace_barrier(), don't check ->ops
Jesse Keating 7a3296
03376fd use set_stop_code() in ptrace_report_signal(UTRACE_SIGNAL_HANDLER)
Jesse Keating 7a3296
85f8b3a detach should reset the context of self-detaching engine
Jesse Keating 7a3296
a27233a attach: try to re-use the self-detaching engine
Jesse Keating 7a3296
8667615 ptrace_notify_stop: fix engine leak
Jesse Keating 7a3296
3d5d053 ptrace_detach_task: don't use engine ptr before IS_ERR(engine)
Jesse Keating 7a3296
01875c7 fold detach_signal() into ptrace_detach_task()
Jesse Keating 7a3296
464c2b7 don't detach the engine with the parting signal
Jesse Keating 7a3296
97b345c implement the basic detach-with-signal logic
Jesse Keating 7a3296
a158247 rework access to context->siginfo
Jesse Keating 7a3296
20ea83b introduce set_stop_code() helper
Jesse Keating 7a3296
eb222ed cosmetic, misc renames
Jesse Keating 7a3296
f83b2ca move "event << 8" into syscall_code()
Jesse Keating 7a3296
4c99287 kill context->ev_name
Jesse Keating 7a3296
df7c8f2 encode internal stop events in ->ev_code too
Jesse Keating 7a3296
3f48297 introduce get_stop_code(context) helper
Jesse Keating 7a3296
313bad1 introduce syscall_code(context) helper
Jesse Keating 7a3296
47b5e2c don't clear context->ev_code for debugging
Jesse Keating 7a3296
4e09fe3 convert ptrace_setsiginfo() to use ptrace_rw_siginfo()
Jesse Keating 7a3296
53187be convert ptrace_getsiginfo() to use ptrace_rw_siginfo()
Jesse Keating 7a3296
e7ac055 introduce ptrace_rw_siginfo() helper
Jesse Keating 7a3296
c625793 move "resume signal" logic into the tracee's context
Jesse Keating 7a3296
0768d89 UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL
Jesse Keating 7a3296
e90cb71 don't use task_struct->ptrace_message
Jesse Keating 7a3296
842684f do_ptrace_notify_stop: fix the race with SIGKILL
Jesse Keating 7a3296
d0ed18d do_ptrace_notify_stop: backport the "sync wakeup" logic
Jesse Keating 7a3296
08f4a21 fix the stepping over syscall
Jesse Keating 7a3296
a55d174 implement the stacked SYSCALL_EXIT event
Jesse Keating 7a3296
ba73824 ptrace_resume: don't ignore "data" argument
Jesse Keating 7a3296
fbd4368 kill context->ev_array[]
Jesse Keating 7a3296
3c6f822 Revert "ptrace_resume_signal() should use context->siginfo under ->siglock"
Jesse Keating 7a3296
ee31432 Revert "UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL"
Jesse Keating 7a3296
a4e5af1 Revert "introduce context_siginfo() helper"
Jesse Keating 7a3296
9bc939a revert merge w/s change
Jesse Keating 7a3296
6752625 introduce context_siginfo() helper
Jesse Keating 7a3296
d43a453 UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL
Jesse Keating 7a3296
e4e48df ptrace_resume_signal() should use context->siginfo under ->siglock
Jesse Keating 7a3296
4492770 implement UTRACE_SIGNAL_HANDLER stepping
Jesse Keating 7a3296
5f926a5 implement PTRACE_SINGLESTEP/PTRACE_SINGLEBLOCK
Jesse Keating 7a3296
8b70ae1 ptrace_request: use ptrace_lookup_engine()
Jesse Keating 7a3296
abd580d change ptrace_resume() to have the single "return"
Jesse Keating 7a3296
85878ae introduce ptrace_lookup_engine()
Jesse Keating 7a3296
74904f1 mv task_struct->last_siginfo ptrace_context->siginfo
Jesse Keating 7a3296
2b17f4a pretens ptrace_detach(sig) works
Jesse Keating 7a3296
075db41 ptrace_report_quiesce() can't trust fatal_signal_pending()
Jesse Keating 7a3296
d583c87 remove the now unneeded code
Jesse Keating 7a3296
69a6c83 break ptrace_report_signal()
Jesse Keating 7a3296
d6a31ee do_ptrace_notify_stop: kill "->ev_message != 0" check
Jesse Keating 7a3296
e194687 convert ptrace_report_exit()
Jesse Keating 7a3296
8bf8304 PTRACE_EVENT_VFORK_DONE: set ev_options = PTRACE_O_TRACEVFORKDONE
Jesse Keating 7a3296
b8f5e2a make sure PTRACE_SYSCALL reports SYSCALL_EXIT
Jesse Keating 7a3296
258b27d make sure PTRACE_CONT "disables" SYSCALL_EXIT report
Jesse Keating 7a3296
d26b659 introduce ptrace_event->ev_options
Jesse Keating 7a3296
03a0fe3 convert ptrace_report_exec()
Jesse Keating 7a3296
bea6139 convert ptrace_report_syscall_entry()
Jesse Keating 7a3296
17dd96d cleanup/simplify stop/resume mess
Jesse Keating 7a3296
97fc962 utrace: comments
Jesse Keating 7a3296
c661ddb utrace: move struct utrace back where it belongs
Jesse Keating 7a3296
95dcdee implement stacked stop events
Jesse Keating 7a3296
8608da6 ptrace_report_syscall_exit: do not WARN() if killed
Jesse Keating 7a3296
95a6b6b ptrace_report_clone: rework the stop/resume logic
Jesse Keating 7a3296
25dd723 remove the current PTRACE_EVENT_VFORK_DONE logic
Jesse Keating 7a3296
7d8900a ptrace_wake_up: fix the "compatibility bug" logic
Jesse Keating 7a3296
9a50d27 ptrace_report_syscall_exit: return UTRACE_STOP, not UTRACE_RESUME
Jesse Keating 7a3296
c07370d simplify utrace_add_engine() vs utrace_reap() protection
Jesse Keating 7a3296
0f4d918 utrace_add_engine: cleanup
Jesse Keating 7a3296
a24e891 fix utrace_reset() vs release_task() theoretical race
Jesse Keating 7a3296
dfc0917 change attach/release to avoid unnecessary utrace_reap()
Jesse Keating 7a3296
cbed668 utrace_attach_task: do no check ->exit_state
Jesse Keating 7a3296
9d114a6 utrace_wakeup: do not check target->state
Jesse Keating 7a3296
9368f18 utrace_wakeup: lock ->siglock directly
Jesse Keating 7a3296
e9b58e9 convert ptrace_report_syscall_exit() to use ptrace_context
Jesse Keating 7a3296
1d47e4d introduce context->resume_stopped()
Jesse Keating 7a3296
c34d813 introduce context->stopped_code
Jesse Keating 7a3296
b7edb5e introduce ptrace_notify_stop()
Jesse Keating 7a3296
93b2e7e utrace_release_task: cosmetic
Jesse Keating 7a3296
ac6e19c utrace_reap: loop lockless, do not clear ->ops and ->flags early
Jesse Keating 7a3296
7852d10 utrace: slow_path -> pending_attach
Jesse Keating 7a3296
c827b15 utrace_add_engine() should set ->utrace_flags |= REAP
Jesse Keating 7a3296
2e12892 utrace_reap: fix missing callback
Jesse Keating 7a3296
04852f3 utrace: do not force report on attach
Jesse Keating 7a3296
37b68f7 kill ptrace_setoptions() and ptrace_update_utrace()
Jesse Keating 7a3296
f1b39f3 use context->options instead of "->ptrace & PT_"
Jesse Keating 7a3296
d05bf8e ptrace_set_options: use PTRACE_O_ instead of PT_
Jesse Keating 7a3296
167b56a "disable" tracehook_prepare_clone()
Jesse Keating 7a3296
5e526f3 introduce ptrace_set_options()
Jesse Keating 7a3296
4a50ac1 introduce ptrace_context->options
Jesse Keating 7a3296
0457aa8 introduce the empty struct ptrace_context
Jesse Keating 7a3296
a2bca6f utrace_reset: do not use "unsafe mode"
Jesse Keating 7a3296
eac91f4 utrace_control: don't mark_engine_detached() before engine_wants_stop()
Jesse Keating 7a3296
c2916fb utrace_control: fix utrace_reset(safe) usage when ->exit_state != 0
Jesse Keating 7a3296
c36a311 utrace_reset fix
Jesse Keating 7a3296
8d2fc04 utrace: remove unused inline
Jesse Keating 7a3296
64a8ca3 utrace_reset cleanup
Jesse Keating 7a3296
d1a14ce utrace: change UTRACE_STOP bookkeeping
Jesse Keating 7a3296
96fe3cc Revert "utrace_stop: fix UTRACE_DETACH race"
Jesse Keating 7a3296
ceaae71 utrace: check QUIESCE before reporting UTRACE_SIGNAL_REPORT/HANDLER
Jesse Keating 7a3296
fc30d20 utrace_do_stop: move "if (exit_state)" logic to the caller
Jesse Keating 7a3296
9b655f7 utrace_do_stop: don't set ->stopped when ->exit_state
Jesse Keating 7a3296
9ed6a39 utrace_set_events: never return -EINPROGRESS on a zombie
Jesse Keating 7a3296
592d977 utrace_do_stop: cleanup the usage of ->siglock
Jesse Keating 7a3296
7f51e58 utrace: fix utrace->signal_handler "leakage"
Jesse Keating 7a3296
be5e266 utrace: utrace_finish_vfork: check ->vfork_stop lockless
Jesse Keating 7a3296
c3580f1 utrace-ptrace: fix conditions in ptrace_do_detach
Jesse Keating 7a3296
00932db utrace_stop: fix UTRACE_DETACH race
Jesse Keating 7a3296
b032859 utrace: move utrace_stop down
Jesse Keating 7a3296
a62ed15 utrace: consolidate utrace_reset callers
Jesse Keating 7a3296
c8315d3 ptrace_do_detach: Fiddle code to avoid warnings.
Jesse Keating 7a3296
e3635f1 utrace-ptrace: use WARN_ON(), suppress __must_check warning
Jesse Keating 7a3296
8ba59d7 ptrace_attach_task: kill ->ptrace != 0 check
Jesse Keating 7a3296
a18378e exit_ptrace: use ptrace_do_detach()
Jesse Keating 7a3296
371c69c ptrace_detach: do ptrace_unlink() first
Jesse Keating 7a3296
096f3ed ptrace_detach: kill the unconditional wakeup
Jesse Keating 7a3296
d999521 ptrace_report_clone: rework auto-attaching
Jesse Keating 7a3296
8cefebf move ->ptrace == 0 checks to ptrace_attach_task()
Jesse Keating 7a3296
471d6f4 utrace_engine_ops: add release hook
Jesse Keating 7a3296
78ca7e7 utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE)
Jesse Keating 7a3296
fcb8fa0 change ptrace_traceme() to use the new helpers, kill prepare/finish attach
Jesse Keating 7a3296
e82feff rework prepare_ptrace_attach/finish_ptrace_attach
Jesse Keating 7a3296
3bea38f do not use engine->data
Jesse Keating 7a3296
57cedd0 ptrace_detach_task: always do UTRACE_DETACH
Jesse Keating 7a3296
2093f3a shift ptrace_utrace_exit() from tracehook_report_exit() to exit_ptrace()
Jesse Keating 7a3296
33fb930 ptrace_resume()->send_sig() can crash
Jesse Keating 7a3296
a7b05fd ptrace_check_attach: check child->parent
Jesse Keating 7a3296
5ed4eff remove (almost all) !CONFIG_UTRACE_PTRACE code
Jesse Keating 7a3296
fb9379c change utrace_stop() to return void
Jesse Keating 7a3296
5bbbb41 kill utrace_report->killed
Jesse Keating 7a3296
0b57f74 finish_utrace_stop: use __fatal_signal_pending(), dont take ->siglock
Jesse Keating 7a3296
113a07e utrace: rework finish_report flag logic
Jesse Keating 7a3296
8ad60bb utrace_stop: preserve report/interrupt requests across stop/resume
Jesse Keating 7a3296
af3eb44 get_utrace_lock: do not check EXIT_DEAD
Jesse Keating 7a3296
d87e8c4 finish_utrace_stop: check ->stopped lockless
Jesse Keating 7a3296
3e0a686 utrace_report_jctl/utrace_get_signal: do not play with ->stopped
Jesse Keating 7a3296
7d97118 utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT
Jesse Keating 7a3296
ad2497a use tracehook_finish_jctl() to clear ->stopped
Jesse Keating 7a3296
f99db9f utrace_report_jctl: do not play with the group-stop state
Jesse Keating 7a3296
fd89498 introduce tracehook_finish_jctl() helper
Jesse Keating 7a3296
ff6be89 do_signal_stop: do not call tracehook_notify_jctl() in TASK_STOPPED state
Jesse Keating 7a3296
66e0705 utrace_stop: don't forget about SIGNAL_STOP_STOPPED
Jesse Keating 7a3296
2edad7d utrace_wakeup: take ->group_stop_count into account
Jesse Keating 7a3296
d4bcb57 utrace_reap: clear engine->flags when finishing detach
Jesse Keating 7a3296
cf890ad utrace: fix utrace->reporting left set for no callback
Jesse Keating 7a3296
cbe5188 More than one user has hit the -EEXIST problem when using utrace_attach_task and UTRACE_ATTACH_EXCLUSIVE without UTRACE_ATTACH_MATCH_DATA|_OPS. Document that a bit more.
Jesse Keating 7a3296
52db080 UTRACE_SYSCALL_RESUMED repeat callback
Jesse Keating 7a3296
5e67e22 utrace docbook: s/first/last/ braino
Jesse Keating 7a3296
4bd78f8 utrace: reverse engine callback order for report_syscall_entry
Jesse Keating 7a3296
1757088 utrace: WARN instead of BUG on misuse of UTRACE_*STEP without arch_has_*_step() check
Jesse Keating 7a3296
5d4e97b utrace: restore tracehook_report_death comment misplaced in merges
Jesse Keating 7a3296
cb49dcd utrace_report_syscall_entry: remove unnecessary recalc_sigpending() check
Jesse Keating 7a3296
c0909b5 utrace_resume: fix potential TIF_SIGPENDING race
Jesse Keating 7a3296
f0a1c64 utrace: use \t separator in /proc/pid/status
Jesse Keating 7a3296
13a5838 utrace: init_task syntax nit
Jesse Keating 7a3296
715d2a1 utrace: cosmetic
Jesse Keating 7a3296
42de707 utrace_report_jctl: do splice_attaching
Jesse Keating 7a3296
622013d utrace_resume: remove racy BUG_ON
Jesse Keating 7a3296
282d685 whitespace fix
Jesse Keating 7a3296
bec92f8 signals: tracehook_notify_jctl change
Jesse Keating 7a3296
a7181aa utrace: simplify death report condition
Jesse Keating 7a3296
4d8a6fd utrace: barrier between TIF_NOTIFY_RESUME check and utrace_flags/utrace->report checks
Jesse Keating 7a3296
ae3096f utrace-ptrace: remove unsafe_exec and tracer_task hooks
Jesse Keating 7a3296
325fecc utrace: get rid of tracer_task and unsafe_exec hooks
Jesse Keating 7a3296
0084fc2 utrace: ensure UTRACE_REPORT callback return leads to callback after utrace_stop
Jesse Keating 7a3296
5bdc6f1 utrace: cosmetic: DEAD_FLAGS_MASK macro
Jesse Keating 7a3296
5c5bdbe utrace: cosmetic: _UTRACE_DEATH_EVENTS macro
Jesse Keating 7a3296
f067223 utrace: make sure utrace_flags is nonzero before set_notify_resume at attach
Jesse Keating 7a3296
e2d293e utrace: drop racy unlocked check in utrace_do_stop
Jesse Keating 7a3296
68f3899 utrace: fix ->report_jctl @notify argument
Jesse Keating 7a3296
c743327 utrace: avoid unnecessary list_for_each_safe
Jesse Keating 7a3296
acd516b utrace_stop: trivial, kill the unnecessary assignment
Jesse Keating 7a3296
81ed517 utrace_add_engine: add missing 'else' after 'if (utrace->reap)'
Jesse Keating 7a3296
215a076 utrace: tracehook.h comment
Jesse Keating 7a3296
a584c66 utrace: fix utrace_attach_delay() creator test
Jesse Keating 7a3296
827ec3b utrace: comment ->reporting implementation
Jesse Keating 7a3296
07732b4 utrace-ptrace: handle -ERESTARTNOINTR from utrace_attach_task
Jesse Keating 7a3296
2233b06 utrace: finish utrace_reap conversion after indirect->direct struct utrace
Jesse Keating 7a3296
dd30e86 utrace: fix utrace_attach_delay() to loop, remove struct utrace.cloning field
Jesse Keating 7a3296
be4f357 get_utrace_lock: kill the bogus engine->kref.refcount check
Jesse Keating 7a3296
c367207 utrace: clear struct in utrace_init_task
Jesse Keating 7a3296
94f168c utrace: define UTRACE_API_VERSION
Jesse Keating 7a3296
742f120 utrace: place struct utrace directly in task_struct
Jesse Keating 7a3296
cb25a58 utrace: comment fixes
Jesse Keating 7a3296
2b834a5 utrace-ptrace: struct utrace_attached_engine -> struct utrace_engine
Jesse Keating 7a3296
6b8306a utrace: struct utrace_attached_engine -> struct utrace_engine
Jesse Keating 7a3296
9fe3bac utrace-ptrace: Kconfig doc update
Jesse Keating 7a3296
5bb0052 utrace: cosmetic changes
Jesse Keating 7a3296
556a7e7 utrace-ptrace: fix resuming with blocked signal
Jesse Keating 7a3296
3a9f4c8 utrace: order utrace_control() after callback return value processing
Jesse Keating 7a3296
269150d Cosmetic reorganization to further simplify utrace pointer vs embedded-struct.
Jesse Keating 7a3296
ea30176 Use task_utrace_struct() helper in utrace_interrupt_pending().
Jesse Keating 7a3296
ed2098a Use task_utrace_struct() helper
Jesse Keating 7a3296
97d5cde cosmetic code reorganization
Jesse Keating 7a3296
4e8a7ca Remove UTRACE_DEBUG hacks
Jesse Keating 7a3296
25fb674 utrace: exclude PTRACE_TRACEME
Jesse Keating 7a3296
f286be7 utrace-ptrace: remove utrace_engine_put stub
Jesse Keating 7a3296
e0c36bd Disable mutual exclusion if CONFIG_UTRACE_PTRACE
Jesse Keating 7a3296
c93d704 utrace/ptrace mutual exclusion
Jesse Keating 7a3296
594f22c cond_resched() before race-restart in utrace_attach_task
Jesse Keating 7a3296
0da72f3 Clean up utrace_attach_task code.
Jesse Keating 7a3296
fd3d457 utrace: ptrace cooperation
Jesse Keating 7a3296
f357a74 utrace core
Jesse Keating 7a3296
---
Jesse Keating 7a3296
 Documentation/DocBook/Makefile    |    2 +-
Jesse Keating 7a3296
 Documentation/DocBook/utrace.tmpl |  590 +++++++++
Jesse Keating 7a3296
 fs/proc/array.c                   |    3 +
Jesse Keating 7a3296
 include/linux/ptrace.h            |    3 +-
Jesse Keating 7a3296
 include/linux/sched.h             |    6 +
Jesse Keating 7a3296
 include/linux/tracehook.h         |   97 ++-
Jesse Keating 7a3296
 include/linux/utrace.h            |  692 +++++++++++
Jesse Keating 7a3296
 init/Kconfig                      |    9 +
Jesse Keating 7a3296
 kernel/Makefile                   |    2 +
Jesse Keating 7a3296
 kernel/fork.c                     |    3 +
Jesse Keating 7a3296
 kernel/ptrace-utrace.c            | 1127 +++++++++++++++++
Jesse Keating 7a3296
 kernel/ptrace.c                   |  620 +++++-----
Jesse Keating 7a3296
 kernel/signal.c                   |    4 +-
Jesse Keating 7a3296
 kernel/utrace.c                   | 2452 +++++++++++++++++++++++++++++++++++++
Jesse Keating 7a3296
 14 files changed, 5291 insertions(+), 319 deletions(-)
Jesse Keating 7a3296
 create mode 100644 Documentation/DocBook/utrace.tmpl
Jesse Keating 7a3296
 create mode 100644 include/linux/utrace.h
Jesse Keating 7a3296
 create mode 100644 kernel/ptrace-utrace.c
Jesse Keating 7a3296
 create mode 100644 kernel/utrace.c
Jesse Keating 7a3296
Jesse Keating 7a3296
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
Jesse Keating 7a3296
index c7e5dc7..e63f889 100644
Jesse Keating 7a3296
--- a/Documentation/DocBook/Makefile
Jesse Keating 7a3296
+++ b/Documentation/DocBook/Makefile
Jesse Keating 7a3296
@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
Jesse Keating 7a3296
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
Jesse Keating 7a3296
 	    mac80211.xml debugobjects.xml sh.xml regulator.xml \
Jesse Keating 7a3296
 	    alsa-driver-api.xml writing-an-alsa-driver.xml \
Jesse Keating 7a3296
-	    tracepoint.xml media.xml drm.xml
Jesse Keating 7a3296
+	    tracepoint.xml utrace.xml media.xml drm.xml
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 ###
Jesse Keating 7a3296
 # The build process is as follows (targets):
Jesse Keating 7a3296
diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..e149f49
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/Documentation/DocBook/utrace.tmpl
Jesse Keating 7a3296
@@ -0,0 +1,590 @@
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<book id="utrace">
Jesse Keating 7a3296
+  <bookinfo>
Jesse Keating 7a3296
+    <title>The utrace User Debugging Infrastructure</title>
Jesse Keating 7a3296
+  </bookinfo>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <toc></toc>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <chapter id="concepts"><title>utrace concepts</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect1 id="intro"><title>Introduction</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    <application>utrace</application> is infrastructure code for tracing
Jesse Keating 7a3296
+    and controlling user threads.  This is the foundation for writing
Jesse Keating 7a3296
+    tracing engines, which can be loadable kernel modules.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    The basic actors in <application>utrace</application> are the thread
Jesse Keating 7a3296
+    and the tracing engine.  A tracing engine is some body of code that
Jesse Keating 7a3296
+    calls into the <filename><linux/utrace.h></filename>
Jesse Keating 7a3296
+    interfaces, represented by a <structname>struct
Jesse Keating 7a3296
+    utrace_engine_ops</structname>.  (Usually it's a kernel module,
Jesse Keating 7a3296
+    though the legacy <function>ptrace</function> support is a tracing
Jesse Keating 7a3296
+    engine that is not in a kernel module.)  The interface operates on
Jesse Keating 7a3296
+    individual threads (<structname>struct task_struct</structname>).
Jesse Keating 7a3296
+    If an engine wants to treat several threads as a group, that is up
Jesse Keating 7a3296
+    to its higher-level code.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Tracing begins by attaching an engine to a thread, using
Jesse Keating 7a3296
+    <function>utrace_attach_task</function> or
Jesse Keating 7a3296
+    <function>utrace_attach_pid</function>.  If successful, it returns a
Jesse Keating 7a3296
+    pointer that is the handle used in all other calls.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  </sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect1 id="callbacks"><title>Events and Callbacks</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    An attached engine does nothing by default.  An engine makes something
Jesse Keating 7a3296
+    happen by requesting callbacks via <function>utrace_set_events</function>
Jesse Keating 7a3296
+    and poking the thread with <function>utrace_control</function>.
Jesse Keating 7a3296
+    The synchronization issues related to these two calls
Jesse Keating 7a3296
+    are discussed further below in <xref linkend="teardown"/>.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Events are specified using the macro
Jesse Keating 7a3296
+    <constant>UTRACE_EVENT(<replaceable>type</replaceable>)</constant>.
Jesse Keating 7a3296
+    Each event type is associated with a callback in <structname>struct
Jesse Keating 7a3296
+    utrace_engine_ops</structname>.  A tracing engine can leave unused
Jesse Keating 7a3296
+    callbacks <constant>NULL</constant>.  The only callbacks required
Jesse Keating 7a3296
+    are those used by the event flags it sets.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Many engines can be attached to each thread.  When a thread has an
Jesse Keating 7a3296
+    event, each engine gets a callback if it has set the event flag for
Jesse Keating 7a3296
+    that event type.  For most events, engines are called in the order they
Jesse Keating 7a3296
+    attached.  Engines that attach after the event has occurred do not get
Jesse Keating 7a3296
+    callbacks for that event.  This includes any new engines just attached
Jesse Keating 7a3296
+    by an existing engine's callback function.  Once the sequence of
Jesse Keating 7a3296
+    callbacks for that one event has completed, such new engines are then
Jesse Keating 7a3296
+    eligible in the next sequence that starts when there is another event.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Event reporting callbacks have details particular to the event type,
Jesse Keating 7a3296
+    but are all called in similar environments and have the same
Jesse Keating 7a3296
+    constraints.  Callbacks are made from safe points, where no locks
Jesse Keating 7a3296
+    are held, no special resources are pinned (usually), and the
Jesse Keating 7a3296
+    user-mode state of the thread is accessible.  So, callback code has
Jesse Keating 7a3296
+    a pretty free hand.  But to be a good citizen, callback code should
Jesse Keating 7a3296
+    never block for long periods.  It is fine to block in
Jesse Keating 7a3296
+    <function>kmalloc</function> and the like, but never wait for i/o or
Jesse Keating 7a3296
+    for user mode to do something.  If you need the thread to wait, use
Jesse Keating 7a3296
+    <constant>UTRACE_STOP</constant> and return from the callback
Jesse Keating 7a3296
+    quickly.  When your i/o finishes or whatever, you can use
Jesse Keating 7a3296
+    <function>utrace_control</function> to resume the thread.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    The <constant>UTRACE_EVENT(SYSCALL_ENTRY)</constant> event is a special
Jesse Keating 7a3296
+    case.  While other events happen in the kernel when it will return to
Jesse Keating 7a3296
+    user mode soon, this event happens when entering the kernel before it
Jesse Keating 7a3296
+    will proceed with the work requested from user mode.  Because of this
Jesse Keating 7a3296
+    difference, the <function>report_syscall_entry</function> callback is
Jesse Keating 7a3296
+    special in two ways.  For this event, engines are called in reverse of
Jesse Keating 7a3296
+    the normal order (this includes the <function>report_quiesce</function>
Jesse Keating 7a3296
+    call that precedes a <function>report_syscall_entry</function> call).
Jesse Keating 7a3296
+    This preserves the semantics that the last engine to attach is called
Jesse Keating 7a3296
+    "closest to user mode"--the engine that is first to see a thread's user
Jesse Keating 7a3296
+    state when it enters the kernel is also the last to see that state when
Jesse Keating 7a3296
+    the thread returns to user mode.  For the same reason, if these
Jesse Keating 7a3296
+    callbacks use <constant>UTRACE_STOP</constant> (see the next section),
Jesse Keating 7a3296
+    the thread stops immediately after callbacks rather than only when it's
Jesse Keating 7a3296
+    ready to return to user mode; when allowed to resume, it will actually
Jesse Keating 7a3296
+    attempt the system call indicated by the register values at that time.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  </sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect1 id="safely"><title>Stopping Safely</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="well-behaved"><title>Writing well-behaved callbacks</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Well-behaved callbacks are important to maintain two essential
Jesse Keating 7a3296
+    properties of the interface.  The first of these is that unrelated
Jesse Keating 7a3296
+    tracing engines should not interfere with each other.  If your engine's
Jesse Keating 7a3296
+    event callback does not return quickly, then another engine won't get
Jesse Keating 7a3296
+    the event notification in a timely manner.  The second important
Jesse Keating 7a3296
+    property is that tracing should be as noninvasive as possible to the
Jesse Keating 7a3296
+    normal operation of the system overall and of the traced thread in
Jesse Keating 7a3296
+    particular.  That is, attached tracing engines should not perturb a
Jesse Keating 7a3296
+    thread's behavior, except to the extent that changing its user-visible
Jesse Keating 7a3296
+    state is explicitly what you want to do.  (Obviously some perturbation
Jesse Keating 7a3296
+    is unavoidable, primarily timing changes, ranging from small delays due
Jesse Keating 7a3296
+    to the overhead of tracing, to arbitrary pauses in user code execution
Jesse Keating 7a3296
+    when a user stops a thread with a debugger for examination.)  Even when
Jesse Keating 7a3296
+    you explicitly want the perturbation of making the traced thread block,
Jesse Keating 7a3296
+    just blocking directly in your callback has more unwanted effects.  For
Jesse Keating 7a3296
+    example, the <constant>CLONE</constant> event callbacks are called when
Jesse Keating 7a3296
+    the new child thread has been created but not yet started running; the
Jesse Keating 7a3296
+    child can never be scheduled until the <constant>CLONE</constant>
Jesse Keating 7a3296
+    tracing callbacks return.  (This allows engines tracing the parent to
Jesse Keating 7a3296
+    attach to the child.)  If a <constant>CLONE</constant> event callback
Jesse Keating 7a3296
+    blocks the parent thread, it also prevents the child thread from
Jesse Keating 7a3296
+    running (even to process a <constant>SIGKILL</constant>).  If what you
Jesse Keating 7a3296
+    want is to make both the parent and child block, then use
Jesse Keating 7a3296
+    <function>utrace_attach_task</function> on the child and then use
Jesse Keating 7a3296
+    <constant>UTRACE_STOP</constant> on both threads.  A more crucial
Jesse Keating 7a3296
+    problem with blocking in callbacks is that it can prevent
Jesse Keating 7a3296
+    <constant>SIGKILL</constant> from working.  A thread that is blocking
Jesse Keating 7a3296
+    due to <constant>UTRACE_STOP</constant> will still wake up and die
Jesse Keating 7a3296
+    immediately when sent a <constant>SIGKILL</constant>, as all threads
Jesse Keating 7a3296
+    should.  Relying on the <application>utrace</application>
Jesse Keating 7a3296
+    infrastructure rather than on private synchronization calls in event
Jesse Keating 7a3296
+    callbacks is an important way to help keep tracing robustly
Jesse Keating 7a3296
+    noninvasive.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="UTRACE_STOP"><title>Using <constant>UTRACE_STOP</constant></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    To control another thread and access its state, it must be stopped
Jesse Keating 7a3296
+    with <constant>UTRACE_STOP</constant>.  This means that it is
Jesse Keating 7a3296
+    stopped and won't start running again while we access it.  When a
Jesse Keating 7a3296
+    thread is not already stopped, <function>utrace_control</function>
Jesse Keating 7a3296
+    returns <constant>-EINPROGRESS</constant> and an engine must wait
Jesse Keating 7a3296
+    for an event callback when the thread is ready to stop.  The thread
Jesse Keating 7a3296
+    may be running on another CPU or may be blocked.  When it is ready
Jesse Keating 7a3296
+    to be examined, it will make callbacks to engines that set the
Jesse Keating 7a3296
+    <constant>UTRACE_EVENT(QUIESCE)</constant> event bit.  To wake up an
Jesse Keating 7a3296
+    interruptible wait, use <constant>UTRACE_INTERRUPT</constant>.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    As long as some engine has used <constant>UTRACE_STOP</constant> and
Jesse Keating 7a3296
+    not called <function>utrace_control</function> to resume the thread,
Jesse Keating 7a3296
+    then the thread will remain stopped.  <constant>SIGKILL</constant>
Jesse Keating 7a3296
+    will wake it up, but it will not run user code.  When the stop is
Jesse Keating 7a3296
+    cleared with <function>utrace_control</function> or a callback
Jesse Keating 7a3296
+    return value, the thread starts running again.
Jesse Keating 7a3296
+    (See also <xref linkend="teardown"/>.)
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  </sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect1 id="teardown"><title>Tear-down Races</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="SIGKILL"><title>Primacy of <constant>SIGKILL</constant></title>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Ordinarily synchronization issues for tracing engines are kept fairly
Jesse Keating 7a3296
+    straightforward by using <constant>UTRACE_STOP</constant>.  You ask a
Jesse Keating 7a3296
+    thread to stop, and then once it makes the
Jesse Keating 7a3296
+    <function>report_quiesce</function> callback it cannot do anything else
Jesse Keating 7a3296
+    that would result in another callback, until you let it with a
Jesse Keating 7a3296
+    <function>utrace_control</function> call.  This simple arrangement
Jesse Keating 7a3296
+    avoids complex and error-prone code in each one of a tracing engine's
Jesse Keating 7a3296
+    event callbacks to keep them serialized with the engine's other
Jesse Keating 7a3296
+    operations done on that thread from another thread of control.
Jesse Keating 7a3296
+    However, giving tracing engines complete power to keep a traced thread
Jesse Keating 7a3296
+    stuck in place runs afoul of a more important kind of simplicity that
Jesse Keating 7a3296
+    the kernel overall guarantees: nothing can prevent or delay
Jesse Keating 7a3296
+    <constant>SIGKILL</constant> from making a thread die and release its
Jesse Keating 7a3296
+    resources.  To preserve this important property of
Jesse Keating 7a3296
+    <constant>SIGKILL</constant>, it as a special case can break
Jesse Keating 7a3296
+    <constant>UTRACE_STOP</constant> like nothing else normally can.  This
Jesse Keating 7a3296
+    includes both explicit <constant>SIGKILL</constant> signals and the
Jesse Keating 7a3296
+    implicit <constant>SIGKILL</constant> sent to each other thread in the
Jesse Keating 7a3296
+    same thread group by a thread doing an exec, or processing a fatal
Jesse Keating 7a3296
+    signal, or making an <function>exit_group</function> system call.  A
Jesse Keating 7a3296
+    tracing engine can prevent a thread from beginning the exit or exec or
Jesse Keating 7a3296
+    dying by signal (other than <constant>SIGKILL</constant>) if it is
Jesse Keating 7a3296
+    attached to that thread, but once the operation begins, no tracing
Jesse Keating 7a3296
+    engine can prevent or delay all other threads in the same thread group
Jesse Keating 7a3296
+    dying.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="reap"><title>Final callbacks</title>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    The <function>report_reap</function> callback is always the final event
Jesse Keating 7a3296
+    in the life cycle of a traced thread.  Tracing engines can use this as
Jesse Keating 7a3296
+    the trigger to clean up their own data structures.  The
Jesse Keating 7a3296
+    <function>report_death</function> callback is always the penultimate
Jesse Keating 7a3296
+    event a tracing engine might see; it's seen unless the thread was
Jesse Keating 7a3296
+    already in the midst of dying when the engine attached.  Many tracing
Jesse Keating 7a3296
+    engines will have no interest in when a parent reaps a dead process,
Jesse Keating 7a3296
+    and nothing they want to do with a zombie thread once it dies; for
Jesse Keating 7a3296
+    them, the <function>report_death</function> callback is the natural
Jesse Keating 7a3296
+    place to clean up data structures and detach.  To facilitate writing
Jesse Keating 7a3296
+    such engines robustly, given the asynchrony of
Jesse Keating 7a3296
+    <constant>SIGKILL</constant>, and without error-prone manual
Jesse Keating 7a3296
+    implementation of synchronization schemes, the
Jesse Keating 7a3296
+    <application>utrace</application> infrastructure provides some special
Jesse Keating 7a3296
+    guarantees about the <function>report_death</function> and
Jesse Keating 7a3296
+    <function>report_reap</function> callbacks.  It still takes some care
Jesse Keating 7a3296
+    to be sure your tracing engine is robust to tear-down races, but these
Jesse Keating 7a3296
+    rules make it reasonably straightforward and concise to handle a lot of
Jesse Keating 7a3296
+    corner cases correctly.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="refcount"><title>Engine and task pointers</title>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    The first sort of guarantee concerns the core data structures
Jesse Keating 7a3296
+    themselves.  <structname>struct utrace_engine</structname> is
Jesse Keating 7a3296
+    a reference-counted data structure.  While you hold a reference, an
Jesse Keating 7a3296
+    engine pointer will always stay valid so that you can safely pass it to
Jesse Keating 7a3296
+    any <application>utrace</application> call.  Each call to
Jesse Keating 7a3296
+    <function>utrace_attach_task</function> or
Jesse Keating 7a3296
+    <function>utrace_attach_pid</function> returns an engine pointer with a
Jesse Keating 7a3296
+    reference belonging to the caller.  You own that reference until you
Jesse Keating 7a3296
+    drop it using <function>utrace_engine_put</function>.  There is an
Jesse Keating 7a3296
+    implicit reference on the engine while it is attached.  So if you drop
Jesse Keating 7a3296
+    your only reference, and then use
Jesse Keating 7a3296
+    <function>utrace_attach_task</function> without
Jesse Keating 7a3296
+    <constant>UTRACE_ATTACH_CREATE</constant> to look up that same engine,
Jesse Keating 7a3296
+    you will get the same pointer with a new reference to replace the one
Jesse Keating 7a3296
+    you dropped, just like calling <function>utrace_engine_get</function>.
Jesse Keating 7a3296
+    When an engine has been detached, either explicitly with
Jesse Keating 7a3296
+    <constant>UTRACE_DETACH</constant> or implicitly after
Jesse Keating 7a3296
+    <function>report_reap</function>, then any references you hold are all
Jesse Keating 7a3296
+    that keep the old engine pointer alive.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    There is nothing a kernel module can do to keep a <structname>struct
Jesse Keating 7a3296
+    task_struct</structname> alive outside of
Jesse Keating 7a3296
+    <function>rcu_read_lock</function>.  When the task dies and is reaped
Jesse Keating 7a3296
+    by its parent (or itself), that structure can be freed so that any
Jesse Keating 7a3296
+    dangling pointers you have stored become invalid.
Jesse Keating 7a3296
+    <application>utrace</application> will not prevent this, but it can
Jesse Keating 7a3296
+    help you detect it safely.  By definition, a task that has been reaped
Jesse Keating 7a3296
+    has had all its engines detached.  All
Jesse Keating 7a3296
+    <application>utrace</application> calls can be safely called on a
Jesse Keating 7a3296
+    detached engine if the caller holds a reference on that engine pointer,
Jesse Keating 7a3296
+    even if the task pointer passed in the call is invalid.  All calls
Jesse Keating 7a3296
+    return <constant>-ESRCH</constant> for a detached engine, which tells
Jesse Keating 7a3296
+    you that the task pointer you passed could be invalid now.  Since
Jesse Keating 7a3296
+    <function>utrace_control</function> and
Jesse Keating 7a3296
+    <function>utrace_set_events</function> do not block, you can call those
Jesse Keating 7a3296
+    inside a <function>rcu_read_lock</function> section and be sure after
Jesse Keating 7a3296
+    they don't return <constant>-ESRCH</constant> that the task pointer is
Jesse Keating 7a3296
+    still valid until <function>rcu_read_unlock</function>.  The
Jesse Keating 7a3296
+    infrastructure never holds task references of its own.  Though neither
Jesse Keating 7a3296
+    <function>rcu_read_lock</function> nor any other lock is held while
Jesse Keating 7a3296
+    making a callback, it's always guaranteed that the <structname>struct
Jesse Keating 7a3296
+    task_struct</structname> and the <structname>struct
Jesse Keating 7a3296
+    utrace_engine</structname> passed as arguments remain valid
Jesse Keating 7a3296
+    until the callback function returns.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    The common means for safely holding task pointers that is available to
Jesse Keating 7a3296
+    kernel modules is to use <structname>struct pid</structname>, which
Jesse Keating 7a3296
+    permits <function>put_pid</function> from kernel modules.  When using
Jesse Keating 7a3296
+    that, the calls <function>utrace_attach_pid</function>,
Jesse Keating 7a3296
+    <function>utrace_control_pid</function>,
Jesse Keating 7a3296
+    <function>utrace_set_events_pid</function>, and
Jesse Keating 7a3296
+    <function>utrace_barrier_pid</function> are available.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="reap-after-death">
Jesse Keating 7a3296
+    <title>
Jesse Keating 7a3296
+      Serialization of <constant>DEATH</constant> and <constant>REAP</constant>
Jesse Keating 7a3296
+    </title>
Jesse Keating 7a3296
+    <para>
Jesse Keating 7a3296
+      The second guarantee is the serialization of
Jesse Keating 7a3296
+      <constant>DEATH</constant> and <constant>REAP</constant> event
Jesse Keating 7a3296
+      callbacks for a given thread.  The actual reaping by the parent
Jesse Keating 7a3296
+      (<function>release_task</function> call) can occur simultaneously
Jesse Keating 7a3296
+      while the thread is still doing the final steps of dying, including
Jesse Keating 7a3296
+      the <function>report_death</function> callback.  If a tracing engine
Jesse Keating 7a3296
+      has requested both <constant>DEATH</constant> and
Jesse Keating 7a3296
+      <constant>REAP</constant> event reports, it's guaranteed that the
Jesse Keating 7a3296
+      <function>report_reap</function> callback will not be made until
Jesse Keating 7a3296
+      after the <function>report_death</function> callback has returned.
Jesse Keating 7a3296
+      If the <function>report_death</function> callback itself detaches
Jesse Keating 7a3296
+      from the thread, then the <function>report_reap</function> callback
Jesse Keating 7a3296
+      will never be made.  Thus it is safe for a
Jesse Keating 7a3296
+      <function>report_death</function> callback to clean up data
Jesse Keating 7a3296
+      structures and detach.
Jesse Keating 7a3296
+    </para>
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="interlock"><title>Interlock with final callbacks</title>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    The final sort of guarantee is that a tracing engine will know for sure
Jesse Keating 7a3296
+    whether or not the <function>report_death</function> and/or
Jesse Keating 7a3296
+    <function>report_reap</function> callbacks will be made for a certain
Jesse Keating 7a3296
+    thread.  These tear-down races are disambiguated by the error return
Jesse Keating 7a3296
+    values of <function>utrace_set_events</function> and
Jesse Keating 7a3296
+    <function>utrace_control</function>.  Normally
Jesse Keating 7a3296
+    <function>utrace_control</function> called with
Jesse Keating 7a3296
+    <constant>UTRACE_DETACH</constant> returns zero, and this means that no
Jesse Keating 7a3296
+    more callbacks will be made.  If the thread is in the midst of dying,
Jesse Keating 7a3296
+    it returns <constant>-EALREADY</constant> to indicate that the
Jesse Keating 7a3296
+    <constant>report_death</constant> callback may already be in progress;
Jesse Keating 7a3296
+    when you get this error, you know that any cleanup your
Jesse Keating 7a3296
+    <function>report_death</function> callback does is about to happen or
Jesse Keating 7a3296
+    has just happened--note that if the <function>report_death</function>
Jesse Keating 7a3296
+    callback does not detach, the engine remains attached until the thread
Jesse Keating 7a3296
+    gets reaped.  If the thread is in the midst of being reaped,
Jesse Keating 7a3296
+    <function>utrace_control</function> returns <constant>-ESRCH</constant>
Jesse Keating 7a3296
+    to indicate that the <function>report_reap</function> callback may
Jesse Keating 7a3296
+    already be in progress; this means the engine is implicitly detached
Jesse Keating 7a3296
+    when the callback completes.  This makes it possible for a tracing
Jesse Keating 7a3296
+    engine that has decided asynchronously to detach from a thread to
Jesse Keating 7a3296
+    safely clean up its data structures, knowing that no
Jesse Keating 7a3296
+    <function>report_death</function> or <function>report_reap</function>
Jesse Keating 7a3296
+    callback will try to do the same.  <constant>utrace_detach</constant>
Jesse Keating 7a3296
+    returns <constant>-ESRCH</constant> when the <structname>struct
Jesse Keating 7a3296
+    utrace_engine</structname> has already been detached, but is
Jesse Keating 7a3296
+    still a valid pointer because of its reference count.  A tracing engine
Jesse Keating 7a3296
+    can use this to safely synchronize its own independent multiple threads
Jesse Keating 7a3296
+    of control with each other and with its event callbacks that detach.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    In the same vein, <function>utrace_set_events</function> normally
Jesse Keating 7a3296
+    returns zero; if the target thread was stopped before the call, then
Jesse Keating 7a3296
+    after a successful call, no event callbacks not requested in the new
Jesse Keating 7a3296
+    flags will be made.  It fails with <constant>-EALREADY</constant> if
Jesse Keating 7a3296
+    you try to clear <constant>UTRACE_EVENT(DEATH)</constant> when the
Jesse Keating 7a3296
+    <function>report_death</function> callback may already have begun, if
Jesse Keating 7a3296
+    you try to clear <constant>UTRACE_EVENT(REAP)</constant> when the
Jesse Keating 7a3296
+    <function>report_reap</function> callback may already have begun, or if
Jesse Keating 7a3296
+    you try to newly set <constant>UTRACE_EVENT(DEATH)</constant> or
Jesse Keating 7a3296
+    <constant>UTRACE_EVENT(QUIESCE)</constant> when the target is already
Jesse Keating 7a3296
+    dead or dying.  Like <function>utrace_control</function>, it returns
Jesse Keating 7a3296
+    <constant>-ESRCH</constant> when the thread has already been detached
Jesse Keating 7a3296
+    (including forcible detach on reaping).  This lets the tracing engine
Jesse Keating 7a3296
+    know for sure which event callbacks it will or won't see after
Jesse Keating 7a3296
+    <function>utrace_set_events</function> has returned.  By checking for
Jesse Keating 7a3296
+    errors, it can know whether to clean up its data structures immediately
Jesse Keating 7a3296
+    or to let its callbacks do the work.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <sect2 id="barrier"><title>Using <function>utrace_barrier</function></title>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    When a thread is safely stopped, calling
Jesse Keating 7a3296
+    <function>utrace_control</function> with <constant>UTRACE_DETACH</constant>
Jesse Keating 7a3296
+    or calling <function>utrace_set_events</function> to disable some events
Jesse Keating 7a3296
+    ensures synchronously that your engine won't get any more of the callbacks
Jesse Keating 7a3296
+    that have been disabled (none at all when detaching).  But these can also
Jesse Keating 7a3296
+    be used while the thread is not stopped, when it might be simultaneously
Jesse Keating 7a3296
+    making a callback to your engine.  For this situation, these calls return
Jesse Keating 7a3296
+    <constant>-EINPROGRESS</constant> when it's possible a callback is in
Jesse Keating 7a3296
+    progress.  If you are not prepared to have your old callbacks still run,
Jesse Keating 7a3296
+    then you can synchronize to be sure all the old callbacks are finished,
Jesse Keating 7a3296
+    using <function>utrace_barrier</function>.  This is necessary if the
Jesse Keating 7a3296
+    kernel module containing your callback code is going to be unloaded.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    After using <constant>UTRACE_DETACH</constant> once, further calls to
Jesse Keating 7a3296
+    <function>utrace_control</function> with the same engine pointer will
Jesse Keating 7a3296
+    return <constant>-ESRCH</constant>.  In contrast, after getting
Jesse Keating 7a3296
+    <constant>-EINPROGRESS</constant> from
Jesse Keating 7a3296
+    <function>utrace_set_events</function>, you can call
Jesse Keating 7a3296
+    <function>utrace_set_events</function> again later and if it returns zero
Jesse Keating 7a3296
+    then know the old callbacks have finished.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    Unlike all other calls, <function>utrace_barrier</function> (and
Jesse Keating 7a3296
+    <function>utrace_barrier_pid</function>) will accept any engine pointer you
Jesse Keating 7a3296
+    hold a reference on, even if <constant>UTRACE_DETACH</constant> has already
Jesse Keating 7a3296
+    been used.  After any <function>utrace_control</function> or
Jesse Keating 7a3296
+    <function>utrace_set_events</function> call (these do not block), you can
Jesse Keating 7a3296
+    call <function>utrace_barrier</function> to block until callbacks have
Jesse Keating 7a3296
+    finished.  This returns <constant>-ESRCH</constant> only if the engine is
Jesse Keating 7a3296
+    completely detached (finished all callbacks).  Otherwise it waits
Jesse Keating 7a3296
+    until the thread is definitely not in the midst of a callback to this
Jesse Keating 7a3296
+    engine and then returns zero, but can return
Jesse Keating 7a3296
+    <constant>-ERESTARTSYS</constant> if its wait is interrupted.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+  </sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</chapter>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<chapter id="core"><title>utrace core API</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  The utrace API is declared in <filename><linux/utrace.h></filename>.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+!Iinclude/linux/utrace.h
Jesse Keating 7a3296
+!Ekernel/utrace.c
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</chapter>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<chapter id="machine"><title>Machine State</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  The <function>task_current_syscall</function> function can be used on any
Jesse Keating 7a3296
+  valid <structname>struct task_struct</structname> at any time, and does
Jesse Keating 7a3296
+  not even require that <function>utrace_attach_task</function> was used at all.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  The other ways to access the registers and other machine-dependent state of
Jesse Keating 7a3296
+  a task can only be used on a task that is at a known safe point.  The safe
Jesse Keating 7a3296
+  points are all the places where <function>utrace_set_events</function> can
Jesse Keating 7a3296
+  request callbacks (except for the <constant>DEATH</constant> and
Jesse Keating 7a3296
+  <constant>REAP</constant> events).  So at any event callback, it is safe to
Jesse Keating 7a3296
+  examine <varname>current</varname>.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  One task can examine another only after a callback in the target task that
Jesse Keating 7a3296
+  returns <constant>UTRACE_STOP</constant> so that task will not return to user
Jesse Keating 7a3296
+  mode after the safe point.  This guarantees that the task will not resume
Jesse Keating 7a3296
+  until the same engine uses <function>utrace_control</function>, unless the
Jesse Keating 7a3296
+  task dies suddenly.  To examine safely, one must use a pair of calls to
Jesse Keating 7a3296
+  <function>utrace_prepare_examine</function> and
Jesse Keating 7a3296
+  <function>utrace_finish_examine</function> surrounding the calls to
Jesse Keating 7a3296
+  <structname>struct user_regset</structname> functions or direct examination
Jesse Keating 7a3296
+  of task data structures.  <function>utrace_prepare_examine</function> returns
Jesse Keating 7a3296
+  an error if the task is not properly stopped, or is dead.  After a
Jesse Keating 7a3296
+  successful examination, the paired <function>utrace_finish_examine</function>
Jesse Keating 7a3296
+  call returns an error if the task ever woke up during the examination.  If
Jesse Keating 7a3296
+  so, any data gathered may be scrambled and should be discarded.  This means
Jesse Keating 7a3296
+  there was a spurious wake-up (which should not happen), or a sudden death.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect1 id="regset"><title><structname>struct user_regset</structname></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  The <structname>struct user_regset</structname> API
Jesse Keating 7a3296
+  is declared in <filename><linux/regset.h></filename>.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+!Finclude/linux/regset.h
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect1 id="task_current_syscall">
Jesse Keating 7a3296
+  <title><filename>System Call Information</filename></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  This function is declared in <filename><linux/ptrace.h></filename>.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+!Elib/syscall.c
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect1 id="syscall"><title><filename>System Call Tracing</filename></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  The arch API for system call information is declared in
Jesse Keating 7a3296
+  <filename><asm/syscall.h></filename>.
Jesse Keating 7a3296
+  Each of these calls can be used only at system call entry tracing,
Jesse Keating 7a3296
+  or can be used only at system call exit and the subsequent safe points
Jesse Keating 7a3296
+  before returning to user mode.
Jesse Keating 7a3296
+  At system call entry tracing means either during a
Jesse Keating 7a3296
+  <structfield>report_syscall_entry</structfield> callback,
Jesse Keating 7a3296
+  or any time after that callback has returned <constant>UTRACE_STOP</constant>.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+!Finclude/asm-generic/syscall.h
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</chapter>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<chapter id="internals"><title>Kernel Internals</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  This chapter covers the interface to the tracing infrastructure
Jesse Keating 7a3296
+  from the core of the kernel and the architecture-specific code.
Jesse Keating 7a3296
+  This is for maintainers of the kernel and arch code, and not relevant
Jesse Keating 7a3296
+  to using the tracing facilities described in preceding chapters.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect1 id="tracehook"><title>Core Calls In</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  These calls are declared in <filename><linux/tracehook.h></filename>.
Jesse Keating 7a3296
+  The core kernel calls these functions at various important places.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+!Finclude/linux/tracehook.h
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect1 id="arch"><title>Architecture Calls Out</title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  An arch that has done all these things sets
Jesse Keating 7a3296
+  <constant>CONFIG_HAVE_ARCH_TRACEHOOK</constant>.
Jesse Keating 7a3296
+  This is required to enable the <application>utrace</application> code.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect2 id="arch-ptrace"><title><filename><asm/ptrace.h></filename></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<para>
Jesse Keating 7a3296
+  An arch defines these in <filename><asm/ptrace.h></filename>
Jesse Keating 7a3296
+  if it supports hardware single-step or block-step features.
Jesse Keating 7a3296
+</para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step
Jesse Keating 7a3296
+!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step
Jesse Keating 7a3296
+!Finclude/linux/ptrace.h user_disable_single_step
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect2 id="arch-syscall">
Jesse Keating 7a3296
+  <title><filename><asm/syscall.h></filename></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    An arch provides <filename><asm/syscall.h></filename> that
Jesse Keating 7a3296
+    defines these as inlines, or declares them as exported functions.
Jesse Keating 7a3296
+    These interfaces are described in <xref linkend="syscall"/>.
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+<sect2 id="arch-tracehook">
Jesse Keating 7a3296
+  <title><filename><linux/tracehook.h></filename></title>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  <para>
Jesse Keating 7a3296
+    An arch must define <constant>TIF_NOTIFY_RESUME</constant>
Jesse Keating 7a3296
+    and <constant>TIF_SYSCALL_TRACE</constant>
Jesse Keating 7a3296
+    in its <filename><asm/thread_info.h></filename>.
Jesse Keating 7a3296
+    The arch code must call the following functions, all declared
Jesse Keating 7a3296
+    in <filename><linux/tracehook.h></filename> and
Jesse Keating 7a3296
+    described in <xref linkend="tracehook"/>:
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+    <itemizedlist>
Jesse Keating 7a3296
+      <listitem>
Jesse Keating 7a3296
+	<para><function>tracehook_notify_resume</function></para>
Jesse Keating 7a3296
+      </listitem>
Jesse Keating 7a3296
+      <listitem>
Jesse Keating 7a3296
+	<para><function>tracehook_report_syscall_entry</function></para>
Jesse Keating 7a3296
+      </listitem>
Jesse Keating 7a3296
+      <listitem>
Jesse Keating 7a3296
+	<para><function>tracehook_report_syscall_exit</function></para>
Jesse Keating 7a3296
+      </listitem>
Jesse Keating 7a3296
+      <listitem>
Jesse Keating 7a3296
+	<para><function>tracehook_signal_handler</function></para>
Jesse Keating 7a3296
+      </listitem>
Jesse Keating 7a3296
+    </itemizedlist>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+  </para>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect2>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</sect1>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</chapter>
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+</book>
Jesse Keating 7a3296
diff --git a/fs/proc/array.c b/fs/proc/array.c
Jesse Keating 7a3296
index 9b58d38..c7c7881 100644
Jesse Keating 7a3296
--- a/fs/proc/array.c
Jesse Keating 7a3296
+++ b/fs/proc/array.c
Jesse Keating 7a3296
@@ -81,6 +81,7 @@
Jesse Keating 7a3296
 #include <linux pid_namespace.h="">
Jesse Keating 7a3296
 #include <linux ptrace.h="">
Jesse Keating 7a3296
 #include <linux tracehook.h="">
Jesse Keating 7a3296
+#include <linux utrace.h="">
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 #include <asm pgtable.h="">
Jesse Keating 7a3296
 #include <asm processor.h="">
Jesse Keating 7a3296
@@ -192,6 +193,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
Jesse Keating 7a3296
 		cred->uid, cred->euid, cred->suid, cred->fsuid,
Jesse Keating 7a3296
 		cred->gid, cred->egid, cred->sgid, cred->fsgid);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+	task_utrace_proc_status(m, p);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	task_lock(p);
Jesse Keating 7a3296
 	if (p->files)
Jesse Keating 7a3296
 		fdt = files_fdtable(p->files);
Jesse Keating 7a3296
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
Jesse Keating 7a3296
index 4272521..235c1b0 100644
Jesse Keating 7a3296
--- a/include/linux/ptrace.h
Jesse Keating 7a3296
+++ b/include/linux/ptrace.h
Jesse Keating 7a3296
@@ -99,12 +99,13 @@
Jesse Keating 7a3296
 #include <linux compiler.h="">		/* For unlikely.  */
Jesse Keating 7a3296
 #include <linux sched.h="">		/* For struct task_struct.  */
Jesse Keating 7a3296
 
Jesse Keating 7a3296
-
Jesse Keating 7a3296
+extern void ptrace_notify_stop(struct task_struct *tracee);
Jesse Keating 7a3296
 extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
Jesse Keating 7a3296
 extern int ptrace_traceme(void);
Jesse Keating 7a3296
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
Jesse Keating 7a3296
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
Jesse Keating 7a3296
 extern int ptrace_attach(struct task_struct *tsk);
Jesse Keating 7a3296
+extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee);
Jesse Keating 7a3296
 extern int ptrace_detach(struct task_struct *, unsigned int);
Jesse Keating 7a3296
 extern void ptrace_disable(struct task_struct *);
Jesse Keating 7a3296
 extern int ptrace_check_attach(struct task_struct *task, int kill);
Jesse Keating 7a3296
diff --git a/include/linux/sched.h b/include/linux/sched.h
Jesse Keating 7a3296
index f118809..d3fef7a 100644
Jesse Keating 7a3296
--- a/include/linux/sched.h
Jesse Keating 7a3296
+++ b/include/linux/sched.h
Jesse Keating 7a3296
@@ -1348,6 +1348,11 @@ struct task_struct {
Jesse Keating 7a3296
 #endif
Jesse Keating 7a3296
 	seccomp_t seccomp;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+#ifdef CONFIG_UTRACE
Jesse Keating 7a3296
+	struct utrace *utrace;
Jesse Keating 7a3296
+	unsigned long utrace_flags;
Jesse Keating 7a3296
+#endif
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 /* Thread group tracking */
Jesse Keating 7a3296
    	u32 parent_exec_id;
Jesse Keating 7a3296
    	u32 self_exec_id;
Jesse Keating 7a3296
@@ -2033,6 +2038,7 @@ extern int kill_pgrp(struct pid *pid, int sig, int priv);
Jesse Keating 7a3296
 extern int kill_pid(struct pid *pid, int sig, int priv);
Jesse Keating 7a3296
 extern int kill_proc_info(int, struct siginfo *, pid_t);
Jesse Keating 7a3296
 extern int do_notify_parent(struct task_struct *, int);
Jesse Keating 7a3296
+extern void do_notify_parent_cldstop(struct task_struct *, int);
Jesse Keating 7a3296
 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
Jesse Keating 7a3296
 extern void force_sig(int, struct task_struct *);
Jesse Keating 7a3296
 extern int send_sig(int, struct task_struct *, int);
Jesse Keating 7a3296
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
Jesse Keating 7a3296
index 10db010..71fa250 100644
Jesse Keating 7a3296
--- a/include/linux/tracehook.h
Jesse Keating 7a3296
+++ b/include/linux/tracehook.h
Jesse Keating 7a3296
@@ -49,6 +49,7 @@
Jesse Keating 7a3296
 #include <linux sched.h="">
Jesse Keating 7a3296
 #include <linux ptrace.h="">
Jesse Keating 7a3296
 #include <linux security.h="">
Jesse Keating 7a3296
+#include <linux utrace.h="">
Jesse Keating 7a3296
 struct linux_binprm;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
@@ -63,6 +64,8 @@ struct linux_binprm;
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline int tracehook_expect_breakpoints(struct task_struct *task)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE)))
Jesse Keating 7a3296
+		return 1;
Jesse Keating 7a3296
 	return (task_ptrace(task) & PT_PTRACED) != 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -111,6 +114,9 @@ static inline void ptrace_report_syscall(struct pt_regs *regs)
Jesse Keating 7a3296
 static inline __must_check int tracehook_report_syscall_entry(
Jesse Keating 7a3296
 	struct pt_regs *regs)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) &&
Jesse Keating 7a3296
+	    utrace_report_syscall_entry(regs))
Jesse Keating 7a3296
+		return 1;
Jesse Keating 7a3296
 	ptrace_report_syscall(regs);
Jesse Keating 7a3296
 	return 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
@@ -134,7 +140,10 @@ static inline __must_check int tracehook_report_syscall_entry(
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	if (step) {
Jesse Keating 7a3296
+	if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT))
Jesse Keating 7a3296
+		utrace_report_syscall_exit(regs);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (step && (task_ptrace(current) & PT_PTRACED)) {
Jesse Keating 7a3296
 		siginfo_t info;
Jesse Keating 7a3296
 		user_single_step_siginfo(current, regs, &info);
Jesse Keating 7a3296
 		force_sig_info(SIGTRAP, &info, current);
Jesse Keating 7a3296
@@ -156,7 +165,7 @@ static inline int tracehook_unsafe_exec(struct task_struct *task)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	int unsafe = 0;
Jesse Keating 7a3296
 	int ptrace = task_ptrace(task);
Jesse Keating 7a3296
-	if (ptrace & PT_PTRACED) {
Jesse Keating 7a3296
+	if (ptrace) {
Jesse Keating 7a3296
 		if (ptrace & PT_PTRACE_CAP)
Jesse Keating 7a3296
 			unsafe |= LSM_UNSAFE_PTRACE_CAP;
Jesse Keating 7a3296
 		else
Jesse Keating 7a3296
@@ -178,7 +187,7 @@ static inline int tracehook_unsafe_exec(struct task_struct *task)
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	if (task_ptrace(tsk) & PT_PTRACED)
Jesse Keating 7a3296
+	if (task_ptrace(tsk))
Jesse Keating 7a3296
 		return rcu_dereference(tsk->parent);
Jesse Keating 7a3296
 	return NULL;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
@@ -201,6 +210,8 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt,
Jesse Keating 7a3296
 					 struct linux_binprm *bprm,
Jesse Keating 7a3296
 					 struct pt_regs *regs)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC)))
Jesse Keating 7a3296
+		utrace_report_exec(fmt, bprm, regs);
Jesse Keating 7a3296
 	if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) &&
Jesse Keating 7a3296
 	    unlikely(task_ptrace(current) & PT_PTRACED))
Jesse Keating 7a3296
 		send_sig(SIGTRAP, current, 0);
Jesse Keating 7a3296
@@ -218,10 +229,37 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt,
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline void tracehook_report_exit(long *exit_code)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT)))
Jesse Keating 7a3296
+		utrace_report_exit(exit_code);
Jesse Keating 7a3296
 	ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
+ * tracehook_init_task - task_struct has just been copied
Jesse Keating 7a3296
+ * @task:		new &struct task_struct just copied from parent
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Called from do_fork() when @task has just been duplicated.
Jesse Keating 7a3296
+ * After this, @task will be passed to tracehook_free_task()
Jesse Keating 7a3296
+ * even if the rest of its setup fails before it is fully created.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline void tracehook_init_task(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	utrace_init_task(task);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * tracehook_free_task - task_struct is being freed
Jesse Keating 7a3296
+ * @task:		dead &struct task_struct being freed
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Called from free_task() when @task is no longer in use.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline void tracehook_free_task(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	if (task_utrace_struct(task))
Jesse Keating 7a3296
+		utrace_free_task(task);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
  * tracehook_prepare_clone - prepare for new child to be cloned
Jesse Keating 7a3296
  * @clone_flags:	%CLONE_* flags from clone/fork/vfork system call
Jesse Keating 7a3296
  *
Jesse Keating 7a3296
@@ -285,6 +323,8 @@ static inline void tracehook_report_clone(struct pt_regs *regs,
Jesse Keating 7a3296
 					  unsigned long clone_flags,
Jesse Keating 7a3296
 					  pid_t pid, struct task_struct *child)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)))
Jesse Keating 7a3296
+		utrace_report_clone(clone_flags, child);
Jesse Keating 7a3296
 	if (unlikely(task_ptrace(child))) {
Jesse Keating 7a3296
 		/*
Jesse Keating 7a3296
 		 * It doesn't matter who attached/attaching to this
Jesse Keating 7a3296
@@ -317,6 +357,9 @@ static inline void tracehook_report_clone_complete(int trace,
Jesse Keating 7a3296
 						   pid_t pid,
Jesse Keating 7a3296
 						   struct task_struct *child)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) &&
Jesse Keating 7a3296
+	    (clone_flags & CLONE_VFORK))
Jesse Keating 7a3296
+		utrace_finish_vfork(current);
Jesse Keating 7a3296
 	if (unlikely(trace))
Jesse Keating 7a3296
 		ptrace_event(0, trace, pid);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
@@ -351,6 +394,10 @@ static inline void tracehook_report_vfork_done(struct task_struct *child,
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline void tracehook_prepare_release_task(struct task_struct *task)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	/* see utrace_add_engine() about this barrier */
Jesse Keating 7a3296
+	smp_mb();
Jesse Keating 7a3296
+	if (task_utrace_flags(task))
Jesse Keating 7a3296
+		utrace_maybe_reap(task, task_utrace_struct(task), true);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
@@ -365,6 +412,7 @@ static inline void tracehook_prepare_release_task(struct task_struct *task)
Jesse Keating 7a3296
 static inline void tracehook_finish_release_task(struct task_struct *task)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
 	ptrace_release_task(task);
Jesse Keating 7a3296
+	BUG_ON(task->exit_state != EXIT_DEAD);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
@@ -386,7 +434,9 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info,
Jesse Keating 7a3296
 					    const struct k_sigaction *ka,
Jesse Keating 7a3296
 					    struct pt_regs *regs, int stepping)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	if (stepping)
Jesse Keating 7a3296
+	if (task_utrace_flags(current))
Jesse Keating 7a3296
+		utrace_signal_handler(current, stepping);
Jesse Keating 7a3296
+	if (stepping && (task_ptrace(current) & PT_PTRACED))
Jesse Keating 7a3296
 		ptrace_notify(SIGTRAP);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -403,6 +453,8 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info,
Jesse Keating 7a3296
 static inline int tracehook_consider_ignored_signal(struct task_struct *task,
Jesse Keating 7a3296
 						    int sig)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN)))
Jesse Keating 7a3296
+		return 1;
Jesse Keating 7a3296
 	return (task_ptrace(task) & PT_PTRACED) != 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -422,6 +474,9 @@ static inline int tracehook_consider_ignored_signal(struct task_struct *task,
Jesse Keating 7a3296
 static inline int tracehook_consider_fatal_signal(struct task_struct *task,
Jesse Keating 7a3296
 						  int sig)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) |
Jesse Keating 7a3296
+						UTRACE_EVENT(SIGNAL_CORE))))
Jesse Keating 7a3296
+		return 1;
Jesse Keating 7a3296
 	return (task_ptrace(task) & PT_PTRACED) != 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -436,6 +491,8 @@ static inline int tracehook_consider_fatal_signal(struct task_struct *task,
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline int tracehook_force_sigpending(void)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(current)))
Jesse Keating 7a3296
+		return utrace_interrupt_pending();
Jesse Keating 7a3296
 	return 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -465,6 +522,8 @@ static inline int tracehook_get_signal(struct task_struct *task,
Jesse Keating 7a3296
 				       siginfo_t *info,
Jesse Keating 7a3296
 				       struct k_sigaction *return_ka)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(task)))
Jesse Keating 7a3296
+		return utrace_get_signal(task, regs, info, return_ka);
Jesse Keating 7a3296
 	return 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -492,7 +551,9 @@ static inline int tracehook_get_signal(struct task_struct *task,
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline int tracehook_notify_jctl(int notify, int why)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
-	return notify ?: (current->ptrace & PT_PTRACED) ? why : 0;
Jesse Keating 7a3296
+	if (task_utrace_flags(current) & UTRACE_EVENT(JCTL))
Jesse Keating 7a3296
+		utrace_report_jctl(notify, why);
Jesse Keating 7a3296
+	return notify ?: task_ptrace(current) ? why : 0;
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 /**
Jesse Keating 7a3296
@@ -502,6 +563,8 @@ static inline int tracehook_notify_jctl(int notify, int why)
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline void tracehook_finish_jctl(void)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	if (task_utrace_flags(current))
Jesse Keating 7a3296
+		utrace_finish_stop();
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 #define DEATH_REAP			-1
Jesse Keating 7a3296
@@ -524,6 +587,8 @@ static inline void tracehook_finish_jctl(void)
Jesse Keating 7a3296
 static inline int tracehook_notify_death(struct task_struct *task,
Jesse Keating 7a3296
 					 void **death_cookie, int group_dead)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	*death_cookie = task_utrace_struct(task);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	if (task_detached(task))
Jesse Keating 7a3296
 		return task->ptrace ? SIGCHLD : DEATH_REAP;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
@@ -560,6 +625,15 @@ static inline void tracehook_report_death(struct task_struct *task,
Jesse Keating 7a3296
 					  int signal, void *death_cookie,
Jesse Keating 7a3296
 					  int group_dead)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * If utrace_set_events() was just called to enable
Jesse Keating 7a3296
+	 * UTRACE_EVENT(DEATH), then we are obliged to call
Jesse Keating 7a3296
+	 * utrace_report_death() and not miss it.  utrace_set_events()
Jesse Keating 7a3296
+	 * checks @task->exit_state under tasklist_lock to synchronize
Jesse Keating 7a3296
+	 * with exit_notify(), the caller.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS)
Jesse Keating 7a3296
+		utrace_report_death(task, death_cookie, group_dead, signal);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 #ifdef TIF_NOTIFY_RESUME
Jesse Keating 7a3296
@@ -589,10 +663,21 @@ static inline void set_notify_resume(struct task_struct *task)
Jesse Keating 7a3296
  * asynchronously, this will be called again before we return to
Jesse Keating 7a3296
  * user mode.
Jesse Keating 7a3296
  *
Jesse Keating 7a3296
- * Called without locks.
Jesse Keating 7a3296
+ * Called without locks.  However, on some machines this may be
Jesse Keating 7a3296
+ * called with interrupts disabled.
Jesse Keating 7a3296
  */
Jesse Keating 7a3296
 static inline void tracehook_notify_resume(struct pt_regs *regs)
Jesse Keating 7a3296
 {
Jesse Keating 7a3296
+	struct task_struct *task = current;
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Prevent the following store/load from getting ahead of the
Jesse Keating 7a3296
+	 * caller which clears TIF_NOTIFY_RESUME. This pairs with the
Jesse Keating 7a3296
+	 * implicit mb() before setting TIF_NOTIFY_RESUME in
Jesse Keating 7a3296
+	 * set_notify_resume().
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	smp_mb();
Jesse Keating 7a3296
+	if (task_utrace_flags(task))
Jesse Keating 7a3296
+		utrace_resume(task, regs);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 #endif	/* TIF_NOTIFY_RESUME */
Jesse Keating 7a3296
 
Jesse Keating 7a3296
diff --git a/include/linux/utrace.h b/include/linux/utrace.h
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..f251efe
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/include/linux/utrace.h
Jesse Keating 7a3296
@@ -0,0 +1,692 @@
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * utrace infrastructure interface for debugging user processes
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Copyright (C) 2006-2009 Red Hat, Inc.  All rights reserved.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This copyrighted material is made available to anyone wishing to use,
Jesse Keating 7a3296
+ * modify, copy, or redistribute it subject to the terms and conditions
Jesse Keating 7a3296
+ * of the GNU General Public License v.2.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Red Hat Author: Roland McGrath.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This interface allows for notification of interesting events in a
Jesse Keating 7a3296
+ * thread.  It also mediates access to thread state such as registers.
Jesse Keating 7a3296
+ * Multiple unrelated users can be associated with a single thread.
Jesse Keating 7a3296
+ * We call each of these a tracing engine.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * A tracing engine starts by calling utrace_attach_task() or
Jesse Keating 7a3296
+ * utrace_attach_pid() on the chosen thread, passing in a set of hooks
Jesse Keating 7a3296
+ * (&struct utrace_engine_ops), and some associated data.  This produces a
Jesse Keating 7a3296
+ * &struct utrace_engine, which is the handle used for all other
Jesse Keating 7a3296
+ * operations.  An attached engine has its ops vector, its data, and an
Jesse Keating 7a3296
+ * event mask controlled by utrace_set_events().
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * For each event bit that is set, that engine will get the
Jesse Keating 7a3296
+ * appropriate ops->report_*() callback when the event occurs.  The
Jesse Keating 7a3296
+ * &struct utrace_engine_ops need not provide callbacks for an event
Jesse Keating 7a3296
+ * unless the engine sets one of the associated event bits.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#ifndef _LINUX_UTRACE_H
Jesse Keating 7a3296
+#define _LINUX_UTRACE_H	1
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <linux list.h="">
Jesse Keating 7a3296
+#include <linux kref.h="">
Jesse Keating 7a3296
+#include <linux signal.h="">
Jesse Keating 7a3296
+#include <linux sched.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+struct linux_binprm;
Jesse Keating 7a3296
+struct pt_regs;
Jesse Keating 7a3296
+struct utrace;
Jesse Keating 7a3296
+struct user_regset;
Jesse Keating 7a3296
+struct user_regset_view;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Event bits passed to utrace_set_events().
Jesse Keating 7a3296
+ * These appear in &struct task_struct.@utrace_flags
Jesse Keating 7a3296
+ * and &struct utrace_engine.@flags.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+enum utrace_events {
Jesse Keating 7a3296
+	_UTRACE_EVENT_QUIESCE,	/* Thread is available for examination.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_REAP,  	/* Zombie reaped, no more tracing possible.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_CLONE,	/* Successful clone/fork/vfork just done.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_EXEC,	/* Successful execve just completed.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_EXIT,	/* Thread exit in progress.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_DEATH,	/* Thread has died.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SIGNAL,	/* Signal delivery will run a user handler.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core.  */
Jesse Keating 7a3296
+	_UTRACE_EVENT_JCTL,	/* Job control stop or continue completed.  */
Jesse Keating 7a3296
+	_UTRACE_NEVENTS
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+#define UTRACE_EVENT(type)	(1UL << _UTRACE_EVENT_##type)
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * All the kinds of signal events.
Jesse Keating 7a3296
+ * These all use the @report_signal() callback.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+#define UTRACE_EVENT_SIGNAL_ALL	(UTRACE_EVENT(SIGNAL) \
Jesse Keating 7a3296
+				 | UTRACE_EVENT(SIGNAL_IGN) \
Jesse Keating 7a3296
+				 | UTRACE_EVENT(SIGNAL_STOP) \
Jesse Keating 7a3296
+				 | UTRACE_EVENT(SIGNAL_TERM) \
Jesse Keating 7a3296
+				 | UTRACE_EVENT(SIGNAL_CORE))
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Both kinds of syscall events; these call the @report_syscall_entry()
Jesse Keating 7a3296
+ * and @report_syscall_exit() callbacks, respectively.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+#define UTRACE_EVENT_SYSCALL	\
Jesse Keating 7a3296
+	(UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT))
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * The event reports triggered synchronously by task death.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE))
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Hooks in <linux tracehook.h=""> call these entry points to the utrace dispatch.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+void utrace_free_task(struct task_struct *);
Jesse Keating 7a3296
+bool utrace_interrupt_pending(void);
Jesse Keating 7a3296
+void utrace_resume(struct task_struct *, struct pt_regs *);
Jesse Keating 7a3296
+void utrace_finish_stop(void);
Jesse Keating 7a3296
+void utrace_maybe_reap(struct task_struct *, struct utrace *, bool);
Jesse Keating 7a3296
+int utrace_get_signal(struct task_struct *, struct pt_regs *,
Jesse Keating 7a3296
+		      siginfo_t *, struct k_sigaction *);
Jesse Keating 7a3296
+void utrace_report_clone(unsigned long, struct task_struct *);
Jesse Keating 7a3296
+void utrace_finish_vfork(struct task_struct *);
Jesse Keating 7a3296
+void utrace_report_exit(long *exit_code);
Jesse Keating 7a3296
+void utrace_report_death(struct task_struct *, struct utrace *, bool, int);
Jesse Keating 7a3296
+void utrace_report_jctl(int notify, int type);
Jesse Keating 7a3296
+void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *,
Jesse Keating 7a3296
+			struct pt_regs *regs);
Jesse Keating 7a3296
+bool utrace_report_syscall_entry(struct pt_regs *);
Jesse Keating 7a3296
+void utrace_report_syscall_exit(struct pt_regs *);
Jesse Keating 7a3296
+void utrace_signal_handler(struct task_struct *, int);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#ifndef CONFIG_UTRACE
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * <linux tracehook.h=""> uses these accessors to avoid #ifdef CONFIG_UTRACE.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline unsigned long task_utrace_flags(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+static inline struct utrace *task_utrace_struct(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return NULL;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+static inline void utrace_init_task(struct task_struct *child)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline void task_utrace_proc_status(struct seq_file *m,
Jesse Keating 7a3296
+					   struct task_struct *p)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#else  /* CONFIG_UTRACE */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline unsigned long task_utrace_flags(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return task->utrace_flags;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline struct utrace *task_utrace_struct(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace *utrace;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * This barrier ensures that any prior load of task->utrace_flags
Jesse Keating 7a3296
+	 * is ordered before this load of task->utrace.  We use those
Jesse Keating 7a3296
+	 * utrace_flags checks in the hot path to decide to call into
Jesse Keating 7a3296
+	 * the utrace code.  The first attach installs task->utrace before
Jesse Keating 7a3296
+	 * setting task->utrace_flags nonzero with implicit barrier in
Jesse Keating 7a3296
+	 * between, see utrace_add_engine().
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	smp_rmb();
Jesse Keating 7a3296
+	utrace = task->utrace;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	smp_read_barrier_depends(); /* See utrace_task_alloc().  */
Jesse Keating 7a3296
+	return utrace;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline void utrace_init_task(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	task->utrace_flags = 0;
Jesse Keating 7a3296
+	task->utrace = NULL;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+void task_utrace_proc_status(struct seq_file *m, struct task_struct *p);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Version number of the API defined in this file.  This will change
Jesse Keating 7a3296
+ * whenever a tracing engine's code would need some updates to keep
Jesse Keating 7a3296
+ * working.  We maintain this here for the benefit of tracing engine code
Jesse Keating 7a3296
+ * that is developed concurrently with utrace API improvements before they
Jesse Keating 7a3296
+ * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+#define UTRACE_API_VERSION	20091216
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * enum utrace_resume_action - engine's choice of action for a traced task
Jesse Keating 7a3296
+ * @UTRACE_STOP:		Stay quiescent after callbacks.
Jesse Keating 7a3296
+ * @UTRACE_INTERRUPT:		Make @report_signal() callback soon.
Jesse Keating 7a3296
+ * @UTRACE_REPORT:		Make some callback soon.
Jesse Keating 7a3296
+ * @UTRACE_SINGLESTEP:		Resume in user mode for one instruction.
Jesse Keating 7a3296
+ * @UTRACE_BLOCKSTEP:		Resume in user mode until next branch.
Jesse Keating 7a3296
+ * @UTRACE_RESUME:		Resume normally in user mode.
Jesse Keating 7a3296
+ * @UTRACE_DETACH:		Detach my engine (implies %UTRACE_RESUME).
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * See utrace_control() for detailed descriptions of each action.  This is
Jesse Keating 7a3296
+ * encoded in the @action argument and the return value for every callback
Jesse Keating 7a3296
+ * with a &u32 return value.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * The order of these is important.  When there is more than one engine,
Jesse Keating 7a3296
+ * each supplies its choice and the smallest value prevails.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+enum utrace_resume_action {
Jesse Keating 7a3296
+	UTRACE_STOP,
Jesse Keating 7a3296
+	UTRACE_INTERRUPT,
Jesse Keating 7a3296
+	UTRACE_REPORT,
Jesse Keating 7a3296
+	UTRACE_SINGLESTEP,
Jesse Keating 7a3296
+	UTRACE_BLOCKSTEP,
Jesse Keating 7a3296
+	UTRACE_RESUME,
Jesse Keating 7a3296
+	UTRACE_DETACH,
Jesse Keating 7a3296
+	UTRACE_RESUME_MAX
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+#define UTRACE_RESUME_BITS	(ilog2(UTRACE_RESUME_MAX) + 1)
Jesse Keating 7a3296
+#define UTRACE_RESUME_MASK	((1 << UTRACE_RESUME_BITS) - 1)
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_resume_action - &enum utrace_resume_action from callback action
Jesse Keating 7a3296
+ * @action:		&u32 callback @action argument or return value
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This extracts the &enum utrace_resume_action from @action,
Jesse Keating 7a3296
+ * which is the @action argument to a &struct utrace_engine_ops
Jesse Keating 7a3296
+ * callback or the return value from one.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline enum utrace_resume_action utrace_resume_action(u32 action)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return action & UTRACE_RESUME_MASK;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * enum utrace_signal_action - disposition of signal
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_DELIVER:	Deliver according to sigaction.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_IGN:		Ignore the signal.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_TERM:		Terminate the process.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_CORE:		Terminate with core dump.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_STOP:		Deliver as absolute stop.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_TSTP:		Deliver as job control stop.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_REPORT:	Reporting before pending signals.
Jesse Keating 7a3296
+ * @UTRACE_SIGNAL_HANDLER:	Reporting after signal handler setup.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This is encoded in the @action argument and the return value for
Jesse Keating 7a3296
+ * a @report_signal() callback.  It says what will happen to the
Jesse Keating 7a3296
+ * signal described by the &siginfo_t parameter to the callback.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when
Jesse Keating 7a3296
+ * a tracing report is being made before dequeuing any pending signal.
Jesse Keating 7a3296
+ * If this is immediately after a signal handler has been set up, then
Jesse Keating 7a3296
+ * %UTRACE_SIGNAL_HANDLER is used instead.  A @report_signal callback
Jesse Keating 7a3296
+ * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure
Jesse Keating 7a3296
+ * it sees a %UTRACE_SIGNAL_HANDLER report.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+enum utrace_signal_action {
Jesse Keating 7a3296
+	UTRACE_SIGNAL_DELIVER	= 0x00,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_IGN	= 0x10,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_TERM	= 0x20,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_CORE	= 0x30,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_STOP	= 0x40,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_TSTP	= 0x50,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_REPORT	= 0x60,
Jesse Keating 7a3296
+	UTRACE_SIGNAL_HANDLER	= 0x70
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+#define	UTRACE_SIGNAL_MASK	0xf0
Jesse Keating 7a3296
+#define UTRACE_SIGNAL_HOLD	0x100 /* Flag, push signal back on queue.  */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_signal_action - &enum utrace_signal_action from callback action
Jesse Keating 7a3296
+ * @action:		@report_signal callback @action argument or return value
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This extracts the &enum utrace_signal_action from @action, which
Jesse Keating 7a3296
+ * is the @action argument to a @report_signal callback or the
Jesse Keating 7a3296
+ * return value from one.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline enum utrace_signal_action utrace_signal_action(u32 action)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return action & UTRACE_SIGNAL_MASK;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * enum utrace_syscall_action - disposition of system call attempt
Jesse Keating 7a3296
+ * @UTRACE_SYSCALL_RUN:		Run the system call.
Jesse Keating 7a3296
+ * @UTRACE_SYSCALL_ABORT:	Don't run the system call.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This is encoded in the @action argument and the return value for
Jesse Keating 7a3296
+ * a @report_syscall_entry callback.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+enum utrace_syscall_action {
Jesse Keating 7a3296
+	UTRACE_SYSCALL_RUN	= 0x00,
Jesse Keating 7a3296
+	UTRACE_SYSCALL_ABORT	= 0x10
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+#define	UTRACE_SYSCALL_MASK	0xf0
Jesse Keating 7a3296
+#define	UTRACE_SYSCALL_RESUMED	0x100 /* Flag, report_syscall_entry() repeats */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_syscall_action - &enum utrace_syscall_action from callback action
Jesse Keating 7a3296
+ * @action:		@report_syscall_entry callback @action or return value
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This extracts the &enum utrace_syscall_action from @action, which
Jesse Keating 7a3296
+ * is the @action argument to a @report_syscall_entry callback or the
Jesse Keating 7a3296
+ * return value from one.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline enum utrace_syscall_action utrace_syscall_action(u32 action)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return action & UTRACE_SYSCALL_MASK;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Flags for utrace_attach_task() and utrace_attach_pid().
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+#define UTRACE_ATTACH_MATCH_OPS		0x0001 /* Match engines on ops.  */
Jesse Keating 7a3296
+#define UTRACE_ATTACH_MATCH_DATA	0x0002 /* Match engines on data.  */
Jesse Keating 7a3296
+#define UTRACE_ATTACH_MATCH_MASK	0x000f
Jesse Keating 7a3296
+#define UTRACE_ATTACH_CREATE		0x0010 /* Attach a new engine.  */
Jesse Keating 7a3296
+#define UTRACE_ATTACH_EXCLUSIVE		0x0020 /* Refuse if existing match.  */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * struct utrace_engine - per-engine structure
Jesse Keating 7a3296
+ * @ops:	&struct utrace_engine_ops pointer passed to utrace_attach_task()
Jesse Keating 7a3296
+ * @data:	engine-private &void * passed to utrace_attach_task()
Jesse Keating 7a3296
+ * @flags:	event mask set by utrace_set_events() plus internal flag bits
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * The task itself never has to worry about engines detaching while
Jesse Keating 7a3296
+ * it's doing event callbacks.  These structures are removed from the
Jesse Keating 7a3296
+ * task's active list only when it's stopped, or by the task itself.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * utrace_engine_get() and utrace_engine_put() maintain a reference count.
Jesse Keating 7a3296
+ * When it drops to zero, the structure is freed.  One reference is held
Jesse Keating 7a3296
+ * implicitly while the engine is attached to its task.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+struct utrace_engine {
Jesse Keating 7a3296
+/* private: */
Jesse Keating 7a3296
+	struct kref kref;
Jesse Keating 7a3296
+	void (*release)(void *);
Jesse Keating 7a3296
+	struct list_head entry;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/* public: */
Jesse Keating 7a3296
+	const struct utrace_engine_ops *ops;
Jesse Keating 7a3296
+	void *data;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	unsigned long flags;
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_engine_get - acquire a reference on a &struct utrace_engine
Jesse Keating 7a3296
+ * @engine:	&struct utrace_engine pointer
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * You must hold a reference on @engine, and you get another.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline void utrace_engine_get(struct utrace_engine *engine)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	kref_get(&engine->kref);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+void __utrace_engine_release(struct kref *);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_engine_put - release a reference on a &struct utrace_engine
Jesse Keating 7a3296
+ * @engine:	&struct utrace_engine pointer
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * You must hold a reference on @engine, and you lose that reference.
Jesse Keating 7a3296
+ * If it was the last one, @engine becomes an invalid pointer.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline void utrace_engine_put(struct utrace_engine *engine)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	kref_put(&engine->kref, __utrace_engine_release);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * struct utrace_engine_ops - tracing engine callbacks
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit.
Jesse Keating 7a3296
+ * utrace_set_events() calls on @engine choose which callbacks will
Jesse Keating 7a3296
+ * be made to @engine from @task.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Most callbacks take an @action argument, giving the resume action
Jesse Keating 7a3296
+ * chosen by other tracing engines.  All callbacks take an @engine
Jesse Keating 7a3296
+ * argument.  The @report_reap callback takes a @task argument that
Jesse Keating 7a3296
+ * might or might not be @current.  All other @report_* callbacks
Jesse Keating 7a3296
+ * report an event in the @current task.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * For some calls, @action also includes bits specific to that event
Jesse Keating 7a3296
+ * and utrace_resume_action() is used to extract the resume action.
Jesse Keating 7a3296
+ * This shows what would happen if @engine wasn't there, or will if
Jesse Keating 7a3296
+ * the callback's return value uses %UTRACE_RESUME.  This always
Jesse Keating 7a3296
+ * starts as %UTRACE_RESUME when no other tracing is being done on
Jesse Keating 7a3296
+ * this task.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * All return values contain &enum utrace_resume_action bits.  For
Jesse Keating 7a3296
+ * some calls, other bits specific to that kind of event are added to
Jesse Keating 7a3296
+ * the resume action bits with OR.  These are the same bits used in
Jesse Keating 7a3296
+ * the @action argument.  The resume action returned by a callback
Jesse Keating 7a3296
+ * does not override previous engines' choices, it only says what
Jesse Keating 7a3296
+ * @engine wants done.  What @current actually does is the action that's
Jesse Keating 7a3296
+ * most constrained among the choices made by all attached engines.
Jesse Keating 7a3296
+ * See utrace_control() for more information on the actions.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * When %UTRACE_STOP is used in @report_syscall_entry, then @current
Jesse Keating 7a3296
+ * stops before attempting the system call.  In this case, another
Jesse Keating 7a3296
+ * @report_syscall_entry callback will follow after @current resumes if
Jesse Keating 7a3296
+ * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback
Jesse Keating 7a3296
+ * or passed to utrace_control().  In a second or later callback,
Jesse Keating 7a3296
+ * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate
Jesse Keating 7a3296
+ * a repeat callback still waiting to attempt the same system call
Jesse Keating 7a3296
+ * invocation.  This repeat callback gives each engine an opportunity
Jesse Keating 7a3296
+ * to reexamine registers another engine might have changed while
Jesse Keating 7a3296
+ * @current was held in %UTRACE_STOP.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * In other cases, the resume action does not take effect until @current
Jesse Keating 7a3296
+ * is ready to check for signals and return to user mode.  If there
Jesse Keating 7a3296
+ * are more callbacks to be made, the last round of calls determines
Jesse Keating 7a3296
+ * the final action.  A @report_quiesce callback with @event zero, or
Jesse Keating 7a3296
+ * a @report_signal callback, will always be the last one made before
Jesse Keating 7a3296
+ * @current resumes.  Only %UTRACE_STOP is "sticky"--if @engine returned
Jesse Keating 7a3296
+ * %UTRACE_STOP then @current stays stopped unless @engine returns
Jesse Keating 7a3296
+ * different from a following callback.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * The report_death() and report_reap() callbacks do not take @action
Jesse Keating 7a3296
+ * arguments, and only %UTRACE_DETACH is meaningful in the return value
Jesse Keating 7a3296
+ * from a report_death() callback.  None of the resume actions applies
Jesse Keating 7a3296
+ * to a dead thread.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * All @report_*() hooks are called with no locks held, in a generally
Jesse Keating 7a3296
+ * safe environment when we will be returning to user mode soon (or just
Jesse Keating 7a3296
+ * entered the kernel).  It is fine to block for memory allocation and
Jesse Keating 7a3296
+ * the like, but all hooks are asynchronous and must not block on
Jesse Keating 7a3296
+ * external events!  If you want the thread to block, use %UTRACE_STOP
Jesse Keating 7a3296
+ * in your hook's return value; then later wake it up with utrace_control().
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_quiesce:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%QUIESCE).
Jesse Keating 7a3296
+ *	This does not indicate any event, but just that @current is in a
Jesse Keating 7a3296
+ *	safe place for examination.  This call is made before each specific
Jesse Keating 7a3296
+ *	event callback, except for @report_reap.  The @event argument gives
Jesse Keating 7a3296
+ *	the %UTRACE_EVENT(@which) value for the event occurring.  This
Jesse Keating 7a3296
+ *	callback might be made for events @engine has not requested, if
Jesse Keating 7a3296
+ *	some other engine is tracing the event; calling utrace_set_events()
Jesse Keating 7a3296
+ *	call here can request the immediate callback for this occurrence of
Jesse Keating 7a3296
+ *	@event.  @event is zero when there is no other event, @current is
Jesse Keating 7a3296
+ *	now ready to check for signals and return to user mode, and some
Jesse Keating 7a3296
+ *	engine has used %UTRACE_REPORT or %UTRACE_INTERRUPT to request this
Jesse Keating 7a3296
+ *	callback.  For this case, if @report_signal is not %NULL, the
Jesse Keating 7a3296
+ *	@report_quiesce callback may be replaced with a @report_signal
Jesse Keating 7a3296
+ *	callback passing %UTRACE_SIGNAL_REPORT in its @action argument,
Jesse Keating 7a3296
+ *	whenever @current is entering the signal-check path anyway.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_signal:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE).
Jesse Keating 7a3296
+ *	Use utrace_signal_action() and utrace_resume_action() on @action.
Jesse Keating 7a3296
+ *	The signal action is %UTRACE_SIGNAL_REPORT when some engine has
Jesse Keating 7a3296
+ *	used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose
Jesse Keating 7a3296
+ *	to stop or to deliver an artificial signal, before pending signals.
Jesse Keating 7a3296
+ *	It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just
Jesse Keating 7a3296
+ *	finished (after a previous %UTRACE_SIGNAL_DELIVER return); this
Jesse Keating 7a3296
+ *	serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by
Jesse Keating 7a3296
+ *	%UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly
Jesse Keating 7a3296
+ *	requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the
Jesse Keating 7a3296
+ *	signal delivery.  The other signal actions indicate a signal about
Jesse Keating 7a3296
+ *	to be delivered; the previous engine's return value sets the signal
Jesse Keating 7a3296
+ *	action seen by the the following engine's callback.  The @info data
Jesse Keating 7a3296
+ *	can be changed at will, including @info->si_signo.  The settings in
Jesse Keating 7a3296
+ *	@return_ka determines what %UTRACE_SIGNAL_DELIVER does.  @orig_ka
Jesse Keating 7a3296
+ *	is what was in force before other tracing engines intervened, and
Jesse Keating 7a3296
+ *	it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or
Jesse Keating 7a3296
+ *	%UTRACE_SIGNAL_HANDLER.  For a report without a new signal, @info
Jesse Keating 7a3296
+ *	is left uninitialized and must be set completely by an engine that
Jesse Keating 7a3296
+ *	chooses to deliver a signal; if there was a previous @report_signal
Jesse Keating 7a3296
+ *	callback ending in %UTRACE_STOP and it was just resumed using
Jesse Keating 7a3296
+ *	%UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged
Jesse Keating 7a3296
+ *	from the previous callback.  In this way, the original signal can
Jesse Keating 7a3296
+ *	be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN
Jesse Keating 7a3296
+ *	and then found again when resuming with %UTRACE_INTERRUPT.
Jesse Keating 7a3296
+ *	The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value,
Jesse Keating 7a3296
+ *	and might be in @action if the previous engine returned it.  This
Jesse Keating 7a3296
+ *	flag asks that the signal in @info be pushed back on @current's queue
Jesse Keating 7a3296
+ *	so that it will be seen again after whatever action is taken now.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_clone:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%CLONE).
Jesse Keating 7a3296
+ *	Event reported for parent, before the new task @child might run.
Jesse Keating 7a3296
+ *	@clone_flags gives the flags used in the clone system call, or
Jesse Keating 7a3296
+ *	equivalent flags for a fork() or vfork() system call.  This
Jesse Keating 7a3296
+ *	function can use utrace_attach_task() on @child.  Then passing
Jesse Keating 7a3296
+ *	%UTRACE_STOP to utrace_control() on @child here keeps the child
Jesse Keating 7a3296
+ *	stopped before it ever runs in user mode, %UTRACE_REPORT or
Jesse Keating 7a3296
+ *	%UTRACE_INTERRUPT ensures a callback from @child before it
Jesse Keating 7a3296
+ *	starts in user mode.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_jctl:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%JCTL).
Jesse Keating 7a3296
+ *	Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED,
Jesse Keating 7a3296
+ *	indicating whether we are stopping or resuming now.  If @notify
Jesse Keating 7a3296
+ *	is nonzero, @current is the last thread to stop and so will send
Jesse Keating 7a3296
+ *	%SIGCHLD to its parent after this callback; @notify reflects
Jesse Keating 7a3296
+ *	what the parent's %SIGCHLD has in @si_code, which can sometimes
Jesse Keating 7a3296
+ *	be %CLD_STOPPED even when @type is %CLD_CONTINUED.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_exec:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%EXEC).
Jesse Keating 7a3296
+ *	An execve system call has succeeded and the new program is about to
Jesse Keating 7a3296
+ *	start running.  The initial user register state is handy to be tweaked
Jesse Keating 7a3296
+ *	directly in @regs.  @fmt and @bprm gives the details of this exec.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_syscall_entry:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%SYSCALL_ENTRY).
Jesse Keating 7a3296
+ *	Thread has entered the kernel to request a system call.
Jesse Keating 7a3296
+ *	The user register state is handy to be tweaked directly in @regs.
Jesse Keating 7a3296
+ *	The @action argument contains an &enum utrace_syscall_action,
Jesse Keating 7a3296
+ *	use utrace_syscall_action() to extract it.  The return value
Jesse Keating 7a3296
+ *	overrides the last engine's action for the system call.
Jesse Keating 7a3296
+ *	If the final action is %UTRACE_SYSCALL_ABORT, no system call
Jesse Keating 7a3296
+ *	is made.  The details of the system call being attempted can
Jesse Keating 7a3296
+ *	be fetched here with syscall_get_nr() and syscall_get_arguments().
Jesse Keating 7a3296
+ *	The parameter registers can be changed with syscall_set_arguments().
Jesse Keating 7a3296
+ *	See above about the %UTRACE_SYSCALL_RESUMED flag in @action.
Jesse Keating 7a3296
+ *	Use %UTRACE_REPORT in the return value to guarantee you get
Jesse Keating 7a3296
+ *	another callback (with %UTRACE_SYSCALL_RESUMED flag) in case
Jesse Keating 7a3296
+ *	@current stops with %UTRACE_STOP before attempting the system call.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_syscall_exit:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%SYSCALL_EXIT).
Jesse Keating 7a3296
+ *	Thread is about to leave the kernel after a system call request.
Jesse Keating 7a3296
+ *	The user register state is handy to be tweaked directly in @regs.
Jesse Keating 7a3296
+ *	The results of the system call attempt can be examined here using
Jesse Keating 7a3296
+ *	syscall_get_error() and syscall_get_return_value().  It is safe
Jesse Keating 7a3296
+ *	here to call syscall_set_return_value() or syscall_rollback().
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_exit:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%EXIT).
Jesse Keating 7a3296
+ *	Thread is exiting and cannot be prevented from doing so,
Jesse Keating 7a3296
+ *	but all its state is still live.  The @code value will be
Jesse Keating 7a3296
+ *	the wait result seen by the parent, and can be changed by
Jesse Keating 7a3296
+ *	this engine or others.  The @orig_code value is the real
Jesse Keating 7a3296
+ *	status, not changed by any tracing engine.  Returning %UTRACE_STOP
Jesse Keating 7a3296
+ *	here keeps @current stopped before it cleans up its state and dies,
Jesse Keating 7a3296
+ *	so it can be examined by other processes.  When @current is allowed
Jesse Keating 7a3296
+ *	to run, it will die and get to the @report_death callback.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_death:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%DEATH).
Jesse Keating 7a3296
+ *	Thread is really dead now.  It might be reaped by its parent at
Jesse Keating 7a3296
+ *	any time, or self-reap immediately.  Though the actual reaping
Jesse Keating 7a3296
+ *	may happen in parallel, a report_reap() callback will always be
Jesse Keating 7a3296
+ *	ordered after a report_death() callback.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @report_reap:
Jesse Keating 7a3296
+ *	Requested by %UTRACE_EVENT(%REAP).
Jesse Keating 7a3296
+ *	Called when someone reaps the dead task (parent, init, or self).
Jesse Keating 7a3296
+ *	This means the parent called wait, or else this was a detached
Jesse Keating 7a3296
+ *	thread or a process whose parent ignores SIGCHLD.
Jesse Keating 7a3296
+ *	No more callbacks are made after this one.
Jesse Keating 7a3296
+ *	The engine is always detached.
Jesse Keating 7a3296
+ *	There is nothing more a tracing engine can do about this thread.
Jesse Keating 7a3296
+ *	After this callback, the @engine pointer will become invalid.
Jesse Keating 7a3296
+ *	The @task pointer may become invalid if get_task_struct() hasn't
Jesse Keating 7a3296
+ *	been used to keep it alive.
Jesse Keating 7a3296
+ *	An engine should always request this callback if it stores the
Jesse Keating 7a3296
+ *	@engine pointer or stores any pointer in @engine->data, so it
Jesse Keating 7a3296
+ *	can clean up its data structures.
Jesse Keating 7a3296
+ *	Unlike other callbacks, this can be called from the parent's context
Jesse Keating 7a3296
+ *	rather than from the traced thread itself--it must not delay the
Jesse Keating 7a3296
+ *	parent by blocking.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * @release:
Jesse Keating 7a3296
+ *	If not %NULL, this is called after the last utrace_engine_put()
Jesse Keating 7a3296
+ *	call for a &struct utrace_engine, which could be implicit after
Jesse Keating 7a3296
+ *	a %UTRACE_DETACH return from another callback.  Its argument is
Jesse Keating 7a3296
+ *	the engine's @data member.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+struct utrace_engine_ops {
Jesse Keating 7a3296
+	u32 (*report_quiesce)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			      unsigned long event);
Jesse Keating 7a3296
+	u32 (*report_signal)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			     struct pt_regs *regs,
Jesse Keating 7a3296
+			     siginfo_t *info,
Jesse Keating 7a3296
+			     const struct k_sigaction *orig_ka,
Jesse Keating 7a3296
+			     struct k_sigaction *return_ka);
Jesse Keating 7a3296
+	u32 (*report_clone)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			    unsigned long clone_flags,
Jesse Keating 7a3296
+			    struct task_struct *child);
Jesse Keating 7a3296
+	u32 (*report_jctl)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			   int type, int notify);
Jesse Keating 7a3296
+	u32 (*report_exec)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			   const struct linux_binfmt *fmt,
Jesse Keating 7a3296
+			   const struct linux_binprm *bprm,
Jesse Keating 7a3296
+			   struct pt_regs *regs);
Jesse Keating 7a3296
+	u32 (*report_syscall_entry)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+				    struct pt_regs *regs);
Jesse Keating 7a3296
+	u32 (*report_syscall_exit)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+				   struct pt_regs *regs);
Jesse Keating 7a3296
+	u32 (*report_exit)(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			   long orig_code, long *code);
Jesse Keating 7a3296
+	u32 (*report_death)(struct utrace_engine *engine,
Jesse Keating 7a3296
+			    bool group_dead, int signal);
Jesse Keating 7a3296
+	void (*report_reap)(struct utrace_engine *engine,
Jesse Keating 7a3296
+			    struct task_struct *task);
Jesse Keating 7a3296
+	void (*release)(void *data);
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * struct utrace_examiner - private state for using utrace_prepare_examine()
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * The members of &struct utrace_examiner are private to the implementation.
Jesse Keating 7a3296
+ * This data type holds the state from a call to utrace_prepare_examine()
Jesse Keating 7a3296
+ * to be used by a call to utrace_finish_examine().
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+struct utrace_examiner {
Jesse Keating 7a3296
+/* private: */
Jesse Keating 7a3296
+	long state;
Jesse Keating 7a3296
+	unsigned long ncsw;
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * These are the exported entry points for tracing engines to use.
Jesse Keating 7a3296
+ * See kernel/utrace.c for their kerneldoc comments with interface details.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+struct utrace_engine *utrace_attach_task(struct task_struct *, int,
Jesse Keating 7a3296
+					 const struct utrace_engine_ops *,
Jesse Keating 7a3296
+					 void *);
Jesse Keating 7a3296
+struct utrace_engine *utrace_attach_pid(struct pid *, int,
Jesse Keating 7a3296
+					const struct utrace_engine_ops *,
Jesse Keating 7a3296
+					void *);
Jesse Keating 7a3296
+int __must_check utrace_control(struct task_struct *,
Jesse Keating 7a3296
+				struct utrace_engine *,
Jesse Keating 7a3296
+				enum utrace_resume_action);
Jesse Keating 7a3296
+int __must_check utrace_set_events(struct task_struct *,
Jesse Keating 7a3296
+				   struct utrace_engine *,
Jesse Keating 7a3296
+				   unsigned long eventmask);
Jesse Keating 7a3296
+int __must_check utrace_barrier(struct task_struct *,
Jesse Keating 7a3296
+				struct utrace_engine *);
Jesse Keating 7a3296
+int __must_check utrace_prepare_examine(struct task_struct *,
Jesse Keating 7a3296
+					struct utrace_engine *,
Jesse Keating 7a3296
+					struct utrace_examiner *);
Jesse Keating 7a3296
+int __must_check utrace_finish_examine(struct task_struct *,
Jesse Keating 7a3296
+				       struct utrace_engine *,
Jesse Keating 7a3296
+				       struct utrace_examiner *);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_control_pid - control a thread being traced by a tracing engine
Jesse Keating 7a3296
+ * @pid:		thread to affect
Jesse Keating 7a3296
+ * @engine:		attached engine to affect
Jesse Keating 7a3296
+ * @action:		&enum utrace_resume_action for thread to do
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This is the same as utrace_control(), but takes a &struct pid
Jesse Keating 7a3296
+ * pointer rather than a &struct task_struct pointer.  The caller must
Jesse Keating 7a3296
+ * hold a ref on @pid, but does not need to worry about the task
Jesse Keating 7a3296
+ * staying valid.  If it's been reaped so that @pid points nowhere,
Jesse Keating 7a3296
+ * then this call returns -%ESRCH.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline __must_check int utrace_control_pid(
Jesse Keating 7a3296
+	struct pid *pid, struct utrace_engine *engine,
Jesse Keating 7a3296
+	enum utrace_resume_action action)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * We don't bother with rcu_read_lock() here to protect the
Jesse Keating 7a3296
+	 * task_struct pointer, because utrace_control will return
Jesse Keating 7a3296
+	 * -ESRCH without looking at that pointer if the engine is
Jesse Keating 7a3296
+	 * already detached.  A task_struct pointer can't die before
Jesse Keating 7a3296
+	 * all the engines are detached in release_task() first.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	struct task_struct *task = pid_task(pid, PIDTYPE_PID);
Jesse Keating 7a3296
+	return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_set_events_pid - choose which event reports a tracing engine gets
Jesse Keating 7a3296
+ * @pid:		thread to affect
Jesse Keating 7a3296
+ * @engine:		attached engine to affect
Jesse Keating 7a3296
+ * @eventmask:		new event mask
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This is the same as utrace_set_events(), but takes a &struct pid
Jesse Keating 7a3296
+ * pointer rather than a &struct task_struct pointer.  The caller must
Jesse Keating 7a3296
+ * hold a ref on @pid, but does not need to worry about the task
Jesse Keating 7a3296
+ * staying valid.  If it's been reaped so that @pid points nowhere,
Jesse Keating 7a3296
+ * then this call returns -%ESRCH.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline __must_check int utrace_set_events_pid(
Jesse Keating 7a3296
+	struct pid *pid, struct utrace_engine *engine, unsigned long eventmask)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct task_struct *task = pid_task(pid, PIDTYPE_PID);
Jesse Keating 7a3296
+	return unlikely(!task) ? -ESRCH :
Jesse Keating 7a3296
+		utrace_set_events(task, engine, eventmask);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/**
Jesse Keating 7a3296
+ * utrace_barrier_pid - synchronize with simultaneous tracing callbacks
Jesse Keating 7a3296
+ * @pid:		thread to affect
Jesse Keating 7a3296
+ * @engine:		engine to affect (can be detached)
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * This is the same as utrace_barrier(), but takes a &struct pid
Jesse Keating 7a3296
+ * pointer rather than a &struct task_struct pointer.  The caller must
Jesse Keating 7a3296
+ * hold a ref on @pid, but does not need to worry about the task
Jesse Keating 7a3296
+ * staying valid.  If it's been reaped so that @pid points nowhere,
Jesse Keating 7a3296
+ * then this call returns -%ESRCH.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static inline __must_check int utrace_barrier_pid(struct pid *pid,
Jesse Keating 7a3296
+						  struct utrace_engine *engine)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct task_struct *task = pid_task(pid, PIDTYPE_PID);
Jesse Keating 7a3296
+	return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#endif	/* CONFIG_UTRACE */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#endif	/* linux/utrace.h */
Jesse Keating 7a3296
diff --git a/init/Kconfig b/init/Kconfig
Jesse Keating 7a3296
index 5cff9a9..c0b7f81 100644
Jesse Keating 7a3296
--- a/init/Kconfig
Jesse Keating 7a3296
+++ b/init/Kconfig
Jesse Keating 7a3296
@@ -328,6 +328,15 @@ config AUDIT_TREE
Jesse Keating 7a3296
 	depends on AUDITSYSCALL
Jesse Keating 7a3296
 	select INOTIFY
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+config UTRACE
Jesse Keating 7a3296
+	bool "Infrastructure for tracing and debugging user processes"
Jesse Keating 7a3296
+	depends on EXPERIMENTAL
Jesse Keating 7a3296
+	depends on HAVE_ARCH_TRACEHOOK
Jesse Keating 7a3296
+	help
Jesse Keating 7a3296
+	  Enable the utrace process tracing interface.  This is an internal
Jesse Keating 7a3296
+	  kernel interface exported to kernel modules, to track events in
Jesse Keating 7a3296
+	  user threads, extract and change user thread state.
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 menu "RCU Subsystem"
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 choice
Jesse Keating 7a3296
diff --git a/kernel/Makefile b/kernel/Makefile
Jesse Keating 7a3296
index 057472f..dfdc01c 100644
Jesse Keating 7a3296
--- a/kernel/Makefile
Jesse Keating 7a3296
+++ b/kernel/Makefile
Jesse Keating 7a3296
@@ -70,6 +70,8 @@ obj-$(CONFIG_IKCONFIG) += configs.o
Jesse Keating 7a3296
 obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
Jesse Keating 7a3296
 obj-$(CONFIG_SMP) += stop_machine.o
Jesse Keating 7a3296
 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
Jesse Keating 7a3296
+obj-$(CONFIG_UTRACE) += utrace.o
Jesse Keating 7a3296
+obj-$(CONFIG_UTRACE) += ptrace-utrace.o
Jesse Keating 7a3296
 obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o
Jesse Keating 7a3296
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
Jesse Keating 7a3296
 obj-$(CONFIG_GCOV_KERNEL) += gcov/
Jesse Keating 7a3296
diff --git a/kernel/fork.c b/kernel/fork.c
Jesse Keating 7a3296
index b6cce14..ac4a6ec 100644
Jesse Keating 7a3296
--- a/kernel/fork.c
Jesse Keating 7a3296
+++ b/kernel/fork.c
Jesse Keating 7a3296
@@ -161,6 +161,7 @@ void free_task(struct task_struct *tsk)
Jesse Keating 7a3296
 	free_thread_info(tsk->stack);
Jesse Keating 7a3296
 	rt_mutex_debug_task_free(tsk);
Jesse Keating 7a3296
 	ftrace_graph_exit_task(tsk);
Jesse Keating 7a3296
+	tracehook_free_task(tsk);
Jesse Keating 7a3296
 	free_task_struct(tsk);
Jesse Keating 7a3296
 }
Jesse Keating 7a3296
 EXPORT_SYMBOL(free_task);
Jesse Keating 7a3296
@@ -1007,6 +1008,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
Jesse Keating 7a3296
 	if (!p)
Jesse Keating 7a3296
 		goto fork_out;
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+	tracehook_init_task(p);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
 	ftrace_graph_init_task(p);
Jesse Keating 7a3296
 
Jesse Keating 7a3296
 	rt_mutex_init_task(p);
Jesse Keating 7a3296
diff --git a/kernel/ptrace-utrace.c b/kernel/ptrace-utrace.c
Jesse Keating 7a3296
new file mode 100644
Jesse Keating 7a3296
index 0000000..86234ee
Jesse Keating 7a3296
--- /dev/null
Jesse Keating 7a3296
+++ b/kernel/ptrace-utrace.c
Jesse Keating 7a3296
@@ -0,0 +1,1127 @@
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * linux/kernel/ptrace.c
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * (C) Copyright 1999 Linus Torvalds
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Common interfaces for "ptrace()" which we do not want
Jesse Keating 7a3296
+ * to continually duplicate across every architecture.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#include <linux capability.h="">
Jesse Keating 7a3296
+#include <linux module.h="">
Jesse Keating 7a3296
+#include <linux sched.h="">
Jesse Keating 7a3296
+#include <linux errno.h="">
Jesse Keating 7a3296
+#include <linux mm.h="">
Jesse Keating 7a3296
+#include <linux highmem.h="">
Jesse Keating 7a3296
+#include <linux pagemap.h="">
Jesse Keating 7a3296
+#include <linux smp_lock.h="">
Jesse Keating 7a3296
+#include <linux ptrace.h="">
Jesse Keating 7a3296
+#include <linux utrace.h="">
Jesse Keating 7a3296
+#include <linux security.h="">
Jesse Keating 7a3296
+#include <linux signal.h="">
Jesse Keating 7a3296
+#include <linux audit.h="">
Jesse Keating 7a3296
+#include <linux pid_namespace.h="">
Jesse Keating 7a3296
+#include <linux syscalls.h="">
Jesse Keating 7a3296
+#include <linux uaccess.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * ptrace a task: make the debugger its new parent and
Jesse Keating 7a3296
+ * move it to the ptrace list.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Must be called with the tasklist lock write-held.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	BUG_ON(!list_empty(&child->ptrace_entry));
Jesse Keating 7a3296
+	list_add(&child->ptrace_entry, &new_parent->ptraced);
Jesse Keating 7a3296
+	child->parent = new_parent;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * unptrace a task: move it back to its original parent and
Jesse Keating 7a3296
+ * remove it from the ptrace list.
Jesse Keating 7a3296
+ *
Jesse Keating 7a3296
+ * Must be called with the tasklist lock write-held.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+void __ptrace_unlink(struct task_struct *child)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	BUG_ON(!child->ptrace);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	child->ptrace = 0;
Jesse Keating 7a3296
+	child->parent = child->real_parent;
Jesse Keating 7a3296
+	list_del_init(&child->ptrace_entry);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	arch_ptrace_untrace(child);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+struct ptrace_context {
Jesse Keating 7a3296
+	int				options;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	int				signr;
Jesse Keating 7a3296
+	siginfo_t			*siginfo;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	int				stop_code;
Jesse Keating 7a3296
+	unsigned long			eventmsg;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	enum utrace_resume_action	resume;
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#define PT_UTRACED			0x00001000
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#define PTRACE_O_SYSEMU			0x100
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#define PTRACE_EVENT_SYSCALL		(1 << 16)
Jesse Keating 7a3296
+#define PTRACE_EVENT_SIGTRAP		(2 << 16)
Jesse Keating 7a3296
+#define PTRACE_EVENT_SIGNAL		(3 << 16)
Jesse Keating 7a3296
+/* events visible to user-space */
Jesse Keating 7a3296
+#define PTRACE_EVENT_MASK		0xFFFF
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline bool ptrace_event_pending(struct ptrace_context *ctx)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return ctx->stop_code != 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline int get_stop_event(struct ptrace_context *ctx)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return ctx->stop_code >> 8;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline void set_stop_code(struct ptrace_context *ctx, int event)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	ctx->stop_code = (event << 8) | SIGTRAP;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline struct ptrace_context *
Jesse Keating 7a3296
+ptrace_context(struct utrace_engine *engine)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return engine->data;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	return utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS,
Jesse Keating 7a3296
+					&ptrace_utrace_ops, NULL);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct utrace_engine *
Jesse Keating 7a3296
+ptrace_reuse_engine(struct task_struct *tracee)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine;
Jesse Keating 7a3296
+	struct ptrace_context *ctx;
Jesse Keating 7a3296
+	int err = -EPERM;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	engine = ptrace_lookup_engine(tracee);
Jesse Keating 7a3296
+	if (IS_ERR(engine))
Jesse Keating 7a3296
+		return engine;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx = ptrace_context(engine);
Jesse Keating 7a3296
+	if (unlikely(ctx->resume == UTRACE_DETACH)) {
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Try to reuse this self-detaching engine.
Jesse Keating 7a3296
+		 * The only caller which can hit this case is ptrace_attach(),
Jesse Keating 7a3296
+		 * it holds ->cred_guard_mutex.
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		ctx->options = 0;
Jesse Keating 7a3296
+		ctx->eventmsg = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		/* make sure we don't get unwanted reports */
Jesse Keating 7a3296
+		err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE));
Jesse Keating 7a3296
+		if (!err || err == -EINPROGRESS) {
Jesse Keating 7a3296
+			ctx->resume = UTRACE_RESUME;
Jesse Keating 7a3296
+			/* synchronize with ptrace_report_signal() */
Jesse Keating 7a3296
+			err = utrace_barrier(tracee, engine);
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+		WARN_ON(!err != (engine->ops == &ptrace_utrace_ops));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (!err)
Jesse Keating 7a3296
+			return engine;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+	return ERR_PTR(err);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static struct utrace_engine *
Jesse Keating 7a3296
+ptrace_attach_engine(struct task_struct *tracee)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine;
Jesse Keating 7a3296
+	struct ptrace_context *ctx;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(task_utrace_flags(tracee))) {
Jesse Keating 7a3296
+		engine = ptrace_reuse_engine(tracee);
Jesse Keating 7a3296
+		if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM)
Jesse Keating 7a3296
+			return engine;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
Jesse Keating 7a3296
+	if (unlikely(!ctx))
Jesse Keating 7a3296
+		return ERR_PTR(-ENOMEM);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx->resume = UTRACE_RESUME;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE |
Jesse Keating 7a3296
+						UTRACE_ATTACH_EXCLUSIVE |
Jesse Keating 7a3296
+						UTRACE_ATTACH_MATCH_OPS,
Jesse Keating 7a3296
+						&ptrace_utrace_ops, ctx);
Jesse Keating 7a3296
+	if (unlikely(IS_ERR(engine))) {
Jesse Keating 7a3296
+		if (engine != ERR_PTR(-ESRCH) &&
Jesse Keating 7a3296
+		    engine != ERR_PTR(-ERESTARTNOINTR))
Jesse Keating 7a3296
+			engine = ERR_PTR(-EPERM);
Jesse Keating 7a3296
+		kfree(ctx);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return engine;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline int ptrace_set_events(struct task_struct *target,
Jesse Keating 7a3296
+					struct utrace_engine *engine,
Jesse Keating 7a3296
+					unsigned long options)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * We need QUIESCE for resume handling, CLONE to check
Jesse Keating 7a3296
+	 * for CLONE_PTRACE, other events are always reported.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) |
Jesse Keating 7a3296
+			       UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx->options = options;
Jesse Keating 7a3296
+	if (options & PTRACE_O_TRACEEXIT)
Jesse Keating 7a3296
+		events |= UTRACE_EVENT(EXIT);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return utrace_set_events(target, engine, events);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Attach a utrace engine for ptrace and set up its event mask.
Jesse Keating 7a3296
+ * Returns error code or 0 on success.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static int ptrace_attach_task(struct task_struct *tracee, int options)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine;
Jesse Keating 7a3296
+	int err;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	engine = ptrace_attach_engine(tracee);
Jesse Keating 7a3296
+	if (IS_ERR(engine))
Jesse Keating 7a3296
+		return PTR_ERR(engine);
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * It can fail only if the tracee is dead, the caller
Jesse Keating 7a3296
+	 * must notice this before setting PT_UTRACED.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	err = ptrace_set_events(tracee, engine, options);
Jesse Keating 7a3296
+	WARN_ON(err && !tracee->exit_state);
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ptrace_wake_up(struct task_struct *tracee,
Jesse Keating 7a3296
+				struct utrace_engine *engine,
Jesse Keating 7a3296
+				enum utrace_resume_action action,
Jesse Keating 7a3296
+				bool force_wakeup)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	if (force_wakeup) {
Jesse Keating 7a3296
+		unsigned long flags;
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Preserve the compatibility bug. Historically ptrace
Jesse Keating 7a3296
+		 * wakes up the tracee even if it should not. Clear
Jesse Keating 7a3296
+		 * SIGNAL_STOP_STOPPED for utrace_wakeup().
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		if (lock_task_sighand(tracee, &flags)) {
Jesse Keating 7a3296
+			tracee->signal->flags &= ~SIGNAL_STOP_STOPPED;
Jesse Keating 7a3296
+			unlock_task_sighand(tracee, &flags);
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (action != UTRACE_REPORT)
Jesse Keating 7a3296
+		ptrace_context(engine)->stop_code = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return utrace_control(tracee, engine, action);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void ptrace_detach_task(struct task_struct *tracee, int sig)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * If true, the caller is PTRACE_DETACH, otherwise
Jesse Keating 7a3296
+	 * the tracer detaches implicitly during exit.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	bool voluntary = (sig >= 0);
Jesse Keating 7a3296
+	struct utrace_engine *engine = ptrace_lookup_engine(tracee);
Jesse Keating 7a3296
+	enum utrace_resume_action action = UTRACE_DETACH;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(IS_ERR(engine)))
Jesse Keating 7a3296
+		return;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (sig) {
Jesse Keating 7a3296
+		struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		switch (get_stop_event(ctx)) {
Jesse Keating 7a3296
+		case PTRACE_EVENT_SYSCALL:
Jesse Keating 7a3296
+			if (voluntary)
Jesse Keating 7a3296
+				send_sig_info(sig, SEND_SIG_PRIV, tracee);
Jesse Keating 7a3296
+			break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		case PTRACE_EVENT_SIGNAL:
Jesse Keating 7a3296
+			if (voluntary)
Jesse Keating 7a3296
+				ctx->signr = sig;
Jesse Keating 7a3296
+			ctx->resume = UTRACE_DETACH;
Jesse Keating 7a3296
+			action = UTRACE_RESUME;
Jesse Keating 7a3296
+			break;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ptrace_wake_up(tracee, engine, action, voluntary);
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void ptrace_abort_attach(struct task_struct *tracee)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	ptrace_detach_task(tracee, 0);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_exit(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			      long orig_code, long *code)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	WARN_ON(ptrace_event_pending(ctx) &&
Jesse Keating 7a3296
+		!signal_group_exit(current->signal));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	set_stop_code(ctx, PTRACE_EVENT_EXIT);
Jesse Keating 7a3296
+	ctx->eventmsg = *code;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return UTRACE_STOP;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void ptrace_clone_attach(struct task_struct *child,
Jesse Keating 7a3296
+				int options)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct task_struct *parent = current;
Jesse Keating 7a3296
+	struct task_struct *tracer;
Jesse Keating 7a3296
+	bool abort = true;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(ptrace_attach_task(child, options))) {
Jesse Keating 7a3296
+		WARN_ON(1);
Jesse Keating 7a3296
+		return;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	write_lock_irq(&tasklist_lock);
Jesse Keating 7a3296
+	tracer = parent->parent;
Jesse Keating 7a3296
+	if (!(tracer->flags & PF_EXITING) && parent->ptrace) {
Jesse Keating 7a3296
+		child->ptrace = parent->ptrace;
Jesse Keating 7a3296
+		__ptrace_link(child, tracer);
Jesse Keating 7a3296
+		abort = false;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+	write_unlock_irq(&tasklist_lock);
Jesse Keating 7a3296
+	if (unlikely(abort)) {
Jesse Keating 7a3296
+		ptrace_abort_attach(child);
Jesse Keating 7a3296
+		return;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	sigaddset(&child->pending.signal, SIGSTOP);
Jesse Keating 7a3296
+	set_tsk_thread_flag(child, TIF_SIGPENDING);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_clone(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			       unsigned long clone_flags,
Jesse Keating 7a3296
+			       struct task_struct *child)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+	int event = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	WARN_ON(ptrace_event_pending(ctx));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (clone_flags & CLONE_UNTRACED) {
Jesse Keating 7a3296
+		/* no events reported */
Jesse Keating 7a3296
+	} else if (clone_flags & CLONE_VFORK) {
Jesse Keating 7a3296
+		if (ctx->options & PTRACE_O_TRACEVFORK)
Jesse Keating 7a3296
+			event = PTRACE_EVENT_VFORK;
Jesse Keating 7a3296
+		else if (ctx->options & PTRACE_O_TRACEVFORKDONE)
Jesse Keating 7a3296
+			event = PTRACE_EVENT_VFORK_DONE;
Jesse Keating 7a3296
+	} else if ((clone_flags & CSIGNAL) != SIGCHLD) {
Jesse Keating 7a3296
+		if (ctx->options & PTRACE_O_TRACECLONE)
Jesse Keating 7a3296
+			event = PTRACE_EVENT_CLONE;
Jesse Keating 7a3296
+	} else if (ctx->options & PTRACE_O_TRACEFORK) {
Jesse Keating 7a3296
+		event = PTRACE_EVENT_FORK;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Any of these reports implies auto-attaching the new child.
Jesse Keating 7a3296
+	 * So does CLONE_PTRACE, even with no event to report.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if ((event && event != PTRACE_EVENT_VFORK_DONE) ||
Jesse Keating 7a3296
+				(clone_flags & CLONE_PTRACE))
Jesse Keating 7a3296
+		ptrace_clone_attach(child, ctx->options);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!event)
Jesse Keating 7a3296
+		return UTRACE_RESUME;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	set_stop_code(ctx, event);
Jesse Keating 7a3296
+	ctx->eventmsg = child->pid;
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * We shouldn't stop now, inside the do_fork() path.
Jesse Keating 7a3296
+	 * We will stop later, before return to user-mode.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (event == PTRACE_EVENT_VFORK_DONE)
Jesse Keating 7a3296
+		return UTRACE_REPORT;
Jesse Keating 7a3296
+	else
Jesse Keating 7a3296
+		return UTRACE_STOP;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static inline void set_syscall_code(struct ptrace_context *ctx)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	set_stop_code(ctx, PTRACE_EVENT_SYSCALL);
Jesse Keating 7a3296
+	if (ctx->options & PTRACE_O_TRACESYSGOOD)
Jesse Keating 7a3296
+		ctx->stop_code |= 0x80;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_syscall_entry(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+				       struct pt_regs *regs)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (action & UTRACE_SYSCALL_RESUMED) {
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * We already reported the first time.
Jesse Keating 7a3296
+		 * Nothing more to do now.
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		if (unlikely(ctx->options & PTRACE_O_SYSEMU))
Jesse Keating 7a3296
+			return UTRACE_SYSCALL_ABORT | UTRACE_REPORT;
Jesse Keating 7a3296
+		return utrace_syscall_action(action) | UTRACE_RESUME;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	WARN_ON(ptrace_event_pending(ctx));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	set_syscall_code(ctx);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(ctx->options & PTRACE_O_SYSEMU))
Jesse Keating 7a3296
+		return UTRACE_SYSCALL_ABORT | UTRACE_REPORT;
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Stop now to report.  We will get another callback after
Jesse Keating 7a3296
+	 * we resume, with the UTRACE_SYSCALL_RESUMED flag set.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	return UTRACE_SYSCALL_RUN | UTRACE_STOP;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_syscall_exit(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+				      struct pt_regs *regs)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ptrace_event_pending(ctx))
Jesse Keating 7a3296
+		return UTRACE_STOP;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ctx->resume != UTRACE_RESUME) {
Jesse Keating 7a3296
+		WARN_ON(ctx->resume != UTRACE_BLOCKSTEP &&
Jesse Keating 7a3296
+			ctx->resume != UTRACE_SINGLESTEP);
Jesse Keating 7a3296
+		ctx->resume = UTRACE_RESUME;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		ctx->signr = SIGTRAP;
Jesse Keating 7a3296
+		return UTRACE_INTERRUPT;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	set_syscall_code(ctx);
Jesse Keating 7a3296
+	return UTRACE_STOP;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_exec(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+			      const struct linux_binfmt *fmt,
Jesse Keating 7a3296
+			      const struct linux_binprm *bprm,
Jesse Keating 7a3296
+			      struct pt_regs *regs)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	WARN_ON(ptrace_event_pending(ctx));
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!(ctx->options & PTRACE_O_TRACEEXEC)) {
Jesse Keating 7a3296
+		/*
Jesse Keating 7a3296
+		 * Old-fashioned ptrace'd exec just posts a plain signal.
Jesse Keating 7a3296
+		 */
Jesse Keating 7a3296
+		send_sig(SIGTRAP, current, 0);
Jesse Keating 7a3296
+		return UTRACE_RESUME;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	set_stop_code(ctx, PTRACE_EVENT_EXEC);
Jesse Keating 7a3296
+	return UTRACE_STOP;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static enum utrace_signal_action resume_signal(struct ptrace_context *ctx,
Jesse Keating 7a3296
+					       struct k_sigaction *return_ka)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	siginfo_t *info = ctx->siginfo;
Jesse Keating 7a3296
+	int signr = ctx->signr;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx->siginfo = NULL;
Jesse Keating 7a3296
+	ctx->signr = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/* Did the debugger cancel the sig? */
Jesse Keating 7a3296
+	if (!signr)
Jesse Keating 7a3296
+		return UTRACE_SIGNAL_IGN;
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Update the siginfo structure if the signal has changed.
Jesse Keating 7a3296
+	 * If the debugger wanted something specific in the siginfo
Jesse Keating 7a3296
+	 * then it should have updated *info via PTRACE_SETSIGINFO.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (info->si_signo != signr) {
Jesse Keating 7a3296
+		info->si_signo = signr;
Jesse Keating 7a3296
+		info->si_errno = 0;
Jesse Keating 7a3296
+		info->si_code = SI_USER;
Jesse Keating 7a3296
+		info->si_pid = task_pid_vnr(current->parent);
Jesse Keating 7a3296
+		info->si_uid = task_uid(current->parent);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/* If the (new) signal is now blocked, requeue it. */
Jesse Keating 7a3296
+	if (sigismember(¤t->blocked, signr)) {
Jesse Keating 7a3296
+		send_sig_info(signr, info, current);
Jesse Keating 7a3296
+		return UTRACE_SIGNAL_IGN;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	spin_lock_irq(¤t->sighand->siglock);
Jesse Keating 7a3296
+	*return_ka = current->sighand->action[signr - 1];
Jesse Keating 7a3296
+	spin_unlock_irq(¤t->sighand->siglock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return UTRACE_SIGNAL_DELIVER;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_signal(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+				struct pt_regs *regs,
Jesse Keating 7a3296
+				siginfo_t *info,
Jesse Keating 7a3296
+				const struct k_sigaction *orig_ka,
Jesse Keating 7a3296
+				struct k_sigaction *return_ka)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+	enum utrace_resume_action resume = ctx->resume;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ptrace_event_pending(ctx)) {
Jesse Keating 7a3296
+		action = utrace_signal_action(action);
Jesse Keating 7a3296
+		WARN_ON(action != UTRACE_SIGNAL_REPORT);
Jesse Keating 7a3296
+		return action | UTRACE_STOP;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (utrace_signal_action(action)) {
Jesse Keating 7a3296
+	case UTRACE_SIGNAL_HANDLER:
Jesse Keating 7a3296
+		if (WARN_ON(ctx->siginfo))
Jesse Keating 7a3296
+			ctx->siginfo = NULL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (resume != UTRACE_RESUME) {
Jesse Keating 7a3296
+			WARN_ON(resume != UTRACE_BLOCKSTEP &&
Jesse Keating 7a3296
+				resume != UTRACE_SINGLESTEP);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+			set_stop_code(ctx, PTRACE_EVENT_SIGTRAP);
Jesse Keating 7a3296
+			return UTRACE_STOP | UTRACE_SIGNAL_IGN;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case UTRACE_SIGNAL_REPORT:
Jesse Keating 7a3296
+		if (!ctx->siginfo) {
Jesse Keating 7a3296
+			if (ctx->signr) {
Jesse Keating 7a3296
+				/* set by ptrace_resume(SYSCALL_EXIT) */
Jesse Keating 7a3296
+				WARN_ON(ctx->signr != SIGTRAP);
Jesse Keating 7a3296
+				user_single_step_siginfo(current, regs, info);
Jesse Keating 7a3296
+				force_sig_info(SIGTRAP, info, current);
Jesse Keating 7a3296
+			}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+			return resume | UTRACE_SIGNAL_IGN;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (WARN_ON(ctx->siginfo != info))
Jesse Keating 7a3296
+			return resume | UTRACE_SIGNAL_IGN;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		return resume | resume_signal(ctx, return_ka);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	WARN_ON(ctx->siginfo);
Jesse Keating 7a3296
+	ctx->siginfo = info;
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * ctx->siginfo points to the caller's stack.
Jesse Keating 7a3296
+	 * Make sure the subsequent UTRACE_SIGNAL_REPORT clears
Jesse Keating 7a3296
+	 * ->siginfo before return from get_signal_to_deliver().
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (utrace_control(current, engine, UTRACE_INTERRUPT))
Jesse Keating 7a3296
+		WARN_ON(1);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx->signr = info->si_signo;
Jesse Keating 7a3296
+	ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return UTRACE_STOP | UTRACE_SIGNAL_IGN;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static u32 ptrace_report_quiesce(u32 action, struct utrace_engine *engine,
Jesse Keating 7a3296
+				 unsigned long event)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (ptrace_event_pending(ctx))
Jesse Keating 7a3296
+		return UTRACE_STOP;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return event ? UTRACE_RESUME : ctx->resume;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void ptrace_release(void *data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	kfree(data);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static const struct utrace_engine_ops ptrace_utrace_ops = {
Jesse Keating 7a3296
+	.report_signal = ptrace_report_signal,
Jesse Keating 7a3296
+	.report_quiesce = ptrace_report_quiesce,
Jesse Keating 7a3296
+	.report_exec = ptrace_report_exec,
Jesse Keating 7a3296
+	.report_exit = ptrace_report_exit,
Jesse Keating 7a3296
+	.report_clone = ptrace_report_clone,
Jesse Keating 7a3296
+	.report_syscall_entry = ptrace_report_syscall_entry,
Jesse Keating 7a3296
+	.report_syscall_exit = ptrace_report_syscall_exit,
Jesse Keating 7a3296
+	.release = ptrace_release,
Jesse Keating 7a3296
+};
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+int ptrace_check_attach(struct task_struct *child, int kill)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine;
Jesse Keating 7a3296
+	struct utrace_examiner exam;
Jesse Keating 7a3296
+	int ret = -ESRCH;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	engine = ptrace_lookup_engine(child);
Jesse Keating 7a3296
+	if (IS_ERR(engine))
Jesse Keating 7a3296
+		return ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (child->parent != current)
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(kill))
Jesse Keating 7a3296
+		ret = 0;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!task_is_stopped_or_traced(child))
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Make sure our engine has already stopped the child.
Jesse Keating 7a3296
+	 * Then wait for it to be off the CPU.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (!utrace_control(child, engine, UTRACE_STOP) &&
Jesse Keating 7a3296
+	    !utrace_prepare_examine(child, engine, &exam))
Jesse Keating 7a3296
+		ret = 0;
Jesse Keating 7a3296
+out:
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+int ptrace_attach(struct task_struct *task)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	int retval;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	audit_ptrace(task);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	retval = -EPERM;
Jesse Keating 7a3296
+	if (unlikely(task->flags & PF_KTHREAD))
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+	if (same_thread_group(task, current))
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Protect exec's credential calculations against our interference;
Jesse Keating 7a3296
+	 * interference; SUID, SGID and LSM creds get determined differently
Jesse Keating 7a3296
+	 * under ptrace.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	retval = -ERESTARTNOINTR;
Jesse Keating 7a3296
+	if (mutex_lock_interruptible(&task->cred_guard_mutex))
Jesse Keating 7a3296
+		goto out;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	task_lock(task);
Jesse Keating 7a3296
+	retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
Jesse Keating 7a3296
+	task_unlock(task);
Jesse Keating 7a3296
+	if (retval)
Jesse Keating 7a3296
+		goto unlock_creds;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	retval = ptrace_attach_task(task, 0);
Jesse Keating 7a3296
+	if (unlikely(retval))
Jesse Keating 7a3296
+		goto unlock_creds;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	write_lock_irq(&tasklist_lock);
Jesse Keating 7a3296
+	retval = -EPERM;
Jesse Keating 7a3296
+	if (unlikely(task->exit_state))
Jesse Keating 7a3296
+		goto unlock_tasklist;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	BUG_ON(task->ptrace);
Jesse Keating 7a3296
+	task->ptrace = PT_UTRACED;
Jesse Keating 7a3296
+	if (capable(CAP_SYS_PTRACE))
Jesse Keating 7a3296
+		task->ptrace |= PT_PTRACE_CAP;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	__ptrace_link(task, current);
Jesse Keating 7a3296
+	send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	retval = 0;
Jesse Keating 7a3296
+unlock_tasklist:
Jesse Keating 7a3296
+	write_unlock_irq(&tasklist_lock);
Jesse Keating 7a3296
+unlock_creds:
Jesse Keating 7a3296
+	mutex_unlock(&task->cred_guard_mutex);
Jesse Keating 7a3296
+out:
Jesse Keating 7a3296
+	return retval;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Performs checks and sets PT_UTRACED.
Jesse Keating 7a3296
+ * Should be used by all ptrace implementations for PTRACE_TRACEME.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+int ptrace_traceme(void)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	bool detach = true;
Jesse Keating 7a3296
+	int ret = ptrace_attach_task(current, 0);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(ret))
Jesse Keating 7a3296
+		return ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ret = -EPERM;
Jesse Keating 7a3296
+	write_lock_irq(&tasklist_lock);
Jesse Keating 7a3296
+	BUG_ON(current->ptrace);
Jesse Keating 7a3296
+	ret = security_ptrace_traceme(current->parent);
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Check PF_EXITING to ensure ->real_parent has not passed
Jesse Keating 7a3296
+	 * exit_ptrace(). Otherwise we don't report the error but
Jesse Keating 7a3296
+	 * pretend ->real_parent untraces us right after return.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (!ret && !(current->real_parent->flags & PF_EXITING)) {
Jesse Keating 7a3296
+		current->ptrace = PT_UTRACED;
Jesse Keating 7a3296
+		__ptrace_link(current, current->real_parent);
Jesse Keating 7a3296
+		detach = false;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+	write_unlock_irq(&tasklist_lock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (detach)
Jesse Keating 7a3296
+		ptrace_abort_attach(current);
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void ptrace_do_detach(struct task_struct *tracee, unsigned int data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	bool detach, release;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	write_lock_irq(&tasklist_lock);
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * This tracee can be already killed. Make sure de_thread() or
Jesse Keating 7a3296
+	 * our sub-thread doing do_wait() didn't do release_task() yet.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	detach = tracee->ptrace != 0;
Jesse Keating 7a3296
+	release = false;
Jesse Keating 7a3296
+	if (likely(detach))
Jesse Keating 7a3296
+		release = __ptrace_detach(current, tracee);
Jesse Keating 7a3296
+	write_unlock_irq(&tasklist_lock);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(release))
Jesse Keating 7a3296
+		release_task(tracee);
Jesse Keating 7a3296
+	else if (likely(detach))
Jesse Keating 7a3296
+		ptrace_detach_task(tracee, data);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+int ptrace_detach(struct task_struct *child, unsigned int data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	if (!valid_signal(data))
Jesse Keating 7a3296
+		return -EIO;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ptrace_do_detach(child, data);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Detach all tasks we were using ptrace on.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+void exit_ptrace(struct task_struct *tracer)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	for (;;) {
Jesse Keating 7a3296
+		struct task_struct *tracee = NULL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		read_lock(&tasklist_lock);
Jesse Keating 7a3296
+		if (!list_empty(&tracer->ptraced)) {
Jesse Keating 7a3296
+			tracee = list_first_entry(&tracer->ptraced,
Jesse Keating 7a3296
+					struct task_struct, ptrace_entry);
Jesse Keating 7a3296
+			get_task_struct(tracee);
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+		read_unlock(&tasklist_lock);
Jesse Keating 7a3296
+		if (!tracee)
Jesse Keating 7a3296
+			break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		ptrace_do_detach(tracee, -1);
Jesse Keating 7a3296
+		put_task_struct(tracee);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ptrace_set_options(struct task_struct *tracee,
Jesse Keating 7a3296
+				struct utrace_engine *engine, long data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ptrace_set_events(tracee, engine, data & PTRACE_O_MASK);
Jesse Keating 7a3296
+	return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ptrace_rw_siginfo(struct task_struct *tracee,
Jesse Keating 7a3296
+				struct ptrace_context *ctx,
Jesse Keating 7a3296
+				siginfo_t *info, bool write)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	unsigned long flags;
Jesse Keating 7a3296
+	int err;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (get_stop_event(ctx)) {
Jesse Keating 7a3296
+	case 0: /* jctl stop */
Jesse Keating 7a3296
+		return -EINVAL;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_EVENT_SIGNAL:
Jesse Keating 7a3296
+		err = -ESRCH;
Jesse Keating 7a3296
+		if (lock_task_sighand(tracee, &flags)) {
Jesse Keating 7a3296
+			if (likely(task_is_traced(tracee))) {
Jesse Keating 7a3296
+				if (write)
Jesse Keating 7a3296
+					*ctx->siginfo = *info;
Jesse Keating 7a3296
+				else
Jesse Keating 7a3296
+					*info = *ctx->siginfo;
Jesse Keating 7a3296
+				err = 0;
Jesse Keating 7a3296
+			}
Jesse Keating 7a3296
+			unlock_task_sighand(tracee, &flags);
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		return err;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		if (!write) {
Jesse Keating 7a3296
+			memset(info, 0, sizeof(*info));
Jesse Keating 7a3296
+			info->si_signo = SIGTRAP;
Jesse Keating 7a3296
+			info->si_code = ctx->stop_code & PTRACE_EVENT_MASK;
Jesse Keating 7a3296
+			info->si_pid = task_pid_vnr(tracee);
Jesse Keating 7a3296
+			info->si_uid = task_uid(tracee);
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		return 0;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static void do_ptrace_notify_stop(struct ptrace_context *ctx,
Jesse Keating 7a3296
+					struct task_struct *tracee)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * This can race with SIGKILL, but we borrow this race from
Jesse Keating 7a3296
+	 * the old ptrace implementation. ->exit_code is only needed
Jesse Keating 7a3296
+	 * for wait_task_stopped()->task_stopped_code(), we should
Jesse Keating 7a3296
+	 * change it to use ptrace_context.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK;
Jesse Keating 7a3296
+	WARN_ON(!tracee->exit_code);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	read_lock(&tasklist_lock);
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * Don't want to allow preemption here, because
Jesse Keating 7a3296
+	 * sys_ptrace() needs this task to be inactive.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	preempt_disable();
Jesse Keating 7a3296
+	/*
Jesse Keating 7a3296
+	 * It can be killed and then released by our subthread,
Jesse Keating 7a3296
+	 * or ptrace_attach() has not completed yet.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	if (task_ptrace(tracee))
Jesse Keating 7a3296
+		do_notify_parent_cldstop(tracee, CLD_TRAPPED);
Jesse Keating 7a3296
+	read_unlock(&tasklist_lock);
Jesse Keating 7a3296
+	preempt_enable_no_resched();
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+void ptrace_notify_stop(struct task_struct *tracee)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine = ptrace_lookup_engine(tracee);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (IS_ERR(engine))
Jesse Keating 7a3296
+		return;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	do_ptrace_notify_stop(ptrace_context(engine), tracee);
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ptrace_resume_action(struct task_struct *tracee,
Jesse Keating 7a3296
+				struct utrace_engine *engine, long request)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+	unsigned long events;
Jesse Keating 7a3296
+	int action;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx->options &= ~PTRACE_O_SYSEMU;
Jesse Keating 7a3296
+	events = engine->flags & ~UTRACE_EVENT_SYSCALL;
Jesse Keating 7a3296
+	action = UTRACE_RESUME;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (request) {
Jesse Keating 7a3296
+#ifdef PTRACE_SINGLEBLOCK
Jesse Keating 7a3296
+	case PTRACE_SINGLEBLOCK:
Jesse Keating 7a3296
+		if (unlikely(!arch_has_block_step()))
Jesse Keating 7a3296
+			return -EIO;
Jesse Keating 7a3296
+		action = UTRACE_BLOCKSTEP;
Jesse Keating 7a3296
+		events |= UTRACE_EVENT(SYSCALL_EXIT);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+#endif
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#ifdef PTRACE_SINGLESTEP
Jesse Keating 7a3296
+	case PTRACE_SINGLESTEP:
Jesse Keating 7a3296
+		if (unlikely(!arch_has_single_step()))
Jesse Keating 7a3296
+			return -EIO;
Jesse Keating 7a3296
+		action = UTRACE_SINGLESTEP;
Jesse Keating 7a3296
+		events |= UTRACE_EVENT(SYSCALL_EXIT);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+#endif
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#ifdef PTRACE_SYSEMU
Jesse Keating 7a3296
+	case PTRACE_SYSEMU_SINGLESTEP:
Jesse Keating 7a3296
+		if (unlikely(!arch_has_single_step()))
Jesse Keating 7a3296
+			return -EIO;
Jesse Keating 7a3296
+		action = UTRACE_SINGLESTEP;
Jesse Keating 7a3296
+	case PTRACE_SYSEMU:
Jesse Keating 7a3296
+		ctx->options |= PTRACE_O_SYSEMU;
Jesse Keating 7a3296
+		events |= UTRACE_EVENT(SYSCALL_ENTRY);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+#endif
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_SYSCALL:
Jesse Keating 7a3296
+		events |= UTRACE_EVENT_SYSCALL;
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_CONT:
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		return -EIO;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (events != engine->flags &&
Jesse Keating 7a3296
+	    utrace_set_events(tracee, engine, events))
Jesse Keating 7a3296
+		return -ESRCH;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return action;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+static int ptrace_resume(struct task_struct *tracee,
Jesse Keating 7a3296
+				struct utrace_engine *engine,
Jesse Keating 7a3296
+				long request, long data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct ptrace_context *ctx = ptrace_context(engine);
Jesse Keating 7a3296
+	int action;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (!valid_signal(data))
Jesse Keating 7a3296
+		return -EIO;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	action = ptrace_resume_action(tracee, engine, request);
Jesse Keating 7a3296
+	if (action < 0)
Jesse Keating 7a3296
+		return action;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (get_stop_event(ctx)) {
Jesse Keating 7a3296
+	case PTRACE_EVENT_VFORK:
Jesse Keating 7a3296
+		if (ctx->options & PTRACE_O_TRACEVFORKDONE) {
Jesse Keating 7a3296
+			set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE);
Jesse Keating 7a3296
+			action = UTRACE_REPORT;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_EVENT_EXEC:
Jesse Keating 7a3296
+	case PTRACE_EVENT_FORK:
Jesse Keating 7a3296
+	case PTRACE_EVENT_CLONE:
Jesse Keating 7a3296
+	case PTRACE_EVENT_VFORK_DONE:
Jesse Keating 7a3296
+		if (request == PTRACE_SYSCALL) {
Jesse Keating 7a3296
+			set_syscall_code(ctx);
Jesse Keating 7a3296
+			do_ptrace_notify_stop(ctx, tracee);
Jesse Keating 7a3296
+			return 0;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (action != UTRACE_RESUME) {
Jesse Keating 7a3296
+			/*
Jesse Keating 7a3296
+			 * single-stepping. UTRACE_SIGNAL_REPORT will
Jesse Keating 7a3296
+			 * synthesize a trap to follow the syscall insn.
Jesse Keating 7a3296
+			*/
Jesse Keating 7a3296
+			ctx->signr = SIGTRAP;
Jesse Keating 7a3296
+			action = UTRACE_INTERRUPT;
Jesse Keating 7a3296
+		}
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_EVENT_SYSCALL:
Jesse Keating 7a3296
+		if (data)
Jesse Keating 7a3296
+			send_sig_info(data, SEND_SIG_PRIV, tracee);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_EVENT_SIGNAL:
Jesse Keating 7a3296
+		ctx->signr = data;
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	ctx->resume = action;
Jesse Keating 7a3296
+	ptrace_wake_up(tracee, engine, action, true);
Jesse Keating 7a3296
+	return 0;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+extern int ptrace_regset(struct task_struct *task, int req, unsigned int type,
Jesse Keating 7a3296
+			 struct iovec *kiov);
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+int ptrace_request(struct task_struct *child, long request,
Jesse Keating 7a3296
+		   long addr, long data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine = ptrace_lookup_engine(child);
Jesse Keating 7a3296
+	siginfo_t siginfo;
Jesse Keating 7a3296
+	int ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(IS_ERR(engine)))
Jesse Keating 7a3296
+		return -ESRCH;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (request) {
Jesse Keating 7a3296
+	case PTRACE_PEEKTEXT:
Jesse Keating 7a3296
+	case PTRACE_PEEKDATA:
Jesse Keating 7a3296
+		ret = generic_ptrace_peekdata(child, addr, data);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	case PTRACE_POKETEXT:
Jesse Keating 7a3296
+	case PTRACE_POKEDATA:
Jesse Keating 7a3296
+		ret = generic_ptrace_pokedata(child, addr, data);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#ifdef PTRACE_OLDSETOPTIONS
Jesse Keating 7a3296
+	case PTRACE_OLDSETOPTIONS:
Jesse Keating 7a3296
+#endif
Jesse Keating 7a3296
+	case PTRACE_SETOPTIONS:
Jesse Keating 7a3296
+		ret = ptrace_set_options(child, engine, data);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	case PTRACE_GETEVENTMSG:
Jesse Keating 7a3296
+		ret = put_user(ptrace_context(engine)->eventmsg,
Jesse Keating 7a3296
+				(unsigned long __user *) data);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_GETSIGINFO:
Jesse Keating 7a3296
+		ret = ptrace_rw_siginfo(child, ptrace_context(engine),
Jesse Keating 7a3296
+					&siginfo, false);
Jesse Keating 7a3296
+		if (!ret)
Jesse Keating 7a3296
+			ret = copy_siginfo_to_user((siginfo_t __user *) data,
Jesse Keating 7a3296
+						   &siginfo);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_SETSIGINFO:
Jesse Keating 7a3296
+		if (copy_from_user(&siginfo, (siginfo_t __user *) data,
Jesse Keating 7a3296
+				   sizeof siginfo))
Jesse Keating 7a3296
+			ret = -EFAULT;
Jesse Keating 7a3296
+		else
Jesse Keating 7a3296
+			ret = ptrace_rw_siginfo(child, ptrace_context(engine),
Jesse Keating 7a3296
+						&siginfo, true);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_DETACH:	 /* detach a process that was attached. */
Jesse Keating 7a3296
+		ret = ptrace_detach(child, data);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_KILL:
Jesse Keating 7a3296
+		/* Ugly historical behaviour. */
Jesse Keating 7a3296
+		if (task_is_traced(child))
Jesse Keating 7a3296
+			ptrace_resume(child, engine, PTRACE_CONT, SIGKILL);
Jesse Keating 7a3296
+		ret = 0;
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_GETREGSET:
Jesse Keating 7a3296
+	case PTRACE_SETREGSET:
Jesse Keating 7a3296
+	{
Jesse Keating 7a3296
+		struct iovec kiov;
Jesse Keating 7a3296
+		struct iovec __user *uiov = (struct iovec __user *) data;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (__get_user(kiov.iov_base, &uiov->iov_base) ||
Jesse Keating 7a3296
+		    __get_user(kiov.iov_len, &uiov->iov_len))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		ret = ptrace_regset(child, request, addr, &kiov);
Jesse Keating 7a3296
+		if (!ret)
Jesse Keating 7a3296
+			ret = __put_user(kiov.iov_len, &uiov->iov_len);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		ret = ptrace_resume(child, engine, request, data);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+#if defined CONFIG_COMPAT
Jesse Keating 7a3296
+#include <linux compat.h="">
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+int compat_ptrace_request(struct task_struct *child, compat_long_t request,
Jesse Keating 7a3296
+			  compat_ulong_t addr, compat_ulong_t data)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	struct utrace_engine *engine = ptrace_lookup_engine(child);
Jesse Keating 7a3296
+	compat_ulong_t __user *datap = compat_ptr(data);
Jesse Keating 7a3296
+	compat_ulong_t word;
Jesse Keating 7a3296
+	siginfo_t siginfo;
Jesse Keating 7a3296
+	int ret;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	if (unlikely(IS_ERR(engine)))
Jesse Keating 7a3296
+		return -ESRCH;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	switch (request) {
Jesse Keating 7a3296
+	case PTRACE_PEEKTEXT:
Jesse Keating 7a3296
+	case PTRACE_PEEKDATA:
Jesse Keating 7a3296
+		ret = access_process_vm(child, addr, &word, sizeof(word), 0);
Jesse Keating 7a3296
+		if (ret != sizeof(word))
Jesse Keating 7a3296
+			ret = -EIO;
Jesse Keating 7a3296
+		else
Jesse Keating 7a3296
+			ret = put_user(word, datap);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_POKETEXT:
Jesse Keating 7a3296
+	case PTRACE_POKEDATA:
Jesse Keating 7a3296
+		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
Jesse Keating 7a3296
+		ret = (ret != sizeof(data) ? -EIO : 0);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_GETEVENTMSG:
Jesse Keating 7a3296
+		ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg,
Jesse Keating 7a3296
+				datap);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_GETSIGINFO:
Jesse Keating 7a3296
+		ret = ptrace_rw_siginfo(child, ptrace_context(engine),
Jesse Keating 7a3296
+					&siginfo, false);
Jesse Keating 7a3296
+		if (!ret)
Jesse Keating 7a3296
+			ret = copy_siginfo_to_user32(
Jesse Keating 7a3296
+				(struct compat_siginfo __user *) datap,
Jesse Keating 7a3296
+				&siginfo);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_SETSIGINFO:
Jesse Keating 7a3296
+		memset(&siginfo, 0, sizeof siginfo);
Jesse Keating 7a3296
+		if (copy_siginfo_from_user32(
Jesse Keating 7a3296
+			    &siginfo, (struct compat_siginfo __user *) datap))
Jesse Keating 7a3296
+			ret = -EFAULT;
Jesse Keating 7a3296
+		else
Jesse Keating 7a3296
+			ret = ptrace_rw_siginfo(child, ptrace_context(engine),
Jesse Keating 7a3296
+						&siginfo, true);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	case PTRACE_GETREGSET:
Jesse Keating 7a3296
+	case PTRACE_SETREGSET:
Jesse Keating 7a3296
+	{
Jesse Keating 7a3296
+		struct iovec kiov;
Jesse Keating 7a3296
+		struct compat_iovec __user *uiov =
Jesse Keating 7a3296
+			(struct compat_iovec __user *) datap;
Jesse Keating 7a3296
+		compat_uptr_t ptr;
Jesse Keating 7a3296
+		compat_size_t len;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		if (__get_user(ptr, &uiov->iov_base) ||
Jesse Keating 7a3296
+		    __get_user(len, &uiov->iov_len))
Jesse Keating 7a3296
+			return -EFAULT;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		kiov.iov_base = compat_ptr(ptr);
Jesse Keating 7a3296
+		kiov.iov_len = len;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+		ret = ptrace_regset(child, request, addr, &kiov);
Jesse Keating 7a3296
+		if (!ret)
Jesse Keating 7a3296
+			ret = __put_user(kiov.iov_len, &uiov->iov_len);
Jesse Keating 7a3296
+		break;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	default:
Jesse Keating 7a3296
+		ret = ptrace_request(child, request, addr, data);
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	utrace_engine_put(engine);
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+#endif	/* CONFIG_COMPAT */
Jesse Keating 7a3296
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
Jesse Keating 7a3296
index 74a3d69..c77f9bf 100644
Jesse Keating 7a3296
--- a/kernel/ptrace.c
Jesse Keating 7a3296
+++ b/kernel/ptrace.c
Jesse Keating 7a3296
@@ -23,7 +23,317 @@
Jesse Keating 7a3296
 #include <linux uaccess.h="">
Jesse Keating 7a3296
 #include <linux regset.h="">
Jesse Keating 7a3296
 
Jesse Keating 7a3296
+int __ptrace_may_access(struct task_struct *task, unsigned int mode)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	const struct cred *cred = current_cred(), *tcred;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	/* May we inspect the given task?
Jesse Keating 7a3296
+	 * This check is used both for attaching with ptrace
Jesse Keating 7a3296
+	 * and for allowing access to sensitive information in /proc.
Jesse Keating 7a3296
+	 *
Jesse Keating 7a3296
+	 * ptrace_attach denies several cases that /proc allows
Jesse Keating 7a3296
+	 * because setting up the necessary parent/child relationship
Jesse Keating 7a3296
+	 * or halting the specified task is impossible.
Jesse Keating 7a3296
+	 */
Jesse Keating 7a3296
+	int dumpable = 0;
Jesse Keating 7a3296
+	/* Don't let security modules deny introspection */
Jesse Keating 7a3296
+	if (task == current)
Jesse Keating 7a3296
+		return 0;
Jesse Keating 7a3296
+	rcu_read_lock();
Jesse Keating 7a3296
+	tcred = __task_cred(task);
Jesse Keating 7a3296
+	if ((cred->uid != tcred->euid ||
Jesse Keating 7a3296
+	     cred->uid != tcred->suid ||
Jesse Keating 7a3296
+	     cred->uid != tcred->uid  ||
Jesse Keating 7a3296
+	     cred->gid != tcred->egid ||
Jesse Keating 7a3296
+	     cred->gid != tcred->sgid ||
Jesse Keating 7a3296
+	     cred->gid != tcred->gid) &&
Jesse Keating 7a3296
+	    !capable(CAP_SYS_PTRACE)) {
Jesse Keating 7a3296
+		rcu_read_unlock();
Jesse Keating 7a3296
+		return -EPERM;
Jesse Keating 7a3296
+	}
Jesse Keating 7a3296
+	rcu_read_unlock();
Jesse Keating 7a3296
+	smp_rmb();
Jesse Keating 7a3296
+	if (task->mm)
Jesse Keating 7a3296
+		dumpable = get_dumpable(task->mm);
Jesse Keating 7a3296
+	if (!dumpable && !capable(CAP_SYS_PTRACE))
Jesse Keating 7a3296
+		return -EPERM;
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+	return security_ptrace_access_check(task, mode);
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+bool ptrace_may_access(struct task_struct *task, unsigned int mode)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	int err;
Jesse Keating 7a3296
+	task_lock(task);
Jesse Keating 7a3296
+	err = __ptrace_may_access(task, mode);
Jesse Keating 7a3296
+	task_unlock(task);
Jesse Keating 7a3296
+	return !err;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Called with irqs disabled, returns true if childs should reap themselves.
Jesse Keating 7a3296
+ */
Jesse Keating 7a3296
+static int ignoring_children(struct sighand_struct *sigh)
Jesse Keating 7a3296
+{
Jesse Keating 7a3296
+	int ret;
Jesse Keating 7a3296
+	spin_lock(&sigh->siglock);
Jesse Keating 7a3296
+	ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) ||
Jesse Keating 7a3296
+	      (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT);
Jesse Keating 7a3296
+	spin_unlock(&sigh->siglock);
Jesse Keating 7a3296
+	return ret;
Jesse Keating 7a3296
+}
Jesse Keating 7a3296
+
Jesse Keating 7a3296
+/*
Jesse Keating 7a3296
+ * Called with tasklist_lock held for writing.
Jesse Keating 7a3296
+ * Unlink a traced task, and clean it up if it was a traced zombie.